{"version":3,"file":"terra-draw.cjs","sources":["../src/common.ts","../src/store/store-feature-validation.ts","../src/validations/common-validations.ts","../src/modes/base.mode.ts","../src/geometry/measure/haversine-distance.ts","../src/geometry/helpers.ts","../src/geometry/limit-decimal-precision.ts","../src/geometry/project/web-mercator.ts","../src/geometry/shape/create-circle.ts","../src/geometry/boolean/self-intersects.ts","../src/geometry/boolean/is-valid-coordinate.ts","../src/validations/polygon.validation.ts","../src/modes/circle/circle.mode.ts","../src/util/styling.ts","../src/geometry/shape/web-mercator-distortion.ts","../src/geometry/measure/pixel-distance.ts","../src/geometry/ensure-right-hand-rule.ts","../src/geometry/boolean/right-hand-rule.ts","../src/modes/freehand/freehand.mode.ts","../src/modes/base.behavior.ts","../src/geometry/shape/create-bbox.ts","../src/modes/click-bounding-box.behavior.ts","../src/modes/pixel-distance.behavior.ts","../src/modes/coordinate-snapping.behavior.ts","../src/geometry/measure/destination.ts","../src/geometry/measure/bearing.ts","../src/geometry/measure/slice-along.ts","../src/geometry/shape/great-circle-coordinates.ts","../src/modes/insert-coordinates.behavior.ts","../src/geometry/coordinates-identical.ts","../src/validations/linestring.validation.ts","../src/geometry/point-on-line.ts","../src/modes/line-snapping.behavior.ts","../src/geometry/web-mercator-point-on-line.ts","../src/modes/linestring/linestring.mode.ts","../src/validations/point.validation.ts","../src/modes/point/point.mode.ts","../src/modes/polygon/behaviors/closing-points.behavior.ts","../src/modes/select/behaviors/coordinate-point.behavior.ts","../src/modes/polygon/polygon.mode.ts","../src/util/geoms.ts","../src/modes/rectangle/rectangle.mode.ts","../src/modes/render/render.mode.ts","../src/geometry/measure/rhumb-bearing.ts","../src/geometry/measure/rhumb-destination.ts","../src/geometry/midpoint-coordinate.ts","../src/geometry/get-midpoints.ts","../src/modes/select/behaviors/midpoint.behavior.ts","../src/modes/select/behaviors/selection-point.behavior.ts","../src/geometry/get-coordinates-as-points.ts","../src/geometry/boolean/point-in-polygon.ts","../src/geometry/measure/pixel-distance-to-line.ts","../src/modes/select/behaviors/feature-at-pointer-event.behavior.ts","../src/modes/select/behaviors/drag-feature.behavior.ts","../src/modes/select/behaviors/drag-coordinate.behavior.ts","../src/geometry/centroid.ts","../src/geometry/web-mercator-centroid.ts","../src/modes/select/behaviors/rotate-feature.behavior.ts","../src/geometry/transform/rotate.ts","../src/geometry/measure/rhumb-distance.ts","../src/modes/select/behaviors/scale-feature.behavior.ts","../src/modes/select/behaviors/drag-coordinate-resize.behavior.ts","../src/modes/select/select.mode.ts","../src/modes/static/static.mode.ts","../src/store/spatial-index/quickselect.ts","../src/store/spatial-index/rbush.ts","../src/store/spatial-index/spatial-index.ts","../src/store/store.ts","../src/util/id.ts","../src/geometry/measure/area.ts","../src/validations/min-size.validation.ts","../src/validations/not-self-intersecting.validation.ts","../src/geometry/calculate-relative-angle.ts","../src/modes/angled-rectangle/angled-rectangle.mode.ts","../src/geometry/determine-halfplane.ts","../src/geometry/clockwise.ts","../src/modes/sector/sector.mode.ts","../src/modes/sensor/sensor.mode.ts","../src/common/adapter-listener.ts","../src/common/base.adapter.ts","../src/validation-reasons.ts","../src/terra-draw.ts","../src/validations/max-size.validation.ts"],"sourcesContent":["import { LineString, Polygon, Position } from \"geojson\";\nimport {\n\tStoreChangeHandler,\n\tGeoJSONStore,\n\tGeoJSONStoreFeatures,\n\tFeatureId,\n} from \"./store/store\";\n\nexport type HexColor = `#${string}`;\n\nexport type HexColorStyling =\n\t| HexColor\n\t| ((feature: GeoJSONStoreFeatures) => HexColor);\n\nexport type NumericStyling =\n\t| number\n\t| ((feature: GeoJSONStoreFeatures) => number);\n\nexport interface TerraDrawAdapterStyling {\n\tpointColor: HexColor;\n\tpointWidth: number;\n\tpointOutlineColor: HexColor;\n\tpointOutlineWidth: number;\n\tpolygonFillColor: HexColor;\n\tpolygonFillOpacity: number;\n\tpolygonOutlineColor: HexColor;\n\tpolygonOutlineWidth: number;\n\tlineStringWidth: number;\n\tlineStringColor: HexColor;\n\tzIndex: number;\n}\n\nexport type CartesianPoint = { x: number; y: number };\n\n// Neither buttons nor touch/pen contact changed since last event\t-1\n// Mouse move with no buttons pressed, Pen moved while hovering with no buttons pressed\t—\n// Left Mouse, Touch Contact, Pen contact\t0\n// Middle Mouse\t1\n// Right Mouse, Pen barrel button\t2\nexport interface TerraDrawMouseEvent {\n\tlng: number;\n\tlat: number;\n\tcontainerX: number;\n\tcontainerY: number;\n\tbutton: \"neither\" | \"left\" | \"middle\" | \"right\";\n\theldKeys: string[];\n\tisContextMenu: boolean;\n}\n\nexport interface TerraDrawKeyboardEvent {\n\tkey: string;\n\theldKeys: string[];\n\tpreventDefault: () => void;\n}\n\nexport type Cursor = Parameters<SetCursor>[0];\n\nexport type SetCursor = (\n\tcursor:\n\t\t| \"unset\"\n\t\t| \"grab\"\n\t\t| \"grabbing\"\n\t\t| \"crosshair\"\n\t\t| \"pointer\"\n\t\t| \"wait\"\n\t\t| \"move\",\n) => void;\n\nexport type Project = (lng: number, lat: number) => CartesianPoint;\nexport type Unproject = (x: number, y: number) => { lat: number; lng: number };\nexport type GetLngLatFromEvent = (event: PointerEvent | MouseEvent) => {\n\tlng: number;\n\tlat: number;\n} | null;\n\nexport type Projection = \"web-mercator\" | \"globe\";\n\nexport type OnFinishContext = { mode: string; action: string };\n\nexport type OnChangeContext = { origin: \"api\" };\n\nexport type TerraDrawGeoJSONStore = GeoJSONStore<\n\tOnChangeContext | undefined,\n\tFeatureId\n>;\n\nexport interface TerraDrawModeRegisterConfig {\n\tmode: string;\n\tstore: TerraDrawGeoJSONStore;\n\tsetDoubleClickToZoom: (enabled: boolean) => void;\n\tsetCursor: SetCursor;\n\tonChange: StoreChangeHandler<OnChangeContext | undefined>;\n\tonSelect: (selectedId: string) => void;\n\tonDeselect: (deselectedId: string) => void;\n\tonFinish: (finishedId: string, context: OnFinishContext) => void;\n\tproject: Project;\n\tunproject: Unproject;\n\tcoordinatePrecision: number;\n}\n\nexport enum UpdateTypes {\n\tCommit = \"commit\",\n\tProvisional = \"provisional\",\n\tFinish = \"finish\",\n}\n\ntype ValidationContext = Pick<\n\tTerraDrawModeRegisterConfig,\n\t\"project\" | \"unproject\" | \"coordinatePrecision\"\n> & {\n\tupdateType: UpdateTypes;\n};\n\nexport type Validation = (\n\tfeature: GeoJSONStoreFeatures,\n\tcontext: ValidationContext,\n) => {\n\tvalid: boolean;\n\treason?: string;\n};\n\nexport interface Snapping {\n\ttoLine?: boolean;\n\ttoCoordinate?: boolean;\n\ttoCustom?: (\n\t\tevent: TerraDrawMouseEvent,\n\t\tcontext: {\n\t\t\tcurrentId?: FeatureId;\n\t\t\tcurrentCoordinate?: number;\n\t\t\tgetCurrentGeometrySnapshot: () => (Polygon | LineString) | null;\n\t\t\tproject: Project;\n\t\t\tunproject: Unproject;\n\t\t},\n\t) => Position | undefined;\n}\n\nexport type TerraDrawModeState =\n\t| \"unregistered\"\n\t| \"registered\"\n\t| \"started\"\n\t| \"drawing\"\n\t| \"selecting\"\n\t| \"stopped\";\n\nexport interface TerraDrawCallbacks {\n\tgetState: () => TerraDrawModeState;\n\tonKeyUp: (event: TerraDrawKeyboardEvent) => void;\n\tonKeyDown: (event: TerraDrawKeyboardEvent) => void;\n\tonClick: (event: TerraDrawMouseEvent) => void;\n\tonMouseMove: (event: TerraDrawMouseEvent) => void;\n\tonDragStart: (\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) => void;\n\tonDrag: (\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) => void;\n\tonDragEnd: (\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) => void;\n\tonClear: () => void;\n\tonReady?(): void;\n}\n\nexport interface TerraDrawChanges {\n\tcreated: GeoJSONStoreFeatures[];\n\tupdated: GeoJSONStoreFeatures[];\n\tunchanged: GeoJSONStoreFeatures[];\n\tdeletedIds: FeatureId[];\n}\n\nexport type TerraDrawStylingFunction = {\n\t[mode: string]: (feature: GeoJSONStoreFeatures) => TerraDrawAdapterStyling;\n};\n\nexport interface TerraDrawAdapter {\n\tproject: Project;\n\tunproject: Unproject;\n\tsetCursor: SetCursor;\n\tgetLngLatFromEvent: GetLngLatFromEvent;\n\tsetDoubleClickToZoom: (enabled: boolean) => void;\n\tgetMapEventElement: () => HTMLElement;\n\tregister(callbacks: TerraDrawCallbacks): void;\n\tunregister(): void;\n\trender(changes: TerraDrawChanges, styling: TerraDrawStylingFunction): void;\n\tclear(): void;\n\tgetCoordinatePrecision(): number;\n}\n\nexport const SELECT_PROPERTIES = {\n\tSELECTED: \"selected\",\n\tMID_POINT: \"midPoint\",\n\tSELECTION_POINT_FEATURE_ID: \"selectionPointFeatureId\",\n\tSELECTION_POINT: \"selectionPoint\",\n} as const;\n\nexport const COMMON_PROPERTIES = {\n\tEDITED: \"edited\",\n\tCLOSING_POINT: \"closingPoint\",\n\tSNAPPING_POINT: \"snappingPoint\",\n\tCOORDINATE_POINT: \"coordinatePoint\",\n\tCOORDINATE_POINT_FEATURE_ID: \"coordinatePointFeatureId\",\n\tCOORDINATE_POINT_IDS: \"coordinatePointIds\",\n} as const;\n\nexport const Z_INDEX = {\n\tLAYER_ONE: 10,\n\tLAYER_TWO: 20,\n\tLAYER_THREE: 30,\n\tLAYER_FOUR: 40,\n\tLAYER_FIVE: 50,\n} as const;\n","import { Validation } from \"../common\";\nimport { FeatureId, IdStrategy } from \"./store\";\n\nexport const StoreValidationErrors = {\n\tFeatureHasNoId: \"Feature has no id\",\n\tFeatureIsNotObject: \"Feature is not object\",\n\tInvalidTrackedProperties: \"updatedAt and createdAt are not valid timestamps\",\n\tFeatureHasNoMode: \"Feature does not have a set mode\",\n\tFeatureIdIsNotValidGeoJSON: `Feature must be string or number as per GeoJSON spec`,\n\tFeatureIdIsNotValid: `Feature must match the id strategy (default is UUID4)`,\n\tFeatureHasNoGeometry: \"Feature has no geometry\",\n\tFeatureHasNoProperties: \"Feature has no properties\",\n\tFeatureGeometryNotSupported: \"Feature is not Point, LineString or Polygon\",\n\tFeatureCoordinatesNotAnArray: \"Feature coordinates is not an array\",\n\tInvalidModeProperty: \"Feature does not have a valid mode property\",\n} as const;\n\nfunction isObject(\n\tfeature: unknown,\n): feature is Record<string | number, unknown> {\n\treturn Boolean(\n\t\tfeature &&\n\t\t\ttypeof feature === \"object\" &&\n\t\t\tfeature !== null &&\n\t\t\t!Array.isArray(feature),\n\t);\n}\n\nexport function hasModeProperty(\n\tfeature: unknown,\n): feature is { properties: { mode: string } } {\n\treturn Boolean(\n\t\tfeature &&\n\t\t\ttypeof feature === \"object\" &&\n\t\t\t\"properties\" in feature &&\n\t\t\ttypeof feature.properties === \"object\" &&\n\t\t\tfeature.properties !== null &&\n\t\t\t\"mode\" in feature.properties,\n\t);\n}\n\nfunction dateIsValid(timestamp: unknown): boolean {\n\treturn (\n\t\ttypeof timestamp === \"number\" &&\n\t\t!isNaN(new Date(timestamp as number).valueOf())\n\t);\n}\n\nexport function isValidTimestamp(timestamp: unknown): boolean {\n\tif (!dateIsValid(timestamp)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nexport function isValidStoreFeature(\n\tfeature: unknown,\n\tisValidId: IdStrategy<FeatureId>[\"isValidId\"],\n): ReturnType<Validation> {\n\tlet error;\n\tif (!isObject(feature)) {\n\t\terror = StoreValidationErrors.FeatureIsNotObject;\n\t} else if (feature.id === null || feature.id === undefined) {\n\t\terror = StoreValidationErrors.FeatureHasNoId;\n\t} else if (typeof feature.id !== \"string\" && typeof feature.id !== \"number\") {\n\t\terror = StoreValidationErrors.FeatureIdIsNotValidGeoJSON;\n\t} else if (!isValidId(feature.id)) {\n\t\terror = StoreValidationErrors.FeatureIdIsNotValid;\n\t} else if (!isObject(feature.geometry)) {\n\t\terror = StoreValidationErrors.FeatureHasNoGeometry;\n\t} else if (!isObject(feature.properties)) {\n\t\terror = StoreValidationErrors.FeatureHasNoProperties;\n\t} else if (\n\t\ttypeof feature.geometry.type !== \"string\" ||\n\t\t![\"Polygon\", \"LineString\", \"Point\"].includes(feature.geometry.type)\n\t) {\n\t\terror = StoreValidationErrors.FeatureGeometryNotSupported;\n\t} else if (!Array.isArray(feature.geometry.coordinates)) {\n\t\terror = StoreValidationErrors.FeatureCoordinatesNotAnArray;\n\t} else if (\n\t\t!feature.properties.mode ||\n\t\ttypeof feature.properties.mode !== \"string\"\n\t) {\n\t\treturn { valid: false, reason: StoreValidationErrors.InvalidModeProperty };\n\t}\n\n\tif (error) {\n\t\treturn { valid: false, reason: error };\n\t}\n\n\treturn { valid: true };\n}\n","export const ValidationReasonFeatureNotPolygon = \"Feature is not a Polygon\";\nexport const ValidationReasonModeMismatch =\n\t\"Feature mode property does not match the mode being added to\";\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport {\n\tOnChangeContext,\n\tHexColor,\n\tOnFinishContext,\n\tProjection,\n\tTerraDrawAdapterStyling,\n\tTerraDrawGeoJSONStore,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawModeRegisterConfig,\n\tTerraDrawModeState,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreChangeHandler,\n} from \"../store/store\";\nimport { isValidStoreFeature } from \"../store/store-feature-validation\";\nimport { ValidationReasonModeMismatch } from \"../validations/common-validations\";\n\nexport type CustomStyling = Record<\n\tstring,\n\t| string\n\t| number\n\t| ((feature: GeoJSONStoreFeatures) => HexColor)\n\t| ((feature: GeoJSONStoreFeatures) => number)\n>;\n\nexport enum ModeTypes {\n\tDrawing = \"drawing\",\n\tSelect = \"select\",\n\tStatic = \"static\",\n\tRender = \"render\",\n}\n\nexport const DefaultPointerEvents = {\n\trightClick: true,\n\tcontextMenu: false,\n\tleftClick: true,\n\tonDragStart: true,\n\tonDrag: true,\n\tonDragEnd: true,\n} as const;\n\ntype AllowPointerEvent = boolean | ((event: TerraDrawMouseEvent) => boolean);\n\nexport interface PointerEvents {\n\tleftClick: AllowPointerEvent;\n\trightClick: AllowPointerEvent;\n\tcontextMenu: AllowPointerEvent;\n\tonDragStart: AllowPointerEvent;\n\tonDrag: AllowPointerEvent;\n\tonDragEnd: AllowPointerEvent;\n}\n\nexport type BaseModeOptions<Styling extends CustomStyling> = {\n\tstyles?: Partial<Styling>;\n\tpointerDistance?: number;\n\tvalidation?: Validation;\n\tprojection?: Projection;\n\tpointerEvents?: PointerEvents;\n};\n\nexport abstract class TerraDrawBaseDrawMode<Styling extends CustomStyling> {\n\t// State\n\tprotected _state: TerraDrawModeState = \"unregistered\";\n\tget state() {\n\t\treturn this._state;\n\t}\n\tset state(_) {\n\t\tthrow new Error(\"Please use the modes lifecycle methods\");\n\t}\n\n\t// Styles\n\tprotected _styles: Partial<Styling> = {};\n\tget styles(): Partial<Styling> {\n\t\treturn this._styles;\n\t}\n\tset styles(styling: Partial<Styling>) {\n\t\tif (typeof styling !== \"object\") {\n\t\t\tthrow new Error(\"Styling must be an object\");\n\t\t}\n\n\t\t// Note: This may not be initialised yet as styles can be set/changed pre-registration\n\t\tif (this.onStyleChange) {\n\t\t\tthis.onStyleChange([], \"styling\");\n\t\t}\n\t\tthis._styles = styling;\n\t}\n\n\tprotected pointerEvents: PointerEvents = DefaultPointerEvents;\n\tprotected behaviors: TerraDrawModeBehavior[] = [];\n\tprotected validate: Validation | undefined;\n\tprotected pointerDistance: number = 40;\n\tprotected coordinatePrecision!: number;\n\tprotected onStyleChange!: StoreChangeHandler<OnChangeContext | undefined>;\n\tprotected store!: TerraDrawGeoJSONStore;\n\tprotected projection: Projection = \"web-mercator\";\n\n\tprotected setDoubleClickToZoom!: TerraDrawModeRegisterConfig[\"setDoubleClickToZoom\"];\n\tprotected unproject!: TerraDrawModeRegisterConfig[\"unproject\"];\n\tprotected project!: TerraDrawModeRegisterConfig[\"project\"];\n\tprotected setCursor!: TerraDrawModeRegisterConfig[\"setCursor\"];\n\tprotected registerBehaviors(behaviorConfig: BehaviorConfig): void {}\n\n\tconstructor(\n\t\toptions?: BaseModeOptions<Styling>,\n\t\twillCallUpdateOptionsInParentClass = false,\n\t) {\n\t\t// Note: We want to updateOptions on the base class by default, but we don't want it to be\n\t\t// called twice if the extending class is going to call it as well\n\t\tif (!willCallUpdateOptionsInParentClass) {\n\t\t\tthis.updateOptions(options);\n\t\t}\n\t}\n\n\tupdateOptions(options?: BaseModeOptions<Styling>) {\n\t\tif (options?.styles) {\n\t\t\t// Note: we are updating this.styles and not this._styles - this is because\n\t\t\t// once registered we want to trigger the onStyleChange\n\t\t\tthis.styles = { ...this._styles, ...options.styles };\n\t\t}\n\n\t\tif (options?.pointerDistance) {\n\t\t\tthis.pointerDistance = options.pointerDistance;\n\t\t}\n\t\tif (options?.validation) {\n\t\t\tthis.validate = options && options.validation;\n\t\t}\n\t\tif (options?.projection) {\n\t\t\tthis.projection = options.projection;\n\t\t}\n\n\t\tif (options?.pointerEvents !== undefined) {\n\t\t\tthis.pointerEvents = options.pointerEvents;\n\t\t}\n\t}\n\n\tprotected allowPointerEvent(\n\t\tpointerEvent: AllowPointerEvent,\n\t\tevent: TerraDrawMouseEvent,\n\t) {\n\t\tif (typeof pointerEvent === \"boolean\") {\n\t\t\treturn pointerEvent;\n\t\t}\n\t\tif (typeof pointerEvent === \"function\") {\n\t\t\treturn pointerEvent(event);\n\t\t}\n\t\treturn true;\n\t}\n\n\ttype = ModeTypes.Drawing;\n\tmode = \"base\";\n\n\tprotected setDrawing() {\n\t\tif (this._state === \"started\") {\n\t\t\tthis._state = \"drawing\";\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be unregistered or stopped to start\");\n\t\t}\n\t}\n\n\tprotected setStarted() {\n\t\tif (\n\t\t\tthis._state === \"stopped\" ||\n\t\t\tthis._state === \"registered\" ||\n\t\t\tthis._state === \"drawing\" ||\n\t\t\tthis._state === \"selecting\"\n\t\t) {\n\t\t\tthis._state = \"started\";\n\t\t\tthis.setDoubleClickToZoom(false);\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be unregistered or stopped to start\");\n\t\t}\n\t}\n\n\tprotected setStopped() {\n\t\tif (this._state === \"started\") {\n\t\t\tthis._state = \"stopped\";\n\t\t\tthis.setDoubleClickToZoom(true);\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be started to be stopped\");\n\t\t}\n\t}\n\n\tregister(config: TerraDrawModeRegisterConfig) {\n\t\tif (this._state === \"unregistered\") {\n\t\t\tthis._state = \"registered\";\n\t\t\tthis.store = config.store;\n\t\t\tthis.store.registerOnChange(config.onChange);\n\t\t\tthis.setDoubleClickToZoom = config.setDoubleClickToZoom;\n\t\t\tthis.project = config.project;\n\t\t\tthis.unproject = config.unproject;\n\t\t\tthis.onSelect = config.onSelect;\n\t\t\tthis.onDeselect = config.onDeselect;\n\t\t\tthis.setCursor = config.setCursor;\n\t\t\tthis.onStyleChange = config.onChange;\n\t\t\tthis.onFinish = config.onFinish;\n\t\t\tthis.coordinatePrecision = config.coordinatePrecision;\n\n\t\t\tthis.registerBehaviors({\n\t\t\t\tmode: config.mode,\n\t\t\t\tstore: this.store,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t\tpointerDistance: this.pointerDistance,\n\t\t\t\tcoordinatePrecision: config.coordinatePrecision,\n\t\t\t\tprojection: this.projection,\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new Error(\"Can not register unless mode is unregistered\");\n\t\t}\n\t}\n\n\tvalidateFeature(feature: unknown): ReturnType<Validation> {\n\t\treturn this.performFeatureValidation(feature);\n\t}\n\n\tafterFeatureAdded(feature: GeoJSONStoreFeatures) {}\n\n\tprivate performFeatureValidation(feature: unknown): ReturnType<Validation> {\n\t\tif (this._state === \"unregistered\") {\n\t\t\tthrow new Error(\"Mode must be registered\");\n\t\t}\n\n\t\tconst validStoreFeature = isValidStoreFeature(\n\t\t\tfeature,\n\t\t\tthis.store.idStrategy.isValidId,\n\t\t);\n\n\t\t// We also want tp validate based on any specific valdiations passed in\n\t\tif (this.validate) {\n\t\t\tconst validation = this.validate(feature as GeoJSONStoreFeatures, {\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t// validatedFeature: feature as GeoJSONStoreFeatures,\n\t\t\t\tvalid: validStoreFeature.valid && validation.valid,\n\t\t\t\treason: validation.reason,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t// validatedFeature: feature as GeoJSONStoreFeatures,\n\t\t\tvalid: validStoreFeature.valid,\n\t\t\treason: validStoreFeature.reason,\n\t\t};\n\t}\n\n\tprotected validateModeFeature(\n\t\tfeature: unknown,\n\t\tmodeValidationFn: (feature: GeoJSONStoreFeatures) => ReturnType<Validation>,\n\t): ReturnType<Validation> {\n\t\tconst validation = this.performFeatureValidation(feature);\n\t\tif (validation.valid) {\n\t\t\tconst validatedFeature = feature as GeoJSONStoreFeatures;\n\t\t\tconst matches = validatedFeature.properties.mode === this.mode;\n\t\t\tif (!matches) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: ValidationReasonModeMismatch,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst modeValidation = modeValidationFn(validatedFeature);\n\t\t\treturn modeValidation;\n\t\t}\n\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: validation.reason,\n\t\t};\n\t}\n\n\tabstract start(): void;\n\tabstract stop(): void;\n\tabstract cleanUp(): void;\n\tabstract styleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling;\n\n\tonFinish(finishedId: FeatureId, context: OnFinishContext) {}\n\tonDeselect(deselectedId: FeatureId) {}\n\tonSelect(selectedId: FeatureId) {}\n\tonKeyDown(event: TerraDrawKeyboardEvent) {}\n\tonKeyUp(event: TerraDrawKeyboardEvent) {}\n\tonMouseMove(event: TerraDrawMouseEvent) {}\n\tonClick(event: TerraDrawMouseEvent) {}\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\n\tprotected getHexColorStylingValue(\n\t\tvalue: HexColor | ((feature: GeoJSONStoreFeatures) => HexColor) | undefined,\n\t\tdefaultValue: HexColor,\n\t\tfeature: GeoJSONStoreFeatures,\n\t): HexColor {\n\t\treturn this.getStylingValue(value, defaultValue, feature);\n\t}\n\n\tprotected getNumericStylingValue(\n\t\tvalue: number | ((feature: GeoJSONStoreFeatures) => number) | undefined,\n\t\tdefaultValue: number,\n\t\tfeature: GeoJSONStoreFeatures,\n\t): number {\n\t\treturn this.getStylingValue(value, defaultValue, feature);\n\t}\n\n\tprivate getStylingValue<T extends string | number>(\n\t\tvalue: T | ((feature: GeoJSONStoreFeatures) => T) | undefined,\n\t\tdefaultValue: T,\n\t\tfeature: GeoJSONStoreFeatures,\n\t) {\n\t\tif (value === undefined) {\n\t\t\treturn defaultValue;\n\t\t} else if (typeof value === \"function\") {\n\t\t\treturn value(feature);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t}\n}\n\nexport abstract class TerraDrawBaseSelectMode<\n\tStyling extends CustomStyling,\n> extends TerraDrawBaseDrawMode<Styling> {\n\tpublic type = ModeTypes.Select;\n\n\tpublic abstract selectFeature(featureId: FeatureId): void;\n\tpublic abstract deselectFeature(featureId: FeatureId): void;\n}\n","import { Position } from \"geojson\";\n\nexport function haversineDistanceKilometers(\n\tpointOne: Position,\n\tpointTwo: Position,\n) {\n\tconst toRadians = (latOrLng: number) => (latOrLng * Math.PI) / 180;\n\n\tconst phiOne = toRadians(pointOne[1]);\n\tconst lambdaOne = toRadians(pointOne[0]);\n\tconst phiTwo = toRadians(pointTwo[1]);\n\tconst lambdaTwo = toRadians(pointTwo[0]);\n\tconst deltaPhi = phiTwo - phiOne;\n\tconst deltalambda = lambdaTwo - lambdaOne;\n\n\tconst a =\n\t\tMath.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +\n\t\tMath.cos(phiOne) *\n\t\t\tMath.cos(phiTwo) *\n\t\t\tMath.sin(deltalambda / 2) *\n\t\t\tMath.sin(deltalambda / 2);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n\tconst radius = 6371e3;\n\tconst distance = radius * c;\n\n\treturn distance / 1000;\n}\n","export const earthRadius = 6371008.8;\n\nexport function degreesToRadians(degrees: number): number {\n\tconst radians = degrees % 360;\n\treturn (radians * Math.PI) / 180;\n}\n\nexport function lengthToRadians(distance: number): number {\n\tconst factor = earthRadius / 1000;\n\treturn distance / factor;\n}\n\nexport function radiansToDegrees(radians: number): number {\n\tconst degrees = radians % (2 * Math.PI);\n\treturn (degrees * 180) / Math.PI;\n}\n","export function limitPrecision(num: number, decimalLimit = 9) {\n\tconst decimals = Math.pow(10, decimalLimit);\n\treturn Math.round(num * decimals) / decimals;\n}\n","import { CartesianPoint } from \"../../common\";\n\nconst RADIANS_TO_DEGREES = 57.29577951308232 as const; // 180 / Math.PI\nconst DEGREES_TO_RADIANS = 0.017453292519943295 as const; // Math.PI / 180\nconst R = 6378137 as const;\n\n/**\n * Convert longitude and latitude to web mercator x and y\n * @param lng\n * @param lat\n * @returns - web mercator x and y\n */\nexport const lngLatToWebMercatorXY = (\n\tlng: number,\n\tlat: number,\n): CartesianPoint => ({\n\tx: lng === 0 ? 0 : lng * DEGREES_TO_RADIANS * R,\n\ty:\n\t\tlat === 0\n\t\t\t? 0\n\t\t\t: Math.log(Math.tan(Math.PI / 4 + (lat * DEGREES_TO_RADIANS) / 2)) * R,\n});\n\n/**\n * Convert web mercator x and y to longitude and latitude\n * @param x - web mercator x\n * @param y - web mercator y\n * @returns - longitude and latitude\n */\nexport const webMercatorXYToLngLat = (\n\tx: number,\n\ty: number,\n): { lng: number; lat: number } => ({\n\tlng: x === 0 ? 0 : RADIANS_TO_DEGREES * (x / R),\n\tlat:\n\t\ty === 0\n\t\t\t? 0\n\t\t\t: (2 * Math.atan(Math.exp(y / R)) - Math.PI / 2) * RADIANS_TO_DEGREES,\n});\n","import { Feature, Polygon, Position } from \"geojson\";\nimport {\n\tdegreesToRadians,\n\tlengthToRadians,\n\tradiansToDegrees,\n} from \"../helpers\";\nimport { limitPrecision } from \"../limit-decimal-precision\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\n\n// Adapted from the @turf/circle module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-circle/index.ts\n\nfunction destination(\n\torigin: Position,\n\tdistance: number,\n\tbearing: number,\n): Position {\n\tconst longitude1 = degreesToRadians(origin[0]);\n\tconst latitude1 = degreesToRadians(origin[1]);\n\tconst bearingRad = degreesToRadians(bearing);\n\tconst radians = lengthToRadians(distance);\n\n\t// Main\n\tconst latitude2 = Math.asin(\n\t\tMath.sin(latitude1) * Math.cos(radians) +\n\t\t\tMath.cos(latitude1) * Math.sin(radians) * Math.cos(bearingRad),\n\t);\n\tconst longitude2 =\n\t\tlongitude1 +\n\t\tMath.atan2(\n\t\t\tMath.sin(bearingRad) * Math.sin(radians) * Math.cos(latitude1),\n\t\t\tMath.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2),\n\t\t);\n\tconst lng = radiansToDegrees(longitude2);\n\tconst lat = radiansToDegrees(latitude2);\n\n\treturn [lng, lat];\n}\n\nexport function circle(options: {\n\tcenter: Position;\n\tradiusKilometers: number;\n\tcoordinatePrecision: number;\n\tsteps?: number;\n}): Feature<Polygon> {\n\tconst { center, radiusKilometers, coordinatePrecision } = options;\n\tconst steps = options.steps ? options.steps : 64;\n\n\tconst coordinates: Position[] = [];\n\tfor (let i = 0; i < steps; i++) {\n\t\tconst circleCoordinate = destination(\n\t\t\tcenter,\n\t\t\tradiusKilometers,\n\t\t\t(i * -360) / steps,\n\t\t);\n\n\t\tcoordinates.push([\n\t\t\tlimitPrecision(circleCoordinate[0], coordinatePrecision),\n\t\t\tlimitPrecision(circleCoordinate[1], coordinatePrecision),\n\t\t]);\n\t}\n\tcoordinates.push(coordinates[0]);\n\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: { type: \"Polygon\", coordinates: [coordinates] },\n\t\tproperties: {},\n\t};\n}\n\nexport function circleWebMercator(options: {\n\tcenter: Position;\n\tradiusKilometers: number;\n\tcoordinatePrecision: number;\n\tsteps?: number;\n}): GeoJSON.Feature<GeoJSON.Polygon> {\n\tconst { center, radiusKilometers, coordinatePrecision } = options;\n\tconst steps = options.steps ? options.steps : 64;\n\n\tconst radiusMeters = radiusKilometers * 1000;\n\n\tconst [lng, lat] = center;\n\tconst { x, y } = lngLatToWebMercatorXY(lng, lat);\n\n\tconst coordinates: Position[] = [];\n\tfor (let i = 0; i < steps; i++) {\n\t\tconst angle = (((i * 360) / steps) * Math.PI) / 180;\n\t\tconst dx = radiusMeters * Math.cos(angle);\n\t\tconst dy = radiusMeters * Math.sin(angle);\n\t\tconst [wx, wy] = [x + dx, y + dy];\n\t\tconst { lng, lat } = webMercatorXYToLngLat(wx, wy);\n\t\tcoordinates.push([\n\t\t\tlimitPrecision(lng, coordinatePrecision),\n\t\t\tlimitPrecision(lat, coordinatePrecision),\n\t\t]);\n\t}\n\n\t// Close the circle by adding the first point at the end\n\tcoordinates.push(coordinates[0]);\n\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: { type: \"Polygon\", coordinates: [coordinates] },\n\t\tproperties: {},\n\t};\n}\n","// Based on - https://github.com/mclaeysb/geojson-polygon-self-intersections\n// MIT License - Copyright (c) 2016 Manuel Claeys Bouuaert\n\nimport { Feature, LineString, Polygon, Position } from \"geojson\";\n// import * as rbush from \"rbush\";\n\ntype SelfIntersectsOptions = {\n\tepsilon: number;\n\t// reportVertexOnVertex: boolean;\n\t// reportVertexOnEdge: boolean;\n};\n\nexport function selfIntersects(\n\tfeature: Feature<Polygon> | Feature<LineString>,\n): boolean {\n\tconst options: SelfIntersectsOptions = {\n\t\tepsilon: 0,\n\t\t// reportVertexOnVertex: false,\n\t\t// reportVertexOnEdge: false,\n\t};\n\n\tlet coord: number[][][];\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tcoord = feature.geometry.coordinates;\n\t} else if (feature.geometry.type === \"LineString\") {\n\t\tcoord = [feature.geometry.coordinates];\n\t} else {\n\t\tthrow new Error(\"Self intersects only accepts Polygons and LineStrings\");\n\t}\n\n\tconst output: number[][] = [];\n\tconst seen: { [key: string]: boolean } = {};\n\n\tfor (let ring0 = 0; ring0 < coord.length; ring0++) {\n\t\tfor (let edge0 = 0; edge0 < coord[ring0].length - 1; edge0++) {\n\t\t\tfor (let ring1 = 0; ring1 < coord.length; ring1++) {\n\t\t\t\tfor (let edge1 = 0; edge1 < coord[ring1].length - 1; edge1++) {\n\t\t\t\t\t// speedup possible if only interested in unique: start last two loops at ring0 and edge0+1\n\t\t\t\t\tifInteresctionAddToOutput(ring0, edge0, ring1, edge1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn output.length > 0;\n\n\t// true if frac is (almost) 1.0 or 0.0\n\t// function isBoundaryCase(frac: number) {\n\t//   const e2 = options.epsilon * options.epsilon;\n\t//   return e2 >= (frac - 1) * (frac - 1) || e2 >= frac * frac;\n\t// }\n\n\tfunction isOutside(frac: number) {\n\t\treturn frac < 0 - options.epsilon || frac > 1 + options.epsilon;\n\t}\n\t// Function to check if two edges intersect and add the intersection to the output\n\tfunction ifInteresctionAddToOutput(\n\t\tring0: number,\n\t\tedge0: number,\n\t\tring1: number,\n\t\tedge1: number,\n\t) {\n\t\tconst start0 = coord[ring0][edge0];\n\t\tconst end0 = coord[ring0][edge0 + 1];\n\t\tconst start1 = coord[ring1][edge1];\n\t\tconst end1 = coord[ring1][edge1 + 1];\n\n\t\tconst intersection = intersect(start0, end0, start1, end1);\n\n\t\tif (intersection === null) {\n\t\t\treturn; // discard parallels and coincidence\n\t\t}\n\n\t\tlet frac0;\n\t\tlet frac1;\n\n\t\tif (end0[0] !== start0[0]) {\n\t\t\tfrac0 = (intersection[0] - start0[0]) / (end0[0] - start0[0]);\n\t\t} else {\n\t\t\tfrac0 = (intersection[1] - start0[1]) / (end0[1] - start0[1]);\n\t\t}\n\t\tif (end1[0] !== start1[0]) {\n\t\t\tfrac1 = (intersection[0] - start1[0]) / (end1[0] - start1[0]);\n\t\t} else {\n\t\t\tfrac1 = (intersection[1] - start1[1]) / (end1[1] - start1[1]);\n\t\t}\n\n\t\t// There are roughly three cases we need to deal with.\n\t\t// 1. If at least one of the fracs lies outside [0,1], there is no intersection.\n\t\tif (isOutside(frac0) || isOutside(frac1)) {\n\t\t\treturn; // require segment intersection\n\t\t}\n\n\t\t// 2. If both are either exactly 0 or exactly 1, this is not an intersection but just\n\t\t// two edge segments sharing a common vertex.\n\t\t// if (isBoundaryCase(frac0) && isBoundaryCase(frac1)) {\n\t\t//   if (!options.reportVertexOnVertex) {\n\t\t//     return;\n\t\t//   }\n\t\t// }\n\n\t\t// // 3. If only one of the fractions is exactly 0 or 1, this is\n\t\t// // a vertex-on-edge situation.\n\t\t// if (isBoundaryCase(frac0) || isBoundaryCase(frac1)) {\n\t\t//   if (!options.reportVertexOnEdge) {\n\t\t//     return;\n\t\t//   }\n\t\t// }\n\n\t\tconst key = intersection.toString();\n\t\tconst unique = !seen[key];\n\t\tif (unique) {\n\t\t\tseen[key] = true;\n\t\t}\n\n\t\toutput.push(intersection);\n\t}\n}\n\nfunction equalArrays(array1: Position, array2: Position) {\n\treturn array1[0] === array2[0] && array1[1] === array2[1];\n}\n\n// Function to compute where two lines (not segments) intersect. From https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection\nfunction intersect(\n\tstart0: Position,\n\tend0: Position,\n\tstart1: Position,\n\tend1: Position,\n) {\n\tif (\n\t\tequalArrays(start0, start1) ||\n\t\tequalArrays(start0, end1) ||\n\t\tequalArrays(end0, start1) ||\n\t\tequalArrays(end1, start1)\n\t) {\n\t\treturn null;\n\t}\n\n\tconst x0 = start0[0],\n\t\ty0 = start0[1],\n\t\tx1 = end0[0],\n\t\ty1 = end0[1],\n\t\tx2 = start1[0],\n\t\ty2 = start1[1],\n\t\tx3 = end1[0],\n\t\ty3 = end1[1];\n\n\tconst denom = (x0 - x1) * (y2 - y3) - (y0 - y1) * (x2 - x3);\n\tif (denom === 0) {\n\t\treturn null;\n\t}\n\n\tconst x4 =\n\t\t((x0 * y1 - y0 * x1) * (x2 - x3) - (x0 - x1) * (x2 * y3 - y2 * x3)) / denom;\n\n\tconst y4 =\n\t\t((x0 * y1 - y0 * x1) * (y2 - y3) - (y0 - y1) * (x2 * y3 - y2 * x3)) / denom;\n\n\treturn [x4, y4];\n}\n","import { Position } from \"geojson\";\n\nexport function validLatitude(lat: number) {\n\treturn lat >= -90 && lat <= 90;\n}\n\nexport function validLongitude(lng: number) {\n\treturn lng >= -180 && lng <= 180;\n}\n\nexport function coordinatePrecisionIsValid(\n\tcoordinate: Position,\n\tcoordinatePrecision: number,\n) {\n\treturn (\n\t\tgetDecimalPlaces(coordinate[0]) <= coordinatePrecision &&\n\t\tgetDecimalPlaces(coordinate[1]) <= coordinatePrecision\n\t);\n}\n\nexport function coordinateIsValid(coordinate: unknown[]) {\n\treturn (\n\t\tcoordinate.length === 2 &&\n\t\ttypeof coordinate[0] === \"number\" &&\n\t\ttypeof coordinate[1] === \"number\" &&\n\t\tcoordinate[0] !== Infinity &&\n\t\tcoordinate[1] !== Infinity &&\n\t\tvalidLongitude(coordinate[0]) &&\n\t\tvalidLatitude(coordinate[1])\n\t);\n}\n\nexport function getDecimalPlaces(value: number): number {\n\tlet current = 1;\n\tlet precision = 0;\n\twhile (Math.round(value * current) / current !== value) {\n\t\tcurrent *= 10;\n\t\tprecision++;\n\t}\n\n\treturn precision;\n}\n","import { Feature, Polygon, Position } from \"geojson\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport { selfIntersects } from \"../geometry/boolean/self-intersects\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\nimport { Validation } from \"../common\";\n\nexport const ValidationReasonFeatureNotPolygon = \"Feature is not a Polygon\";\nexport const ValidationReasonFeatureHasHoles = \"Feature has holes\";\nexport const ValidationReasonFeatureLessThanFourCoordinates =\n\t\"Feature has less than 4 coordinates\";\nexport const ValidationReasonFeatureHasInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureCoordinatesNotClosed =\n\t\"Feature coordinates are not closed\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidatePolygonFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"Polygon\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPolygon,\n\t\t};\n\t}\n\n\tif (feature.geometry.coordinates.length !== 1) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureHasHoles,\n\t\t};\n\t}\n\n\tif (feature.geometry.coordinates[0].length < 4) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureLessThanFourCoordinates,\n\t\t};\n\t}\n\n\tfor (let i = 0; i < feature.geometry.coordinates[0].length; i++) {\n\t\tif (!coordinateIsValid(feature.geometry.coordinates[0][i])) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureHasInvalidCoordinates,\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t!coordinatePrecisionIsValid(\n\t\t\t\tfeature.geometry.coordinates[0][i],\n\t\t\t\tcoordinatePrecision,\n\t\t\t)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (\n\t\t!coordinatesMatch(\n\t\t\tfeature.geometry.coordinates[0][0],\n\t\t\tfeature.geometry.coordinates[0][\n\t\t\t\tfeature.geometry.coordinates[0].length - 1\n\t\t\t],\n\t\t)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureCoordinatesNotClosed,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n\nexport function ValidateNonIntersectingPolygonFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tconst validatePolygonFeature = ValidatePolygonFeature(\n\t\tfeature,\n\t\tcoordinatePrecision,\n\t);\n\n\tif (!validatePolygonFeature.valid) {\n\t\treturn validatePolygonFeature;\n\t}\n\n\tif (selfIntersects(feature as Feature<Polygon>)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: \"Feature intersects itself\",\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n\n/**\n * Check if two coordinates are identical\n * @param coordinateOne - coordinate to compare\n * @param coordinateTwo - coordinate to compare with\n * @returns boolean\n */\nfunction coordinatesMatch(coordinateOne: Position, coordinateTwo: Position) {\n\treturn (\n\t\tcoordinateOne[0] === coordinateTwo[0] &&\n\t\tcoordinateOne[1] === coordinateTwo[1]\n\t);\n}\n","import { Feature, Position } from \"geojson\";\nimport {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tProjection,\n\tZ_INDEX,\n} from \"../../common\";\nimport { haversineDistanceKilometers } from \"../../geometry/measure/haversine-distance\";\nimport { circle, circleWebMercator } from \"../../geometry/shape/create-circle\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { Polygon } from \"geojson\";\nimport { calculateWebMercatorDistortion } from \"../../geometry/shape/web-mercator-distortion\";\n\ntype TerraDrawCircleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype CirclePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawCircleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawCircleModeKeyEvents | null;\n\tcursors?: Cursors;\n\tstartingRadiusKilometers?: number;\n\tprojection?: Projection;\n}\n\nexport class TerraDrawCircleMode extends TerraDrawBaseDrawMode<CirclePolygonStyling> {\n\tmode = \"circle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentCircleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawCircleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate startingRadiusKilometers = 0.00001;\n\tprivate cursorMovedAfterInitialCursorDown = false;\n\n\t/**\n\t * Create a new circle mode instance\n\t * @param options - Options to customize the behavior of the circle mode\n\t * @param options.keyEvents - Key events to cancel or finish the mode\n\t * @param options.cursors - Cursors to use for the mode\n\t * @param options.styles - Custom styling for the circle\n\t * @param options.pointerDistance - Distance in pixels to consider a pointer close to a vertex\n\t */\n\tconstructor(options?: TerraDrawCircleModeOptions<CirclePolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawCircleModeOptions<CirclePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.startingRadiusKilometers) {\n\t\t\tthis.startingRadiusKilometers = options.startingRadiusKilometers;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentCircleId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentCircleId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\tthis.center = undefined;\n\t\tthis.currentCircleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tif (this.clickCount === 0) {\n\t\t\t\tthis.center = [event.lng, event.lat];\n\t\t\t\tconst startingCircle = circle({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\n\t\t\t\tconst [createdId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: startingCircle.geometry,\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentCircleId = createdId;\n\t\t\t\tthis.clickCount++;\n\t\t\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\t\t\tthis.setDrawing();\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tthis.clickCount === 1 &&\n\t\t\t\t\tthis.center &&\n\t\t\t\t\tthis.currentCircleId !== undefined &&\n\t\t\t\t\tthis.cursorMovedAfterInitialCursorDown\n\t\t\t\t) {\n\t\t\t\t\tthis.updateCircle(event);\n\t\t\t\t}\n\n\t\t\t\t// Finish drawing\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.cursorMovedAfterInitialCursorDown = true;\n\t\tthis.updateCircle(event);\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tconst cleanUpId = this.currentCircleId;\n\n\t\tthis.center = undefined;\n\t\tthis.currentCircleId = undefined;\n\t\tthis.clickCount = 0;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\ttry {\n\t\t\tif (cleanUpId !== undefined) {\n\t\t\t\tthis.store.delete([cleanUpId]);\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.fillColor,\n\t\t\t\tstyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.outlineColor,\n\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate updateCircle(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 1 && this.center && this.currentCircleId) {\n\t\t\tconst newRadius = haversineDistanceKilometers(this.center, [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t]);\n\n\t\t\tlet updatedCircle: Feature<Polygon>;\n\n\t\t\tif (this.projection === \"web-mercator\") {\n\t\t\t\t// We want to track the mouse cursor, but we need to adjust the radius based\n\t\t\t\t// on the distortion of the web mercator projection\n\t\t\t\tconst distortion = calculateWebMercatorDistortion(this.center, [\n\t\t\t\t\tevent.lng,\n\t\t\t\t\tevent.lat,\n\t\t\t\t]);\n\n\t\t\t\tupdatedCircle = circleWebMercator({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius * distortion,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else if (this.projection === \"globe\") {\n\t\t\t\tupdatedCircle = circle({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Invalid projection\");\n\t\t\t}\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst valid = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\t\tgeometry: updatedCircle.geometry,\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!valid.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentCircleId, geometry: updatedCircle.geometry },\n\t\t\t]);\n\t\t\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\tproperty: \"radiusKilometers\",\n\t\t\t\t\tvalue: newRadius,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../common\";\n\nexport const getDefaultStyling = (): TerraDrawAdapterStyling => {\n\treturn {\n\t\tpolygonFillColor: \"#3f97e0\",\n\t\tpolygonOutlineColor: \"#3f97e0\",\n\t\tpolygonOutlineWidth: 4,\n\t\tpolygonFillOpacity: 0.3,\n\t\tpointColor: \"#3f97e0\",\n\t\tpointOutlineColor: \"#ffffff\",\n\t\tpointOutlineWidth: 0,\n\t\tpointWidth: 6,\n\t\tlineStringColor: \"#3f97e0\",\n\t\tlineStringWidth: 4,\n\t\tzIndex: 0,\n\t};\n};\n","import { Position } from \"geojson\";\nimport { haversineDistanceKilometers } from \"../measure/haversine-distance\";\nimport { lngLatToWebMercatorXY } from \"../project/web-mercator\";\n\n/*\n * Function to calculate the web mercator vs geodesic distortion between two coordinates\n * Value of 1 means no distortion, higher values mean higher distortion\n * */\nexport function calculateWebMercatorDistortion(\n\tsource: Position,\n\ttarget: Position,\n): number {\n\tconst geodesicDistance = haversineDistanceKilometers(source, target) * 1000;\n\tif (geodesicDistance === 0) {\n\t\treturn 1;\n\t}\n\n\tconst { x: x1, y: y1 } = lngLatToWebMercatorXY(source[0], source[1]);\n\tconst { x: x2, y: y2 } = lngLatToWebMercatorXY(target[0], target[1]);\n\tconst euclideanDistance = Math.sqrt(\n\t\tMath.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2),\n\t);\n\treturn euclideanDistance / geodesicDistance;\n}\n","import { CartesianPoint } from \"../../common\";\n\nexport const cartesianDistance = (\n\tpointOne: CartesianPoint,\n\tpointTwo: CartesianPoint,\n) => {\n\tconst { x: x1, y: y1 } = pointOne;\n\tconst { x: x2, y: y2 } = pointTwo;\n\tconst y = x2 - x1;\n\tconst x = y2 - y1;\n\treturn Math.sqrt(x * x + y * y);\n};\n","import { Feature, Polygon } from \"geojson\";\nimport { followsRightHandRule } from \"./boolean/right-hand-rule\";\n\nexport function ensureRightHandRule(polygon: Polygon): undefined | Polygon {\n\tconst isFollowingRightHandRule = followsRightHandRule(polygon);\n\tif (!isFollowingRightHandRule) {\n\t\treturn {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [polygon.coordinates[0].reverse()],\n\t\t} as Polygon;\n\t}\n}\n","import { Polygon } from \"geojson\";\n\n/**\n * Checks if a GeoJSON Polygon follows the right-hand rule.\n * @param polygon - The GeoJSON Polygon to check.\n * @returns {boolean} - True if the polygon follows the right-hand rule (counterclockwise outer ring), otherwise false.\n */\nexport function followsRightHandRule(polygon: Polygon): boolean {\n\tconst outerRing = polygon.coordinates[0];\n\n\tlet sum = 0;\n\tfor (let i = 0; i < outerRing.length - 1; i++) {\n\t\tconst [x1, y1] = outerRing[i];\n\t\tconst [x2, y2] = outerRing[i + 1];\n\t\tsum += (x2 - x1) * (y2 + y1);\n\t}\n\n\treturn sum < 0; // Right-hand rule: counterclockwise = negative area\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n\tZ_INDEX,\n} from \"../../common\";\nimport { Polygon } from \"geojson\";\n\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawFreehandModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype FreehandPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n\tclosingPointColor: HexColorStyling;\n\tclosingPointWidth: NumericStyling;\n\tclosingPointOutlineColor: HexColorStyling;\n\tclosingPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawFreehandModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tminDistance?: number;\n\tpreventPointsNearClose?: boolean;\n\tautoClose?: boolean;\n\tautoCloseTimeout?: number;\n\tkeyEvents?: TerraDrawFreehandModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawFreehandMode extends TerraDrawBaseDrawMode<FreehandPolygonStyling> {\n\tmode = \"freehand\" as const;\n\n\tprivate startingClick = false;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate minDistance: number = 20;\n\tprivate keyEvents: TerraDrawFreehandModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate preventPointsNearClose: boolean = true;\n\tprivate autoClose: boolean = false;\n\tprivate autoCloseTimeout = 500;\n\tprivate hasLeftStartingPoint = false;\n\tprivate preventNewFeature = false;\n\n\tconstructor(options?: TerraDrawFreehandModeOptions<FreehandPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tpublic updateOptions(\n\t\toptions?: TerraDrawFreehandModeOptions<FreehandPolygonStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.minDistance) {\n\t\t\tthis.minDistance = options.minDistance;\n\t\t}\n\n\t\tif (options?.preventPointsNearClose !== undefined) {\n\t\t\tthis.preventPointsNearClose = options.preventPointsNearClose;\n\t\t}\n\n\t\tif (options?.autoClose !== undefined) {\n\t\t\tthis.autoClose = options.autoClose;\n\t\t}\n\n\t\tif (options?.autoCloseTimeout) {\n\t\t\tthis.autoCloseTimeout = options.autoCloseTimeout;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\t\tthis.startingClick = false;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.hasLeftStartingPoint = false;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tif (this.currentId === undefined || this.startingClick === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst previousIndex = currentLineGeometry.coordinates[0].length - 2;\n\t\tconst [previousLng, previousLat] =\n\t\t\tcurrentLineGeometry.coordinates[0][previousIndex];\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tconst [closingLng, closingLat] = currentLineGeometry.coordinates[0][0];\n\t\tconst { x: closingX, y: closingY } = this.project(closingLng, closingLat);\n\t\tconst closingDistance = cartesianDistance(\n\t\t\t{ x: closingX, y: closingY },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tif (closingDistance < this.pointerDistance) {\n\t\t\t// We only want to close the polygon if the users cursor has left the\n\t\t\t// region of the starting point\n\t\t\tif (this.autoClose && this.hasLeftStartingPoint) {\n\t\t\t\t// If we have an autoCloseTimeout, we want to prevent new features\n\t\t\t\t// being created by accidental clicks for a short period of time\n\t\t\t\tthis.preventNewFeature = true;\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.preventNewFeature = false;\n\t\t\t\t}, this.autoCloseTimeout);\n\n\t\t\t\tthis.close();\n\t\t\t}\n\n\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t// We want to prohibit drawing new points at or around the closing\n\t\t\t// point as it can be non user friendly\n\t\t\tif (this.preventPointsNearClose) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.hasLeftStartingPoint = true;\n\t\t\tthis.setCursor(this.cursors.start);\n\t\t}\n\n\t\t// The cusor must have moved a minimum distance\n\t\t// before we add another coordinate\n\t\tif (distance < this.minDistance) {\n\t\t\treturn;\n\t\t}\n\n\t\tcurrentLineGeometry.coordinates[0].pop();\n\n\t\tconst newGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [\n\t\t\t\t[\n\t\t\t\t\t...currentLineGeometry.coordinates[0],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentLineGeometry.coordinates[0][0],\n\t\t\t\t],\n\t\t\t],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: newGeometry,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tif (this.preventNewFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.startingClick === false) {\n\t\t\t\tconst [createdId, closingPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: [event.lng, event.lat],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.currentId = createdId;\n\t\t\t\tthis.closingPointId = closingPointId;\n\t\t\t\tthis.startingClick = true;\n\t\t\t\tthis.setDrawing();\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tif (this.startingClick === true) {\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tconst cleanUpId = this.currentId;\n\t\tconst cleanUpClosingPointId = this.closingPointId;\n\n\t\tthis.closingPointId = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.startingClick = false;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\ttry {\n\t\t\tif (cleanUpId !== undefined) {\n\t\t\t\tthis.store.delete([cleanUpId]);\n\t\t\t}\n\t\t\tif (cleanUpClosingPointId !== undefined) {\n\t\t\t\tthis.store.delete([cleanUpClosingPointId]);\n\t\t\t}\n\t\t} catch (error) {}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.fillColor,\n\t\t\t\tstyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.outlineColor,\n\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\n\t\t\treturn styles;\n\t\t} else if (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.closingPointWidth,\n\t\t\t\tstyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.closingPointColor,\n\t\t\t\tstyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.closingPointOutlineColor,\n\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.closingPointOutlineWidth,\n\t\t\t\t2,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_FIVE;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePolygonFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n}\n","import {\n\tProject,\n\tProjection,\n\tTerraDrawGeoJSONStore,\n\tUnproject,\n} from \"../common\";\n\nexport type BehaviorConfig = {\n\tstore: TerraDrawGeoJSONStore;\n\tmode: string;\n\tproject: Project;\n\tunproject: Unproject;\n\tpointerDistance: number;\n\tcoordinatePrecision: number;\n\tprojection: Projection;\n};\n\nexport class TerraDrawModeBehavior {\n\tprotected store: TerraDrawGeoJSONStore;\n\tprotected mode: string;\n\tprotected project: Project;\n\tprotected unproject: Unproject;\n\tprotected pointerDistance: number;\n\tprotected coordinatePrecision: number;\n\tprotected projection: Projection;\n\n\tconstructor({\n\t\tstore,\n\t\tmode,\n\t\tproject,\n\t\tunproject,\n\t\tpointerDistance,\n\t\tcoordinatePrecision,\n\t\tprojection,\n\t}: BehaviorConfig) {\n\t\tthis.store = store;\n\t\tthis.mode = mode;\n\t\tthis.project = project;\n\t\tthis.unproject = unproject;\n\t\tthis.pointerDistance = pointerDistance;\n\t\tthis.coordinatePrecision = coordinatePrecision;\n\t\tthis.projection = projection;\n\t}\n}\n","import { Feature, Polygon } from \"geojson\";\nimport { Unproject } from \"../../common\";\n\nexport function createBBoxFromPoint({\n\tunproject,\n\tpoint,\n\tpointerDistance,\n}: {\n\tpoint: {\n\t\tx: number;\n\t\ty: number;\n\t};\n\tunproject: Unproject;\n\tpointerDistance: number;\n}) {\n\tconst halfDist = pointerDistance / 2;\n\tconst { x, y } = point;\n\n\treturn {\n\t\ttype: \"Feature\",\n\t\tproperties: {},\n\t\tgeometry: {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [\n\t\t\t\t[\n\t\t\t\t\tunproject(x - halfDist, y - halfDist), // TopLeft\n\t\t\t\t\tunproject(x + halfDist, y - halfDist), // TopRight\n\t\t\t\t\tunproject(x + halfDist, y + halfDist), // BottomRight\n\t\t\t\t\tunproject(x - halfDist, y + halfDist), // BottomLeft\n\t\t\t\t\tunproject(x - halfDist, y - halfDist), // TopLeft\n\t\t\t\t].map((c) => [c.lng, c.lat]),\n\t\t\t],\n\t\t},\n\t} as Feature<Polygon>;\n}\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\nimport { createBBoxFromPoint } from \"../geometry/shape/create-bbox\";\n\nexport class ClickBoundingBoxBehavior extends TerraDrawModeBehavior {\n\tconstructor(config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\n\tpublic create(event: TerraDrawMouseEvent) {\n\t\tconst { containerX: x, containerY: y } = event;\n\t\treturn createBBoxFromPoint({\n\t\t\tunproject: this.unproject,\n\t\t\tpoint: { x, y },\n\t\t\tpointerDistance: this.pointerDistance,\n\t\t});\n\t}\n}\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\n\nimport { Position } from \"geojson\";\nimport { cartesianDistance } from \"../geometry/measure/pixel-distance\";\n\nexport class PixelDistanceBehavior extends TerraDrawModeBehavior {\n\tconstructor(config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\tpublic measure(clickEvent: TerraDrawMouseEvent, secondCoordinate: Position) {\n\t\tconst { x, y } = this.project(secondCoordinate[0], secondCoordinate[1]);\n\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: clickEvent.containerX, y: clickEvent.containerY },\n\t\t);\n\n\t\treturn distance;\n\t}\n}\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\nimport { Feature, Position } from \"geojson\";\nimport { ClickBoundingBoxBehavior } from \"./click-bounding-box.behavior\";\nimport { BBoxPolygon, FeatureId } from \"../store/store\";\nimport { PixelDistanceBehavior } from \"./pixel-distance.behavior\";\n\nexport class CoordinateSnappingBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly clickBoundingBox: ClickBoundingBoxBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\t/** Returns the nearest snappable coordinate - on first click there is no currentId so no need to provide */\n\tpublic getSnappableCoordinateFirstClick = (event: TerraDrawMouseEvent) => {\n\t\tconst snappble = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties && feature.properties.mode === this.mode,\n\t\t\t);\n\t\t});\n\n\t\treturn snappble.coordinate;\n\t};\n\n\tpublic getSnappableCoordinate = (\n\t\tevent: TerraDrawMouseEvent,\n\t\tcurrentFeatureId: FeatureId,\n\t) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === this.mode &&\n\t\t\t\t\tfeature.id !== currentFeatureId,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappable(\n\t\tevent: TerraDrawMouseEvent,\n\t\tfilter?: (feature: Feature) => boolean,\n\t) {\n\t\tconst bbox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\n\t\tconst features = this.store.search(bbox, filter);\n\n\t\tconst closest: {\n\t\t\tcoordinate: undefined | Position;\n\t\t\tminDist: number;\n\t\t\tfeatureId: undefined | FeatureId;\n\t\t\tfeatureCoordinateIndex: undefined | number;\n\t\t} = {\n\t\t\tfeatureId: undefined,\n\t\t\tfeatureCoordinateIndex: undefined,\n\t\t\tcoordinate: undefined,\n\t\t\tminDist: Infinity,\n\t\t};\n\n\t\tfeatures.forEach((feature) => {\n\t\t\tlet coordinates: Position[];\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcoordinates.forEach((coord, coordIndex) => {\n\t\t\t\tconst dist = this.pixelDistance.measure(event, coord);\n\t\t\t\tif (dist < closest.minDist && dist < this.pointerDistance) {\n\t\t\t\t\tclosest.coordinate = coord;\n\t\t\t\t\tclosest.minDist = dist;\n\t\t\t\t\tclosest.featureId = feature.id;\n\t\t\t\t\tclosest.featureCoordinateIndex = coordIndex;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn closest;\n\t}\n}\n","import { Position } from \"geojson\";\nimport {\n\tdegreesToRadians,\n\tlengthToRadians,\n\tradiansToDegrees,\n} from \"../helpers\";\nimport { CartesianPoint } from \"../../common\";\n\n// Adapted from @turf/destination module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-desination/index.ts\n\nexport function destination(\n\torigin: Position,\n\tdistance: number,\n\tbearing: number,\n): Position {\n\tconst longitude1 = degreesToRadians(origin[0]);\n\tconst latitude1 = degreesToRadians(origin[1]);\n\tconst bearingRad = degreesToRadians(bearing);\n\tconst radians = lengthToRadians(distance);\n\n\tconst latitude2 = Math.asin(\n\t\tMath.sin(latitude1) * Math.cos(radians) +\n\t\t\tMath.cos(latitude1) * Math.sin(radians) * Math.cos(bearingRad),\n\t);\n\tconst longitude2 =\n\t\tlongitude1 +\n\t\tMath.atan2(\n\t\t\tMath.sin(bearingRad) * Math.sin(radians) * Math.cos(latitude1),\n\t\t\tMath.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2),\n\t\t);\n\tconst lng = radiansToDegrees(longitude2);\n\tconst lat = radiansToDegrees(latitude2);\n\n\treturn [lng, lat];\n}\n\n// Function to create a destination point in Web Mercator projection\nexport function webMercatorDestination(\n\t{ x, y }: CartesianPoint,\n\tdistance: number,\n\tbearing: number,\n): CartesianPoint {\n\t// Convert origin to Web Mercator\n\tconst bearingRad = degreesToRadians(bearing);\n\n\t// Calculate the destination coordinates\n\tconst deltaX = distance * Math.cos(bearingRad);\n\tconst deltaY = distance * Math.sin(bearingRad);\n\n\tconst newX = x + deltaX;\n\tconst newY = y + deltaY;\n\n\treturn { x: newX, y: newY };\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, radiansToDegrees } from \"../helpers\";\nimport { CartesianPoint } from \"../../common\";\n\n// Adapted from the @turf/bearing module which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-bearing\n\nexport function bearing(start: Position, end: Position): number {\n\tconst lon1 = degreesToRadians(start[0]);\n\tconst lon2 = degreesToRadians(end[0]);\n\tconst lat1 = degreesToRadians(start[1]);\n\tconst lat2 = degreesToRadians(end[1]);\n\tconst a = Math.sin(lon2 - lon1) * Math.cos(lat2);\n\tconst b =\n\t\tMath.cos(lat1) * Math.sin(lat2) -\n\t\tMath.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);\n\n\treturn radiansToDegrees(Math.atan2(a, b));\n}\n\nexport function webMercatorBearing(\n\t{ x: x1, y: y1 }: CartesianPoint,\n\t{ x: x2, y: y2 }: CartesianPoint,\n): number {\n\tconst deltaX = x2 - x1;\n\tconst deltaY = y2 - y1;\n\n\tif (deltaX === 0 && deltaY === 0) {\n\t\treturn 0; // No movement\n\t}\n\n\t// Calculate the angle in radians\n\tlet angle = Math.atan2(deltaY, deltaX);\n\n\t// Convert the angle to degrees\n\tangle = angle * (180 / Math.PI);\n\n\t// Normalize to -180 to 180\n\tif (angle > 180) {\n\t\tangle -= 360;\n\t} else if (angle < -180) {\n\t\tangle += 360;\n\t}\n\n\treturn angle;\n}\n\nexport function normalizeBearing(bearing: number): number {\n\treturn (bearing + 360) % 360;\n}\n","import { LineString, Position } from \"geojson\";\nimport { destination } from \"./destination\";\nimport { bearing } from \"./bearing\";\nimport { haversineDistanceKilometers } from \"./haversine-distance\";\n\n// Adapted from @turf/line-slice-along module which is MIT licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-line-slice-along/index.ts\n\nexport function lineSliceAlong(\n\tcoords: LineString[\"coordinates\"],\n\tstartDist: number,\n\tstopDist: number,\n): Position[] {\n\tconst slice: Position[] = [];\n\n\tconst origCoordsLength = coords.length;\n\n\tlet travelled = 0;\n\tlet overshot, direction, interpolated;\n\tfor (let i = 0; i < coords.length; i++) {\n\t\tif (startDist >= travelled && i === coords.length - 1) {\n\t\t\tbreak;\n\t\t} else if (travelled > startDist && slice.length === 0) {\n\t\t\tovershot = startDist - travelled;\n\t\t\tif (!overshot) {\n\t\t\t\tslice.push(coords[i]);\n\t\t\t\treturn slice;\n\t\t\t}\n\t\t\tdirection = bearing(coords[i], coords[i - 1]) - 180;\n\t\t\tinterpolated = destination(coords[i], overshot, direction);\n\t\t\tslice.push(interpolated);\n\t\t}\n\n\t\tif (travelled >= stopDist) {\n\t\t\tovershot = stopDist - travelled;\n\t\t\tif (!overshot) {\n\t\t\t\tslice.push(coords[i]);\n\t\t\t\treturn slice;\n\t\t\t}\n\t\t\tdirection = bearing(coords[i], coords[i - 1]) - 180;\n\t\t\tinterpolated = destination(coords[i], overshot, direction);\n\t\t\tslice.push(interpolated);\n\t\t\treturn slice;\n\t\t}\n\n\t\tif (travelled >= startDist) {\n\t\t\tslice.push(coords[i]);\n\t\t}\n\n\t\tif (i === coords.length - 1) {\n\t\t\treturn slice;\n\t\t}\n\n\t\ttravelled += haversineDistanceKilometers(coords[i], coords[i + 1]);\n\t}\n\n\tif (travelled < startDist && coords.length === origCoordsLength) {\n\t\tthrow new Error(\"Start position is beyond line\");\n\t}\n\n\tconst last = coords[coords.length - 1];\n\treturn [last, last];\n}\n","import { Position } from \"geojson\";\n\nfunction toRadians(degrees: number): number {\n\treturn degrees * (Math.PI / 180);\n}\n\nfunction toDegrees(radians: number): number {\n\treturn radians * (180 / Math.PI);\n}\n\nexport function generateGreatCircleCoordinates(\n\tstart: Position,\n\tend: Position,\n\tnumberOfPoints: number,\n): Position[] {\n\tconst points: Position[] = [];\n\n\tconst lat1 = toRadians(start[1]);\n\tconst lon1 = toRadians(start[0]);\n\tconst lat2 = toRadians(end[1]);\n\tconst lon2 = toRadians(end[0]);\n\n\tnumberOfPoints += 1;\n\n\t// Calculate the angular distance between the two points using the Haversine formula\n\tconst d =\n\t\t2 *\n\t\tMath.asin(\n\t\t\tMath.sqrt(\n\t\t\t\tMath.sin((lat2 - lat1) / 2) ** 2 +\n\t\t\t\t\tMath.cos(lat1) * Math.cos(lat2) * Math.sin((lon2 - lon1) / 2) ** 2,\n\t\t\t),\n\t\t);\n\n\tif (d === 0 || isNaN(d)) {\n\t\t// Start and end coordinates are the same, or distance calculation failed, return empty array\n\t\treturn points;\n\t}\n\n\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\tconst f = i / numberOfPoints; // Fraction of the total distance for the current point\n\t\tconst A = Math.sin((1 - f) * d) / Math.sin(d); // Interpolation factor A\n\t\tconst B = Math.sin(f * d) / Math.sin(d); // Interpolation factor B\n\n\t\t// Calculate the x, y, z coordinates of the intermediate point\n\t\tconst x =\n\t\t\tA * Math.cos(lat1) * Math.cos(lon1) + B * Math.cos(lat2) * Math.cos(lon2);\n\t\tconst y =\n\t\t\tA * Math.cos(lat1) * Math.sin(lon1) + B * Math.cos(lat2) * Math.sin(lon2);\n\t\tconst z = A * Math.sin(lat1) + B * Math.sin(lat2);\n\n\t\t// Calculate the latitude and longitude of the intermediate point from the x, y, z coordinates\n\t\tif (isNaN(x) || isNaN(y) || isNaN(z)) {\n\t\t\t// Skip this point if any coordinate is NaN\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst lat = Math.atan2(z, Math.sqrt(x ** 2 + y ** 2));\n\t\tconst lon = Math.atan2(y, x);\n\n\t\tif (isNaN(lat) || isNaN(lon)) {\n\t\t\t// Skip this point if any coordinate is NaN\n\t\t\tcontinue;\n\t\t}\n\n\t\tpoints.push([toDegrees(lon), toDegrees(lat)]);\n\t}\n\n\treturn points.slice(1, -1);\n}\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { Position } from \"geojson\";\nimport { haversineDistanceKilometers } from \"../geometry/measure/haversine-distance\";\nimport { lineSliceAlong } from \"../geometry/measure/slice-along\";\nimport { limitPrecision } from \"../geometry/limit-decimal-precision\";\nimport { generateGreatCircleCoordinates } from \"../geometry/shape/great-circle-coordinates\";\n\nexport class InsertCoordinatesBehavior extends TerraDrawModeBehavior {\n\tconstructor(readonly config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\n\tpublic generateInsertionCoordinates(\n\t\tcoordinateOne: Position,\n\t\tcoordinateTwo: Position,\n\t\tsegmentLength: number,\n\t): Position[] {\n\t\tconst line = [coordinateOne, coordinateTwo];\n\n\t\tlet lineLength = 0;\n\t\tfor (let i = 0; i < line.length - 1; i++) {\n\t\t\tlineLength += haversineDistanceKilometers(line[0], line[1]);\n\t\t}\n\n\t\t// If the line is shorter than the segment length then the original line is returned.\n\t\tif (lineLength <= segmentLength) {\n\t\t\treturn line;\n\t\t}\n\n\t\tlet numberOfSegments = lineLength / segmentLength - 1;\n\n\t\t// If numberOfSegments is integer, no need to plus 1\n\t\tif (!Number.isInteger(numberOfSegments)) {\n\t\t\tnumberOfSegments = Math.floor(numberOfSegments) + 1;\n\t\t}\n\n\t\tconst segments: Position[][] = [];\n\t\tfor (let i = 0; i < numberOfSegments; i++) {\n\t\t\tconst outline = lineSliceAlong(\n\t\t\t\tline,\n\t\t\t\tsegmentLength * i,\n\t\t\t\tsegmentLength * (i + 1),\n\t\t\t);\n\t\t\tsegments.push(outline);\n\t\t}\n\n\t\tconst coordinates: Position[] = [];\n\t\tfor (let i = 0; i < segments.length; i++) {\n\t\t\tconst line = segments[i];\n\t\t\tcoordinates.push(line[1]);\n\t\t}\n\n\t\tconst limitedCoordinates = this.limitCoordinates(coordinates);\n\n\t\treturn limitedCoordinates;\n\t}\n\n\tpublic generateInsertionGeodesicCoordinates(\n\t\tcoordinateOne: Position,\n\t\tcoordinateTwo: Position,\n\t\tsegmentLength: number,\n\t): Position[] {\n\t\tconst distance = haversineDistanceKilometers(coordinateOne, coordinateTwo);\n\t\tconst numberOfPoints = Math.floor(distance / segmentLength);\n\t\tconst coordinates = generateGreatCircleCoordinates(\n\t\t\tcoordinateOne,\n\t\t\tcoordinateTwo,\n\t\t\tnumberOfPoints,\n\t\t);\n\t\tconst limitedCoordinates = this.limitCoordinates(coordinates);\n\n\t\treturn limitedCoordinates;\n\t}\n\n\tprivate limitCoordinates(coordinates: Position[]) {\n\t\treturn coordinates.map((coordinate) => [\n\t\t\tlimitPrecision(coordinate[0], this.config.coordinatePrecision),\n\t\t\tlimitPrecision(coordinate[1], this.config.coordinatePrecision),\n\t\t]);\n\t}\n}\n","import { Position } from \"geojson\";\n\nexport function coordinatesIdentical(\n\tcoordinate: Position,\n\tcoordinateTwo: Position,\n) {\n\treturn (\n\t\tcoordinate[0] === coordinateTwo[0] && coordinate[1] === coordinateTwo[1]\n\t);\n}\n","import { Validation } from \"../common\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\n\nexport const ValidationReasonFeatureIsNotALineString =\n\t\"Feature is not a LineString\";\nexport const ValidationReasonFeatureHasLessThanTwoCoordinates =\n\t\"Feature has less than 2 coordinates\";\nexport const ValidationReasonFeatureInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidateLineStringFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"LineString\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureIsNotALineString,\n\t\t};\n\t}\n\n\tif (feature.geometry.coordinates.length < 2) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureHasLessThanTwoCoordinates,\n\t\t};\n\t}\n\n\tfor (let i = 0; i < feature.geometry.coordinates.length; i++) {\n\t\tif (!coordinateIsValid(feature.geometry.coordinates[i])) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureInvalidCoordinates,\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t!coordinatePrecisionIsValid(\n\t\t\t\tfeature.geometry.coordinates[i],\n\t\t\t\tcoordinatePrecision,\n\t\t\t)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn { valid: true };\n}\n","import { Feature, Point, Position, LineString } from \"geojson\";\nimport { degreesToRadians, radiansToDegrees } from \"./helpers\";\nimport { haversineDistanceKilometers } from \"./measure/haversine-distance\";\n\n// nearestPointOnLine is adapted from the @turf/midpoint which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-nearest-point-on-line\n\nexport function nearestPointOnLine(\n\tinputCoordinate: Position,\n\tlines: [Position, Position][],\n):\n\t| {\n\t\t\tcoordinate: Position;\n\t\t\tdistance: number;\n\t\t\tlineIndex: number;\n\t  }\n\t| undefined {\n\tlet closestPoint: Position = [Infinity, Infinity];\n\tlet closestDistance = Infinity;\n\tlet lineIndex = 0;\n\n\tfor (let line of lines) {\n\t\tconst startPosition: Position = line[0];\n\t\tconst stopPosition: Position = line[1];\n\n\t\t// sectionLength\n\t\tlet intersectPosition: Position;\n\t\tlet intersectDistance: number = Infinity;\n\n\t\t// Short circuit if snap point is start or end position of the line segment.\n\t\tif (\n\t\t\tstartPosition[0] === inputCoordinate[0] &&\n\t\t\tstartPosition[1] === inputCoordinate[1]\n\t\t) {\n\t\t\tintersectPosition = startPosition;\n\t\t} else if (\n\t\t\tstopPosition[0] === inputCoordinate[0] &&\n\t\t\tstopPosition[1] === inputCoordinate[1]\n\t\t) {\n\t\t\tintersectPosition = stopPosition;\n\t\t} else {\n\t\t\t// Otherwise, find the nearest point the hard way.\n\t\t\t[intersectPosition] = nearestPointOnSegment(\n\t\t\t\tstartPosition,\n\t\t\t\tstopPosition,\n\t\t\t\tinputCoordinate,\n\t\t\t);\n\t\t}\n\n\t\tif (intersectPosition) {\n\t\t\tintersectDistance = haversineDistanceKilometers(\n\t\t\t\tinputCoordinate,\n\t\t\t\tintersectPosition,\n\t\t\t);\n\n\t\t\tif (intersectDistance < closestDistance) {\n\t\t\t\tclosestPoint = intersectPosition;\n\t\t\t\tclosestDistance = intersectDistance;\n\t\t\t\tlineIndex = lines.indexOf(line);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn closestDistance === Infinity\n\t\t? undefined\n\t\t: { coordinate: closestPoint, distance: closestDistance, lineIndex };\n}\n\n/*\n * Plan is to externalise these vector functions to a simple third party\n * library.\n * Possible candidate is @amandaghassaei/vector-math though having some import\n * issues.\n */\ntype Vector = [number, number, number];\n\nfunction dot(v1: Vector, v2: Vector): number {\n\tconst [v1x, v1y, v1z] = v1;\n\tconst [v2x, v2y, v2z] = v2;\n\treturn v1x * v2x + v1y * v2y + v1z * v2z;\n}\n\n// https://en.wikipedia.org/wiki/Cross_product\nfunction cross(v1: Vector, v2: Vector): Vector {\n\tconst [v1x, v1y, v1z] = v1;\n\tconst [v2x, v2y, v2z] = v2;\n\treturn [v1y * v2z - v1z * v2y, v1z * v2x - v1x * v2z, v1x * v2y - v1y * v2x];\n}\n\nfunction magnitude(v: Vector) {\n\treturn Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2) + Math.pow(v[2], 2));\n}\n\nfunction angle(v1: Vector, v2: Vector): number {\n\tconst theta = dot(v1, v2) / (magnitude(v1) * magnitude(v2));\n\treturn Math.acos(Math.min(Math.max(theta, -1), 1));\n}\n\nfunction lngLatToVector(a: Position): Vector {\n\tconst lat = degreesToRadians(a[1]);\n\tconst lng = degreesToRadians(a[0]);\n\treturn [\n\t\tMath.cos(lat) * Math.cos(lng),\n\t\tMath.cos(lat) * Math.sin(lng),\n\t\tMath.sin(lat),\n\t];\n}\n\nfunction vectorToLngLat(v: Vector): Position {\n\tconst [x, y, z] = v;\n\tconst lat = radiansToDegrees(Math.asin(z));\n\tconst lng = radiansToDegrees(Math.atan2(y, x));\n\n\treturn [lng, lat];\n}\n\nfunction nearestPointOnSegment(\n\tposA: Position, // start point of segment to measure to\n\tposB: Position, // end point of segment to measure to\n\tposC: Position, // point to measure from\n): [Position, boolean, boolean] {\n\t// Based heavily on this article on finding cross track distance to an arc:\n\t// https://gis.stackexchange.com/questions/209540/projecting-cross-track-distance-on-great-circle\n\n\t// Convert spherical (lng, lat) to cartesian vector coords (x, y, z)\n\t// In the below https://tikz.net/spherical_1/ we convert lng (𝜙) and lat (𝜃)\n\t// into vectors with x, y, and z components with a length (r) of 1.\n\tconst A = lngLatToVector(posA); // the vector from 0,0,0 to posA\n\tconst B = lngLatToVector(posB); // ... to posB\n\tconst C = lngLatToVector(posC); // ... to posC\n\n\t// Components of target point.\n\tconst [Cx, Cy, Cz] = C;\n\n\t// Calculate coefficients.\n\tconst [D, E, F] = cross(A, B);\n\tconst a = E * Cz - F * Cy;\n\tconst b = F * Cx - D * Cz;\n\tconst c = D * Cy - E * Cx;\n\n\tconst f = c * E - b * F;\n\tconst g = a * F - c * D;\n\tconst h = b * D - a * E;\n\n\tconst t = 1 / Math.sqrt(Math.pow(f, 2) + Math.pow(g, 2) + Math.pow(h, 2));\n\n\t// Vectors to the two points these great circles intersect.\n\tconst I1: Vector = [f * t, g * t, h * t];\n\tconst I2: Vector = [-1 * f * t, -1 * g * t, -1 * h * t];\n\n\t// Figure out which is the closest intersection to this segment of the great\n\t// circle.\n\tconst angleAB = angle(A, B);\n\tconst angleAI1 = angle(A, I1);\n\tconst angleBI1 = angle(B, I1);\n\tconst angleAI2 = angle(A, I2);\n\tconst angleBI2 = angle(B, I2);\n\n\tlet I: Vector;\n\n\tif (\n\t\t(angleAI1 < angleAI2 && angleAI1 < angleBI2) ||\n\t\t(angleBI1 < angleAI2 && angleBI1 < angleBI2)\n\t) {\n\t\tI = I1;\n\t} else {\n\t\tI = I2;\n\t}\n\n\t// I is the closest intersection to the segment, though might not actually be\n\t// ON the segment.\n\n\t// If angle AI or BI is greater than angleAB, I lies on the circle *beyond* A\n\t// and B so use the closest of A or B as the intersection\n\tif (angle(A, I) > angleAB || angle(B, I) > angleAB) {\n\t\tif (\n\t\t\thaversineDistanceKilometers(vectorToLngLat(I), vectorToLngLat(A)) <=\n\t\t\thaversineDistanceKilometers(vectorToLngLat(I), vectorToLngLat(B))\n\t\t) {\n\t\t\treturn [vectorToLngLat(A), true, false];\n\t\t} else {\n\t\t\treturn [vectorToLngLat(B), false, true];\n\t\t}\n\t}\n\n\t// As angleAI nor angleBI don't exceed angleAB, I is on the segment\n\treturn [vectorToLngLat(I), false, false];\n}\n","import { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\nimport { Feature, Position } from \"geojson\";\nimport { ClickBoundingBoxBehavior } from \"./click-bounding-box.behavior\";\nimport { BBoxPolygon, FeatureId } from \"../store/store\";\nimport { PixelDistanceBehavior } from \"./pixel-distance.behavior\";\nimport { nearestPointOnLine } from \"../geometry/point-on-line\";\nimport { webMercatorNearestPointOnLine } from \"../geometry/web-mercator-point-on-line\";\n\nexport class LineSnappingBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly clickBoundingBox: ClickBoundingBoxBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\t/** Returns the nearest snappable coordinate - on first click there is no currentId so no need to provide */\n\tpublic getSnappableCoordinateFirstClick = (event: TerraDrawMouseEvent) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties && feature.properties.mode === this.mode,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappableCoordinate = (\n\t\tevent: TerraDrawMouseEvent,\n\t\tcurrentFeatureId: FeatureId,\n\t) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === this.mode &&\n\t\t\t\t\tfeature.id !== currentFeatureId,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappable(\n\t\tevent: TerraDrawMouseEvent,\n\t\tfilter?: (feature: Feature) => boolean,\n\t) {\n\t\tconst boundingBox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(boundingBox, filter);\n\t\tconst closest: {\n\t\t\tcoordinate: undefined | Position;\n\t\t\tminDistance: number;\n\t\t\tfeatureId: undefined | FeatureId;\n\t\t\tfeatureCoordinateIndex: undefined | number;\n\t\t} = {\n\t\t\tfeatureId: undefined,\n\t\t\tfeatureCoordinateIndex: undefined,\n\t\t\tcoordinate: undefined,\n\t\t\tminDistance: Infinity,\n\t\t};\n\t\tfeatures.forEach((feature) => {\n\t\t\tlet coordinates: Position[];\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst lines: [Position, Position][] = [];\n\n\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\tlines.push([coordinates[i], coordinates[i + 1]]);\n\t\t\t}\n\n\t\t\tlet nearest:\n\t\t\t\t| {\n\t\t\t\t\t\tcoordinate: Position;\n\t\t\t\t\t\tlineIndex: number;\n\t\t\t\t\t\tdistance: number;\n\t\t\t\t  }\n\t\t\t\t| undefined;\n\n\t\t\tconst lngLat: Position = [event.lng, event.lat];\n\n\t\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\t\tnearest = webMercatorNearestPointOnLine(lngLat, lines);\n\t\t\t} else if (this.config.projection === \"globe\") {\n\t\t\t\tnearest = nearestPointOnLine(lngLat, lines);\n\t\t\t}\n\n\t\t\tif (!nearest) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst distance = this.pixelDistance.measure(event, nearest.coordinate);\n\t\t\tif (distance < closest.minDistance && distance < this.pointerDistance) {\n\t\t\t\tclosest.featureId = feature.id;\n\t\t\t\tclosest.coordinate = nearest.coordinate;\n\t\t\t\tclosest.featureCoordinateIndex = nearest.lineIndex;\n\t\t\t\tclosest.minDistance = distance;\n\t\t\t}\n\t\t});\n\n\t\treturn closest;\n\t}\n}\n","import { Position } from \"geojson\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"./project/web-mercator\";\nimport { cartesianDistance } from \"./measure/pixel-distance\";\nimport { CartesianPoint } from \"../common\";\n\n// nearestPointOnLine is adapted from the @turf/midpoint which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-nearest-point-on-line\n\n/**\n * Takes two points and finds the closest point on the line between them to a third point.\n * @param lines\n * @param inputCoordinate\n * @returns\n */\nexport function webMercatorNearestPointOnLine(\n\tinputCoordinate: Position,\n\tlines: [Position, Position][],\n):\n\t| {\n\t\t\tcoordinate: Position;\n\t\t\tlineIndex: number;\n\t\t\tdistance: number;\n\t  }\n\t| undefined {\n\tlet closestPoint: Position = [Infinity, Infinity];\n\tlet closestDistance = Infinity;\n\tlet lineIndex = 0;\n\n\tfor (let line of lines) {\n\t\tconst startPosition: Position = line[0];\n\t\tconst stopPosition: Position = line[1];\n\n\t\t// sectionLength\n\t\tlet intersectPosition: Position;\n\t\tlet intersectDistance: number = Infinity;\n\n\t\tconst start = lngLatToWebMercatorXY(startPosition[0], startPosition[1]);\n\t\tconst stop = lngLatToWebMercatorXY(stopPosition[0], stopPosition[1]);\n\t\tconst source = lngLatToWebMercatorXY(\n\t\t\tinputCoordinate[0],\n\t\t\tinputCoordinate[1],\n\t\t);\n\n\t\t// Short circuit if snap point is start or end position of the line segment.\n\t\tif (\n\t\t\tstartPosition[0] === inputCoordinate[0] &&\n\t\t\tstartPosition[1] === inputCoordinate[1]\n\t\t) {\n\t\t\tintersectPosition = startPosition;\n\t\t} else if (\n\t\t\tstopPosition[0] === inputCoordinate[0] &&\n\t\t\tstopPosition[1] === inputCoordinate[1]\n\t\t) {\n\t\t\tintersectPosition = stopPosition;\n\t\t} else {\n\t\t\t// Otherwise, find the nearest point the hard way.\n\t\t\tconst { x, y } = findNearestPointOnLine(start, stop, source);\n\n\t\t\tconst { lng, lat } = webMercatorXYToLngLat(x, y);\n\t\t\tintersectPosition = [lng, lat];\n\t\t}\n\n\t\tif (intersectPosition) {\n\t\t\tintersectDistance = cartesianDistance(\n\t\t\t\tsource,\n\t\t\t\tlngLatToWebMercatorXY(intersectPosition[0], intersectPosition[1]),\n\t\t\t);\n\n\t\t\tif (intersectDistance < closestDistance) {\n\t\t\t\tclosestPoint = intersectPosition;\n\t\t\t\tclosestDistance = intersectDistance;\n\t\t\t\tlineIndex = lines.indexOf(line);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn closestDistance === Infinity\n\t\t? undefined\n\t\t: {\n\t\t\t\tcoordinate: closestPoint,\n\t\t\t\tlineIndex: lineIndex,\n\t\t\t\tdistance: closestDistance,\n\t\t\t};\n}\n\n/**\n * Finds the nearest Web Mercator coordinate on a line to a given coordinate.\n * @param pointA - The first point of the line (Web Mercator coordinate).\n * @param pointB - The second point of the line (Web Mercator coordinate).\n * @param target - The target point to which the nearest point on the line is calculated.\n * @returns The nearest Web Mercator coordinate on the line to the target.\n */\nfunction findNearestPointOnLine(\n\tpointA: CartesianPoint,\n\tpointB: CartesianPoint,\n\ttarget: CartesianPoint,\n): CartesianPoint {\n\t// Vector from pointA to pointB\n\tconst lineVector = {\n\t\tx: pointB.x - pointA.x,\n\t\ty: pointB.y - pointA.y,\n\t};\n\n\t// Vector from pointA to the target point\n\tconst targetVector = {\n\t\tx: target.x - pointA.x,\n\t\ty: target.y - pointA.y,\n\t};\n\n\t// Compute the dot product of the target vector with the line vector\n\tconst dotProduct =\n\t\ttargetVector.x * lineVector.x + targetVector.y * lineVector.y;\n\n\t// Compute the length squared of the line vector\n\tconst lineLengthSquared =\n\t\tlineVector.x * lineVector.x + lineVector.y * lineVector.y;\n\n\t// Find the projection of the target vector onto the line vector\n\tconst t = Math.max(0, Math.min(1, dotProduct / lineLengthSquared));\n\n\t// Compute the nearest point on the line\n\tconst nearestPoint = {\n\t\tx: pointA.x + t * lineVector.x,\n\t\ty: pointA.y + t * lineVector.y,\n\t};\n\n\treturn nearestPoint;\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCartesianPoint,\n\tCOMMON_PROPERTIES,\n\tZ_INDEX,\n\tSnapping,\n} from \"../../common\";\nimport { Feature, LineString, Point, Position } from \"geojson\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { ClickBoundingBoxBehavior } from \"../click-bounding-box.behavior\";\nimport { PixelDistanceBehavior } from \"../pixel-distance.behavior\";\nimport { CoordinateSnappingBehavior } from \"../coordinate-snapping.behavior\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { InsertCoordinatesBehavior } from \"../insert-coordinates.behavior\";\nimport { haversineDistanceKilometers } from \"../../geometry/measure/haversine-distance\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { ValidateLineStringFeature } from \"../../validations/linestring.validation\";\nimport { LineSnappingBehavior } from \"../line-snapping.behavior\";\n\ntype TerraDrawLineStringModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" } as const;\n\ntype LineStringStyling = {\n\tlineStringWidth: NumericStyling;\n\tlineStringColor: HexColorStyling;\n\tclosingPointColor: HexColorStyling;\n\tclosingPointWidth: NumericStyling;\n\tclosingPointOutlineColor: HexColorStyling;\n\tclosingPointOutlineWidth: NumericStyling;\n\tsnappingPointColor: HexColorStyling;\n\tsnappingPointWidth: NumericStyling;\n\tsnappingPointOutlineColor: HexColorStyling;\n\tsnappingPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n\tdragStart?: Cursor;\n\tdragEnd?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n\tdragStart: \"grabbing\",\n\tdragEnd: \"crosshair\",\n} as Required<Cursors>;\n\ninterface InertCoordinates {\n\tstrategy: \"amount\"; // In future this could be extended\n\tvalue: number;\n}\n\ninterface TerraDrawLineStringModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawLineStringModeKeyEvents | null;\n\tcursors?: Cursors;\n\tinsertCoordinates?: InertCoordinates;\n\teditable?: boolean;\n}\n\nexport class TerraDrawLineStringMode extends TerraDrawBaseDrawMode<LineStringStyling> {\n\tmode = \"linestring\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawLineStringModeKeyEvents = defaultKeyEvents;\n\tprivate snapping: Snapping | undefined;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\tprivate insertCoordinates: InertCoordinates | undefined;\n\tprivate lastCommitedCoordinates: Position[] | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\n\t// Editable properties\n\tprivate editable: boolean = false;\n\tprivate editedFeatureId: FeatureId | undefined;\n\tprivate editedFeatureCoordinateIndex: number | undefined;\n\tprivate editedSnapType: \"line\" | \"coordinate\" | undefined;\n\tprivate editedInsertIndex: number | undefined;\n\tprivate editedPointId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate coordinateSnapping!: CoordinateSnappingBehavior;\n\tprivate insertPoint!: InsertCoordinatesBehavior;\n\tprivate lineSnapping!: LineSnappingBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawLineStringModeOptions<LineStringStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawLineStringModeOptions<LineStringStyling> | undefined,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.snapping) {\n\t\t\tthis.snapping = options.snapping;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.insertCoordinates) {\n\t\t\tthis.insertCoordinates = options.insertCoordinates;\n\t\t}\n\n\t\tif (options && options.editable) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\t// Finish off the drawing\n\t\tcurrentLineGeometry.coordinates.pop();\n\n\t\tthis.updateGeometries(\n\t\t\t[...currentLineGeometry.coordinates],\n\t\t\tundefined,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Reset the state back to starting state\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.lastCommitedCoordinates = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listeners are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate updateGeometries(\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tclosingPointCoordinate: Point[\"coordinates\"] | undefined,\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updatedGeometry = { type: \"LineString\", coordinates } as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: updateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst geometries = [\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: updatedGeometry,\n\t\t\t},\n\t\t] as {\n\t\t\tid: FeatureId;\n\t\t\tgeometry: GeoJSONStoreGeometries;\n\t\t}[];\n\n\t\tif (this.closingPointId && closingPointCoordinate) {\n\t\t\tgeometries.push({\n\t\t\t\tid: this.closingPointId,\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: closingPointCoordinate,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tif (updateType === \"commit\") {\n\t\t\tthis.lastCommitedCoordinates = updatedGeometry.coordinates;\n\t\t}\n\n\t\tthis.store.updateGeometry(geometries);\n\t}\n\n\tprivate generateInsertCoordinates(startCoord: Position, endCoord: Position) {\n\t\tif (!this.insertCoordinates || !this.lastCommitedCoordinates) {\n\t\t\tthrow new Error(\"Not able to insert coordinates\");\n\t\t}\n\n\t\t// Other strategies my be implemented in the future\n\t\tif (this.insertCoordinates.strategy !== \"amount\") {\n\t\t\tthrow new Error(\"Strategy does not exist\");\n\t\t}\n\n\t\tconst distance = haversineDistanceKilometers(startCoord, endCoord);\n\t\tconst segmentDistance = distance / (this.insertCoordinates.value + 1);\n\t\tlet insertedCoordinates: Position[] = [];\n\n\t\tif (this.projection === \"globe\") {\n\t\t\tinsertedCoordinates =\n\t\t\t\tthis.insertPoint.generateInsertionGeodesicCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t\tsegmentDistance,\n\t\t\t\t);\n\t\t} else if (this.projection === \"web-mercator\") {\n\t\t\tinsertedCoordinates = this.insertPoint.generateInsertionCoordinates(\n\t\t\t\tstartCoord,\n\t\t\t\tendCoord,\n\t\t\t\tsegmentDistance,\n\t\t\t);\n\t\t}\n\n\t\treturn insertedCoordinates;\n\t}\n\n\tprivate createLine(startingCoord: Position) {\n\t\tconst [createdId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"LineString\",\n\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\tstartingCoord,\n\t\t\t\t\t\tstartingCoord, // This is the 'live' point that changes on mouse move\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.lastCommitedCoordinates = [startingCoord, startingCoord];\n\t\tthis.currentId = createdId;\n\t\tthis.currentCoordinate++;\n\t\tthis.setDrawing();\n\t}\n\n\tprivate firstUpdateToLine(updatedCoord: Position) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\tconst [pointId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: [...updatedCoord],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.closingPointId = pointId;\n\n\t\t// We are creating the point so we immediately want\n\t\t// to set the point cursor to show it can be closed\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst initialLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst closingPointCoordinate = undefined; // We don't need this until second click\n\n\t\tthis.updateGeometries(\n\t\t\tinitialLineCoordinates,\n\t\t\tclosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\tprivate updateToLine(updatedCoord: Position, cursorXY: CartesianPoint) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// If we are not inserting points we can get the penultimate coordinated\n\t\tconst [previousLng, previousLat] = this.lastCommitedCoordinates\n\t\t\t? this.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1]\n\t\t\t: currentCoordinates[currentCoordinates.length - 2];\n\n\t\t// Determine if the click closes the line and finished drawing\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: cursorXY.x, y: cursorXY.y },\n\t\t);\n\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\tif (isClosingClick) {\n\t\t\tthis.close();\n\t\t\treturn;\n\t\t}\n\n\t\t// The cursor will immediately change to closing because the\n\t\t// closing point will be underneath the cursor\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst updatedLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst updatedClosingPointCoordinate =\n\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\n\t\tthis.updateGeometries(\n\t\t\tupdatedLineCoordinates,\n\t\t\tupdatedClosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tnew PixelDistanceBehavior(config),\n\t\t\tnew ClickBoundingBoxBehavior(config),\n\t\t);\n\n\t\tthis.insertPoint = new InsertCoordinatesBehavior(config);\n\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst updatedCoord = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// Remove the 'live' point that changes on mouse move\n\t\tcurrentCoordinates.pop();\n\n\t\t// We want to ensure that when we are hovering over\n\t\t// the closing point that the pointer cursor is shown\n\t\tif (this.closingPointId) {\n\t\t\tconst [previousLng, previousLat] =\n\t\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\t\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\t\tconst distance = cartesianDistance(\n\t\t\t\t{ x, y },\n\t\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t\t);\n\n\t\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\t\tif (isClosingClick) {\n\t\t\t\tthis.setCursor(this.cursors.close);\n\t\t\t}\n\t\t}\n\n\t\tlet line = [...currentCoordinates, updatedCoord];\n\n\t\tif (\n\t\t\tthis.insertCoordinates &&\n\t\t\tthis.currentId &&\n\t\t\tthis.lastCommitedCoordinates\n\t\t) {\n\t\t\tconst startCoord =\n\t\t\t\tthis.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1];\n\t\t\tconst endCoord = updatedCoord;\n\t\t\tif (!coordinatesIdentical(startCoord, endCoord)) {\n\t\t\t\tconst insertedCoordinates = this.generateInsertCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t);\n\t\t\t\tline = [\n\t\t\t\t\t...this.lastCommitedCoordinates.slice(0, -1),\n\t\t\t\t\t...insertedCoordinates,\n\t\t\t\t\tupdatedCoord,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\t// Update the 'live' point\n\t\tthis.updateGeometries(line, undefined, UpdateTypes.Provisional);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\tif (!this.editable || this.state !== \"started\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.lineStringFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tcoordinates = geometry.coordinates;\n\n\t\t\t// Prevent creating an invalid linestring\n\t\t\tif (coordinates.length <= 2) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove coordinate from array\n\t\tcoordinates.splice(coordinateIndex, 1);\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\t\tconst updatedCoordinate = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tthis.createLine(updatedCoordinate);\n\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\tthis.firstUpdateToLine(updatedCoordinate);\n\t\t} else if (this.currentId) {\n\t\t\tthis.updateToLine(updatedCoordinate, {\n\t\t\t\tx: event.containerX,\n\t\t\t\ty: event.containerY,\n\t\t\t});\n\t\t}\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\t// We want pointer devices (mobile/tablet) to have\n\t\t\t// similar behaviour to mouse based devices so we\n\t\t\t// trigger a mousemove event before every click\n\t\t\t// if one has not been triggered to emulate this\n\t\t\tif (this.currentCoordinate > 0 && !this.mouseMove) {\n\t\t\t\tthis.onMouseMove(event);\n\t\t\t}\n\t\t\tthis.mouseMove = false;\n\n\t\t\tif (event.button === \"right\") {\n\t\t\t\tthis.onRightClick(event);\n\t\t\t} else if (event.button === \"left\") {\n\t\t\t\tthis.onLeftClick(event);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t}\n\n\t\tif (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragStart, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.state === \"started\") {\n\t\t\tconst lineSnapped = this.lineSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.lineStringFilter(feature),\n\t\t\t);\n\n\t\t\tif (lineSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"line\";\n\t\t\t\tthis.editedFeatureCoordinateIndex = lineSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = lineSnapped.featureId;\n\t\t\t\tsnappedCoordinate = lineSnapped.coordinate;\n\t\t\t}\n\n\t\t\tconst coordinateSnapped = this.coordinateSnapping.getSnappable(\n\t\t\t\tevent,\n\t\t\t\t(feature) => this.lineStringFilter(feature),\n\t\t\t);\n\n\t\t\tif (coordinateSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"coordinate\";\n\t\t\t\tthis.editedFeatureCoordinateIndex =\n\t\t\t\t\tcoordinateSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = coordinateSnapped.featureId;\n\t\t\t\tsnappedCoordinate = coordinateSnapped.coordinate;\n\t\t\t}\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.editedFeatureId || !snappedCoordinate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create a point to drag when editing\n\t\tif (!this.editedPointId) {\n\t\t\tconst [editedPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t},\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.EDITED]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\tthis.editedPointId = editedPointId;\n\t\t}\n\n\t\t// Drag Feature\n\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\tsetMapDraggability(false);\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDrag, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tthis.editedFeatureId === undefined ||\n\t\t\tthis.editedFeatureCoordinateIndex === undefined\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst featureCopy: LineString = this.store.getGeometryCopy(\n\t\t\tthis.editedFeatureId,\n\t\t);\n\t\tconst featureCoordinates = featureCopy.coordinates;\n\n\t\t// Either it's a coordinate drag or a line drag where the line coordinate has already been inserted\n\t\tif (\n\t\t\tthis.editedSnapType === \"coordinate\" ||\n\t\t\t(this.editedSnapType === \"line\" && this.editedInsertIndex !== undefined)\n\t\t) {\n\t\t\tfeatureCoordinates[this.editedFeatureCoordinateIndex] = [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t];\n\t\t} else if (\n\t\t\tthis.editedSnapType === \"line\" &&\n\t\t\tthis.editedInsertIndex === undefined\n\t\t) {\n\t\t\t// Splice inserts _before_ the index, so we need to add 1\n\t\t\tthis.editedInsertIndex = this.editedFeatureCoordinateIndex + 1;\n\n\t\t\t// Insert the new dragged snapped line coordinate\n\t\t\tfeatureCopy.coordinates.splice(this.editedInsertIndex, 0, [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t]);\n\n\t\t\t// We have inserted a point, need to change the edit index\n\t\t\t// so it can be moved correctly when it gets dragged again\n\t\t\tthis.editedFeatureCoordinateIndex++;\n\t\t}\n\n\t\tconst newLineStringGeometry = {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates: featureCopy.coordinates,\n\t\t} as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: newLineStringGeometry,\n\t\t\t\t\tproperties: this.store.getPropertiesCopy(this.editedFeatureId),\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping && this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tgeometry: newLineStringGeometry,\n\t\t\t},\n\t\t]);\n\n\t\tif (this.editedPointId) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.editedPointId,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: [event.lng, event.lat],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: true,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragEnd, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editedFeatureId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setCursor(this.cursors.dragEnd);\n\n\t\tif (this.editedPointId) {\n\t\t\tthis.store.delete([this.editedPointId]);\n\t\t\tthis.editedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: false,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(this.editedFeatureId, { mode: this.mode, action: \"edit\" });\n\n\t\t// Reset edit state\n\t\tthis.editedFeatureId = undefined;\n\t\tthis.editedFeatureCoordinateIndex = undefined;\n\t\tthis.editedInsertIndex = undefined;\n\t\tthis.editedSnapType = undefined;\n\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tconst cleanUpId = this.currentId;\n\t\tconst cleanupClosingPointId = this.closingPointId;\n\t\tconst snappedPointId = this.snappedPointId;\n\n\t\tthis.closingPointId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.currentCoordinate = 0;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\ttry {\n\t\t\tif (cleanUpId !== undefined) {\n\t\t\t\tthis.store.delete([cleanUpId]);\n\t\t\t}\n\t\t\tif (snappedPointId !== undefined) {\n\t\t\t\tthis.store.delete([snappedPointId]);\n\t\t\t}\n\t\t\tif (cleanupClosingPointId !== undefined) {\n\t\t\t\tthis.store.delete([cleanupClosingPointId]);\n\t\t\t}\n\t\t} catch (error) {}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"LineString\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tstyles.lineStringColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.lineStringColor,\n\t\t\t\tstyles.lineStringColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.lineStringWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.lineStringWidth,\n\t\t\t\tstyles.lineStringWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\n\t\t\treturn styles;\n\t\t} else if (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tconst isClosingPoint =\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.CLOSING_POINT];\n\n\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\tisClosingPoint\n\t\t\t\t\t? this.styles.closingPointColor\n\t\t\t\t\t: this.styles.snappingPointColor,\n\t\t\t\tstyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\tisClosingPoint\n\t\t\t\t\t? this.styles.closingPointWidth\n\t\t\t\t\t: this.styles.snappingPointWidth,\n\t\t\t\tstyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tisClosingPoint\n\t\t\t\t\t? this.styles.closingPointOutlineColor\n\t\t\t\t\t: this.styles.snappingPointOutlineColor,\n\t\t\t\t\"#ffffff\",\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tisClosingPoint\n\t\t\t\t\t? this.styles.closingPointOutlineWidth\n\t\t\t\t\t: this.styles.snappingPointOutlineWidth,\n\t\t\t\t2,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_FIVE;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateLineStringFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n\n\tprivate lineStringFilter(feature: Feature) {\n\t\treturn Boolean(\n\t\t\tfeature.geometry.type === \"LineString\" &&\n\t\t\t\tfeature.properties &&\n\t\t\t\tfeature.properties.mode === this.mode,\n\t\t);\n\t}\n\n\tprivate snapCoordinate(event: TerraDrawMouseEvent) {\n\t\tlet snappedCoordinate: Position | undefined;\n\n\t\tif (this.snapping?.toLine) {\n\t\t\tlet snapped: Position | undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCoordinate) {\n\t\t\tif (this.currentId) {\n\t\t\t\tsnappedCoordinate = this.coordinateSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnappedCoordinate =\n\t\t\t\t\tthis.coordinateSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCustom) {\n\t\t\tsnappedCoordinate = this.snapping.toCustom(event, {\n\t\t\t\tcurrentCoordinate: this.currentCoordinate,\n\t\t\t\tcurrentId: this.currentId,\n\t\t\t\tgetCurrentGeometrySnapshot: this.currentId\n\t\t\t\t\t? () =>\n\t\t\t\t\t\t\tthis.store.getGeometryCopy<LineString>(\n\t\t\t\t\t\t\t\tthis.currentId as FeatureId,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: () => null,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t});\n\t\t}\n\n\t\treturn snappedCoordinate;\n\t}\n}\n","import { Validation } from \"../common\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\n\nexport const ValidationReasonFeatureNotPoint = \"Feature is not a Point\";\nexport const ValidationReasonFeatureInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidatePointFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"Point\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPoint,\n\t\t};\n\t}\n\n\tif (!coordinateIsValid(feature.geometry.coordinates)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinates,\n\t\t};\n\t}\n\n\tif (\n\t\t!coordinatePrecisionIsValid(\n\t\t\tfeature.geometry.coordinates,\n\t\t\tcoordinatePrecision,\n\t\t)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tNumericStyling,\n\tHexColorStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n\tZ_INDEX,\n} from \"../../common\";\nimport {\n\tBBoxPolygon,\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidatePointFeature } from \"../../validations/point.validation\";\nimport { Point, Position } from \"geojson\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { ClickBoundingBoxBehavior } from \"../click-bounding-box.behavior\";\nimport { PixelDistanceBehavior } from \"../pixel-distance.behavior\";\n\ntype PointModeStyling = {\n\tpointWidth: NumericStyling;\n\tpointColor: HexColorStyling;\n\tpointOutlineColor: HexColorStyling;\n\tpointOutlineWidth: NumericStyling;\n\teditedPointColor: HexColorStyling;\n\teditedPointWidth: NumericStyling;\n\teditedPointOutlineColor: HexColorStyling;\n\teditedPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tcreate?: Cursor;\n\tdragStart?: Cursor;\n\tdragEnd?: Cursor;\n}\n\nconst defaultCursors = {\n\tcreate: \"crosshair\",\n\tdragStart: \"grabbing\",\n\tdragEnd: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawPointModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tcursors?: Cursors;\n\teditable?: boolean;\n}\n\nexport class TerraDrawPointMode extends TerraDrawBaseDrawMode<PointModeStyling> {\n\tmode = \"point\" as const;\n\n\t// Options\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate editable: boolean = false;\n\n\t// Internal state\n\tprivate editedFeatureId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawPointModeOptions<PointModeStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawPointModeOptions<PointModeStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.editable) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.create);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (\n\t\t\tevent.button === \"left\" &&\n\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)\n\t\t) {\n\t\t\tthis.onLeftClick(event);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** @internal */\n\tonMouseMove() {}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonKeyUp() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tthis.editedFeatureId = undefined;\n\t}\n\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragStart, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editable) {\n\t\t\tconst nearestPointFeature = this.getNearestPointFeature(event);\n\t\t\tthis.editedFeatureId = nearestPointFeature?.id;\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.editedFeatureId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Drag Feature\n\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\tsetMapDraggability(false);\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDrag, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editedFeatureId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newGeometry = {\n\t\t\ttype: \"Point\",\n\t\t\tcoordinates: [event.lng, event.lat],\n\t\t};\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\tproperties: this.store.getPropertiesCopy(this.editedFeatureId),\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// For cursor points we can simply move it\n\t\t// to the dragged position\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: [event.lng, event.lat],\n\t\t\t\t},\n\t\t\t},\n\t\t]);\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: true,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragEnd, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editedFeatureId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.onFinish(this.editedFeatureId, { mode: this.mode, action: \"edit\" });\n\n\t\tthis.setCursor(this.cursors.dragEnd);\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: false,\n\t\t\t},\n\t\t]);\n\t\tthis.editedFeatureId = undefined;\n\t\tsetMapDraggability(true);\n\t}\n\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tconst isEdited = Boolean(\n\t\t\t\tfeature.id && this.editedFeatureId === feature.id,\n\t\t\t);\n\n\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\tisEdited ? this.styles.editedPointWidth : this.styles.pointWidth,\n\t\t\t\tstyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\tisEdited ? this.styles.editedPointColor : this.styles.pointColor,\n\t\t\t\tstyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tisEdited\n\t\t\t\t\t? this.styles.editedPointOutlineColor\n\t\t\t\t\t: this.styles.pointOutlineColor,\n\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tisEdited\n\t\t\t\t\t? this.styles.editedPointOutlineWidth\n\t\t\t\t\t: this.styles.pointOutlineWidth,\n\t\t\t\t2,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_THREE;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePointFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\tconst geometry = {\n\t\t\ttype: \"Point\",\n\t\t\tcoordinates: [event.lng, event.lat],\n\t\t} as Point;\n\n\t\tconst properties = { mode: this.mode };\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst [pointId] = this.store.create([{ geometry, properties }]);\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(pointId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// We only want to be able to delete points if the mode is editable\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst clickedFeature = this.getNearestPointFeature(event);\n\n\t\tif (clickedFeature) {\n\t\t\tthis.store.delete([clickedFeature.id as FeatureId]);\n\t\t}\n\t}\n\n\tprivate getNearestPointFeature(event: TerraDrawMouseEvent) {\n\t\tconst bbox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(bbox);\n\n\t\tlet distance = Infinity;\n\t\tlet clickedFeature: GeoJSONStoreFeatures | undefined = undefined;\n\n\t\tfor (let i = 0; i < features.length; i++) {\n\t\t\tconst feature = features[i];\n\t\t\tconst isPoint =\n\t\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\t\tfeature.properties.mode === this.mode;\n\n\t\t\tif (!isPoint) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst position = feature.geometry.coordinates as Position;\n\t\t\tconst distanceToFeature = this.pixelDistance.measure(event, position);\n\n\t\t\tif (\n\t\t\t\tdistanceToFeature > distance ||\n\t\t\t\tdistanceToFeature > this.pointerDistance\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdistance = distanceToFeature;\n\t\t\tclickedFeature = feature;\n\t\t}\n\n\t\treturn clickedFeature;\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { COMMON_PROPERTIES, TerraDrawMouseEvent } from \"../../../common\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\n\nexport class ClosingPointsBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate _startEndPoints: string[] = [];\n\n\tget ids() {\n\t\treturn this._startEndPoints.concat();\n\t}\n\n\tset ids(_: string[]) {}\n\n\tpublic create(selectedCoords: Position[], mode: string) {\n\t\tif (this.ids.length) {\n\t\t\tthrow new Error(\"Opening and closing points already created\");\n\t\t}\n\n\t\tif (selectedCoords.length <= 3) {\n\t\t\tthrow new Error(\"Requires at least 4 coordinates\");\n\t\t}\n\n\t\tthis._startEndPoints = this.store.create(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[selectedCoords.length - 2],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this.ids.length) {\n\t\t\tthis.store.delete(this.ids);\n\t\t\tthis._startEndPoints = [];\n\t\t}\n\t}\n\n\tpublic update(updatedCoordinates: Position[]) {\n\t\tif (this.ids.length !== 2) {\n\t\t\tthrow new Error(\"No closing points to update\");\n\t\t}\n\n\t\tthis.store.updateGeometry(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[0],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[1],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[updatedCoordinates.length - 3],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic isClosingPoint(event: TerraDrawMouseEvent) {\n\t\tconst opening = this.store.getGeometryCopy(this.ids[0]);\n\t\tconst closing = this.store.getGeometryCopy(this.ids[1]);\n\n\t\tconst distance = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\topening.coordinates as Position,\n\t\t);\n\n\t\tconst distancePrevious = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\tclosing.coordinates as Position,\n\t\t);\n\n\t\tconst isClosing = distance < this.pointerDistance;\n\t\tconst isPreviousClosing = distancePrevious < this.pointerDistance;\n\n\t\treturn { isClosing, isPreviousClosing };\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { FeatureId } from \"../../../store/store\";\nimport { COMMON_PROPERTIES } from \"../../../common\";\n\nexport class CoordinatePointBehavior extends TerraDrawModeBehavior {\n\tconstructor(config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\n\tpublic createOrUpdate(featureId: FeatureId) {\n\t\tconst existingFeature = this.store.getGeometryCopy(featureId);\n\t\tconst existingProperties = this.store.getPropertiesCopy(featureId);\n\n\t\tlet coordinates: Position[];\n\n\t\tif (existingFeature.type === \"Polygon\") {\n\t\t\tcoordinates = existingFeature.coordinates[0].slice(0, -1) as Position[];\n\t\t} else if (existingFeature.type === \"LineString\") {\n\t\t\tcoordinates = existingFeature.coordinates as Position[];\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tconst existingFeatureProps = this.store.getPropertiesCopy(featureId);\n\n\t\tconst existingCoordinatePointIds =\n\t\t\texistingFeatureProps.coordinatePointIds as FeatureId[];\n\n\t\t// If no existing coordinate points, create them\n\t\tif (!existingCoordinatePointIds) {\n\t\t\tconst coordinatePointIds = this.createPoints(\n\t\t\t\tcoordinates,\n\t\t\t\texistingProperties.mode as string,\n\t\t\t\tfeatureId,\n\t\t\t);\n\t\t\tthis.setFeatureCoordinatePoints(featureId, coordinatePointIds);\n\t\t}\n\t\t// If the existing coordinate points are present in the store, update them\n\t\telse if (\n\t\t\texistingCoordinatePointIds &&\n\t\t\texistingCoordinatePointIds.every((id) => this.store.has(id))\n\t\t) {\n\t\t\t// Check if the coordinates have changed\n\t\t\tconst existingCoordinates =\n\t\t\t\texistingFeatureProps.coordinatePointIds as FeatureId[];\n\t\t\tconst existingCoordinatePoints = existingCoordinates.map(\n\t\t\t\t(id) => this.store.getGeometryCopy(id).coordinates as Position,\n\t\t\t);\n\n\t\t\t// If the number of coordinates has changed, delete and recreate as it's too\n\t\t\t// complex to update the existing coordinates unless someone is feeling brave\n\t\t\tif (existingCoordinates.length !== coordinates.length) {\n\t\t\t\tthis.deleteCoordinatePoints(existingCoordinates);\n\t\t\t\tconst coordinatePointIds = this.createPoints(\n\t\t\t\t\tcoordinates,\n\t\t\t\t\texistingProperties.mode as string,\n\t\t\t\t\tfeatureId,\n\t\t\t\t);\n\t\t\t\tthis.setFeatureCoordinatePoints(featureId, coordinatePointIds);\n\t\t\t} else {\n\t\t\t\t// Update the coordinates\n\t\t\t\tcoordinates.forEach((coordinate, i) => {\n\t\t\t\t\t// If the coordinates are the same, don't update\n\t\t\t\t\tif (\n\t\t\t\t\t\tcoordinate[0] === existingCoordinatePoints[i][0] &&\n\t\t\t\t\t\tcoordinate[1] === existingCoordinatePoints[i][1]\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Only update the coordinates that have changed\n\t\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: existingCoordinates[i],\n\t\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\t\tcoordinates: coordinate,\n\t\t\t\t\t\t\t} as Point,\n\t\t\t\t\t\t},\n\t\t\t\t\t]);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// If the existing coordinate points are not present in the store, delete them and recreate\n\t\telse {\n\t\t\t// If there are any leftover coordinate points we remove them\n\t\t\tconst existingPoints = existingCoordinatePointIds.filter((id) =>\n\t\t\t\tthis.store.has(id),\n\t\t\t);\n\t\t\tif (existingPoints.length) {\n\t\t\t\tthis.deleteCoordinatePoints(existingPoints);\n\t\t\t}\n\n\t\t\t// Create new coordinate points\n\t\t\tconst coordinatePointIds = this.createPoints(\n\t\t\t\tcoordinates,\n\t\t\t\texistingProperties.mode as string,\n\t\t\t\tfeatureId,\n\t\t\t);\n\t\t\tthis.setFeatureCoordinatePoints(featureId, coordinatePointIds);\n\t\t}\n\t}\n\n\tpublic deletePointsByFeatureIds(features: FeatureId[]) {\n\t\tfor (const featureId of features) {\n\t\t\tthis.deleteIfPresent(featureId);\n\t\t}\n\t}\n\n\tpublic getUpdated(featureId: FeatureId, updatedCoordinates: Position[]) {\n\t\tconst featureProperties = this.store.getPropertiesCopy(featureId);\n\n\t\tif (!featureProperties.coordinatePointIds) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn (featureProperties.coordinatePointIds as FeatureId[]).map(\n\t\t\t(id, i) => {\n\t\t\t\treturn {\n\t\t\t\t\tid,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t...this.store.getGeometryCopy(id),\n\t\t\t\t\t\tcoordinates: updatedCoordinates[i],\n\t\t\t\t\t} as Point,\n\t\t\t\t};\n\t\t\t},\n\t\t) as {\n\t\t\tid: FeatureId;\n\t\t\tgeometry: Point;\n\t\t}[];\n\t}\n\n\tprivate createPoints(\n\t\tcoordinates: Position[],\n\t\tmode: string,\n\t\tfeatureId: FeatureId,\n\t) {\n\t\treturn this.store.create(\n\t\t\tcoordinates.map((coordinate, i) => ({\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: coordinate,\n\t\t\t\t},\n\t\t\t\tproperties: {\n\t\t\t\t\tmode,\n\t\t\t\t\t[COMMON_PROPERTIES.COORDINATE_POINT]: true,\n\t\t\t\t\t[COMMON_PROPERTIES.COORDINATE_POINT_FEATURE_ID]: featureId,\n\t\t\t\t\tindex: i,\n\t\t\t\t},\n\t\t\t})),\n\t\t);\n\t}\n\n\tprivate setFeatureCoordinatePoints(\n\t\tfeatureId: FeatureId,\n\t\tvalue: FeatureId[] | null,\n\t) {\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.COORDINATE_POINT_IDS,\n\t\t\t\tvalue: value,\n\t\t\t},\n\t\t]);\n\t}\n\n\tprivate deleteCoordinatePoints(coordinatePointIds: FeatureId[]) {\n\t\t// We have to account for someone manually deleting the coordinate points or only partially restoring them\n\t\t// from some persistent storage. Essentially we cannot assume they are all present in the store.\n\t\tconst existingCoordinatePointIds = coordinatePointIds.filter((id) =>\n\t\t\tthis.store.has(id),\n\t\t) as FeatureId[];\n\t\tthis.store.delete(existingCoordinatePointIds);\n\t}\n\n\tprivate deleteIfPresent(featureId: FeatureId) {\n\t\tconst existingFeatureProps = this.store.getPropertiesCopy(featureId);\n\t\tconst coordinatePoints =\n\t\t\texistingFeatureProps.coordinatePointIds as FeatureId[];\n\n\t\tif (coordinatePoints) {\n\t\t\tthis.deleteCoordinatePoints(coordinatePoints);\n\t\t\tthis.setFeatureCoordinatePoints(featureId, null);\n\t\t}\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n\tProject,\n\tUnproject,\n\tZ_INDEX,\n\tSnapping,\n} from \"../../common\";\nimport { Feature, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n\tPointerEvents,\n} from \"../base.mode\";\nimport { PixelDistanceBehavior } from \"../pixel-distance.behavior\";\nimport { ClickBoundingBoxBehavior } from \"../click-bounding-box.behavior\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { createPolygon } from \"../../util/geoms\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { ClosingPointsBehavior } from \"./behaviors/closing-points.behavior\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { LineSnappingBehavior } from \"../line-snapping.behavior\";\nimport { CoordinateSnappingBehavior } from \"../coordinate-snapping.behavior\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\nimport { CoordinatePointBehavior } from \"../select/behaviors/coordinate-point.behavior\";\n\ntype TerraDrawPolygonModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype PolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n\tclosingPointWidth: NumericStyling;\n\tclosingPointColor: HexColorStyling;\n\tclosingPointOutlineWidth: NumericStyling;\n\tclosingPointOutlineColor: HexColorStyling;\n\tsnappingPointWidth: NumericStyling;\n\tsnappingPointColor: HexColorStyling;\n\tsnappingPointOutlineWidth: NumericStyling;\n\tsnappingPointOutlineColor: HexColorStyling;\n\teditedPointWidth: NumericStyling;\n\teditedPointColor: HexColorStyling;\n\teditedPointOutlineWidth: NumericStyling;\n\teditedPointOutlineColor: HexColorStyling;\n\tcoordinatePointWidth: NumericStyling;\n\tcoordinatePointColor: HexColorStyling;\n\tcoordinatePointOutlineWidth: NumericStyling;\n\tcoordinatePointOutlineColor: HexColorStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n\tdragStart?: Cursor;\n\tdragEnd?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n\tdragStart: \"grabbing\",\n\tdragEnd: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tpointerEvents?: PointerEvents;\n\tcursors?: Cursors;\n\teditable?: boolean;\n\tshowCoordinatePoints?: boolean;\n}\n\nexport class TerraDrawPolygonMode extends TerraDrawBaseDrawMode<PolygonStyling> {\n\tmode = \"polygon\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawPolygonModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\tprivate showCoordinatePoints = false;\n\n\t// Snapping\n\tprivate snapping: Snapping | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\n\t// Editable\n\tprivate editable: boolean = false;\n\tprivate editedFeatureId: FeatureId | undefined;\n\tprivate editedFeatureCoordinateIndex: number | undefined;\n\tprivate editedSnapType: \"line\" | \"coordinate\" | undefined;\n\tprivate editedInsertIndex: number | undefined;\n\tprivate editedPointId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate coordinatePoints!: CoordinatePointBehavior;\n\tprivate lineSnapping!: LineSnappingBehavior;\n\tprivate coordinateSnapping!: CoordinateSnappingBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate closingPoints!: ClosingPointsBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawPolygonModeOptions<PolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawPolygonModeOptions<PolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\t// null is the case where we want to explicitly turn key bindings off\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.snapping) {\n\t\t\tthis.snapping = options.snapping;\n\t\t}\n\n\t\tif (options?.editable !== undefined) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\n\t\tif (options?.pointerEvents !== undefined) {\n\t\t\tthis.pointerEvents = options.pointerEvents;\n\t\t}\n\n\t\tif (options?.showCoordinatePoints !== undefined) {\n\t\t\tthis.showCoordinatePoints = options.showCoordinatePoints;\n\n\t\t\t// If we are not showing coordinate points, we need to add them all\n\t\t\tif (this.coordinatePoints && options.showCoordinatePoints === true) {\n\t\t\t\tconst features = this.store.copyAllWhere(\n\t\t\t\t\t(properties) => properties.mode === this.mode,\n\t\t\t\t);\n\t\t\t\tconst polygonIds = features.map((feature) => feature.id as FeatureId);\n\t\t\t\tpolygonIds.forEach((id) => {\n\t\t\t\t\tthis.coordinatePoints.createOrUpdate(id);\n\t\t\t\t});\n\t\t\t} else if (this.coordinatePoints && this.showCoordinatePoints === false) {\n\t\t\t\tconst featuresWithCoordinates = this.store.copyAllWhere(\n\t\t\t\t\t(properties) =>\n\t\t\t\t\t\tproperties.mode === this.mode &&\n\t\t\t\t\t\tBoolean(\n\t\t\t\t\t\t\tproperties[COMMON_PROPERTIES.COORDINATE_POINT_IDS] as FeatureId[],\n\t\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tthis.coordinatePoints.deletePointsByFeatureIds(\n\t\t\t\t\tfeaturesWithCoordinates.map((f) => f.id as FeatureId),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\t// We don't want to allow closing if there is not enough\n\t\t// coordinates. We have extra because we insert them on mouse\n\t\t// move\n\t\tif (currentPolygonCoordinates.length < 5) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t[...currentPolygonCoordinates.slice(0, -2), currentPolygonCoordinates[0]],\n\t\t\tUpdateTypes.Finish,\n\t\t);\n\n\t\tif (!updated) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.closingPoints.delete();\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.closingPoints = new ClosingPointsBehavior(config, this.pixelDistance);\n\n\t\tthis.coordinatePoints = new CoordinatePointBehavior(config);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else {\n\t\t\tconst { isClosing, isPreviousClosing } =\n\t\t\t\tthis.closingPoints.isClosingPoint(event);\n\n\t\t\tif (isPreviousClosing || isClosing) {\n\t\t\t\tif (this.snappedPointId) {\n\t\t\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\t\t\tthis.snappedPointId = undefined;\n\t\t\t\t}\n\n\t\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\tthis.updatePolygonGeometry(updatedCoordinates, UpdateTypes.Provisional);\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{ id: this.currentId, geometry: updatedGeometry },\n\t\t]);\n\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(this.currentId);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate snapCoordinate(event: TerraDrawMouseEvent): undefined | Position {\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.snapping?.toLine) {\n\t\t\tlet snapped: Position | undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCoordinate) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.coordinateSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped =\n\t\t\t\t\tthis.coordinateSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCustom) {\n\t\t\tsnappedCoordinate = this.snapping.toCustom(event, {\n\t\t\t\tcurrentCoordinate: this.currentCoordinate,\n\t\t\t\tcurrentId: this.currentId,\n\t\t\t\tgetCurrentGeometrySnapshot: this.currentId\n\t\t\t\t\t? () =>\n\t\t\t\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId as FeatureId)\n\t\t\t\t\t: () => null,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t});\n\t\t}\n\n\t\treturn snappedCoordinate;\n\t}\n\n\tprivate polygonFilter(feature: Feature) {\n\t\treturn Boolean(\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\t\tfeature.properties &&\n\t\t\t\tfeature.properties.mode === this.mode,\n\t\t);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// Right click is only relevant when editable is true\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"Polygon\") {\n\t\t\tcoordinates = geometry.coordinates[0];\n\n\t\t\t// Prevent creating an invalid polygon\n\t\t\tif (coordinates.length <= 4) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isFinalPolygonCoordinate =\n\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t(coordinateIndex === 0 || coordinateIndex === coordinates.length - 1);\n\n\t\tif (isFinalPolygonCoordinate) {\n\t\t\t// Deleting the final coordinate in a polygon breaks it\n\t\t\t// because GeoJSON expects a duplicate, so we need to fix\n\t\t\t// it by adding the new first coordinate to the end\n\t\t\tcoordinates.shift();\n\t\t\tcoordinates.pop();\n\t\t\tcoordinates.push([coordinates[0][0], coordinates[0][1]]);\n\t\t} else {\n\t\t\t// Remove coordinate from array\n\t\t\tcoordinates.splice(coordinateIndex, 1);\n\t\t}\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(featureId);\n\t\t}\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\tif (snappedCoordinate) {\n\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t}\n\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\tif (this.showCoordinatePoints) {\n\t\t\t\tthis.coordinatePoints.createOrUpdate(newId);\n\t\t\t}\n\n\t\t\t// Ensure the state is updated to reflect drawing has started\n\t\t\tthis.setDrawing();\n\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\tif (snappedCoordinate) {\n\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t}\n\n\t\t\tconst currentPolygonGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\t\tthis.currentId,\n\t\t\t);\n\n\t\t\tconst previousCoordinate = currentPolygonGeometry.coordinates[0][0];\n\t\t\tconst isIdentical = coordinatesIdentical(\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\tpreviousCoordinate,\n\t\t\t);\n\n\t\t\tif (isIdentical) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t\t[\n\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t],\n\t\t\t\tUpdateTypes.Commit,\n\t\t\t);\n\n\t\t\tif (!updated) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.currentCoordinate++;\n\t\t} else if (this.currentCoordinate === 2 && this.currentId) {\n\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\tif (snappedCoordinate) {\n\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t}\n\n\t\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\t\tthis.currentId,\n\t\t\t).coordinates[0];\n\n\t\t\tconst previousCoordinate = currentPolygonCoordinates[1];\n\t\t\tconst isIdentical = coordinatesIdentical(\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\tpreviousCoordinate,\n\t\t\t);\n\n\t\t\tif (isIdentical) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t\t[\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t],\n\t\t\t\tUpdateTypes.Commit,\n\t\t\t);\n\n\t\t\tif (!updated) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.currentCoordinate === 2) {\n\t\t\t\tthis.closingPoints.create(currentPolygonCoordinates, \"polygon\");\n\t\t\t}\n\n\t\t\tthis.currentCoordinate++;\n\t\t} else if (this.currentId) {\n\t\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\t\tthis.currentId,\n\t\t\t).coordinates[0];\n\n\t\t\tconst { isClosing, isPreviousClosing } =\n\t\t\t\tthis.closingPoints.isClosingPoint(event);\n\n\t\t\tif (isPreviousClosing || isClosing) {\n\t\t\t\tthis.close();\n\t\t\t} else {\n\t\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\t\tif (snappedCoordinate) {\n\t\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t\t}\n\n\t\t\t\tconst previousCoordinate =\n\t\t\t\t\tcurrentPolygonCoordinates[this.currentCoordinate - 1];\n\t\t\t\tconst isIdentical = coordinatesIdentical(\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tpreviousCoordinate,\n\t\t\t\t);\n\n\t\t\t\tif (isIdentical) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst updatedPolygon = createPolygon([\n\t\t\t\t\t[\n\t\t\t\t\t\t...currentPolygonCoordinates.slice(0, -1),\n\t\t\t\t\t\t[event.lng, event.lat], // New point that onMouseMove can manipulate\n\t\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t\t],\n\t\t\t\t]);\n\n\t\t\t\t// If not close to the final point, keep adding points\n\t\t\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t\t\tupdatedPolygon.geometry.coordinates[0],\n\t\t\t\t\tUpdateTypes.Commit,\n\t\t\t\t);\n\t\t\t\tif (!updated) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.currentCoordinate++;\n\n\t\t\t\t// Update closing points straight away\n\t\t\t\tif (this.closingPoints.ids.length) {\n\t\t\t\t\tthis.closingPoints.update(updatedPolygon.geometry.coordinates[0]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\t// We want pointer devices (mobile/tablet) to have\n\t\t// similar behaviour to mouse based devices so we\n\t\t// trigger a mousemove event before every click\n\t\t// if one has not been trigged to emulate this\n\t\tif (this.currentCoordinate > 0 && !this.mouseMove) {\n\t\t\tthis.onMouseMove(event);\n\t\t}\n\t\tthis.mouseMove = false;\n\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (\n\t\t\tevent.button === \"left\" &&\n\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)\n\t\t) {\n\t\t\tthis.onLeftClick(event);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragStart, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.state === \"started\") {\n\t\t\tconst lineSnapped = this.lineSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (lineSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"line\";\n\t\t\t\tthis.editedFeatureCoordinateIndex = lineSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = lineSnapped.featureId;\n\t\t\t\tsnappedCoordinate = lineSnapped.coordinate;\n\t\t\t}\n\n\t\t\tconst coordinateSnapped = this.coordinateSnapping.getSnappable(\n\t\t\t\tevent,\n\t\t\t\t(feature) => this.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (coordinateSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"coordinate\";\n\t\t\t\tthis.editedFeatureCoordinateIndex =\n\t\t\t\t\tcoordinateSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = coordinateSnapped.featureId;\n\t\t\t\tsnappedCoordinate = coordinateSnapped.coordinate;\n\t\t\t}\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.editedFeatureId || !snappedCoordinate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create a point to drag when editing\n\t\tif (!this.editedPointId) {\n\t\t\tconst [editedPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t},\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.EDITED]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\tthis.editedPointId = editedPointId;\n\t\t}\n\n\t\t// Drag Feature\n\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\tsetMapDraggability(false);\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDrag, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tthis.editedFeatureId === undefined ||\n\t\t\tthis.editedFeatureCoordinateIndex === undefined\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst featureCopy: Polygon = this.store.getGeometryCopy(\n\t\t\tthis.editedFeatureId,\n\t\t);\n\t\tconst featureCoordinates = featureCopy.coordinates[0];\n\n\t\t// Either it's a coordinate drag or a line drag where the line coordinate has already been inserted\n\t\tif (\n\t\t\tthis.editedSnapType === \"coordinate\" ||\n\t\t\t(this.editedSnapType === \"line\" && this.editedInsertIndex !== undefined)\n\t\t) {\n\t\t\t// Account for the first and last point being the same\n\t\t\tconst isStartingOrEndingCoordinate =\n\t\t\t\tthis.editedFeatureCoordinateIndex === 0 ||\n\t\t\t\tthis.editedFeatureCoordinateIndex ===\n\t\t\t\t\tfeatureCopy.coordinates[0].length - 1;\n\n\t\t\tif (isStartingOrEndingCoordinate) {\n\t\t\t\tfeatureCoordinates[0] = [event.lng, event.lat];\n\t\t\t\tfeatureCoordinates[featureCoordinates.length - 1] = [\n\t\t\t\t\tevent.lng,\n\t\t\t\t\tevent.lat,\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tfeatureCoordinates[this.editedFeatureCoordinateIndex] = [\n\t\t\t\t\tevent.lng,\n\t\t\t\t\tevent.lat,\n\t\t\t\t];\n\t\t\t}\n\t\t} else if (\n\t\t\tthis.editedSnapType === \"line\" &&\n\t\t\tthis.editedInsertIndex === undefined\n\t\t) {\n\t\t\t// Splice inserts _before_ the index, so we need to add 1\n\t\t\tthis.editedInsertIndex = this.editedFeatureCoordinateIndex + 1;\n\n\t\t\t// Insert the new dragged snapped line coordinate\n\t\t\tfeatureCopy.coordinates[0].splice(this.editedInsertIndex, 0, [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t]);\n\n\t\t\t// We have inserted a point, need to change the edit index\n\t\t\t// so it can be moved correctly when it gets dragged again\n\t\t\tthis.editedFeatureCoordinateIndex++;\n\t\t}\n\n\t\tconst newPolygonGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: featureCopy.coordinates,\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: newPolygonGeometry,\n\t\t\t\t\tproperties: this.store.getPropertiesCopy(this.editedFeatureId),\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping && this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tgeometry: newPolygonGeometry,\n\t\t\t},\n\t\t]);\n\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(this.editedFeatureId);\n\t\t}\n\n\t\tif (this.editedPointId) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.editedPointId,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: [event.lng, event.lat],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: true,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragEnd, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editedFeatureId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setCursor(this.cursors.dragEnd);\n\n\t\tif (this.editedPointId) {\n\t\t\tthis.store.delete([this.editedPointId]);\n\t\t\tthis.editedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.editedFeatureId,\n\t\t\t\tproperty: COMMON_PROPERTIES.EDITED,\n\t\t\t\tvalue: false,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(this.editedFeatureId, { mode: this.mode, action: \"edit\" });\n\n\t\t// Reset edit state\n\t\tthis.editedFeatureId = undefined;\n\t\tthis.editedFeatureCoordinateIndex = undefined;\n\t\tthis.editedInsertIndex = undefined;\n\t\tthis.editedSnapType = undefined;\n\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tconst cleanUpId = this.currentId;\n\t\tconst snappedPointId = this.snappedPointId;\n\t\tconst editedPointId = this.editedPointId;\n\n\t\tthis.currentId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.editedPointId = undefined;\n\t\tthis.editedFeatureId = undefined;\n\t\tthis.editedFeatureCoordinateIndex = undefined;\n\t\tthis.editedInsertIndex = undefined;\n\t\tthis.editedSnapType = undefined;\n\t\tthis.currentCoordinate = 0;\n\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\ttry {\n\t\t\tif (cleanUpId) {\n\t\t\t\tthis.coordinatePoints.deletePointsByFeatureIds([cleanUpId]);\n\t\t\t}\n\n\t\t\tif (cleanUpId !== undefined) {\n\t\t\t\tthis.store.delete([cleanUpId]);\n\t\t\t}\n\t\t\tif (editedPointId !== undefined) {\n\t\t\t\tthis.store.delete([editedPointId]);\n\t\t\t}\n\t\t\tif (snappedPointId !== undefined) {\n\t\t\t\tthis.store.delete([snappedPointId]);\n\t\t\t}\n\t\t\tif (this.closingPoints.ids.length) {\n\t\t\t\tthis.closingPoints.delete();\n\t\t\t}\n\t\t} catch (error) {}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (feature.properties.mode === this.mode) {\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.fillColor,\n\t\t\t\t\tstyles.polygonFillColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.outlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t\treturn styles;\n\t\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\t\tconst editedPoint = feature.properties[COMMON_PROPERTIES.EDITED];\n\t\t\t\tconst closingPoint =\n\t\t\t\t\tfeature.properties[COMMON_PROPERTIES.CLOSING_POINT];\n\t\t\t\tconst snappingPoint =\n\t\t\t\t\tfeature.properties[COMMON_PROPERTIES.SNAPPING_POINT];\n\t\t\t\tconst coordinatePoint =\n\t\t\t\t\tfeature.properties[COMMON_PROPERTIES.COORDINATE_POINT];\n\n\t\t\t\tconst pointType = editedPoint\n\t\t\t\t\t? \"editedPoint\"\n\t\t\t\t\t: closingPoint\n\t\t\t\t\t\t? \"closingPoint\"\n\t\t\t\t\t\t: snappingPoint\n\t\t\t\t\t\t\t? \"snappingPoint\"\n\t\t\t\t\t\t\t: coordinatePoint\n\t\t\t\t\t\t\t\t? \"coordinatePoint\"\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\tif (!pointType) {\n\t\t\t\t\treturn styles;\n\t\t\t\t}\n\n\t\t\t\tconst styleMap = {\n\t\t\t\t\teditedPoint: {\n\t\t\t\t\t\twidth: this.styles.editedPointOutlineWidth,\n\t\t\t\t\t\tcolor: this.styles.editedPointColor,\n\t\t\t\t\t\toutlineColor: this.styles.editedPointOutlineColor,\n\t\t\t\t\t\toutlineWidth: this.styles.editedPointOutlineWidth,\n\t\t\t\t\t},\n\t\t\t\t\tclosingPoint: {\n\t\t\t\t\t\twidth: this.styles.closingPointWidth,\n\t\t\t\t\t\tcolor: this.styles.closingPointColor,\n\t\t\t\t\t\toutlineColor: this.styles.closingPointOutlineColor,\n\t\t\t\t\t\toutlineWidth: this.styles.closingPointOutlineWidth,\n\t\t\t\t\t},\n\t\t\t\t\tsnappingPoint: {\n\t\t\t\t\t\twidth: this.styles.snappingPointWidth,\n\t\t\t\t\t\tcolor: this.styles.snappingPointColor,\n\t\t\t\t\t\toutlineColor: this.styles.snappingPointOutlineColor,\n\t\t\t\t\t\toutlineWidth: this.styles.snappingPointOutlineWidth,\n\t\t\t\t\t},\n\t\t\t\t\tcoordinatePoint: {\n\t\t\t\t\t\twidth: this.styles.coordinatePointWidth,\n\t\t\t\t\t\tcolor: this.styles.coordinatePointColor,\n\t\t\t\t\t\toutlineColor: this.styles.coordinatePointOutlineColor,\n\t\t\t\t\t\toutlineWidth: this.styles.coordinatePointOutlineWidth,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\t\tstyleMap[pointType].width,\n\t\t\t\t\tstyles.pointWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\t\tstyleMap[pointType].color,\n\t\t\t\t\tstyles.pointColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tstyleMap[pointType].outlineColor,\n\t\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tstyleMap[pointType].outlineWidth,\n\t\t\t\t\t2,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tif (editedPoint) {\n\t\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_FOUR;\n\t\t\t\t} else if (coordinatePoint) {\n\t\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_TWO;\n\t\t\t\t} else {\n\t\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_THREE;\n\t\t\t\t}\n\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tafterFeatureAdded(feature: GeoJSONStoreFeatures) {\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(feature.id as FeatureId);\n\t\t}\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePolygonFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\n\nexport function createPolygon(\n\tcoordinates: Position[][] = [\n\t\t[\n\t\t\t[0, 0],\n\t\t\t[0, 1],\n\t\t\t[1, 1],\n\t\t\t[1, 0],\n\t\t\t[0, 0],\n\t\t],\n\t],\n): Feature<Polygon> {\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates,\n\t\t},\n\t\tproperties: {},\n\t};\n}\n\nexport function createLineString(coordinates: Position[]): Feature<LineString> {\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates,\n\t\t},\n\t\tproperties: {},\n\t};\n}\n","import { Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tZ_INDEX,\n} from \"../../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawRectangleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype RectanglePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawRectangleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawRectangleModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawRectangleMode extends TerraDrawBaseDrawMode<RectanglePolygonStyling> {\n\tmode = \"rectangle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentRectangleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawRectangleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\n\tconstructor(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate updateRectangle(event: TerraDrawMouseEvent, updateType: UpdateTypes) {\n\t\tif (this.clickCount === 1 && this.center && this.currentRectangleId) {\n\t\t\tconst geometry = this.store.getGeometryCopy(this.currentRectangleId);\n\n\t\t\tconst firstCoord = (geometry.coordinates as Position[][])[0][0];\n\n\t\t\tconst newGeometry = {\n\t\t\t\ttype: \"Polygon\",\n\t\t\t\tcoordinates: [\n\t\t\t\t\t[\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t\t[event.lng, firstCoord[1]],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t[firstCoord[0], event.lat],\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t} as Polygon;\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst validationResult = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!validationResult.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tconst finishedId = this.currentRectangleId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (finishedId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(finishedId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: finishedId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.center = undefined;\n\t\tthis.currentRectangleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedId !== undefined) {\n\t\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tif (this.clickCount === 0) {\n\t\t\t\tthis.center = [event.lng, event.lat];\n\t\t\t\tconst [createdId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentRectangleId = createdId;\n\t\t\t\tthis.clickCount++;\n\t\t\t\tthis.setDrawing();\n\t\t\t} else {\n\t\t\t\tthis.updateRectangle(event, UpdateTypes.Finish);\n\t\t\t\t// Finish drawing\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.updateRectangle(event, UpdateTypes.Provisional);\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tconst cleanUpId = this.currentRectangleId;\n\n\t\tthis.center = undefined;\n\t\tthis.currentRectangleId = undefined;\n\t\tthis.clickCount = 0;\n\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (cleanUpId !== undefined) {\n\t\t\tthis.store.delete([cleanUpId]);\n\t\t}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.type === \"Feature\" &&\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\tfeature.properties.mode === this.mode\n\t\t) {\n\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.fillColor,\n\t\t\t\tstyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\tthis.styles.outlineColor,\n\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t);\n\n\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tHexColorStyling,\n\tNumericStyling,\n\tTerraDrawAdapterStyling,\n} from \"../../common\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { GeoJSONStoreFeatures } from \"../../terra-draw\";\nimport { ValidatePointFeature } from \"../../validations/point.validation\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ValidateLineStringFeature } from \"../../validations/linestring.validation\";\nimport { StoreValidation } from \"../../store/store\";\n\ntype RenderModeStyling = {\n\tpointColor: HexColorStyling;\n\tpointWidth: NumericStyling;\n\tpointOutlineColor: HexColorStyling;\n\tpointOutlineWidth: NumericStyling;\n\tpolygonFillColor: HexColorStyling;\n\tpolygonFillOpacity: NumericStyling;\n\tpolygonOutlineColor: HexColorStyling;\n\tpolygonOutlineWidth: NumericStyling;\n\tlineStringWidth: NumericStyling;\n\tlineStringColor: HexColorStyling;\n\tzIndex: NumericStyling;\n};\n\ninterface TerraDrawRenderModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tmodeName?: string;\n\t// styles need to be there else we could fall back to BaseModeOptions\n\tstyles: Partial<T>;\n}\n\nexport class TerraDrawRenderMode extends TerraDrawBaseDrawMode<RenderModeStyling> {\n\tpublic type = ModeTypes.Render; // The type of the mode\n\tpublic mode = \"render\"; // This gets changed dynamically\n\n\tconstructor(options: TerraDrawRenderModeOptions<RenderModeStyling>) {\n\t\tif (!options.modeName) {\n\t\t\tthrow new Error(\"Mode name is required for TerraDrawRenderMode\");\n\t\t}\n\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawRenderModeOptions<RenderModeStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\t\tif (options?.modeName) {\n\t\t\tthis.mode = options.modeName;\n\t\t}\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(behaviorConfig: BehaviorConfig) {\n\t\t// TODO: this is probably abusing\n\t\t// registerBehaviors but it works quite well conceptually\n\n\t\t// We can set the mode name dynamically\n\t\tthis.mode = behaviorConfig.mode;\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.setStopped();\n\t}\n\n\t/** @internal */\n\tonKeyUp() {}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonClick() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tonMouseMove() {}\n\n\t/** @internal */\n\tcleanUp() {}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst defaultStyles = getDefaultStyling();\n\n\t\treturn {\n\t\t\tpointColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointColor,\n\t\t\t\tdefaultStyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointWidth,\n\t\t\t\tdefaultStyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointOutlineColor,\n\t\t\t\tdefaultStyles.pointOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointOutlineWidth,\n\t\t\t\tdefaultStyles.pointOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonFillColor,\n\t\t\t\tdefaultStyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillOpacity: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonFillOpacity,\n\t\t\t\tdefaultStyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonOutlineColor,\n\t\t\t\tdefaultStyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonOutlineWidth,\n\t\t\t\tdefaultStyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.lineStringWidth,\n\t\t\t\tdefaultStyles.lineStringWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.lineStringColor,\n\t\t\t\tdefaultStyles.lineStringColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tzIndex: this.getNumericStylingValue(\n\t\t\t\tthis.styles.zIndex,\n\t\t\t\tdefaultStyles.zIndex,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t};\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\tconst validationResult = super.validateFeature(feature);\n\t\tif (validationResult.valid) {\n\t\t\tconst validatedFeature = feature as GeoJSONStoreFeatures;\n\n\t\t\tconst featureIsValid =\n\t\t\t\tValidatePointFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidatePolygonFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidateLineStringFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid;\n\n\t\t\tif (featureIsValid) {\n\t\t\t\treturn { valid: true };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tvalid: featureIsValid,\n\t\t\t\treason: \"Feature is not a valid Point, Polygon or LineString feature\",\n\t\t\t};\n\t\t}\n\n\t\treturn validationResult;\n\t}\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, radiansToDegrees } from \"../helpers\";\n\n// Based on Turf.js Rhumb Bearing module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-bearing/index.ts\n\nexport function rhumbBearing(start: Position, end: Position): number {\n\tconst from = start;\n\tconst to = end;\n\n\t// φ => phi\n\t// Δλ => deltaLambda\n\t// Δψ => deltaPsi\n\t// θ => theta\n\tconst phi1 = degreesToRadians(from[1]);\n\tconst phi2 = degreesToRadians(to[1]);\n\tlet deltaLambda = degreesToRadians(to[0] - from[0]);\n\n\t// if deltaLambdaon over 180° take shorter rhumb line across the anti-meridian:\n\tif (deltaLambda > Math.PI) {\n\t\tdeltaLambda -= 2 * Math.PI;\n\t}\n\tif (deltaLambda < -Math.PI) {\n\t\tdeltaLambda += 2 * Math.PI;\n\t}\n\n\tconst deltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\n\tconst theta = Math.atan2(deltaLambda, deltaPsi);\n\n\tconst bear360 = (radiansToDegrees(theta) + 360) % 360;\n\n\tconst bear180 = bear360 > 180 ? -(360 - bear360) : bear360;\n\n\treturn bear180;\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, earthRadius } from \"../helpers\";\n\n// Based on @turf/rhumb-destination module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-destination/index.ts\n\nexport function rhumbDestination(\n\torigin: Position,\n\tdistanceMeters: number,\n\tbearing: number,\n): Position {\n\tconst wasNegativeDistance = distanceMeters < 0;\n\tlet distanceInMeters = distanceMeters;\n\n\tif (wasNegativeDistance) {\n\t\tdistanceInMeters = -Math.abs(distanceInMeters);\n\t}\n\n\tconst delta = distanceInMeters / earthRadius; // angular distance in radians\n\tconst lambda1 = (origin[0] * Math.PI) / 180; // to radians, but without normalize to 𝜋\n\tconst phi1 = degreesToRadians(origin[1]);\n\tconst theta = degreesToRadians(bearing);\n\n\tconst DeltaPhi = delta * Math.cos(theta);\n\tlet phi2 = phi1 + DeltaPhi;\n\n\t// check for going past the pole, normalise latitude if so\n\tif (Math.abs(phi2) > Math.PI / 2) {\n\t\tphi2 = phi2 > 0 ? Math.PI - phi2 : -Math.PI - phi2;\n\t}\n\n\tconst DeltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\t// E-W course becomes ill-conditioned with 0/0\n\tconst q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);\n\n\tconst DeltaLambda = (delta * Math.sin(theta)) / q;\n\tconst lambda2 = lambda1 + DeltaLambda;\n\n\t// normalise to −180..+180°\n\tconst destination = [\n\t\t(((lambda2 * 180) / Math.PI + 540) % 360) - 180,\n\t\t(phi2 * 180) / Math.PI,\n\t];\n\n\t// compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)\n\t// solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678\n\tdestination[0] +=\n\t\tdestination[0] - origin[0] > 180\n\t\t\t? -360\n\t\t\t: origin[0] - destination[0] > 180\n\t\t\t\t? 360\n\t\t\t\t: 0;\n\treturn destination;\n}\n","import { Position } from \"geojson\";\nimport { limitPrecision } from \"./limit-decimal-precision\";\nimport { Project, Unproject } from \"../common\";\nimport { haversineDistanceKilometers } from \"./measure/haversine-distance\";\nimport { rhumbBearing } from \"./measure/rhumb-bearing\";\nimport { rhumbDestination } from \"./measure/rhumb-destination\";\n\n// midpointCoordinate is adapted from the @turf/midpoint which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-midpoint\n\nexport function midpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n) {\n\tconst projectedCoordinateOne = project(coordinates1[0], coordinates1[1]);\n\tconst projectedCoordinateTwo = project(coordinates2[0], coordinates2[1]);\n\n\tconst { lng, lat } = unproject(\n\t\t(projectedCoordinateOne.x + projectedCoordinateTwo.x) / 2,\n\t\t(projectedCoordinateOne.y + projectedCoordinateTwo.y) / 2,\n\t);\n\n\treturn [limitPrecision(lng, precision), limitPrecision(lat, precision)];\n}\n\n/* Get the geodesic midpoint coordinate between two coordinates */\nexport function geodesicMidpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n) {\n\tconst dist = haversineDistanceKilometers(coordinates1, coordinates2) * 1000;\n\tconst heading = rhumbBearing(coordinates1, coordinates2);\n\tconst midpoint = rhumbDestination(coordinates1, dist / 2, heading);\n\treturn [\n\t\tlimitPrecision(midpoint[0], precision),\n\t\tlimitPrecision(midpoint[1], precision),\n\t];\n}\n","import { Point, Position } from \"geojson\";\nimport { Project, Projection, Unproject } from \"../common\";\nimport { JSONObject } from \"../store/store\";\nimport {\n\tmidpointCoordinate,\n\tgeodesicMidpointCoordinate,\n} from \"./midpoint-coordinate\";\n\nexport function getMidPointCoordinates({\n\tfeatureCoords,\n\tprecision,\n\tunproject,\n\tproject,\n\tprojection,\n}: {\n\tfeatureCoords: Position[];\n\tprecision: number;\n\tproject: Project;\n\tunproject: Unproject;\n\tprojection: Projection;\n}) {\n\tconst midPointCoords: Position[] = [];\n\tfor (let i = 0; i < featureCoords.length - 1; i++) {\n\t\tlet mid;\n\t\tif (projection === \"web-mercator\") {\n\t\t\tmid = midpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t\tproject,\n\t\t\t\tunproject,\n\t\t\t);\n\t\t} else if (projection === \"globe\") {\n\t\t\tmid = geodesicMidpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid projection\");\n\t\t}\n\n\t\tmidPointCoords.push(mid);\n\t}\n\treturn midPointCoords;\n}\n\nexport function getMidPoints(\n\tselectedCoords: Position[],\n\tproperties: (index: number) => JSONObject,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n\tprojection: Projection,\n) {\n\treturn getMidPointCoordinates({\n\t\tfeatureCoords: selectedCoords,\n\t\tprecision,\n\t\tproject,\n\t\tunproject,\n\t\tprojection,\n\t}).map((coord, i) => ({\n\t\tgeometry: { type: \"Point\", coordinates: coord } as Point,\n\t\tproperties: properties(i),\n\t}));\n}\n","import { LineString, Point, Polygon, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport {\n\tgetMidPointCoordinates,\n\tgetMidPoints,\n} from \"../../../geometry/get-midpoints\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport {\n\tCOMMON_PROPERTIES,\n\tProjection,\n\tSELECT_PROPERTIES,\n} from \"../../../common\";\nimport { FeatureId } from \"../../../store/store\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport class MidPointBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly selectionPointBehavior: SelectionPointBehavior,\n\t\tprivate readonly coordinatePointBehavior: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate _midPoints: string[] = [];\n\n\tget ids() {\n\t\treturn this._midPoints.concat();\n\t}\n\n\tset ids(_: string[]) {}\n\n\tpublic insert(\n\t\tfeatureId: FeatureId,\n\t\tmidPointId: FeatureId,\n\t\tcoordinatePrecision: number,\n\t) {\n\t\tconst midPoint = this.store.getGeometryCopy(midPointId);\n\t\tconst { midPointFeatureId, midPointSegment } =\n\t\t\tthis.store.getPropertiesCopy(midPointId);\n\t\tconst geometry = this.store.getGeometryCopy<Polygon | LineString>(\n\t\t\tmidPointFeatureId as FeatureId,\n\t\t);\n\n\t\t// Update the coordinates to include inserted midpoint\n\t\tconst updatedCoordinates =\n\t\t\tgeometry.type === \"Polygon\"\n\t\t\t\t? geometry.coordinates[0]\n\t\t\t\t: geometry.coordinates;\n\n\t\tupdatedCoordinates.splice(\n\t\t\t(midPointSegment as number) + 1,\n\t\t\t0,\n\t\t\tmidPoint.coordinates as Position,\n\t\t);\n\n\t\t// Update geometry coordinates depending\n\t\t// on if a polygon or linestring\n\t\tgeometry.coordinates =\n\t\t\tgeometry.type === \"Polygon\" ? [updatedCoordinates] : updatedCoordinates;\n\n\t\t// Update the selected features geometry to insert\n\t\t// the new midpoint\n\t\tthis.store.updateGeometry([{ id: midPointFeatureId as string, geometry }]);\n\n\t\t// We need to update the coordinate points to reflect the new midpoint\n\t\tconst featureProperties = this.store.getPropertiesCopy(featureId as string);\n\n\t\tif (featureProperties[COMMON_PROPERTIES.COORDINATE_POINT_IDS]) {\n\t\t\tthis.coordinatePointBehavior.createOrUpdate(featureId);\n\t\t}\n\n\t\t// TODO: is there a way of just updating the selection points rather\n\t\t// than fully deleting / recreating?\n\t\t// Recreate the selection points\n\n\t\tthis.store.delete([...this._midPoints, ...this.selectionPointBehavior.ids]);\n\n\t\t// We don't need to check if flags are correct\n\t\t// because selection points are prerequisite for midpoints\n\t\tthis.create(\n\t\t\tupdatedCoordinates,\n\t\t\tmidPointFeatureId as string,\n\t\t\tcoordinatePrecision,\n\t\t);\n\t\tthis.selectionPointBehavior.create(\n\t\t\tupdatedCoordinates,\n\t\t\tgeometry.type,\n\t\t\tmidPointFeatureId as string,\n\t\t);\n\t}\n\n\tpublic create(\n\t\tselectedCoords: Position[],\n\t\tfeatureId: FeatureId,\n\t\tcoordinatePrecision: number,\n\t) {\n\t\tif (!this.store.has(featureId)) {\n\t\t\tthrow new Error(\"Store does not have feature with this id\");\n\t\t}\n\n\t\tthis._midPoints = this.store.create(\n\t\t\tgetMidPoints(\n\t\t\t\tselectedCoords,\n\t\t\t\t(i) => ({\n\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t[SELECT_PROPERTIES.MID_POINT]: true,\n\t\t\t\t\tmidPointSegment: i,\n\t\t\t\t\tmidPointFeatureId: featureId,\n\t\t\t\t}),\n\t\t\t\tcoordinatePrecision,\n\t\t\t\tthis.config.project,\n\t\t\t\tthis.config.unproject,\n\t\t\t\tthis.projection,\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this._midPoints.length) {\n\t\t\tthis.store.delete(this._midPoints);\n\t\t\tthis._midPoints = [];\n\t\t}\n\t}\n\n\tpublic getUpdated(updatedCoordinates: Position[]) {\n\t\tif (this._midPoints.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn getMidPointCoordinates({\n\t\t\tfeatureCoords: updatedCoordinates,\n\t\t\tprecision: this.coordinatePrecision,\n\t\t\tproject: this.config.project,\n\t\t\tunproject: this.config.unproject,\n\t\t\tprojection: this.config.projection as Projection,\n\t\t}).map((updatedMidPointCoord, i) => ({\n\t\t\tid: this._midPoints[i] as string,\n\t\t\tgeometry: {\n\t\t\t\ttype: \"Point\",\n\t\t\t\tcoordinates: updatedMidPointCoord,\n\t\t\t} as Point,\n\t\t}));\n\t}\n}\n","import { LineString, Point, Polygon, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { getCoordinatesAsPoints } from \"../../../geometry/get-coordinates-as-points\";\nimport { FeatureId } from \"../../../store/store\";\nimport { SELECT_PROPERTIES } from \"../../../common\";\n\nexport type SelectionPointProperties = {\n\tmode: string;\n\tindex: number;\n\t[SELECT_PROPERTIES.SELECTION_POINT_FEATURE_ID]: string;\n\t[SELECT_PROPERTIES.SELECTION_POINT]: true;\n};\n\nexport class SelectionPointBehavior extends TerraDrawModeBehavior {\n\tconstructor(config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\n\tprivate _selectionPoints: FeatureId[] = [];\n\n\tget ids() {\n\t\treturn this._selectionPoints.concat();\n\t}\n\n\tset ids(_: FeatureId[]) {}\n\n\tpublic create(\n\t\tselectedCoords: Position[],\n\t\ttype: Polygon[\"type\"] | LineString[\"type\"],\n\t\tfeatureId: FeatureId,\n\t) {\n\t\tthis._selectionPoints = this.store.create(\n\t\t\tgetCoordinatesAsPoints(selectedCoords, type, (i) => ({\n\t\t\t\tmode: this.mode,\n\t\t\t\tindex: i,\n\t\t\t\t[SELECT_PROPERTIES.SELECTION_POINT]: true,\n\t\t\t\t[SELECT_PROPERTIES.SELECTION_POINT_FEATURE_ID]: featureId,\n\t\t\t})),\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this.ids.length) {\n\t\t\tthis.store.delete(this.ids);\n\t\t\tthis._selectionPoints = [];\n\t\t}\n\t}\n\n\tpublic getUpdated(updatedCoordinates: Position[]) {\n\t\tif (this._selectionPoints.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._selectionPoints.map((id, i) => {\n\t\t\treturn {\n\t\t\t\tid,\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: updatedCoordinates[i],\n\t\t\t\t} as Point,\n\t\t\t};\n\t\t});\n\t}\n\n\tpublic getOneUpdated(index: number, updatedCoordinate: Position) {\n\t\tif (this._selectionPoints[index] === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn {\n\t\t\tid: this._selectionPoints[index] as string,\n\t\t\tgeometry: {\n\t\t\t\ttype: \"Point\",\n\t\t\t\tcoordinates: updatedCoordinate,\n\t\t\t} as Point,\n\t\t};\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { JSONObject } from \"../store/store\";\n\nexport function getCoordinatesAsPoints<Properties extends JSONObject>(\n\tselectedCoords: Position[],\n\tgeometryType: \"Polygon\" | \"LineString\",\n\tproperties: (index: number) => Properties,\n) {\n\tconst selectionPoints = [];\n\n\t// We can skip the last point for polygons\n\t// as it's a duplicate of the first\n\tconst length =\n\t\tgeometryType === \"Polygon\"\n\t\t\t? selectedCoords.length - 1\n\t\t\t: selectedCoords.length;\n\n\tfor (let i = 0; i < length; i++) {\n\t\tselectionPoints.push({\n\t\t\tgeometry: {\n\t\t\t\ttype: \"Point\",\n\t\t\t\tcoordinates: selectedCoords[i],\n\t\t\t} as Point,\n\t\t\tproperties: properties(i),\n\t\t});\n\t}\n\n\treturn selectionPoints;\n}\n","import { Position } from \"geojson\";\n\n// Based on which-polygon (Mapbox)\n// https://github.com/mapbox/which-polygon/blob/2eb5b8a427d018ebd964c05acd3b9166c4558b2c/index.js#L81\n// ISC License - Copyright (c) 2017, Mapbox\n\nexport function pointInPolygon(point: Position, rings: Position[][]) {\n\tlet inside = false;\n\tfor (let i = 0, len = rings.length; i < len; i++) {\n\t\tconst ring = rings[i];\n\t\tfor (let j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {\n\t\t\tif (rayIntersect(point, ring[j], ring[k])) {\n\t\t\t\tinside = !inside;\n\t\t\t}\n\t\t}\n\t}\n\treturn inside;\n}\n\nfunction rayIntersect(p: Position, p1: Position, p2: Position) {\n\treturn (\n\t\tp1[1] > p[1] !== p2[1] > p[1] &&\n\t\tp[0] < ((p2[0] - p1[0]) * (p[1] - p1[1])) / (p2[1] - p1[1]) + p1[0]\n\t);\n}\n","import { CartesianPoint } from \"../../common\";\n\nexport const pixelDistanceToLine = (\n\tpoint: CartesianPoint,\n\tlinePointOne: CartesianPoint,\n\tlinePointTwo: CartesianPoint,\n) => {\n\tconst square = (x: number) => {\n\t\treturn x * x;\n\t};\n\tconst dist2 = (v: CartesianPoint, w: CartesianPoint) => {\n\t\treturn square(v.x - w.x) + square(v.y - w.y);\n\t};\n\tconst distToSegmentSquared = (\n\t\tp: CartesianPoint,\n\t\tv: CartesianPoint,\n\t\tw: CartesianPoint,\n\t) => {\n\t\tconst l2 = dist2(v, w);\n\n\t\tif (l2 === 0) {\n\t\t\treturn dist2(p, v);\n\t\t}\n\n\t\tlet t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;\n\t\tt = Math.max(0, Math.min(1, t));\n\n\t\treturn dist2(p, { x: v.x + t * (w.x - v.x), y: v.y + t * (w.y - v.y) });\n\t};\n\n\treturn Math.sqrt(distToSegmentSquared(point, linePointOne, linePointTwo));\n};\n","import { SELECT_PROPERTIES, TerraDrawMouseEvent } from \"../../../common\";\nimport { BBoxPolygon, GeoJSONStoreFeatures } from \"../../../store/store\";\n\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { ClickBoundingBoxBehavior } from \"../../click-bounding-box.behavior\";\n\nimport { pointInPolygon } from \"../../../geometry/boolean/point-in-polygon\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\nimport { pixelDistanceToLine } from \"../../../geometry/measure/pixel-distance-to-line\";\n\nexport class FeatureAtPointerEventBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly createClickBoundingBox: ClickBoundingBoxBehavior,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tpublic find(event: TerraDrawMouseEvent, hasSelection: boolean) {\n\t\tlet clickedPoint: GeoJSONStoreFeatures | undefined = undefined;\n\t\tlet clickedPointDistance = Infinity;\n\t\tlet clickedLineString: GeoJSONStoreFeatures | undefined = undefined;\n\t\tlet clickedLineStringDistance = Infinity;\n\t\tlet clickedMidPoint: GeoJSONStoreFeatures | undefined = undefined;\n\t\tlet clickedMidPointDistance = Infinity;\n\t\tlet clickedPolygon: GeoJSONStoreFeatures | undefined = undefined;\n\n\t\tconst bbox = this.createClickBoundingBox.create(event);\n\t\tconst features = this.store.search(bbox as BBoxPolygon);\n\n\t\tfor (let i = 0; i < features.length; i++) {\n\t\t\tconst feature = features[i];\n\t\t\tconst geometry = feature.geometry;\n\n\t\t\tif (geometry.type === \"Point\") {\n\t\t\t\t// Ignore selection points always, and ignore mid points\n\t\t\t\t// when nothing is selected\n\t\t\t\tconst isSelectionPoint = feature.properties.selectionPoint;\n\t\t\t\tconst isCoordinatePoint = feature.properties.coordinatePoint;\n\t\t\t\tconst isNonSelectedMidPoint =\n\t\t\t\t\t!hasSelection && feature.properties[SELECT_PROPERTIES.MID_POINT];\n\n\t\t\t\tif (isSelectionPoint || isCoordinatePoint || isNonSelectedMidPoint) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst distance = this.pixelDistance.measure(\n\t\t\t\t\tevent,\n\t\t\t\t\tgeometry.coordinates,\n\t\t\t\t);\n\n\t\t\t\t// We want to catch both clicked\n\t\t\t\t// features but also any midpoints\n\t\t\t\t// in the clicked area\n\t\t\t\tif (\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.MID_POINT] &&\n\t\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\t\tdistance < clickedMidPointDistance\n\t\t\t\t) {\n\t\t\t\t\tclickedMidPointDistance = distance;\n\t\t\t\t\tclickedMidPoint = feature;\n\t\t\t\t} else if (\n\t\t\t\t\t!feature.properties[SELECT_PROPERTIES.MID_POINT] &&\n\t\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\t\tdistance < clickedPointDistance\n\t\t\t\t) {\n\t\t\t\t\tclickedPointDistance = distance;\n\t\t\t\t\tclickedPoint = feature;\n\t\t\t\t}\n\t\t\t} else if (geometry.type === \"LineString\") {\n\t\t\t\tif (clickedPoint) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0; i < geometry.coordinates.length - 1; i++) {\n\t\t\t\t\tconst coord = geometry.coordinates[i];\n\t\t\t\t\tconst nextCoord = geometry.coordinates[i + 1];\n\t\t\t\t\tconst distanceToLine = pixelDistanceToLine(\n\t\t\t\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t\t\t\t\tthis.project(coord[0], coord[1]),\n\t\t\t\t\t\tthis.project(nextCoord[0], nextCoord[1]),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tdistanceToLine < this.pointerDistance &&\n\t\t\t\t\t\tdistanceToLine < clickedLineStringDistance\n\t\t\t\t\t) {\n\t\t\t\t\t\tclickedLineStringDistance = distanceToLine;\n\t\t\t\t\t\tclickedLineString = feature;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (geometry.type === \"Polygon\") {\n\t\t\t\tif (clickedPoint || clickedLineString) {\n\t\t\t\t\t// We already have a clicked feature\n\t\t\t\t\t// so we can ignore the polygon\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst clickInsidePolygon = pointInPolygon(\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tgeometry.coordinates,\n\t\t\t\t);\n\n\t\t\t\tif (clickInsidePolygon) {\n\t\t\t\t\tclickedPolygon = feature;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tclickedFeature: clickedPoint || clickedLineString || clickedPolygon,\n\t\t\tclickedMidPoint,\n\t\t};\n\t}\n}\n","import { TerraDrawMouseEvent, UpdateTypes, Validation } from \"../../../common\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { FeatureAtPointerEventBehavior } from \"./feature-at-pointer-event.behavior\";\nimport { Position } from \"geojson\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport { MidPointBehavior } from \"./midpoint.behavior\";\nimport { limitPrecision } from \"../../../geometry/limit-decimal-precision\";\nimport { FeatureId } from \"../../../store/store\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport class DragFeatureBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly featuresAtCursorEvent: FeatureAtPointerEventBehavior,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t\tprivate readonly coordinatePoints: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate draggedFeatureId: FeatureId | null = null;\n\n\tprivate dragPosition: Position | undefined;\n\n\tstartDragging(event: TerraDrawMouseEvent, id: FeatureId) {\n\t\tthis.draggedFeatureId = id;\n\t\tthis.dragPosition = [event.lng, event.lat];\n\t}\n\n\tstopDragging() {\n\t\tthis.draggedFeatureId = null;\n\t\tthis.dragPosition = undefined;\n\t}\n\n\tisDragging() {\n\t\treturn this.draggedFeatureId !== null;\n\t}\n\n\tcanDrag(event: TerraDrawMouseEvent, selectedId: FeatureId) {\n\t\tconst { clickedFeature } = this.featuresAtCursorEvent.find(event, true);\n\n\t\t// If the cursor is not over the selected\n\t\t// feature then we don't want to drag\n\t\tif (!clickedFeature || clickedFeature.id !== selectedId) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tdrag(event: TerraDrawMouseEvent, validateFeature?: Validation) {\n\t\tif (!this.draggedFeatureId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(this.draggedFeatureId);\n\t\tconst cursorCoord = [event.lng, event.lat];\n\n\t\t// Update the geometry of the dragged feature\n\t\tif (geometry.type === \"Polygon\" || geometry.type === \"LineString\") {\n\t\t\tlet updatedCoords: Position[];\n\t\t\tlet upToCoord: number;\n\n\t\t\tif (geometry.type === \"Polygon\") {\n\t\t\t\tupdatedCoords = geometry.coordinates[0];\n\t\t\t\tupToCoord = updatedCoords.length - 1;\n\t\t\t} else {\n\t\t\t\t// Must be LineString here\n\t\t\t\tupdatedCoords = geometry.coordinates;\n\t\t\t\tupToCoord = updatedCoords.length;\n\t\t\t}\n\n\t\t\tif (!this.dragPosition) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < upToCoord; i++) {\n\t\t\t\tconst coordinate = updatedCoords[i];\n\n\t\t\t\tlet updatedLng: number;\n\t\t\t\tlet updatedLat: number;\n\n\t\t\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\t\t\tconst webMercatorDragPosition = lngLatToWebMercatorXY(\n\t\t\t\t\t\tthis.dragPosition[0],\n\t\t\t\t\t\tthis.dragPosition[1],\n\t\t\t\t\t);\n\t\t\t\t\tconst webMercatorCursorCoord = lngLatToWebMercatorXY(\n\t\t\t\t\t\tcursorCoord[0],\n\t\t\t\t\t\tcursorCoord[1],\n\t\t\t\t\t);\n\t\t\t\t\tconst webMercatorCoordinate = lngLatToWebMercatorXY(\n\t\t\t\t\t\tcoordinate[0],\n\t\t\t\t\t\tcoordinate[1],\n\t\t\t\t\t);\n\n\t\t\t\t\tconst delta = {\n\t\t\t\t\t\tx: webMercatorDragPosition.x - webMercatorCursorCoord.x,\n\t\t\t\t\t\ty: webMercatorDragPosition.y - webMercatorCursorCoord.y,\n\t\t\t\t\t};\n\n\t\t\t\t\tconst updatedX = webMercatorCoordinate.x - delta.x;\n\t\t\t\t\tconst updatedY = webMercatorCoordinate.y - delta.y;\n\n\t\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(updatedX, updatedY);\n\n\t\t\t\t\tupdatedLng = lng;\n\t\t\t\t\tupdatedLat = lat;\n\t\t\t\t} else {\n\t\t\t\t\tconst delta = [\n\t\t\t\t\t\tthis.dragPosition[0] - cursorCoord[0],\n\t\t\t\t\t\tthis.dragPosition[1] - cursorCoord[1],\n\t\t\t\t\t];\n\t\t\t\t\tupdatedLng = coordinate[0] - delta[0];\n\t\t\t\t\tupdatedLat = coordinate[1] - delta[1];\n\t\t\t\t}\n\n\t\t\t\t// Keep precision limited when calculating new coordinates\n\t\t\t\tupdatedLng = limitPrecision(\n\t\t\t\t\tupdatedLng,\n\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t);\n\n\t\t\t\tupdatedLat = limitPrecision(\n\t\t\t\t\tupdatedLat,\n\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t);\n\n\t\t\t\t// Ensure that coordinates do not exceed\n\t\t\t\t// lng lat limits. Long term we may want to figure out\n\t\t\t\t// proper handling of anti meridian crossings\n\t\t\t\tif (\n\t\t\t\t\tupdatedLng > 180 ||\n\t\t\t\t\tupdatedLng < -180 ||\n\t\t\t\t\tupdatedLat > 90 ||\n\t\t\t\t\tupdatedLat < -90\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tupdatedCoords[i] = [updatedLng, updatedLat];\n\t\t\t}\n\n\t\t\t// Set final coordinate identical to first\n\t\t\t// We only want to do this for polygons!\n\t\t\tif (geometry.type === \"Polygon\") {\n\t\t\t\tupdatedCoords[updatedCoords.length - 1] = [\n\t\t\t\t\tupdatedCoords[0][0],\n\t\t\t\t\tupdatedCoords[0][1],\n\t\t\t\t];\n\t\t\t}\n\n\t\t\tconst updatedSelectionPoints =\n\t\t\t\tthis.selectionPoints.getUpdated(updatedCoords) || [];\n\n\t\t\tconst updatedMidPoints = this.midPoints.getUpdated(updatedCoords) || [];\n\n\t\t\tconst updatedCoordinatePoints =\n\t\t\t\tthis.coordinatePoints.getUpdated(\n\t\t\t\t\tthis.draggedFeatureId,\n\t\t\t\t\tupdatedCoords,\n\t\t\t\t) || [];\n\n\t\t\tif (validateFeature) {\n\t\t\t\tconst validationResult = validateFeature(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tid: this.draggedFeatureId,\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.config.project,\n\t\t\t\t\t\tunproject: this.config.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!validationResult.valid) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Issue the update to the selected feature\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.draggedFeatureId, geometry },\n\t\t\t\t...updatedSelectionPoints,\n\t\t\t\t...updatedMidPoints,\n\t\t\t\t...updatedCoordinatePoints,\n\t\t\t]);\n\n\t\t\tthis.dragPosition = [event.lng, event.lat];\n\n\t\t\t// Update mid point positions\n\t\t} else if (geometry.type === \"Point\") {\n\t\t\t// For cursor points we can simply move it\n\t\t\t// to the dragged position\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.draggedFeatureId,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: cursorCoord,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\tthis.dragPosition = [event.lng, event.lat];\n\t\t}\n\t}\n}\n","import {\n\tSnapping,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../../../common\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\n\nimport { LineString, Polygon, Position, Point, Feature } from \"geojson\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\nimport { MidPointBehavior } from \"./midpoint.behavior\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport { selfIntersects } from \"../../../geometry/boolean/self-intersects\";\nimport { FeatureId, GeoJSONStoreFeatures } from \"../../../store/store\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\nimport { CoordinateSnappingBehavior } from \"../../coordinate-snapping.behavior\";\nimport { LineSnappingBehavior } from \"../../line-snapping.behavior\";\n\nexport class DragCoordinateBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t\tprivate readonly coordinatePoints: CoordinatePointBehavior,\n\t\tprivate readonly coordinateSnapping: CoordinateSnappingBehavior,\n\t\tprivate readonly lineSnapping: LineSnappingBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate draggedCoordinate: { id: null | FeatureId; index: number } = {\n\t\tid: null,\n\t\tindex: -1,\n\t};\n\n\tprivate getClosestCoordinate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tgeometry: Polygon | LineString | Point,\n\t) {\n\t\tconst closestCoordinate = {\n\t\t\tdist: Infinity,\n\t\t\tindex: -1,\n\t\t\tisFirstOrLastPolygonCoord: false,\n\t\t};\n\n\t\tlet geomCoordinates: Position[] | undefined;\n\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tgeomCoordinates = geometry.coordinates;\n\t\t} else if (geometry.type === \"Polygon\") {\n\t\t\tgeomCoordinates = geometry.coordinates[0];\n\t\t} else {\n\t\t\t// We don't want to handle dragging\n\t\t\t// points here\n\t\t\treturn closestCoordinate;\n\t\t}\n\n\t\t// Look through the selected features coordinates\n\t\t// and try to find a coordinate that is draggable\n\t\tfor (let i = 0; i < geomCoordinates.length; i++) {\n\t\t\tconst coord = geomCoordinates[i];\n\t\t\tconst distance = this.pixelDistance.measure(event, coord);\n\n\t\t\tif (\n\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\tdistance < closestCoordinate.dist\n\t\t\t) {\n\t\t\t\t// We don't create a point for the final\n\t\t\t\t// polygon coord, so we must set it to the first\n\t\t\t\t// coordinate instead\n\t\t\t\tconst isFirstOrLastPolygonCoord =\n\t\t\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t\t\t(i === geomCoordinates.length - 1 || i === 0);\n\n\t\t\t\tclosestCoordinate.dist = distance;\n\t\t\t\tclosestCoordinate.index = isFirstOrLastPolygonCoord ? 0 : i;\n\t\t\t\tclosestCoordinate.isFirstOrLastPolygonCoord = isFirstOrLastPolygonCoord;\n\t\t\t}\n\t\t}\n\n\t\treturn closestCoordinate;\n\t}\n\n\tpublic getDraggableIndex(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t): number {\n\t\tconst geometry = this.store.getGeometryCopy(selectedId);\n\t\tconst closestCoordinate = this.getClosestCoordinate(event, geometry);\n\n\t\t// No coordinate was within the pointer distance\n\t\tif (closestCoordinate.index === -1) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn closestCoordinate.index;\n\t}\n\n\tprivate snapCoordinate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsnapping: Snapping,\n\t\tdraggedFeature: GeoJSONStoreFeatures,\n\t): Position {\n\t\tlet snappedCoordinate: Position = [event.lng, event.lat];\n\n\t\t// This is a uniform filter we can use across all snapping behaviors\n\t\tconst filter = (feature: Feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === draggedFeature.properties.mode &&\n\t\t\t\t\tfeature.id !== this.draggedCoordinate.id,\n\t\t\t);\n\t\t};\n\n\t\tif (snapping?.toLine) {\n\t\t\tlet snapped: Position | undefined;\n\n\t\t\tsnapped = this.lineSnapping.getSnappable(event, filter).coordinate;\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (snapping.toCoordinate) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\n\t\t\tsnapped = this.coordinateSnapping.getSnappable(event, filter).coordinate;\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (snapping?.toCustom) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\n\t\t\tsnapped = snapping.toCustom(event, {\n\t\t\t\tcurrentCoordinate: this.draggedCoordinate.index,\n\t\t\t\tcurrentId: draggedFeature.id,\n\t\t\t\tgetCurrentGeometrySnapshot: draggedFeature.id\n\t\t\t\t\t? () =>\n\t\t\t\t\t\t\tthis.store.getGeometryCopy<Polygon>(\n\t\t\t\t\t\t\t\tdraggedFeature.id as FeatureId,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: () => null,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t});\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\treturn snappedCoordinate;\n\t}\n\n\tdrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tallowSelfIntersection: boolean,\n\t\tvalidateFeature: Validation,\n\t\tsnapping: Snapping,\n\t): boolean {\n\t\tconst draggedFeatureId = this.draggedCoordinate.id;\n\n\t\tif (draggedFeatureId === null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst index = this.draggedCoordinate.index;\n\t\tconst geometry = this.store.getGeometryCopy(draggedFeatureId);\n\t\tconst properties = this.store.getPropertiesCopy(draggedFeatureId);\n\n\t\tconst geomCoordinates = (\n\t\t\tgeometry.type === \"LineString\"\n\t\t\t\t? geometry.coordinates\n\t\t\t\t: geometry.coordinates[0]\n\t\t) as Position[];\n\n\t\tconst isFirstOrLastPolygonCoord =\n\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t(index === geomCoordinates.length - 1 || index === 0);\n\n\t\tconst draggedFeature: GeoJSONStoreFeatures = {\n\t\t\ttype: \"Feature\",\n\t\t\tid: draggedFeatureId,\n\t\t\tgeometry,\n\t\t\tproperties,\n\t\t};\n\n\t\tconst updatedCoordinate = this.snapCoordinate(\n\t\t\tevent,\n\t\t\tsnapping,\n\t\t\tdraggedFeature,\n\t\t);\n\n\t\t// Ensure that coordinates do not exceed\n\t\t// lng lat limits. Long term we may want to figure out\n\t\t// proper handling of anti meridian crossings\n\t\tif (\n\t\t\tevent.lng > 180 ||\n\t\t\tevent.lng < -180 ||\n\t\t\tevent.lat > 90 ||\n\t\t\tevent.lat < -90\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We want to update the actual Polygon/LineString itself -\n\t\t// for Polygons we want the first and last coordinates to match\n\t\tif (isFirstOrLastPolygonCoord) {\n\t\t\tconst lastCoordIndex = geomCoordinates.length - 1;\n\t\t\tgeomCoordinates[0] = updatedCoordinate;\n\t\t\tgeomCoordinates[lastCoordIndex] = updatedCoordinate;\n\t\t} else {\n\t\t\tgeomCoordinates[index] = updatedCoordinate;\n\t\t}\n\n\t\tconst updatedSelectionPoint = this.selectionPoints.getOneUpdated(\n\t\t\tindex,\n\t\t\tupdatedCoordinate,\n\t\t);\n\n\t\tconst updatedSelectionPoints = updatedSelectionPoint\n\t\t\t? [updatedSelectionPoint]\n\t\t\t: [];\n\n\t\tconst updatedMidPoints = this.midPoints.getUpdated(geomCoordinates) || [];\n\n\t\tconst updatedCoordinatePoints =\n\t\t\tthis.coordinatePoints.getUpdated(draggedFeatureId, geomCoordinates) || [];\n\n\t\tif (\n\t\t\tgeometry.type !== \"Point\" &&\n\t\t\t!allowSelfIntersection &&\n\t\t\tselfIntersects({\n\t\t\t\ttype: \"Feature\",\n\t\t\t\tgeometry: geometry,\n\t\t\t\tproperties: {},\n\t\t\t} as Feature<Polygon>)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (validateFeature) {\n\t\t\tconst validationResult = validateFeature(draggedFeature, {\n\t\t\t\tproject: this.config.project,\n\t\t\t\tunproject: this.config.unproject,\n\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t});\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Apply all the updates\n\t\tthis.store.updateGeometry([\n\t\t\t// Update feature\n\t\t\t{\n\t\t\t\tid: draggedFeatureId,\n\t\t\t\tgeometry: geometry,\n\t\t\t},\n\t\t\t// Update selection and mid points\n\t\t\t...updatedSelectionPoints,\n\t\t\t...updatedMidPoints,\n\t\t\t...updatedCoordinatePoints,\n\t\t]);\n\n\t\treturn true;\n\t}\n\n\tisDragging() {\n\t\treturn this.draggedCoordinate.id !== null;\n\t}\n\n\tstartDragging(id: FeatureId, index: number) {\n\t\tthis.draggedCoordinate = {\n\t\t\tid,\n\t\t\tindex,\n\t\t};\n\t}\n\n\tstopDragging() {\n\t\tthis.draggedCoordinate = {\n\t\t\tid: null,\n\t\t\tindex: -1,\n\t\t};\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\n\n// Adapter from the @turf/bearing which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-centroid\n\nexport function centroid(geojson: Feature<Polygon | LineString>): Position {\n\tlet xSum = 0;\n\tlet ySum = 0;\n\tlet len = 0;\n\n\tconst coordinates =\n\t\tgeojson.geometry.type === \"Polygon\"\n\t\t\t? geojson.geometry.coordinates[0].slice(0, -1)\n\t\t\t: geojson.geometry.coordinates;\n\n\tcoordinates.forEach((coord: Position) => {\n\t\txSum += coord[0];\n\t\tySum += coord[1];\n\t\tlen++;\n\t}, true);\n\n\treturn [xSum / len, ySum / len];\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\nimport { lngLatToWebMercatorXY } from \"./project/web-mercator\";\nimport { CartesianPoint } from \"../common\";\n\n/**\n * Calculates the centroid of a GeoJSON Polygon or LineString in Web Mercator\n\n * @param {Feature<Polygon | LineString>} feature - The GeoJSON Feature containing either a Polygon or LineString\n * @returns {{ x: number, y: number }} The centroid of the polygon or line string in Web Mercator coordinates.\n */\nexport function webMercatorCentroid(feature: Feature<Polygon | LineString>) {\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\n\tconst webMercatorCoordinates = coordinates.map((coord) => {\n\t\tconst { x, y } = lngLatToWebMercatorXY(coord[0], coord[1]);\n\t\treturn [x, y];\n\t});\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\treturn calculatePolygonCentroid(webMercatorCoordinates);\n\t} else {\n\t\treturn calculateLineStringMidpoint(webMercatorCoordinates);\n\t}\n}\n\nfunction calculatePolygonCentroid(\n\twebMercatorCoordinates: Position[],\n): CartesianPoint {\n\tlet area = 0;\n\tlet centroidX = 0;\n\tlet centroidY = 0;\n\n\tconst n = webMercatorCoordinates.length;\n\n\tfor (let i = 0; i < n - 1; i++) {\n\t\tconst [x1, y1] = webMercatorCoordinates[i];\n\t\tconst [x2, y2] = webMercatorCoordinates[i + 1];\n\n\t\tconst crossProduct = x1 * y2 - x2 * y1;\n\t\tarea += crossProduct;\n\t\tcentroidX += (x1 + x2) * crossProduct;\n\t\tcentroidY += (y1 + y2) * crossProduct;\n\t}\n\n\tarea /= 2;\n\tcentroidX /= 6 * area;\n\tcentroidY /= 6 * area;\n\n\treturn { x: centroidX, y: centroidY };\n}\n\nfunction calculateLineStringMidpoint(lineString: Position[]): CartesianPoint {\n\tconst n = lineString.length;\n\tlet totalX = 0;\n\tlet totalY = 0;\n\n\tfor (let i = 0; i < n; i++) {\n\t\tconst [x, y] = lineString[i];\n\t\ttotalX += x;\n\t\ttotalY += y;\n\t}\n\n\treturn { x: totalX / n, y: totalY / n };\n}\n","import {\n\tCartesianPoint,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../../../common\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { Feature, LineString, Polygon, Position } from \"geojson\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport { MidPointBehavior } from \"./midpoint.behavior\";\nimport {\n\ttransformRotate,\n\ttransformRotateWebMercator,\n} from \"../../../geometry/transform/rotate\";\nimport { centroid } from \"../../../geometry/centroid\";\nimport { rhumbBearing } from \"../../../geometry/measure/rhumb-bearing\";\nimport { limitPrecision } from \"../../../geometry/limit-decimal-precision\";\nimport { FeatureId } from \"../../../store/store\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\nimport { lngLatToWebMercatorXY } from \"../../../geometry/project/web-mercator\";\nimport { webMercatorBearing } from \"../../../geometry/measure/bearing\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport class RotateFeatureBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t\tprivate readonly coordinatePoints: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate lastBearing: number | undefined;\n\tprivate selectedGeometry: Polygon | LineString | undefined;\n\tprivate selectedGeometryCentroid: Position | undefined;\n\tprivate selectedGeometryWebMercatorCentroid: CartesianPoint | undefined;\n\n\treset() {\n\t\tthis.lastBearing = undefined;\n\t\tthis.selectedGeometry = undefined;\n\t\tthis.selectedGeometryWebMercatorCentroid = undefined;\n\t\tthis.selectedGeometryCentroid = undefined;\n\t}\n\n\trotate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t\tvalidateFeature?: Validation,\n\t) {\n\t\tif (!this.selectedGeometry) {\n\t\t\tthis.selectedGeometry = this.store.getGeometryCopy<LineString | Polygon>(\n\t\t\t\tselectedId,\n\t\t\t);\n\t\t}\n\n\t\tconst geometry = this.selectedGeometry;\n\n\t\t// Update the geometry of the dragged feature\n\t\tif (geometry.type !== \"Polygon\" && geometry.type !== \"LineString\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mouseCoord = [event.lng, event.lat];\n\n\t\tlet bearing: number;\n\t\tconst feature = { type: \"Feature\", geometry, properties: {} } as\n\t\t\t| Feature<Polygon>\n\t\t\t| Feature<LineString>;\n\n\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\t// Cache the centroid of the selected geometry\n\t\t\t// to avoid recalculating it on every cursor move\n\t\t\tif (!this.selectedGeometryWebMercatorCentroid) {\n\t\t\t\tthis.selectedGeometryWebMercatorCentroid = webMercatorCentroid(feature);\n\t\t\t}\n\n\t\t\tconst cursorWebMercator = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\tbearing = webMercatorBearing(\n\t\t\t\tthis.selectedGeometryWebMercatorCentroid,\n\t\t\t\tcursorWebMercator,\n\t\t\t);\n\n\t\t\tif (bearing === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!this.lastBearing) {\n\t\t\t\tthis.lastBearing = bearing;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst angle = this.lastBearing - bearing;\n\n\t\t\ttransformRotateWebMercator(feature, -angle);\n\t\t} else if (this.config.projection === \"globe\") {\n\t\t\t// Cache the centroid of the selected geometry\n\t\t\t// to avoid recalculating it on every cursor move\n\t\t\tif (!this.selectedGeometryCentroid) {\n\t\t\t\tthis.selectedGeometryCentroid = centroid({\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tbearing = rhumbBearing(this.selectedGeometryCentroid, mouseCoord);\n\n\t\t\t// We need an original bearing to compare against\n\t\t\tif (!this.lastBearing) {\n\t\t\t\tthis.lastBearing = bearing + 180;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst angle = this.lastBearing - (bearing + 180);\n\n\t\t\ttransformRotate(feature, -angle);\n\t\t} else {\n\t\t\tthrow new Error(\"Unsupported projection\");\n\t\t}\n\n\t\t// Coordinates are either polygon or linestring at this point\n\t\tconst updatedCoords: Position[] =\n\t\t\tgeometry.type === \"Polygon\"\n\t\t\t\t? geometry.coordinates[0]\n\t\t\t\t: geometry.coordinates;\n\n\t\t// Ensure that coordinate precision is maintained\n\t\tupdatedCoords.forEach((coordinate) => {\n\t\t\tcoordinate[0] = limitPrecision(coordinate[0], this.coordinatePrecision);\n\t\t\tcoordinate[1] = limitPrecision(coordinate[1], this.coordinatePrecision);\n\t\t});\n\n\t\tconst updatedMidPoints = this.midPoints.getUpdated(updatedCoords) || [];\n\n\t\tconst updatedSelectionPoints =\n\t\t\tthis.selectionPoints.getUpdated(updatedCoords) || [];\n\n\t\tconst updatedCoordinatePoints =\n\t\t\tthis.coordinatePoints.getUpdated(selectedId, updatedCoords) || [];\n\n\t\tif (validateFeature) {\n\t\t\tif (\n\t\t\t\t!validateFeature(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: selectedId,\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.config.project,\n\t\t\t\t\t\tunproject: this.config.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Issue the update to the selected feature\n\t\tthis.store.updateGeometry([\n\t\t\t{ id: selectedId, geometry },\n\t\t\t...updatedSelectionPoints,\n\t\t\t...updatedMidPoints,\n\t\t\t...updatedCoordinatePoints,\n\t\t]);\n\n\t\tif (this.projection === \"web-mercator\") {\n\t\t\tthis.lastBearing = bearing;\n\t\t} else if (this.projection === \"globe\") {\n\t\t\tthis.lastBearing = bearing + 180;\n\t\t}\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\nimport { centroid } from \"../centroid\";\nimport { rhumbBearing } from \"../measure/rhumb-bearing\";\nimport { rhumbDestination } from \"../measure/rhumb-destination\";\nimport { rhumbDistance } from \"../measure/rhumb-distance\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\nimport { CartesianPoint } from \"../../common\";\n\n// Adapted on @turf/transform-rotate module which is MIT licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-transform-rotate\n\nexport function transformRotate(\n\tfeature: Feature<Polygon | LineString>,\n\tangle: number,\n) {\n\t// Shortcut no-rotation\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\t// Use centroid of GeoJSON if pivot is not provided\n\tconst pivot = centroid(feature);\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\n\tcoordinates.forEach((pointCoords: Position) => {\n\t\tconst initialAngle = rhumbBearing(pivot, pointCoords);\n\t\tconst finalAngle = initialAngle + angle;\n\t\tconst distance = rhumbDistance(pivot, pointCoords);\n\t\tconst newCoords = rhumbDestination(pivot, distance, finalAngle);\n\t\tpointCoords[0] = newCoords[0];\n\t\tpointCoords[1] = newCoords[1];\n\t});\n\n\treturn feature;\n}\n\n/**\n * Rotate a GeoJSON Polygon geometry in web mercator\n * @param polygon - GeoJSON Polygon geometry\n * @param angle - rotation angle in degrees\n * @returns - rotated GeoJSON Polygon geometry\n */\nexport const transformRotateWebMercator = (\n\tfeature: Feature<Polygon> | Feature<LineString>,\n\tangle: number,\n) => {\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\tconst DEGREES_TO_RADIANS = 0.017453292519943295 as const; // Math.PI / 180\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\tconst angleRad = angle * DEGREES_TO_RADIANS;\n\n\t// Convert polygon coordinates to Web Mercator\n\tconst webMercatorCoords = coordinates.map(([lng, lat]) =>\n\t\tlngLatToWebMercatorXY(lng, lat),\n\t);\n\n\t// Find centroid of the polygon in Web Mercator\n\tconst centroid = webMercatorCoords.reduce(\n\t\t(acc: CartesianPoint, coord: CartesianPoint) => ({\n\t\t\tx: acc.x + coord.x,\n\t\t\ty: acc.y + coord.y,\n\t\t}),\n\t\t{ x: 0, y: 0 },\n\t);\n\tcentroid.x /= webMercatorCoords.length;\n\tcentroid.y /= webMercatorCoords.length;\n\n\t// Rotate the coordinates around the centroid\n\tconst rotatedWebMercatorCoords = webMercatorCoords.map((coord) => ({\n\t\tx:\n\t\t\tcentroid.x +\n\t\t\t(coord.x - centroid.x) * Math.cos(angleRad) -\n\t\t\t(coord.y - centroid.y) * Math.sin(angleRad),\n\t\ty:\n\t\t\tcentroid.y +\n\t\t\t(coord.x - centroid.x) * Math.sin(angleRad) +\n\t\t\t(coord.y - centroid.y) * Math.cos(angleRad),\n\t}));\n\n\t// Convert rotated Web Mercator coordinates back to geographic\n\tconst rotatedCoordinates = rotatedWebMercatorCoords.map(\n\t\t({ x, y }) =>\n\t\t\t[\n\t\t\t\twebMercatorXYToLngLat(x, y).lng,\n\t\t\t\twebMercatorXYToLngLat(x, y).lat,\n\t\t\t] as Position,\n\t);\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tfeature.geometry.coordinates[0] = rotatedCoordinates;\n\t} else {\n\t\tfeature.geometry.coordinates = rotatedCoordinates;\n\t}\n\n\treturn feature;\n};\n","import { Position } from \"geojson\";\nimport { earthRadius } from \"../helpers\";\n\n// Adapted from @turf/rhumb-distance module\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-distance/index.ts\n\nexport function rhumbDistance(destination: Position, origin: Position): number {\n\t// compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)\n\t// solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678\n\tdestination[0] +=\n\t\tdestination[0] - origin[0] > 180\n\t\t\t? -360\n\t\t\t: origin[0] - destination[0] > 180\n\t\t\t\t? 360\n\t\t\t\t: 0;\n\n\t// see www.edwilliams.org/avform.htm#Rhumb\n\n\tconst R = earthRadius;\n\tconst phi1 = (origin[1] * Math.PI) / 180;\n\tconst phi2 = (destination[1] * Math.PI) / 180;\n\tconst DeltaPhi = phi2 - phi1;\n\tlet DeltaLambda = (Math.abs(destination[0] - origin[0]) * Math.PI) / 180;\n\n\t// if dLon over 180° take shorter rhumb line across the anti-meridian:\n\tif (DeltaLambda > Math.PI) {\n\t\tDeltaLambda -= 2 * Math.PI;\n\t}\n\n\t// on Mercator projection, longitude distances shrink by latitude; q is the 'stretch factor'\n\t// q becomes ill-conditioned along E-W line (0/0); use empirical tolerance to avoid it\n\tconst DeltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\tconst q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);\n\n\t// distance is pythagoras on 'stretched' Mercator projection\n\tconst delta = Math.sqrt(\n\t\tDeltaPhi * DeltaPhi + q * q * DeltaLambda * DeltaLambda,\n\t); // angular distance in radians\n\n\tconst distanceMeters = delta * R;\n\n\treturn distanceMeters;\n}\n","import { TerraDrawMouseEvent, Validation } from \"../../../common\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { FeatureId } from \"../../../store/store\";\nimport { DragCoordinateResizeBehavior } from \"./drag-coordinate-resize.behavior\";\n\nexport class ScaleFeatureBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly dragCoordinateResizeBehavior: DragCoordinateResizeBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tpublic scale(\n\t\tevent: TerraDrawMouseEvent,\n\t\tfeatureId: FeatureId,\n\t\tvalidation?: Validation,\n\t) {\n\t\tif (!this.dragCoordinateResizeBehavior.isDragging()) {\n\t\t\tconst index = this.dragCoordinateResizeBehavior.getDraggableIndex(\n\t\t\t\tevent,\n\t\t\t\tfeatureId,\n\t\t\t);\n\t\t\tthis.dragCoordinateResizeBehavior.startDragging(featureId, index);\n\t\t}\n\n\t\tthis.dragCoordinateResizeBehavior.drag(event, \"center-fixed\", validation);\n\t}\n\n\tpublic reset() {\n\t\tthis.dragCoordinateResizeBehavior.stopDragging();\n\t}\n}\n","import {\n\tCartesianPoint,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../../../common\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { LineString, Polygon, Position, Point, Feature } from \"geojson\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\nimport { MidPointBehavior } from \"./midpoint.behavior\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport { FeatureId, GeoJSONStoreGeometries } from \"../../../store/store\";\nimport { limitPrecision } from \"../../../geometry/limit-decimal-precision\";\nimport { cartesianDistance } from \"../../../geometry/measure/pixel-distance\";\nimport { coordinatePrecisionIsValid } from \"../../../geometry/boolean/is-valid-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport type ResizeOptions =\n\t| \"center\"\n\t| \"opposite\"\n\t| \"center-fixed\"\n\t| \"opposite-fixed\";\n\ntype BoundingBoxIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;\n\ntype BoundingBox = readonly [\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n];\n\nexport class DragCoordinateResizeBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t\tprivate readonly coordinatePoints: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate minimumScale = 0.0001;\n\n\tprivate draggedCoordinate: { id: null | FeatureId; index: number } = {\n\t\tid: null,\n\t\tindex: -1,\n\t};\n\n\t// This map provides the oppsite corner of the bbox\n\t// to the index of the coordinate provided\n\t//   0    1    2\n\t//   *----*----*\n\t// \t |\t\t   |\n\t// 7 *\t\t   *  3\n\t//   |\t\t   |\n\t//   *----*----*\n\t// \t 6    5    4\n\t//\n\tprivate boundingBoxMaps = {\n\t\topposite: {\n\t\t\t0: 4,\n\t\t\t1: 5,\n\t\t\t2: 6,\n\t\t\t3: 7,\n\t\t\t4: 0,\n\t\t\t5: 1,\n\t\t\t6: 2,\n\t\t\t7: 3,\n\t\t},\n\t};\n\n\tprivate getClosestCoordinate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tgeometry: Polygon | LineString | Point,\n\t) {\n\t\tconst closestCoordinate = {\n\t\t\tdist: Infinity,\n\t\t\tindex: -1,\n\t\t\tisFirstOrLastPolygonCoord: false,\n\t\t};\n\n\t\tlet geomCoordinates: Position[] | undefined;\n\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tgeomCoordinates = geometry.coordinates;\n\t\t} else if (geometry.type === \"Polygon\") {\n\t\t\tgeomCoordinates = geometry.coordinates[0];\n\t\t} else {\n\t\t\t// We don't want to handle dragging\n\t\t\t// points here\n\t\t\treturn closestCoordinate;\n\t\t}\n\n\t\t// Look through the selected features coordinates\n\t\t// and try to find a coordinate that is draggable\n\t\tfor (let i = 0; i < geomCoordinates.length; i++) {\n\t\t\tconst coord = geomCoordinates[i];\n\t\t\tconst distance = this.pixelDistance.measure(event, coord);\n\n\t\t\tif (\n\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\tdistance < closestCoordinate.dist\n\t\t\t) {\n\t\t\t\t// We don't create a point for the final\n\t\t\t\t// polygon coord, so we must set it to the first\n\t\t\t\t// coordinate instead\n\t\t\t\tconst isFirstOrLastPolygonCoord =\n\t\t\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t\t\t(i === geomCoordinates.length - 1 || i === 0);\n\n\t\t\t\tclosestCoordinate.dist = distance;\n\t\t\t\tclosestCoordinate.index = isFirstOrLastPolygonCoord ? 0 : i;\n\t\t\t\tclosestCoordinate.isFirstOrLastPolygonCoord = isFirstOrLastPolygonCoord;\n\t\t\t}\n\t\t}\n\n\t\treturn closestCoordinate;\n\t}\n\n\tprivate isValidDragWebMercator(\n\t\tindex: BoundingBoxIndex,\n\t\tdistanceX: number,\n\t\tdistanceY: number,\n\t) {\n\t\tswitch (index) {\n\t\t\tcase 0:\n\t\t\t\tif (distanceX <= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif (distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (distanceX >= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif (distanceX >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tif (distanceX >= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tif (distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tif (distanceX <= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tif (distanceX <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate getSelectedFeatureDataWebMercator() {\n\t\tif (!this.draggedCoordinate.id || this.draggedCoordinate.index === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = this.getFeature(this.draggedCoordinate.id);\n\t\tif (!feature) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst updatedCoords = this.getNormalisedCoordinates(feature.geometry);\n\t\tconst boundingBox = this.getBBoxWebMercator(updatedCoords);\n\n\t\treturn {\n\t\t\tboundingBox,\n\t\t\tfeature,\n\t\t\tupdatedCoords,\n\t\t\tselectedCoordinate: updatedCoords[this.draggedCoordinate.index],\n\t\t};\n\t}\n\n\tprivate centerWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate centerFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleFixedWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet scale =\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorCursor) /\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorSelected);\n\n\t\tif (scale < 0) {\n\t\t\tscale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\tscale,\n\t\t\tscale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet xScale = 1;\n\t\tif (\n\t\t\tcursorDistanceX !== 0 &&\n\t\t\tclosestBBoxIndex !== 1 &&\n\t\t\tclosestBBoxIndex !== 5\n\t\t) {\n\t\t\tconst currentDistanceX = webMercatorOrigin.x - webMercatorSelected.x;\n\t\t\txScale = 1 - (currentDistanceX - cursorDistanceX) / cursorDistanceX;\n\t\t}\n\n\t\tlet yScale = 1;\n\t\tif (\n\t\t\tcursorDistanceY !== 0 &&\n\t\t\tclosestBBoxIndex !== 3 &&\n\t\t\tclosestBBoxIndex !== 7\n\t\t) {\n\t\t\tconst currentDistanceY = webMercatorOrigin.y - webMercatorSelected.y;\n\t\t\tyScale = 1 - (currentDistanceY - cursorDistanceY) / cursorDistanceY;\n\t\t}\n\n\t\tif (!this.validateScale(xScale, yScale)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (xScale < 0) {\n\t\t\txScale = this.minimumScale;\n\t\t}\n\n\t\tif (yScale < 0) {\n\t\t\tyScale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\txScale,\n\t\t\tyScale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate getFeature(id: FeatureId) {\n\t\tif (this.draggedCoordinate.id === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(id);\n\n\t\t// Update the geometry of the dragged feature\n\t\tif (geometry.type !== \"Polygon\" && geometry.type !== \"LineString\") {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = {\n\t\t\tid,\n\t\t\ttype: \"Feature\",\n\t\t\tgeometry,\n\t\t\tproperties: {},\n\t\t} as Feature<Polygon | LineString>;\n\n\t\treturn feature;\n\t}\n\n\tprivate getNormalisedCoordinates(geometry: Polygon | LineString) {\n\t\t// Coordinates are either polygon or linestring at this point\n\t\treturn geometry.type === \"Polygon\"\n\t\t\t? geometry.coordinates[0]\n\t\t\t: geometry.coordinates;\n\t}\n\n\tprivate validateScale(xScale: number, yScale: number) {\n\t\tconst validX = !isNaN(xScale) && yScale < Number.MAX_SAFE_INTEGER;\n\t\tconst validY = !isNaN(yScale) && yScale < Number.MAX_SAFE_INTEGER;\n\n\t\treturn validX && validY;\n\t}\n\n\tprivate performWebMercatorScale(\n\t\tcoordinates: Position[],\n\t\toriginX: number,\n\t\toriginY: number,\n\t\txScale: number,\n\t\tyScale: number,\n\t) {\n\t\tcoordinates.forEach((coordinate) => {\n\t\t\tconst { x, y } = lngLatToWebMercatorXY(coordinate[0], coordinate[1]);\n\n\t\t\tconst updatedX = originX + (x - originX) * xScale;\n\t\t\tconst updatedY = originY + (y - originY) * yScale;\n\n\t\t\tconst { lng, lat } = webMercatorXYToLngLat(updatedX, updatedY);\n\n\t\t\tcoordinate[0] = lng;\n\t\t\tcoordinate[1] = lat;\n\t\t});\n\t}\n\n\tprivate getBBoxWebMercator(coordinates: Position[]) {\n\t\tconst bbox: [number, number, number, number] = [\n\t\t\tInfinity,\n\t\t\tInfinity,\n\t\t\t-Infinity,\n\t\t\t-Infinity,\n\t\t];\n\n\t\t// Convert from [lng, lat] -> [x, y]\n\t\tcoordinates = coordinates.map((coord) => {\n\t\t\tconst { x, y } = lngLatToWebMercatorXY(coord[0], coord[1]);\n\t\t\treturn [x, y];\n\t\t});\n\n\t\tcoordinates.forEach(([x, y]) => {\n\t\t\tif (x < bbox[0]) {\n\t\t\t\tbbox[0] = x;\n\t\t\t}\n\n\t\t\tif (y < bbox[1]) {\n\t\t\t\tbbox[1] = y;\n\t\t\t}\n\n\t\t\tif (x > bbox[2]) {\n\t\t\t\tbbox[2] = x;\n\t\t\t}\n\n\t\t\tif (y > bbox[3]) {\n\t\t\t\tbbox[3] = y;\n\t\t\t}\n\t\t});\n\n\t\tconst [west, south, east, north] = bbox;\n\n\t\t//   Bounding box is represented as follows:\n\t\t//\n\t\t//   0    1    2\n\t\t//   *----*----*\n\t\t// \t |\t\t   |\n\t\t// 7 *\t\t   *  3\n\t\t//   |\t\t   |\n\t\t//   *----*----*\n\t\t// \t 6    5    4\n\t\t//\n\t\tconst topLeft = [west, north];\n\t\tconst topRight = [east, north];\n\t\tconst lowRight = [east, south];\n\t\tconst lowLeft = [west, south];\n\n\t\tconst midTop = [(west + east) / 2, north];\n\t\tconst midRight = [east, north + (south - north) / 2];\n\t\tconst midBottom = [(west + east) / 2, south];\n\t\tconst midLeft = [west, north + (south - north) / 2];\n\n\t\treturn [\n\t\t\ttopLeft, // 0\n\t\t\tmidTop, // 1\n\t\t\ttopRight, // 2\n\t\t\tmidRight, // 3\n\t\t\tlowRight, // 4\n\t\t\tmidBottom, // 5\n\t\t\tlowLeft, // 6\n\t\t\tmidLeft, // 7\n\t\t] as const;\n\t}\n\n\tprivate getIndexesWebMercator(\n\t\tboundingBox: BoundingBox,\n\t\tselectedXY: CartesianPoint,\n\t) {\n\t\tlet closestIndex: BoundingBoxIndex | undefined;\n\t\tlet closestDistance = Infinity;\n\n\t\tfor (let i = 0; i < boundingBox.length; i++) {\n\t\t\tconst distance = cartesianDistance(\n\t\t\t\t{ x: selectedXY.x, y: selectedXY.y },\n\t\t\t\t{ x: boundingBox[i][0], y: boundingBox[i][1] },\n\t\t\t);\n\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestIndex = i as BoundingBoxIndex;\n\t\t\t\tclosestDistance = distance;\n\t\t\t}\n\t\t}\n\n\t\tif (closestIndex === undefined) {\n\t\t\tthrow new Error(\"No closest coordinate found\");\n\t\t}\n\n\t\t// Depending on where what the origin is set to, we need to find the position to\n\t\t// scale from\n\t\tconst oppositeIndex = this.boundingBoxMaps[\"opposite\"][\n\t\t\tclosestIndex\n\t\t] as BoundingBoxIndex;\n\n\t\treturn {\n\t\t\toppositeBboxIndex: oppositeIndex,\n\t\t\tclosestBBoxIndex: closestIndex,\n\t\t} as const;\n\t}\n\n\t/**\n\t * @returns - true if the feature is being dragged (resized), false otherwise\n\t */\n\tpublic isDragging() {\n\t\treturn this.draggedCoordinate.id !== null;\n\t}\n\n\t/**\n\t * Starts the resizing of the feature\n\t * @param id - feature id of the feature that is being dragged\n\t * @param index - index of the coordinate that is being dragged\n\t * @returns - void\n\t */\n\tpublic startDragging(id: FeatureId, index: number) {\n\t\tthis.draggedCoordinate = {\n\t\t\tid,\n\t\t\tindex,\n\t\t};\n\t}\n\n\t/**\n\t * Stops the resizing of the feature\n\t * @returns - void\t *\n\t */\n\tpublic stopDragging() {\n\t\tthis.draggedCoordinate = {\n\t\t\tid: null,\n\t\t\tindex: -1,\n\t\t};\n\t}\n\n\t/**\n\t * Returns the index of the coordinate that is going to be dragged\n\t * @param event - cursor event\n\t * @param selectedId - feature id of the feature that is selected\n\t * @returns - the index to be dragged\n\t */\n\tpublic getDraggableIndex(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t): number {\n\t\tconst geometry = this.store.getGeometryCopy(selectedId);\n\t\tconst closestCoordinate = this.getClosestCoordinate(event, geometry);\n\n\t\t// No coordinate was within the pointer distance\n\t\tif (closestCoordinate.index === -1) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn closestCoordinate.index;\n\t}\n\n\t/**\n\t * Resizes the feature based on the cursor event\n\t * @param event - cursor event\n\t * @param resizeOption - the resize option, either \"center\" or \"opposite\"\n\t * @returns - true is resize was successful, false otherwise\n\t */\n\tpublic drag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tresizeOption: ResizeOptions,\n\t\tvalidateFeature?: Validation,\n\t): boolean {\n\t\tif (!this.draggedCoordinate.id) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst feature = this.getFeature(this.draggedCoordinate.id);\n\t\tif (!feature) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet updatedCoords: Position[] | null = null;\n\n\t\tif (resizeOption === \"center\") {\n\t\t\tupdatedCoords = this.centerWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"opposite\") {\n\t\t\tupdatedCoords = this.oppositeWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"center-fixed\") {\n\t\t\tupdatedCoords = this.centerFixedWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"opposite-fixed\") {\n\t\t\tupdatedCoords = this.oppositeFixedWebMercatorDrag(event);\n\t\t}\n\n\t\tif (!updatedCoords) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Ensure that coordinate precision is maintained\n\t\tfor (let i = 0; i < updatedCoords.length; i++) {\n\t\t\tconst coordinate = updatedCoords[i];\n\t\t\tcoordinate[0] = limitPrecision(coordinate[0], this.coordinatePrecision);\n\t\t\tcoordinate[1] = limitPrecision(coordinate[1], this.coordinatePrecision);\n\n\t\t\t// Ensure the coordinate we are about to update with is valid\n\t\t\tif (!coordinatePrecisionIsValid(coordinate, this.coordinatePrecision)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Perform the update to the midpoints and selection points\n\t\tconst updatedMidPoints = this.midPoints.getUpdated(updatedCoords) || [];\n\t\tconst updatedSelectionPoints =\n\t\t\tthis.selectionPoints.getUpdated(updatedCoords) || [];\n\t\tconst updatedCoordinatePoints =\n\t\t\tthis.coordinatePoints.getUpdated(\n\t\t\t\tfeature.id as FeatureId,\n\t\t\t\tupdatedCoords,\n\t\t\t) || [];\n\n\t\tconst updatedGeometry = {\n\t\t\ttype: feature.geometry.type as \"Polygon\" | \"LineString\",\n\t\t\tcoordinates:\n\t\t\t\tfeature.geometry.type === \"Polygon\" ? [updatedCoords] : updatedCoords,\n\t\t} as GeoJSONStoreGeometries;\n\n\t\tif (validateFeature) {\n\t\t\tconst validationResult = validateFeature(\n\t\t\t\t{\n\t\t\t\t\tid: this.draggedCoordinate.id,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.config.project,\n\t\t\t\t\tunproject: this.config.unproject,\n\t\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Issue the update to the selected feature\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.draggedCoordinate.id,\n\t\t\t\tgeometry: updatedGeometry,\n\t\t\t},\n\t\t\t...updatedSelectionPoints,\n\t\t\t...updatedMidPoints,\n\t\t\t...updatedCoordinatePoints,\n\t\t]);\n\n\t\treturn true;\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawKeyboardEvent,\n\tSELECT_PROPERTIES,\n\tTerraDrawAdapterStyling,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tValidation,\n\tUpdateTypes,\n\tZ_INDEX,\n\tSnapping,\n} from \"../../common\";\nimport { Point, Position } from \"geojson\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseSelectMode,\n} from \"../base.mode\";\nimport { MidPointBehavior } from \"./behaviors/midpoint.behavior\";\nimport {\n\tSelectionPointBehavior,\n\tSelectionPointProperties,\n} from \"./behaviors/selection-point.behavior\";\nimport { FeatureAtPointerEventBehavior } from \"./behaviors/feature-at-pointer-event.behavior\";\nimport { PixelDistanceBehavior } from \"../pixel-distance.behavior\";\nimport { ClickBoundingBoxBehavior } from \"../click-bounding-box.behavior\";\nimport { DragFeatureBehavior } from \"./behaviors/drag-feature.behavior\";\nimport { DragCoordinateBehavior } from \"./behaviors/drag-coordinate.behavior\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { RotateFeatureBehavior } from \"./behaviors/rotate-feature.behavior\";\nimport { ScaleFeatureBehavior } from \"./behaviors/scale-feature.behavior\";\nimport { FeatureId, GeoJSONStoreFeatures } from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tDragCoordinateResizeBehavior,\n\tResizeOptions,\n} from \"./behaviors/drag-coordinate-resize.behavior\";\nimport { CoordinatePointBehavior } from \"./behaviors/coordinate-point.behavior\";\nimport { CoordinateSnappingBehavior } from \"../coordinate-snapping.behavior\";\nimport { LineSnappingBehavior } from \"../line-snapping.behavior\";\n\ntype TerraDrawSelectModeKeyEvents = {\n\tdeselect: KeyboardEvent[\"key\"] | null;\n\tdelete: KeyboardEvent[\"key\"] | null;\n\trotate: KeyboardEvent[\"key\"][] | null;\n\tscale: KeyboardEvent[\"key\"][] | null;\n};\n\nconst defaultKeyEvents = {\n\tdeselect: \"Escape\",\n\tdelete: \"Delete\",\n\trotate: [\"Control\", \"r\"],\n\tscale: [\"Control\", \"s\"],\n};\n\ntype ModeFlags = {\n\tfeature?: {\n\t\tvalidation?: Validation;\n\t\tdraggable?: boolean;\n\t\trotateable?: boolean;\n\t\tscaleable?: boolean;\n\t\tselfIntersectable?: boolean;\n\t\tcoordinates?: {\n\t\t\tsnappable?: boolean | Snapping;\n\t\t\tmidpoints?:\n\t\t\t\t| boolean\n\t\t\t\t| {\n\t\t\t\t\t\tdraggable?: boolean;\n\t\t\t\t  };\n\t\t\tdraggable?: boolean;\n\t\t\tresizable?: ResizeOptions;\n\t\t\tdeletable?: boolean;\n\t\t};\n\t};\n};\n\ntype SelectionStyling = {\n\t// Point\n\tselectedPointColor: HexColorStyling;\n\tselectedPointWidth: NumericStyling;\n\tselectedPointOutlineColor: HexColorStyling;\n\tselectedPointOutlineWidth: NumericStyling;\n\n\t// LineString\n\tselectedLineStringColor: HexColorStyling;\n\tselectedLineStringWidth: NumericStyling;\n\n\t// Polygon\n\tselectedPolygonColor: HexColorStyling;\n\tselectedPolygonFillOpacity: NumericStyling;\n\tselectedPolygonOutlineColor: HexColorStyling;\n\tselectedPolygonOutlineWidth: NumericStyling;\n\n\t// Selection Points (points at vertices of a polygon/linestring feature)\n\tselectionPointWidth: NumericStyling;\n\tselectionPointColor: HexColorStyling;\n\tselectionPointOutlineColor: HexColorStyling;\n\tselectionPointOutlineWidth: NumericStyling;\n\n\t// Mid points (points at mid point of a polygon/linestring feature)\n\tmidPointColor: HexColorStyling;\n\tmidPointOutlineColor: HexColorStyling;\n\tmidPointWidth: NumericStyling;\n\tmidPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tpointerOver?: Cursor;\n\tdragStart?: Cursor;\n\tdragEnd?: Cursor;\n\tinsertMidpoint?: Cursor;\n}\n\nconst defaultCursors = {\n\tpointerOver: \"move\",\n\tdragStart: \"move\",\n\tdragEnd: \"move\",\n\tinsertMidpoint: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawSelectModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tpointerDistance?: number;\n\tflags?: { [mode: string]: ModeFlags };\n\tkeyEvents?: TerraDrawSelectModeKeyEvents | null;\n\tdragEventThrottle?: number;\n\tcursors?: Cursors;\n\tallowManualDeselection?: boolean;\n}\n\nexport class TerraDrawSelectMode extends TerraDrawBaseSelectMode<SelectionStyling> {\n\tpublic mode = \"select\" as const;\n\n\tprivate allowManualDeselection = true;\n\tprivate dragEventThrottle = 5;\n\tprivate dragEventCount = 0;\n\tprivate selected: FeatureId[] = [];\n\n\tprivate flags: { [mode: string]: ModeFlags } = {};\n\tprivate keyEvents: TerraDrawSelectModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate validations: Record<string, Validation> = {};\n\n\t// Behaviors\n\tprivate selectionPoints!: SelectionPointBehavior;\n\tprivate midPoints!: MidPointBehavior;\n\tprivate coordinateSnap!: CoordinateSnappingBehavior;\n\tprivate featuresAtMouseEvent!: FeatureAtPointerEventBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\tprivate dragFeature!: DragFeatureBehavior;\n\tprivate dragCoordinate!: DragCoordinateBehavior;\n\tprivate rotateFeature!: RotateFeatureBehavior;\n\tprivate scaleFeature!: ScaleFeatureBehavior;\n\tprivate dragCoordinateResizeFeature!: DragCoordinateResizeBehavior;\n\tprivate coordinatePoints!: CoordinatePointBehavior;\n\tprivate lineSnap!: LineSnappingBehavior;\n\n\tconstructor(options?: TerraDrawSelectModeOptions<SelectionStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSelectModeOptions<SelectionStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options && options.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t} else {\n\t\t\tthis.cursors = defaultCursors;\n\t\t}\n\n\t\t// We want to have some defaults, but also allow key bindings\n\t\t// to be explicitly turned off\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = {\n\t\t\t\tdeselect: null,\n\t\t\t\tdelete: null,\n\t\t\t\trotate: null,\n\t\t\t\tscale: null,\n\t\t\t};\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.dragEventThrottle !== undefined) {\n\t\t\tthis.dragEventThrottle = options.dragEventThrottle;\n\t\t}\n\n\t\tif (options?.allowManualDeselection !== undefined) {\n\t\t\tthis.allowManualDeselection = options.allowManualDeselection;\n\t\t}\n\n\t\t// Flags and Validations\n\t\tif (options?.flags) {\n\t\t\tthis.flags = { ...this.flags, ...options.flags };\n\t\t\tthis.validations = {};\n\n\t\t\tfor (const mode in this.flags) {\n\t\t\t\tconst feature = this.flags[mode].feature;\n\t\t\t\tif (feature && feature.validation) {\n\t\t\t\t\tthis.validations[mode] = feature.validation;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tselectFeature(featureId: FeatureId) {\n\t\tthis.select(featureId, false);\n\t}\n\n\tsetSelecting() {\n\t\tif (this._state === \"started\") {\n\t\t\tthis._state = \"selecting\";\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be started to move to selecting state\");\n\t\t}\n\t}\n\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.featuresAtMouseEvent = new FeatureAtPointerEventBehavior(\n\t\t\tconfig,\n\t\t\tthis.clickBoundingBox,\n\t\t\tthis.pixelDistance,\n\t\t);\n\n\t\tthis.selectionPoints = new SelectionPointBehavior(config);\n\t\tthis.coordinatePoints = new CoordinatePointBehavior(config);\n\t\tthis.midPoints = new MidPointBehavior(\n\t\t\tconfig,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.coordinatePoints,\n\t\t);\n\t\tthis.coordinateSnap = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.lineSnap = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.rotateFeature = new RotateFeatureBehavior(\n\t\t\tconfig,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\n\t\t\tthis.coordinatePoints,\n\t\t);\n\n\t\tthis.dragFeature = new DragFeatureBehavior(\n\t\t\tconfig,\n\t\t\tthis.featuresAtMouseEvent,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\n\t\t\tthis.coordinatePoints,\n\t\t);\n\t\tthis.dragCoordinate = new DragCoordinateBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\n\t\t\tthis.coordinatePoints,\n\t\t\tthis.coordinateSnap,\n\t\t\tthis.lineSnap,\n\t\t);\n\t\tthis.dragCoordinateResizeFeature = new DragCoordinateResizeBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\n\t\t\tthis.coordinatePoints,\n\t\t);\n\t\tthis.scaleFeature = new ScaleFeatureBehavior(\n\t\t\tconfig,\n\t\t\tthis.dragCoordinateResizeFeature,\n\t\t);\n\t}\n\n\tpublic deselectFeature() {\n\t\tthis.deselect();\n\t}\n\n\tprivate deselect() {\n\t\tconst updateSelectedFeatures = this.selected\n\t\t\t.filter((id) => this.store.has(id))\n\t\t\t.map((id) => ({\n\t\t\t\tid,\n\t\t\t\tproperty: SELECT_PROPERTIES.SELECTED,\n\t\t\t\tvalue: false,\n\t\t\t}));\n\n\t\tthis.store.updateProperty(updateSelectedFeatures);\n\n\t\tthis.onDeselect(this.selected[0]);\n\t\tthis.selected = [];\n\t\tthis.selectionPoints.delete();\n\t\tthis.midPoints.delete();\n\t}\n\n\tprivate deleteSelected() {\n\t\t// Delete all selected features\n\t\t// from the store and clear selected\n\t\t// We don't need to set selected false\n\t\t// as we're going to delete the feature\n\n\t\tthis.store.delete(this.selected);\n\t\tthis.selected = [];\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\tif (!this.selectionPoints.ids.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet clickedSelectionPointProps: SelectionPointProperties | undefined;\n\n\t\tlet clickedFeatureDistance = Infinity;\n\n\t\tthis.selectionPoints.ids.forEach((id) => {\n\t\t\tconst geometry = this.store.getGeometryCopy<Point>(id);\n\t\t\tconst distance = this.pixelDistance.measure(event, geometry.coordinates);\n\n\t\t\tif (\n\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\tdistance < clickedFeatureDistance\n\t\t\t) {\n\t\t\t\tclickedFeatureDistance = distance;\n\t\t\t\tclickedSelectionPointProps = this.store.getPropertiesCopy(\n\t\t\t\t\tid,\n\t\t\t\t) as SelectionPointProperties;\n\t\t\t}\n\t\t});\n\n\t\tif (!clickedSelectionPointProps) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst featureId = clickedSelectionPointProps.selectionPointFeatureId;\n\t\tconst coordinateIndex = clickedSelectionPointProps.index;\n\n\t\t// We allow for preventing deleting coordinates via flags\n\t\tconst properties = this.store.getPropertiesCopy(featureId);\n\t\tconst modeFlags = this.flags[properties.mode as string];\n\t\tconst validation = this.validations[properties.mode as string];\n\n\t\t// Check if we can actually delete the coordinate\n\t\tconst cannotDelete =\n\t\t\t!modeFlags ||\n\t\t\t!modeFlags.feature ||\n\t\t\t!modeFlags.feature.coordinates ||\n\t\t\t!modeFlags.feature.coordinates.deletable;\n\n\t\tif (cannotDelete) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"Polygon\") {\n\t\t\tcoordinates = geometry.coordinates[0];\n\n\t\t\t// Prevent creating an invalid polygon\n\t\t\tif (coordinates.length <= 4) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else if (geometry.type === \"LineString\") {\n\t\t\tcoordinates = geometry.coordinates;\n\n\t\t\t// Prevent creating an invalid linestring\n\t\t\tif (coordinates.length <= 2) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Geometry is not Polygon or LineString\n\t\tif (!coordinates) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isFinalPolygonCoordinate =\n\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t(coordinateIndex === 0 || coordinateIndex === coordinates.length - 1);\n\n\t\tif (isFinalPolygonCoordinate) {\n\t\t\t// Deleting the final coordinate in a polygon breaks it\n\t\t\t// because GeoJSON expects a duplicate, so we need to fix\n\t\t\t// it by adding the new first coordinate to the end\n\t\t\tcoordinates.shift();\n\t\t\tcoordinates.pop();\n\t\t\tcoordinates.push([coordinates[0][0], coordinates[0][1]]);\n\t\t} else {\n\t\t\t// Remove coordinate from array\n\t\t\tcoordinates.splice(coordinateIndex, 1);\n\t\t}\n\n\t\t// Validate the new geometry\n\t\tif (validation) {\n\t\t\tconst validationResult = validation(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst deletePoints = [...this.midPoints.ids, ...this.selectionPoints.ids];\n\n\t\tthis.store.delete(deletePoints);\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tif (properties.coordinatePointIds) {\n\t\t\tthis.coordinatePoints.createOrUpdate(featureId);\n\t\t}\n\n\t\tthis.selectionPoints.create(\n\t\t\tcoordinates,\n\t\t\tgeometry.type as \"Polygon\" | \"LineString\",\n\t\t\tfeatureId,\n\t\t);\n\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.coordinates &&\n\t\t\tmodeFlags.feature.coordinates.midpoints\n\t\t) {\n\t\t\tthis.midPoints.create(coordinates, featureId, this.coordinatePrecision);\n\t\t}\n\t}\n\n\tprivate select(featureId: FeatureId, fromCursor = true) {\n\t\tif (this.selected[0] === featureId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { mode } = this.store.getPropertiesCopy(featureId);\n\n\t\t// This will be undefined for points\n\t\tconst modeFlags = this.flags[mode as string];\n\n\t\t// If feature is not selectable then return\n\t\tif (!modeFlags || !modeFlags.feature) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst previouslySelectedId = this.selected[0];\n\n\t\t// If we have something currently selected\n\t\tif (previouslySelectedId) {\n\t\t\t// If it matches the current selected feature id, do nothing\n\t\t\tif (previouslySelectedId === featureId) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t// If it's a different feature set selected\n\t\t\t\t// to false on previously selected feature\n\t\t\t\tthis.deselect();\n\t\t\t}\n\t\t}\n\n\t\tif (fromCursor) {\n\t\t\tthis.setCursor(this.cursors.pointerOver);\n\t\t}\n\n\t\t// Select feature\n\t\tthis.selected = [featureId];\n\n\t\tthis.store.updateProperty([\n\t\t\t{ id: featureId, property: SELECT_PROPERTIES.SELECTED, value: true },\n\t\t]);\n\t\tthis.onSelect(featureId);\n\n\t\t// Get the clicked feature\n\t\tconst { type, coordinates } = this.store.getGeometryCopy(featureId);\n\n\t\tif (type !== \"LineString\" && type !== \"Polygon\") {\n\t\t\treturn;\n\t\t}\n\n\t\t// LineString does not have nesting so we can just take 'coordinates'\n\t\t// directly. Polygon is nested so we need to take [0] item in the array\n\t\tconst selectedCoords: Position[] =\n\t\t\ttype === \"LineString\" ? coordinates : coordinates[0];\n\n\t\tif (selectedCoords && modeFlags && modeFlags.feature.coordinates) {\n\t\t\tthis.selectionPoints.create(selectedCoords, type, featureId);\n\n\t\t\tif (modeFlags.feature.coordinates.midpoints) {\n\t\t\t\tthis.midPoints.create(\n\t\t\t\t\tselectedCoords,\n\t\t\t\t\tfeatureId,\n\t\t\t\t\tthis.coordinatePrecision,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\tconst { clickedFeature, clickedMidPoint } = this.featuresAtMouseEvent.find(\n\t\t\tevent,\n\t\t\tthis.selected.length > 0,\n\t\t);\n\n\t\tif (this.selected.length && clickedMidPoint) {\n\t\t\t// TODO: We probably want to make sure the midpoint\n\t\t\t// is visible?\n\n\t\t\tthis.midPoints.insert(\n\t\t\t\tthis.selected[0],\n\t\t\t\tclickedMidPoint.id as string,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (clickedFeature && clickedFeature.id) {\n\t\t\tthis.select(clickedFeature.id, true);\n\t\t} else if (this.selected.length && this.allowManualDeselection) {\n\t\t\tthis.deselect();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setSelecting();\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStarted();\n\t\tthis.setStopped();\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\tthis.onRightClick(event);\n\t\t} else if (\n\t\t\tevent.button === \"left\" &&\n\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)\n\t\t) {\n\t\t\tthis.onLeftClick(event);\n\t\t}\n\t}\n\n\tprivate canScale(event: TerraDrawKeyboardEvent | TerraDrawMouseEvent) {\n\t\treturn (\n\t\t\tthis.keyEvents.scale &&\n\t\t\tthis.keyEvents.scale.every((key) => event.heldKeys.includes(key))\n\t\t);\n\t}\n\n\tprivate canRotate(event: TerraDrawKeyboardEvent | TerraDrawMouseEvent) {\n\t\treturn (\n\t\t\tthis.keyEvents.rotate &&\n\t\t\tthis.keyEvents.rotate.every((key) => event.heldKeys.includes(key))\n\t\t);\n\t}\n\n\tprivate preventDefaultKeyEvent(event: TerraDrawKeyboardEvent) {\n\t\tconst isRotationKeys = this.canRotate(event);\n\t\tconst isScaleKeys = this.canScale(event);\n\n\t\t// If we are deliberately rotating or scaling then prevent default\n\t\tif (isRotationKeys || isScaleKeys) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown(event: TerraDrawKeyboardEvent) {\n\t\tthis.preventDefaultKeyEvent(event);\n\t}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tthis.preventDefaultKeyEvent(event);\n\n\t\tif (this.keyEvents.delete && event.key === this.keyEvents.delete) {\n\t\t\tif (!this.selected.length) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selectedId = this.selected[0];\n\n\t\t\t// We are technically deselecting\n\t\t\t// because the selected feature is deleted\n\t\t\t// and will no longer exist or be selected\n\t\t\tconst previouslySelected = this.selected[0];\n\t\t\tthis.onDeselect(previouslySelected);\n\n\t\t\t// Delete coordinate point first if they are present, this needs\n\t\t\t// to be done before deleting the feature\n\t\t\tthis.coordinatePoints.deletePointsByFeatureIds([selectedId]);\n\n\t\t\t// Delete all selected features\n\t\t\tthis.deleteSelected();\n\n\t\t\t// Remove all selection points\n\t\t\tthis.selectionPoints.delete();\n\t\t\tthis.midPoints.delete();\n\t\t} else if (\n\t\t\tthis.keyEvents.deselect &&\n\t\t\tevent.key === this.keyEvents.deselect\n\t\t) {\n\t\t\tthis.cleanUp();\n\t\t}\n\t}\n\n\t/** @internal */\n\tcleanUp() {\n\t\tif (this.selected.length) {\n\t\t\tthis.deselect();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragStart, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.selected.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the selected feature is not draggable\n\t\t// don't do anything\n\t\tconst properties = this.store.getPropertiesCopy(this.selected[0]);\n\t\tconst modeFlags = this.flags[properties.mode as string];\n\t\tconst draggable =\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\t(modeFlags.feature.draggable ||\n\t\t\t\t(modeFlags.feature.coordinates &&\n\t\t\t\t\tmodeFlags.feature.coordinates.draggable) ||\n\t\t\t\t(modeFlags.feature.coordinates &&\n\t\t\t\t\tmodeFlags.feature.coordinates.resizable) ||\n\t\t\t\t(modeFlags.feature.coordinates &&\n\t\t\t\t\ttypeof modeFlags.feature.coordinates.midpoints === \"object\" &&\n\t\t\t\t\tmodeFlags.feature.coordinates.midpoints.draggable));\n\n\t\tif (!draggable) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.dragEventCount = 0;\n\n\t\tconst selectedId = this.selected[0];\n\t\tconst draggableCoordinateIndex = this.dragCoordinate.getDraggableIndex(\n\t\t\tevent,\n\t\t\tselectedId,\n\t\t);\n\n\t\t// Drag Coordinate\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.coordinates &&\n\t\t\t(modeFlags.feature.coordinates.draggable ||\n\t\t\t\tmodeFlags.feature.coordinates.resizable) &&\n\t\t\tdraggableCoordinateIndex !== -1\n\t\t) {\n\t\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\t\t// With resizable\n\t\t\tif (modeFlags.feature.coordinates.resizable) {\n\t\t\t\tthis.dragCoordinateResizeFeature.startDragging(\n\t\t\t\t\tselectedId,\n\t\t\t\t\tdraggableCoordinateIndex,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Without with resizable being set\n\t\t\t\tthis.dragCoordinate.startDragging(selectedId, draggableCoordinateIndex);\n\t\t\t}\n\n\t\t\tsetMapDraggability(false);\n\t\t\treturn;\n\t\t}\n\n\t\t// Dragging Midpoint\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.coordinates &&\n\t\t\ttypeof modeFlags.feature.coordinates.midpoints === \"object\" &&\n\t\t\tmodeFlags.feature.coordinates.midpoints.draggable\n\t\t) {\n\t\t\tconst { clickedMidPoint: draggedMidPoint } =\n\t\t\t\tthis.featuresAtMouseEvent.find(event, this.selected.length > 0);\n\n\t\t\tif (this.selected.length && draggedMidPoint) {\n\t\t\t\t// We insert the midpoint first\n\t\t\t\tthis.midPoints.insert(\n\t\t\t\t\tselectedId,\n\t\t\t\t\tdraggedMidPoint.id as string,\n\t\t\t\t\tthis.coordinatePrecision,\n\t\t\t\t);\n\n\t\t\t\tconst draggableCoordinateIndexAfterInsert =\n\t\t\t\t\tthis.dragCoordinate.getDraggableIndex(event, selectedId);\n\n\t\t\t\tthis.dragCoordinate.startDragging(\n\t\t\t\t\tselectedId,\n\t\t\t\t\tdraggableCoordinateIndexAfterInsert,\n\t\t\t\t);\n\n\t\t\t\tsetMapDraggability(false);\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Drag Feature\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.draggable &&\n\t\t\tthis.dragFeature.canDrag(event, selectedId)\n\t\t) {\n\t\t\tthis.setCursor(this.cursors.dragStart);\n\t\t\tthis.dragFeature.startDragging(event, selectedId);\n\t\t\tsetMapDraggability(false);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDrag, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst selectedId = this.selected[0];\n\n\t\t// If nothing selected we can return early\n\t\tif (!selectedId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst properties = this.store.getPropertiesCopy(selectedId);\n\t\tconst modeFlags = this.flags[properties.mode as string];\n\t\tconst canSelfIntersect: boolean =\n\t\t\t(modeFlags &&\n\t\t\t\tmodeFlags.feature &&\n\t\t\t\tmodeFlags.feature.selfIntersectable) === true;\n\n\t\t// Ensure drag count is incremented\n\t\tthis.dragEventCount++;\n\n\t\t// Return if we haven't hit the drag throttle limit\n\t\t// (i.e. we only want to drag every nth event)\n\t\tif (this.dragEventCount % this.dragEventThrottle === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst validation = this.validations[properties.mode as string];\n\n\t\t// Check if should rotate\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.rotateable &&\n\t\t\tthis.canRotate(event)\n\t\t) {\n\t\t\tsetMapDraggability(false);\n\t\t\tthis.rotateFeature.rotate(event, selectedId, validation);\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if should scale\n\t\tif (\n\t\t\tmodeFlags &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.scaleable &&\n\t\t\tthis.canScale(event)\n\t\t) {\n\t\t\tsetMapDraggability(false);\n\n\t\t\tthis.scaleFeature.scale(event, selectedId, validation);\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tthis.dragCoordinateResizeFeature.isDragging() &&\n\t\t\tmodeFlags.feature &&\n\t\t\tmodeFlags.feature.coordinates &&\n\t\t\tmodeFlags.feature.coordinates.resizable\n\t\t) {\n\t\t\tif (this.projection === \"globe\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Globe is currently unsupported projection for resizable\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tsetMapDraggability(false);\n\t\t\tthis.dragCoordinateResizeFeature.drag(\n\t\t\t\tevent,\n\t\t\t\tmodeFlags.feature.coordinates.resizable,\n\t\t\t\tvalidation,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if coordinate is draggable and is dragged\n\t\tif (this.dragCoordinate.isDragging()) {\n\t\t\tconst snappable = modeFlags.feature?.coordinates?.snappable;\n\n\t\t\tlet snapOptions: Snapping = { toCoordinate: false };\n\t\t\tif (snappable === true) {\n\t\t\t\tsnapOptions = { toCoordinate: true };\n\t\t\t} else if (typeof snappable === \"object\") {\n\t\t\t\tsnapOptions = snappable;\n\t\t\t}\n\n\t\t\tthis.dragCoordinate.drag(\n\t\t\t\tevent,\n\t\t\t\tcanSelfIntersect,\n\t\t\t\tvalidation,\n\t\t\t\tsnapOptions,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if feature is draggable and is dragged\n\t\tif (this.dragFeature.isDragging()) {\n\t\t\tthis.dragFeature.drag(event, validation);\n\t\t\treturn;\n\t\t}\n\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (!this.allowPointerEvent(this.pointerEvents.onDragEnd, event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setCursor(this.cursors.dragEnd);\n\n\t\t// If we have finished dragging a coordinate or a feature\n\t\t// lets fire an onFinish event which can be listened to\n\t\tif (this.dragCoordinate.isDragging()) {\n\t\t\tthis.onFinish(this.selected[0], {\n\t\t\t\tmode: this.mode,\n\t\t\t\taction: \"dragCoordinate\",\n\t\t\t});\n\t\t} else if (this.dragFeature.isDragging()) {\n\t\t\tthis.onFinish(this.selected[0], {\n\t\t\t\tmode: this.mode,\n\t\t\t\taction: \"dragFeature\",\n\t\t\t});\n\t\t} else if (this.dragCoordinateResizeFeature.isDragging()) {\n\t\t\tthis.onFinish(this.selected[0], {\n\t\t\t\tmode: this.mode,\n\t\t\t\taction: \"dragCoordinateResize\",\n\t\t\t});\n\t\t}\n\n\t\tthis.dragCoordinate.stopDragging();\n\t\tthis.dragFeature.stopDragging();\n\t\tthis.dragCoordinateResizeFeature.stopDragging();\n\t\tthis.rotateFeature.reset();\n\t\tthis.scaleFeature.reset();\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tif (!this.selected.length) {\n\t\t\tthis.setCursor(\"unset\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.dragFeature.isDragging()) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet nearbyMidPoint = false;\n\t\tthis.midPoints.ids.forEach((id: string) => {\n\t\t\tif (nearbyMidPoint) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst geometry = this.store.getGeometryCopy<Point>(id);\n\t\t\tconst distance = this.pixelDistance.measure(event, geometry.coordinates);\n\n\t\t\tif (distance < this.pointerDistance) {\n\t\t\t\tnearbyMidPoint = true;\n\t\t\t}\n\t\t});\n\n\t\tlet nearbySelectionPoint = false;\n\t\t// TODO: Is there a cleaner way to handle prioritising\n\t\t// dragging selection points?\n\t\tthis.selectionPoints.ids.forEach((id: FeatureId) => {\n\t\t\tconst geometry = this.store.getGeometryCopy<Point>(id);\n\t\t\tconst distance = this.pixelDistance.measure(event, geometry.coordinates);\n\t\t\tif (distance < this.pointerDistance) {\n\t\t\t\tnearbyMidPoint = false;\n\t\t\t\tnearbySelectionPoint = true;\n\t\t\t}\n\t\t});\n\n\t\tif (nearbyMidPoint) {\n\t\t\tthis.setCursor(this.cursors.insertMidpoint);\n\t\t\treturn;\n\t\t}\n\n\t\t// If we have a feature under the pointer then show the pointer over cursor\n\t\tconst { clickedFeature: featureUnderPointer } =\n\t\t\tthis.featuresAtMouseEvent.find(event, true);\n\n\t\tif (\n\t\t\tthis.selected.length > 0 &&\n\t\t\t((featureUnderPointer && featureUnderPointer.id === this.selected[0]) ||\n\t\t\t\tnearbySelectionPoint)\n\t\t) {\n\t\t\tthis.setCursor(this.cursors.pointerOver);\n\t\t} else {\n\t\t\t// Set it back to whatever the default cursor is\n\t\t\tthis.setCursor(\"unset\");\n\t\t}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (\n\t\t\tfeature.properties.mode === this.mode &&\n\t\t\tfeature.geometry.type === \"Point\"\n\t\t) {\n\t\t\tif (feature.properties.selectionPoint) {\n\t\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectionPointColor,\n\t\t\t\t\tstyles.pointColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectionPointOutlineColor,\n\t\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectionPointWidth,\n\t\t\t\t\tstyles.pointWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectionPointOutlineWidth,\n\t\t\t\t\t2,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_THREE;\n\n\t\t\t\treturn styles;\n\t\t\t}\n\n\t\t\tif (feature.properties.midPoint) {\n\t\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.midPointColor,\n\t\t\t\t\tstyles.pointColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.midPointOutlineColor,\n\t\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.midPointWidth,\n\t\t\t\t\t4,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.midPointOutlineWidth,\n\t\t\t\t\t2,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_FIVE;\n\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t} else if (feature.properties[SELECT_PROPERTIES.SELECTED]) {\n\t\t\t// Select mode shortcuts the styling of a feature if it is selected\n\t\t\t// A selected feature from another mode will end up in this block\n\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectedPolygonColor,\n\t\t\t\t\tstyles.polygonFillColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectedPolygonOutlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectedPolygonOutlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectedPolygonFillOpacity,\n\t\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t\treturn styles;\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tstyles.lineStringColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectedLineStringColor,\n\t\t\t\t\tstyles.lineStringColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.lineStringWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectedLineStringWidth,\n\t\t\t\t\tstyles.lineStringWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t\treturn styles;\n\t\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectedPointWidth,\n\t\t\t\t\tstyles.pointWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectedPointColor,\n\t\t\t\t\tstyles.pointColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.selectedPointOutlineColor,\n\t\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.selectedPointOutlineWidth,\n\t\t\t\t\tstyles.pointOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../../common\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { ModeTypes, TerraDrawBaseDrawMode } from \"../base.mode\";\n\ntype StaticModeStylingExt<T extends TerraDrawAdapterStyling> = {};\ntype StaticModeStyling = StaticModeStylingExt<TerraDrawAdapterStyling>;\n\nexport class TerraDrawStaticMode extends TerraDrawBaseDrawMode<StaticModeStyling> {\n\ttype = ModeTypes.Static;\n\tmode = \"static\" as const;\n\tstart() {}\n\tstop() {}\n\tonKeyUp() {}\n\tonKeyDown() {}\n\tonClick() {}\n\tonDragStart() {}\n\tonDrag() {}\n\tonDragEnd() {}\n\tonMouseMove() {}\n\tcleanUp() {}\n\tstyleFeature() {\n\t\treturn { ...getDefaultStyling() };\n\t}\n}\n","// ISC License\n// Copyright (c) 2018, Vladimir Agafonkin\n\nexport type CompareFunction<T> = (a: T, b: T) => number;\n\nexport function quickselect<T>(\n\tarr: T[],\n\tk: number,\n\tleft: number,\n\tright: number,\n\tcompare: CompareFunction<T>,\n) {\n\twhile (right > left) {\n\t\tif (right - left > 600) {\n\t\t\tconst n = right - left + 1;\n\t\t\tconst m = k - left + 1;\n\t\t\tconst z = Math.log(n);\n\t\t\tconst s = 0.5 * Math.exp((2 * z) / 3);\n\t\t\tconst sd =\n\t\t\t\t0.5 * Math.sqrt((z * s * (n - s)) / n) * (m - n / 2 < 0 ? -1 : 1);\n\t\t\tconst newLeft = Math.max(left, Math.floor(k - (m * s) / n + sd));\n\t\t\tconst newRight = Math.min(right, Math.floor(k + ((n - m) * s) / n + sd));\n\t\t\tquickselect(arr, k, newLeft, newRight, compare);\n\t\t}\n\n\t\tconst t = arr[k];\n\t\tlet i = left;\n\t\tlet j = right;\n\n\t\tswap(arr, left, k);\n\t\tif (compare(arr[right], t) > 0) swap(arr, left, right);\n\n\t\twhile (i < j) {\n\t\t\tswap(arr, i, j);\n\t\t\ti++;\n\t\t\tj--;\n\t\t\twhile (compare(arr[i], t) < 0) i++;\n\t\t\twhile (compare(arr[j], t) > 0) j--;\n\t\t}\n\n\t\tif (compare(arr[left], t) === 0) {\n\t\t\tswap(arr, left, j);\n\t\t} else {\n\t\t\tj++;\n\t\t\tswap(arr, j, right);\n\t\t}\n\n\t\tif (j <= k) left = j + 1;\n\t\tif (k <= j) right = j - 1;\n\t}\n}\n\nfunction swap<T>(arr: T[], i: number, j: number) {\n\tconst tmp = arr[i];\n\tarr[i] = arr[j];\n\tarr[j] = tmp;\n}\n","// Base on Rbush - https://github.com/mourner/rbush\n// MIT License\n// Copyright (c) 2016 Vladimir Agafonkin\n\nimport { CompareFunction, quickselect } from \"./quickselect\";\n\nexport type Node = {\n\tchildren: Node[];\n\theight: number;\n\tleaf: boolean;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n};\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node: Node, toBBox: (node: Node) => any) {\n\tdistBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(\n\tnode: Node,\n\tk: number,\n\tp: number,\n\ttoBBox: (node: Node) => Node,\n\tdestNode?: Node,\n) {\n\tif (!destNode) destNode = createNode([]);\n\tdestNode.minX = Infinity;\n\tdestNode.minY = Infinity;\n\tdestNode.maxX = -Infinity;\n\tdestNode.maxY = -Infinity;\n\n\tfor (let i = k; i < p; i++) {\n\t\tconst child = node.children[i];\n\t\textend(destNode, node.leaf ? toBBox(child) : child);\n\t}\n\n\treturn destNode;\n}\n\nfunction extend(a: Node, b: Node) {\n\ta.minX = Math.min(a.minX, b.minX);\n\ta.minY = Math.min(a.minY, b.minY);\n\ta.maxX = Math.max(a.maxX, b.maxX);\n\ta.maxY = Math.max(a.maxY, b.maxY);\n\treturn a;\n}\n\nfunction compareNodeMinX(a: Node, b: Node) {\n\treturn a.minX - b.minX;\n}\nfunction compareNodeMinY(a: Node, b: Node) {\n\treturn a.minY - b.minY;\n}\n\nfunction bboxArea(a: Node) {\n\treturn (a.maxX - a.minX) * (a.maxY - a.minY);\n}\nfunction bboxMargin(a: {\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}) {\n\treturn a.maxX - a.minX + (a.maxY - a.minY);\n}\n\nfunction enlargedArea(a: Node, b: Node) {\n\treturn (\n\t\t(Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n\t\t(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY))\n\t);\n}\n\nfunction intersectionArea(a: Node, b: Node) {\n\tconst minX = Math.max(a.minX, b.minX);\n\tconst minY = Math.max(a.minY, b.minY);\n\tconst maxX = Math.min(a.maxX, b.maxX);\n\tconst maxY = Math.min(a.maxY, b.maxY);\n\n\treturn Math.max(0, maxX - minX) * Math.max(0, maxY - minY);\n}\n\nfunction contains(a: Node, b: Node) {\n\treturn (\n\t\ta.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY\n\t);\n}\n\nfunction intersects(a: Node, b: Node) {\n\treturn (\n\t\tb.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY\n\t);\n}\n\nfunction createNode(children: Node[]) {\n\treturn {\n\t\tchildren,\n\t\theight: 1,\n\t\tleaf: true,\n\t\tminX: Infinity,\n\t\tminY: Infinity,\n\t\tmaxX: -Infinity,\n\t\tmaxY: -Infinity,\n\t};\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect<T>(\n\tarr: T[],\n\tleft: number,\n\tright: number,\n\tn: number,\n\tcompare: CompareFunction<T>,\n) {\n\tconst stack = [left, right];\n\n\twhile (stack.length) {\n\t\tright = stack.pop() as number;\n\t\tleft = stack.pop() as number;\n\n\t\tif (right - left <= n) continue;\n\n\t\tconst mid = left + Math.ceil((right - left) / n / 2) * n;\n\t\tquickselect(arr, mid, left, right, compare);\n\n\t\tstack.push(left, mid, mid, right);\n\t}\n}\n\nexport class RBush {\n\tprivate _maxEntries: number;\n\tprivate _minEntries: number;\n\tprivate data!: Node;\n\n\tconstructor(maxEntries: number) {\n\t\t// max entries in a node is 9 by default; min node fill is 40% for best performance\n\t\tthis._maxEntries = Math.max(4, maxEntries);\n\t\tthis._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n\t\tthis.clear();\n\t}\n\n\tsearch(bbox: Node): Node[] {\n\t\tlet node = this.data;\n\t\tconst result: Node[] = [];\n\n\t\tif (!intersects(bbox, node)) {\n\t\t\treturn result;\n\t\t}\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst nodesToSearch = [];\n\n\t\twhile (node) {\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\t\t\t\tconst childBBox = node.leaf ? toBBox(child) : child;\n\n\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\tif (node.leaf) result.push(child);\n\t\t\t\t\telse if (contains(bbox, childBBox)) this._all(child, result);\n\t\t\t\t\telse nodesToSearch.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tcollides(bbox: Node) {\n\t\tlet node = this.data;\n\n\t\tconst intersect = intersects(bbox, node);\n\t\tif (intersect) {\n\t\t\tconst nodesToSearch = [];\n\t\t\twhile (node) {\n\t\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\t\tconst child = node.children[i];\n\t\t\t\t\tconst childBBox = node.leaf ? this.toBBox(child) : child;\n\n\t\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\t\tif (node.leaf || contains(bbox, childBBox)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnodesToSearch.push(child);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tload(data: Node[]): void {\n\t\tif (data.length < this._minEntries) {\n\t\t\tfor (let i = 0; i < data.length; i++) {\n\t\t\t\tthis.insert(data[i]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// recursively build the tree with the given data from scratch using OMT algorithm\n\t\tlet node = this._build(data.slice(), 0, data.length - 1, 0);\n\n\t\tif (!this.data.children.length) {\n\t\t\t// save as is if tree is empty\n\t\t\tthis.data = node;\n\t\t} else if (this.data.height === node.height) {\n\t\t\t// split root if trees have the same height\n\t\t\tthis._splitRoot(this.data, node);\n\t\t} else {\n\t\t\tif (this.data.height < node.height) {\n\t\t\t\t// swap trees if inserted one is bigger\n\t\t\t\tconst tmpNode = this.data;\n\t\t\t\tthis.data = node;\n\t\t\t\tnode = tmpNode;\n\t\t\t}\n\n\t\t\t// insert the small tree into the large tree at appropriate level\n\t\t\tthis._insert(node, this.data.height - node.height - 1, true);\n\t\t}\n\t}\n\n\tinsert(item: Node): void {\n\t\tthis._insert(item, this.data.height - 1);\n\t}\n\n\tclear(): void {\n\t\tthis.data = createNode([]);\n\t}\n\n\tremove(item: Node): void {\n\t\tlet node: Node | null = this.data;\n\t\tconst bbox = this.toBBox(item);\n\t\tconst path = [];\n\t\tconst indexes: number[] = [];\n\t\tlet i: number | undefined;\n\t\tlet parent: Node | undefined;\n\t\tlet goingUp = false;\n\n\t\t// depth-first iterative tree traversal\n\t\twhile (node || path.length) {\n\t\t\tif (!node) {\n\t\t\t\t// go up\n\t\t\t\tnode = path.pop() as Node;\n\t\t\t\tparent = path[path.length - 1];\n\t\t\t\ti = indexes.pop() as number;\n\t\t\t\tgoingUp = true;\n\t\t\t}\n\n\t\t\tif (node.leaf) {\n\t\t\t\t// check current node\n\n\t\t\t\tconst index = node.children.indexOf(item);\n\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\t// item found, remove the item and condense tree upwards\n\t\t\t\t\tnode.children.splice(index, 1);\n\t\t\t\t\tpath.push(node);\n\t\t\t\t\tthis._condense(path);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!goingUp && !node.leaf && contains(node, bbox)) {\n\t\t\t\t// go down\n\t\t\t\tpath.push(node);\n\t\t\t\tindexes.push(i as number);\n\t\t\t\ti = 0;\n\t\t\t\tparent = node;\n\t\t\t\tnode = node.children[0];\n\t\t\t} else if (parent) {\n\t\t\t\t// go right\n\t\t\t\t(i as number)++;\n\t\t\t\tnode = parent.children[i as number];\n\t\t\t\tgoingUp = false;\n\t\t\t} else {\n\t\t\t\tnode = null; // nothing found\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate toBBox<T>(item: T): T {\n\t\treturn item;\n\t}\n\n\tprivate compareMinX(a: Node, b: Node) {\n\t\treturn a.minX - b.minX;\n\t}\n\tprivate compareMinY(a: Node, b: Node) {\n\t\treturn a.minY - b.minY;\n\t}\n\n\tprivate _all(node: Node, result: Node[]) {\n\t\tconst nodesToSearch = [];\n\t\twhile (node) {\n\t\t\tif (node.leaf) result.push(...node.children);\n\t\t\telse nodesToSearch.push(...node.children);\n\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _build(items: Node[], left: number, right: number, height: number) {\n\t\tconst N = right - left + 1;\n\t\tlet M = this._maxEntries;\n\t\tlet node;\n\n\t\tif (N <= M) {\n\t\t\t// reached leaf level; return leaf\n\t\t\tnode = createNode(items.slice(left, right + 1));\n\t\t\tcalcBBox(node, this.toBBox);\n\t\t\treturn node;\n\t\t}\n\n\t\tif (!height) {\n\t\t\t// target height of the bulk-loaded tree\n\t\t\theight = Math.ceil(Math.log(N) / Math.log(M));\n\n\t\t\t// target number of root entries to maximize storage utilization\n\t\t\tM = Math.ceil(N / Math.pow(M, height - 1));\n\t\t}\n\n\t\tnode = createNode([]);\n\t\tnode.leaf = false;\n\t\tnode.height = height;\n\n\t\t// split the items into M mostly square tiles\n\n\t\tconst N2 = Math.ceil(N / M);\n\t\tconst N1 = N2 * Math.ceil(Math.sqrt(M));\n\n\t\tmultiSelect(items, left, right, N1, this.compareMinX);\n\n\t\tfor (let i = left; i <= right; i += N1) {\n\t\t\tconst right2 = Math.min(i + N1 - 1, right);\n\n\t\t\tmultiSelect(items, i, right2, N2, this.compareMinY);\n\n\t\t\tfor (let j = i; j <= right2; j += N2) {\n\t\t\t\tconst right3 = Math.min(j + N2 - 1, right2);\n\n\t\t\t\t// pack each entry recursively\n\t\t\t\tnode.children.push(this._build(items, j, right3, height - 1));\n\t\t\t}\n\t\t}\n\n\t\tcalcBBox(node, this.toBBox);\n\n\t\treturn node;\n\t}\n\n\tprivate _chooseSubtree(bbox: Node, node: Node, level: number, path: Node[]) {\n\t\twhile (true) {\n\t\t\tpath.push(node);\n\n\t\t\tif (node.leaf || path.length - 1 === level) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet minArea = Infinity;\n\t\t\tlet minEnlargement = Infinity;\n\t\t\tlet targetNode;\n\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\n\t\t\t\tconst area = bboxArea(child);\n\t\t\t\tconst enlargement = enlargedArea(bbox, child) - area;\n\n\t\t\t\t// choose entry with the least area enlargement\n\n\t\t\t\tif (enlargement < minEnlargement) {\n\t\t\t\t\tminEnlargement = enlargement;\n\t\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t\t\ttargetNode = child;\n\t\t\t\t} else if (enlargement === minEnlargement) {\n\t\t\t\t\t// otherwise choose one with the smallest area\n\t\t\t\t\tif (area < minArea) {\n\t\t\t\t\t\tminArea = area;\n\t\t\t\t\t\ttargetNode = child;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnode = targetNode || node.children[0];\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate _insert(item: Node, level: number, isNode?: boolean) {\n\t\tconst bbox = isNode ? item : this.toBBox(item);\n\t\tconst insertPath: Node[] = [];\n\n\t\t// find the best node for accommodating the item, saving all nodes along the path too\n\t\tconst node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n\t\t// put the item into the node\n\t\tnode.children.push(item);\n\t\textend(node, bbox);\n\n\t\t// split on node overflow; propagate upwards if necessary\n\t\twhile (level >= 0) {\n\t\t\tif (insertPath[level].children.length > this._maxEntries) {\n\t\t\t\tthis._split(insertPath, level);\n\t\t\t\tlevel--;\n\t\t\t} else break;\n\t\t}\n\n\t\t// adjust bboxes along the insertion path\n\t\tthis._adjustParentBBoxes(bbox, insertPath, level);\n\t}\n\n\t// split overflowed node into two\n\tprivate _split(insertPath: Node[], level: number) {\n\t\tconst node = insertPath[level];\n\t\tconst M = node.children.length;\n\t\tconst m = this._minEntries;\n\n\t\tthis._chooseSplitAxis(node, m, M);\n\n\t\tconst splitIndex = this._chooseSplitIndex(node, m, M);\n\n\t\tconst newNode = createNode(\n\t\t\tnode.children.splice(splitIndex, node.children.length - splitIndex),\n\t\t);\n\t\tnewNode.height = node.height;\n\t\tnewNode.leaf = node.leaf;\n\n\t\tcalcBBox(node, this.toBBox);\n\t\tcalcBBox(newNode, this.toBBox);\n\n\t\tif (level) insertPath[level - 1].children.push(newNode);\n\t\telse this._splitRoot(node, newNode);\n\t}\n\n\tprivate _splitRoot(node: Node, newNode: Node) {\n\t\t// split root node\n\t\tthis.data = createNode([node, newNode]);\n\t\tthis.data.height = node.height + 1;\n\t\tthis.data.leaf = false;\n\t\tcalcBBox(this.data, this.toBBox);\n\t}\n\n\tprivate _chooseSplitIndex(node: Node, m: number, M: number) {\n\t\tlet index;\n\t\tlet minOverlap = Infinity;\n\t\tlet minArea = Infinity;\n\n\t\tfor (let i = m; i <= M - m; i++) {\n\t\t\tconst bbox1 = distBBox(node, 0, i, this.toBBox);\n\t\t\tconst bbox2 = distBBox(node, i, M, this.toBBox);\n\n\t\t\tconst overlap = intersectionArea(bbox1, bbox2);\n\t\t\tconst area = bboxArea(bbox1) + bboxArea(bbox2);\n\n\t\t\t// choose distribution with minimum overlap\n\t\t\tif (overlap < minOverlap) {\n\t\t\t\tminOverlap = overlap;\n\t\t\t\tindex = i;\n\n\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t} else if (overlap === minOverlap) {\n\t\t\t\t// otherwise choose distribution with minimum area\n\t\t\t\tif (area < minArea) {\n\t\t\t\t\tminArea = area;\n\t\t\t\t\tindex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn index || M - m;\n\t}\n\n\t// sorts node children by the best axis for split\n\tprivate _chooseSplitAxis(node: Node, m: number, M: number) {\n\t\tconst compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n\t\tconst compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n\t\tconst xMargin = this._allDistMargin(node, m, M, compareMinX);\n\t\tconst yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n\t\t// if total distributions margin value is minimal for x, sort by minX,\n\t\t// otherwise it's already sorted by minY\n\t\tif (xMargin < yMargin) {\n\t\t\tnode.children.sort(compareMinX);\n\t\t}\n\t}\n\n\t// total margin of all possible split distributions where each node is at least m full\n\tprivate _allDistMargin(\n\t\tnode: Node,\n\t\tm: number,\n\t\tM: number,\n\t\tcompare: CompareFunction<Node>,\n\t) {\n\t\tnode.children.sort(compare);\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst leftBBox = distBBox(node, 0, m, toBBox);\n\t\tconst rightBBox = distBBox(node, M - m, M, toBBox);\n\t\tlet margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n\t\tfor (let i = m; i < M - m; i++) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(leftBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(leftBBox);\n\t\t}\n\n\t\tfor (let i = M - m - 1; i >= m; i--) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(rightBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(rightBBox);\n\t\t}\n\n\t\treturn margin;\n\t}\n\n\tprivate _adjustParentBBoxes(bbox: Node, path: Node[], level: number) {\n\t\t// adjust bboxes along the given tree path\n\t\tfor (let i = level; i >= 0; i--) {\n\t\t\textend(path[i], bbox);\n\t\t}\n\t}\n\n\tprivate _condense(path: Node[]) {\n\t\t// go through the path, removing empty nodes and updating bboxes\n\t\tfor (let i = path.length - 1, siblings; i >= 0; i--) {\n\t\t\tif (path[i].children.length === 0) {\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tsiblings = path[i - 1].children;\n\t\t\t\t\tsiblings.splice(siblings.indexOf(path[i]), 1);\n\t\t\t\t} else this.clear();\n\t\t\t} else {\n\t\t\t\tcalcBBox(path[i], this.toBBox);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Position } from \"geojson\";\nimport { FeatureId, GeoJSONStoreFeatures } from \"../store\";\nimport { RBush, Node } from \"./rbush\";\n\nexport class SpatialIndex {\n\tprivate tree: RBush;\n\tprivate idToNode: Map<FeatureId, Node>;\n\tprivate nodeToId: Map<Node, FeatureId>;\n\n\tconstructor(options?: { maxEntries: number }) {\n\t\tthis.tree = new RBush(\n\t\t\toptions && options.maxEntries ? options.maxEntries : 9,\n\t\t);\n\t\tthis.idToNode = new Map();\n\t\tthis.nodeToId = new Map();\n\t}\n\n\tprivate setMaps(feature: GeoJSONStoreFeatures, bbox: Node) {\n\t\tthis.idToNode.set(feature.id as FeatureId, bbox);\n\t\tthis.nodeToId.set(bbox, feature.id as FeatureId);\n\t}\n\n\tprivate toBBox(feature: GeoJSONStoreFeatures) {\n\t\tconst longitudes: number[] = [];\n\t\tconst latitudes: number[] = [];\n\n\t\tlet coordinates: Position[];\n\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\tcoordinates = [feature.geometry.coordinates];\n\t\t} else {\n\t\t\tthrow new Error(\"Not a valid feature to turn into a bounding box\");\n\t\t}\n\n\t\tfor (let i = 0; i < coordinates.length; i++) {\n\t\t\tlatitudes.push(coordinates[i][1]);\n\t\t\tlongitudes.push(coordinates[i][0]);\n\t\t}\n\n\t\tconst minLat = Math.min(...latitudes);\n\t\tconst maxLat = Math.max(...latitudes);\n\t\tconst minLng = Math.min(...longitudes);\n\t\tconst maxLng = Math.max(...longitudes);\n\n\t\treturn {\n\t\t\tminX: minLng,\n\t\t\tminY: minLat,\n\t\t\tmaxX: maxLng,\n\t\t\tmaxY: maxLat,\n\t\t} as Node;\n\t}\n\n\tinsert(feature: GeoJSONStoreFeatures): void {\n\t\tif (this.idToNode.get(String(feature.id))) {\n\t\t\tthrow new Error(\"Feature already exists\");\n\t\t}\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tload(features: GeoJSONStoreFeatures[]): void {\n\t\tconst load: Node[] = [];\n\t\tconst seenIds: Set<string> = new Set();\n\t\tfeatures.forEach((feature) => {\n\t\t\tconst bbox = this.toBBox(feature);\n\t\t\tthis.setMaps(feature, bbox);\n\t\t\tif (seenIds.has(String(feature.id))) {\n\t\t\t\tthrow new Error(`Duplicate feature ID found ${feature.id}`);\n\t\t\t}\n\t\t\tseenIds.add(String(feature.id));\n\t\t\tload.push(bbox);\n\t\t});\n\t\tthis.tree.load(load);\n\t}\n\n\tupdate(feature: GeoJSONStoreFeatures): void {\n\t\tthis.remove(feature.id as FeatureId);\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tremove(featureId: FeatureId): void {\n\t\tconst node = this.idToNode.get(featureId);\n\t\tif (!node) {\n\t\t\tthrow new Error(`${featureId} not inserted into the spatial index`);\n\t\t}\n\n\t\tthis.tree.remove(node);\n\t}\n\n\tclear(): void {\n\t\tthis.tree.clear();\n\t}\n\n\tsearch(feature: GeoJSONStoreFeatures): FeatureId[] {\n\t\tconst found = this.tree.search(this.toBBox(feature));\n\t\treturn found.map((node) => {\n\t\t\treturn this.nodeToId.get(node) as FeatureId;\n\t\t});\n\t}\n\n\tcollides(feature: GeoJSONStoreFeatures): boolean {\n\t\treturn this.tree.collides(this.toBBox(feature));\n\t}\n}\n","import { Feature, Point, Polygon, LineString } from \"geojson\";\nimport { uuid4 } from \"../util/id\";\nimport { SpatialIndex } from \"./spatial-index/spatial-index\";\nimport { isValidTimestamp } from \"./store-feature-validation\";\nimport { Validation } from \"../common\";\n\ntype JSON = string | number | boolean | null | JSONArray | JSONObject;\n\nexport interface JSONObject {\n\t[member: string]: JSON;\n}\ntype JSONArray = Array<JSON>;\n\ntype DefinedProperties = Record<string, JSON>;\n\nexport type GeoJSONStoreGeometries = Polygon | LineString | Point;\n\nexport type BBoxPolygon = Feature<Polygon, DefinedProperties>;\n\nexport type GeoJSONStoreFeatures = Feature<\n\tGeoJSONStoreGeometries,\n\tDefinedProperties\n>;\n\nexport type StoreValidation = {\n\tid?: FeatureId;\n} & ReturnType<Validation>;\n\ntype StoreChangeEvents = \"delete\" | \"create\" | \"update\" | \"styling\";\n\nexport type StoreChangeHandler<OnChangeContext> = (\n\tids: FeatureId[],\n\tchange: StoreChangeEvents,\n\tcontext?: OnChangeContext,\n) => void;\n\nexport type FeatureId = string | number;\n\nexport type IdStrategy<Id extends FeatureId> = {\n\tisValidId: (id: Id) => boolean;\n\tgetId: () => Id;\n};\n\ntype GeoJSONStoreConfig<Id extends FeatureId> = {\n\tidStrategy?: IdStrategy<Id>;\n\ttracked?: boolean;\n};\n\nexport const defaultIdStrategy = {\n\tgetId: <FeatureId>() => uuid4() as FeatureId,\n\tisValidId: (id: FeatureId) => typeof id === \"string\" && id.length === 36,\n};\n\nexport class GeoJSONStore<\n\tOnChangeContext extends Record<string, JSON> | undefined,\n\tId extends FeatureId = FeatureId,\n> {\n\tconstructor(config?: GeoJSONStoreConfig<Id>) {\n\t\tthis.store = {};\n\t\tthis.spatialIndex = new SpatialIndex();\n\n\t\t// Setting tracked has to happen first\n\t\t// because we use it in featureValidation\n\t\tthis.tracked = config && config.tracked === false ? false : true;\n\t\tthis.idStrategy =\n\t\t\tconfig && config.idStrategy ? config.idStrategy : defaultIdStrategy;\n\t}\n\n\tpublic idStrategy: IdStrategy<Id>;\n\n\tprivate tracked: boolean;\n\n\tprivate spatialIndex: SpatialIndex;\n\n\tprivate store: {\n\t\t[key: FeatureId]: GeoJSONStoreFeatures;\n\t};\n\n\t// Default to no-op\n\tprivate _onChange: StoreChangeHandler<OnChangeContext | undefined> = () => {};\n\n\tprivate clone<T>(obj: T): T {\n\t\treturn JSON.parse(JSON.stringify(obj));\n\t}\n\n\tgetId(): FeatureId {\n\t\treturn this.idStrategy.getId();\n\t}\n\n\thas(id: FeatureId): boolean {\n\t\treturn Boolean(this.store[id]);\n\t}\n\n\tload(\n\t\tdata: GeoJSONStoreFeatures[],\n\t\tfeatureValidation?: (\n\t\t\tfeature: unknown,\n\t\t\ttracked?: boolean,\n\t\t) => StoreValidation,\n\t\tafterFeatureAdded?: (feature: GeoJSONStoreFeatures) => void,\n\t\tcontext?: OnChangeContext,\n\t): StoreValidation[] {\n\t\tif (data.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// We don't want to update the original data\n\t\tlet clonedData = this.clone(data);\n\n\t\tconst changes: FeatureId[] = []; // The list of changes that we will trigger to onChange\n\t\tconst validations: StoreValidation[] = []; // The list of validations that we will return\n\n\t\t// We filter out the features that are not valid and do not add them to the store\n\t\tclonedData = clonedData.filter((feature) => {\n\t\t\tif (feature.id === undefined || feature.id === null) {\n\t\t\t\tfeature.id = this.idStrategy.getId();\n\t\t\t}\n\n\t\t\tconst id = feature.id as FeatureId;\n\t\t\tif (featureValidation) {\n\t\t\t\tconst validation = featureValidation(feature);\n\n\t\t\t\t// Generic error handling if the featureValidation function\n\t\t\t\t// does not throw something more specific itself\n\t\t\t\tif (!validation.valid) {\n\t\t\t\t\tvalidations.push({ id, valid: false, reason: validation.reason });\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.tracked) {\n\t\t\t\tif (!feature.properties.createdAt) {\n\t\t\t\t\tfeature.properties.createdAt = +new Date();\n\t\t\t\t} else {\n\t\t\t\t\tconst valid = isValidTimestamp(feature.properties.createdAt);\n\t\t\t\t\tif (!valid) {\n\t\t\t\t\t\tvalidations.push({\n\t\t\t\t\t\t\tid: feature.id as FeatureId,\n\t\t\t\t\t\t\tvalid: false,\n\t\t\t\t\t\t\treason: \"createdAt is not a valid numeric timestamp\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!feature.properties.updatedAt) {\n\t\t\t\t\tfeature.properties.updatedAt = +new Date();\n\t\t\t\t} else {\n\t\t\t\t\tconst valid = isValidTimestamp(feature.properties.updatedAt);\n\t\t\t\t\tif (!valid) {\n\t\t\t\t\t\tvalidations.push({\n\t\t\t\t\t\t\tid: feature.id as FeatureId,\n\t\t\t\t\t\t\tvalid: false,\n\t\t\t\t\t\t\treason: \"updatedAt is not a valid numeric timestamp\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We have to be sure that the feature does not already exist with this ID\n\t\t\tif (this.has(id)) {\n\t\t\t\tvalidations.push({\n\t\t\t\t\tid,\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: `Feature already exists with this id: ${id}`,\n\t\t\t\t});\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis.store[id] = feature;\n\t\t\tchanges.push(id);\n\n\t\t\tafterFeatureAdded && afterFeatureAdded(feature);\n\n\t\t\tvalidations.push({ id, valid: true });\n\n\t\t\treturn true;\n\t\t});\n\t\tthis.spatialIndex.load(clonedData);\n\n\t\t// Only trigger onChange if we have changes\n\t\tif (changes.length > 0) {\n\t\t\tthis._onChange(changes, \"create\", context);\n\t\t}\n\n\t\treturn validations;\n\t}\n\n\tsearch(\n\t\tbbox: BBoxPolygon,\n\t\tfilter?: (feature: GeoJSONStoreFeatures) => boolean,\n\t) {\n\t\tconst features = this.spatialIndex.search(bbox).map((id) => this.store[id]);\n\t\tif (filter) {\n\t\t\treturn this.clone(features.filter(filter));\n\t\t} else {\n\t\t\treturn this.clone(features);\n\t\t}\n\t}\n\n\tregisterOnChange(onChange: StoreChangeHandler<OnChangeContext | undefined>) {\n\t\tthis._onChange = (ids, change, context) => {\n\t\t\tonChange(ids, change, context);\n\t\t};\n\t}\n\n\tgetGeometryCopy<T extends GeoJSONStoreGeometries>(id: FeatureId): T {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get geometry copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.geometry as T);\n\t}\n\n\tgetPropertiesCopy(id: FeatureId) {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get properties copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.properties);\n\t}\n\n\tupdateProperty(\n\t\tpropertiesToUpdate: { id: FeatureId; property: string; value: JSON }[],\n\t\tcontext?: OnChangeContext,\n\t): void {\n\t\tconst ids: FeatureId[] = [];\n\t\tpropertiesToUpdate.forEach(({ id, property, value }) => {\n\t\t\tconst feature = this.store[id];\n\n\t\t\tif (!feature) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No feature with this (${id}), can not update geometry`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tids.push(id);\n\n\t\t\tfeature.properties[property] = value;\n\n\t\t\t// Update the time the feature was updated\n\t\t\tif (this.tracked) {\n\t\t\t\tfeature.properties.updatedAt = +new Date();\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange(ids, \"update\", context);\n\t\t}\n\t}\n\n\tupdateGeometry(\n\t\tgeometriesToUpdate: { id: FeatureId; geometry: GeoJSONStoreGeometries }[],\n\t\tcontext?: OnChangeContext,\n\t): void {\n\t\tconst ids: FeatureId[] = [];\n\t\tgeometriesToUpdate.forEach(({ id, geometry }) => {\n\t\t\tids.push(id);\n\n\t\t\tconst feature = this.store[id];\n\n\t\t\tif (!feature) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No feature with this (${id}), can not update geometry`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tfeature.geometry = this.clone(geometry);\n\n\t\t\tthis.spatialIndex.update(feature);\n\n\t\t\t// Update the time the feature was updated\n\t\t\tif (this.tracked) {\n\t\t\t\tfeature.properties.updatedAt = +new Date();\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange(ids, \"update\", context);\n\t\t}\n\t}\n\n\tcreate<Id extends FeatureId>(\n\t\tfeatures: {\n\t\t\tgeometry: GeoJSONStoreGeometries;\n\t\t\tproperties?: JSONObject;\n\t\t}[],\n\t\tcontext?: OnChangeContext,\n\t): Id[] {\n\t\tconst ids: FeatureId[] = [];\n\t\tfeatures.forEach(({ geometry, properties }) => {\n\t\t\tlet createdAt;\n\t\t\tlet createdProperties = { ...properties };\n\n\t\t\tif (this.tracked) {\n\t\t\t\tcreatedAt = +new Date();\n\n\t\t\t\tif (properties) {\n\t\t\t\t\tcreatedProperties.createdAt =\n\t\t\t\t\t\ttypeof properties.createdAt === \"number\"\n\t\t\t\t\t\t\t? properties.createdAt\n\t\t\t\t\t\t\t: createdAt;\n\t\t\t\t\tcreatedProperties.updatedAt =\n\t\t\t\t\t\ttypeof properties.updatedAt === \"number\"\n\t\t\t\t\t\t\t? properties.updatedAt\n\t\t\t\t\t\t\t: createdAt;\n\t\t\t\t} else {\n\t\t\t\t\tcreatedProperties = { createdAt, updatedAt: createdAt };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst id = this.getId();\n\t\t\tconst feature = {\n\t\t\t\tid,\n\t\t\t\ttype: \"Feature\",\n\t\t\t\tgeometry,\n\t\t\t\tproperties: createdProperties,\n\t\t\t} as GeoJSONStoreFeatures;\n\n\t\t\tthis.store[id] = feature;\n\t\t\tthis.spatialIndex.insert(feature);\n\n\t\t\tids.push(id);\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange([...ids], \"create\", context);\n\t\t}\n\n\t\treturn ids as Id[];\n\t}\n\n\tdelete(ids: FeatureId[], context?: OnChangeContext): void {\n\t\tids.forEach((id) => {\n\t\t\tif (this.store[id]) {\n\t\t\t\tdelete this.store[id];\n\t\t\t\tthis.spatialIndex.remove(id as FeatureId);\n\t\t\t} else {\n\t\t\t\tthrow new Error(`No feature with id ${id}, can not delete`);\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange([...ids], \"delete\", context);\n\t\t}\n\t}\n\n\tcopy(id: FeatureId): GeoJSONStoreFeatures {\n\t\treturn this.clone(this.store[id]);\n\t}\n\n\tcopyAll(): GeoJSONStoreFeatures[] {\n\t\treturn this.clone(Object.keys(this.store).map((id) => this.store[id]));\n\t}\n\n\tcopyAllWhere(\n\t\tequals: (properties: JSONObject) => boolean,\n\t): GeoJSONStoreFeatures[] {\n\t\treturn this.clone(\n\t\t\tObject.keys(this.store)\n\t\t\t\t.map((id) => this.store[id])\n\t\t\t\t.filter((feature) => {\n\t\t\t\t\treturn feature.properties && equals(feature.properties);\n\t\t\t\t}),\n\t\t);\n\t}\n\n\tclear(): void {\n\t\tthis.store = {};\n\t\tthis.spatialIndex.clear();\n\t}\n\n\tsize(): number {\n\t\treturn Object.keys(this.store).length;\n\t}\n}\n","export const uuid4 = function (): string {\n\treturn \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n\t\tconst r = (Math.random() * 16) | 0,\n\t\t\tv = c == \"x\" ? r : (r & 0x3) | 0x8;\n\t\treturn v.toString(16);\n\t});\n};\n","import { Polygon } from \"geojson\";\nimport { earthRadius } from \"../helpers\";\n\n// Adapted from @turf/area is MIT Licensed licensed https://github.com/Turfjs/turf/blob/master/packages/turf-area/index.ts\n// In turn adapted from NASA: https://dataverse.jpl.nasa.gov/file.xhtml?fileId=47998&version=2.0\n\nexport function polygonAreaSquareMeters(polygon: Polygon) {\n\tconst coords = polygon.coordinates;\n\tlet total = 0;\n\tif (coords && coords.length > 0) {\n\t\ttotal += Math.abs(ringArea(coords[0]));\n\t\tfor (let i = 1; i < coords.length; i++) {\n\t\t\ttotal -= Math.abs(ringArea(coords[i]));\n\t\t}\n\t}\n\treturn total;\n}\n\nconst FACTOR = (earthRadius * earthRadius) / 2;\nconst PI_OVER_180 = Math.PI / 180;\n\nfunction ringArea(coords: number[][]): number {\n\tconst coordsLength = coords.length;\n\n\tif (coordsLength <= 2) {\n\t\treturn 0;\n\t}\n\n\tlet total = 0;\n\n\tlet i = 0;\n\twhile (i < coordsLength) {\n\t\tconst lower = coords[i];\n\t\tconst middle = coords[i + 1 === coordsLength ? 0 : i + 1];\n\t\tconst upper =\n\t\t\tcoords[i + 2 >= coordsLength ? (i + 2) % coordsLength : i + 2];\n\n\t\tconst lowerX = lower[0] * PI_OVER_180;\n\t\tconst middleY = middle[1] * PI_OVER_180;\n\t\tconst upperX = upper[0] * PI_OVER_180;\n\n\t\ttotal += (upperX - lowerX) * Math.sin(middleY);\n\n\t\ti++;\n\t}\n\n\treturn total * FACTOR;\n}\n","import { Validation } from \"../common\";\nimport { polygonAreaSquareMeters } from \"../geometry/measure/area\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport { ValidationReasonFeatureNotPolygon } from \"./common-validations\";\n\nexport const ValidationReasonFeatureLessThanMinSize =\n\t\"Feature is smaller than the minimum area\";\n\nexport const ValidateMinAreaSquareMeters = (\n\tfeature: GeoJSONStoreFeatures,\n\tminSize: number,\n): ReturnType<Validation> => {\n\tif (feature.geometry.type !== \"Polygon\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPolygon,\n\t\t};\n\t}\n\n\tif (polygonAreaSquareMeters(feature.geometry) < minSize) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureLessThanMinSize,\n\t\t};\n\t}\n\n\treturn { valid: true };\n};\n","import { Feature, LineString, Polygon } from \"geojson\";\nimport { selfIntersects } from \"../geometry/boolean/self-intersects\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport { Validation } from \"../common\";\n\nexport const ValidationReasonFeatureNotPolygonOrLineString =\n\t\"Feature is not a Polygon or LineString\";\nexport const ValidationReasonFeatureSelfIntersects =\n\t\"Feature intersects itself\";\n\nexport const ValidateNotSelfIntersecting = (\n\tfeature: GeoJSONStoreFeatures,\n): ReturnType<Validation> => {\n\tif (\n\t\tfeature.geometry.type !== \"Polygon\" &&\n\t\tfeature.geometry.type !== \"LineString\"\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPolygonOrLineString,\n\t\t};\n\t}\n\n\tconst hasSelfIntersections = selfIntersects(\n\t\tfeature as Feature<LineString> | Feature<Polygon>,\n\t);\n\n\tif (hasSelfIntersections) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureSelfIntersects,\n\t\t};\n\t}\n\n\treturn { valid: true };\n};\n","import { CartesianPoint } from \"../common\";\nimport { webMercatorBearing } from \"./measure/bearing\";\n\n/**\n * Calculate the relative angle between two lines\n * @param A The first point of the first line\n * @param B The second point of the first line and the first point of the second line\n * @param C The second point of the second line\n * @returns The relative angle between the two lines\n */\nexport function calculateRelativeAngle(\n\tA: CartesianPoint,\n\tB: CartesianPoint,\n\tC: CartesianPoint,\n): number {\n\tconst bearingAB = webMercatorBearing(A, B); // Bearing from A to B\n\tconst bearingBC = webMercatorBearing(B, C); // Bearing from B to C\n\n\t// Calculate the relative angle (bearingBC relative to bearingAB)\n\tlet relativeAngle = bearingBC - bearingAB;\n\n\t// Normalize the relative angle to 0-360 range\n\tif (relativeAngle < 0) {\n\t\trelativeAngle += 360;\n\t}\n\n\t// Normalise to 0 - 90\n\tconst angle = relativeAngle - 90;\n\n\treturn 180 - Math.abs(-90 + angle);\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tZ_INDEX,\n} from \"../../common\";\nimport { Polygon } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport { webMercatorBearing } from \"../../geometry/measure/bearing\";\nimport { midpointCoordinate } from \"../../geometry/midpoint-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { degreesToRadians } from \"../../geometry/helpers\";\nimport { determineHalfPlane } from \"../../geometry/determine-halfplane\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { calculateRelativeAngle } from \"../../geometry/calculate-relative-angle\";\n\ntype TerraDrawPolygonModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype PolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawAngledRectangleMode extends TerraDrawBaseDrawMode<PolygonStyling> {\n\tmode = \"angled-rectangle\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawPolygonModeKeyEvents = defaultKeyEvents;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawPolygonModeOptions<PolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawPolygonModeOptions<PolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst firstCoordinate = currentPolygonCoordinates[0];\n\t\t\tconst secondCoordinate = currentPolygonCoordinates[1];\n\t\t\tconst midpoint = midpointCoordinate(\n\t\t\t\tfirstCoordinate,\n\t\t\t\tsecondCoordinate,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t\tthis.project,\n\t\t\t\tthis.unproject,\n\t\t\t);\n\n\t\t\tconst A = lngLatToWebMercatorXY(firstCoordinate[0], firstCoordinate[1]);\n\t\t\tconst B = lngLatToWebMercatorXY(midpoint[0], midpoint[1]);\n\t\t\tconst C = lngLatToWebMercatorXY(secondCoordinate[0], secondCoordinate[1]);\n\t\t\tconst D = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\t// Determine if the cursor is closer to A or C\n\t\t\tconst distanceToA = cartesianDistance(D, A);\n\t\t\tconst distanceToB = cartesianDistance(D, C);\n\t\t\tconst ACloserThanC = distanceToA < distanceToB ? true : false;\n\n\t\t\t// We need to work out if the cursor is closer to A or C and then calculate the angle\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst relativeAngle = calculateRelativeAngle(A, B, D);\n\t\t\tconst theta = ACloserThanC\n\t\t\t\t? 90 - relativeAngle\n\t\t\t\t: calculateRelativeAngle(A, B, D) - 90;\n\n\t\t\t// We want to calculate the adjacent i.e. the calculated distance\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst hypotenuse = cartesianDistance(B, D);\n\t\t\tconst adjacent = Math.cos(degreesToRadians(theta)) * hypotenuse;\n\n\t\t\t// Calculate the bearing between the first and second point\n\t\t\tconst firstAndSecondPointBearing = webMercatorBearing(A, C);\n\n\t\t\t// Determine which side of the line the cursor is on\n\t\t\tconst side = determineHalfPlane(A, C, D);\n\n\t\t\t// Determine which direction to draw the rectangle\n\t\t\tconst angle = side === \"right\" ? -90 : 90;\n\n\t\t\t// Calculate the third and fourth coordinates based on the cursor position\n\t\t\tconst rectangleAngle = firstAndSecondPointBearing + angle;\n\t\t\tconst thirdCoordinateXY = webMercatorDestination(\n\t\t\t\tA,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\t\t\tconst fourthCoordinateXY = webMercatorDestination(\n\t\t\t\tC,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\n\t\t\t// Convert the third and fourth coordinates back to lng/lat\n\t\t\tconst thirdCoordinate = webMercatorXYToLngLat(\n\t\t\t\tthirdCoordinateXY.x,\n\t\t\t\tthirdCoordinateXY.y,\n\t\t\t);\n\t\t\tconst fourthCoordinate = webMercatorXYToLngLat(\n\t\t\t\tfourthCoordinateXY.x,\n\t\t\t\tfourthCoordinateXY.y,\n\t\t\t);\n\n\t\t\t// The final coordinates\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[fourthCoordinate.lng, fourthCoordinate.lat],\n\t\t\t\t[thirdCoordinate.lng, thirdCoordinate.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\t// We want pointer devices (mobile/tablet) to have\n\t\t\t// similar behaviour to mouse based devices so we\n\t\t\t// trigger a mousemove event before every click\n\t\t\t// if one has not been triggered to emulate this\n\t\t\tif (this.currentCoordinate > 0 && !this.mouseMove) {\n\t\t\t\tthis.onMouseMove(event);\n\t\t\t}\n\t\t\tthis.mouseMove = false;\n\n\t\t\tif (this.currentCoordinate === 0) {\n\t\t\t\tconst [newId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentId = newId;\n\t\t\t\tthis.currentCoordinate++;\n\n\t\t\t\t// Ensure the state is updated to reflect drawing has started\n\t\t\t\tthis.setDrawing();\n\t\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\t\tconst currentPolygonGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\n\t\t\t\tconst previousCoordinate = currentPolygonGeometry.coordinates[0][0];\n\t\t\t\tconst isIdentical = coordinatesIdentical(\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tpreviousCoordinate,\n\t\t\t\t);\n\n\t\t\t\tif (isIdentical) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t\t[\n\t\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t\t],\n\t\t\t\t\tUpdateTypes.Commit,\n\t\t\t\t);\n\n\t\t\t\tif (!updated) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.currentCoordinate++;\n\t\t\t} else if (this.currentCoordinate === 2 && this.currentId) {\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\t// We don't want to close a unfinished polygon\n\t\t\tif (this.currentCoordinate < 2) {\n\t\t\t\tthis.cleanUp();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\ttry {\n\t\t\tif (this.currentId) {\n\t\t\t\tthis.store.delete([this.currentId]);\n\t\t\t}\n\t\t} catch (error) {}\n\t\tthis.currentId = undefined;\n\t\tthis.currentCoordinate = 0;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (feature.properties.mode === this.mode) {\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.fillColor,\n\t\t\t\t\tstyles.polygonFillColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.outlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\n// Function to determine the relative position of a point to a line segment\nexport function determineHalfPlane(\n\tpoint: CartesianPoint,\n\tlineStart: CartesianPoint,\n\tlineEnd: CartesianPoint,\n): string {\n\t// Calculate the vectors\n\tconst vectorLine = { x: lineEnd.x - lineStart.x, y: lineEnd.y - lineStart.y };\n\tconst vectorPoint = { x: point.x - lineStart.x, y: point.y - lineStart.y };\n\n\t// Calculate the cross product\n\tconst crossProduct =\n\t\tvectorLine.x * vectorPoint.y - vectorLine.y * vectorPoint.x;\n\n\t// Use a small epsilon value to handle floating-point precision errors\n\tconst epsilon = 1e-10;\n\n\tif (crossProduct > epsilon) {\n\t\treturn \"left\";\n\t} else if (crossProduct < -epsilon) {\n\t\treturn \"right\";\n\t} else {\n\t\t// Technically on the line but we treat it as left\n\t\treturn \"left\";\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\nexport function isClockwiseWebMercator(\n\tcenter: CartesianPoint,\n\tsecondCoord: CartesianPoint,\n\tthirdCoord: CartesianPoint,\n): boolean {\n\t// Calculate the vectors\n\tconst vector1 = { x: secondCoord.x - center.x, y: secondCoord.y - center.y };\n\tconst vector2 = { x: thirdCoord.x - center.x, y: thirdCoord.y - center.y };\n\n\t// Calculate the cross product\n\tconst cross = vector1.x * vector2.y - vector1.y * vector2.x;\n\n\t// If the cross product is negative, the third point is on the right (clockwise)\n\t// If the cross product is positive, the third point is on the left (anticlockwise)\n\treturn cross <= 0;\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tZ_INDEX,\n} from \"../../common\";\nimport { Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSectorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SectorPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSectorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSectorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSectorMode extends TerraDrawBaseDrawMode<SectorPolygonStyling> {\n\tmode = \"sector\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSectorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSectorModeOptions<SectorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSectorModeOptions<SectorPolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t);\n\t\tif (correctedGeometry) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t]);\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates: Polygon[\"coordinates\"][0] | undefined;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst center = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[1];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\t// Convert coordinates to Web Mercator\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate the radius (distance from center to second point in Web Mercator)\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [center]; // Start with the center (in WGS84)\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add the first coordinate to the polygon\n\t\t\tcoordinates.push(arcCoordOne);\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(center);\n\n\t\t\tupdatedCoordinates = [...coordinates];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\t// We want pointer devices (mobile/tablet) to have\n\t\t\t// similar behaviour to mouse based devices so we\n\t\t\t// trigger a mousemove event before every click\n\t\t\t// if one has not been triggered to emulate this\n\t\t\tif (this.currentCoordinate > 0 && !this.mouseMove) {\n\t\t\t\tthis.onMouseMove(event);\n\t\t\t}\n\t\t\tthis.mouseMove = false;\n\n\t\t\tif (this.currentCoordinate === 0) {\n\t\t\t\tconst [newId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentId = newId;\n\t\t\t\tthis.currentCoordinate++;\n\n\t\t\t\t// Ensure the state is updated to reflect drawing has started\n\t\t\t\tthis.setDrawing();\n\t\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\t\tconst currentPolygonGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\n\t\t\t\tconst previousCoordinate = currentPolygonGeometry.coordinates[0][0];\n\t\t\t\tconst isIdentical = coordinatesIdentical(\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tpreviousCoordinate,\n\t\t\t\t);\n\n\t\t\t\tif (isIdentical) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t\t[\n\t\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\tcurrentPolygonGeometry.coordinates[0][0],\n\t\t\t\t\t],\n\t\t\t\t\tUpdateTypes.Commit,\n\t\t\t\t);\n\n\t\t\t\tif (!updated) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.currentCoordinate++;\n\t\t\t} else if (this.currentCoordinate === 2 && this.currentId) {\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\ttry {\n\t\t\tif (this.currentId) {\n\t\t\t\tthis.store.delete([this.currentId]);\n\t\t\t}\n\t\t} catch (error) {}\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\t\tthis.currentCoordinate = 0;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (feature.properties.mode === this.mode) {\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.fillColor,\n\t\t\t\t\tstyles.polygonFillColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.outlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tZ_INDEX,\n} from \"../../common\";\nimport { LineString, Point, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSensorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SensorPolygonStyling = {\n\tcenterPointColor: HexColorStyling;\n\tcenterPointWidth: NumericStyling;\n\tcenterPointOutlineColor: HexColorStyling;\n\tcenterPointOutlineWidth: NumericStyling;\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSensorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSensorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSensorMode extends TerraDrawBaseDrawMode<SensorPolygonStyling> {\n\tmode = \"sensor\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate currentInitialArcId: FeatureId | undefined;\n\tprivate currentStartingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSensorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSensorModeOptions<SensorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSensorModeOptions<SensorPolygonStyling>,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentStartingPointId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedCurrentStartingPointId = this.currentStartingPointId;\n\t\tconst finishedInitialArcId = this.currentInitialArcId;\n\t\tconst finishedCurrentId = this.currentId;\n\n\t\tif (finishedCurrentStartingPointId) {\n\t\t\tthis.store.delete([finishedCurrentStartingPointId]);\n\t\t}\n\n\t\tif (finishedInitialArcId) {\n\t\t\tthis.store.delete([finishedInitialArcId]);\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentStartingPointId = undefined;\n\t\tthis.currentInitialArcId = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedCurrentId) {\n\t\t\tthis.onFinish(finishedCurrentId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (\n\t\t\tthis.currentInitialArcId === undefined ||\n\t\t\tthis.currentStartingPointId === undefined ||\n\t\t\tthis.currentCoordinate === 0\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentCoordinate === 2) {\n\t\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [arcCoordOne];\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.updateLineStringGeometry(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t\tcoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t} else if (this.currentCoordinate === 3) {\n\t\t\tconst coordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\n\t\t\tif (coordinates.length < 2) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// This shouldn't happen but we protect against it in case as we can't calculate if the cursor\n\t\t\t// is in the sector otherwise\n\t\t\tif (!this.direction) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst firstCoord = coordinates[0];\n\t\t\tconst lastCoord = coordinates[coordinates.length - 1];\n\n\t\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\t\t\tconst webMercatorCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tfirstCoord[0],\n\t\t\t\tfirstCoord[1],\n\t\t\t);\n\t\t\tconst webMercatorCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tlastCoord[0],\n\t\t\t\tlastCoord[1],\n\t\t\t);\n\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst innerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\n\t\t\tconst outerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst hasLessThanZeroSize = outerRadius < innerRadius;\n\n\t\t\t// If the cursor is inside the inner radius, the depth of the sensor is always 0\n\t\t\tconst radiusCalculationPosition = hasLessThanZeroSize\n\t\t\t\t? webMercatorCoordOne\n\t\t\t\t: webMercatorCursor;\n\n\t\t\tconst cursorBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordTwo,\n\t\t\t);\n\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\t\t\tconst normalizedCursor = normalizeBearing(cursorBearing);\n\n\t\t\tconst notInSector = this.notInSector({\n\t\t\t\tnormalizedCursor,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t\tdirection: this.direction,\n\t\t\t});\n\n\t\t\t// If it's not a valid cursor movement then we don't update\n\t\t\tif (notInSector) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tconst deltaBearing = this.getDeltaBearing(\n\t\t\t\tthis.direction,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t);\n\n\t\t\t// Number of points to approximate the arc\n\t\t\tconst numberOfPoints = this.arcPoints;\n\n\t\t\t// Calculate bearing step\n\t\t\tconst multiplier = this.direction === \"anticlockwise\" ? 1 : -1;\n\t\t\tconst bearingStep = (multiplier * deltaBearing) / numberOfPoints;\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\tradiusCalculationPosition,\n\t\t\t);\n\n\t\t\t// Add all the arc points\n\t\t\tconst finalArc = [];\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tfinalArc.unshift(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcoordinates.push(...finalArc);\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(coordinates[0]);\n\n\t\t\t// If the polygon doesn't exist, create it\n\t\t\t// else update the existing geometry\n\t\t\tif (!this.currentId) {\n\t\t\t\t[this.currentId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [coordinates],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tthis.updatePolygonGeometry(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t\tcoordinates,\n\t\t\t\t\tUpdateTypes.Provisional,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateLineStringGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates,\n\t\t} as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (\n\t\t\t(event.button === \"right\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.rightClick, event)) ||\n\t\t\t(event.button === \"left\" &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.leftClick, event)) ||\n\t\t\t(event.isContextMenu &&\n\t\t\t\tthis.allowPointerEvent(this.pointerEvents.contextMenu, event))\n\t\t) {\n\t\t\t// We want pointer devices (mobile/tablet) to have\n\t\t\t// similar behaviour to mouse based devices so we\n\t\t\t// trigger a mousemove event before every click\n\t\t\t// if one has not been triggered to emulate this\n\t\t\tif (this.currentCoordinate > 0 && !this.mouseMove) {\n\t\t\t\tthis.onMouseMove(event);\n\t\t\t}\n\t\t\tthis.mouseMove = false;\n\n\t\t\tif (this.currentCoordinate === 0) {\n\t\t\t\tconst [newId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: { type: \"Point\", coordinates: [event.lng, event.lat] },\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentStartingPointId = newId;\n\t\t\t\tthis.currentCoordinate++;\n\n\t\t\t\t// Ensure the state is updated to reflect drawing has started\n\t\t\t\tthis.setDrawing();\n\t\t\t} else if (this.currentCoordinate === 1 && this.currentStartingPointId) {\n\t\t\t\tconst [newId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"LineString\",\n\t\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t\tthis.currentInitialArcId = newId;\n\t\t\t\tthis.currentCoordinate++;\n\t\t\t} else if (this.currentCoordinate === 2 && this.currentStartingPointId) {\n\t\t\t\tthis.currentCoordinate++;\n\t\t\t\t// pass\n\t\t\t} else if (this.currentCoordinate === 3 && this.currentStartingPointId) {\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyUp(event: TerraDrawKeyboardEvent) {\n\t\tif (event.key === this.keyEvents.cancel) {\n\t\t\tthis.cleanUp();\n\t\t} else if (event.key === this.keyEvents.finish) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tcleanUp() {\n\t\ttry {\n\t\t\tif (this.currentStartingPointId) {\n\t\t\t\tthis.store.delete([this.currentStartingPointId]);\n\t\t\t}\n\t\t\tif (this.currentInitialArcId) {\n\t\t\t\tthis.store.delete([this.currentInitialArcId]);\n\t\t\t}\n\t\t\tif (this.currentId) {\n\t\t\t\tthis.store.delete([this.currentId]);\n\t\t\t}\n\t\t} catch (error) {}\n\t\tthis.currentStartingPointId = undefined;\n\t\tthis.direction = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.currentCoordinate = 0;\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\t}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst styles = { ...getDefaultStyling() };\n\n\t\tif (feature.properties.mode === this.mode) {\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tstyles.polygonFillColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.fillColor,\n\t\t\t\t\tstyles.polygonFillColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.outlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.polygonFillOpacity = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.fillOpacity,\n\t\t\t\t\tstyles.polygonFillOpacity,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tstyles.lineStringColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.outlineColor,\n\t\t\t\t\tstyles.polygonOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.lineStringWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.outlineWidth,\n\t\t\t\t\tstyles.polygonOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_ONE;\n\t\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\t\tstyles.pointColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.centerPointColor,\n\t\t\t\t\tstyles.pointColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.centerPointWidth,\n\t\t\t\t\tstyles.pointWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineColor = this.getHexColorStylingValue(\n\t\t\t\t\tthis.styles.centerPointOutlineColor,\n\t\t\t\t\tstyles.pointOutlineColor,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.pointOutlineWidth = this.getNumericStylingValue(\n\t\t\t\t\tthis.styles.centerPointOutlineWidth,\n\t\t\t\t\tstyles.pointOutlineWidth,\n\t\t\t\t\tfeature,\n\t\t\t\t);\n\n\t\t\t\tstyles.zIndex = Z_INDEX.LAYER_TWO;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate getDeltaBearing(\n\t\tdirection: \"anticlockwise\" | \"clockwise\",\n\t\tnormalizedStart: number,\n\t\tnormalizedEnd: number,\n\t) {\n\t\tlet deltaBearing;\n\t\tif (direction === \"anticlockwise\") {\n\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t} else {\n\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t}\n\t\treturn deltaBearing;\n\t}\n\n\tprivate notInSector({\n\t\tnormalizedCursor,\n\t\tnormalizedStart,\n\t\tnormalizedEnd,\n\t\tdirection,\n\t}: {\n\t\tnormalizedCursor: number;\n\t\tnormalizedStart: number;\n\t\tnormalizedEnd: number;\n\t\tdirection: \"clockwise\" | \"anticlockwise\";\n\t}) {\n\t\tif (direction === \"clockwise\") {\n\t\t\t// Handle clockwise direction\n\t\t\tif (normalizedStart <= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart &&\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart ||\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Handle anticlockwise direction\n\t\t\tif (normalizedStart >= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart &&\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart ||\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n","export class AdapterListener<Callback extends (...args: any[]) => any> {\n\tpublic name: string;\n\tpublic callback: (...args: any[]) => any;\n\tpublic registered = false;\n\tpublic register: any;\n\tpublic unregister: any;\n\n\t/**\n\t * Creates a new AdapterListener instance with the provided configuration.\n\t *\n\t * @param {Object} config - The configuration object for the listener.\n\t * @param {string} config.name - The name of the event listener.\n\t * @param {Function} config.callback - The callback function to be called when the event is triggered.\n\t * @param {Function} config.unregister - The function to unregister the event listeners.\n\t * @param {Function} config.register - The function to register the event listeners.\n\t */\n\tconstructor({\n\t\tname,\n\t\tcallback,\n\t\tunregister,\n\t\tregister,\n\t}: {\n\t\tname: string;\n\t\tcallback: Callback;\n\t\tunregister: (callbacks: Callback) => void;\n\t\tregister: (callback: Callback) => void;\n\t}) {\n\t\tthis.name = name;\n\n\t\t// Function to register the event listeners\n\t\tthis.register = () => {\n\t\t\tif (!this.registered) {\n\t\t\t\tthis.registered = true;\n\t\t\t\tregister(callback);\n\t\t\t}\n\t\t};\n\n\t\t// Function to unregister the event listeners\n\t\tthis.unregister = () => {\n\t\t\tif (this.register) {\n\t\t\t\tthis.registered = false;\n\t\t\t\tunregister(callback);\n\t\t\t}\n\t\t};\n\n\t\tthis.callback = callback;\n\t}\n}\n","import {\n\tProject,\n\tUnproject,\n\tTerraDrawCallbacks,\n\tTerraDrawChanges,\n\tTerraDrawMouseEvent,\n\tSetCursor,\n\tTerraDrawStylingFunction,\n\tGetLngLatFromEvent,\n\tTerraDrawAdapter,\n} from \"../common\";\nimport { limitPrecision } from \"../geometry/limit-decimal-precision\";\nimport { cartesianDistance } from \"../geometry/measure/pixel-distance\";\nimport { AdapterListener } from \"./adapter-listener\";\n\ntype BasePointerListener = (event: PointerEvent) => void;\ntype BaseKeyboardListener = (event: KeyboardEvent) => void;\ntype BaseMouseListener = (event: MouseEvent) => void;\n\nexport type BaseAdapterConfig = {\n\tcoordinatePrecision?: number;\n\tminPixelDragDistanceDrawing?: number;\n\tminPixelDragDistance?: number;\n\tminPixelDragDistanceSelecting?: number;\n};\n\nexport abstract class TerraDrawBaseAdapter implements TerraDrawAdapter {\n\tconstructor(config: BaseAdapterConfig) {\n\t\tthis._minPixelDragDistance =\n\t\t\ttypeof config.minPixelDragDistance === \"number\"\n\t\t\t\t? config.minPixelDragDistance\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceSelecting =\n\t\t\ttypeof config.minPixelDragDistanceSelecting === \"number\"\n\t\t\t\t? config.minPixelDragDistanceSelecting\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceDrawing =\n\t\t\ttypeof config.minPixelDragDistanceDrawing === \"number\"\n\t\t\t\t? config.minPixelDragDistanceDrawing\n\t\t\t\t: 8;\n\n\t\tthis._coordinatePrecision =\n\t\t\ttypeof config.coordinatePrecision === \"number\"\n\t\t\t\t? config.coordinatePrecision\n\t\t\t\t: 9;\n\t}\n\n\tprivate _nextKeyUpIsContextMenu = false;\n\n\tprotected _minPixelDragDistance: number;\n\tprotected _minPixelDragDistanceDrawing: number;\n\tprotected _minPixelDragDistanceSelecting: number;\n\tprotected _lastDrawEvent: TerraDrawMouseEvent | undefined;\n\tprotected _coordinatePrecision: number;\n\tprotected _heldKeys: Set<string> = new Set();\n\tprotected _listeners: AdapterListener<\n\t\tBasePointerListener | BaseKeyboardListener | BaseMouseListener\n\t>[] = [];\n\tprotected _dragState: \"not-dragging\" | \"pre-dragging\" | \"dragging\" =\n\t\t\"not-dragging\";\n\tprotected _currentModeCallbacks: TerraDrawCallbacks | undefined;\n\n\tpublic abstract getMapEventElement(): HTMLElement;\n\n\tprotected getButton(event: PointerEvent | MouseEvent) {\n\t\tif (event.button === -1) {\n\t\t\treturn \"neither\";\n\t\t} else if (event.button === 0) {\n\t\t\treturn \"left\";\n\t\t} else if (event.button === 1) {\n\t\t\treturn \"middle\";\n\t\t} else if (event.button === 2) {\n\t\t\treturn \"right\";\n\t\t}\n\n\t\t// This shouldn't happen (?)\n\t\treturn \"neither\";\n\t}\n\n\tprotected getMapElementXYPosition(event: PointerEvent | MouseEvent) {\n\t\tconst mapElement = this.getMapEventElement();\n\t\tconst { left, top } = mapElement.getBoundingClientRect();\n\n\t\treturn {\n\t\t\tcontainerX: event.clientX - left,\n\t\t\tcontainerY: event.clientY - top,\n\t\t};\n\t}\n\n\tprotected getDrawEventFromEvent(\n\t\tevent: PointerEvent | MouseEvent,\n\t\tisContextMenu = false,\n\t): TerraDrawMouseEvent | null {\n\t\tconst latLng = this.getLngLatFromEvent(event);\n\n\t\tif (!latLng) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { lng, lat } = latLng;\n\t\tconst { containerX, containerY } = this.getMapElementXYPosition(event);\n\t\tconst button = this.getButton(event);\n\t\tconst heldKeys = Array.from(this._heldKeys);\n\n\t\treturn {\n\t\t\tlng: limitPrecision(lng, this._coordinatePrecision),\n\t\t\tlat: limitPrecision(lat, this._coordinatePrecision),\n\t\t\tcontainerX,\n\t\t\tcontainerY,\n\t\t\tbutton,\n\t\t\theldKeys,\n\t\t\tisContextMenu,\n\t\t};\n\t}\n\n\t/**\n\t * Registers the provided callbacks for the current drawing mode and attaches\n\t * the necessary event listeners.\n\t * @param {TerraDrawCallbacks} callbacks - An object containing callback functions\n\t * for handling various drawing events in the current mode.\n\t */\n\tpublic register(callbacks: TerraDrawCallbacks) {\n\t\tthis._currentModeCallbacks = callbacks;\n\n\t\tthis._listeners = this.getAdapterListeners();\n\n\t\tthis._listeners.forEach((listener) => {\n\t\t\tlistener.register();\n\t\t});\n\t}\n\n\t/**\n\t * Gets the coordinate precision. The coordinate precision is the number of decimal places in geometry\n\t * coordinates stored in the store.\n\t * @returns {number} The coordinate precision.\n\t */\n\tpublic getCoordinatePrecision() {\n\t\treturn this._coordinatePrecision;\n\t}\n\n\tprotected getAdapterListeners() {\n\t\treturn [\n\t\t\tnew AdapterListener<BasePointerListener>({\n\t\t\t\tname: \"pointerdown\",\n\t\t\t\tcallback: (event) => {\n\t\t\t\t\tif (!this._currentModeCallbacks) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// We don't support multitouch as this point in time\n\t\t\t\t\tif (!event.isPrimary) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst drawEvent = this.getDrawEventFromEvent(event);\n\t\t\t\t\tif (!drawEvent) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._dragState = \"pre-dragging\";\n\n\t\t\t\t\t// On pointer devices pointer mouse move events won't be\n\t\t\t\t\t// triggered so this._lastDrawEvent will not get set in\n\t\t\t\t\t// pointermove listener, so we must set it here.\n\t\t\t\t\tthis._lastDrawEvent = drawEvent;\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tthis.getMapEventElement().addEventListener(\"pointerdown\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tthis.getMapEventElement().removeEventListener(\n\t\t\t\t\t\t\"pointerdown\",\n\t\t\t\t\t\tcallback,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew AdapterListener<BasePointerListener>({\n\t\t\t\tname: \"pointermove\",\n\t\t\t\tcallback: (event) => {\n\t\t\t\t\tif (!this._currentModeCallbacks) return;\n\n\t\t\t\t\t// We don't support multitouch as this point in time\n\t\t\t\t\tif (!event.isPrimary) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\tconst drawEvent = this.getDrawEventFromEvent(event);\n\t\t\t\t\tif (!drawEvent) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this._dragState === \"not-dragging\") {\n\t\t\t\t\t\t// If we're not dragging we can trigger the onMouseMove event\n\t\t\t\t\t\tthis._currentModeCallbacks.onMouseMove(drawEvent);\n\t\t\t\t\t\tthis._lastDrawEvent = drawEvent;\n\t\t\t\t\t} else if (this._dragState === \"pre-dragging\") {\n\t\t\t\t\t\t// This should always be set because of pointerdown event\n\t\t\t\t\t\tif (!this._lastDrawEvent) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst lastEventXY = {\n\t\t\t\t\t\t\tx: this._lastDrawEvent.containerX,\n\t\t\t\t\t\t\ty: this._lastDrawEvent.containerY,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst currentEventXY = {\n\t\t\t\t\t\t\tx: drawEvent.containerX,\n\t\t\t\t\t\t\ty: drawEvent.containerY,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// We only want to prevent micro drags when we are\n\t\t\t\t\t\t// drawing as doing in on selection can cause janky\n\t\t\t\t\t\t// behaviours\n\t\t\t\t\t\tconst modeState = this._currentModeCallbacks.getState();\n\n\t\t\t\t\t\tconst pixelDistanceToCheck = cartesianDistance(\n\t\t\t\t\t\t\tlastEventXY,\n\t\t\t\t\t\t\tcurrentEventXY,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// We start off assuming it is not a microdrag\n\t\t\t\t\t\tlet isMicroDrag = false;\n\n\t\t\t\t\t\tif (modeState === \"drawing\") {\n\t\t\t\t\t\t\t// We want to ignore very small pointer movements when holding\n\t\t\t\t\t\t\t// the map down as these are normally done by accident when\n\t\t\t\t\t\t\t// drawing and is not an intended drag\n\t\t\t\t\t\t\tisMicroDrag =\n\t\t\t\t\t\t\t\tpixelDistanceToCheck < this._minPixelDragDistanceDrawing;\n\t\t\t\t\t\t} else if (modeState === \"selecting\") {\n\t\t\t\t\t\t\t// Similarly when selecting, we want to ignore very small pointer\n\t\t\t\t\t\t\t// movements when holding the map down as these are normally done\n\t\t\t\t\t\t\t// by accident when drawing and is not an intended drag\n\t\t\t\t\t\t\tisMicroDrag =\n\t\t\t\t\t\t\t\tpixelDistanceToCheck < this._minPixelDragDistanceSelecting;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Same as above, but when not drawing we generally want a much lower tolerance\n\t\t\t\t\t\t\tisMicroDrag = pixelDistanceToCheck < this._minPixelDragDistance;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If it is a microdrag we do not register it by returning early\n\t\t\t\t\t\tif (isMicroDrag) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If we are dragging it is not a context menu key up event any more\n\t\t\t\t\t\tthis._nextKeyUpIsContextMenu = false;\n\n\t\t\t\t\t\tthis._dragState = \"dragging\";\n\t\t\t\t\t\tthis._currentModeCallbacks.onDragStart(\n\t\t\t\t\t\t\tdrawEvent,\n\t\t\t\t\t\t\t(enabled: boolean) => {\n\t\t\t\t\t\t\t\tthis.setDraggability.bind(this)(enabled);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (this._dragState === \"dragging\") {\n\t\t\t\t\t\tthis._currentModeCallbacks.onDrag(drawEvent, (enabled: boolean) => {\n\t\t\t\t\t\t\tthis.setDraggability.bind(this)(enabled);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.addEventListener(\"pointermove\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.removeEventListener(\"pointermove\", callback);\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew AdapterListener<BaseMouseListener>({\n\t\t\t\tname: \"contextmenu\",\n\t\t\t\tcallback: (event) => {\n\t\t\t\t\tif (!this._currentModeCallbacks) return;\n\n\t\t\t\t\t// We do not want the context menu to open\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t// We signify that the next keyup event is related to the context menu\n\t\t\t\t\t// and we want to set isContextMenu to true\n\t\t\t\t\tthis._nextKeyUpIsContextMenu = true;\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.addEventListener(\"contextmenu\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.removeEventListener(\"contextmenu\", callback);\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew AdapterListener<BasePointerListener>({\n\t\t\t\tname: \"pointerup\",\n\t\t\t\tcallback: (event) => {\n\t\t\t\t\tif (!this._currentModeCallbacks) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (event.target !== this.getMapEventElement()) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// We don't support multitouch as this point in time\n\t\t\t\t\tif (!event.isPrimary) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst drawEvent = this.getDrawEventFromEvent(event);\n\n\t\t\t\t\tif (!drawEvent) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this._dragState === \"dragging\") {\n\t\t\t\t\t\tthis._currentModeCallbacks.onDragEnd(drawEvent, (enabled) => {\n\t\t\t\t\t\t\tthis.setDraggability.bind(this)(enabled);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (\n\t\t\t\t\t\tthis._dragState === \"not-dragging\" ||\n\t\t\t\t\t\tthis._dragState === \"pre-dragging\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// If we're not dragging or about to drag we\n\t\t\t\t\t\t// can trigger the onClick event\n\t\t\t\t\t\t// We want to reset it to false after we have used it\n\t\t\t\t\t\tif (this._nextKeyUpIsContextMenu) {\n\t\t\t\t\t\t\tdrawEvent.isContextMenu = true;\n\t\t\t\t\t\t\tthis._nextKeyUpIsContextMenu = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis._currentModeCallbacks.onClick(drawEvent);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensure we go back to the regular behaviour\n\t\t\t\t\t// not dragging and re-enable dragging on the actual map\n\t\t\t\t\tthis._dragState = \"not-dragging\";\n\t\t\t\t\tthis.setDraggability(true);\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.addEventListener(\"pointerup\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.removeEventListener(\"pointerup\", callback);\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew AdapterListener({\n\t\t\t\tname: \"keyup\",\n\t\t\t\tcallback: (event: KeyboardEvent) => {\n\t\t\t\t\t// map has no keypress event, so we add one to the canvas itself\n\n\t\t\t\t\tif (!this._currentModeCallbacks) return;\n\n\t\t\t\t\tthis._heldKeys.delete(event.key);\n\n\t\t\t\t\tthis._currentModeCallbacks.onKeyUp({\n\t\t\t\t\t\tkey: event.key,\n\t\t\t\t\t\theldKeys: Array.from(this._heldKeys),\n\t\t\t\t\t\tpreventDefault: () => event.preventDefault(),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.addEventListener(\"keyup\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.removeEventListener(\"keyup\", callback);\n\t\t\t\t},\n\t\t\t}),\n\t\t\tnew AdapterListener({\n\t\t\t\tname: \"keydown\",\n\t\t\t\tcallback: (event: KeyboardEvent) => {\n\t\t\t\t\tif (!this._currentModeCallbacks) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._heldKeys.add(event.key);\n\n\t\t\t\t\tthis._currentModeCallbacks.onKeyDown({\n\t\t\t\t\t\tkey: event.key,\n\t\t\t\t\t\theldKeys: Array.from(this._heldKeys),\n\t\t\t\t\t\tpreventDefault: () => event.preventDefault(),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.addEventListener(\"keydown\", callback);\n\t\t\t\t},\n\t\t\t\tunregister: (callback) => {\n\t\t\t\t\tconst mapElement = this.getMapEventElement();\n\t\t\t\t\tmapElement.removeEventListener(\"keydown\", callback);\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\t}\n\n\t/**\n\t * Unregisters the event listeners for the current drawing mode.\n\t * This is typically called when switching between drawing modes or\n\t * stopping the drawing process.\n\t */\n\tpublic unregister() {\n\t\tthis._listeners.forEach((listener) => {\n\t\t\tlistener.unregister();\n\t\t});\n\n\t\tthis.clear();\n\n\t\t// This has to come last because we call this._currentModeCallbacks.onClear()\n\t\tthis._currentModeCallbacks = undefined;\n\t}\n\n\tpublic abstract clear(): void;\n\n\tpublic abstract project(...args: Parameters<Project>): ReturnType<Project>;\n\n\tpublic abstract unproject(\n\t\t...args: Parameters<Unproject>\n\t): ReturnType<Unproject>;\n\n\tpublic abstract setCursor(\n\t\t...args: Parameters<SetCursor>\n\t): ReturnType<SetCursor>;\n\n\tpublic abstract getLngLatFromEvent(\n\t\t...event: Parameters<GetLngLatFromEvent>\n\t): ReturnType<GetLngLatFromEvent>;\n\n\tpublic abstract setDraggability(enabled: boolean): void;\n\n\tpublic abstract setDoubleClickToZoom(enabled: boolean): void;\n\n\tpublic abstract render(\n\t\tchanges: TerraDrawChanges,\n\t\tstyling: TerraDrawStylingFunction,\n\t): void;\n}\n","import {\n\tValidationReasonModeMismatch,\n\tValidationReasonFeatureNotPolygon,\n} from \"./validations/common-validations\";\nimport { ValidationReasonFeatureLessThanMinSize } from \"./validations/min-size.validation\";\nimport {\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n} from \"./validations/not-self-intersecting.validation\";\nimport {\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n} from \"./validations/point.validation\";\nimport {\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n} from \"./validations/polygon.validation\";\n\nexport const ValidationReasons = {\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n\tValidationReasonFeatureNotPolygon,\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n\tValidationReasonFeatureLessThanMinSize,\n\tValidationReasonModeMismatch,\n};\n","/**\n * @module terra-draw\n */\nimport {\n\tTerraDrawAdapter,\n\tTerraDrawAdapterStyling,\n\tGetLngLatFromEvent,\n\tProject,\n\tSetCursor,\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tUnproject,\n\tHexColor,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawMouseEvent,\n\tSELECT_PROPERTIES,\n\tOnFinishContext,\n\tCOMMON_PROPERTIES,\n\tTerraDrawGeoJSONStore,\n\tOnChangeContext,\n} from \"./common\";\nimport {\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n\tTerraDrawBaseSelectMode,\n} from \"./modes/base.mode\";\nimport { TerraDrawCircleMode } from \"./modes/circle/circle.mode\";\nimport { TerraDrawFreehandMode } from \"./modes/freehand/freehand.mode\";\nimport { TerraDrawLineStringMode } from \"./modes/linestring/linestring.mode\";\nimport { TerraDrawPointMode } from \"./modes/point/point.mode\";\nimport { TerraDrawPolygonMode } from \"./modes/polygon/polygon.mode\";\nimport { TerraDrawRectangleMode } from \"./modes/rectangle/rectangle.mode\";\nimport { TerraDrawRenderMode } from \"./modes/render/render.mode\";\nimport { TerraDrawSelectMode } from \"./modes/select/select.mode\";\nimport { TerraDrawStaticMode } from \"./modes/static/static.mode\";\nimport {\n\tBBoxPolygon,\n\tFeatureId,\n\tGeoJSONStore,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tIdStrategy,\n\tStoreChangeHandler,\n\tStoreValidation,\n} from \"./store/store\";\nimport { BehaviorConfig } from \"./modes/base.behavior\";\nimport { cartesianDistance } from \"./geometry/measure/pixel-distance\";\nimport { pixelDistanceToLine } from \"./geometry/measure/pixel-distance-to-line\";\nimport { Position } from \"geojson\";\nimport { pointInPolygon } from \"./geometry/boolean/point-in-polygon\";\nimport { createBBoxFromPoint } from \"./geometry/shape/create-bbox\";\nimport { ValidateMinAreaSquareMeters } from \"./validations/min-size.validation\";\nimport { ValidateMaxAreaSquareMeters } from \"./validations/max-size.validation\";\nimport { ValidateNotSelfIntersecting } from \"./validations/not-self-intersecting.validation\";\nimport { TerraDrawAngledRectangleMode } from \"./modes/angled-rectangle/angled-rectangle.mode\";\nimport { TerraDrawSectorMode } from \"./modes/sector/sector.mode\";\nimport { TerraDrawSensorMode } from \"./modes/sensor/sensor.mode\";\nimport * as TerraDrawExtend from \"./extend\";\nimport { hasModeProperty } from \"./store/store-feature-validation\";\nimport { ValidationReasons } from \"./validation-reasons\";\n\n// Helper type to determine the instance type of a class\ntype InstanceType<T extends new (...args: any[]) => any> = T extends new (\n\t...args: any[]\n) => infer R\n\t? R\n\t: never;\n\ntype FinishListener = (id: FeatureId, context: OnFinishContext) => void;\ntype ChangeListener = (\n\tids: FeatureId[],\n\ttype: string,\n\tcontext?: OnChangeContext,\n) => void;\ntype SelectListener = (id: FeatureId) => void;\ntype DeselectListener = () => void;\n\ninterface TerraDrawEventListeners {\n\tready: () => void;\n\tfinish: FinishListener;\n\tchange: ChangeListener;\n\tselect: SelectListener;\n\tdeselect: DeselectListener;\n}\n\ntype TerraDrawEvents = keyof TerraDrawEventListeners;\n\nclass TerraDraw {\n\tprivate _modes: {\n\t\t[mode: string]: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\t};\n\tprivate _mode: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\tprivate _adapter: TerraDrawAdapter;\n\tprivate _enabled = false;\n\tprivate _store: TerraDrawGeoJSONStore;\n\tprivate _eventListeners: {\n\t\tready: (() => void)[];\n\t\tchange: ChangeListener[];\n\t\tfinish: FinishListener[];\n\t\tselect: SelectListener[];\n\t\tdeselect: DeselectListener[];\n\t};\n\t// This is the select mode that is assigned in the instance.\n\t// There can only be 1 select mode active per instance\n\tprivate _instanceSelectMode: undefined | string;\n\n\tconstructor(options: {\n\t\tadapter: TerraDrawAdapter;\n\t\tmodes: TerraDrawBaseDrawMode<any>[];\n\t\tidStrategy?: IdStrategy<FeatureId>;\n\t\ttracked?: boolean;\n\t}) {\n\t\tthis._adapter = options.adapter;\n\n\t\tthis._mode = new TerraDrawStaticMode();\n\n\t\t// Keep track of if there are duplicate modes\n\t\tconst duplicateModeTracker = new Set();\n\n\t\t// Construct a map of the mode name to the mode\n\t\tconst modesMap = options.modes.reduce<{\n\t\t\t[mode: string]: TerraDrawBaseDrawMode<any>;\n\t\t}>((modeMap, currentMode) => {\n\t\t\tif (duplicateModeTracker.has(currentMode.mode)) {\n\t\t\t\tthrow new Error(`There is already a ${currentMode.mode} mode provided`);\n\t\t\t}\n\t\t\tduplicateModeTracker.add(currentMode.mode);\n\t\t\tmodeMap[currentMode.mode] = currentMode;\n\t\t\treturn modeMap;\n\t\t}, {});\n\n\t\t// Construct an array of the mode keys (names)\n\t\tconst modeKeys = Object.keys(modesMap);\n\n\t\t// Ensure at least one draw mode is provided\n\t\tif (modeKeys.length === 0) {\n\t\t\tthrow new Error(\"No modes provided\");\n\t\t}\n\n\t\t// Ensure only one select mode can be present\n\t\tmodeKeys.forEach((mode) => {\n\t\t\tif (modesMap[mode].type !== ModeTypes.Select) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this._instanceSelectMode) {\n\t\t\t\tthrow new Error(\"only one type of select mode can be provided\");\n\t\t\t} else {\n\t\t\t\tthis._instanceSelectMode = mode;\n\t\t\t}\n\t\t});\n\n\t\tthis._modes = { ...modesMap, static: this._mode };\n\t\tthis._eventListeners = {\n\t\t\tchange: [],\n\t\t\tselect: [],\n\t\t\tdeselect: [],\n\t\t\tfinish: [],\n\t\t\tready: [],\n\t\t};\n\t\tthis._store = new GeoJSONStore<OnChangeContext | undefined, FeatureId>({\n\t\t\ttracked: options.tracked ? true : false,\n\t\t\tidStrategy: options.idStrategy ? options.idStrategy : undefined,\n\t\t});\n\n\t\tconst getChanged = (\n\t\t\tids: FeatureId[],\n\t\t): {\n\t\t\tchanged: GeoJSONStoreFeatures[];\n\t\t\tunchanged: GeoJSONStoreFeatures[];\n\t\t} => {\n\t\t\tconst changed: GeoJSONStoreFeatures[] = [];\n\n\t\t\tconst unchanged = this._store.copyAll().filter((f) => {\n\t\t\t\tif (ids.includes(f.id as string)) {\n\t\t\t\t\tchanged.push(f);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\t\treturn { changed, unchanged };\n\t\t};\n\n\t\tconst onFinish = (finishedId: FeatureId, context: OnFinishContext) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.finish.forEach((listener) => {\n\t\t\t\tlistener(finishedId, context);\n\t\t\t});\n\t\t};\n\n\t\tconst onChange: StoreChangeHandler<OnChangeContext | undefined> = (\n\t\t\tids,\n\t\t\tevent,\n\t\t\tcontext,\n\t\t) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.change.forEach((listener) => {\n\t\t\t\tlistener(ids, event, context);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged(ids);\n\n\t\t\tif (event === \"create\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: changed,\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: [],\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"update\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"delete\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: ids, unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"styling\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onSelect = (selectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.select.forEach((listener) => {\n\t\t\t\tlistener(selectedId);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([selectedId]);\n\n\t\t\tthis._adapter.render(\n\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: changed },\n\t\t\t\tthis.getModeStyles(),\n\t\t\t);\n\t\t};\n\n\t\tconst onDeselect = (deselectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.deselect.forEach((listener) => {\n\t\t\t\tlistener();\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([deselectedId]);\n\n\t\t\t// onDeselect can be called after a delete call which means that\n\t\t\t// you are deselecting a feature that has been deleted. We\n\t\t\t// double check here to ensure that the feature still exists.\n\t\t\tif (changed) {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\t// Register stores and callbacks\n\t\tObject.keys(this._modes).forEach((modeId) => {\n\t\t\tthis._modes[modeId].register({\n\t\t\t\tmode: modeId,\n\t\t\t\tstore: this._store,\n\t\t\t\tsetCursor: this._adapter.setCursor.bind(this._adapter),\n\t\t\t\tproject: this._adapter.project.bind(this._adapter),\n\t\t\t\tunproject: this._adapter.unproject.bind(this._adapter),\n\t\t\t\tsetDoubleClickToZoom: this._adapter.setDoubleClickToZoom.bind(\n\t\t\t\t\tthis._adapter,\n\t\t\t\t),\n\t\t\t\tonChange: onChange,\n\t\t\t\tonSelect: onSelect,\n\t\t\t\tonDeselect: onDeselect,\n\t\t\t\tonFinish: onFinish,\n\t\t\t\tcoordinatePrecision: this._adapter.getCoordinatePrecision(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate checkEnabled() {\n\t\tif (!this._enabled) {\n\t\t\tthrow new Error(\"Terra Draw is not enabled\");\n\t\t}\n\t}\n\n\tprivate getModeStyles() {\n\t\tconst modeStyles: {\n\t\t\t[key: string]: (feature: GeoJSONStoreFeatures) => TerraDrawAdapterStyling;\n\t\t} = {};\n\n\t\tObject.keys(this._modes).forEach((mode) => {\n\t\t\tmodeStyles[mode] = (feature: GeoJSONStoreFeatures) => {\n\t\t\t\t// If the feature is selected, we want to use the select mode styling\n\t\t\t\tif (\n\t\t\t\t\tthis._instanceSelectMode &&\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTED]\n\t\t\t\t) {\n\t\t\t\t\treturn this._modes[this._instanceSelectMode].styleFeature.bind(\n\t\t\t\t\t\tthis._modes[this._instanceSelectMode],\n\t\t\t\t\t)(feature);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise use regular styling\n\t\t\t\treturn this._modes[mode].styleFeature.bind(this._modes[mode])(feature);\n\t\t\t};\n\t\t});\n\t\treturn modeStyles;\n\t}\n\n\tprivate featuresAtLocation(\n\t\t{\n\t\t\tlng,\n\t\t\tlat,\n\t\t}: {\n\t\t\tlng: number;\n\t\t\tlat: number;\n\t\t},\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst pointerDistance =\n\t\t\toptions && options.pointerDistance !== undefined\n\t\t\t\t? options.pointerDistance\n\t\t\t\t: 30; // default is 30px\n\n\t\tconst ignoreSelectFeatures =\n\t\t\toptions && options.ignoreSelectFeatures !== undefined\n\t\t\t\t? options.ignoreSelectFeatures\n\t\t\t\t: true;\n\n\t\tconst unproject = this._adapter.unproject.bind(this._adapter);\n\t\tconst project = this._adapter.project.bind(this._adapter);\n\n\t\tconst inputPoint = project(lng, lat);\n\n\t\tconst bbox = createBBoxFromPoint({\n\t\t\tunproject,\n\t\t\tpoint: inputPoint,\n\t\t\tpointerDistance,\n\t\t});\n\n\t\tconst features = this._store.search(bbox as BBoxPolygon);\n\n\t\t// TODO: This is designed to work in a similar way as FeatureAtPointerEvent\n\t\t// perhaps at some point we could figure out how to unify them\n\t\treturn features.filter((feature) => {\n\t\t\tif (\n\t\t\t\tignoreSelectFeatures &&\n\t\t\t\t(feature.properties[SELECT_PROPERTIES.MID_POINT] ||\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTION_POINT])\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (feature.geometry.type === \"Point\") {\n\t\t\t\tconst pointCoordinates = feature.geometry.coordinates;\n\t\t\t\tconst pointXY = project(pointCoordinates[0], pointCoordinates[1]);\n\t\t\t\tconst distance = cartesianDistance(inputPoint, pointXY);\n\t\t\t\treturn distance < pointerDistance;\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tconst coordinates: Position[] = feature.geometry.coordinates;\n\n\t\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\t\tconst coord = coordinates[i];\n\t\t\t\t\tconst nextCoord = coordinates[i + 1];\n\t\t\t\t\tconst distanceToLine = pixelDistanceToLine(\n\t\t\t\t\t\tinputPoint,\n\t\t\t\t\t\tproject(coord[0], coord[1]),\n\t\t\t\t\t\tproject(nextCoord[0], nextCoord[1]),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (distanceToLine < pointerDistance) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tconst lngLatInsidePolygon = pointInPolygon(\n\t\t\t\t\t[lng, lat],\n\t\t\t\t\tfeature.geometry.coordinates,\n\t\t\t\t);\n\n\t\t\t\tif (lngLatInsidePolygon) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate getSelectMode() {\n\t\tthis.checkEnabled();\n\n\t\tif (!this._instanceSelectMode) {\n\t\t\tthrow new Error(\"No select mode defined in instance\");\n\t\t}\n\n\t\tconst currentMode = this.getMode();\n\n\t\t// If we're not already in the select mode, we switch to it\n\t\tif (currentMode !== this._instanceSelectMode) {\n\t\t\tthis.setMode(this._instanceSelectMode);\n\t\t}\n\n\t\tconst selectMode = this._modes[\n\t\t\tthis._instanceSelectMode\n\t\t] as TerraDrawBaseSelectMode<any>;\n\n\t\treturn selectMode;\n\t}\n\n\t/**\n\t * @deprecated This method is scheduled for removal in the next major version. Instead use the 'updateModeOptions' method passing the\n\t * styles property in the options object, and this will dynamically update the styles for the mode.\n\t *\n\t * Allows the setting of a style for a given mode\n\t *\n\t * @param mode - The mode you wish to set a style for\n\t * @param styles - The styles you wish to set for the mode - this is\n\t * the same as the initialisation style schema\n\t */\n\tsetModeStyles<Styling extends Record<string, number | HexColor>>(\n\t\tmode: string,\n\t\tstyles: Styling,\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\t// TODO: Not sure why this fails TypeScript with TerraDrawBaseSelectMode?\n\t\t(this._modes[mode] as TerraDrawBaseDrawMode<any>).styles = styles;\n\t}\n\n\t/**\n\t * Allow updating of the current options passed to the mode dynamically\n\t * after the mode has been started. You can also use this method to update styles\n\t * as these are passed from the options object.\n\t * @param mode - the mode name you wish to update (the mode name is the public 'mode' property of the mode class)\n\t * @param options - the options object - this allows _partial_ updating of the modes options (i.e. you do not need to pass the whole options object)\n\t */\n\tupdateModeOptions<Mode extends { new (...args: any[]): any }>(\n\t\tmode: InstanceType<Mode>[\"mode\"],\n\t\toptions: ConstructorParameters<Mode>[0],\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\tthis._modes[mode].updateOptions(\n\t\t\toptions as TerraDrawExtend.BaseModeOptions<any>,\n\t\t);\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of all given features\n\t *\n\t * @returns An array of all given Feature Geometries in the instances store\n\t */\n\tgetSnapshot() {\n\t\t// This is a read only method so we do not need to check if enabled\n\t\treturn this._store.copyAll();\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of a given feature by id\n\t *\n\t * @returns A copy of the feature geometry in the instances store\n\t */\n\tgetSnapshotFeature(id: FeatureId) {\n\t\tif (!this._store.has(id)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._store.copy(id);\n\t}\n\n\t/**\n\t * Removes all data from the current store and ensures any rendered data is cleared\n\t * from the map.\n\t */\n\tclear() {\n\t\tthis.checkEnabled();\n\t\tthis._adapter.clear();\n\t}\n\n\t/**\n\t * A property used to determine whether the instance is active or not. You\n\t * can use the start method to set this to true, and stop method to set this to false.\n\t * This is a read only property.\n\t *\n\t * @return true or false depending on if the instance is stopped or started\n\t * @readonly\n\t */\n\tget enabled(): boolean {\n\t\treturn this._enabled;\n\t}\n\n\t/**\n\t * enabled is a read only property and will throw and error if you try and set it.\n\t */\n\tset enabled(_) {\n\t\tthrow new Error(\"Enabled is read only\");\n\t}\n\n\t/**\n\t * A method for getting the current mode name\n\t * @return the current mode name\n\t */\n\tgetMode(): string {\n\t\t// This is a read only method so we do not need to check if enabled\n\t\treturn this._mode.mode;\n\t}\n\n\t/**\n\t * Get the state of the mode i.e. if we are currently unregistered, registered, drawing etc. This can\n\t * be used to make decisions based on what the current mode is doing.\n\t * @returns the current mode state as a string\n\t */\n\tgetModeState() {\n\t\treturn this._mode.state;\n\t}\n\n\t/**\n\t * A method for setting the current mode by name. Under the hood this will stop\n\t * the previous mode and start the new one.\n\t * @param mode - The mode name you wish to start\n\t */\n\tsetMode(mode: string) {\n\t\tthis.checkEnabled();\n\n\t\tif (this._modes[mode]) {\n\t\t\t// Before we swap modes we want to\n\t\t\t// clean up any state that has been left behind,\n\t\t\t// for example current drawing geometries\n\t\t\t// and mode state\n\t\t\tthis._mode.stop();\n\n\t\t\t// Swap the mode to the new mode\n\t\t\tthis._mode = this._modes[mode];\n\n\t\t\t// Start the new mode\n\t\t\tthis._mode.start();\n\t\t} else {\n\t\t\t// If the mode doesn't exist, we throw an error\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\t}\n\n\t/**\n\t * A method for removing features to the store\n\t * @param ids\n\t * @returns\n\t */\n\tremoveFeatures(ids: FeatureId[]) {\n\t\tthis.checkEnabled();\n\n\t\tconst coordinatePointsToDelete: FeatureId[] = [];\n\n\t\tids.forEach((id) => {\n\t\t\t// Deselect any passed features - this removes all selection points and midpoints\n\t\t\tif (!this._store.has(id)) {\n\t\t\t\tthrow new Error(`No feature with id ${id}, can not delete`);\n\t\t\t}\n\n\t\t\tconst feature = this._store.copy(id);\n\t\t\tif (feature.properties[SELECT_PROPERTIES.SELECTED]) {\n\t\t\t\tthis.deselectFeature(id);\n\t\t\t}\n\n\t\t\t// If the feature has coordinate points, we want to remove them as well\n\t\t\tif (feature.properties[COMMON_PROPERTIES.COORDINATE_POINT_IDS]) {\n\t\t\t\tcoordinatePointsToDelete.push(\n\t\t\t\t\t...(feature.properties[\n\t\t\t\t\t\tCOMMON_PROPERTIES.COORDINATE_POINT_IDS\n\t\t\t\t\t] as FeatureId[]),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tthis._store.delete([...ids, ...coordinatePointsToDelete], {\n\t\t\torigin: \"api\",\n\t\t});\n\t}\n\n\t/**\n\t * Provides the ability to programmatically select a feature using the instances provided select mode.\n\t * If not select mode is provided in the instance, an error will be thrown. If the instance is not currently\n\t * in the select mode, it will switch to it.\n\t * @param id - the id of the feature to select\n\t */\n\tselectFeature(id: FeatureId) {\n\t\tconst selectMode = this.getSelectMode();\n\t\tselectMode.selectFeature(id);\n\t}\n\n\t/**\n\t * Provides the ability to programmatically deselect a feature using the instances provided select mode.\n\t * If not select mode is provided in the instance, an error will be thrown. If the instance is not currently\n\t * in the select mode, it will switch to it.\n\t * @param id  - the id of the feature to deselect\n\t */\n\tdeselectFeature(id: FeatureId) {\n\t\tconst selectMode = this.getSelectMode();\n\t\tselectMode.deselectFeature(id);\n\t}\n\n\t/**\n\t * Returns the next feature id from the store - defaults to UUID4 unless you have\n\t * set a custom idStrategy. This method can be useful if you are needing creating features\n\t * outside of the Terra Draw instance but want to add them in to the store.\n\t * @returns a id, either number of string based on whatever the configured idStrategy is\n\t *\n\t */\n\tgetFeatureId(): FeatureId {\n\t\treturn this._store.getId();\n\t}\n\n\t/**\n\t * Returns true or false depending on if the Terra Draw instance has a feature with a given id\n\t * @returns a boolean determining if the instance has a feature with the given id\n\t */\n\thasFeature(id: FeatureId): boolean {\n\t\treturn this._store.has(id);\n\t}\n\n\t/**\n\t * A method for adding features to the store. This method will validate the features\n\t * returning an array of validation results. Features must match one of the modes enabled\n\t * in the instance.\n\t * @param features - an array of GeoJSON features\n\t * @returns an array of validation results\n\t */\n\taddFeatures(features: GeoJSONStoreFeatures[]): StoreValidation[] {\n\t\tthis.checkEnabled();\n\n\t\tif (features.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this._store.load(\n\t\t\tfeatures,\n\t\t\t(feature) => {\n\t\t\t\t// If the feature has a mode property, we use that to validate the feature\n\t\t\t\tif (hasModeProperty(feature)) {\n\t\t\t\t\tconst featureMode = feature.properties.mode;\n\t\t\t\t\tconst modeToAddTo = this._modes[featureMode];\n\n\t\t\t\t\t// if the mode does not exist, we return false\n\t\t\t\t\tif (!modeToAddTo) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\t\t\tvalid: false,\n\t\t\t\t\t\t\treason: `${featureMode} mode is not in the list of instantiated modes`,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// use the inbuilt validation of the mode\n\t\t\t\t\tconst validation = modeToAddTo.validateFeature.bind(modeToAddTo);\n\t\t\t\t\tconst validationResult = validation(feature);\n\t\t\t\t\tconst valid = validationResult.valid;\n\t\t\t\t\tconst reason = validationResult.reason\n\t\t\t\t\t\t? validationResult.reason\n\t\t\t\t\t\t: !validationResult.valid\n\t\t\t\t\t\t\t? \"Feature is invalid\"\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\t\tvalid,\n\t\t\t\t\t\treason,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// If the feature does not have a mode property, we return false\n\t\t\t\treturn {\n\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: \"Mode property does not exist\",\n\t\t\t\t};\n\t\t\t},\n\t\t\t(feature) => {\n\t\t\t\tif (hasModeProperty(feature)) {\n\t\t\t\t\tconst featureMode = feature.properties.mode;\n\t\t\t\t\tconst modeToAddTo = this._modes[featureMode];\n\t\t\t\t\tif (modeToAddTo && modeToAddTo.afterFeatureAdded) {\n\t\t\t\t\t\tmodeToAddTo.afterFeatureAdded(feature);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ origin: \"api\" },\n\t\t);\n\t}\n\n\t/**\n\t * A method starting Terra Draw. It put the instance into a started state, and\n\t * in registers the passed adapter giving it all the callbacks required to operate.\n\t */\n\tstart() {\n\t\t// If the instance is already enabled, we do nothing\n\t\tif (this._enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._enabled = true;\n\t\tthis._adapter.register({\n\t\t\tonReady: () => {\n\t\t\t\tthis._eventListeners.ready.forEach((listener) => {\n\t\t\t\t\tlistener();\n\t\t\t\t});\n\t\t\t},\n\t\t\tgetState: () => {\n\t\t\t\treturn this._mode.state;\n\t\t\t},\n\t\t\tonClick: (event) => {\n\t\t\t\tthis._mode.onClick(event);\n\t\t\t},\n\t\t\tonMouseMove: (event) => {\n\t\t\t\tthis._mode.onMouseMove(event);\n\t\t\t},\n\t\t\tonKeyDown: (event) => {\n\t\t\t\tthis._mode.onKeyDown(event);\n\t\t\t},\n\t\t\tonKeyUp: (event) => {\n\t\t\t\tthis._mode.onKeyUp(event);\n\t\t\t},\n\t\t\tonDragStart: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragStart(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDrag: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDrag(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDragEnd: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragEnd(event, setMapDraggability);\n\t\t\t},\n\t\t\tonClear: () => {\n\t\t\t\t// Ensure that the mode resets its state\n\t\t\t\t// as it may be storing feature ids internally in it's instance\n\t\t\t\tthis._mode.cleanUp();\n\n\t\t\t\t// Remove all features from the store\n\t\t\t\tthis._store.clear();\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Gets the features at a given longitude and latitude.\n\t * Will return point and linestrings that are a given pixel distance\n\t * away from the lng/lat and any polygons which contain it.\n\t */\n\tgetFeaturesAtLngLat(\n\t\tlngLat: { lng: number; lat: number },\n\t\toptions?: { pointerDistance: number; ignoreSelectFeatures: boolean },\n\t) {\n\t\tconst { lng, lat } = lngLat;\n\n\t\treturn this.featuresAtLocation(\n\t\t\t{\n\t\t\t\tlng,\n\t\t\t\tlat,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Takes a given pointer event and will return point and linestrings that are\n\t * a given pixel distance away from the longitude/latitude, and any polygons which contain it.\n\t */\n\tgetFeaturesAtPointerEvent(\n\t\tevent: PointerEvent | MouseEvent,\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst getLngLatFromEvent = this._adapter.getLngLatFromEvent.bind(\n\t\t\tthis._adapter,\n\t\t);\n\n\t\tconst lngLat = getLngLatFromEvent(event);\n\n\t\t// If the pointer event is outside the container or the underlying library is\n\t\t// not ready we can get null as a returned value\n\t\tif (lngLat === null) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this.featuresAtLocation(lngLat, options);\n\t}\n\n\t/**\n\t * A method for stopping Terra Draw. Will clear the store, deregister the adapter and\n\t * remove any rendered layers in the process.\n\t */\n\tstop() {\n\t\t// If the instance is already stopped, we do nothing\n\t\tif (!this._enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._enabled = false;\n\t\tthis._adapter.unregister();\n\t}\n\n\t/**\n\t * Registers a Terra Draw event\n\t *\n\t * @param event - The name of the event you wish to listen for\n\t * @param callback - The callback with you wish to be called when this event occurs\n\t *\n\t */\n\ton<T extends TerraDrawEvents>(\n\t\tevent: T,\n\t\tcallback: TerraDrawEventListeners[T],\n\t) {\n\t\tconst listeners = this._eventListeners[\n\t\t\tevent\n\t\t] as TerraDrawEventListeners[T][];\n\t\tif (!listeners.includes(callback)) {\n\t\t\tlisteners.push(callback);\n\t\t}\n\t}\n\n\t/**\n\t * Unregisters a Terra Draw event\n\t *\n\t * @param event - The name of the event you wish to unregister\n\t * @param callback - The callback you originally provided to the 'on' method\n\t *\n\t */\n\toff<T extends TerraDrawEvents>(\n\t\tevent: TerraDrawEvents,\n\t\tcallback: TerraDrawEventListeners[T],\n\t) {\n\t\tconst listeners = this._eventListeners[\n\t\t\tevent\n\t\t] as TerraDrawEventListeners[T][];\n\t\tif (listeners.includes(callback)) {\n\t\t\tlisteners.splice(listeners.indexOf(callback), 1);\n\t\t}\n\t}\n}\n\nexport {\n\tTerraDraw,\n\tIdStrategy,\n\tTerraDrawEvents,\n\tTerraDrawEventListeners,\n\n\t// Modes\n\tTerraDrawSelectMode,\n\tTerraDrawPointMode,\n\tTerraDrawLineStringMode,\n\tTerraDrawPolygonMode,\n\tTerraDrawCircleMode,\n\tTerraDrawFreehandMode,\n\tTerraDrawRenderMode,\n\tTerraDrawRectangleMode,\n\tTerraDrawAngledRectangleMode,\n\tTerraDrawSectorMode,\n\tTerraDrawSensorMode,\n\n\t// Types that are required for 3rd party developers to extend\n\tTerraDrawExtend,\n\n\t// TerraDrawBaseMode\n\tBehaviorConfig,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tHexColor,\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\n\t// TerraDrawBaseAdapter\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tProject,\n\tUnproject,\n\tSetCursor,\n\tGetLngLatFromEvent,\n\n\t// Validations\n\tValidateMinAreaSquareMeters,\n\tValidateMaxAreaSquareMeters,\n\tValidateNotSelfIntersecting,\n\tValidationReasons,\n};\n","import { Validation } from \"../common\";\nimport { polygonAreaSquareMeters } from \"../geometry/measure/area\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport { ValidationReasonFeatureNotPolygon } from \"./common-validations\";\n\nexport const ValidationMaxAreaSquareMetersReason =\n\t\"Feature is larger than the maximum area\";\n\nexport const ValidateMaxAreaSquareMeters = (\n\tfeature: GeoJSONStoreFeatures,\n\tmaxSize: number,\n): ReturnType<Validation> => {\n\tif (feature.geometry.type !== \"Polygon\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPolygon,\n\t\t};\n\t}\n\n\tconst size = polygonAreaSquareMeters(feature.geometry);\n\n\tif (size > maxSize) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationMaxAreaSquareMetersReason,\n\t\t};\n\t}\n\n\treturn { valid: true };\n};\n"],"names":["UpdateTypes","SELECT_PROPERTIES","SELECTED","MID_POINT","SELECTION_POINT_FEATURE_ID","SELECTION_POINT","COMMON_PROPERTIES","Z_INDEX","isObject","feature","Boolean","Array","isArray","hasModeProperty","properties","isValidTimestamp","timestamp","isNaN","Date","valueOf","dateIsValid","ModeTypes","ValidationReasonFeatureNotPolygon","ValidationReasonModeMismatch","DefaultPointerEvents","rightClick","contextMenu","leftClick","onDragStart","onDrag","onDragEnd","TerraDrawBaseDrawMode","options","willCallUpdateOptionsInParentClass","this","_state","_styles","pointerEvents","behaviors","validate","pointerDistance","coordinatePrecision","onStyleChange","store","projection","setDoubleClickToZoom","unproject","project","setCursor","type","Drawing","mode","updateOptions","_proto","prototype","registerBehaviors","behaviorConfig","styles","_extends","validation","undefined","allowPointerEvent","pointerEvent","event","setDrawing","Error","setStarted","setStopped","register","config","registerOnChange","onChange","onSelect","onDeselect","onFinish","validateFeature","performFeatureValidation","afterFeatureAdded","validStoreFeature","isValidId","error","id","geometry","includes","coordinates","valid","reason","isValidStoreFeature","idStrategy","updateType","Provisional","validateModeFeature","modeValidationFn","finishedId","context","deselectedId","selectedId","onKeyDown","onKeyUp","onMouseMove","onClick","setMapDraggability","getHexColorStylingValue","value","defaultValue","getStylingValue","getNumericStylingValue","_createClass","key","get","set","_","styling","TerraDrawBaseSelectMode","_TerraDrawBaseDrawMod","_len","_this","arguments","length","args","_key","call","apply","concat","Select","_inheritsLoose","haversineDistanceKilometers","pointOne","pointTwo","toRadians","latOrLng","Math","PI","phiOne","lambdaOne","phiTwo","deltaPhi","deltalambda","a","sin","cos","atan2","sqrt","earthRadius","degreesToRadians","degrees","lengthToRadians","distance","radiansToDegrees","radians","limitPrecision","num","decimalLimit","decimals","pow","round","RADIANS_TO_DEGREES","DEGREES_TO_RADIANS","R","lngLatToWebMercatorXY","lng","lat","x","y","log","tan","webMercatorXYToLngLat","atan","exp","destination","origin","bearing","longitude1","latitude1","bearingRad","latitude2","asin","circle","center","radiusKilometers","steps","i","circleCoordinate","push","selfIntersects","coord","output","ring0","edge0","ring1","edge1","ifInteresctionAddToOutput","isOutside","frac","frac1","start0","end0","start1","end1","intersection","equalArrays","x0","y0","x1","y1","x2","y2","x3","y3","denom","intersect","toString","array1","array2","coordinatePrecisionIsValid","coordinate","getDecimalPlaces","coordinateIsValid","Infinity","current","precision","ValidationReasonFeatureHasHoles","ValidationReasonFeatureLessThanFourCoordinates","ValidationReasonFeatureHasInvalidCoordinates","ValidationReasonFeatureCoordinatesNotClosed","ValidatePolygonFeature","coordinateOne","coordinateTwo","ValidateNonIntersectingPolygonFeature","validatePolygonFeature","defaultKeyEvents","cancel","finish","defaultCursors","start","TerraDrawCircleMode","clickCount","currentCircleId","keyEvents","cursors","startingRadiusKilometers","cursorMovedAfterInitialCursorDown","close","currentGeometry","getGeometryCopy","Finish","state","action","stop","cleanUp","button","isContextMenu","startingCircle","_this$store$create","create","updateCircle","cleanUpId","_unused","styleFeature","getDefaultStyling","polygonFillColor","polygonOutlineColor","polygonOutlineWidth","polygonFillOpacity","pointColor","pointOutlineColor","pointOutlineWidth","pointWidth","lineStringColor","lineStringWidth","zIndex","fillColor","outlineColor","outlineWidth","fillOpacity","_this2","baseValidatedFeature","updatedCircle","newRadius","distortion","source","target","geodesicDistance","_lngLatToWebMercatorX","_lngLatToWebMercatorX2","calculateWebMercatorDistortion","radiusMeters","angle","dx","dy","_webMercatorXYToLngLa","circleWebMercator","updateGeometry","updateProperty","property","cartesianDistance","ensureRightHandRule","polygon","isFollowingRightHandRule","outerRing","sum","_outerRing$i","_outerRing","followsRightHandRule","reverse","TerraDrawFreehandMode","startingClick","currentId","closingPointId","minDistance","preventPointsNearClose","autoClose","autoCloseTimeout","hasLeftStartingPoint","preventNewFeature","correctedGeometry","currentLineGeometry","_currentLineGeometry$","_this$project","containerX","containerY","_currentLineGeometry$2","_this$project2","closingLat","setTimeout","pop","newGeometry","_properties","cleanUpClosingPointId","closingPointWidth","closingPointColor","closingPointOutlineColor","closingPointOutlineWidth","_this3","TerraDrawModeBehavior","_ref","createBBoxFromPoint","point","halfDist","map","c","ClickBoundingBoxBehavior","_TerraDrawModeBehavio","PixelDistanceBehavior","measure","clickEvent","secondCoordinate","CoordinateSnappingBehavior","pixelDistance","clickBoundingBox","getSnappableCoordinateFirstClick","getSnappable","getSnappableCoordinate","currentFeatureId","filter","bbox","features","search","closest","featureId","featureCoordinateIndex","minDist","forEach","coordIndex","dist","webMercatorDestination","end","lon1","lon2","lat1","lat2","b","webMercatorBearing","_ref2","deltaX","deltaY","normalizeBearing","lineSliceAlong","coords","startDist","stopDist","overshot","direction","interpolated","slice","origCoordsLength","travelled","last","toDegrees","InsertCoordinatesBehavior","generateInsertionCoordinates","segmentLength","line","lineLength","numberOfSegments","Number","isInteger","floor","segments","outline","limitCoordinates","generateInsertionGeodesicCoordinates","numberOfPoints","points","d","f","A","B","z","lon","generateGreatCircleCoordinates","coordinatesIdentical","ValidateLineStringFeature","magnitude","v","v1","v2","theta","v2y","v1z","dot","acos","min","max","lngLatToVector","vectorToLngLat","LineSnappingBehavior","boundingBox","nearest","lines","lngLat","inputCoordinate","_step","pointA","pointB","lineVector","targetVector","dotProduct","t","closestPoint","closestDistance","lineIndex","_iterator","_createForOfIteratorHelperLoose","done","startPosition","stopPosition","intersectPosition","intersectDistance","_findNearestPointOnLi","indexOf","webMercatorNearestPointOnLine","posA","posB","posC","C","Cx","Cy","Cz","_cross","v1y","v2z","v2x","v1x","D","E","F","g","h","I1","I2","angleAB","angleAI1","angleBI1","angleAI2","angleBI2","I","nearestPointOnLine","dragStart","dragEnd","TerraDrawLineStringMode","currentCoordinate","snapping","mouseMove","insertCoordinates","lastCommitedCoordinates","snappedPointId","editable","editedFeatureId","editedFeatureCoordinateIndex","editedSnapType","editedInsertIndex","editedPointId","coordinateSnapping","insertPoint","lineSnapping","updateGeometries","Commit","closingPointCoordinate","updatedGeometry","geometries","generateInsertCoordinates","startCoord","endCoord","strategy","segmentDistance","insertedCoordinates","createLine","startingCoord","createdId","firstUpdateToLine","updatedCoord","currentCoordinates","_this$store$create2","initialLineCoordinates","updateToLine","cursorXY","updatedLineCoordinates","snappedCoordinate","snapCoordinate","_this$store$create3","_currentCoordinates","onRightClick","_this$coordinateSnapp","lineStringFilter","coordinateIndex","splice","onLeftClick","updatedCoordinate","lineSnapped","coordinateSnapped","_properties2","_this$store$create4","featureCopy","newLineStringGeometry","getPropertiesCopy","cleanupClosingPointId","isClosingPoint","snappingPointColor","snappingPointWidth","snappingPointOutlineColor","snappingPointOutlineWidth","_this4","_this$snapping","_this$snapping2","_this$snapping3","snapped","_this5","toLine","toCoordinate","toCustom","getCurrentGeometrySnapshot","ValidationReasonFeatureNotPoint","ValidationReasonFeatureInvalidCoordinates","ValidationReasonFeatureInvalidCoordinatePrecision","ValidatePointFeature","TerraDrawPointMode","nearestPointFeature","getNearestPointFeature","isEdited","editedPointWidth","editedPointColor","editedPointOutlineColor","editedPointOutlineWidth","clickedFeature","distanceToFeature","ClosingPointsBehavior","_startEndPoints","selectedCoords","ids","update","updatedCoordinates","opening","closing","distancePrevious","isClosing","isPreviousClosing","CoordinatePointBehavior","createOrUpdate","existingFeature","existingProperties","existingFeatureProps","existingCoordinatePointIds","coordinatePointIds","every","has","existingCoordinates","existingCoordinatePoints","deleteCoordinatePoints","createPoints","setFeatureCoordinatePoints","existingPoints","deletePointsByFeatureIds","deleteIfPresent","getUpdated","featureProperties","index","coordinatePoints","TerraDrawPolygonMode","showCoordinatePoints","closingPoints","copyAllWhere","featuresWithCoordinates","currentPolygonCoordinates","updatePolygonGeometry","epsilon","offset","_this$closingPoints$i","polygonFilter","shift","newId","currentPolygonGeometry","_this$closingPoints$i2","updatedPolygon","featureCoordinates","newPolygonGeometry","editedPoint","coordinatePoint","pointType","styleMap","width","color","closingPoint","snappingPoint","coordinatePointWidth","coordinatePointColor","coordinatePointOutlineColor","coordinatePointOutlineWidth","_this6","TerraDrawRectangleMode","currentRectangleId","updateRectangle","firstCoord","TerraDrawRenderMode","modeName","Render","validationResult","validatedFeature","featureIsValid","rhumbBearing","from","to","phi1","phi2","deltaLambda","deltaPsi","bear360","rhumbDestination","distanceMeters","distanceInMeters","abs","delta","lambda1","DeltaPhi","DeltaPsi","q","midpointCoordinate","coordinates1","coordinates2","projectedCoordinateOne","projectedCoordinateTwo","_unproject","geodesicMidpointCoordinate","midpoint","getMidPointCoordinates","featureCoords","midPointCoords","mid","MidPointBehavior","selectionPointBehavior","coordinatePointBehavior","_midPoints","insert","midPointId","midPoint","_this$store$getProper","midPointFeatureId","midPointSegment","getMidPoints","updatedMidPointCoord","SelectionPointBehavior","_selectionPoints","geometryType","selectionPoints","getCoordinatesAsPoints","getOneUpdated","pointInPolygon","rings","p","p1","p2","inside","len","ring","j","len2","k","pixelDistanceToLine","linePointOne","linePointTwo","square","dist2","w","l2","distToSegmentSquared","FeatureAtPointerEventBehavior","createClickBoundingBox","find","hasSelection","clickedPoint","clickedPointDistance","clickedLineString","clickedLineStringDistance","clickedMidPoint","clickedMidPointDistance","clickedPolygon","selectionPoint","nextCoord","distanceToLine","DragFeatureBehavior","featuresAtCursorEvent","midPoints","draggedFeatureId","dragPosition","startDragging","stopDragging","isDragging","canDrag","drag","cursorCoord","updatedCoords","upToCoord","updatedLng","updatedLat","webMercatorDragPosition","webMercatorCursorCoord","webMercatorCoordinate","updatedSelectionPoints","updatedMidPoints","updatedCoordinatePoints","DragCoordinateBehavior","draggedCoordinate","getClosestCoordinate","geomCoordinates","closestCoordinate","isFirstOrLastPolygonCoord","getDraggableIndex","draggedFeature","allowSelfIntersection","lastCoordIndex","updatedSelectionPoint","centroid","geojson","xSum","ySum","webMercatorCentroid","webMercatorCoordinates","area","centroidX","centroidY","n","_webMercatorCoordinat","_webMercatorCoordinat2","crossProduct","calculatePolygonCentroid","lineString","totalX","totalY","_lineString$i","calculateLineStringMidpoint","RotateFeatureBehavior","lastBearing","selectedGeometry","selectedGeometryCentroid","selectedGeometryWebMercatorCentroid","reset","rotate","mouseCoord","cursorWebMercator","angleRad","webMercatorCoords","reduce","acc","rotatedCoordinates","transformRotateWebMercator","pivot","pointCoords","finalAngle","DeltaLambda","rhumbDistance","newCoords","transformRotate","ScaleFeatureBehavior","dragCoordinateResizeBehavior","scale","DragCoordinateResizeBehavior","minimumScale","boundingBoxMaps","opposite","isValidDragWebMercator","distanceX","distanceY","getSelectedFeatureDataWebMercator","getFeature","getNormalisedCoordinates","getBBoxWebMercator","selectedCoordinate","centerWebMercatorDrag","featureData","webMercatorOrigin","webMercatorSelected","closestBBoxIndex","getIndexesWebMercator","webMercatorCursor","scaleWebMercator","centerFixedWebMercatorDrag","scaleFixedWebMercator","performWebMercatorScale","oppositeFixedWebMercatorDrag","_this$getIndexesWebMe3","oppositeBboxIndex","oppositeWebMercatorDrag","_this$getIndexesWebMe4","cursorDistanceX","cursorDistanceY","xScale","yScale","validateScale","validX","MAX_SAFE_INTEGER","validY","originX","originY","_ref3","west","south","east","north","selectedXY","closestIndex","resizeOption","deselect","delete","pointerOver","insertMidpoint","TerraDrawSelectMode","_TerraDrawBaseSelectM","allowManualDeselection","dragEventThrottle","dragEventCount","selected","flags","validations","coordinateSnap","featuresAtMouseEvent","dragFeature","dragCoordinate","rotateFeature","scaleFeature","dragCoordinateResizeFeature","lineSnap","selectFeature","select","setSelecting","deselectFeature","updateSelectedFeatures","deleteSelected","clickedSelectionPointProps","clickedFeatureDistance","selectionPointFeatureId","modeFlags","deletable","deletePoints","midpoints","fromCursor","previouslySelectedId","_this$store$getGeomet","_this$featuresAtMouse","canScale","heldKeys","canRotate","preventDefaultKeyEvent","isRotationKeys","isScaleKeys","preventDefault","draggable","resizable","draggableCoordinateIndex","draggedMidPoint","draggableCoordinateIndexAfterInsert","canSelfIntersect","selfIntersectable","rotateable","scaleable","_modeFlags$feature","snappable","snapOptions","nearbyMidPoint","nearbySelectionPoint","featureUnderPointer","selectionPointColor","selectionPointOutlineColor","selectionPointWidth","selectionPointOutlineWidth","midPointColor","midPointOutlineColor","midPointWidth","midPointOutlineWidth","selectedPolygonColor","selectedPolygonOutlineWidth","selectedPolygonOutlineColor","selectedPolygonFillOpacity","selectedLineStringColor","selectedLineStringWidth","selectedPointWidth","selectedPointColor","selectedPointOutlineColor","selectedPointOutlineWidth","TerraDrawStaticMode","Static","quickselect","arr","left","right","compare","m","s","sd","swap","tmp","calcBBox","node","toBBox","distBBox","children","destNode","createNode","minX","minY","maxX","maxY","child","extend","leaf","compareNodeMinX","compareNodeMinY","bboxArea","bboxMargin","contains","intersects","height","multiSelect","stack","ceil","RBush","maxEntries","_maxEntries","_minEntries","data","clear","result","nodesToSearch","childBBox","_all","collides","load","_build","_splitRoot","tmpNode","_insert","item","remove","parent","path","indexes","goingUp","_condense","compareMinX","compareMinY","items","N","M","N2","N1","right2","right3","_chooseSubtree","level","minArea","minEnlargement","targetNode","enlargement","isNode","insertPath","_split","_adjustParentBBoxes","_chooseSplitAxis","splitIndex","_chooseSplitIndex","newNode","minOverlap","bbox1","bbox2","overlap","_allDistMargin","sort","leftBBox","rightBBox","margin","siblings","SpatialIndex","tree","idToNode","nodeToId","Map","setMaps","longitudes","latitudes","minLat","maxLat","String","seenIds","Set","add","defaultIdStrategy","getId","replace","r","random","GeoJSONStore","tracked","spatialIndex","_onChange","clone","obj","JSON","parse","stringify","featureValidation","clonedData","changes","createdAt","updatedAt","change","propertiesToUpdate","geometriesToUpdate","createdProperties","copy","copyAll","_this7","Object","keys","equals","_this8","size","polygonAreaSquareMeters","total","ringArea","FACTOR","PI_OVER_180","coordsLength","ValidationReasonFeatureLessThanMinSize","ValidationReasonFeatureNotPolygonOrLineString","ValidationReasonFeatureSelfIntersects","calculateRelativeAngle","bearingAB","relativeAngle","TerraDrawAngledRectangleMode","lineStart","lineEnd","firstCoordinate","ACloserThanC","hypotenuse","adjacent","rectangleAngle","thirdCoordinateXY","fourthCoordinateXY","thirdCoordinate","fourthCoordinate","isClockwiseWebMercator","secondCoord","thirdCoord","TerraDrawSectorMode","arcPoints","arcCoordOne","arcCoordTwo","webMercatorCenter","webMercatorArcCoordOne","webMercatorArcCoordTwo","clockwise","deltaBearing","radius","startBearing","endBearing","normalizedStart","normalizedEnd","bearingStep","pointOnArc","TerraDrawSensorMode","currentInitialArcId","currentStartingPointId","finishedCurrentStartingPointId","finishedInitialArcId","finishedCurrentId","updateLineStringGeometry","lastCoord","webMercatorCoordOne","webMercatorCoordTwo","innerRadius","radiusCalculationPosition","cursorBearing","normalizedCursor","notInSector","getDeltaBearing","finalArc","_webMercatorXYToLngLa2","unshift","centerPointColor","centerPointWidth","centerPointOutlineColor","centerPointOutlineWidth","AdapterListener","name","callback","unregister","registered","TerraDrawBaseAdapter","_nextKeyUpIsContextMenu","_minPixelDragDistance","_minPixelDragDistanceDrawing","_minPixelDragDistanceSelecting","_lastDrawEvent","_coordinatePrecision","_heldKeys","_listeners","_dragState","_currentModeCallbacks","minPixelDragDistance","minPixelDragDistanceSelecting","minPixelDragDistanceDrawing","getButton","getMapElementXYPosition","_mapElement$getBoundi","getMapEventElement","getBoundingClientRect","clientX","clientY","top","getDrawEventFromEvent","latLng","getLngLatFromEvent","_this$getMapElementXY","callbacks","getAdapterListeners","listener","getCoordinatePrecision","isPrimary","drawEvent","addEventListener","removeEventListener","lastEventXY","currentEventXY","modeState","getState","pixelDistanceToCheck","enabled","setDraggability","bind","ValidationReasons","TerraDraw","_modes","_mode","_adapter","_enabled","_store","_eventListeners","_instanceSelectMode","adapter","duplicateModeTracker","modesMap","modes","modeMap","currentMode","modeKeys","static","ready","getChanged","changed","unchanged","_getChanged","render","created","deletedIds","updated","getModeStyles","_getChanged2","_getChanged3","modeId","checkEnabled","modeStyles","featuresAtLocation","ignoreSelectFeatures","inputPoint","pointCoordinates","pointXY","getSelectMode","getMode","setMode","setModeStyles","updateModeOptions","getSnapshot","getSnapshotFeature","getModeState","removeFeatures","coordinatePointsToDelete","getFeatureId","hasFeature","addFeatures","featureMode","modeToAddTo","onReady","onClear","getFeaturesAtLngLat","getFeaturesAtPointerEvent","on","listeners","off","maxSize","minSize"],"mappings":"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"}