{"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/transform/rotate.ts","../src/geometry/web-mercator-centroid.ts","../src/modes/select/behaviors/rotate-feature.behavior.ts","../src/geometry/measure/rhumb-distance.ts","../src/modes/select/behaviors/scale-feature.behavior.ts","../src/geometry/transform/scale.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/modes/freehand-linestring/freehand-linestring.mode.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\tCURRENTLY_DRAWING: \"currentlyDrawing\",\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\tafterFeatureUpdated(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\tCOMMON_PROPERTIES,\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\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.currentCircleId,\n\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\tvalue: undefined,\n\t\t\t},\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\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures): void {\n\t\t// If we are in the middle of drawing a circle and the feature being updated is the current circle,\n\t\t// we need to reset the drawing state\n\t\tif (this.currentCircleId === feature.id) {\n\t\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\t\tthis.center = undefined;\n\t\t\tthis.currentCircleId = undefined;\n\t\t\tthis.clickCount = 0;\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\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\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\t\tvalue: undefined,\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\tthis.setCursor(this.cursors.start);\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: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\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\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\n\t\t\t\t// We could already be in drawing due to updating the existing polygon\n\t\t\t\t// via afterFeatureUpdated\n\t\t\t\tif (this.state !== \"drawing\") {\n\t\t\t\t\tthis.setDrawing();\n\t\t\t\t}\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// NOTE: This handles the case we are currently drawing a polygon\n\t\t// We need to reset the drawing state because it is very complicated (impossible?)\n\t\t// to recover the drawing state after a feature update\n\t\tif (this.currentId === feature.id) {\n\t\t\tif (this.closingPointId) {\n\t\t\t\tthis.store.delete([this.closingPointId]);\n\t\t\t}\n\t\t\tthis.startingClick = false;\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.closingPointId = undefined;\n\t\t\tthis.hasLeftStartingPoint = false;\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\";\nimport { limitPrecision } from \"../geometry/limit-decimal-precision\";\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\t\t? [\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tsnappable.coordinate[0],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tsnappable.coordinate[1],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: undefined;\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\t\t? [\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tsnappable.coordinate[0],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tsnappable.coordinate[1],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: undefined;\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 = [\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tnearest.coordinate[0],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t\tlimitPrecision(\n\t\t\t\t\t\tnearest.coordinate[1],\n\t\t\t\t\t\tthis.config.coordinatePrecision,\n\t\t\t\t\t),\n\t\t\t\t];\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\tZ_INDEX,\n\tSnapping,\n\tCOMMON_PROPERTIES,\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 lastCommittedCoordinates: Position[] | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\tprivate lastMouseMoveEvent: TerraDrawMouseEvent | 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 updateSnappedCoordinate(event: TerraDrawMouseEvent) {\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\treturn snappedCoordinate;\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\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\tvalue: undefined,\n\t\t\t},\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.lastCommittedCoordinates = 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.lastCommittedCoordinates = 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.lastCommittedCoordinates) {\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: {\n\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true, // This is the current line being drawn\n\t\t\t\t},\n\t\t\t},\n\t\t]);\n\t\tthis.lastCommittedCoordinates = [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.lastCommittedCoordinates\n\t\t\t? this.lastCommittedCoordinates[this.lastCommittedCoordinates.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\t\tthis.lastMouseMoveEvent = event;\n\n\t\tconst snappedCoordinate = this.updateSnappedCoordinate(event);\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.lastCommittedCoordinates\n\t\t) {\n\t\t\tconst startCoord =\n\t\t\t\tthis.lastCommittedCoordinates[this.lastCommittedCoordinates.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.lastCommittedCoordinates.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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// Clean up here is important to get right as we need to make a best effort to avoid erroneous\n\t\t// internal state.\n\n\t\t// If we are editing a feature by dragging one of its points\n\t\t// we want to clear that state up as new polygon might be completely\n\t\t// different in terms of it's coordinates\n\t\tif (this.editedFeatureId === feature.id && this.editedPointId) {\n\t\t\tthis.store.delete([this.editedPointId]);\n\t\t\tthis.editedPointId = undefined;\n\t\t\tthis.editedFeatureId = undefined;\n\t\t\tthis.editedFeatureCoordinateIndex = undefined;\n\t\t\tthis.editedSnapType = undefined;\n\t\t}\n\n\t\t// We can recalculate the snapped point from the last mouse event if there was one\n\t\tif (this.snappedPointId && this.lastMouseMoveEvent) {\n\t\t\tthis.updateSnappedCoordinate(\n\t\t\t\tthis.lastMouseMoveEvent as TerraDrawMouseEvent,\n\t\t\t);\n\t\t}\n\n\t\t// NOTE: This handles the case we are currently drawing a polygon\n\t\t// We need to reset the drawing state because it is very complicated (impossible?)\n\t\t// to recover the drawing state after a feature update\n\t\tif (this.currentId === feature.id) {\n\t\t\tif (this.closingPointId) {\n\t\t\t\tthis.store.delete([this.closingPointId]);\n\t\t\t\tthis.closingPointId = undefined;\n\t\t\t}\n\n\t\t\tthis.currentCoordinate = 0;\n\t\t\tthis.currentId = undefined;\n\n\t\t\t// Go back to started state\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\n\t\t\t}\n\t\t}\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// If we are editing a point by dragging it we want to clear that state\n\t\t// up as new point location might be completely  different in terms of it's location\n\t\tif (this.editedFeatureId === feature.id) {\n\t\t\tthis.editedFeatureId = undefined;\n\t\t\tthis.setCursor(this.cursors.create);\n\t\t}\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\tprivate lastMouseMoveEvent: TerraDrawMouseEvent | undefined;\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\n\t\t\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\t\tvalue: undefined,\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\tprivate updateSnappedCoordinate(event: TerraDrawMouseEvent) {\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\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tthis.lastMouseMoveEvent = event;\n\t\tthis.updateSnappedCoordinate(event);\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 || 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.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: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\n\t\t\t\t\t},\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\t// Here we reuse the snapping logic to find the feature and coordinate\n\t\t\t// that we want to edit. We can drag a arbitrary polygon coordinate point\n\t\t\t// or an arbitrary point on one of its 'lines\n\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// Clean up here is important to get right as we need to make a best effort to avoid erroneous\n\t\t// internal state.\n\n\t\t// IF we have coordinate points showing these need to be completely recreated\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(feature.id as FeatureId);\n\t\t}\n\n\t\t// If we are editing a feature by dragging one of its points\n\t\t// we want to clear that state up as new polygon might be completely\n\t\t// different in terms of it's coordinates\n\t\tif (this.editedFeatureId === feature.id && this.editedPointId) {\n\t\t\tthis.store.delete([this.editedPointId]);\n\t\t\tthis.editedPointId = undefined;\n\t\t\tthis.editedFeatureId = undefined;\n\t\t\tthis.editedFeatureCoordinateIndex = undefined;\n\t\t\tthis.editedSnapType = undefined;\n\t\t}\n\n\t\t// We can recalculate the snapped point from the last mouse event if there was one\n\t\tif (this.snappedPointId && this.lastMouseMoveEvent) {\n\t\t\tthis.updateSnappedCoordinate(\n\t\t\t\tthis.lastMouseMoveEvent as TerraDrawMouseEvent,\n\t\t\t);\n\t\t}\n\n\t\t// NOTE: This handles the case we are currently drawing a polygon\n\t\t// We need to reset the drawing state because it is very complicated (impossible?)\n\t\t// to recover the drawing state after a feature update\n\t\tif (this.currentId === feature.id) {\n\t\t\tthis.currentCoordinate = 0;\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.closingPoints.delete();\n\n\t\t\t// Go back to started state\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\n\t\t\t}\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\tCOMMON_PROPERTIES,\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\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\t\tvalue: undefined,\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\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures): void {\n\t\t// If we are in the middle of drawing a rectangle and the feature being updated is the current rectangle,\n\t\t// we need to reset the drawing state\n\t\tif (this.currentRectangleId === feature.id) {\n\t\t\tthis.center = undefined;\n\t\t\tthis.currentRectangleId = undefined;\n\t\t\tthis.clickCount = 0;\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\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 { 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 { 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 { 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 { Position } from \"geojson\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\n\nexport function transformScaleWebMercatorCoordinates({\n\tcoordinates,\n\toriginX,\n\toriginY,\n\txScale,\n\tyScale,\n}: {\n\tcoordinates: Position[];\n\toriginX: number;\n\toriginY: number;\n\txScale: number;\n\tyScale: number;\n}): void {\n\tif (xScale === 1 && yScale === 1) {\n\t\t// No scaling needed, return early\n\t\treturn;\n\t}\n\n\tcoordinates.forEach((coordinate) => {\n\t\tconst { x, y } = lngLatToWebMercatorXY(coordinate[0], coordinate[1]);\n\n\t\tconst updatedX = originX + (x - originX) * xScale;\n\t\tconst updatedY = originY + (y - originY) * yScale;\n\n\t\tconst { lng, lat } = webMercatorXYToLngLat(updatedX, updatedY);\n\n\t\tcoordinate[0] = lng;\n\t\tcoordinate[1] = lat;\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\";\nimport { transformScaleWebMercatorCoordinates } from \"../../../geometry/transform/scale\";\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\ttransformScaleWebMercatorCoordinates({\n\t\t\tcoordinates: updatedCoords,\n\t\t\toriginX: webMercatorOrigin.x,\n\t\t\toriginY: webMercatorOrigin.y,\n\t\t\txScale: scale,\n\t\t\tyScale: scale,\n\t\t});\n\n\t\t// this.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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// If we have a selected feature and it has been updated\n\t\t// we need to update the selection points and midpoints\n\t\tif (this.selected.length && feature.id === this.selected[0]) {\n\t\t\tconst flags = this.flags[feature.properties.mode as string];\n\n\t\t\tif (!flags?.feature?.coordinates) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst type = feature.geometry.type as \"Polygon\" | \"LineString\";\n\t\t\tconst id = feature.id as FeatureId;\n\n\t\t\tthis.selectionPoints.delete();\n\t\t\tthis.midPoints.delete();\n\n\t\t\tlet coordinates: Position[] | undefined;\n\t\t\tif (type === \"Polygon\") {\n\t\t\t\t// For Polygon we need to take the first item in the coordinates array\n\t\t\t\tcoordinates = feature.geometry.coordinates[0] as Position[];\n\t\t\t} else if (type === \"LineString\") {\n\t\t\t\t// For LineString we can take the coordinates directly\n\t\t\t\tcoordinates = feature.geometry.coordinates as Position[];\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.selectionPoints.create(coordinates, type, id);\n\n\t\t\tif (flags?.feature?.coordinates?.midpoints) {\n\t\t\t\tthis.midPoints.create(\n\t\t\t\t\t(type === \"Polygon\"\n\t\t\t\t\t\t? feature.geometry.coordinates[0]\n\t\t\t\t\t\t: feature.geometry.coordinates) as Position[],\n\t\t\t\t\tid,\n\t\t\t\t\tthis.coordinatePrecision,\n\t\t\t\t);\n\t\t\t}\n\t\t}\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: {\n\t\t\tid: FeatureId;\n\t\t\tproperty: string;\n\t\t\tvalue: JSON | undefined;\n\t\t}[],\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\tif (value === undefined) {\n\t\t\t\tdelete feature.properties[property];\n\t\t\t} else {\n\t\t\t\tfeature.properties[property] = value;\n\t\t\t}\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\tCOMMON_PROPERTIES,\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\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\tvalue: undefined,\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\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: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\n\t\t\t\t\t\t},\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures): void {\n\t\t// If we are in the middle of drawing a rectangle and the feature being updated is the current rectangle,\n\t\t// we need to reset the drawing state\n\t\tif (this.currentId === feature.id) {\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.currentCoordinate = 0;\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\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\tCOMMON_PROPERTIES,\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\t\tthis.store.updateProperty([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\tvalue: undefined,\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: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\n\t\t\t\t\t\t},\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures): void {\n\t\t// If we are in the middle of drawing a sector and the feature being updated is the current sector,\n\t\t// we need to reset the drawing state\n\t\tif (this.currentId === feature.id) {\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.direction = undefined;\n\t\t\tthis.currentCoordinate = 0;\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\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\tCOMMON_PROPERTIES,\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\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\t\tvalue: undefined,\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: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\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\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\tafterFeatureUpdated(feature: GeoJSONStoreFeatures): void {\n\t\t// If we are in the middle of drawing a sensor and the feature being updated is the current sensor,\n\t\t// we need to reset the drawing state\n\t\tif (this.currentId === feature.id) {\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\n\t\t\tthis.currentStartingPointId = undefined;\n\t\t\tthis.direction = undefined;\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.currentCoordinate = 0;\n\n\t\t\tif (this.state === \"drawing\") {\n\t\t\t\tthis.setStarted();\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","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 { LineString } 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 { ValidateLineStringFeature } from \"../../validations/linestring.validation\";\n\ntype TerraDrawFreehandLineStringModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype FreehandLineStringStyling = {\n\tlineStringWidth: NumericStyling;\n\tlineStringColor: HexColorStyling;\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 TerraDrawFreehandLineStringModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tminDistance?: number;\n\tkeyEvents?: TerraDrawFreehandLineStringModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawFreehandLineStringMode extends TerraDrawBaseDrawMode<FreehandLineStringStyling> {\n\tmode = \"freehand-linestring\" 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: TerraDrawFreehandLineStringModeKeyEvents =\n\t\tdefaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate preventNewFeature = false;\n\n\tconstructor(\n\t\toptions?: TerraDrawFreehandLineStringModeOptions<FreehandLineStringStyling>,\n\t) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tpublic updateOptions(\n\t\toptions?:\n\t\t\t| TerraDrawFreehandLineStringModeOptions<FreehandLineStringStyling>\n\t\t\t| 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?.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\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tproperty: COMMON_PROPERTIES.CURRENTLY_DRAWING,\n\t\t\t\t\tvalue: undefined,\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 =\n\t\t\t\tthis.store.getGeometryCopy<LineString>(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\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\tthis.setCursor(this.cursors.start);\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 previousIndex = currentLineGeometry.coordinates.length - 2;\n\t\tconst [previousLng, previousLat] =\n\t\t\tcurrentLineGeometry.coordinates[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] =\n\t\t\tcurrentLineGeometry.coordinates[\n\t\t\t\tcurrentLineGeometry.coordinates.length - 1\n\t\t\t];\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\tthis.setCursor(this.cursors.close);\n\t\t} else {\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\tconst newGeometry = {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates: [...currentLineGeometry.coordinates, [event.lng, event.lat]],\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\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\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.closingPointId,\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\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: \"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: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.CURRENTLY_DRAWING]: true,\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\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\n\t\t\t\t// We could already be in drawing due to updating the existing linestring\n\t\t\t\t// via afterFeatureUpdated\n\t\t\t\tif (this.state !== \"drawing\") {\n\t\t\t\t\tthis.setDrawing();\n\t\t\t\t}\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 === \"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\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\tValidateLineStringFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n\n\tafterFeatureUpdated(feature: GeoJSONStoreFeatures) {\n\t\t// NOTE: This handles the case we are currently drawing a linestring\n\t\t// We need to reset the drawing state because it is very complicated (impossible?)\n\t\t// to recover the drawing state after a feature update\n\t\tif (this.currentId === feature.id) {\n\t\t\tif (this.closingPointId) {\n\t\t\t\tthis.store.delete([this.closingPointId]);\n\t\t\t}\n\t\t\tthis.startingClick = false;\n\t\t\tthis.currentId = undefined;\n\t\t\tthis.closingPointId = undefined;\n\t\t}\n\t}\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\tProjection,\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 { Feature, LineString, Polygon, 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\";\nimport { TerraDrawFreehandLineStringMode } from \"./modes/freehand-linestring/freehand-linestring.mode\";\nimport { ScaleFeatureBehavior } from \"./modes/select/behaviors/scale-feature.behavior\";\nimport { DragCoordinateResizeBehavior } from \"./modes/select/behaviors/drag-coordinate-resize.behavior\";\nimport { PixelDistanceBehavior } from \"./modes/pixel-distance.behavior\";\nimport { SelectionPointBehavior } from \"./modes/select/behaviors/selection-point.behavior\";\nimport { MidPointBehavior } from \"./modes/select/behaviors/midpoint.behavior\";\nimport { CoordinatePointBehavior } from \"./modes/select/behaviors/coordinate-point.behavior\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"./geometry/project/web-mercator\";\nimport { transformRotateWebMercator } from \"./geometry/transform/rotate\";\nimport { transformScaleWebMercatorCoordinates } from \"./geometry/transform/scale\";\nimport { limitPrecision } from \"./geometry/limit-decimal-precision\";\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 GetFeatureOptions = {\n\tpointerDistance?: number;\n\tincludePolygonsWithinPointerDistance?: boolean;\n\tignoreSelectFeatures?: boolean;\n\tignoreCoordinatePoints?: boolean;\n\tignoreCurrentlyDrawing?: boolean;\n\tignoreClosingPoints?: boolean;\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?: GetFeatureOptions,\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 ignoreCoordinatePoints =\n\t\t\toptions && options.ignoreCoordinatePoints !== undefined\n\t\t\t\t? options.ignoreCoordinatePoints\n\t\t\t\t: false;\n\n\t\tconst ignoreCurrentlyDrawing =\n\t\t\toptions && options.ignoreCurrentlyDrawing !== undefined\n\t\t\t\t? options.ignoreCurrentlyDrawing\n\t\t\t\t: false;\n\n\t\tconst ignoreClosingPoints =\n\t\t\toptions && options.ignoreClosingPoints !== undefined\n\t\t\t\t? options.ignoreClosingPoints\n\t\t\t\t: false;\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\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 (\n\t\t\t\tignoreCoordinatePoints &&\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.COORDINATE_POINT]\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tignoreClosingPoints &&\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.CLOSING_POINT]\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tignoreCurrentlyDrawing &&\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.CURRENTLY_DRAWING]\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\n\t\t\t\tif (options?.includePolygonsWithinPointerDistance) {\n\t\t\t\t\tconst rings: Position[][] = feature.geometry.coordinates;\n\n\t\t\t\t\tfor (const ring of rings) {\n\t\t\t\t\t\tfor (let i = 0; i < ring.length - 1; i++) {\n\t\t\t\t\t\t\tconst coord = ring[i];\n\t\t\t\t\t\t\tconst nextCoord = ring[i + 1];\n\n\t\t\t\t\t\t\tconst projectedStart = project(coord[0], coord[1]);\n\t\t\t\t\t\t\tconst projectedEnd = project(nextCoord[0], nextCoord[1]);\n\n\t\t\t\t\t\t\tconst distanceToEdge = pixelDistanceToLine(\n\t\t\t\t\t\t\t\tinputPoint,\n\t\t\t\t\t\t\t\tprojectedStart,\n\t\t\t\t\t\t\t\tprojectedEnd,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tif (distanceToEdge < pointerDistance) {\n\t\t\t\t\t\t\t\treturn true;\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}\n\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate getSelectModeOrThrow() {\n\t\tconst selectMode = this.getSelectMode({ switchToSelectMode: true });\n\n\t\tif (!selectMode) {\n\t\t\tthrow new Error(\"No select mode defined in instance\");\n\t\t}\n\n\t\treturn selectMode;\n\t}\n\n\tprivate getSelectMode({\n\t\tswitchToSelectMode,\n\t}: {\n\t\tswitchToSelectMode: boolean;\n\t}) {\n\t\tthis.checkEnabled();\n\n\t\tif (!this._instanceSelectMode) {\n\t\t\treturn null;\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 (switchToSelectMode && 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\tprivate isGuidanceFeature(feature: GeoJSONStoreFeatures): boolean {\n\t\treturn Boolean(\n\t\t\tfeature.properties[SELECT_PROPERTIES.MID_POINT] ||\n\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTION_POINT] ||\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.COORDINATE_POINT] ||\n\t\t\t\tfeature.properties[COMMON_PROPERTIES.SNAPPING_POINT],\n\t\t);\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.getSelectModeOrThrow();\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.getSelectModeOrThrow();\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 * Updates a features geometry. This an be used to programmatically change the coordinates of a feature. This\n\t * can be useful for if you want to modify a geometry via a button or some similar user interaction.\n\t * @param id - the id of the feature to update the geometry for\n\t * @param geometry - the new geometry that will replace the existing geometry\n\t */\n\tupdateFeatureGeometry(id: FeatureId, geometry: GeoJSONStoreGeometries) {\n\t\tif (!this._store.has(id)) {\n\t\t\tthrow new Error(`No feature with id ${id} present in store`);\n\t\t}\n\n\t\tconst feature = this._store.copy(id);\n\n\t\t// We don't want users to be able to update guidance features directly\n\t\tif (this.isGuidanceFeature(feature)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Guidance features are not allowed to be updated directly.`,\n\t\t\t);\n\t\t}\n\n\t\t// Ensure that the geometry is valid\n\t\tif (!feature || !geometry || !geometry.type || !geometry.coordinates) {\n\t\t\tthrow new Error(\"Invalid geometry provided\");\n\t\t}\n\t\tif (geometry.type !== feature.geometry.type) {\n\t\t\tthrow new Error(\n\t\t\t\t`Geometry type mismatch: expected ${feature.geometry.type}, got ${geometry.type}`,\n\t\t\t);\n\t\t}\n\n\t\tconst mode = feature.properties.mode;\n\t\tconst modeToUpdate = this._modes[mode as string];\n\n\t\tif (!modeToUpdate) {\n\t\t\tthrow new Error(`No mode with name ${mode} present in instance`);\n\t\t}\n\n\t\tconst updatedFeature = { ...feature, geometry };\n\n\t\tconst validationResult = modeToUpdate.validateFeature(updatedFeature);\n\n\t\tif (!validationResult.valid) {\n\t\t\tthrow new Error(\n\t\t\t\t`Feature validation failed: ${validationResult.reason || \"Unknown reason\"}`,\n\t\t\t);\n\t\t}\n\n\t\tthis._store.updateGeometry(\n\t\t\t[{ id: feature.id as FeatureId, geometry }],\n\t\t\t{ origin: \"api\" }, // origin is used to indicate that this update has come from an API call\n\t\t);\n\n\t\t// If the mode has an afterFeatureUpdated method, we call it\n\t\tif (modeToUpdate.afterFeatureUpdated) {\n\t\t\tmodeToUpdate.afterFeatureUpdated(updatedFeature);\n\n\t\t\tconst featureIsSelected =\n\t\t\t\tupdatedFeature.properties[SELECT_PROPERTIES.SELECTED];\n\t\t\tconst selectModePresent = this.getSelectMode({\n\t\t\t\tswitchToSelectMode: false,\n\t\t\t});\n\n\t\t\tif (selectModePresent && featureIsSelected) {\n\t\t\t\tselectModePresent.afterFeatureUpdated(updatedFeature);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * A method for transforming a feature's geometry. This can be used to rotate or scale a feature's geometry.\n\t * This matches the functionality of the scale and rotate behaviors in the select mode.\n\t * @param id - the id of the feature to transform\n\t * @param transformation - the transformation to apply to the feature's geometry\n\t */\n\ttransformFeatureGeometry(\n\t\tid: FeatureId,\n\t\ttransformation:\n\t\t\t| {\n\t\t\t\t\tprojection?: Exclude<Projection, \"globe\">;\n\t\t\t\t\torigin: Position;\n\t\t\t\t\ttype: \"rotate\";\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tangle: number;\n\t\t\t\t\t};\n\t\t\t  }\n\t\t\t| {\n\t\t\t\t\tprojection?: Exclude<Projection, \"globe\">;\n\t\t\t\t\torigin: Position;\n\t\t\t\t\ttype: \"scale\";\n\t\t\t\t\toptions: {\n\t\t\t\t\t\txScale: number;\n\t\t\t\t\t\tyScale: number;\n\t\t\t\t\t};\n\t\t\t  },\n\t) {\n\t\tif (!this._store.has(id)) {\n\t\t\tthrow new Error(`No feature with id ${id} present in store`);\n\t\t}\n\n\t\tlet feature = this._store.copy(id);\n\n\t\t// We don't want users to be able to update guidance features directly\n\t\tif (this.isGuidanceFeature(feature)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Guidance features are not allowed to be updated directly.`,\n\t\t\t);\n\t\t}\n\n\t\tconst mode = feature.properties.mode;\n\t\tconst modeToUpdate = this._modes[mode as string];\n\n\t\tif (!modeToUpdate) {\n\t\t\tthrow new Error(`No mode with name ${mode} present in instance`);\n\t\t}\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 {\n\t\t\tthrow new Error(\n\t\t\t\t`Feature geometry type ${feature.geometry.type} is not supported for transformation`,\n\t\t\t);\n\t\t}\n\n\t\tif (transformation.projection == \"web-mercator\") {\n\t\t\tif (transformation.type === \"scale\") {\n\t\t\t\tconst { x: originX, y: originY } = lngLatToWebMercatorXY(\n\t\t\t\t\ttransformation.origin[0],\n\t\t\t\t\ttransformation.origin[1],\n\t\t\t\t);\n\n\t\t\t\tconst xScale = transformation.options.xScale || 1;\n\t\t\t\tconst yScale = transformation.options.yScale || 1;\n\n\t\t\t\ttransformScaleWebMercatorCoordinates({\n\t\t\t\t\tcoordinates,\n\t\t\t\t\toriginX,\n\t\t\t\t\toriginY,\n\t\t\t\t\txScale,\n\t\t\t\t\tyScale,\n\t\t\t\t});\n\t\t\t} else if (transformation.type === \"rotate\") {\n\t\t\t\tconst angle = transformation.options.angle || 0;\n\t\t\t\tfeature = transformRotateWebMercator(\n\t\t\t\t\tfeature as Feature<Polygon> | Feature<LineString>,\n\t\t\t\t\tangle,\n\t\t\t\t) as GeoJSONStoreFeatures;\n\n\t\t\t\tcoordinates =\n\t\t\t\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t\t\t\t? (feature.geometry as Polygon).coordinates[0]\n\t\t\t\t\t\t: (feature.geometry as LineString).coordinates;\n\t\t\t}\n\n\t\t\tcoordinates = coordinates.map((coord) => [\n\t\t\t\tlimitPrecision(coord[0], this._adapter.getCoordinatePrecision()),\n\t\t\t\tlimitPrecision(coord[1], this._adapter.getCoordinatePrecision()),\n\t\t\t]);\n\n\t\t\tfeature.geometry.coordinates =\n\t\t\t\tfeature.geometry.type === \"Polygon\" ? [coordinates] : coordinates;\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`Projection ${transformation.projection} is not currently supported for transformation`,\n\t\t\t);\n\t\t}\n\n\t\tthis._store.updateGeometry(\n\t\t\t[{ id: feature.id as FeatureId, geometry: feature.geometry }],\n\t\t\t{ origin: \"api\" }, // origin is used to indicate that this update has come from an API call\n\t\t);\n\n\t\tif (modeToUpdate.afterFeatureUpdated) {\n\t\t\tmodeToUpdate.afterFeatureUpdated(feature);\n\t\t\tconst featureIsSelected = feature.properties[SELECT_PROPERTIES.SELECTED];\n\t\t\tconst selectModePresent = this.getSelectMode({\n\t\t\t\tswitchToSelectMode: false,\n\t\t\t});\n\n\t\t\tif (selectModePresent && featureIsSelected) {\n\t\t\t\tselectModePresent.afterFeatureUpdated(feature);\n\t\t\t}\n\t\t}\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?: GetFeatureOptions,\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?: GetFeatureOptions,\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\ttype IdStrategy,\n\ttype TerraDrawEvents,\n\ttype TerraDrawEventListeners,\n\n\t// Modes\n\tTerraDrawSelectMode,\n\tTerraDrawPointMode,\n\tTerraDrawLineStringMode,\n\tTerraDrawPolygonMode,\n\tTerraDrawCircleMode,\n\tTerraDrawFreehandMode,\n\tTerraDrawFreehandLineStringMode,\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\ttype BehaviorConfig,\n\ttype GeoJSONStoreFeatures,\n\ttype GeoJSONStoreGeometries,\n\ttype HexColor,\n\ttype TerraDrawMouseEvent,\n\ttype TerraDrawAdapterStyling,\n\ttype TerraDrawKeyboardEvent,\n\n\t// TerraDrawBaseAdapter\n\ttype TerraDrawChanges,\n\ttype TerraDrawStylingFunction,\n\ttype Project,\n\ttype Unproject,\n\ttype SetCursor,\n\ttype GetLngLatFromEvent,\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","_state","this","_styles","pointerEvents","behaviors","validate","pointerDistance","coordinatePrecision","onStyleChange","store","projection","setDoubleClickToZoom","unproject","project","setCursor","type","Drawing","mode","updateOptions","_proto","prototype","_createClass","registerBehaviors","behaviorConfig","styles","_extends","validation","undefined","allowPointerEvent","pointerEvent","event","setDrawing","Error","setStarted","setStopped","register","config","registerOnChange","onChange","onSelect","onDeselect","onFinish","validateFeature","performFeatureValidation","afterFeatureAdded","afterFeatureUpdated","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","key","get","set","_","styling","TerraDrawBaseSelectMode","_TerraDrawBaseDrawMod","_this","_len","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","updateProperty","property","currentGeometry","getGeometryCopy","Finish","state","action","stop","cleanUp","button","isContextMenu","_properties","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","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","previousLat","containerX","containerY","_currentLineGeometry$2","_this$project2","setTimeout","pop","newGeometry","_properties2","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","snappable","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","lastCommittedCoordinates","snappedPointId","lastMouseMoveEvent","editable","editedFeatureId","editedFeatureCoordinateIndex","editedSnapType","editedInsertIndex","editedPointId","coordinateSnapping","insertPoint","lineSnapping","updateSnappedCoordinate","snappedCoordinate","snapCoordinate","updateGeometries","Commit","closingPointCoordinate","updatedGeometry","geometries","generateInsertCoordinates","startCoord","endCoord","strategy","segmentDistance","insertedCoordinates","createLine","startingCoord","createdId","firstUpdateToLine","updatedCoord","currentCoordinates","_this$store$create3","initialLineCoordinates","updateToLine","cursorXY","updatedLineCoordinates","_currentCoordinates","onRightClick","_this$coordinateSnapp","lineStringFilter","coordinateIndex","splice","onLeftClick","updatedCoordinate","lineSnapped","coordinateSnapped","_properties3","_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","transformRotateWebMercator","angleRad","webMercatorCoords","reduce","acc","rotatedCoordinates","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","pivot","pointCoords","finalAngle","DeltaLambda","rhumbDistance","newCoords","transformRotate","ScaleFeatureBehavior","dragCoordinateResizeBehavior","scale","transformScaleWebMercatorCoordinates","originX","originY","xScale","yScale","DragCoordinateResizeBehavior","minimumScale","boundingBoxMaps","opposite","isValidDragWebMercator","distanceX","distanceY","getSelectedFeatureDataWebMercator","getFeature","getNormalisedCoordinates","getBBoxWebMercator","selectedCoordinate","centerWebMercatorDrag","featureData","webMercatorOrigin","webMercatorSelected","closestBBoxIndex","getIndexesWebMercator","webMercatorCursor","scaleWebMercator","centerFixedWebMercatorDrag","scaleFixedWebMercator","oppositeFixedWebMercatorDrag","_this$getIndexesWebMe3","oppositeBboxIndex","oppositeWebMercatorDrag","_this$getIndexesWebMe4","cursorDistanceX","cursorDistanceY","validateScale","performWebMercatorScale","validX","MAX_SAFE_INTEGER","validY","_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","snapOptions","nearbyMidPoint","nearbySelectionPoint","featureUnderPointer","selectionPointColor","selectionPointOutlineColor","selectionPointWidth","selectionPointOutlineWidth","midPointColor","midPointOutlineColor","midPointWidth","midPointOutlineWidth","selectedPolygonColor","selectedPolygonOutlineWidth","selectedPolygonOutlineColor","selectedPolygonFillOpacity","selectedLineStringColor","selectedLineStringWidth","selectedPointWidth","selectedPointColor","selectedPointOutlineColor","selectedPointOutlineWidth","_flags$feature","_flags$feature2","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","_this$store$create2","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","TerraDrawFreehandLineStringMode","closingDistance","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","ignoreCoordinatePoints","ignoreCurrentlyDrawing","ignoreClosingPoints","inputPoint","pointCoordinates","pointXY","includePolygonsWithinPointerDistance","projectedStart","projectedEnd","getSelectModeOrThrow","selectMode","getSelectMode","switchToSelectMode","getMode","setMode","isGuidanceFeature","setModeStyles","updateModeOptions","getSnapshot","getSnapshotFeature","getModeState","removeFeatures","coordinatePointsToDelete","getFeatureId","hasFeature","updateFeatureGeometry","modeToUpdate","updatedFeature","featureIsSelected","selectModePresent","transformFeatureGeometry","transformation","addFeatures","featureMode","modeToAddTo","onReady","onClear","getFeaturesAtLngLat","getFeaturesAtPointerEvent","on","listeners","off","maxSize","minSize"],"mappings":"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"}