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 • 23.3 kB
Source Map (JSON)
{"version":3,"file":"Polygon.mjs","sources":["../../../src/maths/shapes/Polygon.ts"],"sourcesContent":["import { 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, 0); // Inside\n * const centerStroke = polygon.strokeContains(25, 25, 4, 0.5); // Centered\n * const outerStroke = polygon.strokeContains(25, 25, 4, 1); // 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 (0 = inner, 0.5 = centered, 1 = 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 first X coordinate of the polygon\n * @readonly\n */\n get x(): number\n {\n return this.points[this.points.length - 2];\n }\n /**\n * Get the first Y coordinate of the polygon\n * @readonly\n */\n get y(): number\n {\n return this.points[this.points.length - 1];\n }\n}\n\n"],"names":[],"mappings":";;;;AAOA,IAAI,QAAA,CAAA;AACJ,IAAI,SAAA,CAAA;AAkCG,MAAM,OACb,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuEI,eAAe,MACf,EAAA;AAZA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAgB,IAAwB,GAAA,SAAA,CAAA;AAapC,IAAI,IAAA,IAAA,GAAO,MAAM,OAAQ,CAAA,MAAA,CAAO,CAAC,CAAC,CAAA,GAAI,MAAO,CAAA,CAAC,CAAI,GAAA,MAAA,CAAA;AAGlD,IAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,QACvB,EAAA;AACI,MAAA,MAAM,IAAc,EAAC,CAAA;AAErB,MAAA,KAAA,IAAS,IAAI,CAAG,EAAA,EAAA,GAAK,KAAK,MAAQ,EAAA,CAAA,GAAI,IAAI,CAC1C,EAAA,EAAA;AACI,QAAE,CAAA,CAAA,IAAA,CAAM,KAAK,CAAC,CAAA,CAAgB,GAAI,IAAK,CAAA,CAAC,EAAgB,CAAC,CAAA,CAAA;AAAA,OAC7D;AAEA,MAAO,IAAA,GAAA,CAAA,CAAA;AAAA,KACX;AAEA,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA,CAAA;AAEd,IAAA,IAAA,CAAK,SAAY,GAAA,IAAA,CAAA;AAAA,GACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBO,WACP,GAAA;AACI,IAAA,IAAI,IAAO,GAAA,CAAA,CAAA;AACX,IAAA,MAAM,SAAS,IAAK,CAAA,MAAA,CAAA;AACpB,IAAA,MAAM,SAAS,MAAO,CAAA,MAAA,CAAA;AAEtB,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,EAAQ,KAAK,CACjC,EAAA;AACI,MAAM,MAAA,EAAA,GAAK,OAAO,CAAC,CAAA,CAAA;AACnB,MAAM,MAAA,EAAA,GAAK,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AACvB,MAAA,MAAM,EAAK,GAAA,MAAA,CAAA,CAAQ,CAAI,GAAA,CAAA,IAAK,MAAM,CAAA,CAAA;AAClC,MAAA,MAAM,EAAK,GAAA,MAAA,CAAA,CAAQ,CAAI,GAAA,CAAA,IAAK,MAAM,CAAA,CAAA;AAElC,MAAS,IAAA,IAAA,CAAA,EAAA,GAAK,OAAO,EAAK,GAAA,EAAA,CAAA,CAAA;AAAA,KAC9B;AAEA,IAAA,OAAO,IAAO,GAAA,CAAA,CAAA;AAAA,GAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBO,gBAAgB,OACvB,EAAA;AAEI,IAAM,MAAA,UAAA,GAAa,IAAK,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AAC1C,IAAM,MAAA,WAAA,GAAc,OAAQ,CAAA,SAAA,CAAU,SAAS,CAAA,CAAA;AAE/C,IAAA,IAAI,CAAC,UAAA,CAAW,YAAa,CAAA,WAAW,CACxC,EAAA;AACI,MAAO,OAAA,KAAA,CAAA;AAAA,KACX;AAGA,IAAA,MAAM,SAAS,OAAQ,CAAA,MAAA,CAAA;AAEvB,IAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,MAAO,CAAA,MAAA,EAAQ,KAAK,CACxC,EAAA;AACI,MAAM,MAAA,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAClB,MAAM,MAAA,CAAA,GAAI,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AAGtB,MAAA,IAAI,CAAC,IAAA,CAAK,QAAS,CAAA,CAAA,EAAG,CAAC,CACvB,EAAA;AACI,QAAO,OAAA,KAAA,CAAA;AAAA,OACX;AAAA,KACJ;AAEA,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBO,KACP,GAAA;AACI,IAAM,MAAA,MAAA,GAAS,IAAK,CAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AACjC,IAAM,MAAA,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAM,CAAA,CAAA;AAElC,IAAA,OAAA,CAAQ,YAAY,IAAK,CAAA,SAAA,CAAA;AAEzB,IAAO,OAAA,OAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBO,QAAA,CAAS,GAAW,CAC3B,EAAA;AACI,IAAA,IAAI,MAAS,GAAA,KAAA,CAAA;AAIb,IAAM,MAAA,MAAA,GAAS,IAAK,CAAA,MAAA,CAAO,MAAS,GAAA,CAAA,CAAA;AAEpC,IAAS,KAAA,IAAA,CAAA,GAAI,GAAG,CAAI,GAAA,MAAA,GAAS,GAAG,CAAI,GAAA,MAAA,EAAQ,IAAI,CAChD,EAAA,EAAA;AACI,MAAA,MAAM,EAAK,GAAA,IAAA,CAAK,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AAC5B,MAAA,MAAM,EAAK,GAAA,IAAA,CAAK,MAAQ,CAAA,CAAA,GAAI,IAAK,CAAC,CAAA,CAAA;AAClC,MAAA,MAAM,EAAK,GAAA,IAAA,CAAK,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AAC5B,MAAA,MAAM,EAAK,GAAA,IAAA,CAAK,MAAQ,CAAA,CAAA,GAAI,IAAK,CAAC,CAAA,CAAA;AAClC,MAAM,MAAA,SAAA,GAAc,EAAK,GAAA,CAAA,KAAQ,EAAK,GAAA,CAAA,IAAQ,CAAM,GAAA,CAAA,EAAA,GAAK,EAAQ,KAAA,CAAA,CAAA,GAAI,EAAO,KAAA,EAAA,GAAK,EAAQ,CAAA,CAAA,GAAA,EAAA,CAAA;AAEzF,MAAA,IAAI,SACJ,EAAA;AACI,QAAA,MAAA,GAAS,CAAC,MAAA,CAAA;AAAA,OACd;AAAA,KACJ;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBO,cAAe,CAAA,CAAA,EAAW,CAAW,EAAA,WAAA,EAAqB,YAAY,GAC7E,EAAA;AACI,IAAA,MAAM,qBAAqB,WAAc,GAAA,WAAA,CAAA;AACzC,IAAM,MAAA,iBAAA,GAAoB,sBAAsB,CAAI,GAAA,SAAA,CAAA,CAAA;AACpD,IAAA,MAAM,mBAAmB,kBAAqB,GAAA,iBAAA,CAAA;AAE9C,IAAM,MAAA,EAAE,QAAW,GAAA,IAAA,CAAA;AACnB,IAAA,MAAM,eAAkB,GAAA,MAAA,CAAO,MAAU,IAAA,IAAA,CAAK,YAAY,CAAI,GAAA,CAAA,CAAA,CAAA;AAE9D,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,eAAA,EAAiB,KAAK,CAC1C,EAAA;AACI,MAAM,MAAA,EAAA,GAAK,OAAO,CAAC,CAAA,CAAA;AACnB,MAAM,MAAA,EAAA,GAAK,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AACvB,MAAA,MAAM,EAAK,GAAA,MAAA,CAAA,CAAQ,CAAI,GAAA,CAAA,IAAK,OAAO,MAAM,CAAA,CAAA;AACzC,MAAA,MAAM,EAAK,GAAA,MAAA,CAAA,CAAQ,CAAI,GAAA,CAAA,IAAK,OAAO,MAAM,CAAA,CAAA;AAEzC,MAAA,MAAM,kBAAkB,4BAA6B,CAAA,CAAA,EAAG,GAAG,EAAI,EAAA,EAAA,EAAI,IAAI,EAAE,CAAA,CAAA;AAEzE,MAAM,MAAA,IAAA,GAAO,IAAK,CAAA,IAAA,CAAA,CAAO,EAAK,GAAA,EAAA,KAAO,IAAI,EAAS,CAAA,GAAA,CAAA,EAAA,GAAK,EAAO,KAAA,CAAA,GAAI,EAAI,CAAA,CAAA,CAAA;AAEtE,MAAA,IAAI,eAAoB,KAAA,IAAA,GAAO,CAAI,GAAA,gBAAA,GAAmB,iBACtD,CAAA,EAAA;AACI,QAAO,OAAA,IAAA,CAAA;AAAA,OACX;AAAA,KACJ;AAEA,IAAO,OAAA,KAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBO,UAAU,GACjB,EAAA;AACI,IAAA,GAAA,KAAA,GAAA,GAAQ,IAAI,SAAU,EAAA,CAAA,CAAA;AAEtB,IAAA,MAAM,SAAS,IAAK,CAAA,MAAA,CAAA;AAEpB,IAAA,IAAI,IAAO,GAAA,QAAA,CAAA;AACX,IAAA,IAAI,IAAO,GAAA,CAAA,QAAA,CAAA;AAEX,IAAA,IAAI,IAAO,GAAA,QAAA,CAAA;AACX,IAAA,IAAI,IAAO,GAAA,CAAA,QAAA,CAAA;AAEX,IAAS,KAAA,IAAA,CAAA,GAAI,GAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CAAI,GAAA,CAAA,EAAG,KAAK,CAC/C,EAAA;AACI,MAAM,MAAA,CAAA,GAAI,OAAO,CAAC,CAAA,CAAA;AAClB,MAAM,MAAA,CAAA,GAAI,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,CAAA;AAEtB,MAAO,IAAA,GAAA,CAAA,GAAI,OAAO,CAAI,GAAA,IAAA,CAAA;AACtB,MAAO,IAAA,GAAA,CAAA,GAAI,OAAO,CAAI,GAAA,IAAA,CAAA;AAEtB,MAAO,IAAA,GAAA,CAAA,GAAI,OAAO,CAAI,GAAA,IAAA,CAAA;AACtB,MAAO,IAAA,GAAA,CAAA,GAAI,OAAO,CAAI,GAAA,IAAA,CAAA;AAAA,KAC1B;AAEA,IAAA,GAAA,CAAI,CAAI,GAAA,IAAA,CAAA;AACR,IAAA,GAAA,CAAI,QAAQ,IAAO,GAAA,IAAA,CAAA;AAEnB,IAAA,GAAA,CAAI,CAAI,GAAA,IAAA,CAAA;AACR,IAAA,GAAA,CAAI,SAAS,IAAO,GAAA,IAAA,CAAA;AAEpB,IAAO,OAAA,GAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBO,SAAS,OAChB,EAAA;AACI,IAAK,IAAA,CAAA,MAAA,GAAS,OAAQ,CAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AACnC,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA,CAAA;AAEzB,IAAO,OAAA,IAAA,CAAA;AAAA,GACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBO,OAAO,OACd,EAAA;AACI,IAAA,OAAA,CAAQ,SAAS,IAAI,CAAA,CAAA;AAErB,IAAO,OAAA,OAAA,CAAA;AAAA,GACX;AAAA,EAGO,QACP,GAAA;AACI,IAAA,OAAO,oCACc,IAAK,CAAA,SAAS,CACnB,OAAA,EAAA,IAAA,CAAK,OAAO,MAAO,CAAA,CAAC,UAAY,EAAA,YAAA,KAAiB,GAAG,UAAU,CAAA,EAAA,EAAK,YAAY,CAAA,CAAA,EAAI,EAAE,CAAC,CAAA,CAAA,CAAA,CAAA;AAAA,GAC1G;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,IAAI,KACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,GAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,IAAI,KACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,GAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,CACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,GAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,CACJ,GAAA;AACI,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,IAAK,CAAA,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,GAC7C;AACJ;;;;"}