import { Epsilon, Scalar } from '../loader/babylonjs-import';
import { Line2D } from './Line2D';
/**
 * Given a collection of points(vertices), representing corners of outer edges of a polygon. Calculate
 * the centroid.
 * @param points Points
 * @param dst Where centroid value is written
 * @returns Reference to `dst`
 */
export function calculateCentroidVertex2ToRef(points, dst) {
    dst.x = 0;
    dst.y = 0;
    let len = 0;
    for (const p of points) {
        len++;
        dst.x += p.x;
        dst.y += p.y;
    }
    dst.x /= len;
    dst.y /= len;
    return dst;
}
/**
 * Sorts the {@link Vertex2} array in clockwise order IN PLACE SORTING.
 * @param points An array of {@link Vertex2} points. Will be sorted in place, in clockwise order.
 * @returns A reference to `points` (now sorted).
 */
export function sortVertex2CW(points) {
    const centroid = calculateCentroidVertex2ToRef(points.values(), { x: 0, y: 0 });
    // Transpose to local space
    for (const elem of points) {
        elem.x = elem.x - centroid.x;
        elem.y = elem.y - centroid.y;
    }
    // Ready for sort to start
    const center = { x: 0, y: 0 };
    points.sort((p0, p1) => {
        const angle0 = getAngleVertex2(center, p0);
        const angle1 = getAngleVertex2(center, p1);
        if (!Scalar.WithinEpsilon(angle0, angle1, Epsilon)) {
            if (angle0 < angle1) {
                return -1;
            }
            if (angle0 > angle1) {
                return 1;
            }
        }
        const d0 = getDistanceVertex2(center, p0);
        const d1 = getDistanceVertex2(center, p1);
        if (Scalar.WithinEpsilon(d0, d1, Epsilon)) {
            return 0;
        }
        else if (d0 < d1) {
            return -1;
        }
        else {
            return 1;
        }
    });
    // Transpose back to world space
    for (const elem of points) {
        elem.x = elem.x + centroid.x;
        elem.y = elem.y + centroid.y;
    }
    return points;
}
/**
 * Calculates euclidean distance between two points.
 * @param p0 {@link Vertex2} point.
 * @param p1 {@link Vertex2} point.
 * @returns Euclidean distance between `p0` and `p1`.
 */
function getDistanceVertex2(p0, p1) {
    const x = p0.x - p1.x;
    const y = p0.y - p1.y;
    return Math.sqrt(x * x + y * y);
}
/**
 * Calculates angle between two points in radians.
 * @param p0 {@link Vertex2} point.
 * @param p1 {@link Vertex2} point.
 * @returns Angle in radians between `p0` and `p1`.
 */
function getAngleVertex2(p0, p1) {
    const x = p0.x - p1.x;
    const y = p0.y - p1.y;
    let angle = Math.atan2(y, x);
    if (angle <= 0) {
        angle += 2 * Math.PI;
    }
    return angle;
}
/**
 * Checks if a polygon is self-intersecting.
 * @param polygonPoints An array of {@link Vertex2} polygon corners (points).
 * @returns `true` if the polygon shape is complex, `false` otherwise.
 */
export function isComplexPolygonVertex2(polygonPoints) {
    if (polygonPoints.length < 2) {
        return false;
    }
    polygonPoints.push(polygonPoints[0]);
    try {
        const len = polygonPoints.length;
        const line = { p1: { x: 0, y: 0 }, p2: { x: 0, y: 0 } };
        const subLine = { p1: { x: 0, y: 0 }, p2: { x: 0, y: 0 } };
        for (let i = 1; i < len; ++i) {
            line.p1 = polygonPoints[i - 1];
            line.p2 = polygonPoints[i];
            const subLen = i === 1 ? len - 1 : len;
            for (let j = i + 2; j < subLen; ++j) {
                subLine.p1 = polygonPoints[j - 1];
                subLine.p2 = polygonPoints[j];
                if (Line2D.intersects(line, subLine)) {
                    return true;
                }
            }
        }
    }
    finally {
        polygonPoints.pop();
    }
    return false;
}
//# sourceMappingURL=Vertex2.js.map