UNPKG

pixi.js

Version:

<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">

1 lines 24.8 kB
{"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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"}