{"version":3,"file":"Polygon.mjs","sources":["../../../src/maths/shapes/Polygon.ts"],"sourcesContent":["import { deprecation } from '../../utils/logging/deprecation';\nimport { squaredDistanceToLineSegment } from '../misc/squaredDistanceToLineSegment';\nimport { Rectangle } from './Rectangle';\n\nimport type { SHAPE_PRIMITIVE } from '../misc/const';\nimport type { PointData } from '../point/PointData';\nimport type { ShapePrimitive } from './ShapePrimitive';\n\nlet tempRect: Rectangle;\nlet tempRect2: Rectangle;\n\n/**\n * A class to define a shape via user defined coordinates.\n * Used for creating complex shapes and hit areas with custom points.\n * @example\n * ```ts\n * // Create polygon from array of points\n * const polygon1 = new Polygon([\n *     new Point(0, 0),\n *     new Point(0, 100),\n *     new Point(100, 100)\n * ]);\n *\n * // Create from array of coordinates\n * const polygon2 = new Polygon([0, 0, 0, 100, 100, 100]);\n *\n * // Create from sequence of points\n * const polygon3 = new Polygon(\n *     new Point(0, 0),\n *     new Point(0, 100),\n *     new Point(100, 100)\n * );\n *\n * // Create from sequence of coordinates\n * const polygon4 = new Polygon(0, 0, 0, 100, 100, 100);\n *\n * // Use as container hit area\n * container.hitArea = new Polygon([0, 0, 100, 0, 50, 100]);\n * ```\n * @see {@link Point} For point objects used in construction\n * @category maths\n * @standard\n */\nexport class Polygon implements ShapePrimitive\n{\n    /**\n     * An array of the points of this polygon stored as a flat array of numbers.\n     * @example\n     * ```ts\n     * // Access points directly\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * console.log(polygon.points); // [0, 0, 100, 0, 50, 100]\n     *\n     * // Modify points\n     * polygon.points[0] = 10; // Move first x coordinate\n     * polygon.points[1] = 10; // Move first y coordinate\n     * ```\n     * @remarks\n     * - Stored as [x1, y1, x2, y2, ...]\n     * - Each pair represents a vertex\n     * - Length is always even\n     * - Can be modified directly\n     */\n    public points: number[];\n\n    /**\n     * Indicates if the polygon path is closed.\n     * @example\n     * ```ts\n     * // Create open polygon\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * polygon.closePath = false;\n     *\n     * // Check path state\n     * if (polygon.closePath) {\n     *     // Last point connects to first\n     * }\n     * ```\n     * @remarks\n     * - True by default\n     * - False after moveTo\n     * - True after closePath\n     * @default true\n     */\n    public closePath: boolean;\n\n    /**\n     * The type of the object, mainly used to avoid `instanceof` checks\n     * @example\n     * ```ts\n     * // Check shape type\n     * const shape = new Polygon([0, 0, 100, 0, 50, 100]);\n     * console.log(shape.type); // 'polygon'\n     *\n     * // Use in type guards\n     * if (shape.type === 'polygon') {\n     *     // TypeScript knows this is a Polygon\n     *     console.log(shape.points.length);\n     * }\n     * ```\n     * @readonly\n     * @default 'polygon'\n     * @see {@link SHAPE_PRIMITIVE} For all shape types\n     */\n    public readonly type: SHAPE_PRIMITIVE = 'polygon';\n\n    constructor(points: PointData[] | number[]);\n    constructor(...points: PointData[] | number[]);\n    /**\n     * @param points - This can be an array of Points\n     *  that form the polygon, a flat array of numbers that will be interpreted as [x,y, x,y, ...], or\n     *  the arguments passed can be all the points of the polygon e.g.\n     *  `new Polygon(new Point(), new Point(), ...)`, or the arguments passed can be flat\n     *  x,y values e.g. `new Polygon(x,y, x,y, x,y, ...)` where `x` and `y` are Numbers.\n     */\n    constructor(...points: (PointData[] | number[])[] | PointData[] | number[])\n    {\n        let flat = Array.isArray(points[0]) ? points[0] : points;\n\n        // if this is an array of points, convert it to a flat array of numbers\n        if (typeof flat[0] !== 'number')\n        {\n            const p: number[] = [];\n\n            for (let i = 0, il = flat.length; i < il; i++)\n            {\n                p.push((flat[i] as PointData).x, (flat[i] as PointData).y);\n            }\n\n            flat = p;\n        }\n\n        this.points = flat as number[];\n\n        this.closePath = true;\n    }\n\n    /**\n     * Determines whether the polygon's points are arranged in a clockwise direction.\n     * Uses the shoelace formula (surveyor's formula) to calculate the signed area.\n     *\n     * A positive area indicates clockwise winding, while negative indicates counter-clockwise.\n     *\n     * The formula sums up the cross products of adjacent vertices:\n     * For each pair of adjacent points (x1,y1) and (x2,y2), we calculate (x1*y2 - x2*y1)\n     * The final sum divided by 2 gives the signed area - positive for clockwise.\n     * @example\n     * ```ts\n     * // Check polygon winding\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * console.log(polygon.isClockwise()); // Check direction\n     *\n     * // Use in path construction\n     * const hole = new Polygon([25, 25, 75, 25, 75, 75, 25, 75]);\n     * if (hole.isClockwise() === shape.isClockwise()) {\n     *     hole.points.reverse(); // Reverse for proper hole winding\n     * }\n     * ```\n     * @returns `true` if the polygon's points are arranged clockwise, `false` if counter-clockwise\n     */\n    public isClockwise(): boolean\n    {\n        let area = 0;\n        const points = this.points;\n        const length = points.length;\n\n        for (let i = 0; i < length; i += 2)\n        {\n            const x1 = points[i];\n            const y1 = points[i + 1];\n            const x2 = points[(i + 2) % length];\n            const y2 = points[(i + 3) % length];\n\n            area += (x2 - x1) * (y2 + y1);\n        }\n\n        return area < 0;\n    }\n\n    /**\n     * Checks if this polygon completely contains another polygon.\n     * Used for detecting holes in shapes, like when parsing SVG paths.\n     * @example\n     * ```ts\n     * // Basic containment check\n     * const outerSquare = new Polygon([0,0, 100,0, 100,100, 0,100]); // A square\n     * const innerSquare = new Polygon([25,25, 75,25, 75,75, 25,75]); // A smaller square inside\n     *\n     * outerSquare.containsPolygon(innerSquare); // Returns true\n     * innerSquare.containsPolygon(outerSquare); // Returns false\n     * ```\n     * @remarks\n     * - Uses bounds check for quick rejection\n     * - Tests all points for containment\n     * @param polygon - The polygon to test for containment\n     * @returns True if this polygon completely contains the other polygon\n     * @see {@link Polygon.contains} For single point testing\n     * @see {@link Polygon.getBounds} For bounds calculation\n     */\n    public containsPolygon(polygon: Polygon): boolean\n    {\n    // Quick early-out: bounds check\n        const thisBounds = this.getBounds(tempRect);\n        const otherBounds = polygon.getBounds(tempRect2);\n\n        if (!thisBounds.containsRect(otherBounds))\n        {\n            return false; // If bounds aren't contained, the polygon cannot be a hole\n        }\n\n        // Full point containment check\n        const points = polygon.points;\n\n        for (let i = 0; i < points.length; i += 2)\n        {\n            const x = points[i];\n            const y = points[i + 1];\n\n            // Combine bounds and polygon checks for efficiency\n            if (!this.contains(x, y))\n            {\n                return false;\n            }\n        }\n\n        return true; // All points are contained within bounds and polygon\n    }\n\n    /**\n     * Creates a clone of this polygon.\n     * @example\n     * ```ts\n     * // Basic cloning\n     * const original = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const copy = original.clone();\n     *\n     * // Clone and modify\n     * const modified = original.clone();\n     * modified.points[0] = 10; // Modify first x coordinate\n     * ```\n     * @returns A copy of the polygon\n     * @see {@link Polygon.copyFrom} For copying into existing polygon\n     * @see {@link Polygon.copyTo} For copying to another polygon\n     */\n    public clone(): Polygon\n    {\n        const points = this.points.slice();\n        const polygon = new Polygon(points);\n\n        polygon.closePath = this.closePath;\n\n        return polygon;\n    }\n\n    /**\n     * Checks whether the x and y coordinates passed to this function are contained within this polygon.\n     * Uses raycasting algorithm for point-in-polygon testing.\n     * @example\n     * ```ts\n     * // Basic containment check\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const isInside = polygon.contains(25, 25); // true\n     * ```\n     * @param x - The X coordinate of the point to test\n     * @param y - The Y coordinate of the point to test\n     * @returns Whether the x/y coordinates are within this polygon\n     * @see {@link Polygon.strokeContains} For checking stroke intersection\n     * @see {@link Polygon.containsPolygon} For polygon-in-polygon testing\n     */\n    public contains(x: number, y: number): boolean\n    {\n        let inside = false;\n\n        // use some raycasting to test hits\n        // https://github.com/substack/point-in-polygon/blob/master/index.js\n        const length = this.points.length / 2;\n\n        for (let i = 0, j = length - 1; i < length; j = i++)\n        {\n            const xi = this.points[i * 2];\n            const yi = this.points[(i * 2) + 1];\n            const xj = this.points[j * 2];\n            const yj = this.points[(j * 2) + 1];\n            const intersect = ((yi > y) !== (yj > y)) && (x < ((xj - xi) * ((y - yi) / (yj - yi))) + xi);\n\n            if (intersect)\n            {\n                inside = !inside;\n            }\n        }\n\n        return inside;\n    }\n\n    /**\n     * Checks whether the x and y coordinates given are contained within this polygon including the stroke.\n     * @example\n     * ```ts\n     * // Basic stroke check\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const isOnStroke = polygon.strokeContains(25, 25, 4); // 4px line width\n     *\n     * // Check with different alignments\n     * const innerStroke = polygon.strokeContains(25, 25, 4, 1);   // Inside\n     * const centerStroke = polygon.strokeContains(25, 25, 4, 0.5); // Centered\n     * const outerStroke = polygon.strokeContains(25, 25, 4, 0);   // Outside\n     * ```\n     * @param x - The X coordinate of the point to test\n     * @param y - The Y coordinate of the point to test\n     * @param strokeWidth - The width of the line to check\n     * @param alignment - The alignment of the stroke (1 = inner, 0.5 = centered, 0 = outer)\n     * @returns Whether the x/y coordinates are within this polygon's stroke\n     * @see {@link Polygon.contains} For checking fill containment\n     * @see {@link Polygon.getBounds} For getting stroke bounds\n     */\n    public strokeContains(x: number, y: number, strokeWidth: number, alignment = 0.5): boolean\n    {\n        const strokeWidthSquared = strokeWidth * strokeWidth;\n        const rightWidthSquared = strokeWidthSquared * (1 - alignment);\n        const leftWidthSquared = strokeWidthSquared - rightWidthSquared;\n\n        const { points } = this;\n        const iterationLength = points.length - (this.closePath ? 0 : 2);\n\n        for (let i = 0; i < iterationLength; i += 2)\n        {\n            const x1 = points[i];\n            const y1 = points[i + 1];\n            const x2 = points[(i + 2) % points.length];\n            const y2 = points[(i + 3) % points.length];\n\n            const distanceSquared = squaredDistanceToLineSegment(x, y, x1, y1, x2, y2);\n\n            const sign = Math.sign(((x2 - x1) * (y - y1)) - ((y2 - y1) * (x - x1)));\n\n            if (distanceSquared <= (sign < 0 ? leftWidthSquared : rightWidthSquared))\n            {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Returns the framing rectangle of the polygon as a Rectangle object.\n     * @example\n     * ```ts\n     * // Basic bounds calculation\n     * const polygon = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const bounds = polygon.getBounds();\n     * // bounds: x=0, y=0, width=100, height=100\n     *\n     * // Reuse existing rectangle\n     * const rect = new Rectangle();\n     * polygon.getBounds(rect);\n     * ```\n     * @param out - Optional rectangle to store the result\n     * @returns The framing rectangle\n     * @see {@link Rectangle} For rectangle properties\n     * @see {@link Polygon.contains} For checking if a point is inside\n     */\n    public getBounds(out?: Rectangle): Rectangle\n    {\n        out ||= new Rectangle();\n\n        const points = this.points;\n\n        let minX = Infinity;\n        let maxX = -Infinity;\n\n        let minY = Infinity;\n        let maxY = -Infinity;\n\n        for (let i = 0, n = points.length; i < n; i += 2)\n        {\n            const x = points[i];\n            const y = points[i + 1];\n\n            minX = x < minX ? x : minX;\n            maxX = x > maxX ? x : maxX;\n\n            minY = y < minY ? y : minY;\n            maxY = y > maxY ? y : maxY;\n        }\n\n        out.x = minX;\n        out.width = maxX - minX;\n\n        out.y = minY;\n        out.height = maxY - minY;\n\n        return out;\n    }\n\n    /**\n     * Copies another polygon to this one.\n     * @example\n     * ```ts\n     * // Basic copying\n     * const source = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const target = new Polygon();\n     * target.copyFrom(source);\n     * ```\n     * @param polygon - The polygon to copy from\n     * @returns Returns itself\n     * @see {@link Polygon.copyTo} For copying to another polygon\n     * @see {@link Polygon.clone} For creating new polygon copy\n     */\n    public copyFrom(polygon: Polygon): this\n    {\n        this.points = polygon.points.slice();\n        this.closePath = polygon.closePath;\n\n        return this;\n    }\n\n    /**\n     * Copies this polygon to another one.\n     * @example\n     * ```ts\n     * // Basic copying\n     * const source = new Polygon([0, 0, 100, 0, 50, 100]);\n     * const target = new Polygon();\n     * source.copyTo(target);\n     * ```\n     * @param polygon - The polygon to copy to\n     * @returns Returns given parameter\n     * @see {@link Polygon.copyFrom} For copying from another polygon\n     * @see {@link Polygon.clone} For creating new polygon copy\n     */\n    public copyTo(polygon: Polygon): Polygon\n    {\n        polygon.copyFrom(this);\n\n        return polygon;\n    }\n\n    // #if _DEBUG\n    public toString(): string\n    {\n        return `[pixi.js/math:Polygon`\n            + `closeStroke=${this.closePath}`\n            + `points=${this.points.reduce((pointsDesc, currentPoint) => `${pointsDesc}, ${currentPoint}`, '')}]`;\n    }\n    // #endif\n\n    /**\n     * Get the last X coordinate of the polygon.\n     * @example\n     * ```ts\n     * // Basic coordinate access\n     * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);\n     * console.log(polygon.lastX); // 300\n     * ```\n     * @readonly\n     * @returns The x-coordinate of the last vertex\n     * @see {@link Polygon.lastY} For last Y coordinate\n     * @see {@link Polygon.points} For raw points array\n     */\n    get lastX(): number\n    {\n        return this.points[this.points.length - 2];\n    }\n\n    /**\n     * Get the last Y coordinate of the polygon.\n     * @example\n     * ```ts\n     * // Basic coordinate access\n     * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);\n     * console.log(polygon.lastY); // 400\n     * ```\n     * @readonly\n     * @returns The y-coordinate of the last vertex\n     * @see {@link Polygon.lastX} For last X coordinate\n     * @see {@link Polygon.points} For raw points array\n     */\n    get lastY(): number\n    {\n        return this.points[this.points.length - 1];\n    }\n\n    /**\n     * Get the last X coordinate of the polygon.\n     * @readonly\n     * @deprecated since 8.11.0, use {@link Polygon.lastX} instead.\n     */\n    get x(): number\n    {\n        // #if _DEBUG\n        deprecation('8.11.0', 'Polygon.lastX is deprecated, please use Polygon.lastX instead.');\n        // #endif\n\n        return this.points[this.points.length - 2];\n    }\n\n    /**\n     * Get the last Y coordinate of the polygon.\n     * @readonly\n     * @deprecated since 8.11.0, use {@link Polygon.lastY} instead.\n     */\n    get y(): number\n    {\n        // #if _DEBUG\n        deprecation('8.11.0', 'Polygon.y is deprecated, please use Polygon.lastY instead.');\n        // #endif\n\n        return this.points[this.points.length - 1];\n    }\n    /**\n     * Get the first X coordinate of the polygon.\n     * @example\n     * ```ts\n     * // Basic coordinate access\n     * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);\n     * console.log(polygon.x); // 0\n     * ```\n     * @readonly\n     * @returns The x-coordinate of the first vertex\n     * @see {@link Polygon.startY} For first Y coordinate\n     * @see {@link Polygon.points} For raw points array\n     */\n    get startX(): number\n    {\n        return this.points[0];\n    }\n\n    /**\n     * Get the first Y coordinate of the polygon.\n     * @example\n     * ```ts\n     * // Basic coordinate access\n     * const polygon = new Polygon([0, 0, 100, 200, 300, 400]);\n     * console.log(polygon.y); // 0\n     * ```\n     * @readonly\n     * @returns The y-coordinate of the first vertex\n     * @see {@link Polygon.startX} For first X coordinate\n     * @see {@link Polygon.points} For raw points array\n     */\n    get startY(): number\n    {\n        return this.points[1];\n    }\n}\n\n"],"names":[],"mappings":"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"}