"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.rebuildShape = void 0;
const point_1 = require("../../point/point");
const in_place_array_1 = require("../../util/in-place-array");
const slice_arc_1 = require("../shared/slice-arc");
const to_poly_1 = require("./to-poly");
function rebuildShape(polys, segHash, resolution) {
    let rebuiltShape = [];
    for (const poly of polys) {
        let rebuiltArc = [];
        rebuildContour(poly, segHash, resolution, rebuiltArc);
        if (rebuiltArc.length)
            rebuiltShape.push(rebuiltArc);
    }
    return rebuiltShape;
}
exports.rebuildShape = rebuildShape;
function rebuildContour(poly, segHash, resolution, sink) {
    if (poly.length <= 1)
        return;
    preparePoly(poly, segHash);
    let primSegments = collectPrimSegments(poly, segHash, resolution);
    inPlaceAnnexPrimSegments(primSegments);
    for (const seg of primSegments)
        sink.push(seg.toArc());
}
function preparePoly(poly, segHash) {
    for (let j = 0; j < poly.length; j++) {
        if (segHash.getStart(poly[j])) {
            (0, in_place_array_1.inPlaceRotateArray)(poly, -j);
            break;
        }
    }
    if (poly[0].X !== poly[poly.length - 1].X || poly[0].Y !== poly[poly.length - 1].Y) {
        poly.push(poly[0]);
    }
}
function collectPrimSegments(poly, segHash, resolution) {
    let primSegments = [];
    for (let j = 0; j < poly.length - 1; j++) {
        let segment = segHash.getSegment(poly[j], poly[j + 1]);
        if (segment) {
            primSegments.push(segment);
        }
        else {
            const a = descale(poly[j], resolution);
            const d = descale(poly[j + 1], resolution);
            const b = point_1.Point2.from(a).mix(d, 1 / 3);
            const c = point_1.Point2.from(a).mix(d, 2 / 3);
            primSegments.push(new to_poly_1.SegEntry(new slice_arc_1.Bez3Slice(a, b, c, d), 0, 1));
        }
    }
    return primSegments;
}
function descale(Z, resolution) {
    return new point_1.Point2(Z.X / resolution, Z.Y / resolution);
}
function inPlaceAnnexPrimSegments(primSegments) {
    if (!primSegments.length)
        return;
    let i = 1, j = 1;
    for (; i < primSegments.length; i++) {
        let last = primSegments[j - 1], cur = primSegments[i];
        if (!last.tryAnnex(cur)) {
            primSegments[j++] = cur;
        }
    }
    primSegments.length = j;
}
