// math.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors /* eslint-disable no-undef, no-console */ import {isArray} from '@math.gl/core'; import type {SegmentVisitorPoints} from './polygon-utils'; import type {NumericArray} from '@math.gl/core'; import { getPolygonSignedArea, forEachSegmentInPolygon, modifyPolygonWindingDirection, getPolygonSignedAreaPoints, forEachSegmentInPolygonPoints, modifyPolygonWindingDirectionPoints } from './polygon-utils'; export type PolygonOptions = { start?: number; end?: number; size?: number; isClosed?: boolean; }; export class Polygon { points: NumericArray | number[][]; isFlatArray: boolean; options: PolygonOptions; constructor(points: NumericArray | number[][], options: PolygonOptions = {}) { this.points = points; this.isFlatArray = !isArray(points[0]); this.options = { start: options.start || 0, end: options.end || points.length, size: options.size || 2, isClosed: options.isClosed }; Object.freeze(this); } /** * Returns signed area of the polygon. * @returns Signed area of the polygon. */ getSignedArea(): number { if (this.isFlatArray) return getPolygonSignedArea(this.points as NumericArray, this.options); return getPolygonSignedAreaPoints(this.points as number[][], this.options); } /** * Returns absolute area of the polygon. * @returns Absolute area of the polygon. */ getArea(): number { return Math.abs(this.getSignedArea()); } /** * Returns winding direction of the polygon. * @returns Winding direction of the polygon. 1 is for clockwise, -1 for counterclockwise winding direction. */ getWindingDirection(): number { return Math.sign(this.getSignedArea()); } /** * Calls the visitor callback for each segment in the polygon. * @param visitor A callback to call for each segment. */ forEachSegment(visitor: SegmentVisitorPoints): void { if (this.isFlatArray) { forEachSegmentInPolygon( this.points as NumericArray, // eslint-disable-next-line max-params (x1, y1, x2, y2, i1, i2) => { // TODO @igorDykhta original visitor uses arrays for each point, but with flat arrays performance degrades if we allocate points for each segment visitor([x1, y1], [x2, y2], i1, i2); }, this.options ); } else { forEachSegmentInPolygonPoints(this.points as number[][], visitor, this.options); } } /** * Checks winding direction of the polygon and reverses the polygon in case of opposite winding direction. * @param direction Requested winding direction. 1 is for clockwise, -1 for counterclockwise winding direction. * @return Returns true if the winding direction was changed. */ modifyWindingDirection(direction: number): boolean { if (this.isFlatArray) { return modifyPolygonWindingDirection(this.points as NumericArray, direction, this.options); } return modifyPolygonWindingDirectionPoints(this.points as number[][], direction, this.options); } }