terra-draw 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common.d.ts +2 -0
- package/dist/modes/base.mode.d.ts +1 -0
- package/dist/modes/polygon/polygon.mode.d.ts +8 -0
- package/dist/modes/select/behaviors/coordinate-point.behavior.d.ts +16 -0
- package/dist/modes/select/behaviors/coordinate-point.behavior.spec.d.ts +1 -0
- package/dist/modes/select/behaviors/drag-coordinate-resize.behavior.d.ts +3 -1
- package/dist/modes/select/behaviors/drag-coordinate.behavior.d.ts +6 -2
- package/dist/modes/select/behaviors/drag-feature.behavior.d.ts +3 -1
- package/dist/modes/select/behaviors/midpoint.behavior.d.ts +4 -2
- package/dist/modes/select/behaviors/rotate-feature.behavior.d.ts +3 -1
- package/dist/modes/select/behaviors/scale-feature.behavior.d.ts +3 -1
- package/dist/modes/select/select.mode.d.ts +4 -0
- package/dist/store/store.d.ts +2 -1
- package/dist/terra-draw.cjs +1 -1
- package/dist/terra-draw.cjs.map +1 -1
- package/dist/terra-draw.modern.js +1 -1
- package/dist/terra-draw.modern.js.map +1 -1
- package/dist/terra-draw.module.js +1 -1
- package/dist/terra-draw.module.js.map +1 -1
- package/dist/terra-draw.umd.js +1 -1
- package/dist/terra-draw.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terra-draw.modern.js","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/geometry/web-mercator-point-on-line.ts","../src/modes/line-snapping.behavior.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/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/measure/rhumb-distance.ts","../src/geometry/web-mercator-centroid.ts","../src/modes/select/behaviors/rotate-feature.behavior.ts","../src/geometry/transform/rotate.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/max-size.validation.ts","../src/validations/not-self-intersecting.validation.ts","../src/geometry/calculate-relative-angle.ts","../src/modes/angled-rectangle/angled-rectangle.mode.ts","../src/geometry/determine-halfplane.ts","../src/geometry/clockwise.ts","../src/modes/sector/sector.mode.ts","../src/modes/sensor/sensor.mode.ts","../src/common/adapter-listener.ts","../src/common/base.adapter.ts","../src/validation-reasons.ts","../src/terra-draw.ts"],"sourcesContent":["import {\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}\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 interface TerraDrawModeRegisterConfig {\n\tmode: string;\n\tstore: GeoJSONStore;\n\tsetDoubleClickToZoom: (enabled: boolean) => void;\n\tsetCursor: SetCursor;\n\tonChange: StoreChangeHandler;\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 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: \"selectionPoint\",\n} as const;\n\nexport const COMMON_PROPERTIES = {\n\tEDITED: \"edited\",\n\tCLOSING_POINT: \"closingPoint\",\n\tSNAPPING_POINT: \"snappingPoint\",\n};\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\tHexColor,\n\tOnFinishContext,\n\tProjection,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawModeRegisterConfig,\n\tTerraDrawModeState,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStore,\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 type BaseModeOptions<Styling extends CustomStyling> = {\n\tstyles?: Partial<Styling>;\n\tpointerDistance?: number;\n\tvalidation?: Validation;\n\tprojection?: Projection;\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 behaviors: TerraDrawModeBehavior[] = [];\n\tprotected validate: Validation | undefined;\n\tprotected pointerDistance: number = 40;\n\tprotected coordinatePrecision!: number;\n\tprotected onStyleChange!: StoreChangeHandler;\n\tprotected store!: GeoJSONStore;\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\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\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} from \"../../common\";\nimport { haversineDistanceKilometers } from \"../../geometry/measure/haversine-distance\";\nimport { circle, circleWebMercator } from \"../../geometry/shape/create-circle\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { Polygon } from \"geojson\";\nimport { calculateWebMercatorDistortion } from \"../../geometry/shape/web-mercator-distortion\";\n\ntype TerraDrawCircleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype CirclePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawCircleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawCircleModeKeyEvents | null;\n\tcursors?: Cursors;\n\tstartingRadiusKilometers?: number;\n\tprojection?: Projection;\n}\n\nexport class TerraDrawCircleMode extends TerraDrawBaseDrawMode<CirclePolygonStyling> {\n\tmode = \"circle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentCircleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawCircleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate startingRadiusKilometers = 0.00001;\n\tprivate cursorMovedAfterInitialCursorDown = false;\n\n\t/**\n\t * Create a new circle mode instance\n\t * @param options - Options to customize the behavior of the circle mode\n\t * @param options.keyEvents - Key events to cancel or finish the mode\n\t * @param options.cursors - Cursors to use for the mode\n\t * @param options.styles - Custom styling for the circle\n\t * @param options.pointerDistance - Distance in pixels to consider a pointer close to a vertex\n\t */\n\tconstructor(options?: TerraDrawCircleModeOptions<CirclePolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawCircleModeOptions<CirclePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.startingRadiusKilometers) {\n\t\t\tthis.startingRadiusKilometers = options.startingRadiusKilometers;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentCircleId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentCircleId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\tthis.center = undefined;\n\t\tthis.currentCircleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 0) {\n\t\t\tthis.center = [event.lng, event.lat];\n\t\t\tconst startingCircle = circle({\n\t\t\t\tcenter: this.center,\n\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t});\n\n\t\t\tconst [createdId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: startingCircle.geometry,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentCircleId = createdId;\n\t\t\tthis.clickCount++;\n\t\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\t\tthis.setDrawing();\n\t\t} else {\n\t\t\tif (\n\t\t\t\tthis.clickCount === 1 &&\n\t\t\t\tthis.center &&\n\t\t\t\tthis.currentCircleId !== undefined &&\n\t\t\t\tthis.cursorMovedAfterInitialCursorDown\n\t\t\t) {\n\t\t\t\tthis.updateCircle(event);\n\t\t\t}\n\n\t\t\t// Finish drawing\n\t\t\tthis.close();\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 = 10;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate updateCircle(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 1 && this.center && this.currentCircleId) {\n\t\t\tconst newRadius = haversineDistanceKilometers(this.center, [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t]);\n\n\t\t\tlet updatedCircle: Feature<Polygon>;\n\n\t\t\tif (this.projection === \"web-mercator\") {\n\t\t\t\t// We want to track the mouse cursor, but we need to adjust the radius based\n\t\t\t\t// on the distortion of the web mercator projection\n\t\t\t\tconst distortion = calculateWebMercatorDistortion(this.center, [\n\t\t\t\t\tevent.lng,\n\t\t\t\t\tevent.lat,\n\t\t\t\t]);\n\n\t\t\t\tupdatedCircle = circleWebMercator({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius * distortion,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else if (this.projection === \"globe\") {\n\t\t\t\tupdatedCircle = circle({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Invalid projection\");\n\t\t\t}\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst valid = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\t\tgeometry: updatedCircle.geometry,\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!valid.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentCircleId, geometry: updatedCircle.geometry },\n\t\t\t]);\n\t\t\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\tproperty: \"radiusKilometers\",\n\t\t\t\t\tvalue: newRadius,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../common\";\n\nexport const getDefaultStyling = (): TerraDrawAdapterStyling => {\n\treturn {\n\t\tpolygonFillColor: \"#3f97e0\",\n\t\tpolygonOutlineColor: \"#3f97e0\",\n\t\tpolygonOutlineWidth: 4,\n\t\tpolygonFillOpacity: 0.3,\n\t\tpointColor: \"#3f97e0\",\n\t\tpointOutlineColor: \"#ffffff\",\n\t\tpointOutlineWidth: 0,\n\t\tpointWidth: 6,\n\t\tlineStringColor: \"#3f97e0\",\n\t\tlineStringWidth: 4,\n\t\tzIndex: 0,\n\t};\n};\n","import { Position } from \"geojson\";\nimport { haversineDistanceKilometers } from \"../measure/haversine-distance\";\nimport { lngLatToWebMercatorXY } from \"../project/web-mercator\";\n\n/*\n * Function to calculate the web mercator vs geodesic distortion between two coordinates\n * Value of 1 means no distortion, higher values mean higher distortion\n * */\nexport function calculateWebMercatorDistortion(\n\tsource: Position,\n\ttarget: Position,\n): number {\n\tconst geodesicDistance = haversineDistanceKilometers(source, target) * 1000;\n\tif (geodesicDistance === 0) {\n\t\treturn 1;\n\t}\n\n\tconst { x: x1, y: y1 } = lngLatToWebMercatorXY(source[0], source[1]);\n\tconst { x: x2, y: y2 } = lngLatToWebMercatorXY(target[0], target[1]);\n\tconst euclideanDistance = Math.sqrt(\n\t\tMath.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2),\n\t);\n\treturn euclideanDistance / geodesicDistance;\n}\n","import { CartesianPoint } from \"../../common\";\n\nexport const cartesianDistance = (\n\tpointOne: CartesianPoint,\n\tpointTwo: CartesianPoint,\n) => {\n\tconst { x: x1, y: y1 } = pointOne;\n\tconst { x: x2, y: y2 } = pointTwo;\n\tconst y = x2 - x1;\n\tconst x = y2 - y1;\n\treturn Math.sqrt(x * x + y * y);\n};\n","import { Feature, Polygon } from \"geojson\";\nimport { followsRightHandRule } from \"./boolean/right-hand-rule\";\n\nexport function ensureRightHandRule(polygon: Polygon): undefined | Polygon {\n\tconst isFollowingRightHandRule = followsRightHandRule(polygon);\n\tif (!isFollowingRightHandRule) {\n\t\treturn {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [polygon.coordinates[0].reverse()],\n\t\t} as Polygon;\n\t}\n}\n","import { Polygon } from \"geojson\";\n\n/**\n * Checks if a GeoJSON Polygon follows the right-hand rule.\n * @param polygon - The GeoJSON Polygon to check.\n * @returns {boolean} - True if the polygon follows the right-hand rule (counterclockwise outer ring), otherwise false.\n */\nexport function followsRightHandRule(polygon: Polygon): boolean {\n\tconst outerRing = polygon.coordinates[0];\n\n\tlet sum = 0;\n\tfor (let i = 0; i < outerRing.length - 1; i++) {\n\t\tconst [x1, y1] = outerRing[i];\n\t\tconst [x2, y2] = outerRing[i + 1];\n\t\tsum += (x2 - x1) * (y2 + y1);\n\t}\n\n\treturn sum < 0; // Right-hand rule: counterclockwise = negative area\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n} from \"../../common\";\nimport { Polygon } from \"geojson\";\n\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawFreehandModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype FreehandPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n\tclosingPointColor: HexColorStyling;\n\tclosingPointWidth: NumericStyling;\n\tclosingPointOutlineColor: HexColorStyling;\n\tclosingPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawFreehandModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tminDistance?: number;\n\tpreventPointsNearClose?: boolean;\n\tautoClose?: boolean;\n\tautoCloseTimeout?: number;\n\tkeyEvents?: TerraDrawFreehandModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawFreehandMode extends TerraDrawBaseDrawMode<FreehandPolygonStyling> {\n\tmode = \"freehand\" as const;\n\n\tprivate startingClick = false;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate minDistance: number = 20;\n\tprivate keyEvents: TerraDrawFreehandModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate preventPointsNearClose: boolean = true;\n\tprivate autoClose: boolean = false;\n\tprivate autoCloseTimeout = 500;\n\tprivate hasLeftStartingPoint = false;\n\tprivate preventNewFeature = false;\n\n\tconstructor(options?: TerraDrawFreehandModeOptions<FreehandPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tpublic updateOptions(\n\t\toptions?: TerraDrawFreehandModeOptions<FreehandPolygonStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.minDistance) {\n\t\t\tthis.minDistance = options.minDistance;\n\t\t}\n\n\t\tif (options?.preventPointsNearClose !== undefined) {\n\t\t\tthis.preventPointsNearClose = options.preventPointsNearClose;\n\t\t}\n\n\t\tif (options?.autoClose !== undefined) {\n\t\t\tthis.autoClose = options.autoClose;\n\t\t}\n\n\t\tif (options?.autoCloseTimeout) {\n\t\t\tthis.autoCloseTimeout = options.autoCloseTimeout;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\t\tthis.startingClick = false;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.hasLeftStartingPoint = false;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tif (this.currentId === undefined || this.startingClick === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst previousIndex = currentLineGeometry.coordinates[0].length - 2;\n\t\tconst [previousLng, previousLat] =\n\t\t\tcurrentLineGeometry.coordinates[0][previousIndex];\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tconst [closingLng, closingLat] = currentLineGeometry.coordinates[0][0];\n\t\tconst { x: closingX, y: closingY } = this.project(closingLng, closingLat);\n\t\tconst closingDistance = cartesianDistance(\n\t\t\t{ x: closingX, y: closingY },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tif (closingDistance < this.pointerDistance) {\n\t\t\t// We only want to close the polygon if the users cursor has left the\n\t\t\t// region of the starting point\n\t\t\tif (this.autoClose && this.hasLeftStartingPoint) {\n\t\t\t\t// If we have an autoCloseTimeout, we want to prevent new features\n\t\t\t\t// being created by accidental clicks for a short period of time\n\t\t\t\tthis.preventNewFeature = true;\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.preventNewFeature = false;\n\t\t\t\t}, this.autoCloseTimeout);\n\n\t\t\t\tthis.close();\n\t\t\t}\n\n\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t// We want to prohibit drawing new points at or around the closing\n\t\t\t// point as it can be non user friendly\n\t\t\tif (this.preventPointsNearClose) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.hasLeftStartingPoint = true;\n\t\t\tthis.setCursor(this.cursors.start);\n\t\t}\n\n\t\t// The cusor must have moved a minimum distance\n\t\t// before we add another coordinate\n\t\tif (distance < this.minDistance) {\n\t\t\treturn;\n\t\t}\n\n\t\tcurrentLineGeometry.coordinates[0].pop();\n\n\t\tconst newGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [\n\t\t\t\t[\n\t\t\t\t\t...currentLineGeometry.coordinates[0],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentLineGeometry.coordinates[0][0],\n\t\t\t\t],\n\t\t\t],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: newGeometry,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.preventNewFeature) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.startingClick === false) {\n\t\t\tconst [createdId, closingPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t\t{\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\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\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\n\t\t\tthis.currentId = createdId;\n\t\t\tthis.closingPointId = closingPointId;\n\t\t\tthis.startingClick = true;\n\t\t\tthis.setDrawing();\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis.close();\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 = 10;\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 = 40;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePolygonFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n}\n","import { Project, Projection, Unproject } from \"../common\";\nimport { GeoJSONStore } from \"../store/store\";\n\nexport type BehaviorConfig = {\n\tstore: GeoJSONStore;\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: GeoJSONStore;\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\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 { 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 { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\nimport { Feature, Position } from \"geojson\";\nimport { ClickBoundingBoxBehavior } from \"./click-bounding-box.behavior\";\nimport { BBoxPolygon, FeatureId } from \"../store/store\";\nimport { PixelDistanceBehavior } from \"./pixel-distance.behavior\";\nimport { nearestPointOnLine } from \"../geometry/point-on-line\";\nimport { webMercatorNearestPointOnLine } from \"../geometry/web-mercator-point-on-line\";\n\nexport class LineSnappingBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly clickBoundingBox: ClickBoundingBoxBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\t/** Returns the nearest snappable coordinate - on first click there is no currentId so no need to provide */\n\tpublic getSnappableCoordinateFirstClick = (event: TerraDrawMouseEvent) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties && feature.properties.mode === this.mode,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappableCoordinate = (\n\t\tevent: TerraDrawMouseEvent,\n\t\tcurrentFeatureId: FeatureId,\n\t) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === this.mode &&\n\t\t\t\t\tfeature.id !== currentFeatureId,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappable(\n\t\tevent: TerraDrawMouseEvent,\n\t\tfilter?: (feature: Feature) => boolean,\n\t) {\n\t\tconst boundingBox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(boundingBox, filter);\n\t\tconst closest: {\n\t\t\tcoordinate: undefined | Position;\n\t\t\tminDistance: number;\n\t\t\tfeatureId: undefined | FeatureId;\n\t\t\tfeatureCoordinateIndex: undefined | number;\n\t\t} = {\n\t\t\tfeatureId: undefined,\n\t\t\tfeatureCoordinateIndex: undefined,\n\t\t\tcoordinate: undefined,\n\t\t\tminDistance: Infinity,\n\t\t};\n\t\tfeatures.forEach((feature) => {\n\t\t\tlet coordinates: Position[];\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst lines: [Position, Position][] = [];\n\n\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\tlines.push([coordinates[i], coordinates[i + 1]]);\n\t\t\t}\n\n\t\t\tlet nearest:\n\t\t\t\t| {\n\t\t\t\t\t\tcoordinate: Position;\n\t\t\t\t\t\tlineIndex: number;\n\t\t\t\t\t\tdistance: number;\n\t\t\t\t }\n\t\t\t\t| undefined;\n\n\t\t\tconst lngLat: Position = [event.lng, event.lat];\n\n\t\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\t\tnearest = webMercatorNearestPointOnLine(lngLat, lines);\n\t\t\t} else if (this.config.projection === \"globe\") {\n\t\t\t\tnearest = nearestPointOnLine(lngLat, lines);\n\t\t\t}\n\n\t\t\tif (!nearest) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst distance = this.pixelDistance.measure(event, nearest.coordinate);\n\t\t\tif (distance < closest.minDistance && distance < this.pointerDistance) {\n\t\t\t\tclosest.featureId = feature.id;\n\t\t\t\tclosest.coordinate = nearest.coordinate;\n\t\t\t\tclosest.featureCoordinateIndex = nearest.lineIndex;\n\t\t\t\tclosest.minDistance = distance;\n\t\t\t}\n\t\t});\n\n\t\treturn closest;\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCartesianPoint,\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 Snapping {\n\ttoCoordinate?: boolean;\n\ttoCustom?: (event: TerraDrawMouseEvent) => Position | undefined;\n}\n\ninterface TerraDrawLineStringModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawLineStringModeKeyEvents | null;\n\tcursors?: Cursors;\n\tinsertCoordinates?: InertCoordinates;\n\teditable?: boolean;\n}\n\nexport class TerraDrawLineStringMode extends TerraDrawBaseDrawMode<LineStringStyling> {\n\tmode = \"linestring\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawLineStringModeKeyEvents = defaultKeyEvents;\n\tprivate snapping: Snapping | undefined;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\tprivate insertCoordinates: InertCoordinates | undefined;\n\tprivate lastCommitedCoordinates: Position[] | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\n\t// Editable properties\n\tprivate editable: boolean = false;\n\tprivate editedFeatureId: FeatureId | undefined;\n\tprivate editedFeatureCoordinateIndex: number | undefined;\n\tprivate editedSnapType: \"line\" | \"coordinate\" | undefined;\n\tprivate editedInsertIndex: number | undefined;\n\tprivate editedPointId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate coordinateSnapping!: CoordinateSnappingBehavior;\n\tprivate insertPoint!: InsertCoordinatesBehavior;\n\tprivate lineSnapping!: LineSnappingBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawLineStringModeOptions<LineStringStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawLineStringModeOptions<LineStringStyling> | undefined,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.snapping) {\n\t\t\tthis.snapping = options.snapping;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.insertCoordinates) {\n\t\t\tthis.insertCoordinates = options.insertCoordinates;\n\t\t}\n\n\t\tif (options && options.editable) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\t// Finish off the drawing\n\t\tcurrentLineGeometry.coordinates.pop();\n\n\t\tthis.updateGeometries(\n\t\t\t[...currentLineGeometry.coordinates],\n\t\t\tundefined,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Reset the state back to starting state\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.lastCommitedCoordinates = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listeners are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate updateGeometries(\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tclosingPointCoordinate: Point[\"coordinates\"] | undefined,\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updatedGeometry = { type: \"LineString\", coordinates } as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: updateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst geometries = [\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: updatedGeometry,\n\t\t\t},\n\t\t] as {\n\t\t\tid: FeatureId;\n\t\t\tgeometry: GeoJSONStoreGeometries;\n\t\t}[];\n\n\t\tif (this.closingPointId && closingPointCoordinate) {\n\t\t\tgeometries.push({\n\t\t\t\tid: this.closingPointId,\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: closingPointCoordinate,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tif (updateType === \"commit\") {\n\t\t\tthis.lastCommitedCoordinates = updatedGeometry.coordinates;\n\t\t}\n\n\t\tthis.store.updateGeometry(geometries);\n\t}\n\n\tprivate generateInsertCoordinates(startCoord: Position, endCoord: Position) {\n\t\tif (!this.insertCoordinates || !this.lastCommitedCoordinates) {\n\t\t\tthrow new Error(\"Not able to insert coordinates\");\n\t\t}\n\n\t\t// Other strategies my be implemented in the future\n\t\tif (this.insertCoordinates.strategy !== \"amount\") {\n\t\t\tthrow new Error(\"Strategy does not exist\");\n\t\t}\n\n\t\tconst distance = haversineDistanceKilometers(startCoord, endCoord);\n\t\tconst segmentDistance = distance / (this.insertCoordinates.value + 1);\n\t\tlet insertedCoordinates: Position[] = [];\n\n\t\tif (this.projection === \"globe\") {\n\t\t\tinsertedCoordinates =\n\t\t\t\tthis.insertPoint.generateInsertionGeodesicCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t\tsegmentDistance,\n\t\t\t\t);\n\t\t} else if (this.projection === \"web-mercator\") {\n\t\t\tinsertedCoordinates = this.insertPoint.generateInsertionCoordinates(\n\t\t\t\tstartCoord,\n\t\t\t\tendCoord,\n\t\t\t\tsegmentDistance,\n\t\t\t);\n\t\t}\n\n\t\treturn insertedCoordinates;\n\t}\n\n\tprivate createLine(startingCoord: Position) {\n\t\tconst [createdId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"LineString\",\n\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\tstartingCoord,\n\t\t\t\t\t\tstartingCoord, // This is the 'live' point that changes on mouse move\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.lastCommitedCoordinates = [startingCoord, startingCoord];\n\t\tthis.currentId = createdId;\n\t\tthis.currentCoordinate++;\n\t\tthis.setDrawing();\n\t}\n\n\tprivate firstUpdateToLine(updatedCoord: Position) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\tconst [pointId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: [...updatedCoord],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.closingPointId = pointId;\n\n\t\t// We are creating the point so we immediately want\n\t\t// to set the point cursor to show it can be closed\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst initialLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst closingPointCoordinate = undefined; // We don't need this until second click\n\n\t\tthis.updateGeometries(\n\t\t\tinitialLineCoordinates,\n\t\t\tclosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\tprivate updateToLine(updatedCoord: Position, cursorXY: CartesianPoint) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// If we are not inserting points we can get the penultimate coordinated\n\t\tconst [previousLng, previousLat] = this.lastCommitedCoordinates\n\t\t\t? this.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1]\n\t\t\t: currentCoordinates[currentCoordinates.length - 2];\n\n\t\t// Determine if the click closes the line and finished drawing\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: cursorXY.x, y: cursorXY.y },\n\t\t);\n\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\tif (isClosingClick) {\n\t\t\tthis.close();\n\t\t\treturn;\n\t\t}\n\n\t\t// The cursor will immediately change to closing because the\n\t\t// closing point will be underneath the cursor\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst updatedLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst updatedClosingPointCoordinate =\n\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\n\t\tthis.updateGeometries(\n\t\t\tupdatedLineCoordinates,\n\t\t\tupdatedClosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tnew PixelDistanceBehavior(config),\n\t\t\tnew ClickBoundingBoxBehavior(config),\n\t\t);\n\n\t\tthis.insertPoint = new InsertCoordinatesBehavior(config);\n\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst updatedCoord = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// Remove the 'live' point that changes on mouse move\n\t\tcurrentCoordinates.pop();\n\n\t\t// We want to ensure that when we are hovering over\n\t\t// the closing point that the pointer cursor is shown\n\t\tif (this.closingPointId) {\n\t\t\tconst [previousLng, previousLat] =\n\t\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\t\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\t\tconst distance = cartesianDistance(\n\t\t\t\t{ x, y },\n\t\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t\t);\n\n\t\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\t\tif (isClosingClick) {\n\t\t\t\tthis.setCursor(this.cursors.close);\n\t\t\t}\n\t\t}\n\n\t\tlet line = [...currentCoordinates, updatedCoord];\n\n\t\tif (\n\t\t\tthis.insertCoordinates &&\n\t\t\tthis.currentId &&\n\t\t\tthis.lastCommitedCoordinates\n\t\t) {\n\t\t\tconst startCoord =\n\t\t\t\tthis.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1];\n\t\t\tconst endCoord = updatedCoord;\n\t\t\tif (!coordinatesIdentical(startCoord, endCoord)) {\n\t\t\t\tconst insertedCoordinates = this.generateInsertCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t);\n\t\t\t\tline = [\n\t\t\t\t\t...this.lastCommitedCoordinates.slice(0, -1),\n\t\t\t\t\t...insertedCoordinates,\n\t\t\t\t\tupdatedCoord,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\t// Update the 'live' point\n\t\tthis.updateGeometries(line, undefined, UpdateTypes.Provisional);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\tif (!this.editable || this.state !== \"started\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.lineStringFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tcoordinates = geometry.coordinates;\n\n\t\t\t// Prevent creating an invalid linestring\n\t\t\tif (coordinates.length <= 2) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove coordinate from array\n\t\tcoordinates.splice(coordinateIndex, 1);\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\t\tconst updatedCoordinate = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tthis.createLine(updatedCoordinate);\n\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\tthis.firstUpdateToLine(updatedCoordinate);\n\t\t} else if (this.currentId) {\n\t\t\tthis.updateToLine(updatedCoordinate, {\n\t\t\t\tx: event.containerX,\n\t\t\t\ty: event.containerY,\n\t\t\t});\n\t\t}\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t} else if (event.button === \"left\") {\n\t\t\tthis.onLeftClick(event);\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.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 (\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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 10;\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 = 40;\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?.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}\n\n\t\treturn snappedCoordinate;\n\t}\n}\n","import { Validation } from \"../common\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\n\nexport const ValidationReasonFeatureNotPoint = \"Feature is not a Point\";\nexport const ValidationReasonFeatureInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidatePointFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"Point\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPoint,\n\t\t};\n\t}\n\n\tif (!coordinateIsValid(feature.geometry.coordinates)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinates,\n\t\t};\n\t}\n\n\tif (\n\t\t!coordinatePrecisionIsValid(\n\t\t\tfeature.geometry.coordinates,\n\t\t\tcoordinatePrecision,\n\t\t)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tNumericStyling,\n\tHexColorStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n} 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 (!this.store) {\n\t\t\tthrow new Error(\"Mode must be registered first\");\n\t\t}\n\n\t\tif (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t} else if (event.button === \"left\") {\n\t\t\tthis.onLeftClick(event);\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.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.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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 30;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePointFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\tconst geometry = {\n\t\t\ttype: \"Point\",\n\t\t\tcoordinates: [event.lng, event.lat],\n\t\t} as Point;\n\n\t\tconst properties = { mode: this.mode };\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst [pointId] = this.store.create([{ geometry, properties }]);\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(pointId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// We only want to be able to delete points if the mode is editable\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst clickedFeature = this.getNearestPointFeature(event);\n\n\t\tif (clickedFeature) {\n\t\t\tthis.store.delete([clickedFeature.id as FeatureId]);\n\t\t}\n\t}\n\n\tprivate getNearestPointFeature(event: TerraDrawMouseEvent) {\n\t\tconst bbox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(bbox);\n\n\t\tlet distance = Infinity;\n\t\tlet clickedFeature: GeoJSONStoreFeatures | undefined = undefined;\n\n\t\tfor (let i = 0; i < features.length; i++) {\n\t\t\tconst feature = features[i];\n\t\t\tconst isPoint =\n\t\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\t\tfeature.properties.mode === this.mode;\n\n\t\t\tif (!isPoint) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst position = feature.geometry.coordinates as Position;\n\t\t\tconst distanceToFeature = this.pixelDistance.measure(event, position);\n\n\t\t\tif (\n\t\t\t\tdistanceToFeature > distance ||\n\t\t\t\tdistanceToFeature > this.pointerDistance\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdistance = distanceToFeature;\n\t\t\tclickedFeature = feature;\n\t\t}\n\n\t\treturn clickedFeature;\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { COMMON_PROPERTIES, TerraDrawMouseEvent } from \"../../../common\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\n\nexport class ClosingPointsBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate _startEndPoints: string[] = [];\n\n\tget ids() {\n\t\treturn this._startEndPoints.concat();\n\t}\n\n\tset ids(_: string[]) {}\n\n\tpublic create(selectedCoords: Position[], mode: string) {\n\t\tif (this.ids.length) {\n\t\t\tthrow new Error(\"Opening and closing points already created\");\n\t\t}\n\n\t\tif (selectedCoords.length <= 3) {\n\t\t\tthrow new Error(\"Requires at least 4 coordinates\");\n\t\t}\n\n\t\tthis._startEndPoints = this.store.create(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[selectedCoords.length - 2],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this.ids.length) {\n\t\t\tthis.store.delete(this.ids);\n\t\t\tthis._startEndPoints = [];\n\t\t}\n\t}\n\n\tpublic update(updatedCoordinates: Position[]) {\n\t\tif (this.ids.length !== 2) {\n\t\t\tthrow new Error(\"No closing points to update\");\n\t\t}\n\n\t\tthis.store.updateGeometry(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[0],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[1],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[updatedCoordinates.length - 3],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic isClosingPoint(event: TerraDrawMouseEvent) {\n\t\tconst opening = this.store.getGeometryCopy(this.ids[0]);\n\t\tconst closing = this.store.getGeometryCopy(this.ids[1]);\n\n\t\tconst distance = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\topening.coordinates as Position,\n\t\t);\n\n\t\tconst distancePrevious = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\tclosing.coordinates as Position,\n\t\t);\n\n\t\tconst isClosing = distance < this.pointerDistance;\n\t\tconst isPreviousClosing = distancePrevious < this.pointerDistance;\n\n\t\treturn { isClosing, isPreviousClosing };\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n\tProject,\n\tUnproject,\n} from \"../../common\";\nimport { Feature, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\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\";\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};\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 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 | null;\n\t\t\tproject: Project;\n\t\t\tunproject: Unproject;\n\t\t},\n\t) => Position | undefined;\n}\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tcursors?: Cursors;\n\teditable?: 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\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 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) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\t// We don't want to allow closing if there is not enough\n\t\t// coordinates. We have extra because we insert them on mouse\n\t\t// move\n\t\tif (currentPolygonCoordinates.length < 5) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t[...currentPolygonCoordinates.slice(0, -2), currentPolygonCoordinates[0]],\n\t\t\tUpdateTypes.Finish,\n\t\t);\n\n\t\tif (!updated) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.closingPoints.delete();\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.closingPoints = new ClosingPointsBehavior(config, this.pixelDistance);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else {\n\t\t\tconst { isClosing, isPreviousClosing } =\n\t\t\t\tthis.closingPoints.isClosingPoint(event);\n\n\t\t\tif (isPreviousClosing || isClosing) {\n\t\t\t\tif (this.snappedPointId) {\n\t\t\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\t\t\tthis.snappedPointId = undefined;\n\t\t\t\t}\n\n\t\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\tthis.updatePolygonGeometry(updatedCoordinates, UpdateTypes.Provisional);\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{ id: this.currentId, geometry: updatedGeometry },\n\t\t]);\n\n\t\treturn true;\n\t}\n\n\tprivate snapCoordinate(event: TerraDrawMouseEvent): undefined | Position {\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.snapping?.toLine) {\n\t\t\tlet snapped: Position | undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCoordinate) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.coordinateSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped =\n\t\t\t\t\tthis.coordinateSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCustom) {\n\t\t\tsnappedCoordinate = this.snapping.toCustom(event, {\n\t\t\t\tcurrentCoordinate: this.currentCoordinate,\n\t\t\t\tcurrentId: this.currentId,\n\t\t\t\tgetCurrentGeometrySnapshot: this.currentId\n\t\t\t\t\t? () =>\n\t\t\t\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId as FeatureId)\n\t\t\t\t\t: () => null,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t});\n\t\t}\n\n\t\treturn snappedCoordinate;\n\t}\n\n\tprivate polygonFilter(feature: Feature) {\n\t\treturn Boolean(\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\t\tfeature.properties &&\n\t\t\t\tfeature.properties.mode === this.mode,\n\t\t);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// Right click is only relevant when editable is true\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"Polygon\") {\n\t\t\tcoordinates = geometry.coordinates[0];\n\n\t\t\t// Prevent creating an invalid polygon\n\t\t\tif (coordinates.length <= 4) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isFinalPolygonCoordinate =\n\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t(coordinateIndex === 0 || coordinateIndex === coordinates.length - 1);\n\n\t\tif (isFinalPolygonCoordinate) {\n\t\t\t// Deleting the final coordinate in a polygon breaks it\n\t\t\t// because GeoJSON expects a duplicate, so we need to fix\n\t\t\t// it by adding the new first coordinate to the end\n\t\t\tcoordinates.shift();\n\t\t\tcoordinates.pop();\n\t\t\tcoordinates.push([coordinates[0][0], coordinates[0][1]]);\n\t\t} else {\n\t\t\t// Remove coordinate from array\n\t\t\tcoordinates.splice(coordinateIndex, 1);\n\t\t}\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\tif (snappedCoordinate) {\n\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t}\n\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (event.button === \"left\") {\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.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.state === \"started\") {\n\t\t\tconst lineSnapped = this.lineSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (lineSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"line\";\n\t\t\t\tthis.editedFeatureCoordinateIndex = lineSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = lineSnapped.featureId;\n\t\t\t\tsnappedCoordinate = lineSnapped.coordinate;\n\t\t\t}\n\n\t\t\tconst coordinateSnapped = this.coordinateSnapping.getSnappable(\n\t\t\t\tevent,\n\t\t\t\t(feature) => this.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (coordinateSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"coordinate\";\n\t\t\t\tthis.editedFeatureCoordinateIndex =\n\t\t\t\t\tcoordinateSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = coordinateSnapped.featureId;\n\t\t\t\tsnappedCoordinate = coordinateSnapped.coordinate;\n\t\t\t}\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.editedFeatureId || !snappedCoordinate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create a point to drag when editing\n\t\tif (!this.editedPointId) {\n\t\t\tconst [editedPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t},\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.EDITED]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\tthis.editedPointId = editedPointId;\n\t\t}\n\n\t\t// Drag Feature\n\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\tsetMapDraggability(false);\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (\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.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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 !== 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 = 10;\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\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: 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};\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 = 35;\n\t\t\t\t} else {\n\t\t\t\t\tstyles.zIndex = 30;\n\t\t\t\t}\n\t\t\t\treturn styles;\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\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} from \"../../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawRectangleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype RectanglePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawRectangleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawRectangleModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawRectangleMode extends TerraDrawBaseDrawMode<RectanglePolygonStyling> {\n\tmode = \"rectangle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentRectangleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawRectangleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\n\tconstructor(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate updateRectangle(event: TerraDrawMouseEvent, updateType: UpdateTypes) {\n\t\tif (this.clickCount === 1 && this.center && this.currentRectangleId) {\n\t\t\tconst geometry = this.store.getGeometryCopy(this.currentRectangleId);\n\n\t\t\tconst firstCoord = (geometry.coordinates as Position[][])[0][0];\n\n\t\t\tconst newGeometry = {\n\t\t\t\ttype: \"Polygon\",\n\t\t\t\tcoordinates: [\n\t\t\t\t\t[\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t\t[event.lng, firstCoord[1]],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t[firstCoord[0], event.lat],\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t} as Polygon;\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst validationResult = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!validationResult.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tconst finishedId = this.currentRectangleId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (finishedId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(finishedId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: finishedId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.center = undefined;\n\t\tthis.currentRectangleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedId !== undefined) {\n\t\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 0) {\n\t\t\tthis.center = [event.lng, event.lat];\n\t\t\tconst [createdId] = 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},\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentRectangleId = createdId;\n\t\t\tthis.clickCount++;\n\t\t\tthis.setDrawing();\n\t\t} else {\n\t\t\tthis.updateRectangle(event, UpdateTypes.Finish);\n\t\t\t// Finish drawing\n\t\t\tthis.close();\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 = 10;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tHexColorStyling,\n\tNumericStyling,\n\tTerraDrawAdapterStyling,\n} from \"../../common\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { GeoJSONStoreFeatures } from \"../../terra-draw\";\nimport { ValidatePointFeature } from \"../../validations/point.validation\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ValidateLineStringFeature } from \"../../validations/linestring.validation\";\nimport { StoreValidation } from \"../../store/store\";\n\ntype RenderModeStyling = {\n\tpointColor: HexColorStyling;\n\tpointWidth: NumericStyling;\n\tpointOutlineColor: HexColorStyling;\n\tpointOutlineWidth: NumericStyling;\n\tpolygonFillColor: HexColorStyling;\n\tpolygonFillOpacity: NumericStyling;\n\tpolygonOutlineColor: HexColorStyling;\n\tpolygonOutlineWidth: NumericStyling;\n\tlineStringWidth: NumericStyling;\n\tlineStringColor: HexColorStyling;\n\tzIndex: NumericStyling;\n};\n\ninterface TerraDrawRenderModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tmodeName?: string;\n\t// styles need to be there else we could fall back to BaseModeOptions\n\tstyles: Partial<T>;\n}\n\nexport class TerraDrawRenderMode extends TerraDrawBaseDrawMode<RenderModeStyling> {\n\tpublic type = ModeTypes.Render; // The type of the mode\n\tpublic mode = \"render\"; // This gets changed dynamically\n\n\tconstructor(options: TerraDrawRenderModeOptions<RenderModeStyling>) {\n\t\tif (!options.modeName) {\n\t\t\tthrow new Error(\"Mode name is required for TerraDrawRenderMode\");\n\t\t}\n\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawRenderModeOptions<RenderModeStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\t\tif (options?.modeName) {\n\t\t\tthis.mode = options.modeName;\n\t\t}\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(behaviorConfig: BehaviorConfig) {\n\t\t// TODO: this is probably abusing\n\t\t// registerBehaviors but it works quite well conceptually\n\n\t\t// We can set the mode name dynamically\n\t\tthis.mode = behaviorConfig.mode;\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.setStopped();\n\t}\n\n\t/** @internal */\n\tonKeyUp() {}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonClick() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tonMouseMove() {}\n\n\t/** @internal */\n\tcleanUp() {}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst defaultStyles = getDefaultStyling();\n\n\t\treturn {\n\t\t\tpointColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointColor,\n\t\t\t\tdefaultStyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointWidth,\n\t\t\t\tdefaultStyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointOutlineColor,\n\t\t\t\tdefaultStyles.pointOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointOutlineWidth,\n\t\t\t\tdefaultStyles.pointOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonFillColor,\n\t\t\t\tdefaultStyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillOpacity: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonFillOpacity,\n\t\t\t\tdefaultStyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonOutlineColor,\n\t\t\t\tdefaultStyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonOutlineWidth,\n\t\t\t\tdefaultStyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.lineStringWidth,\n\t\t\t\tdefaultStyles.lineStringWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.lineStringColor,\n\t\t\t\tdefaultStyles.lineStringColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tzIndex: this.getNumericStylingValue(\n\t\t\t\tthis.styles.zIndex,\n\t\t\t\tdefaultStyles.zIndex,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t};\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\tconst validationResult = super.validateFeature(feature);\n\t\tif (validationResult.valid) {\n\t\t\tconst validatedFeature = feature as GeoJSONStoreFeatures;\n\n\t\t\tconst featureIsValid =\n\t\t\t\tValidatePointFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidatePolygonFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidateLineStringFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid;\n\n\t\t\tif (featureIsValid) {\n\t\t\t\treturn { valid: true };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tvalid: featureIsValid,\n\t\t\t\treason: \"Feature is not a valid Point, Polygon or LineString feature\",\n\t\t\t};\n\t\t}\n\n\t\treturn validationResult;\n\t}\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, radiansToDegrees } from \"../helpers\";\n\n// Based on Turf.js Rhumb Bearing module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-bearing/index.ts\n\nexport function rhumbBearing(start: Position, end: Position): number {\n\tconst from = start;\n\tconst to = end;\n\n\t// φ => phi\n\t// Δλ => deltaLambda\n\t// Δψ => deltaPsi\n\t// θ => theta\n\tconst phi1 = degreesToRadians(from[1]);\n\tconst phi2 = degreesToRadians(to[1]);\n\tlet deltaLambda = degreesToRadians(to[0] - from[0]);\n\n\t// if deltaLambdaon over 180° take shorter rhumb line across the anti-meridian:\n\tif (deltaLambda > Math.PI) {\n\t\tdeltaLambda -= 2 * Math.PI;\n\t}\n\tif (deltaLambda < -Math.PI) {\n\t\tdeltaLambda += 2 * Math.PI;\n\t}\n\n\tconst deltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\n\tconst theta = Math.atan2(deltaLambda, deltaPsi);\n\n\tconst bear360 = (radiansToDegrees(theta) + 360) % 360;\n\n\tconst bear180 = bear360 > 180 ? -(360 - bear360) : bear360;\n\n\treturn bear180;\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, earthRadius } from \"../helpers\";\n\n// Based on @turf/rhumb-destination module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-destination/index.ts\n\nexport function rhumbDestination(\n\torigin: Position,\n\tdistanceMeters: number,\n\tbearing: number,\n): Position {\n\tconst wasNegativeDistance = distanceMeters < 0;\n\tlet distanceInMeters = distanceMeters;\n\n\tif (wasNegativeDistance) {\n\t\tdistanceInMeters = -Math.abs(distanceInMeters);\n\t}\n\n\tconst delta = distanceInMeters / earthRadius; // angular distance in radians\n\tconst lambda1 = (origin[0] * Math.PI) / 180; // to radians, but without normalize to 𝜋\n\tconst phi1 = degreesToRadians(origin[1]);\n\tconst theta = degreesToRadians(bearing);\n\n\tconst DeltaPhi = delta * Math.cos(theta);\n\tlet phi2 = phi1 + DeltaPhi;\n\n\t// check for going past the pole, normalise latitude if so\n\tif (Math.abs(phi2) > Math.PI / 2) {\n\t\tphi2 = phi2 > 0 ? Math.PI - phi2 : -Math.PI - phi2;\n\t}\n\n\tconst DeltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\t// E-W course becomes ill-conditioned with 0/0\n\tconst q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);\n\n\tconst DeltaLambda = (delta * Math.sin(theta)) / q;\n\tconst lambda2 = lambda1 + DeltaLambda;\n\n\t// normalise to −180..+180°\n\tconst destination = [\n\t\t(((lambda2 * 180) / Math.PI + 540) % 360) - 180,\n\t\t(phi2 * 180) / Math.PI,\n\t];\n\n\t// compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)\n\t// solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678\n\tdestination[0] +=\n\t\tdestination[0] - origin[0] > 180\n\t\t\t? -360\n\t\t\t: origin[0] - destination[0] > 180\n\t\t\t\t? 360\n\t\t\t\t: 0;\n\treturn destination;\n}\n","import { Position } from \"geojson\";\nimport { limitPrecision } from \"./limit-decimal-precision\";\nimport { Project, Unproject } from \"../common\";\nimport { haversineDistanceKilometers } from \"./measure/haversine-distance\";\nimport { rhumbBearing } from \"./measure/rhumb-bearing\";\nimport { rhumbDestination } from \"./measure/rhumb-destination\";\n\n// midpointCoordinate is adapted from the @turf/midpoint which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-midpoint\n\nexport function midpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n) {\n\tconst projectedCoordinateOne = project(coordinates1[0], coordinates1[1]);\n\tconst projectedCoordinateTwo = project(coordinates2[0], coordinates2[1]);\n\n\tconst { lng, lat } = unproject(\n\t\t(projectedCoordinateOne.x + projectedCoordinateTwo.x) / 2,\n\t\t(projectedCoordinateOne.y + projectedCoordinateTwo.y) / 2,\n\t);\n\n\treturn [limitPrecision(lng, precision), limitPrecision(lat, precision)];\n}\n\n/* Get the geodesic midpoint coordinate between two coordinates */\nexport function geodesicMidpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n) {\n\tconst dist = haversineDistanceKilometers(coordinates1, coordinates2) * 1000;\n\tconst heading = rhumbBearing(coordinates1, coordinates2);\n\tconst midpoint = rhumbDestination(coordinates1, dist / 2, heading);\n\treturn [\n\t\tlimitPrecision(midpoint[0], precision),\n\t\tlimitPrecision(midpoint[1], precision),\n\t];\n}\n","import { Point, Position } from \"geojson\";\nimport { Project, Projection, Unproject } from \"../common\";\nimport { JSONObject } from \"../store/store\";\nimport {\n\tmidpointCoordinate,\n\tgeodesicMidpointCoordinate,\n} from \"./midpoint-coordinate\";\n\nexport function getMidPointCoordinates({\n\tfeatureCoords,\n\tprecision,\n\tunproject,\n\tproject,\n\tprojection,\n}: {\n\tfeatureCoords: Position[];\n\tprecision: number;\n\tproject: Project;\n\tunproject: Unproject;\n\tprojection: Projection;\n}) {\n\tconst midPointCoords: Position[] = [];\n\tfor (let i = 0; i < featureCoords.length - 1; i++) {\n\t\tlet mid;\n\t\tif (projection === \"web-mercator\") {\n\t\t\tmid = midpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t\tproject,\n\t\t\t\tunproject,\n\t\t\t);\n\t\t} else if (projection === \"globe\") {\n\t\t\tmid = geodesicMidpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid projection\");\n\t\t}\n\n\t\tmidPointCoords.push(mid);\n\t}\n\treturn midPointCoords;\n}\n\nexport function getMidPoints(\n\tselectedCoords: Position[],\n\tproperties: (index: number) => JSONObject,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n\tprojection: Projection,\n) {\n\treturn getMidPointCoordinates({\n\t\tfeatureCoords: selectedCoords,\n\t\tprecision,\n\t\tproject,\n\t\tunproject,\n\t\tprojection,\n\t}).map((coord, i) => ({\n\t\tgeometry: { type: \"Point\", coordinates: coord } as Point,\n\t\tproperties: properties(i),\n\t}));\n}\n","import { LineString, Point, Polygon, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport {\n\tgetMidPointCoordinates,\n\tgetMidPoints,\n} from \"../../../geometry/get-midpoints\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport { Projection, SELECT_PROPERTIES } from \"../../../common\";\nimport { FeatureId } from \"../../../store/store\";\n\nexport class MidPointBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly selectionPointBehavior: SelectionPointBehavior,\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(midPointId: string, coordinatePrecision: number) {\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 string,\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// 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\";\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\tselectionPoint: true,\n\t\t\t\tselectionPointFeatureId: featureId,\n\t\t\t\tindex: i,\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(\n\tselectedCoords: Position[],\n\tgeometryType: \"Polygon\" | \"LineString\",\n\tproperties: (index: number) => JSONObject,\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 isNonSelectedMidPoint =\n\t\t\t\t\t!hasSelection && feature.properties[SELECT_PROPERTIES.MID_POINT];\n\n\t\t\t\tif (isSelectionPoint || 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\";\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) {\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\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]);\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 { TerraDrawMouseEvent, UpdateTypes, Validation } 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 } from \"../../../store/store\";\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) {\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\tpublic drag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tallowSelfIntersection: boolean,\n\t\tvalidateFeature?: Validation,\n\t): boolean {\n\t\tif (this.draggedCoordinate.id === null) {\n\t\t\treturn false;\n\t\t}\n\t\tconst index = this.draggedCoordinate.index;\n\t\tconst geometry = this.store.getGeometryCopy(this.draggedCoordinate.id);\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\t// Store the updated coord\n\t\tconst updatedCoordinate = [event.lng, event.lat];\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\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(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: this.draggedCoordinate.id,\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.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\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: this.draggedCoordinate.id,\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]);\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 { 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 { 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 { TerraDrawMouseEvent, UpdateTypes, Validation } 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\";\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) {\n\t\tsuper(config);\n\t}\n\n\tprivate lastBearing: number | undefined;\n\n\treset() {\n\t\tthis.lastBearing = undefined;\n\t}\n\n\trotate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t\tvalidateFeature?: Validation,\n\t) {\n\t\tconst geometry = this.store.getGeometryCopy<LineString | Polygon>(\n\t\t\tselectedId,\n\t\t);\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\tconst centerWebMercator = webMercatorCentroid(feature);\n\t\t\tconst cursorWebMercator = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\tbearing = webMercatorBearing(centerWebMercator, cursorWebMercator);\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\tbearing = rhumbBearing(\n\t\t\t\tcentroid({ type: \"Feature\", geometry, properties: {} }),\n\t\t\t\tmouseCoord,\n\t\t\t);\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\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]);\n\n\t\tif (this.projection === \"web-mercator\") {\n\t\t\tthis.lastBearing = bearing;\n\t\t} else if (this.projection === \"globe\") {\n\t\t\tthis.lastBearing = bearing + 180;\n\t\t}\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\nimport { centroid } from \"../centroid\";\nimport { rhumbBearing } from \"../measure/rhumb-bearing\";\nimport { rhumbDestination } from \"../measure/rhumb-destination\";\nimport { rhumbDistance } from \"../measure/rhumb-distance\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\nimport { CartesianPoint } from \"../../common\";\n\n// Adapted on @turf/transform-rotate module which is MIT licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-transform-rotate\n\nexport function transformRotate(\n\tfeature: Feature<Polygon | LineString>,\n\tangle: number,\n) {\n\t// Shortcut no-rotation\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\t// Use centroid of GeoJSON if pivot is not provided\n\tconst pivot = centroid(feature);\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\n\tcoordinates.forEach((pointCoords: Position) => {\n\t\tconst initialAngle = rhumbBearing(pivot, pointCoords);\n\t\tconst finalAngle = initialAngle + angle;\n\t\tconst distance = rhumbDistance(pivot, pointCoords);\n\t\tconst newCoords = rhumbDestination(pivot, distance, finalAngle);\n\t\tpointCoords[0] = newCoords[0];\n\t\tpointCoords[1] = newCoords[1];\n\t});\n\n\treturn feature;\n}\n\n/**\n * Rotate a GeoJSON Polygon geometry in web mercator\n * @param polygon - GeoJSON Polygon geometry\n * @param angle - rotation angle in degrees\n * @returns - rotated GeoJSON Polygon geometry\n */\nexport const transformRotateWebMercator = (\n\tfeature: Feature<Polygon> | Feature<LineString>,\n\tangle: number,\n) => {\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\tconst DEGREES_TO_RADIANS = 0.017453292519943295 as const; // Math.PI / 180\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\tconst angleRad = angle * DEGREES_TO_RADIANS;\n\n\t// Convert polygon coordinates to Web Mercator\n\tconst webMercatorCoords = coordinates.map(([lng, lat]) =>\n\t\tlngLatToWebMercatorXY(lng, lat),\n\t);\n\n\t// Find centroid of the polygon in Web Mercator\n\tconst centroid = webMercatorCoords.reduce(\n\t\t(acc: CartesianPoint, coord: CartesianPoint) => ({\n\t\t\tx: acc.x + coord.x,\n\t\t\ty: acc.y + coord.y,\n\t\t}),\n\t\t{ x: 0, y: 0 },\n\t);\n\tcentroid.x /= webMercatorCoords.length;\n\tcentroid.y /= webMercatorCoords.length;\n\n\t// Rotate the coordinates around the centroid\n\tconst rotatedWebMercatorCoords = webMercatorCoords.map((coord) => ({\n\t\tx:\n\t\t\tcentroid.x +\n\t\t\t(coord.x - centroid.x) * Math.cos(angleRad) -\n\t\t\t(coord.y - centroid.y) * Math.sin(angleRad),\n\t\ty:\n\t\t\tcentroid.y +\n\t\t\t(coord.x - centroid.x) * Math.sin(angleRad) +\n\t\t\t(coord.y - centroid.y) * Math.cos(angleRad),\n\t}));\n\n\t// Convert rotated Web Mercator coordinates back to geographic\n\tconst rotatedCoordinates = rotatedWebMercatorCoords.map(\n\t\t({ x, y }) =>\n\t\t\t[\n\t\t\t\twebMercatorXYToLngLat(x, y).lng,\n\t\t\t\twebMercatorXYToLngLat(x, y).lat,\n\t\t\t] as Position,\n\t);\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tfeature.geometry.coordinates[0] = rotatedCoordinates;\n\t} else {\n\t\tfeature.geometry.coordinates = rotatedCoordinates;\n\t}\n\n\treturn feature;\n};\n","import { TerraDrawMouseEvent, UpdateTypes, Validation } 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 { centroid } from \"../../../geometry/centroid\";\nimport { haversineDistanceKilometers } from \"../../../geometry/measure/haversine-distance\";\nimport {\n\ttransformScale,\n\ttransformScaleWebMercator,\n} from \"../../../geometry/transform/scale\";\nimport { limitPrecision } from \"../../../geometry/limit-decimal-precision\";\nimport { FeatureId } from \"../../../store/store\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../../geometry/measure/pixel-distance\";\n\nexport class ScaleFeatureBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate lastDistance: number | undefined;\n\n\treset() {\n\t\tthis.lastDistance = undefined;\n\t}\n\n\tscale(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t\tvalidateFeature?: Validation,\n\t) {\n\t\tconst geometry = this.store.getGeometryCopy<LineString | Polygon>(\n\t\t\tselectedId,\n\t\t);\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\tconst feature = { type: \"Feature\", geometry, properties: {} } as Feature<\n\t\t\tPolygon | LineString\n\t\t>;\n\n\t\tlet distance;\n\n\t\tconst originWebMercator = webMercatorCentroid(feature);\n\n\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\tconst selectedWebMercator = lngLatToWebMercatorXY(event.lng, event.lat);\n\t\t\tdistance = cartesianDistance(originWebMercator, selectedWebMercator);\n\t\t} else if (this.config.projection === \"globe\") {\n\t\t\tdistance = haversineDistanceKilometers(\n\t\t\t\tcentroid({ type: \"Feature\", geometry, properties: {} }),\n\t\t\t\tmouseCoord,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid projection\");\n\t\t}\n\n\t\t// We need an original bearing to compare against\n\t\tif (!this.lastDistance) {\n\t\t\tthis.lastDistance = distance;\n\t\t\treturn;\n\t\t}\n\n\t\tconst scale = 1 - (this.lastDistance - distance) / distance;\n\n\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\tconst { lng, lat } = webMercatorXYToLngLat(\n\t\t\t\toriginWebMercator.x,\n\t\t\t\toriginWebMercator.y,\n\t\t\t);\n\t\t\ttransformScaleWebMercator(feature, scale, [lng, lat]);\n\t\t} else if (this.config.projection === \"globe\") {\n\t\t\tconst origin = centroid(feature);\n\t\t\ttransformScale(feature, scale, origin);\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\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]);\n\n\t\tthis.lastDistance = distance;\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\n// import { 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\";\n\n// Adapted from the @turf/transform-scale module which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-transform-scale\n\nexport function transformScale(\n\tfeature: Feature<Polygon | LineString>,\n\tfactor: number,\n\torigin: Position,\n\taxis: \"x\" | \"y\" | \"xy\" = \"xy\",\n) {\n\t// Shortcut no-scaling\n\tif (factor === 1) {\n\t\treturn feature;\n\t}\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 originalDistance = rhumbDistance(origin, pointCoords);\n\t\tconst bearing = rhumbBearing(origin, pointCoords);\n\t\tconst newDistance = originalDistance * factor;\n\t\tconst newCoord = rhumbDestination(origin, newDistance, bearing);\n\n\t\tif (axis === \"x\" || axis === \"xy\") {\n\t\t\tpointCoords[0] = newCoord[0];\n\t\t}\n\n\t\tif (axis === \"y\" || axis === \"xy\") {\n\t\t\tpointCoords[1] = newCoord[1];\n\t\t}\n\t});\n\n\treturn feature;\n}\n\n/**\n * Scale a GeoJSON Polygon geometry in web mercator\n * @param polygon - GeoJSON Polygon geometry\n * @param scale - scaling factor\n * @returns - scaled GeoJSON Polygon geometry\n */\nexport function transformScaleWebMercator(\n\tfeature: Feature<Polygon | LineString>,\n\tfactor: number,\n\torigin: Position,\n): Feature<Polygon | LineString> {\n\tif (factor === 1) {\n\t\treturn feature;\n\t}\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\t// Convert polygon coordinates to Web Mercator\n\tconst webMercatorCoords = coordinates.map(([lng, lat]) =>\n\t\tlngLatToWebMercatorXY(lng, lat),\n\t);\n\n\tconst originWebMercator = lngLatToWebMercatorXY(origin[0], origin[1]);\n\n\t// Scale the coordinates around the centroid\n\tconst scaledWebMercatorCoords = webMercatorCoords.map((coord) => ({\n\t\tx: originWebMercator.x + (coord.x - originWebMercator.x) * factor,\n\t\ty: originWebMercator.y + (coord.y - originWebMercator.y) * factor,\n\t}));\n\n\t// Convert scaled Web Mercator coordinates back to geographic\n\tconst scaledCoordinates = scaledWebMercatorCoords.map(({ x, y }) => [\n\t\twebMercatorXYToLngLat(x, y).lng,\n\t\twebMercatorXYToLngLat(x, y).lat,\n\t]);\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tfeature.geometry.coordinates[0] = scaledCoordinates;\n\t} else {\n\t\tfeature.geometry.coordinates = scaledCoordinates;\n\t}\n\n\treturn feature;\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 {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../../../geometry/boolean/is-valid-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\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) {\n\t\tsuper(config);\n\t}\n\n\tprivate minimumScale = 0.0001;\n\n\tprivate draggedCoordinate: { id: null | FeatureId; index: number } = {\n\t\tid: null,\n\t\tindex: -1,\n\t};\n\n\t// This map provides the oppsite corner of the bbox\n\t// to the index of the coordinate provided\n\t// 0 1 2\n\t// *----*----*\n\t// \t |\t\t |\n\t// 7 *\t\t * 3\n\t// |\t\t |\n\t// *----*----*\n\t// \t 6 5 4\n\t//\n\tprivate boundingBoxMaps = {\n\t\topposite: {\n\t\t\t0: 4,\n\t\t\t1: 5,\n\t\t\t2: 6,\n\t\t\t3: 7,\n\t\t\t4: 0,\n\t\t\t5: 1,\n\t\t\t6: 2,\n\t\t\t7: 3,\n\t\t},\n\t};\n\n\tprivate getClosestCoordinate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tgeometry: Polygon | LineString | Point,\n\t) {\n\t\tconst closestCoordinate = {\n\t\t\tdist: Infinity,\n\t\t\tindex: -1,\n\t\t\tisFirstOrLastPolygonCoord: false,\n\t\t};\n\n\t\tlet geomCoordinates: Position[] | undefined;\n\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tgeomCoordinates = geometry.coordinates;\n\t\t} else if (geometry.type === \"Polygon\") {\n\t\t\tgeomCoordinates = geometry.coordinates[0];\n\t\t} else {\n\t\t\t// We don't want to handle dragging\n\t\t\t// points here\n\t\t\treturn closestCoordinate;\n\t\t}\n\n\t\t// Look through the selected features coordinates\n\t\t// and try to find a coordinate that is draggable\n\t\tfor (let i = 0; i < geomCoordinates.length; i++) {\n\t\t\tconst coord = geomCoordinates[i];\n\t\t\tconst distance = this.pixelDistance.measure(event, coord);\n\n\t\t\tif (\n\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\tdistance < closestCoordinate.dist\n\t\t\t) {\n\t\t\t\t// We don't create a point for the final\n\t\t\t\t// polygon coord, so we must set it to the first\n\t\t\t\t// coordinate instead\n\t\t\t\tconst isFirstOrLastPolygonCoord =\n\t\t\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t\t\t(i === geomCoordinates.length - 1 || i === 0);\n\n\t\t\t\tclosestCoordinate.dist = distance;\n\t\t\t\tclosestCoordinate.index = isFirstOrLastPolygonCoord ? 0 : i;\n\t\t\t\tclosestCoordinate.isFirstOrLastPolygonCoord = isFirstOrLastPolygonCoord;\n\t\t\t}\n\t\t}\n\n\t\treturn closestCoordinate;\n\t}\n\n\tprivate isValidDragWebMercator(\n\t\tindex: BoundingBoxIndex,\n\t\tdistanceX: number,\n\t\tdistanceY: number,\n\t) {\n\t\tswitch (index) {\n\t\t\tcase 0:\n\t\t\t\tif (distanceX <= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif (distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (distanceX >= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif (distanceX >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tif (distanceX >= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tif (distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tif (distanceX <= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tif (distanceX <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate getSelectedFeatureDataWebMercator() {\n\t\tif (!this.draggedCoordinate.id || this.draggedCoordinate.index === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = this.getFeature(this.draggedCoordinate.id);\n\t\tif (!feature) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst updatedCoords = this.getNormalisedCoordinates(feature.geometry);\n\t\tconst boundingBox = this.getBBoxWebMercator(updatedCoords);\n\n\t\treturn {\n\t\t\tboundingBox,\n\t\t\tfeature,\n\t\t\tupdatedCoords,\n\t\t\tselectedCoordinate: updatedCoords[this.draggedCoordinate.index],\n\t\t};\n\t}\n\n\tprivate centerWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate centerFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleFixedWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet scale =\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorCursor) /\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorSelected);\n\n\t\tif (scale < 0) {\n\t\t\tscale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\tscale,\n\t\t\tscale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet xScale = 1;\n\t\tif (\n\t\t\tcursorDistanceX !== 0 &&\n\t\t\tclosestBBoxIndex !== 1 &&\n\t\t\tclosestBBoxIndex !== 5\n\t\t) {\n\t\t\tconst currentDistanceX = webMercatorOrigin.x - webMercatorSelected.x;\n\t\t\txScale = 1 - (currentDistanceX - cursorDistanceX) / cursorDistanceX;\n\t\t}\n\n\t\tlet yScale = 1;\n\t\tif (\n\t\t\tcursorDistanceY !== 0 &&\n\t\t\tclosestBBoxIndex !== 3 &&\n\t\t\tclosestBBoxIndex !== 7\n\t\t) {\n\t\t\tconst currentDistanceY = webMercatorOrigin.y - webMercatorSelected.y;\n\t\t\tyScale = 1 - (currentDistanceY - cursorDistanceY) / cursorDistanceY;\n\t\t}\n\n\t\tif (!this.validateScale(xScale, yScale)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (xScale < 0) {\n\t\t\txScale = this.minimumScale;\n\t\t}\n\n\t\tif (yScale < 0) {\n\t\t\tyScale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\txScale,\n\t\t\tyScale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate getFeature(id: FeatureId) {\n\t\tif (this.draggedCoordinate.id === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(id);\n\n\t\t// Update the geometry of the dragged feature\n\t\tif (geometry.type !== \"Polygon\" && geometry.type !== \"LineString\") {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = { type: \"Feature\", geometry, properties: {} } as Feature<\n\t\t\tPolygon | LineString\n\t\t>;\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\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]);\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} 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 { SelectionPointBehavior } 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\";\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\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 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\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.midPoints = new MidPointBehavior(config, this.selectionPoints);\n\n\t\tthis.rotateFeature = new RotateFeatureBehavior(\n\t\t\tconfig,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\n\t\t);\n\n\t\tthis.scaleFeature = new ScaleFeatureBehavior(\n\t\t\tconfig,\n\t\t\tthis.selectionPoints,\n\t\t\tthis.midPoints,\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);\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);\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);\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:\n\t\t\t| {\n\t\t\t\t\tselectionPointFeatureId: string;\n\t\t\t\t\tindex: number;\n\t\t\t }\n\t\t\t| 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(id) as {\n\t\t\t\t\tselectionPointFeatureId: string;\n\t\t\t\t\tindex: number;\n\t\t\t\t};\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\tthis.store.delete([...this.midPoints.ids, ...this.selectionPoints.ids]);\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.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: \"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\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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (event.button === \"left\") {\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\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 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\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\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\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\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\tthis.dragCoordinate.drag(event, canSelfIntersect, validation);\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\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 30;\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 = 40;\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 = 10;\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 = 10;\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 = 10;\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../../common\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { ModeTypes, TerraDrawBaseDrawMode } from \"../base.mode\";\n\ntype StaticModeStylingExt<T extends TerraDrawAdapterStyling> = {};\ntype StaticModeStyling = StaticModeStylingExt<TerraDrawAdapterStyling>;\n\nexport class TerraDrawStaticMode extends TerraDrawBaseDrawMode<StaticModeStyling> {\n\ttype = ModeTypes.Static;\n\tmode = \"static\" as const;\n\tstart() {}\n\tstop() {}\n\tonKeyUp() {}\n\tonKeyDown() {}\n\tonClick() {}\n\tonDragStart() {}\n\tonDrag() {}\n\tonDragEnd() {}\n\tonMouseMove() {}\n\tcleanUp() {}\n\tstyleFeature() {\n\t\treturn { ...getDefaultStyling() };\n\t}\n}\n","// ISC License\n// Copyright (c) 2018, Vladimir Agafonkin\n\nexport type CompareFunction<T> = (a: T, b: T) => number;\n\nexport function quickselect<T>(\n\tarr: T[],\n\tk: number,\n\tleft: number,\n\tright: number,\n\tcompare: CompareFunction<T>,\n) {\n\twhile (right > left) {\n\t\tif (right - left > 600) {\n\t\t\tconst n = right - left + 1;\n\t\t\tconst m = k - left + 1;\n\t\t\tconst z = Math.log(n);\n\t\t\tconst s = 0.5 * Math.exp((2 * z) / 3);\n\t\t\tconst sd =\n\t\t\t\t0.5 * Math.sqrt((z * s * (n - s)) / n) * (m - n / 2 < 0 ? -1 : 1);\n\t\t\tconst newLeft = Math.max(left, Math.floor(k - (m * s) / n + sd));\n\t\t\tconst newRight = Math.min(right, Math.floor(k + ((n - m) * s) / n + sd));\n\t\t\tquickselect(arr, k, newLeft, newRight, compare);\n\t\t}\n\n\t\tconst t = arr[k];\n\t\tlet i = left;\n\t\tlet j = right;\n\n\t\tswap(arr, left, k);\n\t\tif (compare(arr[right], t) > 0) swap(arr, left, right);\n\n\t\twhile (i < j) {\n\t\t\tswap(arr, i, j);\n\t\t\ti++;\n\t\t\tj--;\n\t\t\twhile (compare(arr[i], t) < 0) i++;\n\t\t\twhile (compare(arr[j], t) > 0) j--;\n\t\t}\n\n\t\tif (compare(arr[left], t) === 0) {\n\t\t\tswap(arr, left, j);\n\t\t} else {\n\t\t\tj++;\n\t\t\tswap(arr, j, right);\n\t\t}\n\n\t\tif (j <= k) left = j + 1;\n\t\tif (k <= j) right = j - 1;\n\t}\n}\n\nfunction swap<T>(arr: T[], i: number, j: number) {\n\tconst tmp = arr[i];\n\tarr[i] = arr[j];\n\tarr[j] = tmp;\n}\n","// Base on Rbush - https://github.com/mourner/rbush\n// MIT License\n// Copyright (c) 2016 Vladimir Agafonkin\n\nimport { CompareFunction, quickselect } from \"./quickselect\";\n\nexport type Node = {\n\tchildren: Node[];\n\theight: number;\n\tleaf: boolean;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n};\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node: Node, toBBox: (node: Node) => any) {\n\tdistBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(\n\tnode: Node,\n\tk: number,\n\tp: number,\n\ttoBBox: (node: Node) => Node,\n\tdestNode?: Node,\n) {\n\tif (!destNode) destNode = createNode([]);\n\tdestNode.minX = Infinity;\n\tdestNode.minY = Infinity;\n\tdestNode.maxX = -Infinity;\n\tdestNode.maxY = -Infinity;\n\n\tfor (let i = k; i < p; i++) {\n\t\tconst child = node.children[i];\n\t\textend(destNode, node.leaf ? toBBox(child) : child);\n\t}\n\n\treturn destNode;\n}\n\nfunction extend(a: Node, b: Node) {\n\ta.minX = Math.min(a.minX, b.minX);\n\ta.minY = Math.min(a.minY, b.minY);\n\ta.maxX = Math.max(a.maxX, b.maxX);\n\ta.maxY = Math.max(a.maxY, b.maxY);\n\treturn a;\n}\n\nfunction compareNodeMinX(a: Node, b: Node) {\n\treturn a.minX - b.minX;\n}\nfunction compareNodeMinY(a: Node, b: Node) {\n\treturn a.minY - b.minY;\n}\n\nfunction bboxArea(a: Node) {\n\treturn (a.maxX - a.minX) * (a.maxY - a.minY);\n}\nfunction bboxMargin(a: {\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}) {\n\treturn a.maxX - a.minX + (a.maxY - a.minY);\n}\n\nfunction enlargedArea(a: Node, b: Node) {\n\treturn (\n\t\t(Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n\t\t(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY))\n\t);\n}\n\nfunction intersectionArea(a: Node, b: Node) {\n\tconst minX = Math.max(a.minX, b.minX);\n\tconst minY = Math.max(a.minY, b.minY);\n\tconst maxX = Math.min(a.maxX, b.maxX);\n\tconst maxY = Math.min(a.maxY, b.maxY);\n\n\treturn Math.max(0, maxX - minX) * Math.max(0, maxY - minY);\n}\n\nfunction contains(a: Node, b: Node) {\n\treturn (\n\t\ta.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY\n\t);\n}\n\nfunction intersects(a: Node, b: Node) {\n\treturn (\n\t\tb.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY\n\t);\n}\n\nfunction createNode(children: Node[]) {\n\treturn {\n\t\tchildren,\n\t\theight: 1,\n\t\tleaf: true,\n\t\tminX: Infinity,\n\t\tminY: Infinity,\n\t\tmaxX: -Infinity,\n\t\tmaxY: -Infinity,\n\t};\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect<T>(\n\tarr: T[],\n\tleft: number,\n\tright: number,\n\tn: number,\n\tcompare: CompareFunction<T>,\n) {\n\tconst stack = [left, right];\n\n\twhile (stack.length) {\n\t\tright = stack.pop() as number;\n\t\tleft = stack.pop() as number;\n\n\t\tif (right - left <= n) continue;\n\n\t\tconst mid = left + Math.ceil((right - left) / n / 2) * n;\n\t\tquickselect(arr, mid, left, right, compare);\n\n\t\tstack.push(left, mid, mid, right);\n\t}\n}\n\nexport class RBush {\n\tprivate _maxEntries: number;\n\tprivate _minEntries: number;\n\tprivate data!: Node;\n\n\tconstructor(maxEntries: number) {\n\t\t// max entries in a node is 9 by default; min node fill is 40% for best performance\n\t\tthis._maxEntries = Math.max(4, maxEntries);\n\t\tthis._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n\t\tthis.clear();\n\t}\n\n\tsearch(bbox: Node): Node[] {\n\t\tlet node = this.data;\n\t\tconst result: Node[] = [];\n\n\t\tif (!intersects(bbox, node)) {\n\t\t\treturn result;\n\t\t}\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst nodesToSearch = [];\n\n\t\twhile (node) {\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\t\t\t\tconst childBBox = node.leaf ? toBBox(child) : child;\n\n\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\tif (node.leaf) result.push(child);\n\t\t\t\t\telse if (contains(bbox, childBBox)) this._all(child, result);\n\t\t\t\t\telse nodesToSearch.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tcollides(bbox: Node) {\n\t\tlet node = this.data;\n\n\t\tconst intersect = intersects(bbox, node);\n\t\tif (intersect) {\n\t\t\tconst nodesToSearch = [];\n\t\t\twhile (node) {\n\t\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\t\tconst child = node.children[i];\n\t\t\t\t\tconst childBBox = node.leaf ? this.toBBox(child) : child;\n\n\t\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\t\tif (node.leaf || contains(bbox, childBBox)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnodesToSearch.push(child);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tload(data: Node[]): void {\n\t\tif (data.length < this._minEntries) {\n\t\t\tfor (let i = 0; i < data.length; i++) {\n\t\t\t\tthis.insert(data[i]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// recursively build the tree with the given data from scratch using OMT algorithm\n\t\tlet node = this._build(data.slice(), 0, data.length - 1, 0);\n\n\t\tif (!this.data.children.length) {\n\t\t\t// save as is if tree is empty\n\t\t\tthis.data = node;\n\t\t} else if (this.data.height === node.height) {\n\t\t\t// split root if trees have the same height\n\t\t\tthis._splitRoot(this.data, node);\n\t\t} else {\n\t\t\tif (this.data.height < node.height) {\n\t\t\t\t// swap trees if inserted one is bigger\n\t\t\t\tconst tmpNode = this.data;\n\t\t\t\tthis.data = node;\n\t\t\t\tnode = tmpNode;\n\t\t\t}\n\n\t\t\t// insert the small tree into the large tree at appropriate level\n\t\t\tthis._insert(node, this.data.height - node.height - 1, true);\n\t\t}\n\t}\n\n\tinsert(item: Node): void {\n\t\tthis._insert(item, this.data.height - 1);\n\t}\n\n\tclear(): void {\n\t\tthis.data = createNode([]);\n\t}\n\n\tremove(item: Node): void {\n\t\tlet node: Node | null = this.data;\n\t\tconst bbox = this.toBBox(item);\n\t\tconst path = [];\n\t\tconst indexes: number[] = [];\n\t\tlet i: number | undefined;\n\t\tlet parent: Node | undefined;\n\t\tlet goingUp = false;\n\n\t\t// depth-first iterative tree traversal\n\t\twhile (node || path.length) {\n\t\t\tif (!node) {\n\t\t\t\t// go up\n\t\t\t\tnode = path.pop() as Node;\n\t\t\t\tparent = path[path.length - 1];\n\t\t\t\ti = indexes.pop() as number;\n\t\t\t\tgoingUp = true;\n\t\t\t}\n\n\t\t\tif (node.leaf) {\n\t\t\t\t// check current node\n\n\t\t\t\tconst index = node.children.indexOf(item);\n\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\t// item found, remove the item and condense tree upwards\n\t\t\t\t\tnode.children.splice(index, 1);\n\t\t\t\t\tpath.push(node);\n\t\t\t\t\tthis._condense(path);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!goingUp && !node.leaf && contains(node, bbox)) {\n\t\t\t\t// go down\n\t\t\t\tpath.push(node);\n\t\t\t\tindexes.push(i as number);\n\t\t\t\ti = 0;\n\t\t\t\tparent = node;\n\t\t\t\tnode = node.children[0];\n\t\t\t} else if (parent) {\n\t\t\t\t// go right\n\t\t\t\t(i as number)++;\n\t\t\t\tnode = parent.children[i as number];\n\t\t\t\tgoingUp = false;\n\t\t\t} else {\n\t\t\t\tnode = null; // nothing found\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate toBBox<T>(item: T): T {\n\t\treturn item;\n\t}\n\n\tprivate compareMinX(a: Node, b: Node) {\n\t\treturn a.minX - b.minX;\n\t}\n\tprivate compareMinY(a: Node, b: Node) {\n\t\treturn a.minY - b.minY;\n\t}\n\n\tprivate _all(node: Node, result: Node[]) {\n\t\tconst nodesToSearch = [];\n\t\twhile (node) {\n\t\t\tif (node.leaf) result.push(...node.children);\n\t\t\telse nodesToSearch.push(...node.children);\n\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _build(items: Node[], left: number, right: number, height: number) {\n\t\tconst N = right - left + 1;\n\t\tlet M = this._maxEntries;\n\t\tlet node;\n\n\t\tif (N <= M) {\n\t\t\t// reached leaf level; return leaf\n\t\t\tnode = createNode(items.slice(left, right + 1));\n\t\t\tcalcBBox(node, this.toBBox);\n\t\t\treturn node;\n\t\t}\n\n\t\tif (!height) {\n\t\t\t// target height of the bulk-loaded tree\n\t\t\theight = Math.ceil(Math.log(N) / Math.log(M));\n\n\t\t\t// target number of root entries to maximize storage utilization\n\t\t\tM = Math.ceil(N / Math.pow(M, height - 1));\n\t\t}\n\n\t\tnode = createNode([]);\n\t\tnode.leaf = false;\n\t\tnode.height = height;\n\n\t\t// split the items into M mostly square tiles\n\n\t\tconst N2 = Math.ceil(N / M);\n\t\tconst N1 = N2 * Math.ceil(Math.sqrt(M));\n\n\t\tmultiSelect(items, left, right, N1, this.compareMinX);\n\n\t\tfor (let i = left; i <= right; i += N1) {\n\t\t\tconst right2 = Math.min(i + N1 - 1, right);\n\n\t\t\tmultiSelect(items, i, right2, N2, this.compareMinY);\n\n\t\t\tfor (let j = i; j <= right2; j += N2) {\n\t\t\t\tconst right3 = Math.min(j + N2 - 1, right2);\n\n\t\t\t\t// pack each entry recursively\n\t\t\t\tnode.children.push(this._build(items, j, right3, height - 1));\n\t\t\t}\n\t\t}\n\n\t\tcalcBBox(node, this.toBBox);\n\n\t\treturn node;\n\t}\n\n\tprivate _chooseSubtree(bbox: Node, node: Node, level: number, path: Node[]) {\n\t\twhile (true) {\n\t\t\tpath.push(node);\n\n\t\t\tif (node.leaf || path.length - 1 === level) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet minArea = Infinity;\n\t\t\tlet minEnlargement = Infinity;\n\t\t\tlet targetNode;\n\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\n\t\t\t\tconst area = bboxArea(child);\n\t\t\t\tconst enlargement = enlargedArea(bbox, child) - area;\n\n\t\t\t\t// choose entry with the least area enlargement\n\n\t\t\t\tif (enlargement < minEnlargement) {\n\t\t\t\t\tminEnlargement = enlargement;\n\t\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t\t\ttargetNode = child;\n\t\t\t\t} else if (enlargement === minEnlargement) {\n\t\t\t\t\t// otherwise choose one with the smallest area\n\t\t\t\t\tif (area < minArea) {\n\t\t\t\t\t\tminArea = area;\n\t\t\t\t\t\ttargetNode = child;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnode = targetNode || node.children[0];\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate _insert(item: Node, level: number, isNode?: boolean) {\n\t\tconst bbox = isNode ? item : this.toBBox(item);\n\t\tconst insertPath: Node[] = [];\n\n\t\t// find the best node for accommodating the item, saving all nodes along the path too\n\t\tconst node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n\t\t// put the item into the node\n\t\tnode.children.push(item);\n\t\textend(node, bbox);\n\n\t\t// split on node overflow; propagate upwards if necessary\n\t\twhile (level >= 0) {\n\t\t\tif (insertPath[level].children.length > this._maxEntries) {\n\t\t\t\tthis._split(insertPath, level);\n\t\t\t\tlevel--;\n\t\t\t} else break;\n\t\t}\n\n\t\t// adjust bboxes along the insertion path\n\t\tthis._adjustParentBBoxes(bbox, insertPath, level);\n\t}\n\n\t// split overflowed node into two\n\tprivate _split(insertPath: Node[], level: number) {\n\t\tconst node = insertPath[level];\n\t\tconst M = node.children.length;\n\t\tconst m = this._minEntries;\n\n\t\tthis._chooseSplitAxis(node, m, M);\n\n\t\tconst splitIndex = this._chooseSplitIndex(node, m, M);\n\n\t\tconst newNode = createNode(\n\t\t\tnode.children.splice(splitIndex, node.children.length - splitIndex),\n\t\t);\n\t\tnewNode.height = node.height;\n\t\tnewNode.leaf = node.leaf;\n\n\t\tcalcBBox(node, this.toBBox);\n\t\tcalcBBox(newNode, this.toBBox);\n\n\t\tif (level) insertPath[level - 1].children.push(newNode);\n\t\telse this._splitRoot(node, newNode);\n\t}\n\n\tprivate _splitRoot(node: Node, newNode: Node) {\n\t\t// split root node\n\t\tthis.data = createNode([node, newNode]);\n\t\tthis.data.height = node.height + 1;\n\t\tthis.data.leaf = false;\n\t\tcalcBBox(this.data, this.toBBox);\n\t}\n\n\tprivate _chooseSplitIndex(node: Node, m: number, M: number) {\n\t\tlet index;\n\t\tlet minOverlap = Infinity;\n\t\tlet minArea = Infinity;\n\n\t\tfor (let i = m; i <= M - m; i++) {\n\t\t\tconst bbox1 = distBBox(node, 0, i, this.toBBox);\n\t\t\tconst bbox2 = distBBox(node, i, M, this.toBBox);\n\n\t\t\tconst overlap = intersectionArea(bbox1, bbox2);\n\t\t\tconst area = bboxArea(bbox1) + bboxArea(bbox2);\n\n\t\t\t// choose distribution with minimum overlap\n\t\t\tif (overlap < minOverlap) {\n\t\t\t\tminOverlap = overlap;\n\t\t\t\tindex = i;\n\n\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t} else if (overlap === minOverlap) {\n\t\t\t\t// otherwise choose distribution with minimum area\n\t\t\t\tif (area < minArea) {\n\t\t\t\t\tminArea = area;\n\t\t\t\t\tindex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn index || M - m;\n\t}\n\n\t// sorts node children by the best axis for split\n\tprivate _chooseSplitAxis(node: Node, m: number, M: number) {\n\t\tconst compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n\t\tconst compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n\t\tconst xMargin = this._allDistMargin(node, m, M, compareMinX);\n\t\tconst yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n\t\t// if total distributions margin value is minimal for x, sort by minX,\n\t\t// otherwise it's already sorted by minY\n\t\tif (xMargin < yMargin) {\n\t\t\tnode.children.sort(compareMinX);\n\t\t}\n\t}\n\n\t// total margin of all possible split distributions where each node is at least m full\n\tprivate _allDistMargin(\n\t\tnode: Node,\n\t\tm: number,\n\t\tM: number,\n\t\tcompare: CompareFunction<Node>,\n\t) {\n\t\tnode.children.sort(compare);\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst leftBBox = distBBox(node, 0, m, toBBox);\n\t\tconst rightBBox = distBBox(node, M - m, M, toBBox);\n\t\tlet margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n\t\tfor (let i = m; i < M - m; i++) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(leftBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(leftBBox);\n\t\t}\n\n\t\tfor (let i = M - m - 1; i >= m; i--) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(rightBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(rightBBox);\n\t\t}\n\n\t\treturn margin;\n\t}\n\n\tprivate _adjustParentBBoxes(bbox: Node, path: Node[], level: number) {\n\t\t// adjust bboxes along the given tree path\n\t\tfor (let i = level; i >= 0; i--) {\n\t\t\textend(path[i], bbox);\n\t\t}\n\t}\n\n\tprivate _condense(path: Node[]) {\n\t\t// go through the path, removing empty nodes and updating bboxes\n\t\tfor (let i = path.length - 1, siblings; i >= 0; i--) {\n\t\t\tif (path[i].children.length === 0) {\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tsiblings = path[i - 1].children;\n\t\t\t\t\tsiblings.splice(siblings.indexOf(path[i]), 1);\n\t\t\t\t} else this.clear();\n\t\t\t} else {\n\t\t\t\tcalcBBox(path[i], this.toBBox);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Position } from \"geojson\";\nimport { FeatureId, GeoJSONStoreFeatures } from \"../store\";\nimport { RBush, Node } from \"./rbush\";\n\nexport class SpatialIndex {\n\tprivate tree: RBush;\n\tprivate idToNode: Map<FeatureId, Node>;\n\tprivate nodeToId: Map<Node, FeatureId>;\n\n\tconstructor(options?: { maxEntries: number }) {\n\t\tthis.tree = new RBush(\n\t\t\toptions && options.maxEntries ? options.maxEntries : 9,\n\t\t);\n\t\tthis.idToNode = new Map();\n\t\tthis.nodeToId = new Map();\n\t}\n\n\tprivate setMaps(feature: GeoJSONStoreFeatures, bbox: Node) {\n\t\tthis.idToNode.set(feature.id as FeatureId, bbox);\n\t\tthis.nodeToId.set(bbox, feature.id as FeatureId);\n\t}\n\n\tprivate toBBox(feature: GeoJSONStoreFeatures) {\n\t\tconst longitudes: number[] = [];\n\t\tconst latitudes: number[] = [];\n\n\t\tlet coordinates: Position[];\n\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\tcoordinates = [feature.geometry.coordinates];\n\t\t} else {\n\t\t\tthrow new Error(\"Not a valid feature to turn into a bounding box\");\n\t\t}\n\n\t\tfor (let i = 0; i < coordinates.length; i++) {\n\t\t\tlatitudes.push(coordinates[i][1]);\n\t\t\tlongitudes.push(coordinates[i][0]);\n\t\t}\n\n\t\tconst minLat = Math.min(...latitudes);\n\t\tconst maxLat = Math.max(...latitudes);\n\t\tconst minLng = Math.min(...longitudes);\n\t\tconst maxLng = Math.max(...longitudes);\n\n\t\treturn {\n\t\t\tminX: minLng,\n\t\t\tminY: minLat,\n\t\t\tmaxX: maxLng,\n\t\t\tmaxY: maxLat,\n\t\t} as Node;\n\t}\n\n\tinsert(feature: GeoJSONStoreFeatures): void {\n\t\tif (this.idToNode.get(String(feature.id))) {\n\t\t\tthrow new Error(\"Feature already exists\");\n\t\t}\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tload(features: GeoJSONStoreFeatures[]): void {\n\t\tconst load: Node[] = [];\n\t\tconst seenIds: Set<string> = new Set();\n\t\tfeatures.forEach((feature) => {\n\t\t\tconst bbox = this.toBBox(feature);\n\t\t\tthis.setMaps(feature, bbox);\n\t\t\tif (seenIds.has(String(feature.id))) {\n\t\t\t\tthrow new Error(`Duplicate feature ID found ${feature.id}`);\n\t\t\t}\n\t\t\tseenIds.add(String(feature.id));\n\t\t\tload.push(bbox);\n\t\t});\n\t\tthis.tree.load(load);\n\t}\n\n\tupdate(feature: GeoJSONStoreFeatures): void {\n\t\tthis.remove(feature.id as FeatureId);\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tremove(featureId: FeatureId): void {\n\t\tconst node = this.idToNode.get(featureId);\n\t\tif (!node) {\n\t\t\tthrow new Error(`${featureId} not inserted into the spatial index`);\n\t\t}\n\n\t\tthis.tree.remove(node);\n\t}\n\n\tclear(): void {\n\t\tthis.tree.clear();\n\t}\n\n\tsearch(feature: GeoJSONStoreFeatures): FeatureId[] {\n\t\tconst found = this.tree.search(this.toBBox(feature));\n\t\treturn found.map((node) => {\n\t\t\treturn this.nodeToId.get(node) as FeatureId;\n\t\t});\n\t}\n\n\tcollides(feature: GeoJSONStoreFeatures): boolean {\n\t\treturn this.tree.collides(this.toBBox(feature));\n\t}\n}\n","import { Feature, Point, Polygon, LineString } from \"geojson\";\nimport { uuid4 } from \"../util/id\";\nimport { SpatialIndex } from \"./spatial-index/spatial-index\";\nimport { isValidTimestamp } from \"./store-feature-validation\";\nimport { Validation } from \"../common\";\n\ntype JSON = string | number | boolean | null | JSONArray | JSONObject;\n\nexport interface JSONObject {\n\t[member: string]: JSON;\n}\ntype JSONArray = Array<JSON>;\n\ntype DefinedProperties = Record<string, JSON>;\n\nexport type GeoJSONStoreGeometries = Polygon | LineString | Point;\n\nexport type BBoxPolygon = Feature<Polygon, DefinedProperties>;\n\nexport type GeoJSONStoreFeatures = Feature<\n\tGeoJSONStoreGeometries,\n\tDefinedProperties\n>;\n\nexport type StoreValidation = {\n\tid?: FeatureId;\n} & ReturnType<Validation>;\n\ntype StoreChangeEvents = \"delete\" | \"create\" | \"update\" | \"styling\";\n\nexport type StoreChangeHandler = (\n\tids: FeatureId[],\n\tchange: StoreChangeEvents,\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<Id extends FeatureId = FeatureId> {\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 = () => {};\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): 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\tvalidations.push({ id, valid: true });\n\n\t\t\treturn true;\n\t\t});\n\t\tthis.spatialIndex.load(clonedData);\n\t\tthis._onChange(changes, \"create\");\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) {\n\t\tthis._onChange = (ids, change) => {\n\t\t\tonChange(ids, change);\n\t\t};\n\t}\n\n\tgetGeometryCopy<T extends GeoJSONStoreGeometries>(id: FeatureId): T {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get geometry copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.geometry as T);\n\t}\n\n\tgetPropertiesCopy(id: FeatureId) {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get properties copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.properties);\n\t}\n\n\tupdateProperty(\n\t\tpropertiesToUpdate: { id: FeatureId; property: string; value: JSON }[],\n\t): void {\n\t\tconst ids: FeatureId[] = [];\n\t\tpropertiesToUpdate.forEach(({ id, property, value }) => {\n\t\t\tconst feature = this.store[id];\n\n\t\t\tif (!feature) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No feature with this (${id}), can not update geometry`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tids.push(id);\n\n\t\t\tfeature.properties[property] = value;\n\n\t\t\t// Update the time the feature was updated\n\t\t\tif (this.tracked) {\n\t\t\t\tfeature.properties.updatedAt = +new Date();\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange(ids, \"update\");\n\t\t}\n\t}\n\n\tupdateGeometry(\n\t\tgeometriesToUpdate: { id: FeatureId; geometry: GeoJSONStoreGeometries }[],\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\");\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): 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\");\n\t\t}\n\n\t\treturn ids as Id[];\n\t}\n\n\tdelete(ids: FeatureId[]): 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 this id, can not delete\");\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange([...ids], \"delete\");\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\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 { 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","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} from \"../../common\";\nimport { Polygon } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport { webMercatorBearing } from \"../../geometry/measure/bearing\";\nimport { midpointCoordinate } from \"../../geometry/midpoint-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { degreesToRadians } from \"../../geometry/helpers\";\nimport { determineHalfPlane } from \"../../geometry/determine-halfplane\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { calculateRelativeAngle } from \"../../geometry/calculate-relative-angle\";\n\ntype TerraDrawPolygonModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype PolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawAngledRectangleMode extends TerraDrawBaseDrawMode<PolygonStyling> {\n\tmode = \"angled-rectangle\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawPolygonModeKeyEvents = defaultKeyEvents;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawPolygonModeOptions<PolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawPolygonModeOptions<PolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst firstCoordinate = currentPolygonCoordinates[0];\n\t\t\tconst secondCoordinate = currentPolygonCoordinates[1];\n\t\t\tconst midpoint = midpointCoordinate(\n\t\t\t\tfirstCoordinate,\n\t\t\t\tsecondCoordinate,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t\tthis.project,\n\t\t\t\tthis.unproject,\n\t\t\t);\n\n\t\t\tconst A = lngLatToWebMercatorXY(firstCoordinate[0], firstCoordinate[1]);\n\t\t\tconst B = lngLatToWebMercatorXY(midpoint[0], midpoint[1]);\n\t\t\tconst C = lngLatToWebMercatorXY(secondCoordinate[0], secondCoordinate[1]);\n\t\t\tconst D = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\t// Determine if the cursor is closer to A or C\n\t\t\tconst distanceToA = cartesianDistance(D, A);\n\t\t\tconst distanceToB = cartesianDistance(D, C);\n\t\t\tconst ACloserThanC = distanceToA < distanceToB ? true : false;\n\n\t\t\t// We need to work out if the cursor is closer to A or C and then calculate the angle\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst relativeAngle = calculateRelativeAngle(A, B, D);\n\t\t\tconst theta = ACloserThanC\n\t\t\t\t? 90 - relativeAngle\n\t\t\t\t: calculateRelativeAngle(A, B, D) - 90;\n\n\t\t\t// We want to calculate the adjacent i.e. the calculated distance\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst hypotenuse = cartesianDistance(B, D);\n\t\t\tconst adjacent = Math.cos(degreesToRadians(theta)) * hypotenuse;\n\n\t\t\t// Calculate the bearing between the first and second point\n\t\t\tconst firstAndSecondPointBearing = webMercatorBearing(A, C);\n\n\t\t\t// Determine which side of the line the cursor is on\n\t\t\tconst side = determineHalfPlane(A, C, D);\n\n\t\t\t// Determine which direction to draw the rectangle\n\t\t\tconst angle = side === \"right\" ? -90 : 90;\n\n\t\t\t// Calculate the third and fourth coordinates based on the cursor position\n\t\t\tconst rectangleAngle = firstAndSecondPointBearing + angle;\n\t\t\tconst thirdCoordinateXY = webMercatorDestination(\n\t\t\t\tA,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\t\t\tconst fourthCoordinateXY = webMercatorDestination(\n\t\t\t\tC,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\n\t\t\t// Convert the third and fourth coordinates back to lng/lat\n\t\t\tconst thirdCoordinate = webMercatorXYToLngLat(\n\t\t\t\tthirdCoordinateXY.x,\n\t\t\t\tthirdCoordinateXY.y,\n\t\t\t);\n\t\t\tconst fourthCoordinate = webMercatorXYToLngLat(\n\t\t\t\tfourthCoordinateXY.x,\n\t\t\t\tfourthCoordinateXY.y,\n\t\t\t);\n\n\t\t\t// The final coordinates\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[fourthCoordinate.lng, fourthCoordinate.lat],\n\t\t\t\t[thirdCoordinate.lng, thirdCoordinate.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 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\tthis.currentId,\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\tthis.close();\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 = 10;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\n// Function to determine the relative position of a point to a line segment\nexport function determineHalfPlane(\n\tpoint: CartesianPoint,\n\tlineStart: CartesianPoint,\n\tlineEnd: CartesianPoint,\n): string {\n\t// Calculate the vectors\n\tconst vectorLine = { x: lineEnd.x - lineStart.x, y: lineEnd.y - lineStart.y };\n\tconst vectorPoint = { x: point.x - lineStart.x, y: point.y - lineStart.y };\n\n\t// Calculate the cross product\n\tconst crossProduct =\n\t\tvectorLine.x * vectorPoint.y - vectorLine.y * vectorPoint.x;\n\n\t// Use a small epsilon value to handle floating-point precision errors\n\tconst epsilon = 1e-10;\n\n\tif (crossProduct > epsilon) {\n\t\treturn \"left\";\n\t} else if (crossProduct < -epsilon) {\n\t\treturn \"right\";\n\t} else {\n\t\t// Technically on the line but we treat it as left\n\t\treturn \"left\";\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\nexport function isClockwiseWebMercator(\n\tcenter: CartesianPoint,\n\tsecondCoord: CartesianPoint,\n\tthirdCoord: CartesianPoint,\n): boolean {\n\t// Calculate the vectors\n\tconst vector1 = { x: secondCoord.x - center.x, y: secondCoord.y - center.y };\n\tconst vector2 = { x: thirdCoord.x - center.x, y: thirdCoord.y - center.y };\n\n\t// Calculate the cross product\n\tconst cross = vector1.x * vector2.y - vector1.y * vector2.x;\n\n\t// If the cross product is negative, the third point is on the right (clockwise)\n\t// If the cross product is positive, the third point is on the left (anticlockwise)\n\treturn cross <= 0;\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n} from \"../../common\";\nimport { Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSectorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SectorPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSectorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSectorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSectorMode extends TerraDrawBaseDrawMode<SectorPolygonStyling> {\n\tmode = \"sector\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSectorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSectorModeOptions<SectorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSectorModeOptions<SectorPolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t);\n\t\tif (correctedGeometry) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t]);\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates: Polygon[\"coordinates\"][0] | undefined;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst center = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[1];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\t// Convert coordinates to Web Mercator\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate the radius (distance from center to second point in Web Mercator)\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [center]; // Start with the center (in WGS84)\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add the first coordinate to the polygon\n\t\t\tcoordinates.push(arcCoordOne);\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(center);\n\n\t\t\tupdatedCoordinates = [...coordinates];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 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\tthis.currentId,\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\tthis.close();\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 = 10;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n} from \"../../common\";\nimport { LineString, Point, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSensorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SensorPolygonStyling = {\n\tcenterPointColor: HexColorStyling;\n\tcenterPointWidth: NumericStyling;\n\tcenterPointOutlineColor: HexColorStyling;\n\tcenterPointOutlineWidth: NumericStyling;\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSensorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSensorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSensorMode extends TerraDrawBaseDrawMode<SensorPolygonStyling> {\n\tmode = \"sensor\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate currentInitialArcId: FeatureId | undefined;\n\tprivate currentStartingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSensorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSensorModeOptions<SensorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSensorModeOptions<SensorPolygonStyling>,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentStartingPointId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedCurrentStartingPointId = this.currentStartingPointId;\n\t\tconst finishedInitialArcId = this.currentInitialArcId;\n\t\tconst finishedCurrentId = this.currentId;\n\n\t\tif (finishedCurrentStartingPointId) {\n\t\t\tthis.store.delete([finishedCurrentStartingPointId]);\n\t\t}\n\n\t\tif (finishedInitialArcId) {\n\t\t\tthis.store.delete([finishedInitialArcId]);\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentStartingPointId = undefined;\n\t\tthis.currentInitialArcId = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedCurrentId) {\n\t\t\tthis.onFinish(finishedCurrentId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (\n\t\t\tthis.currentInitialArcId === undefined ||\n\t\t\tthis.currentStartingPointId === undefined ||\n\t\t\tthis.currentCoordinate === 0\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentCoordinate === 2) {\n\t\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [arcCoordOne];\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.updateLineStringGeometry(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t\tcoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t} else if (this.currentCoordinate === 3) {\n\t\t\tconst coordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\n\t\t\tif (coordinates.length < 2) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// This shouldn't happen but we protect against it in case as we can't calculate if the cursor\n\t\t\t// is in the sector otherwise\n\t\t\tif (!this.direction) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst firstCoord = coordinates[0];\n\t\t\tconst lastCoord = coordinates[coordinates.length - 1];\n\n\t\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\t\t\tconst webMercatorCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tfirstCoord[0],\n\t\t\t\tfirstCoord[1],\n\t\t\t);\n\t\t\tconst webMercatorCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tlastCoord[0],\n\t\t\t\tlastCoord[1],\n\t\t\t);\n\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst innerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\n\t\t\tconst outerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst hasLessThanZeroSize = outerRadius < innerRadius;\n\n\t\t\t// If the cursor is inside the inner radius, the depth of the sensor is always 0\n\t\t\tconst radiusCalculationPosition = hasLessThanZeroSize\n\t\t\t\t? webMercatorCoordOne\n\t\t\t\t: webMercatorCursor;\n\n\t\t\tconst cursorBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordTwo,\n\t\t\t);\n\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\t\t\tconst normalizedCursor = normalizeBearing(cursorBearing);\n\n\t\t\tconst notInSector = this.notInSector({\n\t\t\t\tnormalizedCursor,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t\tdirection: this.direction,\n\t\t\t});\n\n\t\t\t// If it's not a valid cursor movement then we don't update\n\t\t\tif (notInSector) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tconst deltaBearing = this.getDeltaBearing(\n\t\t\t\tthis.direction,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t);\n\n\t\t\t// Number of points to approximate the arc\n\t\t\tconst numberOfPoints = this.arcPoints;\n\n\t\t\t// Calculate bearing step\n\t\t\tconst multiplier = this.direction === \"anticlockwise\" ? 1 : -1;\n\t\t\tconst bearingStep = (multiplier * deltaBearing) / numberOfPoints;\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\tradiusCalculationPosition,\n\t\t\t);\n\n\t\t\t// Add all the arc points\n\t\t\tconst finalArc = [];\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tfinalArc.unshift(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcoordinates.push(...finalArc);\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(coordinates[0]);\n\n\t\t\t// If the polygon doesn't exist, create it\n\t\t\t// else update the existing geometry\n\t\t\tif (!this.currentId) {\n\t\t\t\t[this.currentId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [coordinates],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tthis.updatePolygonGeometry(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t\tcoordinates,\n\t\t\t\t\tUpdateTypes.Provisional,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateLineStringGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates,\n\t\t} as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: { type: \"Point\", coordinates: [event.lng, event.lat] },\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentStartingPointId = newId;\n\t\t\tthis.currentCoordinate++;\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.currentStartingPointId) {\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: \"LineString\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentInitialArcId = newId;\n\t\t\tthis.currentCoordinate++;\n\t\t} else if (this.currentCoordinate === 2 && this.currentStartingPointId) {\n\t\t\tthis.currentCoordinate++;\n\t\t\t// pass\n\t\t} else if (this.currentCoordinate === 3 && this.currentStartingPointId) {\n\t\t\tthis.close();\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 = 10;\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 = 10;\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 = 20;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate getDeltaBearing(\n\t\tdirection: \"anticlockwise\" | \"clockwise\",\n\t\tnormalizedStart: number,\n\t\tnormalizedEnd: number,\n\t) {\n\t\tlet deltaBearing;\n\t\tif (direction === \"anticlockwise\") {\n\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t} else {\n\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t}\n\t\treturn deltaBearing;\n\t}\n\n\tprivate notInSector({\n\t\tnormalizedCursor,\n\t\tnormalizedStart,\n\t\tnormalizedEnd,\n\t\tdirection,\n\t}: {\n\t\tnormalizedCursor: number;\n\t\tnormalizedStart: number;\n\t\tnormalizedEnd: number;\n\t\tdirection: \"clockwise\" | \"anticlockwise\";\n\t}) {\n\t\tif (direction === \"clockwise\") {\n\t\t\t// Handle clockwise direction\n\t\t\tif (normalizedStart <= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart &&\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart ||\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Handle anticlockwise direction\n\t\t\tif (normalizedStart >= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart &&\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart ||\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n","export class AdapterListener<Callback extends (...args: any[]) => any> {\n\tpublic name: string;\n\tpublic callback: (...args: any[]) => any;\n\tpublic registered = false;\n\tpublic register: any;\n\tpublic unregister: any;\n\n\t/**\n\t * Creates a new AdapterListener instance with the provided configuration.\n\t *\n\t * @param {Object} config - The configuration object for the listener.\n\t * @param {string} config.name - The name of the event listener.\n\t * @param {Function} config.callback - The callback function to be called when the event is triggered.\n\t * @param {Function} config.unregister - The function to unregister the event listeners.\n\t * @param {Function} config.register - The function to register the event listeners.\n\t */\n\tconstructor({\n\t\tname,\n\t\tcallback,\n\t\tunregister,\n\t\tregister,\n\t}: {\n\t\tname: string;\n\t\tcallback: Callback;\n\t\tunregister: (callbacks: Callback) => void;\n\t\tregister: (callback: Callback) => void;\n\t}) {\n\t\tthis.name = name;\n\n\t\t// Function to register the event listeners\n\t\tthis.register = () => {\n\t\t\tif (!this.registered) {\n\t\t\t\tthis.registered = true;\n\t\t\t\tregister(callback);\n\t\t\t}\n\t\t};\n\n\t\t// Function to unregister the event listeners\n\t\tthis.unregister = () => {\n\t\t\tif (this.register) {\n\t\t\t\tthis.registered = false;\n\t\t\t\tunregister(callback);\n\t\t\t}\n\t\t};\n\n\t\tthis.callback = callback;\n\t}\n}\n","import {\n\tProject,\n\tUnproject,\n\tTerraDrawCallbacks,\n\tTerraDrawChanges,\n\tTerraDrawMouseEvent,\n\tSetCursor,\n\tTerraDrawStylingFunction,\n\tGetLngLatFromEvent,\n\tTerraDrawAdapter,\n} from \"../common\";\nimport { limitPrecision } from \"../geometry/limit-decimal-precision\";\nimport { cartesianDistance } from \"../geometry/measure/pixel-distance\";\nimport { AdapterListener } from \"./adapter-listener\";\n\ntype BasePointerListener = (event: PointerEvent) => void;\ntype BaseKeyboardListener = (event: KeyboardEvent) => void;\ntype BaseMouseListener = (event: MouseEvent) => void;\n\nexport type BaseAdapterConfig = {\n\tcoordinatePrecision?: number;\n\tminPixelDragDistanceDrawing?: number;\n\tminPixelDragDistance?: number;\n\tminPixelDragDistanceSelecting?: number;\n};\n\nexport abstract class TerraDrawBaseAdapter implements TerraDrawAdapter {\n\tconstructor(config: BaseAdapterConfig) {\n\t\tthis._minPixelDragDistance =\n\t\t\ttypeof config.minPixelDragDistance === \"number\"\n\t\t\t\t? config.minPixelDragDistance\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceSelecting =\n\t\t\ttypeof config.minPixelDragDistanceSelecting === \"number\"\n\t\t\t\t? config.minPixelDragDistanceSelecting\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceDrawing =\n\t\t\ttypeof config.minPixelDragDistanceDrawing === \"number\"\n\t\t\t\t? config.minPixelDragDistanceDrawing\n\t\t\t\t: 8;\n\n\t\tthis._coordinatePrecision =\n\t\t\ttypeof config.coordinatePrecision === \"number\"\n\t\t\t\t? config.coordinatePrecision\n\t\t\t\t: 9;\n\t}\n\n\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): 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};\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\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\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\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\t\tthis.clear();\n\t}\n\n\tpublic abstract clear(): void;\n\n\tpublic abstract project(...args: Parameters<Project>): ReturnType<Project>;\n\n\tpublic abstract unproject(\n\t\t...args: Parameters<Unproject>\n\t): ReturnType<Unproject>;\n\n\tpublic abstract setCursor(\n\t\t...args: Parameters<SetCursor>\n\t): ReturnType<SetCursor>;\n\n\tpublic abstract getLngLatFromEvent(\n\t\t...event: Parameters<GetLngLatFromEvent>\n\t): ReturnType<GetLngLatFromEvent>;\n\n\tpublic abstract setDraggability(enabled: boolean): void;\n\n\tpublic abstract setDoubleClickToZoom(enabled: boolean): void;\n\n\tpublic abstract render(\n\t\tchanges: TerraDrawChanges,\n\t\tstyling: TerraDrawStylingFunction,\n\t): void;\n}\n","import {\n\tValidationReasonModeMismatch,\n\tValidationReasonFeatureNotPolygon,\n} from \"./validations/common-validations\";\nimport { ValidationReasonFeatureLessThanMinSize } from \"./validations/min-size.validation\";\nimport {\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n} from \"./validations/not-self-intersecting.validation\";\nimport {\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n} from \"./validations/point.validation\";\nimport {\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n} from \"./validations/polygon.validation\";\n\nexport const ValidationReasons = {\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n\tValidationReasonFeatureNotPolygon,\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n\tValidationReasonFeatureLessThanMinSize,\n\tValidationReasonModeMismatch,\n};\n","/**\n * @module terra-draw\n */\nimport {\n\tTerraDrawAdapter,\n\tTerraDrawAdapterStyling,\n\tGetLngLatFromEvent,\n\tProject,\n\tSetCursor,\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tUnproject,\n\tHexColor,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawMouseEvent,\n\tSELECT_PROPERTIES,\n\tOnFinishContext,\n} from \"./common\";\nimport {\n\tCustomStyling,\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n\tTerraDrawBaseSelectMode,\n} from \"./modes/base.mode\";\nimport { TerraDrawCircleMode } from \"./modes/circle/circle.mode\";\nimport { TerraDrawFreehandMode } from \"./modes/freehand/freehand.mode\";\nimport { TerraDrawLineStringMode } from \"./modes/linestring/linestring.mode\";\nimport { TerraDrawPointMode } from \"./modes/point/point.mode\";\nimport { TerraDrawPolygonMode } from \"./modes/polygon/polygon.mode\";\nimport { TerraDrawRectangleMode } from \"./modes/rectangle/rectangle.mode\";\nimport { TerraDrawRenderMode } from \"./modes/render/render.mode\";\nimport { TerraDrawSelectMode } from \"./modes/select/select.mode\";\nimport { TerraDrawStaticMode } from \"./modes/static/static.mode\";\nimport {\n\tBBoxPolygon,\n\tFeatureId,\n\tGeoJSONStore,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tIdStrategy,\n\tStoreChangeHandler,\n\tStoreValidation,\n} from \"./store/store\";\nimport { BehaviorConfig } from \"./modes/base.behavior\";\nimport { cartesianDistance } from \"./geometry/measure/pixel-distance\";\nimport { pixelDistanceToLine } from \"./geometry/measure/pixel-distance-to-line\";\nimport { Position } from \"geojson\";\nimport { pointInPolygon } from \"./geometry/boolean/point-in-polygon\";\nimport { createBBoxFromPoint } from \"./geometry/shape/create-bbox\";\nimport { ValidateMinAreaSquareMeters } from \"./validations/min-size.validation\";\nimport { ValidateMaxAreaSquareMeters } from \"./validations/max-size.validation\";\nimport { ValidateNotSelfIntersecting } from \"./validations/not-self-intersecting.validation\";\nimport { TerraDrawAngledRectangleMode } from \"./modes/angled-rectangle/angled-rectangle.mode\";\nimport { TerraDrawSectorMode } from \"./modes/sector/sector.mode\";\nimport { TerraDrawSensorMode } from \"./modes/sensor/sensor.mode\";\nimport * as TerraDrawExtend from \"./extend\";\nimport { hasModeProperty } from \"./store/store-feature-validation\";\nimport { ValidationReasons } from \"./validation-reasons\";\n\n// Helper type to determine the instance type of a class\ntype InstanceType<T extends new (...args: any[]) => any> = T extends new (\n\t...args: any[]\n) => infer R\n\t? R\n\t: never;\n\ntype FinishListener = (id: FeatureId, context: OnFinishContext) => void;\ntype ChangeListener = (ids: FeatureId[], type: string) => void;\ntype SelectListener = (id: FeatureId) => void;\ntype DeselectListener = () => void;\n\ninterface TerraDrawEventListeners {\n\tready: () => void;\n\tfinish: FinishListener;\n\tchange: ChangeListener;\n\tselect: SelectListener;\n\tdeselect: DeselectListener;\n}\n\ntype TerraDrawEvents = keyof TerraDrawEventListeners;\n\nclass TerraDraw {\n\tprivate _modes: {\n\t\t[mode: string]: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\t};\n\tprivate _mode: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\tprivate _adapter: TerraDrawAdapter;\n\tprivate _enabled = false;\n\tprivate _store: GeoJSONStore;\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<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 = (ids, event) => {\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);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged(ids);\n\n\t\t\tif (event === \"create\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: changed,\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: [],\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"update\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"delete\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: ids, unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"styling\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onSelect = (selectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.select.forEach((listener) => {\n\t\t\t\tlistener(selectedId);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([selectedId]);\n\n\t\t\tthis._adapter.render(\n\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: changed },\n\t\t\t\tthis.getModeStyles(),\n\t\t\t);\n\t\t};\n\n\t\tconst onDeselect = (deselectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.deselect.forEach((listener) => {\n\t\t\t\tlistener();\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([deselectedId]);\n\n\t\t\t// onDeselect can be called after a delete call which means that\n\t\t\t// you are deselecting a feature that has been deleted. We\n\t\t\t// double check here to ensure that the feature still exists.\n\t\t\tif (changed) {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\t// Register stores and callbacks\n\t\tObject.keys(this._modes).forEach((modeId) => {\n\t\t\tthis._modes[modeId].register({\n\t\t\t\tmode: modeId,\n\t\t\t\tstore: this._store,\n\t\t\t\tsetCursor: this._adapter.setCursor.bind(this._adapter),\n\t\t\t\tproject: this._adapter.project.bind(this._adapter),\n\t\t\t\tunproject: this._adapter.unproject.bind(this._adapter),\n\t\t\t\tsetDoubleClickToZoom: this._adapter.setDoubleClickToZoom.bind(\n\t\t\t\t\tthis._adapter,\n\t\t\t\t),\n\t\t\t\tonChange: onChange,\n\t\t\t\tonSelect: onSelect,\n\t\t\t\tonDeselect: onDeselect,\n\t\t\t\tonFinish: onFinish,\n\t\t\t\tcoordinatePrecision: this._adapter.getCoordinatePrecision(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate checkEnabled() {\n\t\tif (!this._enabled) {\n\t\t\tthrow new Error(\"Terra Draw is not enabled\");\n\t\t}\n\t}\n\n\tprivate getModeStyles() {\n\t\tconst modeStyles: {\n\t\t\t[key: string]: (feature: GeoJSONStoreFeatures) => TerraDrawAdapterStyling;\n\t\t} = {};\n\n\t\tObject.keys(this._modes).forEach((mode) => {\n\t\t\tmodeStyles[mode] = (feature: GeoJSONStoreFeatures) => {\n\t\t\t\t// If the feature is selected, we want to use the select mode styling\n\t\t\t\tif (\n\t\t\t\t\tthis._instanceSelectMode &&\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTED]\n\t\t\t\t) {\n\t\t\t\t\treturn this._modes[this._instanceSelectMode].styleFeature.bind(\n\t\t\t\t\t\tthis._modes[this._instanceSelectMode],\n\t\t\t\t\t)(feature);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise use regular styling\n\t\t\t\treturn this._modes[mode].styleFeature.bind(this._modes[mode])(feature);\n\t\t\t};\n\t\t});\n\t\treturn modeStyles;\n\t}\n\n\tprivate featuresAtLocation(\n\t\t{\n\t\t\tlng,\n\t\t\tlat,\n\t\t}: {\n\t\t\tlng: number;\n\t\t\tlat: number;\n\t\t},\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst pointerDistance =\n\t\t\toptions && options.pointerDistance !== undefined\n\t\t\t\t? options.pointerDistance\n\t\t\t\t: 30; // default is 30px\n\n\t\tconst ignoreSelectFeatures =\n\t\t\toptions && options.ignoreSelectFeatures !== undefined\n\t\t\t\t? options.ignoreSelectFeatures\n\t\t\t\t: true;\n\n\t\tconst unproject = this._adapter.unproject.bind(this._adapter);\n\t\tconst project = this._adapter.project.bind(this._adapter);\n\n\t\tconst inputPoint = project(lng, lat);\n\n\t\tconst bbox = createBBoxFromPoint({\n\t\t\tunproject,\n\t\t\tpoint: inputPoint,\n\t\t\tpointerDistance,\n\t\t});\n\n\t\tconst features = this._store.search(bbox as BBoxPolygon);\n\n\t\t// TODO: This is designed to work in a similar way as FeatureAtPointerEvent\n\t\t// perhaps at some point we could figure out how to unify them\n\t\treturn features.filter((feature) => {\n\t\t\tif (\n\t\t\t\tignoreSelectFeatures &&\n\t\t\t\t(feature.properties[SELECT_PROPERTIES.MID_POINT] ||\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTION_POINT])\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (feature.geometry.type === \"Point\") {\n\t\t\t\tconst pointCoordinates = feature.geometry.coordinates;\n\t\t\t\tconst pointXY = project(pointCoordinates[0], pointCoordinates[1]);\n\t\t\t\tconst distance = cartesianDistance(inputPoint, pointXY);\n\t\t\t\treturn distance < pointerDistance;\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tconst coordinates: Position[] = feature.geometry.coordinates;\n\n\t\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\t\tconst coord = coordinates[i];\n\t\t\t\t\tconst nextCoord = coordinates[i + 1];\n\t\t\t\t\tconst distanceToLine = pixelDistanceToLine(\n\t\t\t\t\t\tinputPoint,\n\t\t\t\t\t\tproject(coord[0], coord[1]),\n\t\t\t\t\t\tproject(nextCoord[0], nextCoord[1]),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (distanceToLine < pointerDistance) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tconst lngLatInsidePolygon = pointInPolygon(\n\t\t\t\t\t[lng, lat],\n\t\t\t\t\tfeature.geometry.coordinates,\n\t\t\t\t);\n\n\t\t\t\tif (lngLatInsidePolygon) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate getSelectMode() {\n\t\tthis.checkEnabled();\n\n\t\tif (!this._instanceSelectMode) {\n\t\t\tthrow new Error(\"No select mode defined in instance\");\n\t\t}\n\n\t\tconst currentMode = this.getMode();\n\n\t\t// If we're not already in the select mode, we switch to it\n\t\tif (currentMode !== this._instanceSelectMode) {\n\t\t\tthis.setMode(this._instanceSelectMode);\n\t\t}\n\n\t\tconst selectMode = this._modes[\n\t\t\tthis._instanceSelectMode\n\t\t] as TerraDrawBaseSelectMode<any>;\n\n\t\treturn selectMode;\n\t}\n\n\t/**\n\t * @deprecated This method is scheduled for removal in the next major version. Instead use the 'updateModeOptions' method passing the\n\t * styles property in the options object, and this will dynamically update the styles for the mode.\n\t *\n\t * Allows the setting of a style for a given mode\n\t *\n\t * @param mode - The mode you wish to set a style for\n\t * @param styles - The styles you wish to set for the mode - this is\n\t * the same as the initialisation style schema\n\t */\n\tsetModeStyles<Styling extends Record<string, number | HexColor>>(\n\t\tmode: string,\n\t\tstyles: Styling,\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\t// TODO: Not sure why this fails TypeScript with TerraDrawBaseSelectMode?\n\t\t(this._modes[mode] as TerraDrawBaseDrawMode<any>).styles = styles;\n\t}\n\n\t/**\n\t * Allow updating of the current options passed to the mode dynamically\n\t * after the mode has been started. You can also use this method to update styles\n\t * as these are passed from the options object.\n\t * @param mode - the mode name you wish to update (the mode name is the public 'mode' property of the mode class)\n\t * @param options - the options object - this allows _partial_ updating of the modes options (i.e. you do not need to pass the whole options object)\n\t */\n\tupdateModeOptions<Mode extends { new (...args: any[]): any }>(\n\t\tmode: InstanceType<Mode>[\"mode\"],\n\t\toptions: ConstructorParameters<Mode>[0],\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\tthis._modes[mode].updateOptions(\n\t\t\toptions as TerraDrawExtend.BaseModeOptions<any>,\n\t\t);\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of all given features\n\t *\n\t * @returns An array of all given Feature Geometries in the instances store\n\t */\n\tgetSnapshot() {\n\t\t// This is a read only method so we do not need to check if enabled\n\t\treturn this._store.copyAll();\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of a given feature by id\n\t *\n\t * @returns A copy of the feature geometry in the instances store\n\t */\n\tgetSnapshotFeature(id: FeatureId) {\n\t\tif (!this._store.has(id)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._store.copy(id);\n\t}\n\n\t/**\n\t * Removes all data from the current store and removes any rendered layers\n\t * via the registering the adapter.\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 * 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\t\tthis._store.delete(ids);\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 selectMdode = this.getSelectMode();\n\t\tselectMdode.selectFeature(id);\n\t}\n\n\t/**\n\t * Provides the ability to programmatically deselect a feature using the instances provided select mode.\n\t * If not select mode is provided in the instance, an error will be thrown. If the instance is not currently\n\t * in the select mode, it will switch to it.\n\t * @param id - the id of the feature to deselect\n\t */\n\tdeselectFeature(id: FeatureId) {\n\t\tconst selectMode = this.getSelectMode();\n\t\tselectMode.deselectFeature(id);\n\t}\n\n\t/**\n\t * Returns the next feature id from the store - defaults to UUID4 unless you have\n\t * set a custom idStrategy. This method can be useful if you are needing creating features\n\t * outside of the Terra Draw instance but want to add them in to the store.\n\t * @returns a id, either number of string based on whatever the configured idStrategy is\n\t *\n\t */\n\tgetFeatureId(): FeatureId {\n\t\treturn this._store.getId();\n\t}\n\n\t/**\n\t * Returns true or false depending on if the Terra Draw instance has a feature with a given id\n\t * @returns a boolean determining if the instance has a feature with the given id\n\t */\n\thasFeature(id: FeatureId): boolean {\n\t\treturn this._store.has(id);\n\t}\n\n\t/**\n\t * A method for adding features to the store. This method will validate the features\n\t * returning an array of validation results. Features must match one of the modes enabled\n\t * in the instance.\n\t * @param features - an array of GeoJSON features\n\t * @returns an array of validation results\n\t */\n\taddFeatures(features: GeoJSONStoreFeatures[]): StoreValidation[] {\n\t\tthis.checkEnabled();\n\n\t\tif (features.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this._store.load(features, (feature) => {\n\t\t\t// If the feature has a mode property, we use that to validate the feature\n\t\t\tif (hasModeProperty(feature)) {\n\t\t\t\tconst featureMode = feature.properties.mode;\n\t\t\t\tconst modeToAddTo = this._modes[featureMode];\n\n\t\t\t\t// if the mode does not exist, we return false\n\t\t\t\tif (!modeToAddTo) {\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: false,\n\t\t\t\t\t\treason: `${featureMode} mode is not in the list of instantiated modes`,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// use the inbuilt validation of the mode\n\t\t\t\tconst validation = modeToAddTo.validateFeature.bind(modeToAddTo);\n\t\t\t\tconst validationResult = validation(feature);\n\t\t\t\tconst valid = validationResult.valid;\n\t\t\t\tconst reason = validationResult.reason\n\t\t\t\t\t? validationResult.reason\n\t\t\t\t\t: !validationResult.valid\n\t\t\t\t\t\t? \"Feature is invalid\"\n\t\t\t\t\t\t: undefined;\n\t\t\t\treturn {\n\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\tvalid,\n\t\t\t\t\treason,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// If the feature does not have a mode property, we return false\n\t\t\treturn {\n\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\tvalid: false,\n\t\t\t\treason: \"Mode property does not exist\",\n\t\t\t};\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\tthis._enabled = true;\n\t\tthis._adapter.register({\n\t\t\tonReady: () => {\n\t\t\t\tthis._eventListeners.ready.forEach((listener) => {\n\t\t\t\t\tlistener();\n\t\t\t\t});\n\t\t\t},\n\t\t\tgetState: () => {\n\t\t\t\treturn this._mode.state;\n\t\t\t},\n\t\t\tonClick: (event) => {\n\t\t\t\tthis._mode.onClick(event);\n\t\t\t},\n\t\t\tonMouseMove: (event) => {\n\t\t\t\tthis._mode.onMouseMove(event);\n\t\t\t},\n\t\t\tonKeyDown: (event) => {\n\t\t\t\tthis._mode.onKeyDown(event);\n\t\t\t},\n\t\t\tonKeyUp: (event) => {\n\t\t\t\tthis._mode.onKeyUp(event);\n\t\t\t},\n\t\t\tonDragStart: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragStart(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDrag: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDrag(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDragEnd: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragEnd(event, setMapDraggability);\n\t\t\t},\n\t\t\tonClear: () => {\n\t\t\t\t// Ensure that the mode resets its state\n\t\t\t\t// as it may be storing feature ids internally in it's instance\n\t\t\t\tthis._mode.cleanUp();\n\n\t\t\t\t// Remove all features from the store\n\t\t\t\tthis._store.clear();\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Gets the features at a given longitude and latitude.\n\t * Will return point and linestrings that are a given pixel distance\n\t * away from the lng/lat and any polygons which contain it.\n\t */\n\tgetFeaturesAtLngLat(\n\t\tlngLat: { lng: number; lat: number },\n\t\toptions?: { pointerDistance: number; ignoreSelectFeatures: boolean },\n\t) {\n\t\tconst { lng, lat } = lngLat;\n\n\t\treturn this.featuresAtLocation(\n\t\t\t{\n\t\t\t\tlng,\n\t\t\t\tlat,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Takes a given pointer event and will return point and linestrings that are\n\t * a given pixel distance away from the longitude/latitude, and any polygons which contain it.\n\t */\n\tgetFeaturesAtPointerEvent(\n\t\tevent: PointerEvent | MouseEvent,\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst getLngLatFromEvent = this._adapter.getLngLatFromEvent.bind(\n\t\t\tthis._adapter,\n\t\t);\n\n\t\tconst lngLat = getLngLatFromEvent(event);\n\n\t\t// If the pointer event is outside the container or the underlying library is\n\t\t// not ready we can get null as a returned value\n\t\tif (lngLat === null) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this.featuresAtLocation(lngLat, options);\n\t}\n\n\t/**\n\t * A method for stopping Terra Draw. Will clear the store, deregister the adapter and\n\t * remove any rendered layers in the process.\n\t */\n\tstop() {\n\t\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\n\t// Modes\n\tTerraDrawSelectMode,\n\tTerraDrawPointMode,\n\tTerraDrawLineStringMode,\n\tTerraDrawPolygonMode,\n\tTerraDrawCircleMode,\n\tTerraDrawFreehandMode,\n\tTerraDrawRenderMode,\n\tTerraDrawRectangleMode,\n\tTerraDrawAngledRectangleMode,\n\tTerraDrawSectorMode,\n\tTerraDrawSensorMode,\n\n\t// Types that are required for 3rd party developers to extend\n\tTerraDrawExtend,\n\n\t// TerraDrawBaseMode\n\tBehaviorConfig,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tHexColor,\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\n\t// TerraDrawBaseAdapter\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tProject,\n\tUnproject,\n\tSetCursor,\n\tGetLngLatFromEvent,\n\n\t// Validations\n\tValidateMinAreaSquareMeters,\n\tValidateMaxAreaSquareMeters,\n\tValidateNotSelfIntersecting,\n\tValidationReasons,\n};\n"],"names":["UpdateTypes","SELECT_PROPERTIES","SELECTED","MID_POINT","SELECTION_POINT","COMMON_PROPERTIES","isObject","feature","Boolean","Array","isArray","isValidTimestamp","timestamp","isNaN","Date","valueOf","dateIsValid","ValidationReasonFeatureNotPolygon","ValidationReasonModeMismatch","ModeTypes","TerraDrawBaseDrawMode","state","_state","_","Error","styles","this","_styles","styling","onStyleChange","registerBehaviors","behaviorConfig","constructor","options","willCallUpdateOptionsInParentClass","behaviors","validate","pointerDistance","coordinatePrecision","store","projection","setDoubleClickToZoom","unproject","project","setCursor","type","Drawing","mode","updateOptions","_extends","validation","setDrawing","setStarted","setStopped","register","config","registerOnChange","onChange","onSelect","onDeselect","onFinish","validateFeature","performFeatureValidation","validStoreFeature","isValidId","error","id","geometry","properties","includes","coordinates","valid","reason","isValidStoreFeature","idStrategy","updateType","Provisional","validateModeFeature","modeValidationFn","finishedId","context","deselectedId","selectedId","onKeyDown","event","onKeyUp","onMouseMove","onClick","onDragStart","setMapDraggability","onDrag","onDragEnd","getHexColorStylingValue","value","defaultValue","getStylingValue","getNumericStylingValue","undefined","TerraDrawBaseSelectMode","args","Select","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","length","edge0","ring1","edge1","ifInteresctionAddToOutput","isOutside","frac","start0","end0","start1","end1","intersection","equalArrays","x0","y0","x1","y1","x2","y2","x3","y3","denom","intersect","frac0","frac1","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","super","clickCount","currentCircleId","keyEvents","cursors","startingRadiusKilometers","cursorMovedAfterInitialCursorDown","close","currentGeometry","getGeometryCopy","Finish","action","stop","cleanUp","startingCircle","createdId","create","updateCircle","key","cleanUpId","delete","_unused","styleFeature","polygonFillColor","polygonOutlineColor","polygonOutlineWidth","polygonFillOpacity","pointColor","pointOutlineColor","pointOutlineWidth","pointWidth","lineStringColor","lineStringWidth","zIndex","fillColor","outlineColor","outlineWidth","fillOpacity","baseValidatedFeature","newRadius","updatedCircle","distortion","source","target","geodesicDistance","calculateWebMercatorDistortion","radiusMeters","angle","dx","dy","wx","wy","circleWebMercator","updateGeometry","updateProperty","property","cartesianDistance","ensureRightHandRule","polygon","isFollowingRightHandRule","outerRing","sum","followsRightHandRule","reverse","TerraDrawFreehandMode","startingClick","currentId","closingPointId","minDistance","preventPointsNearClose","autoClose","autoCloseTimeout","hasLeftStartingPoint","preventNewFeature","correctedGeometry","currentLineGeometry","previousIndex","previousLng","previousLat","containerX","containerY","closingLng","closingLat","closingX","closingY","setTimeout","pop","newGeometry","COMMON_PROPERTIES_CLOSING_POINT","cleanUpClosingPointId","getDefaultStyling","closingPointWidth","closingPointColor","closingPointOutlineColor","closingPointOutlineWidth","TerraDrawModeBehavior","createBBoxFromPoint","point","halfDist","map","c","ClickBoundingBoxBehavior","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","normalizeBearing","lineSliceAlong","coords","startDist","stopDist","slice","origCoordsLength","overshot","direction","interpolated","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","v1x","v1y","v1z","v2x","v2y","v2z","dot","acos","min","max","lngLatToVector","vectorToLngLat","nearestPointOnSegment","posA","posB","posC","C","Cx","Cy","Cz","D","E","F","cross","g","h","t","I1","I2","angleAB","angleAI1","angleBI1","angleAI2","angleBI2","I","findNearestPointOnLine","pointA","pointB","lineVector","LineSnappingBehavior","boundingBox","lines","nearest","lngLat","inputCoordinate","closestPoint","closestDistance","lineIndex","startPosition","stopPosition","intersectPosition","intersectDistance","indexOf","webMercatorNearestPointOnLine","nearestPointOnLine","dragStart","dragEnd","TerraDrawLineStringMode","currentCoordinate","snapping","mouseMove","insertCoordinates","lastCommitedCoordinates","snappedPointId","editable","editedFeatureId","editedFeatureCoordinateIndex","editedSnapType","editedInsertIndex","editedPointId","coordinateSnapping","insertPoint","lineSnapping","updateGeometries","Commit","closingPointCoordinate","updatedGeometry","geometries","generateInsertCoordinates","startCoord","endCoord","strategy","segmentDistance","insertedCoordinates","createLine","startingCoord","firstUpdateToLine","updatedCoord","currentCoordinates","pointId","initialLineCoordinates","updateToLine","cursorXY","updatedLineCoordinates","snappedCoordinate","snapCoordinate","COMMON_PROPERTIES_SNAPPING_POINT","onRightClick","coordinateIndex","lineStringFilter","splice","onLeftClick","updatedCoordinate","button","lineSnapped","coordinateSnapped","COMMON_PROPERTIES_EDITED","featureCopy","newLineStringGeometry","getPropertiesCopy","cleanupClosingPointId","isClosingPoint","snappingPointColor","snappingPointWidth","snappingPointOutlineColor","snappingPointOutlineWidth","_this$snapping","_this$snapping2","toCoordinate","toCustom","ValidationReasonFeatureNotPoint","ValidationReasonFeatureInvalidCoordinates","ValidationReasonFeatureInvalidCoordinatePrecision","ValidatePointFeature","TerraDrawPointMode","nearestPointFeature","getNearestPointFeature","isEdited","editedPointWidth","editedPointColor","editedPointOutlineColor","editedPointOutlineWidth","clickedFeature","distanceToFeature","ClosingPointsBehavior","_startEndPoints","ids","concat","selectedCoords","update","updatedCoordinates","opening","closing","distancePrevious","isClosing","isPreviousClosing","TerraDrawPolygonMode","closingPoints","currentPolygonCoordinates","updatePolygonGeometry","epsilon","offset","_this$snapping3","toLine","snapped","getCurrentGeometrySnapshot","polygonFilter","shift","newId","currentPolygonGeometry","updatedPolygon","createPolygon","featureCoordinates","newPolygonGeometry","editedPoint","pointType","styleMap","width","color","closingPoint","snappingPoint","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","geodesicMidpointCoordinate","midpoint","getMidPointCoordinates","featureCoords","midPointCoords","mid","MidPointBehavior","selectionPointBehavior","_midPoints","insert","midPointId","midPoint","midPointFeatureId","midPointSegment","has","getMidPoints","getUpdated","updatedMidPointCoord","SelectionPointBehavior","_selectionPoints","geometryType","selectionPoints","getCoordinatesAsPoints","selectionPoint","selectionPointFeatureId","index","getOneUpdated","pointInPolygon","rings","inside","len","ring","j","len2","k","p1","p","p2","pixelDistanceToLine","linePointOne","linePointTwo","square","dist2","w","distToSegmentSquared","l2","FeatureAtPointerEventBehavior","createClickBoundingBox","find","hasSelection","clickedPoint","clickedLineString","clickedMidPoint","clickedPolygon","clickedPointDistance","clickedLineStringDistance","clickedMidPointDistance","nextCoord","distanceToLine","DragFeatureBehavior","featuresAtCursorEvent","midPoints","draggedFeatureId","dragPosition","startDragging","stopDragging","isDragging","canDrag","drag","cursorCoord","updatedCoords","upToCoord","updatedLng","updatedLat","webMercatorDragPosition","webMercatorCursorCoord","webMercatorCoordinate","updatedX","updatedY","updatedSelectionPoints","updatedMidPoints","DragCoordinateBehavior","draggedCoordinate","getClosestCoordinate","closestCoordinate","isFirstOrLastPolygonCoord","geomCoordinates","getDraggableIndex","allowSelfIntersection","lastCoordIndex","updatedSelectionPoint","centroid","geojson","xSum","ySum","rhumbDistance","DeltaLambda","webMercatorCentroid","webMercatorCoordinates","area","centroidX","centroidY","n","crossProduct","calculatePolygonCentroid","lineString","totalX","totalY","calculateLineStringMidpoint","RotateFeatureBehavior","lastBearing","reset","rotate","mouseCoord","transformRotateWebMercator","angleRad","webMercatorCoords","reduce","acc","rotatedCoordinates","pivot","pointCoords","finalAngle","newCoords","transformRotate","ScaleFeatureBehavior","lastDistance","scale","originWebMercator","selectedWebMercator","factor","scaledCoordinates","transformScaleWebMercator","axis","originalDistance","newCoord","transformScale","DragCoordinateResizeBehavior","minimumScale","boundingBoxMaps","opposite","isValidDragWebMercator","distanceX","distanceY","getSelectedFeatureDataWebMercator","getFeature","getNormalisedCoordinates","getBBoxWebMercator","selectedCoordinate","centerWebMercatorDrag","featureData","webMercatorOrigin","webMercatorSelected","closestBBoxIndex","getIndexesWebMercator","webMercatorCursor","scaleWebMercator","centerFixedWebMercatorDrag","scaleFixedWebMercator","performWebMercatorScale","oppositeFixedWebMercatorDrag","oppositeBboxIndex","oppositeWebMercatorDrag","cursorDistanceX","cursorDistanceY","xScale","yScale","validateScale","validX","MAX_SAFE_INTEGER","validY","originX","originY","west","south","east","north","selectedXY","closestIndex","resizeOption","deselect","pointerOver","insertMidpoint","TerraDrawSelectMode","allowManualDeselection","dragEventThrottle","dragEventCount","selected","flags","validations","featuresAtMouseEvent","dragFeature","dragCoordinate","rotateFeature","scaleFeature","dragCoordinateResizeFeature","selectFeature","select","setSelecting","deselectFeature","updateSelectedFeatures","deleteSelected","clickedSelectionPointProps","clickedFeatureDistance","modeFlags","deletable","midpoints","fromCursor","previouslySelectedId","canScale","every","heldKeys","canRotate","preventDefaultKeyEvent","isRotationKeys","isScaleKeys","preventDefault","draggable","resizable","draggableCoordinateIndex","draggedMidPoint","draggableCoordinateIndexAfterInsert","canSelfIntersect","selfIntersectable","rotateable","scaleable","nearbyMidPoint","nearbySelectionPoint","featureUnderPointer","selectionPointColor","selectionPointOutlineColor","selectionPointWidth","selectionPointOutlineWidth","midPointColor","midPointOutlineColor","midPointWidth","midPointOutlineWidth","selectedPolygonColor","selectedPolygonOutlineWidth","selectedPolygonOutlineColor","selectedPolygonFillOpacity","selectedLineStringColor","selectedLineStringWidth","selectedPointWidth","selectedPointColor","selectedPointOutlineColor","selectedPointOutlineWidth","TerraDrawStaticMode","Static","quickselect","arr","left","right","compare","m","s","sd","swap","tmp","calcBBox","node","toBBox","distBBox","children","destNode","createNode","minX","minY","maxX","maxY","child","extend","leaf","compareNodeMinX","compareNodeMinY","bboxArea","bboxMargin","intersectionArea","contains","intersects","height","multiSelect","stack","ceil","RBush","maxEntries","_maxEntries","_minEntries","data","clear","result","nodesToSearch","childBBox","_all","collides","load","_build","_splitRoot","tmpNode","_insert","item","remove","path","indexes","parent","goingUp","_condense","compareMinX","compareMinY","items","N","M","N2","N1","right2","right3","_chooseSubtree","level","targetNode","minArea","minEnlargement","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","set","longitudes","latitudes","minLat","maxLat","get","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","Object","keys","size","polygonAreaSquareMeters","total","ringArea","FACTOR","PI_OVER_180","coordsLength","ValidationReasonFeatureLessThanMinSize","ValidateMinAreaSquareMeters","minSize","ValidateMaxAreaSquareMeters","maxSize","ValidationReasonFeatureNotPolygonOrLineString","ValidationReasonFeatureSelfIntersects","ValidateNotSelfIntersecting","calculateRelativeAngle","bearingAB","relativeAngle","TerraDrawAngledRectangleMode","firstCoordinate","ACloserThanC","hypotenuse","adjacent","rectangleAngle","lineStart","lineEnd","determineHalfPlane","thirdCoordinateXY","fourthCoordinateXY","thirdCoordinate","fourthCoordinate","isClockwiseWebMercator","secondCoord","thirdCoord","TerraDrawSectorMode","arcPoints","arcCoordOne","arcCoordTwo","webMercatorCenter","webMercatorArcCoordOne","webMercatorArcCoordTwo","clockwise","radius","startBearing","endBearing","normalizedStart","normalizedEnd","deltaBearing","bearingStep","pointOnArc","TerraDrawSensorMode","currentInitialArcId","currentStartingPointId","finishedCurrentStartingPointId","finishedInitialArcId","finishedCurrentId","updateLineStringGeometry","lastCoord","webMercatorCoordOne","webMercatorCoordTwo","innerRadius","radiusCalculationPosition","cursorBearing","normalizedCursor","notInSector","getDeltaBearing","finalArc","unshift","centerPointColor","centerPointWidth","centerPointOutlineColor","centerPointOutlineWidth","AdapterListener","name","callback","unregister","registered","_minPixelDragDistance","_minPixelDragDistanceDrawing","_minPixelDragDistanceSelecting","_lastDrawEvent","_coordinatePrecision","_heldKeys","_listeners","_dragState","_currentModeCallbacks","minPixelDragDistance","minPixelDragDistanceSelecting","minPixelDragDistanceDrawing","getButton","getMapElementXYPosition","mapElement","getMapEventElement","top","getBoundingClientRect","clientX","clientY","getDrawEventFromEvent","latLng","getLngLatFromEvent","callbacks","getAdapterListeners","listener","getCoordinatePrecision","isPrimary","drawEvent","addEventListener","removeEventListener","lastEventXY","currentEventXY","modeState","getState","pixelDistanceToCheck","isMicroDrag","enabled","setDraggability","bind","ValidationReasons","TerraDraw","_modes","_mode","_adapter","_enabled","_store","_eventListeners","_instanceSelectMode","adapter","duplicateModeTracker","modesMap","modes","modeMap","currentMode","modeKeys","static","ready","getChanged","changed","unchanged","render","created","deletedIds","updated","getModeStyles","modeId","checkEnabled","modeStyles","featuresAtLocation","ignoreSelectFeatures","inputPoint","pointCoordinates","pointXY","getSelectMode","getMode","setMode","setModeStyles","updateModeOptions","getSnapshot","getSnapshotFeature","removeFeatures","getFeatureId","hasFeature","addFeatures","hasModeProperty","featureMode","modeToAddTo","onReady","onClear","getFeaturesAtLngLat","getFeaturesAtPointerEvent","on","listeners","off"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"terra-draw.modern.js","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/geometry/web-mercator-point-on-line.ts","../src/modes/line-snapping.behavior.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/measure/rhumb-distance.ts","../src/geometry/web-mercator-centroid.ts","../src/modes/select/behaviors/rotate-feature.behavior.ts","../src/geometry/transform/rotate.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/max-size.validation.ts","../src/validations/not-self-intersecting.validation.ts","../src/geometry/calculate-relative-angle.ts","../src/modes/angled-rectangle/angled-rectangle.mode.ts","../src/geometry/determine-halfplane.ts","../src/geometry/clockwise.ts","../src/modes/sector/sector.mode.ts","../src/modes/sensor/sensor.mode.ts","../src/common/adapter-listener.ts","../src/common/base.adapter.ts","../src/validation-reasons.ts","../src/terra-draw.ts"],"sourcesContent":["import {\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}\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 interface TerraDrawModeRegisterConfig {\n\tmode: string;\n\tstore: GeoJSONStore;\n\tsetDoubleClickToZoom: (enabled: boolean) => void;\n\tsetCursor: SetCursor;\n\tonChange: StoreChangeHandler;\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 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: \"selectionPoint\",\n} as const;\n\nexport const COMMON_PROPERTIES = {\n\tEDITED: \"edited\",\n\tCLOSING_POINT: \"closingPoint\",\n\tSNAPPING_POINT: \"snappingPoint\",\n\tCOORDINATE_POINT: \"coordinatePoint\",\n\tCOORDINATE_POINT_IDS: \"coordinatePointIds\",\n};\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\tHexColor,\n\tOnFinishContext,\n\tProjection,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawModeRegisterConfig,\n\tTerraDrawModeState,\n\tTerraDrawMouseEvent,\n\tUpdateTypes,\n\tValidation,\n} from \"../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStore,\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 type BaseModeOptions<Styling extends CustomStyling> = {\n\tstyles?: Partial<Styling>;\n\tpointerDistance?: number;\n\tvalidation?: Validation;\n\tprojection?: Projection;\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 behaviors: TerraDrawModeBehavior[] = [];\n\tprotected validate: Validation | undefined;\n\tprotected pointerDistance: number = 40;\n\tprotected coordinatePrecision!: number;\n\tprotected onStyleChange!: StoreChangeHandler;\n\tprotected store!: GeoJSONStore;\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\t}\n\n\ttype = ModeTypes.Drawing;\n\tmode = \"base\";\n\n\tprotected setDrawing() {\n\t\tif (this._state === \"started\") {\n\t\t\tthis._state = \"drawing\";\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be unregistered or stopped to start\");\n\t\t}\n\t}\n\n\tprotected setStarted() {\n\t\tif (\n\t\t\tthis._state === \"stopped\" ||\n\t\t\tthis._state === \"registered\" ||\n\t\t\tthis._state === \"drawing\" ||\n\t\t\tthis._state === \"selecting\"\n\t\t) {\n\t\t\tthis._state = \"started\";\n\t\t\tthis.setDoubleClickToZoom(false);\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be unregistered or stopped to start\");\n\t\t}\n\t}\n\n\tprotected setStopped() {\n\t\tif (this._state === \"started\") {\n\t\t\tthis._state = \"stopped\";\n\t\t\tthis.setDoubleClickToZoom(true);\n\t\t} else {\n\t\t\tthrow new Error(\"Mode must be started to be stopped\");\n\t\t}\n\t}\n\n\tregister(config: TerraDrawModeRegisterConfig) {\n\t\tif (this._state === \"unregistered\") {\n\t\t\tthis._state = \"registered\";\n\t\t\tthis.store = config.store;\n\t\t\tthis.store.registerOnChange(config.onChange);\n\t\t\tthis.setDoubleClickToZoom = config.setDoubleClickToZoom;\n\t\t\tthis.project = config.project;\n\t\t\tthis.unproject = config.unproject;\n\t\t\tthis.onSelect = config.onSelect;\n\t\t\tthis.onDeselect = config.onDeselect;\n\t\t\tthis.setCursor = config.setCursor;\n\t\t\tthis.onStyleChange = config.onChange;\n\t\t\tthis.onFinish = config.onFinish;\n\t\t\tthis.coordinatePrecision = config.coordinatePrecision;\n\n\t\t\tthis.registerBehaviors({\n\t\t\t\tmode: config.mode,\n\t\t\t\tstore: this.store,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t\tpointerDistance: this.pointerDistance,\n\t\t\t\tcoordinatePrecision: config.coordinatePrecision,\n\t\t\t\tprojection: this.projection,\n\t\t\t});\n\t\t} else {\n\t\t\tthrow new Error(\"Can not register unless mode is unregistered\");\n\t\t}\n\t}\n\n\tvalidateFeature(feature: unknown): ReturnType<Validation> {\n\t\treturn this.performFeatureValidation(feature);\n\t}\n\n\tafterFeatureAdded(feature: GeoJSONStoreFeatures) {}\n\n\tprivate performFeatureValidation(feature: unknown): ReturnType<Validation> {\n\t\tif (this._state === \"unregistered\") {\n\t\t\tthrow new Error(\"Mode must be registered\");\n\t\t}\n\n\t\tconst validStoreFeature = isValidStoreFeature(\n\t\t\tfeature,\n\t\t\tthis.store.idStrategy.isValidId,\n\t\t);\n\n\t\t// We also want tp validate based on any specific valdiations passed in\n\t\tif (this.validate) {\n\t\t\tconst validation = this.validate(feature as GeoJSONStoreFeatures, {\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t// validatedFeature: feature as GeoJSONStoreFeatures,\n\t\t\t\tvalid: validStoreFeature.valid && validation.valid,\n\t\t\t\treason: validation.reason,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t// validatedFeature: feature as GeoJSONStoreFeatures,\n\t\t\tvalid: validStoreFeature.valid,\n\t\t\treason: validStoreFeature.reason,\n\t\t};\n\t}\n\n\tprotected validateModeFeature(\n\t\tfeature: unknown,\n\t\tmodeValidationFn: (feature: GeoJSONStoreFeatures) => ReturnType<Validation>,\n\t): ReturnType<Validation> {\n\t\tconst validation = this.performFeatureValidation(feature);\n\t\tif (validation.valid) {\n\t\t\tconst validatedFeature = feature as GeoJSONStoreFeatures;\n\t\t\tconst matches = validatedFeature.properties.mode === this.mode;\n\t\t\tif (!matches) {\n\t\t\t\treturn {\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: ValidationReasonModeMismatch,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst modeValidation = modeValidationFn(validatedFeature);\n\t\t\treturn modeValidation;\n\t\t}\n\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: validation.reason,\n\t\t};\n\t}\n\n\tabstract start(): void;\n\tabstract stop(): void;\n\tabstract cleanUp(): void;\n\tabstract styleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling;\n\n\tonFinish(finishedId: FeatureId, context: OnFinishContext) {}\n\tonDeselect(deselectedId: FeatureId) {}\n\tonSelect(selectedId: FeatureId) {}\n\tonKeyDown(event: TerraDrawKeyboardEvent) {}\n\tonKeyUp(event: TerraDrawKeyboardEvent) {}\n\tonMouseMove(event: TerraDrawMouseEvent) {}\n\tonClick(event: TerraDrawMouseEvent) {}\n\tonDragStart(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\tonDragEnd(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {}\n\n\tprotected getHexColorStylingValue(\n\t\tvalue: HexColor | ((feature: GeoJSONStoreFeatures) => HexColor) | undefined,\n\t\tdefaultValue: HexColor,\n\t\tfeature: GeoJSONStoreFeatures,\n\t): HexColor {\n\t\treturn this.getStylingValue(value, defaultValue, feature);\n\t}\n\n\tprotected getNumericStylingValue(\n\t\tvalue: number | ((feature: GeoJSONStoreFeatures) => number) | undefined,\n\t\tdefaultValue: number,\n\t\tfeature: GeoJSONStoreFeatures,\n\t): number {\n\t\treturn this.getStylingValue(value, defaultValue, feature);\n\t}\n\n\tprivate getStylingValue<T extends string | number>(\n\t\tvalue: T | ((feature: GeoJSONStoreFeatures) => T) | undefined,\n\t\tdefaultValue: T,\n\t\tfeature: GeoJSONStoreFeatures,\n\t) {\n\t\tif (value === undefined) {\n\t\t\treturn defaultValue;\n\t\t} else if (typeof value === \"function\") {\n\t\t\treturn value(feature);\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t}\n}\n\nexport abstract class TerraDrawBaseSelectMode<\n\tStyling extends CustomStyling,\n> extends TerraDrawBaseDrawMode<Styling> {\n\tpublic type = ModeTypes.Select;\n\n\tpublic abstract selectFeature(featureId: FeatureId): void;\n\tpublic abstract deselectFeature(featureId: FeatureId): void;\n}\n","import { Position } from \"geojson\";\n\nexport function haversineDistanceKilometers(\n\tpointOne: Position,\n\tpointTwo: Position,\n) {\n\tconst toRadians = (latOrLng: number) => (latOrLng * Math.PI) / 180;\n\n\tconst phiOne = toRadians(pointOne[1]);\n\tconst lambdaOne = toRadians(pointOne[0]);\n\tconst phiTwo = toRadians(pointTwo[1]);\n\tconst lambdaTwo = toRadians(pointTwo[0]);\n\tconst deltaPhi = phiTwo - phiOne;\n\tconst deltalambda = lambdaTwo - lambdaOne;\n\n\tconst a =\n\t\tMath.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +\n\t\tMath.cos(phiOne) *\n\t\t\tMath.cos(phiTwo) *\n\t\t\tMath.sin(deltalambda / 2) *\n\t\t\tMath.sin(deltalambda / 2);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n\tconst radius = 6371e3;\n\tconst distance = radius * c;\n\n\treturn distance / 1000;\n}\n","export const earthRadius = 6371008.8;\n\nexport function degreesToRadians(degrees: number): number {\n\tconst radians = degrees % 360;\n\treturn (radians * Math.PI) / 180;\n}\n\nexport function lengthToRadians(distance: number): number {\n\tconst factor = earthRadius / 1000;\n\treturn distance / factor;\n}\n\nexport function radiansToDegrees(radians: number): number {\n\tconst degrees = radians % (2 * Math.PI);\n\treturn (degrees * 180) / Math.PI;\n}\n","export function limitPrecision(num: number, decimalLimit = 9) {\n\tconst decimals = Math.pow(10, decimalLimit);\n\treturn Math.round(num * decimals) / decimals;\n}\n","import { CartesianPoint } from \"../../common\";\n\nconst RADIANS_TO_DEGREES = 57.29577951308232 as const; // 180 / Math.PI\nconst DEGREES_TO_RADIANS = 0.017453292519943295 as const; // Math.PI / 180\nconst R = 6378137 as const;\n\n/**\n * Convert longitude and latitude to web mercator x and y\n * @param lng\n * @param lat\n * @returns - web mercator x and y\n */\nexport const lngLatToWebMercatorXY = (\n\tlng: number,\n\tlat: number,\n): CartesianPoint => ({\n\tx: lng === 0 ? 0 : lng * DEGREES_TO_RADIANS * R,\n\ty:\n\t\tlat === 0\n\t\t\t? 0\n\t\t\t: Math.log(Math.tan(Math.PI / 4 + (lat * DEGREES_TO_RADIANS) / 2)) * R,\n});\n\n/**\n * Convert web mercator x and y to longitude and latitude\n * @param x - web mercator x\n * @param y - web mercator y\n * @returns - longitude and latitude\n */\nexport const webMercatorXYToLngLat = (\n\tx: number,\n\ty: number,\n): { lng: number; lat: number } => ({\n\tlng: x === 0 ? 0 : RADIANS_TO_DEGREES * (x / R),\n\tlat:\n\t\ty === 0\n\t\t\t? 0\n\t\t\t: (2 * Math.atan(Math.exp(y / R)) - Math.PI / 2) * RADIANS_TO_DEGREES,\n});\n","import { Feature, Polygon, Position } from \"geojson\";\nimport {\n\tdegreesToRadians,\n\tlengthToRadians,\n\tradiansToDegrees,\n} from \"../helpers\";\nimport { limitPrecision } from \"../limit-decimal-precision\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\n\n// Adapted from the @turf/circle module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-circle/index.ts\n\nfunction destination(\n\torigin: Position,\n\tdistance: number,\n\tbearing: number,\n): Position {\n\tconst longitude1 = degreesToRadians(origin[0]);\n\tconst latitude1 = degreesToRadians(origin[1]);\n\tconst bearingRad = degreesToRadians(bearing);\n\tconst radians = lengthToRadians(distance);\n\n\t// Main\n\tconst latitude2 = Math.asin(\n\t\tMath.sin(latitude1) * Math.cos(radians) +\n\t\t\tMath.cos(latitude1) * Math.sin(radians) * Math.cos(bearingRad),\n\t);\n\tconst longitude2 =\n\t\tlongitude1 +\n\t\tMath.atan2(\n\t\t\tMath.sin(bearingRad) * Math.sin(radians) * Math.cos(latitude1),\n\t\t\tMath.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2),\n\t\t);\n\tconst lng = radiansToDegrees(longitude2);\n\tconst lat = radiansToDegrees(latitude2);\n\n\treturn [lng, lat];\n}\n\nexport function circle(options: {\n\tcenter: Position;\n\tradiusKilometers: number;\n\tcoordinatePrecision: number;\n\tsteps?: number;\n}): Feature<Polygon> {\n\tconst { center, radiusKilometers, coordinatePrecision } = options;\n\tconst steps = options.steps ? options.steps : 64;\n\n\tconst coordinates: Position[] = [];\n\tfor (let i = 0; i < steps; i++) {\n\t\tconst circleCoordinate = destination(\n\t\t\tcenter,\n\t\t\tradiusKilometers,\n\t\t\t(i * -360) / steps,\n\t\t);\n\n\t\tcoordinates.push([\n\t\t\tlimitPrecision(circleCoordinate[0], coordinatePrecision),\n\t\t\tlimitPrecision(circleCoordinate[1], coordinatePrecision),\n\t\t]);\n\t}\n\tcoordinates.push(coordinates[0]);\n\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: { type: \"Polygon\", coordinates: [coordinates] },\n\t\tproperties: {},\n\t};\n}\n\nexport function circleWebMercator(options: {\n\tcenter: Position;\n\tradiusKilometers: number;\n\tcoordinatePrecision: number;\n\tsteps?: number;\n}): GeoJSON.Feature<GeoJSON.Polygon> {\n\tconst { center, radiusKilometers, coordinatePrecision } = options;\n\tconst steps = options.steps ? options.steps : 64;\n\n\tconst radiusMeters = radiusKilometers * 1000;\n\n\tconst [lng, lat] = center;\n\tconst { x, y } = lngLatToWebMercatorXY(lng, lat);\n\n\tconst coordinates: Position[] = [];\n\tfor (let i = 0; i < steps; i++) {\n\t\tconst angle = (((i * 360) / steps) * Math.PI) / 180;\n\t\tconst dx = radiusMeters * Math.cos(angle);\n\t\tconst dy = radiusMeters * Math.sin(angle);\n\t\tconst [wx, wy] = [x + dx, y + dy];\n\t\tconst { lng, lat } = webMercatorXYToLngLat(wx, wy);\n\t\tcoordinates.push([\n\t\t\tlimitPrecision(lng, coordinatePrecision),\n\t\t\tlimitPrecision(lat, coordinatePrecision),\n\t\t]);\n\t}\n\n\t// Close the circle by adding the first point at the end\n\tcoordinates.push(coordinates[0]);\n\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: { type: \"Polygon\", coordinates: [coordinates] },\n\t\tproperties: {},\n\t};\n}\n","// Based on - https://github.com/mclaeysb/geojson-polygon-self-intersections\n// MIT License - Copyright (c) 2016 Manuel Claeys Bouuaert\n\nimport { Feature, LineString, Polygon, Position } from \"geojson\";\n// import * as rbush from \"rbush\";\n\ntype SelfIntersectsOptions = {\n\tepsilon: number;\n\t// reportVertexOnVertex: boolean;\n\t// reportVertexOnEdge: boolean;\n};\n\nexport function selfIntersects(\n\tfeature: Feature<Polygon> | Feature<LineString>,\n): boolean {\n\tconst options: SelfIntersectsOptions = {\n\t\tepsilon: 0,\n\t\t// reportVertexOnVertex: false,\n\t\t// reportVertexOnEdge: false,\n\t};\n\n\tlet coord: number[][][];\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tcoord = feature.geometry.coordinates;\n\t} else if (feature.geometry.type === \"LineString\") {\n\t\tcoord = [feature.geometry.coordinates];\n\t} else {\n\t\tthrow new Error(\"Self intersects only accepts Polygons and LineStrings\");\n\t}\n\n\tconst output: number[][] = [];\n\tconst seen: { [key: string]: boolean } = {};\n\n\tfor (let ring0 = 0; ring0 < coord.length; ring0++) {\n\t\tfor (let edge0 = 0; edge0 < coord[ring0].length - 1; edge0++) {\n\t\t\tfor (let ring1 = 0; ring1 < coord.length; ring1++) {\n\t\t\t\tfor (let edge1 = 0; edge1 < coord[ring1].length - 1; edge1++) {\n\t\t\t\t\t// speedup possible if only interested in unique: start last two loops at ring0 and edge0+1\n\t\t\t\t\tifInteresctionAddToOutput(ring0, edge0, ring1, edge1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn output.length > 0;\n\n\t// true if frac is (almost) 1.0 or 0.0\n\t// function isBoundaryCase(frac: number) {\n\t// const e2 = options.epsilon * options.epsilon;\n\t// return e2 >= (frac - 1) * (frac - 1) || e2 >= frac * frac;\n\t// }\n\n\tfunction isOutside(frac: number) {\n\t\treturn frac < 0 - options.epsilon || frac > 1 + options.epsilon;\n\t}\n\t// Function to check if two edges intersect and add the intersection to the output\n\tfunction ifInteresctionAddToOutput(\n\t\tring0: number,\n\t\tedge0: number,\n\t\tring1: number,\n\t\tedge1: number,\n\t) {\n\t\tconst start0 = coord[ring0][edge0];\n\t\tconst end0 = coord[ring0][edge0 + 1];\n\t\tconst start1 = coord[ring1][edge1];\n\t\tconst end1 = coord[ring1][edge1 + 1];\n\n\t\tconst intersection = intersect(start0, end0, start1, end1);\n\n\t\tif (intersection === null) {\n\t\t\treturn; // discard parallels and coincidence\n\t\t}\n\n\t\tlet frac0;\n\t\tlet frac1;\n\n\t\tif (end0[0] !== start0[0]) {\n\t\t\tfrac0 = (intersection[0] - start0[0]) / (end0[0] - start0[0]);\n\t\t} else {\n\t\t\tfrac0 = (intersection[1] - start0[1]) / (end0[1] - start0[1]);\n\t\t}\n\t\tif (end1[0] !== start1[0]) {\n\t\t\tfrac1 = (intersection[0] - start1[0]) / (end1[0] - start1[0]);\n\t\t} else {\n\t\t\tfrac1 = (intersection[1] - start1[1]) / (end1[1] - start1[1]);\n\t\t}\n\n\t\t// There are roughly three cases we need to deal with.\n\t\t// 1. If at least one of the fracs lies outside [0,1], there is no intersection.\n\t\tif (isOutside(frac0) || isOutside(frac1)) {\n\t\t\treturn; // require segment intersection\n\t\t}\n\n\t\t// 2. If both are either exactly 0 or exactly 1, this is not an intersection but just\n\t\t// two edge segments sharing a common vertex.\n\t\t// if (isBoundaryCase(frac0) && isBoundaryCase(frac1)) {\n\t\t// if (!options.reportVertexOnVertex) {\n\t\t// return;\n\t\t// }\n\t\t// }\n\n\t\t// // 3. If only one of the fractions is exactly 0 or 1, this is\n\t\t// // a vertex-on-edge situation.\n\t\t// if (isBoundaryCase(frac0) || isBoundaryCase(frac1)) {\n\t\t// if (!options.reportVertexOnEdge) {\n\t\t// return;\n\t\t// }\n\t\t// }\n\n\t\tconst key = intersection.toString();\n\t\tconst unique = !seen[key];\n\t\tif (unique) {\n\t\t\tseen[key] = true;\n\t\t}\n\n\t\toutput.push(intersection);\n\t}\n}\n\nfunction equalArrays(array1: Position, array2: Position) {\n\treturn array1[0] === array2[0] && array1[1] === array2[1];\n}\n\n// Function to compute where two lines (not segments) intersect. From https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection\nfunction intersect(\n\tstart0: Position,\n\tend0: Position,\n\tstart1: Position,\n\tend1: Position,\n) {\n\tif (\n\t\tequalArrays(start0, start1) ||\n\t\tequalArrays(start0, end1) ||\n\t\tequalArrays(end0, start1) ||\n\t\tequalArrays(end1, start1)\n\t) {\n\t\treturn null;\n\t}\n\n\tconst x0 = start0[0],\n\t\ty0 = start0[1],\n\t\tx1 = end0[0],\n\t\ty1 = end0[1],\n\t\tx2 = start1[0],\n\t\ty2 = start1[1],\n\t\tx3 = end1[0],\n\t\ty3 = end1[1];\n\n\tconst denom = (x0 - x1) * (y2 - y3) - (y0 - y1) * (x2 - x3);\n\tif (denom === 0) {\n\t\treturn null;\n\t}\n\n\tconst x4 =\n\t\t((x0 * y1 - y0 * x1) * (x2 - x3) - (x0 - x1) * (x2 * y3 - y2 * x3)) / denom;\n\n\tconst y4 =\n\t\t((x0 * y1 - y0 * x1) * (y2 - y3) - (y0 - y1) * (x2 * y3 - y2 * x3)) / denom;\n\n\treturn [x4, y4];\n}\n","import { Position } from \"geojson\";\n\nexport function validLatitude(lat: number) {\n\treturn lat >= -90 && lat <= 90;\n}\n\nexport function validLongitude(lng: number) {\n\treturn lng >= -180 && lng <= 180;\n}\n\nexport function coordinatePrecisionIsValid(\n\tcoordinate: Position,\n\tcoordinatePrecision: number,\n) {\n\treturn (\n\t\tgetDecimalPlaces(coordinate[0]) <= coordinatePrecision &&\n\t\tgetDecimalPlaces(coordinate[1]) <= coordinatePrecision\n\t);\n}\n\nexport function coordinateIsValid(coordinate: unknown[]) {\n\treturn (\n\t\tcoordinate.length === 2 &&\n\t\ttypeof coordinate[0] === \"number\" &&\n\t\ttypeof coordinate[1] === \"number\" &&\n\t\tcoordinate[0] !== Infinity &&\n\t\tcoordinate[1] !== Infinity &&\n\t\tvalidLongitude(coordinate[0]) &&\n\t\tvalidLatitude(coordinate[1])\n\t);\n}\n\nexport function getDecimalPlaces(value: number): number {\n\tlet current = 1;\n\tlet precision = 0;\n\twhile (Math.round(value * current) / current !== value) {\n\t\tcurrent *= 10;\n\t\tprecision++;\n\t}\n\n\treturn precision;\n}\n","import { Feature, Polygon, Position } from \"geojson\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport { selfIntersects } from \"../geometry/boolean/self-intersects\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\nimport { Validation } from \"../common\";\n\nexport const ValidationReasonFeatureNotPolygon = \"Feature is not a Polygon\";\nexport const ValidationReasonFeatureHasHoles = \"Feature has holes\";\nexport const ValidationReasonFeatureLessThanFourCoordinates =\n\t\"Feature has less than 4 coordinates\";\nexport const ValidationReasonFeatureHasInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureCoordinatesNotClosed =\n\t\"Feature coordinates are not closed\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidatePolygonFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"Polygon\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPolygon,\n\t\t};\n\t}\n\n\tif (feature.geometry.coordinates.length !== 1) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureHasHoles,\n\t\t};\n\t}\n\n\tif (feature.geometry.coordinates[0].length < 4) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureLessThanFourCoordinates,\n\t\t};\n\t}\n\n\tfor (let i = 0; i < feature.geometry.coordinates[0].length; i++) {\n\t\tif (!coordinateIsValid(feature.geometry.coordinates[0][i])) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureHasInvalidCoordinates,\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t!coordinatePrecisionIsValid(\n\t\t\t\tfeature.geometry.coordinates[0][i],\n\t\t\t\tcoordinatePrecision,\n\t\t\t)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tvalid: false,\n\t\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (\n\t\t!coordinatesMatch(\n\t\t\tfeature.geometry.coordinates[0][0],\n\t\t\tfeature.geometry.coordinates[0][\n\t\t\t\tfeature.geometry.coordinates[0].length - 1\n\t\t\t],\n\t\t)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureCoordinatesNotClosed,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n\nexport function ValidateNonIntersectingPolygonFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tconst validatePolygonFeature = ValidatePolygonFeature(\n\t\tfeature,\n\t\tcoordinatePrecision,\n\t);\n\n\tif (!validatePolygonFeature.valid) {\n\t\treturn validatePolygonFeature;\n\t}\n\n\tif (selfIntersects(feature as Feature<Polygon>)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: \"Feature intersects itself\",\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n\n/**\n * Check if two coordinates are identical\n * @param coordinateOne - coordinate to compare\n * @param coordinateTwo - coordinate to compare with\n * @returns boolean\n */\nfunction coordinatesMatch(coordinateOne: Position, coordinateTwo: Position) {\n\treturn (\n\t\tcoordinateOne[0] === coordinateTwo[0] &&\n\t\tcoordinateOne[1] === coordinateTwo[1]\n\t);\n}\n","import { Feature, Position } from \"geojson\";\nimport {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tProjection,\n} from \"../../common\";\nimport { haversineDistanceKilometers } from \"../../geometry/measure/haversine-distance\";\nimport { circle, circleWebMercator } from \"../../geometry/shape/create-circle\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { Polygon } from \"geojson\";\nimport { calculateWebMercatorDistortion } from \"../../geometry/shape/web-mercator-distortion\";\n\ntype TerraDrawCircleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype CirclePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawCircleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawCircleModeKeyEvents | null;\n\tcursors?: Cursors;\n\tstartingRadiusKilometers?: number;\n\tprojection?: Projection;\n}\n\nexport class TerraDrawCircleMode extends TerraDrawBaseDrawMode<CirclePolygonStyling> {\n\tmode = \"circle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentCircleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawCircleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate startingRadiusKilometers = 0.00001;\n\tprivate cursorMovedAfterInitialCursorDown = false;\n\n\t/**\n\t * Create a new circle mode instance\n\t * @param options - Options to customize the behavior of the circle mode\n\t * @param options.keyEvents - Key events to cancel or finish the mode\n\t * @param options.cursors - Cursors to use for the mode\n\t * @param options.styles - Custom styling for the circle\n\t * @param options.pointerDistance - Distance in pixels to consider a pointer close to a vertex\n\t */\n\tconstructor(options?: TerraDrawCircleModeOptions<CirclePolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawCircleModeOptions<CirclePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.startingRadiusKilometers) {\n\t\t\tthis.startingRadiusKilometers = options.startingRadiusKilometers;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentCircleId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentCircleId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\tthis.center = undefined;\n\t\tthis.currentCircleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 0) {\n\t\t\tthis.center = [event.lng, event.lat];\n\t\t\tconst startingCircle = circle({\n\t\t\t\tcenter: this.center,\n\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t});\n\n\t\t\tconst [createdId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: startingCircle.geometry,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\tradiusKilometers: this.startingRadiusKilometers,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentCircleId = createdId;\n\t\t\tthis.clickCount++;\n\t\t\tthis.cursorMovedAfterInitialCursorDown = false;\n\t\t\tthis.setDrawing();\n\t\t} else {\n\t\t\tif (\n\t\t\t\tthis.clickCount === 1 &&\n\t\t\t\tthis.center &&\n\t\t\t\tthis.currentCircleId !== undefined &&\n\t\t\t\tthis.cursorMovedAfterInitialCursorDown\n\t\t\t) {\n\t\t\t\tthis.updateCircle(event);\n\t\t\t}\n\n\t\t\t// Finish drawing\n\t\t\tthis.close();\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 = 10;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate updateCircle(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 1 && this.center && this.currentCircleId) {\n\t\t\tconst newRadius = haversineDistanceKilometers(this.center, [\n\t\t\t\tevent.lng,\n\t\t\t\tevent.lat,\n\t\t\t]);\n\n\t\t\tlet updatedCircle: Feature<Polygon>;\n\n\t\t\tif (this.projection === \"web-mercator\") {\n\t\t\t\t// We want to track the mouse cursor, but we need to adjust the radius based\n\t\t\t\t// on the distortion of the web mercator projection\n\t\t\t\tconst distortion = calculateWebMercatorDistortion(this.center, [\n\t\t\t\t\tevent.lng,\n\t\t\t\t\tevent.lat,\n\t\t\t\t]);\n\n\t\t\t\tupdatedCircle = circleWebMercator({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius * distortion,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else if (this.projection === \"globe\") {\n\t\t\t\tupdatedCircle = circle({\n\t\t\t\t\tcenter: this.center,\n\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Invalid projection\");\n\t\t\t}\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst valid = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\t\tgeometry: updatedCircle.geometry,\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tradiusKilometers: newRadius,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!valid.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentCircleId, geometry: updatedCircle.geometry },\n\t\t\t]);\n\t\t\tthis.store.updateProperty([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentCircleId,\n\t\t\t\t\tproperty: \"radiusKilometers\",\n\t\t\t\t\tvalue: newRadius,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../common\";\n\nexport const getDefaultStyling = (): TerraDrawAdapterStyling => {\n\treturn {\n\t\tpolygonFillColor: \"#3f97e0\",\n\t\tpolygonOutlineColor: \"#3f97e0\",\n\t\tpolygonOutlineWidth: 4,\n\t\tpolygonFillOpacity: 0.3,\n\t\tpointColor: \"#3f97e0\",\n\t\tpointOutlineColor: \"#ffffff\",\n\t\tpointOutlineWidth: 0,\n\t\tpointWidth: 6,\n\t\tlineStringColor: \"#3f97e0\",\n\t\tlineStringWidth: 4,\n\t\tzIndex: 0,\n\t};\n};\n","import { Position } from \"geojson\";\nimport { haversineDistanceKilometers } from \"../measure/haversine-distance\";\nimport { lngLatToWebMercatorXY } from \"../project/web-mercator\";\n\n/*\n * Function to calculate the web mercator vs geodesic distortion between two coordinates\n * Value of 1 means no distortion, higher values mean higher distortion\n * */\nexport function calculateWebMercatorDistortion(\n\tsource: Position,\n\ttarget: Position,\n): number {\n\tconst geodesicDistance = haversineDistanceKilometers(source, target) * 1000;\n\tif (geodesicDistance === 0) {\n\t\treturn 1;\n\t}\n\n\tconst { x: x1, y: y1 } = lngLatToWebMercatorXY(source[0], source[1]);\n\tconst { x: x2, y: y2 } = lngLatToWebMercatorXY(target[0], target[1]);\n\tconst euclideanDistance = Math.sqrt(\n\t\tMath.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2),\n\t);\n\treturn euclideanDistance / geodesicDistance;\n}\n","import { CartesianPoint } from \"../../common\";\n\nexport const cartesianDistance = (\n\tpointOne: CartesianPoint,\n\tpointTwo: CartesianPoint,\n) => {\n\tconst { x: x1, y: y1 } = pointOne;\n\tconst { x: x2, y: y2 } = pointTwo;\n\tconst y = x2 - x1;\n\tconst x = y2 - y1;\n\treturn Math.sqrt(x * x + y * y);\n};\n","import { Feature, Polygon } from \"geojson\";\nimport { followsRightHandRule } from \"./boolean/right-hand-rule\";\n\nexport function ensureRightHandRule(polygon: Polygon): undefined | Polygon {\n\tconst isFollowingRightHandRule = followsRightHandRule(polygon);\n\tif (!isFollowingRightHandRule) {\n\t\treturn {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [polygon.coordinates[0].reverse()],\n\t\t} as Polygon;\n\t}\n}\n","import { Polygon } from \"geojson\";\n\n/**\n * Checks if a GeoJSON Polygon follows the right-hand rule.\n * @param polygon - The GeoJSON Polygon to check.\n * @returns {boolean} - True if the polygon follows the right-hand rule (counterclockwise outer ring), otherwise false.\n */\nexport function followsRightHandRule(polygon: Polygon): boolean {\n\tconst outerRing = polygon.coordinates[0];\n\n\tlet sum = 0;\n\tfor (let i = 0; i < outerRing.length - 1; i++) {\n\t\tconst [x1, y1] = outerRing[i];\n\t\tconst [x2, y2] = outerRing[i + 1];\n\t\tsum += (x2 - x1) * (y2 + y1);\n\t}\n\n\treturn sum < 0; // Right-hand rule: counterclockwise = negative area\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n} from \"../../common\";\nimport { Polygon } from \"geojson\";\n\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawFreehandModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype FreehandPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n\tclosingPointColor: HexColorStyling;\n\tclosingPointWidth: NumericStyling;\n\tclosingPointOutlineColor: HexColorStyling;\n\tclosingPointOutlineWidth: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawFreehandModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tminDistance?: number;\n\tpreventPointsNearClose?: boolean;\n\tautoClose?: boolean;\n\tautoCloseTimeout?: number;\n\tkeyEvents?: TerraDrawFreehandModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawFreehandMode extends TerraDrawBaseDrawMode<FreehandPolygonStyling> {\n\tmode = \"freehand\" as const;\n\n\tprivate startingClick = false;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate minDistance: number = 20;\n\tprivate keyEvents: TerraDrawFreehandModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate preventPointsNearClose: boolean = true;\n\tprivate autoClose: boolean = false;\n\tprivate autoCloseTimeout = 500;\n\tprivate hasLeftStartingPoint = false;\n\tprivate preventNewFeature = false;\n\n\tconstructor(options?: TerraDrawFreehandModeOptions<FreehandPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tpublic updateOptions(\n\t\toptions?: TerraDrawFreehandModeOptions<FreehandPolygonStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.minDistance) {\n\t\t\tthis.minDistance = options.minDistance;\n\t\t}\n\n\t\tif (options?.preventPointsNearClose !== undefined) {\n\t\t\tthis.preventPointsNearClose = options.preventPointsNearClose;\n\t\t}\n\n\t\tif (options?.autoClose !== undefined) {\n\t\t\tthis.autoClose = options.autoClose;\n\t\t}\n\n\t\tif (options?.autoCloseTimeout) {\n\t\t\tthis.autoCloseTimeout = options.autoCloseTimeout;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tif (this.validate && finishedId) {\n\t\t\tconst currentGeometry = this.store.getGeometryCopy<Polygon>(finishedId);\n\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: finishedId,\n\t\t\t\t\tgeometry: currentGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\t\tthis.startingClick = false;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.hasLeftStartingPoint = false;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tif (this.currentId === undefined || this.startingClick === false) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst previousIndex = currentLineGeometry.coordinates[0].length - 2;\n\t\tconst [previousLng, previousLat] =\n\t\t\tcurrentLineGeometry.coordinates[0][previousIndex];\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tconst [closingLng, closingLat] = currentLineGeometry.coordinates[0][0];\n\t\tconst { x: closingX, y: closingY } = this.project(closingLng, closingLat);\n\t\tconst closingDistance = cartesianDistance(\n\t\t\t{ x: closingX, y: closingY },\n\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t);\n\n\t\tif (closingDistance < this.pointerDistance) {\n\t\t\t// We only want to close the polygon if the users cursor has left the\n\t\t\t// region of the starting point\n\t\t\tif (this.autoClose && this.hasLeftStartingPoint) {\n\t\t\t\t// If we have an autoCloseTimeout, we want to prevent new features\n\t\t\t\t// being created by accidental clicks for a short period of time\n\t\t\t\tthis.preventNewFeature = true;\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.preventNewFeature = false;\n\t\t\t\t}, this.autoCloseTimeout);\n\n\t\t\t\tthis.close();\n\t\t\t}\n\n\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t// We want to prohibit drawing new points at or around the closing\n\t\t\t// point as it can be non user friendly\n\t\t\tif (this.preventPointsNearClose) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.hasLeftStartingPoint = true;\n\t\t\tthis.setCursor(this.cursors.start);\n\t\t}\n\n\t\t// The cusor must have moved a minimum distance\n\t\t// before we add another coordinate\n\t\tif (distance < this.minDistance) {\n\t\t\treturn;\n\t\t}\n\n\t\tcurrentLineGeometry.coordinates[0].pop();\n\n\t\tconst newGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [\n\t\t\t\t[\n\t\t\t\t\t...currentLineGeometry.coordinates[0],\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentLineGeometry.coordinates[0][0],\n\t\t\t\t],\n\t\t\t],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: this.currentId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: newGeometry,\n\t\t\t},\n\t\t]);\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.preventNewFeature) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.startingClick === false) {\n\t\t\tconst [createdId, closingPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t\t{\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\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\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\n\t\t\tthis.currentId = createdId;\n\t\t\tthis.closingPointId = closingPointId;\n\t\t\tthis.startingClick = true;\n\t\t\tthis.setDrawing();\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis.close();\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 = 10;\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 = 40;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePolygonFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n}\n","import { Project, Projection, Unproject } from \"../common\";\nimport { GeoJSONStore } from \"../store/store\";\n\nexport type BehaviorConfig = {\n\tstore: GeoJSONStore;\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: GeoJSONStore;\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\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 { 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 { BehaviorConfig, TerraDrawModeBehavior } from \"./base.behavior\";\nimport { TerraDrawMouseEvent } from \"../common\";\nimport { Feature, Position } from \"geojson\";\nimport { ClickBoundingBoxBehavior } from \"./click-bounding-box.behavior\";\nimport { BBoxPolygon, FeatureId } from \"../store/store\";\nimport { PixelDistanceBehavior } from \"./pixel-distance.behavior\";\nimport { nearestPointOnLine } from \"../geometry/point-on-line\";\nimport { webMercatorNearestPointOnLine } from \"../geometry/web-mercator-point-on-line\";\n\nexport class LineSnappingBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly clickBoundingBox: ClickBoundingBoxBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\t/** Returns the nearest snappable coordinate - on first click there is no currentId so no need to provide */\n\tpublic getSnappableCoordinateFirstClick = (event: TerraDrawMouseEvent) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties && feature.properties.mode === this.mode,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappableCoordinate = (\n\t\tevent: TerraDrawMouseEvent,\n\t\tcurrentFeatureId: FeatureId,\n\t) => {\n\t\tconst snappable = this.getSnappable(event, (feature) => {\n\t\t\treturn Boolean(\n\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === this.mode &&\n\t\t\t\t\tfeature.id !== currentFeatureId,\n\t\t\t);\n\t\t});\n\n\t\treturn snappable.coordinate;\n\t};\n\n\tpublic getSnappable(\n\t\tevent: TerraDrawMouseEvent,\n\t\tfilter?: (feature: Feature) => boolean,\n\t) {\n\t\tconst boundingBox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(boundingBox, filter);\n\t\tconst closest: {\n\t\t\tcoordinate: undefined | Position;\n\t\t\tminDistance: number;\n\t\t\tfeatureId: undefined | FeatureId;\n\t\t\tfeatureCoordinateIndex: undefined | number;\n\t\t} = {\n\t\t\tfeatureId: undefined,\n\t\t\tfeatureCoordinateIndex: undefined,\n\t\t\tcoordinate: undefined,\n\t\t\tminDistance: Infinity,\n\t\t};\n\t\tfeatures.forEach((feature) => {\n\t\t\tlet coordinates: Position[];\n\t\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst lines: [Position, Position][] = [];\n\n\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\tlines.push([coordinates[i], coordinates[i + 1]]);\n\t\t\t}\n\n\t\t\tlet nearest:\n\t\t\t\t| {\n\t\t\t\t\t\tcoordinate: Position;\n\t\t\t\t\t\tlineIndex: number;\n\t\t\t\t\t\tdistance: number;\n\t\t\t\t }\n\t\t\t\t| undefined;\n\n\t\t\tconst lngLat: Position = [event.lng, event.lat];\n\n\t\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\t\tnearest = webMercatorNearestPointOnLine(lngLat, lines);\n\t\t\t} else if (this.config.projection === \"globe\") {\n\t\t\t\tnearest = nearestPointOnLine(lngLat, lines);\n\t\t\t}\n\n\t\t\tif (!nearest) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst distance = this.pixelDistance.measure(event, nearest.coordinate);\n\t\t\tif (distance < closest.minDistance && distance < this.pointerDistance) {\n\t\t\t\tclosest.featureId = feature.id;\n\t\t\t\tclosest.coordinate = nearest.coordinate;\n\t\t\t\tclosest.featureCoordinateIndex = nearest.lineIndex;\n\t\t\t\tclosest.minDistance = distance;\n\t\t\t}\n\t\t});\n\n\t\treturn closest;\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n\tCartesianPoint,\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 Snapping {\n\ttoCoordinate?: boolean;\n\ttoCustom?: (event: TerraDrawMouseEvent) => Position | undefined;\n}\n\ninterface TerraDrawLineStringModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawLineStringModeKeyEvents | null;\n\tcursors?: Cursors;\n\tinsertCoordinates?: InertCoordinates;\n\teditable?: boolean;\n}\n\nexport class TerraDrawLineStringMode extends TerraDrawBaseDrawMode<LineStringStyling> {\n\tmode = \"linestring\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate closingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawLineStringModeKeyEvents = defaultKeyEvents;\n\tprivate snapping: Snapping | undefined;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\tprivate insertCoordinates: InertCoordinates | undefined;\n\tprivate lastCommitedCoordinates: Position[] | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\n\t// Editable properties\n\tprivate editable: boolean = false;\n\tprivate editedFeatureId: FeatureId | undefined;\n\tprivate editedFeatureCoordinateIndex: number | undefined;\n\tprivate editedSnapType: \"line\" | \"coordinate\" | undefined;\n\tprivate editedInsertIndex: number | undefined;\n\tprivate editedPointId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate coordinateSnapping!: CoordinateSnappingBehavior;\n\tprivate insertPoint!: InsertCoordinatesBehavior;\n\tprivate lineSnapping!: LineSnappingBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawLineStringModeOptions<LineStringStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawLineStringModeOptions<LineStringStyling> | undefined,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.snapping) {\n\t\t\tthis.snapping = options.snapping;\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.insertCoordinates) {\n\t\t\tthis.insertCoordinates = options.insertCoordinates;\n\t\t}\n\n\t\tif (options && options.editable) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\t// Finish off the drawing\n\t\tcurrentLineGeometry.coordinates.pop();\n\n\t\tthis.updateGeometries(\n\t\t\t[...currentLineGeometry.coordinates],\n\t\t\tundefined,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Reset the state back to starting state\n\t\tif (this.closingPointId) {\n\t\t\tthis.store.delete([this.closingPointId]);\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.closingPointId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.lastCommitedCoordinates = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\t// Ensure that any listeners are triggered with the main created geometry\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate updateGeometries(\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tclosingPointCoordinate: Point[\"coordinates\"] | undefined,\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updatedGeometry = { type: \"LineString\", coordinates } as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: updateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst geometries = [\n\t\t\t{\n\t\t\t\tid: this.currentId,\n\t\t\t\tgeometry: updatedGeometry,\n\t\t\t},\n\t\t] as {\n\t\t\tid: FeatureId;\n\t\t\tgeometry: GeoJSONStoreGeometries;\n\t\t}[];\n\n\t\tif (this.closingPointId && closingPointCoordinate) {\n\t\t\tgeometries.push({\n\t\t\t\tid: this.closingPointId,\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: closingPointCoordinate,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tif (updateType === \"commit\") {\n\t\t\tthis.lastCommitedCoordinates = updatedGeometry.coordinates;\n\t\t}\n\n\t\tthis.store.updateGeometry(geometries);\n\t}\n\n\tprivate generateInsertCoordinates(startCoord: Position, endCoord: Position) {\n\t\tif (!this.insertCoordinates || !this.lastCommitedCoordinates) {\n\t\t\tthrow new Error(\"Not able to insert coordinates\");\n\t\t}\n\n\t\t// Other strategies my be implemented in the future\n\t\tif (this.insertCoordinates.strategy !== \"amount\") {\n\t\t\tthrow new Error(\"Strategy does not exist\");\n\t\t}\n\n\t\tconst distance = haversineDistanceKilometers(startCoord, endCoord);\n\t\tconst segmentDistance = distance / (this.insertCoordinates.value + 1);\n\t\tlet insertedCoordinates: Position[] = [];\n\n\t\tif (this.projection === \"globe\") {\n\t\t\tinsertedCoordinates =\n\t\t\t\tthis.insertPoint.generateInsertionGeodesicCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t\tsegmentDistance,\n\t\t\t\t);\n\t\t} else if (this.projection === \"web-mercator\") {\n\t\t\tinsertedCoordinates = this.insertPoint.generateInsertionCoordinates(\n\t\t\t\tstartCoord,\n\t\t\t\tendCoord,\n\t\t\t\tsegmentDistance,\n\t\t\t);\n\t\t}\n\n\t\treturn insertedCoordinates;\n\t}\n\n\tprivate createLine(startingCoord: Position) {\n\t\tconst [createdId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"LineString\",\n\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\tstartingCoord,\n\t\t\t\t\t\tstartingCoord, // This is the 'live' point that changes on mouse move\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.lastCommitedCoordinates = [startingCoord, startingCoord];\n\t\tthis.currentId = createdId;\n\t\tthis.currentCoordinate++;\n\t\tthis.setDrawing();\n\t}\n\n\tprivate firstUpdateToLine(updatedCoord: Position) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\tconst [pointId] = this.store.create([\n\t\t\t{\n\t\t\t\tgeometry: {\n\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\tcoordinates: [...updatedCoord],\n\t\t\t\t},\n\t\t\t\tproperties: { mode: this.mode },\n\t\t\t},\n\t\t]);\n\t\tthis.closingPointId = pointId;\n\n\t\t// We are creating the point so we immediately want\n\t\t// to set the point cursor to show it can be closed\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst initialLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst closingPointCoordinate = undefined; // We don't need this until second click\n\n\t\tthis.updateGeometries(\n\t\t\tinitialLineCoordinates,\n\t\t\tclosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\tprivate updateToLine(updatedCoord: Position, cursorXY: CartesianPoint) {\n\t\tif (!this.currentId) {\n\t\t\treturn;\n\t\t}\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// If we are not inserting points we can get the penultimate coordinated\n\t\tconst [previousLng, previousLat] = this.lastCommitedCoordinates\n\t\t\t? this.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1]\n\t\t\t: currentCoordinates[currentCoordinates.length - 2];\n\n\t\t// Determine if the click closes the line and finished drawing\n\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\tconst distance = cartesianDistance(\n\t\t\t{ x, y },\n\t\t\t{ x: cursorXY.x, y: cursorXY.y },\n\t\t);\n\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\tif (isClosingClick) {\n\t\t\tthis.close();\n\t\t\treturn;\n\t\t}\n\n\t\t// The cursor will immediately change to closing because the\n\t\t// closing point will be underneath the cursor\n\t\tthis.setCursor(this.cursors.close);\n\n\t\tconst updatedLineCoordinates = [...currentCoordinates, updatedCoord];\n\t\tconst updatedClosingPointCoordinate =\n\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\n\t\tthis.updateGeometries(\n\t\t\tupdatedLineCoordinates,\n\t\t\tupdatedClosingPointCoordinate,\n\t\t\tUpdateTypes.Commit,\n\t\t);\n\n\t\tthis.currentCoordinate++;\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tnew PixelDistanceBehavior(config),\n\t\t\tnew ClickBoundingBoxBehavior(config),\n\t\t);\n\n\t\tthis.insertPoint = new InsertCoordinatesBehavior(config);\n\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst updatedCoord = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentLineGeometry = this.store.getGeometryCopy<LineString>(\n\t\t\tthis.currentId,\n\t\t);\n\n\t\tconst currentCoordinates = currentLineGeometry.coordinates;\n\n\t\t// Remove the 'live' point that changes on mouse move\n\t\tcurrentCoordinates.pop();\n\n\t\t// We want to ensure that when we are hovering over\n\t\t// the closing point that the pointer cursor is shown\n\t\tif (this.closingPointId) {\n\t\t\tconst [previousLng, previousLat] =\n\t\t\t\tcurrentCoordinates[currentCoordinates.length - 1];\n\t\t\tconst { x, y } = this.project(previousLng, previousLat);\n\t\t\tconst distance = cartesianDistance(\n\t\t\t\t{ x, y },\n\t\t\t\t{ x: event.containerX, y: event.containerY },\n\t\t\t);\n\n\t\t\tconst isClosingClick = distance < this.pointerDistance;\n\n\t\t\tif (isClosingClick) {\n\t\t\t\tthis.setCursor(this.cursors.close);\n\t\t\t}\n\t\t}\n\n\t\tlet line = [...currentCoordinates, updatedCoord];\n\n\t\tif (\n\t\t\tthis.insertCoordinates &&\n\t\t\tthis.currentId &&\n\t\t\tthis.lastCommitedCoordinates\n\t\t) {\n\t\t\tconst startCoord =\n\t\t\t\tthis.lastCommitedCoordinates[this.lastCommitedCoordinates.length - 1];\n\t\t\tconst endCoord = updatedCoord;\n\t\t\tif (!coordinatesIdentical(startCoord, endCoord)) {\n\t\t\t\tconst insertedCoordinates = this.generateInsertCoordinates(\n\t\t\t\t\tstartCoord,\n\t\t\t\t\tendCoord,\n\t\t\t\t);\n\t\t\t\tline = [\n\t\t\t\t\t...this.lastCommitedCoordinates.slice(0, -1),\n\t\t\t\t\t...insertedCoordinates,\n\t\t\t\t\tupdatedCoord,\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\t// Update the 'live' point\n\t\tthis.updateGeometries(line, undefined, UpdateTypes.Provisional);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\tif (!this.editable || this.state !== \"started\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.lineStringFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tcoordinates = geometry.coordinates;\n\n\t\t\t// Prevent creating an invalid linestring\n\t\t\tif (coordinates.length <= 2) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove coordinate from array\n\t\tcoordinates.splice(coordinateIndex, 1);\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\t\tconst updatedCoordinate = snappedCoordinate\n\t\t\t? snappedCoordinate\n\t\t\t: [event.lng, event.lat];\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tthis.createLine(updatedCoordinate);\n\t\t} else if (this.currentCoordinate === 1 && this.currentId) {\n\t\t\tthis.firstUpdateToLine(updatedCoordinate);\n\t\t} else if (this.currentId) {\n\t\t\tthis.updateToLine(updatedCoordinate, {\n\t\t\t\tx: event.containerX,\n\t\t\t\ty: event.containerY,\n\t\t\t});\n\t\t}\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t} else if (event.button === \"left\") {\n\t\t\tthis.onLeftClick(event);\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.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 (\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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 10;\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 = 40;\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?.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}\n\n\t\treturn snappedCoordinate;\n\t}\n}\n","import { Validation } from \"../common\";\nimport { GeoJSONStoreFeatures } from \"../terra-draw\";\nimport {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../geometry/boolean/is-valid-coordinate\";\n\nexport const ValidationReasonFeatureNotPoint = \"Feature is not a Point\";\nexport const ValidationReasonFeatureInvalidCoordinates =\n\t\"Feature has invalid coordinates\";\nexport const ValidationReasonFeatureInvalidCoordinatePrecision =\n\t\"Feature has coordinates with excessive precision\";\n\nexport function ValidatePointFeature(\n\tfeature: GeoJSONStoreFeatures,\n\tcoordinatePrecision: number,\n): ReturnType<Validation> {\n\tif (feature.geometry.type !== \"Point\") {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureNotPoint,\n\t\t};\n\t}\n\n\tif (!coordinateIsValid(feature.geometry.coordinates)) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinates,\n\t\t};\n\t}\n\n\tif (\n\t\t!coordinatePrecisionIsValid(\n\t\t\tfeature.geometry.coordinates,\n\t\t\tcoordinatePrecision,\n\t\t)\n\t) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\treason: ValidationReasonFeatureInvalidCoordinatePrecision,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tNumericStyling,\n\tHexColorStyling,\n\tCursor,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n} 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 (!this.store) {\n\t\t\tthrow new Error(\"Mode must be registered first\");\n\t\t}\n\n\t\tif (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t} else if (event.button === \"left\") {\n\t\t\tthis.onLeftClick(event);\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.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.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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 30;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePointFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\tconst geometry = {\n\t\t\ttype: \"Point\",\n\t\t\tcoordinates: [event.lng, event.lat],\n\t\t} as Point;\n\n\t\tconst properties = { mode: this.mode };\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Finish,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst [pointId] = this.store.create([{ geometry, properties }]);\n\n\t\t// Ensure that any listerers are triggered with the main created geometry\n\t\tthis.onFinish(pointId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// We only want to be able to delete points if the mode is editable\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst clickedFeature = this.getNearestPointFeature(event);\n\n\t\tif (clickedFeature) {\n\t\t\tthis.store.delete([clickedFeature.id as FeatureId]);\n\t\t}\n\t}\n\n\tprivate getNearestPointFeature(event: TerraDrawMouseEvent) {\n\t\tconst bbox = this.clickBoundingBox.create(event) as BBoxPolygon;\n\t\tconst features = this.store.search(bbox);\n\n\t\tlet distance = Infinity;\n\t\tlet clickedFeature: GeoJSONStoreFeatures | undefined = undefined;\n\n\t\tfor (let i = 0; i < features.length; i++) {\n\t\t\tconst feature = features[i];\n\t\t\tconst isPoint =\n\t\t\t\tfeature.geometry.type === \"Point\" &&\n\t\t\t\tfeature.properties.mode === this.mode;\n\n\t\t\tif (!isPoint) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst position = feature.geometry.coordinates as Position;\n\t\t\tconst distanceToFeature = this.pixelDistance.measure(event, position);\n\n\t\t\tif (\n\t\t\t\tdistanceToFeature > distance ||\n\t\t\t\tdistanceToFeature > this.pointerDistance\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdistance = distanceToFeature;\n\t\t\tclickedFeature = feature;\n\t\t}\n\n\t\treturn clickedFeature;\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { COMMON_PROPERTIES, TerraDrawMouseEvent } from \"../../../common\";\nimport { PixelDistanceBehavior } from \"../../pixel-distance.behavior\";\n\nexport class ClosingPointsBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate _startEndPoints: string[] = [];\n\n\tget ids() {\n\t\treturn this._startEndPoints.concat();\n\t}\n\n\tset ids(_: string[]) {}\n\n\tpublic create(selectedCoords: Position[], mode: string) {\n\t\tif (this.ids.length) {\n\t\t\tthrow new Error(\"Opening and closing points already created\");\n\t\t}\n\n\t\tif (selectedCoords.length <= 3) {\n\t\t\tthrow new Error(\"Requires at least 4 coordinates\");\n\t\t}\n\n\t\tthis._startEndPoints = this.store.create(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: selectedCoords[selectedCoords.length - 2],\n\t\t\t\t\t} as Point,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.CLOSING_POINT]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this.ids.length) {\n\t\t\tthis.store.delete(this.ids);\n\t\t\tthis._startEndPoints = [];\n\t\t}\n\t}\n\n\tpublic update(updatedCoordinates: Position[]) {\n\t\tif (this.ids.length !== 2) {\n\t\t\tthrow new Error(\"No closing points to update\");\n\t\t}\n\n\t\tthis.store.updateGeometry(\n\t\t\t// Opening coordinate\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[0],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[0],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t\t// Final coordinate\n\t\t\t\t{\n\t\t\t\t\tid: this.ids[1],\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: updatedCoordinates[updatedCoordinates.length - 3],\n\t\t\t\t\t} as Point,\n\t\t\t\t},\n\t\t\t],\n\t\t);\n\t}\n\n\tpublic isClosingPoint(event: TerraDrawMouseEvent) {\n\t\tconst opening = this.store.getGeometryCopy(this.ids[0]);\n\t\tconst closing = this.store.getGeometryCopy(this.ids[1]);\n\n\t\tconst distance = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\topening.coordinates as Position,\n\t\t);\n\n\t\tconst distancePrevious = this.pixelDistance.measure(\n\t\t\tevent,\n\t\t\tclosing.coordinates as Position,\n\t\t);\n\n\t\tconst isClosing = distance < this.pointerDistance;\n\t\tconst isPreviousClosing = distancePrevious < this.pointerDistance;\n\n\t\treturn { isClosing, isPreviousClosing };\n\t}\n}\n","import { Point, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { FeatureId } from \"../../../store/store\";\nimport { COMMON_PROPERTIES } from \"../../../common\";\n\nexport class CoordinatePointBehavior extends TerraDrawModeBehavior {\n\tconstructor(config: BehaviorConfig) {\n\t\tsuper(config);\n\t}\n\n\tpublic createOrUpdate(featureId: FeatureId) {\n\t\tconst existingFeature = this.store.getGeometryCopy(featureId);\n\t\tconst existingProperties = this.store.getPropertiesCopy(featureId);\n\n\t\tlet coordinates: Position[];\n\n\t\tif (existingFeature.type === \"Polygon\") {\n\t\t\tcoordinates = existingFeature.coordinates[0].slice(0, -1) as Position[];\n\t\t} else if (existingFeature.type === \"LineString\") {\n\t\t\tcoordinates = existingFeature.coordinates as Position[];\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tconst existingFeatureProps = this.store.getPropertiesCopy(featureId);\n\n\t\tif (!existingFeatureProps.coordinatePointIds) {\n\t\t\tconst coordinatePointIds = this.createPoints(\n\t\t\t\tcoordinates,\n\t\t\t\texistingProperties.mode as string,\n\t\t\t);\n\t\t\tthis.setFeatureCoordinatePoints(featureId, coordinatePointIds);\n\t\t} else {\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);\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}\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(coordinates: Position[], mode: string) {\n\t\treturn this.store.create(\n\t\t\tcoordinates.map((coordinate) => ({\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},\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\tthis.store.delete(coordinatePointIds as FeatureId[]);\n\t}\n\n\tprivate deleteIfPresent(featureId: FeatureId) {\n\t\tconst existingFeatureProps = this.store.getPropertiesCopy(featureId);\n\n\t\tif (existingFeatureProps.coordinatePointIds) {\n\t\t\tthis.deleteCoordinatePoints(\n\t\t\t\texistingFeatureProps.coordinatePointIds as FeatureId[],\n\t\t\t);\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} from \"../../common\";\nimport { Feature, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\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 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 | null;\n\t\t\tproject: Project;\n\t\t\tunproject: Unproject;\n\t\t},\n\t) => Position | undefined;\n}\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tsnapping?: Snapping;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tcursors?: Cursors;\n\teditable?: boolean;\n\tshowCoordinatePoints?: boolean;\n}\n\nexport class TerraDrawPolygonMode extends TerraDrawBaseDrawMode<PolygonStyling> {\n\tmode = \"polygon\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawPolygonModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\tprivate showCoordinatePoints = false;\n\n\t// Snapping\n\tprivate snapping: Snapping | undefined;\n\tprivate snappedPointId: FeatureId | undefined;\n\n\t// Editable\n\tprivate editable: boolean = false;\n\tprivate editedFeatureId: FeatureId | undefined;\n\tprivate editedFeatureCoordinateIndex: number | undefined;\n\tprivate editedSnapType: \"line\" | \"coordinate\" | undefined;\n\tprivate editedInsertIndex: number | undefined;\n\tprivate editedPointId: FeatureId | undefined;\n\n\t// Behaviors\n\tprivate coordinatePoints!: CoordinatePointBehavior;\n\tprivate lineSnapping!: LineSnappingBehavior;\n\tprivate coordinateSnapping!: CoordinateSnappingBehavior;\n\tprivate pixelDistance!: PixelDistanceBehavior;\n\tprivate closingPoints!: ClosingPointsBehavior;\n\tprivate clickBoundingBox!: ClickBoundingBoxBehavior;\n\n\tconstructor(options?: TerraDrawPolygonModeOptions<PolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawPolygonModeOptions<PolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\t// null is the case where we want to explicitly turn key bindings off\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.snapping) {\n\t\t\tthis.snapping = options.snapping;\n\t\t}\n\n\t\tif (options?.editable !== undefined) {\n\t\t\tthis.editable = options.editable;\n\t\t}\n\n\t\tif (options?.showCoordinatePoints !== undefined) {\n\t\t\tthis.showCoordinatePoints = options.showCoordinatePoints;\n\n\t\t\t// If we are not showing coordinate points, we need to add them all\n\t\t\tif (this.coordinatePoints && options.showCoordinatePoints === true) {\n\t\t\t\tconst features = this.store.copyAllWhere(\n\t\t\t\t\t(properties) => properties.mode === this.mode,\n\t\t\t\t);\n\t\t\t\tconst polygonIds = features.map((feature) => feature.id as FeatureId);\n\t\t\t\tpolygonIds.forEach((id) => {\n\t\t\t\t\tthis.coordinatePoints.createOrUpdate(id);\n\t\t\t\t});\n\t\t\t} else if (this.coordinatePoints && this.showCoordinatePoints === false) {\n\t\t\t\tconst featuresWithCoordinates = this.store.copyAllWhere(\n\t\t\t\t\t(properties) =>\n\t\t\t\t\t\tproperties.mode === this.mode &&\n\t\t\t\t\t\tBoolean(\n\t\t\t\t\t\t\tproperties[COMMON_PROPERTIES.COORDINATE_POINT_IDS] as FeatureId[],\n\t\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tthis.coordinatePoints.deletePointsByFeatureIds(\n\t\t\t\t\tfeaturesWithCoordinates.map((f) => f.id as FeatureId),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\t// We don't want to allow closing if there is not enough\n\t\t// coordinates. We have extra because we insert them on mouse\n\t\t// move\n\t\tif (currentPolygonCoordinates.length < 5) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst updated = this.updatePolygonGeometry(\n\t\t\t[...currentPolygonCoordinates.slice(0, -2), currentPolygonCoordinates[0]],\n\t\t\tUpdateTypes.Finish,\n\t\t);\n\n\t\tif (!updated) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.snappedPointId = undefined;\n\t\tthis.closingPoints.delete();\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(config: BehaviorConfig) {\n\t\tthis.clickBoundingBox = new ClickBoundingBoxBehavior(config);\n\t\tthis.pixelDistance = new PixelDistanceBehavior(config);\n\t\tthis.lineSnapping = new LineSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.coordinateSnapping = new CoordinateSnappingBehavior(\n\t\t\tconfig,\n\t\t\tthis.pixelDistance,\n\t\t\tthis.clickBoundingBox,\n\t\t);\n\t\tthis.closingPoints = new ClosingPointsBehavior(config, this.pixelDistance);\n\n\t\tthis.coordinatePoints = new CoordinatePointBehavior(config);\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\tif (snappedCoordinate) {\n\t\t\tif (this.snappedPointId) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.snappedPointId,\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tconst [snappedPointId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t\t[COMMON_PROPERTIES.SNAPPING_POINT]: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t]);\n\n\t\t\t\tthis.snappedPointId = snappedPointId;\n\t\t\t}\n\n\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\tevent.lat = snappedCoordinate[1];\n\t\t} else if (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else {\n\t\t\tconst { isClosing, isPreviousClosing } =\n\t\t\t\tthis.closingPoints.isClosingPoint(event);\n\n\t\t\tif (isPreviousClosing || isClosing) {\n\t\t\t\tif (this.snappedPointId) {\n\t\t\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\t\t\tthis.snappedPointId = undefined;\n\t\t\t\t}\n\n\t\t\t\tthis.setCursor(this.cursors.close);\n\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tupdatedCoordinates = [\n\t\t\t\t\t...currentPolygonCoordinates.slice(0, -2),\n\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\tthis.updatePolygonGeometry(updatedCoordinates, UpdateTypes.Provisional);\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tif (!this.currentId) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{ id: this.currentId, geometry: updatedGeometry },\n\t\t]);\n\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(this.currentId);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate snapCoordinate(event: TerraDrawMouseEvent): undefined | Position {\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.snapping?.toLine) {\n\t\t\tlet snapped: Position | undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped = this.lineSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCoordinate) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\t\t\tif (this.currentId) {\n\t\t\t\tsnapped = this.coordinateSnapping.getSnappableCoordinate(\n\t\t\t\t\tevent,\n\t\t\t\t\tthis.currentId,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsnapped =\n\t\t\t\t\tthis.coordinateSnapping.getSnappableCoordinateFirstClick(event);\n\t\t\t}\n\n\t\t\tif (snapped) {\n\t\t\t\tsnappedCoordinate = snapped;\n\t\t\t}\n\t\t}\n\n\t\tif (this.snapping?.toCustom) {\n\t\t\tsnappedCoordinate = this.snapping.toCustom(event, {\n\t\t\t\tcurrentCoordinate: this.currentCoordinate,\n\t\t\t\tcurrentId: this.currentId,\n\t\t\t\tgetCurrentGeometrySnapshot: this.currentId\n\t\t\t\t\t? () =>\n\t\t\t\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId as FeatureId)\n\t\t\t\t\t: () => null,\n\t\t\t\tproject: this.project,\n\t\t\t\tunproject: this.unproject,\n\t\t\t});\n\t\t}\n\n\t\treturn snappedCoordinate;\n\t}\n\n\tprivate polygonFilter(feature: Feature) {\n\t\treturn Boolean(\n\t\t\tfeature.geometry.type === \"Polygon\" &&\n\t\t\t\tfeature.properties &&\n\t\t\t\tfeature.properties.mode === this.mode,\n\t\t);\n\t}\n\n\tprivate onRightClick(event: TerraDrawMouseEvent) {\n\t\t// Right click is only relevant when editable is true\n\t\tif (!this.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { featureId, featureCoordinateIndex: coordinateIndex } =\n\t\t\tthis.coordinateSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\tif (!featureId || coordinateIndex === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(featureId);\n\n\t\tlet coordinates;\n\t\tif (geometry.type === \"Polygon\") {\n\t\t\tcoordinates = geometry.coordinates[0];\n\n\t\t\t// Prevent creating an invalid polygon\n\t\t\tif (coordinates.length <= 4) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isFinalPolygonCoordinate =\n\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t(coordinateIndex === 0 || coordinateIndex === coordinates.length - 1);\n\n\t\tif (isFinalPolygonCoordinate) {\n\t\t\t// Deleting the final coordinate in a polygon breaks it\n\t\t\t// because GeoJSON expects a duplicate, so we need to fix\n\t\t\t// it by adding the new first coordinate to the end\n\t\t\tcoordinates.shift();\n\t\t\tcoordinates.pop();\n\t\t\tcoordinates.push([coordinates[0][0], coordinates[0][1]]);\n\t\t} else {\n\t\t\t// Remove coordinate from array\n\t\t\tcoordinates.splice(coordinateIndex, 1);\n\t\t}\n\n\t\t// Validate the new geometry\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\tid: featureId,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Commit,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// The geometry has changed, so if we were snapped to a point we need to remove it\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: featureId,\n\t\t\t\tgeometry,\n\t\t\t},\n\t\t]);\n\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(featureId);\n\t\t}\n\n\t\tthis.onFinish(featureId, { mode: this.mode, action: \"edit\" });\n\t}\n\n\tprivate onLeftClick(event: TerraDrawMouseEvent) {\n\t\t// Reset the snapping point\n\t\tif (this.snappedPointId) {\n\t\t\tthis.store.delete([this.snappedPointId]);\n\t\t\tthis.snappedPointId = undefined;\n\t\t}\n\n\t\tif (this.currentCoordinate === 0) {\n\t\t\tconst snappedCoordinate = this.snapCoordinate(event);\n\n\t\t\tif (snappedCoordinate) {\n\t\t\t\tevent.lng = snappedCoordinate[0];\n\t\t\t\tevent.lat = snappedCoordinate[1];\n\t\t\t}\n\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (event.button === \"left\") {\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.editable) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet snappedCoordinate: Position | undefined = undefined;\n\n\t\tif (this.state === \"started\") {\n\t\t\tconst lineSnapped = this.lineSnapping.getSnappable(event, (feature) =>\n\t\t\t\tthis.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (lineSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"line\";\n\t\t\t\tthis.editedFeatureCoordinateIndex = lineSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = lineSnapped.featureId;\n\t\t\t\tsnappedCoordinate = lineSnapped.coordinate;\n\t\t\t}\n\n\t\t\tconst coordinateSnapped = this.coordinateSnapping.getSnappable(\n\t\t\t\tevent,\n\t\t\t\t(feature) => this.polygonFilter(feature),\n\t\t\t);\n\n\t\t\tif (coordinateSnapped.coordinate) {\n\t\t\t\tthis.editedSnapType = \"coordinate\";\n\t\t\t\tthis.editedFeatureCoordinateIndex =\n\t\t\t\t\tcoordinateSnapped.featureCoordinateIndex;\n\t\t\t\tthis.editedFeatureId = coordinateSnapped.featureId;\n\t\t\t\tsnappedCoordinate = coordinateSnapped.coordinate;\n\t\t\t}\n\t\t}\n\n\t\t// We only need to stop the map dragging if\n\t\t// we actually have something selected\n\t\tif (!this.editedFeatureId || !snappedCoordinate) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create a point to drag when editing\n\t\tif (!this.editedPointId) {\n\t\t\tconst [editedPointId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Point\",\n\t\t\t\t\t\tcoordinates: snappedCoordinate,\n\t\t\t\t\t},\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t\t[COMMON_PROPERTIES.EDITED]: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t]);\n\n\t\t\tthis.editedPointId = editedPointId;\n\t\t}\n\n\t\t// Drag Feature\n\t\tthis.setCursor(this.cursors.dragStart);\n\n\t\tsetMapDraggability(false);\n\t}\n\n\t/** @internal */\n\tonDrag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\n\t\tif (\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\n\t\tsetMapDraggability(true);\n\t}\n\n\t/** @internal */\n\tonDragEnd(\n\t\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 10;\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 = 35;\n\t\t\t\t} else if (coordinatePoint) {\n\t\t\t\t\tstyles.zIndex = 25;\n\t\t\t\t} else {\n\t\t\t\t\tstyles.zIndex = 30;\n\t\t\t\t}\n\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tafterFeatureAdded(feature: GeoJSONStoreFeatures) {\n\t\tif (this.showCoordinatePoints) {\n\t\t\tthis.coordinatePoints.createOrUpdate(feature.id as FeatureId);\n\t\t}\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidatePolygonFeature(baseValidatedFeature, this.coordinatePrecision),\n\t\t);\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\n\nexport function createPolygon(\n\tcoordinates: Position[][] = [\n\t\t[\n\t\t\t[0, 0],\n\t\t\t[0, 1],\n\t\t\t[1, 1],\n\t\t\t[1, 0],\n\t\t\t[0, 0],\n\t\t],\n\t],\n): Feature<Polygon> {\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates,\n\t\t},\n\t\tproperties: {},\n\t};\n}\n\nexport function createLineString(coordinates: Position[]): Feature<LineString> {\n\treturn {\n\t\ttype: \"Feature\",\n\t\tgeometry: {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates,\n\t\t},\n\t\tproperties: {},\n\t};\n}\n","import { Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n} from \"../../common\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawRectangleModeKeyEvents = {\n\tcancel: KeyboardEvent[\"key\"] | null;\n\tfinish: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype RectanglePolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n} as Required<Cursors>;\n\ninterface TerraDrawRectangleModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tkeyEvents?: TerraDrawRectangleModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawRectangleMode extends TerraDrawBaseDrawMode<RectanglePolygonStyling> {\n\tmode = \"rectangle\" as const;\n\tprivate center: Position | undefined;\n\tprivate clickCount = 0;\n\tprivate currentRectangleId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawRectangleModeKeyEvents = defaultKeyEvents;\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\n\tconstructor(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawRectangleModeOptions<RectanglePolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate updateRectangle(event: TerraDrawMouseEvent, updateType: UpdateTypes) {\n\t\tif (this.clickCount === 1 && this.center && this.currentRectangleId) {\n\t\t\tconst geometry = this.store.getGeometryCopy(this.currentRectangleId);\n\n\t\t\tconst firstCoord = (geometry.coordinates as Position[][])[0][0];\n\n\t\t\tconst newGeometry = {\n\t\t\t\ttype: \"Polygon\",\n\t\t\t\tcoordinates: [\n\t\t\t\t\t[\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t\t[event.lng, firstCoord[1]],\n\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t[firstCoord[0], event.lat],\n\t\t\t\t\t\tfirstCoord,\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t} as Polygon;\n\n\t\t\tif (this.validate) {\n\t\t\t\tconst validationResult = this.validate(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.project,\n\t\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\t\tupdateType,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!validationResult.valid) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{\n\t\t\t\t\tid: this.currentRectangleId,\n\t\t\t\t\tgeometry: newGeometry,\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tconst finishedId = this.currentRectangleId;\n\n\t\t// Fix right hand rule if necessary\n\t\tif (finishedId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(finishedId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: finishedId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.center = undefined;\n\t\tthis.currentRectangleId = undefined;\n\t\tthis.clickCount = 0;\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedId !== undefined) {\n\t\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\tif (this.clickCount === 0) {\n\t\t\tthis.center = [event.lng, event.lat];\n\t\t\tconst [createdId] = 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},\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentRectangleId = createdId;\n\t\t\tthis.clickCount++;\n\t\t\tthis.setDrawing();\n\t\t} else {\n\t\t\tthis.updateRectangle(event, UpdateTypes.Finish);\n\t\t\t// Finish drawing\n\t\t\tthis.close();\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 = 10;\n\n\t\t\treturn styles;\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tHexColorStyling,\n\tNumericStyling,\n\tTerraDrawAdapterStyling,\n} from \"../../common\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n} from \"../base.mode\";\nimport { BehaviorConfig } from \"../base.behavior\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { GeoJSONStoreFeatures } from \"../../terra-draw\";\nimport { ValidatePointFeature } from \"../../validations/point.validation\";\nimport { ValidatePolygonFeature } from \"../../validations/polygon.validation\";\nimport { ValidateLineStringFeature } from \"../../validations/linestring.validation\";\nimport { StoreValidation } from \"../../store/store\";\n\ntype RenderModeStyling = {\n\tpointColor: HexColorStyling;\n\tpointWidth: NumericStyling;\n\tpointOutlineColor: HexColorStyling;\n\tpointOutlineWidth: NumericStyling;\n\tpolygonFillColor: HexColorStyling;\n\tpolygonFillOpacity: NumericStyling;\n\tpolygonOutlineColor: HexColorStyling;\n\tpolygonOutlineWidth: NumericStyling;\n\tlineStringWidth: NumericStyling;\n\tlineStringColor: HexColorStyling;\n\tzIndex: NumericStyling;\n};\n\ninterface TerraDrawRenderModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tmodeName?: string;\n\t// styles need to be there else we could fall back to BaseModeOptions\n\tstyles: Partial<T>;\n}\n\nexport class TerraDrawRenderMode extends TerraDrawBaseDrawMode<RenderModeStyling> {\n\tpublic type = ModeTypes.Render; // The type of the mode\n\tpublic mode = \"render\"; // This gets changed dynamically\n\n\tconstructor(options: TerraDrawRenderModeOptions<RenderModeStyling>) {\n\t\tif (!options.modeName) {\n\t\t\tthrow new Error(\"Mode name is required for TerraDrawRenderMode\");\n\t\t}\n\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\tupdateOptions(\n\t\toptions?: TerraDrawRenderModeOptions<RenderModeStyling> | undefined,\n\t): void {\n\t\tsuper.updateOptions(options);\n\t\tif (options?.modeName) {\n\t\t\tthis.mode = options.modeName;\n\t\t}\n\t}\n\n\t/** @internal */\n\tregisterBehaviors(behaviorConfig: BehaviorConfig) {\n\t\t// TODO: this is probably abusing\n\t\t// registerBehaviors but it works quite well conceptually\n\n\t\t// We can set the mode name dynamically\n\t\tthis.mode = behaviorConfig.mode;\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.setStopped();\n\t}\n\n\t/** @internal */\n\tonKeyUp() {}\n\n\t/** @internal */\n\tonKeyDown() {}\n\n\t/** @internal */\n\tonClick() {}\n\n\t/** @internal */\n\tonDragStart() {}\n\n\t/** @internal */\n\tonDrag() {}\n\n\t/** @internal */\n\tonDragEnd() {}\n\n\t/** @internal */\n\tonMouseMove() {}\n\n\t/** @internal */\n\tcleanUp() {}\n\n\t/** @internal */\n\tstyleFeature(feature: GeoJSONStoreFeatures): TerraDrawAdapterStyling {\n\t\tconst defaultStyles = getDefaultStyling();\n\n\t\treturn {\n\t\t\tpointColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointColor,\n\t\t\t\tdefaultStyles.pointColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointWidth,\n\t\t\t\tdefaultStyles.pointWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.pointOutlineColor,\n\t\t\t\tdefaultStyles.pointOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpointOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.pointOutlineWidth,\n\t\t\t\tdefaultStyles.pointOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonFillColor,\n\t\t\t\tdefaultStyles.polygonFillColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonFillOpacity: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonFillOpacity,\n\t\t\t\tdefaultStyles.polygonFillOpacity,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.polygonOutlineColor,\n\t\t\t\tdefaultStyles.polygonOutlineColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tpolygonOutlineWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.polygonOutlineWidth,\n\t\t\t\tdefaultStyles.polygonOutlineWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringWidth: this.getNumericStylingValue(\n\t\t\t\tthis.styles.lineStringWidth,\n\t\t\t\tdefaultStyles.lineStringWidth,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tlineStringColor: this.getHexColorStylingValue(\n\t\t\t\tthis.styles.lineStringColor,\n\t\t\t\tdefaultStyles.lineStringColor,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t\tzIndex: this.getNumericStylingValue(\n\t\t\t\tthis.styles.zIndex,\n\t\t\t\tdefaultStyles.zIndex,\n\t\t\t\tfeature,\n\t\t\t),\n\t\t};\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\tconst validationResult = super.validateFeature(feature);\n\t\tif (validationResult.valid) {\n\t\t\tconst validatedFeature = feature as GeoJSONStoreFeatures;\n\n\t\t\tconst featureIsValid =\n\t\t\t\tValidatePointFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidatePolygonFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid ||\n\t\t\t\tValidateLineStringFeature(validatedFeature, this.coordinatePrecision)\n\t\t\t\t\t.valid;\n\n\t\t\tif (featureIsValid) {\n\t\t\t\treturn { valid: true };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tvalid: featureIsValid,\n\t\t\t\treason: \"Feature is not a valid Point, Polygon or LineString feature\",\n\t\t\t};\n\t\t}\n\n\t\treturn validationResult;\n\t}\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, radiansToDegrees } from \"../helpers\";\n\n// Based on Turf.js Rhumb Bearing module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-bearing/index.ts\n\nexport function rhumbBearing(start: Position, end: Position): number {\n\tconst from = start;\n\tconst to = end;\n\n\t// φ => phi\n\t// Δλ => deltaLambda\n\t// Δψ => deltaPsi\n\t// θ => theta\n\tconst phi1 = degreesToRadians(from[1]);\n\tconst phi2 = degreesToRadians(to[1]);\n\tlet deltaLambda = degreesToRadians(to[0] - from[0]);\n\n\t// if deltaLambdaon over 180° take shorter rhumb line across the anti-meridian:\n\tif (deltaLambda > Math.PI) {\n\t\tdeltaLambda -= 2 * Math.PI;\n\t}\n\tif (deltaLambda < -Math.PI) {\n\t\tdeltaLambda += 2 * Math.PI;\n\t}\n\n\tconst deltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\n\tconst theta = Math.atan2(deltaLambda, deltaPsi);\n\n\tconst bear360 = (radiansToDegrees(theta) + 360) % 360;\n\n\tconst bear180 = bear360 > 180 ? -(360 - bear360) : bear360;\n\n\treturn bear180;\n}\n","import { Position } from \"geojson\";\nimport { degreesToRadians, earthRadius } from \"../helpers\";\n\n// Based on @turf/rhumb-destination module which is MIT Licensed\n// https://github.com/Turfjs/turf/blob/master/packages/turf-rhumb-destination/index.ts\n\nexport function rhumbDestination(\n\torigin: Position,\n\tdistanceMeters: number,\n\tbearing: number,\n): Position {\n\tconst wasNegativeDistance = distanceMeters < 0;\n\tlet distanceInMeters = distanceMeters;\n\n\tif (wasNegativeDistance) {\n\t\tdistanceInMeters = -Math.abs(distanceInMeters);\n\t}\n\n\tconst delta = distanceInMeters / earthRadius; // angular distance in radians\n\tconst lambda1 = (origin[0] * Math.PI) / 180; // to radians, but without normalize to 𝜋\n\tconst phi1 = degreesToRadians(origin[1]);\n\tconst theta = degreesToRadians(bearing);\n\n\tconst DeltaPhi = delta * Math.cos(theta);\n\tlet phi2 = phi1 + DeltaPhi;\n\n\t// check for going past the pole, normalise latitude if so\n\tif (Math.abs(phi2) > Math.PI / 2) {\n\t\tphi2 = phi2 > 0 ? Math.PI - phi2 : -Math.PI - phi2;\n\t}\n\n\tconst DeltaPsi = Math.log(\n\t\tMath.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi1 / 2 + Math.PI / 4),\n\t);\n\t// E-W course becomes ill-conditioned with 0/0\n\tconst q = Math.abs(DeltaPsi) > 10e-12 ? DeltaPhi / DeltaPsi : Math.cos(phi1);\n\n\tconst DeltaLambda = (delta * Math.sin(theta)) / q;\n\tconst lambda2 = lambda1 + DeltaLambda;\n\n\t// normalise to −180..+180°\n\tconst destination = [\n\t\t(((lambda2 * 180) / Math.PI + 540) % 360) - 180,\n\t\t(phi2 * 180) / Math.PI,\n\t];\n\n\t// compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html)\n\t// solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678\n\tdestination[0] +=\n\t\tdestination[0] - origin[0] > 180\n\t\t\t? -360\n\t\t\t: origin[0] - destination[0] > 180\n\t\t\t\t? 360\n\t\t\t\t: 0;\n\treturn destination;\n}\n","import { Position } from \"geojson\";\nimport { limitPrecision } from \"./limit-decimal-precision\";\nimport { Project, Unproject } from \"../common\";\nimport { haversineDistanceKilometers } from \"./measure/haversine-distance\";\nimport { rhumbBearing } from \"./measure/rhumb-bearing\";\nimport { rhumbDestination } from \"./measure/rhumb-destination\";\n\n// midpointCoordinate is adapted from the @turf/midpoint which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-midpoint\n\nexport function midpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n) {\n\tconst projectedCoordinateOne = project(coordinates1[0], coordinates1[1]);\n\tconst projectedCoordinateTwo = project(coordinates2[0], coordinates2[1]);\n\n\tconst { lng, lat } = unproject(\n\t\t(projectedCoordinateOne.x + projectedCoordinateTwo.x) / 2,\n\t\t(projectedCoordinateOne.y + projectedCoordinateTwo.y) / 2,\n\t);\n\n\treturn [limitPrecision(lng, precision), limitPrecision(lat, precision)];\n}\n\n/* Get the geodesic midpoint coordinate between two coordinates */\nexport function geodesicMidpointCoordinate(\n\tcoordinates1: Position,\n\tcoordinates2: Position,\n\tprecision: number,\n) {\n\tconst dist = haversineDistanceKilometers(coordinates1, coordinates2) * 1000;\n\tconst heading = rhumbBearing(coordinates1, coordinates2);\n\tconst midpoint = rhumbDestination(coordinates1, dist / 2, heading);\n\treturn [\n\t\tlimitPrecision(midpoint[0], precision),\n\t\tlimitPrecision(midpoint[1], precision),\n\t];\n}\n","import { Point, Position } from \"geojson\";\nimport { Project, Projection, Unproject } from \"../common\";\nimport { JSONObject } from \"../store/store\";\nimport {\n\tmidpointCoordinate,\n\tgeodesicMidpointCoordinate,\n} from \"./midpoint-coordinate\";\n\nexport function getMidPointCoordinates({\n\tfeatureCoords,\n\tprecision,\n\tunproject,\n\tproject,\n\tprojection,\n}: {\n\tfeatureCoords: Position[];\n\tprecision: number;\n\tproject: Project;\n\tunproject: Unproject;\n\tprojection: Projection;\n}) {\n\tconst midPointCoords: Position[] = [];\n\tfor (let i = 0; i < featureCoords.length - 1; i++) {\n\t\tlet mid;\n\t\tif (projection === \"web-mercator\") {\n\t\t\tmid = midpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t\tproject,\n\t\t\t\tunproject,\n\t\t\t);\n\t\t} else if (projection === \"globe\") {\n\t\t\tmid = geodesicMidpointCoordinate(\n\t\t\t\tfeatureCoords[i],\n\t\t\t\tfeatureCoords[i + 1],\n\t\t\t\tprecision,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid projection\");\n\t\t}\n\n\t\tmidPointCoords.push(mid);\n\t}\n\treturn midPointCoords;\n}\n\nexport function getMidPoints(\n\tselectedCoords: Position[],\n\tproperties: (index: number) => JSONObject,\n\tprecision: number,\n\tproject: Project,\n\tunproject: Unproject,\n\tprojection: Projection,\n) {\n\treturn getMidPointCoordinates({\n\t\tfeatureCoords: selectedCoords,\n\t\tprecision,\n\t\tproject,\n\t\tunproject,\n\t\tprojection,\n\t}).map((coord, i) => ({\n\t\tgeometry: { type: \"Point\", coordinates: coord } as Point,\n\t\tproperties: properties(i),\n\t}));\n}\n","import { LineString, Point, Polygon, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport {\n\tgetMidPointCoordinates,\n\tgetMidPoints,\n} from \"../../../geometry/get-midpoints\";\nimport { SelectionPointBehavior } from \"./selection-point.behavior\";\nimport {\n\tCOMMON_PROPERTIES,\n\tProjection,\n\tSELECT_PROPERTIES,\n} from \"../../../common\";\nimport { FeatureId } from \"../../../store/store\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport class MidPointBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly selectionPointBehavior: SelectionPointBehavior,\n\t\tprivate readonly coordinatePointBehavior: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate _midPoints: string[] = [];\n\n\tget ids() {\n\t\treturn this._midPoints.concat();\n\t}\n\n\tset ids(_: string[]) {}\n\n\tpublic insert(\n\t\tfeatureId: FeatureId,\n\t\tmidPointId: FeatureId,\n\t\tcoordinatePrecision: number,\n\t) {\n\t\tconst midPoint = this.store.getGeometryCopy(midPointId);\n\t\tconst { midPointFeatureId, midPointSegment } =\n\t\t\tthis.store.getPropertiesCopy(midPointId);\n\t\tconst geometry = this.store.getGeometryCopy<Polygon | LineString>(\n\t\t\tmidPointFeatureId as FeatureId,\n\t\t);\n\n\t\t// Update the coordinates to include inserted midpoint\n\t\tconst updatedCoordinates =\n\t\t\tgeometry.type === \"Polygon\"\n\t\t\t\t? geometry.coordinates[0]\n\t\t\t\t: geometry.coordinates;\n\n\t\tupdatedCoordinates.splice(\n\t\t\t(midPointSegment as number) + 1,\n\t\t\t0,\n\t\t\tmidPoint.coordinates as Position,\n\t\t);\n\n\t\t// Update geometry coordinates depending\n\t\t// on if a polygon or linestring\n\t\tgeometry.coordinates =\n\t\t\tgeometry.type === \"Polygon\" ? [updatedCoordinates] : updatedCoordinates;\n\n\t\t// Update the selected features geometry to insert\n\t\t// the new midpoint\n\t\tthis.store.updateGeometry([{ id: midPointFeatureId as string, geometry }]);\n\n\t\t// We need to update the coordinate points to reflect the new midpoint\n\t\tconst featureProperties = this.store.getPropertiesCopy(featureId as string);\n\n\t\tif (featureProperties[COMMON_PROPERTIES.COORDINATE_POINT_IDS]) {\n\t\t\tthis.coordinatePointBehavior.createOrUpdate(featureId);\n\t\t}\n\n\t\t// TODO: is there a way of just updating the selection points rather\n\t\t// than fully deleting / recreating?\n\t\t// Recreate the selection points\n\n\t\tthis.store.delete([...this._midPoints, ...this.selectionPointBehavior.ids]);\n\n\t\t// We don't need to check if flags are correct\n\t\t// because selection points are prerequisite for midpoints\n\t\tthis.create(\n\t\t\tupdatedCoordinates,\n\t\t\tmidPointFeatureId as string,\n\t\t\tcoordinatePrecision,\n\t\t);\n\t\tthis.selectionPointBehavior.create(\n\t\t\tupdatedCoordinates,\n\t\t\tgeometry.type,\n\t\t\tmidPointFeatureId as string,\n\t\t);\n\t}\n\n\tpublic create(\n\t\tselectedCoords: Position[],\n\t\tfeatureId: FeatureId,\n\t\tcoordinatePrecision: number,\n\t) {\n\t\tif (!this.store.has(featureId)) {\n\t\t\tthrow new Error(\"Store does not have feature with this id\");\n\t\t}\n\n\t\tthis._midPoints = this.store.create(\n\t\t\tgetMidPoints(\n\t\t\t\tselectedCoords,\n\t\t\t\t(i) => ({\n\t\t\t\t\tmode: this.mode,\n\t\t\t\t\t[SELECT_PROPERTIES.MID_POINT]: true,\n\t\t\t\t\tmidPointSegment: i,\n\t\t\t\t\tmidPointFeatureId: featureId,\n\t\t\t\t}),\n\t\t\t\tcoordinatePrecision,\n\t\t\t\tthis.config.project,\n\t\t\t\tthis.config.unproject,\n\t\t\t\tthis.projection,\n\t\t\t),\n\t\t);\n\t}\n\n\tpublic delete() {\n\t\tif (this._midPoints.length) {\n\t\t\tthis.store.delete(this._midPoints);\n\t\t\tthis._midPoints = [];\n\t\t}\n\t}\n\n\tpublic getUpdated(updatedCoordinates: Position[]) {\n\t\tif (this._midPoints.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn getMidPointCoordinates({\n\t\t\tfeatureCoords: updatedCoordinates,\n\t\t\tprecision: this.coordinatePrecision,\n\t\t\tproject: this.config.project,\n\t\t\tunproject: this.config.unproject,\n\t\t\tprojection: this.config.projection as Projection,\n\t\t}).map((updatedMidPointCoord, i) => ({\n\t\t\tid: this._midPoints[i] as string,\n\t\t\tgeometry: {\n\t\t\t\ttype: \"Point\",\n\t\t\t\tcoordinates: updatedMidPointCoord,\n\t\t\t} as Point,\n\t\t}));\n\t}\n}\n","import { LineString, Point, Polygon, Position } from \"geojson\";\nimport { BehaviorConfig, TerraDrawModeBehavior } from \"../../base.behavior\";\nimport { getCoordinatesAsPoints } from \"../../../geometry/get-coordinates-as-points\";\nimport { FeatureId } from \"../../../store/store\";\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\tselectionPoint: true,\n\t\t\t\tselectionPointFeatureId: featureId,\n\t\t\t\tindex: i,\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(\n\tselectedCoords: Position[],\n\tgeometryType: \"Polygon\" | \"LineString\",\n\tproperties: (index: number) => JSONObject,\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 { TerraDrawMouseEvent, UpdateTypes, Validation } 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 } from \"../../../store/store\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\nimport { CoordinateSnappingBehavior } from \"../../coordinate-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) {\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\tpublic drag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tallowSelfIntersection: boolean,\n\t\tvalidateFeature: Validation,\n\t\tsnapping: boolean,\n\t): boolean {\n\t\tif (this.draggedCoordinate.id === null) {\n\t\t\treturn false;\n\t\t}\n\t\tconst index = this.draggedCoordinate.index;\n\t\tconst geometry = this.store.getGeometryCopy(this.draggedCoordinate.id);\n\t\tconst properties = this.store.getPropertiesCopy(this.draggedCoordinate.id);\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\t// Store the updated coord\n\t\tlet updatedCoordinate = [event.lng, event.lat];\n\n\t\t// When we are snapping find the nearest coordinate of the same mode\n\t\t// that is not the one we are dragging\n\t\tif (snapping) {\n\t\t\tlet snapped: Position | undefined = undefined;\n\n\t\t\tsnapped = this.coordinateSnapping.getSnappable(event, (feature) => {\n\t\t\t\treturn Boolean(\n\t\t\t\t\tfeature.properties &&\n\t\t\t\t\tfeature.properties.mode === properties.mode &&\n\t\t\t\t\tfeature.id !== this.draggedCoordinate.id,\n\t\t\t\t);\n\t\t\t}).coordinate;\n\n\t\t\tif (snapped) {\n\t\t\t\tupdatedCoordinate = snapped;\n\t\t\t}\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(\n\t\t\t\tthis.draggedCoordinate.id,\n\t\t\t\tgeomCoordinates,\n\t\t\t) || [];\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(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tid: this.draggedCoordinate.id,\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.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\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: this.draggedCoordinate.id,\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 { 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 { 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 { TerraDrawMouseEvent, UpdateTypes, Validation } 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\n\treset() {\n\t\tthis.lastBearing = undefined;\n\t}\n\n\trotate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t\tvalidateFeature?: Validation,\n\t) {\n\t\tconst geometry = this.store.getGeometryCopy<LineString | Polygon>(\n\t\t\tselectedId,\n\t\t);\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\tconst centerWebMercator = webMercatorCentroid(feature);\n\t\t\tconst cursorWebMercator = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\tbearing = webMercatorBearing(centerWebMercator, cursorWebMercator);\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\tbearing = rhumbBearing(\n\t\t\t\tcentroid({ type: \"Feature\", geometry, properties: {} }),\n\t\t\t\tmouseCoord,\n\t\t\t);\n\n\t\t\t// We need an original bearing to compare against\n\t\t\tif (!this.lastBearing) {\n\t\t\t\tthis.lastBearing = bearing + 180;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst angle = this.lastBearing - (bearing + 180);\n\n\t\t\ttransformRotate(feature, -angle);\n\t\t} else {\n\t\t\tthrow new Error(\"Unsupported projection\");\n\t\t}\n\n\t\t// Coordinates are either polygon or linestring at this point\n\t\tconst updatedCoords: Position[] =\n\t\t\tgeometry.type === \"Polygon\"\n\t\t\t\t? geometry.coordinates[0]\n\t\t\t\t: geometry.coordinates;\n\n\t\t// Ensure that coordinate precision is maintained\n\t\tupdatedCoords.forEach((coordinate) => {\n\t\t\tcoordinate[0] = limitPrecision(coordinate[0], this.coordinatePrecision);\n\t\t\tcoordinate[1] = limitPrecision(coordinate[1], this.coordinatePrecision);\n\t\t});\n\n\t\tconst updatedMidPoints = this.midPoints.getUpdated(updatedCoords) || [];\n\n\t\tconst updatedSelectionPoints =\n\t\t\tthis.selectionPoints.getUpdated(updatedCoords) || [];\n\n\t\tconst updatedCoordinatePoints =\n\t\t\tthis.coordinatePoints.getUpdated(selectedId, updatedCoords) || [];\n\n\t\tif (validateFeature) {\n\t\t\tif (\n\t\t\t\t!validateFeature(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: selectedId,\n\t\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\t\tgeometry,\n\t\t\t\t\t\tproperties: {},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tproject: this.config.project,\n\t\t\t\t\t\tunproject: this.config.unproject,\n\t\t\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Issue the update to the selected feature\n\t\tthis.store.updateGeometry([\n\t\t\t{ id: selectedId, geometry },\n\t\t\t...updatedSelectionPoints,\n\t\t\t...updatedMidPoints,\n\t\t\t...updatedCoordinatePoints,\n\t\t]);\n\n\t\tif (this.projection === \"web-mercator\") {\n\t\t\tthis.lastBearing = bearing;\n\t\t} else if (this.projection === \"globe\") {\n\t\t\tthis.lastBearing = bearing + 180;\n\t\t}\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\nimport { centroid } from \"../centroid\";\nimport { rhumbBearing } from \"../measure/rhumb-bearing\";\nimport { rhumbDestination } from \"../measure/rhumb-destination\";\nimport { rhumbDistance } from \"../measure/rhumb-distance\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../project/web-mercator\";\nimport { CartesianPoint } from \"../../common\";\n\n// Adapted on @turf/transform-rotate module which is MIT licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-transform-rotate\n\nexport function transformRotate(\n\tfeature: Feature<Polygon | LineString>,\n\tangle: number,\n) {\n\t// Shortcut no-rotation\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\t// Use centroid of GeoJSON if pivot is not provided\n\tconst pivot = centroid(feature);\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\n\tcoordinates.forEach((pointCoords: Position) => {\n\t\tconst initialAngle = rhumbBearing(pivot, pointCoords);\n\t\tconst finalAngle = initialAngle + angle;\n\t\tconst distance = rhumbDistance(pivot, pointCoords);\n\t\tconst newCoords = rhumbDestination(pivot, distance, finalAngle);\n\t\tpointCoords[0] = newCoords[0];\n\t\tpointCoords[1] = newCoords[1];\n\t});\n\n\treturn feature;\n}\n\n/**\n * Rotate a GeoJSON Polygon geometry in web mercator\n * @param polygon - GeoJSON Polygon geometry\n * @param angle - rotation angle in degrees\n * @returns - rotated GeoJSON Polygon geometry\n */\nexport const transformRotateWebMercator = (\n\tfeature: Feature<Polygon> | Feature<LineString>,\n\tangle: number,\n) => {\n\tif (angle === 0 || angle === 360 || angle === -360) {\n\t\treturn feature;\n\t}\n\n\tconst DEGREES_TO_RADIANS = 0.017453292519943295 as const; // Math.PI / 180\n\n\tconst coordinates =\n\t\tfeature.geometry.type === \"Polygon\"\n\t\t\t? feature.geometry.coordinates[0]\n\t\t\t: feature.geometry.coordinates;\n\tconst angleRad = angle * DEGREES_TO_RADIANS;\n\n\t// Convert polygon coordinates to Web Mercator\n\tconst webMercatorCoords = coordinates.map(([lng, lat]) =>\n\t\tlngLatToWebMercatorXY(lng, lat),\n\t);\n\n\t// Find centroid of the polygon in Web Mercator\n\tconst centroid = webMercatorCoords.reduce(\n\t\t(acc: CartesianPoint, coord: CartesianPoint) => ({\n\t\t\tx: acc.x + coord.x,\n\t\t\ty: acc.y + coord.y,\n\t\t}),\n\t\t{ x: 0, y: 0 },\n\t);\n\tcentroid.x /= webMercatorCoords.length;\n\tcentroid.y /= webMercatorCoords.length;\n\n\t// Rotate the coordinates around the centroid\n\tconst rotatedWebMercatorCoords = webMercatorCoords.map((coord) => ({\n\t\tx:\n\t\t\tcentroid.x +\n\t\t\t(coord.x - centroid.x) * Math.cos(angleRad) -\n\t\t\t(coord.y - centroid.y) * Math.sin(angleRad),\n\t\ty:\n\t\t\tcentroid.y +\n\t\t\t(coord.x - centroid.x) * Math.sin(angleRad) +\n\t\t\t(coord.y - centroid.y) * Math.cos(angleRad),\n\t}));\n\n\t// Convert rotated Web Mercator coordinates back to geographic\n\tconst rotatedCoordinates = rotatedWebMercatorCoords.map(\n\t\t({ x, y }) =>\n\t\t\t[\n\t\t\t\twebMercatorXYToLngLat(x, y).lng,\n\t\t\t\twebMercatorXYToLngLat(x, y).lat,\n\t\t\t] as Position,\n\t);\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tfeature.geometry.coordinates[0] = rotatedCoordinates;\n\t} else {\n\t\tfeature.geometry.coordinates = rotatedCoordinates;\n\t}\n\n\treturn feature;\n};\n","import { TerraDrawMouseEvent, UpdateTypes, Validation } 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 { centroid } from \"../../../geometry/centroid\";\nimport { haversineDistanceKilometers } from \"../../../geometry/measure/haversine-distance\";\nimport {\n\ttransformScale,\n\ttransformScaleWebMercator,\n} from \"../../../geometry/transform/scale\";\nimport { limitPrecision } from \"../../../geometry/limit-decimal-precision\";\nimport { FeatureId } from \"../../../store/store\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../../geometry/measure/pixel-distance\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport class ScaleFeatureBehavior 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 lastDistance: number | undefined;\n\n\treset() {\n\t\tthis.lastDistance = undefined;\n\t}\n\n\tscale(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t\tvalidateFeature?: Validation,\n\t) {\n\t\tconst geometry = this.store.getGeometryCopy<LineString | Polygon>(\n\t\t\tselectedId,\n\t\t);\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\tconst feature = { type: \"Feature\", geometry, properties: {} } as Feature<\n\t\t\tPolygon | LineString\n\t\t>;\n\n\t\tlet distance;\n\n\t\tconst originWebMercator = webMercatorCentroid(feature);\n\n\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\tconst selectedWebMercator = lngLatToWebMercatorXY(event.lng, event.lat);\n\t\t\tdistance = cartesianDistance(originWebMercator, selectedWebMercator);\n\t\t} else if (this.config.projection === \"globe\") {\n\t\t\tdistance = haversineDistanceKilometers(\n\t\t\t\tcentroid({ type: \"Feature\", geometry, properties: {} }),\n\t\t\t\tmouseCoord,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new Error(\"Invalid projection\");\n\t\t}\n\n\t\t// We need an original bearing to compare against\n\t\tif (!this.lastDistance) {\n\t\t\tthis.lastDistance = distance;\n\t\t\treturn;\n\t\t}\n\n\t\tconst scale = 1 - (this.lastDistance - distance) / distance;\n\n\t\tif (this.config.projection === \"web-mercator\") {\n\t\t\tconst { lng, lat } = webMercatorXYToLngLat(\n\t\t\t\toriginWebMercator.x,\n\t\t\t\toriginWebMercator.y,\n\t\t\t);\n\t\t\ttransformScaleWebMercator(feature, scale, [lng, lat]);\n\t\t} else if (this.config.projection === \"globe\") {\n\t\t\tconst origin = centroid(feature);\n\t\t\ttransformScale(feature, scale, origin);\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\tthis.lastDistance = distance;\n\t}\n}\n","import { Feature, LineString, Polygon, Position } from \"geojson\";\n// import { 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\";\n\n// Adapted from the @turf/transform-scale module which is MIT Licensed\n// https://github.com/Turfjs/turf/tree/master/packages/turf-transform-scale\n\nexport function transformScale(\n\tfeature: Feature<Polygon | LineString>,\n\tfactor: number,\n\torigin: Position,\n\taxis: \"x\" | \"y\" | \"xy\" = \"xy\",\n) {\n\t// Shortcut no-scaling\n\tif (factor === 1) {\n\t\treturn feature;\n\t}\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 originalDistance = rhumbDistance(origin, pointCoords);\n\t\tconst bearing = rhumbBearing(origin, pointCoords);\n\t\tconst newDistance = originalDistance * factor;\n\t\tconst newCoord = rhumbDestination(origin, newDistance, bearing);\n\n\t\tif (axis === \"x\" || axis === \"xy\") {\n\t\t\tpointCoords[0] = newCoord[0];\n\t\t}\n\n\t\tif (axis === \"y\" || axis === \"xy\") {\n\t\t\tpointCoords[1] = newCoord[1];\n\t\t}\n\t});\n\n\treturn feature;\n}\n\n/**\n * Scale a GeoJSON Polygon geometry in web mercator\n * @param polygon - GeoJSON Polygon geometry\n * @param scale - scaling factor\n * @returns - scaled GeoJSON Polygon geometry\n */\nexport function transformScaleWebMercator(\n\tfeature: Feature<Polygon | LineString>,\n\tfactor: number,\n\torigin: Position,\n): Feature<Polygon | LineString> {\n\tif (factor === 1) {\n\t\treturn feature;\n\t}\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\t// Convert polygon coordinates to Web Mercator\n\tconst webMercatorCoords = coordinates.map(([lng, lat]) =>\n\t\tlngLatToWebMercatorXY(lng, lat),\n\t);\n\n\tconst originWebMercator = lngLatToWebMercatorXY(origin[0], origin[1]);\n\n\t// Scale the coordinates around the centroid\n\tconst scaledWebMercatorCoords = webMercatorCoords.map((coord) => ({\n\t\tx: originWebMercator.x + (coord.x - originWebMercator.x) * factor,\n\t\ty: originWebMercator.y + (coord.y - originWebMercator.y) * factor,\n\t}));\n\n\t// Convert scaled Web Mercator coordinates back to geographic\n\tconst scaledCoordinates = scaledWebMercatorCoords.map(({ x, y }) => [\n\t\twebMercatorXYToLngLat(x, y).lng,\n\t\twebMercatorXYToLngLat(x, y).lat,\n\t]);\n\n\tif (feature.geometry.type === \"Polygon\") {\n\t\tfeature.geometry.coordinates[0] = scaledCoordinates;\n\t} else {\n\t\tfeature.geometry.coordinates = scaledCoordinates;\n\t}\n\n\treturn feature;\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 {\n\tcoordinateIsValid,\n\tcoordinatePrecisionIsValid,\n} from \"../../../geometry/boolean/is-valid-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../../geometry/project/web-mercator\";\nimport { webMercatorCentroid } from \"../../../geometry/web-mercator-centroid\";\nimport { CoordinatePointBehavior } from \"./coordinate-point.behavior\";\n\nexport type ResizeOptions =\n\t| \"center\"\n\t| \"opposite\"\n\t| \"center-fixed\"\n\t| \"opposite-fixed\";\n\ntype BoundingBoxIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;\n\ntype BoundingBox = readonly [\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n\tnumber[],\n];\n\nexport class DragCoordinateResizeBehavior extends TerraDrawModeBehavior {\n\tconstructor(\n\t\treadonly config: BehaviorConfig,\n\t\tprivate readonly pixelDistance: PixelDistanceBehavior,\n\t\tprivate readonly selectionPoints: SelectionPointBehavior,\n\t\tprivate readonly midPoints: MidPointBehavior,\n\t\tprivate readonly coordinatePoints: CoordinatePointBehavior,\n\t) {\n\t\tsuper(config);\n\t}\n\n\tprivate minimumScale = 0.0001;\n\n\tprivate draggedCoordinate: { id: null | FeatureId; index: number } = {\n\t\tid: null,\n\t\tindex: -1,\n\t};\n\n\t// This map provides the oppsite corner of the bbox\n\t// to the index of the coordinate provided\n\t// 0 1 2\n\t// *----*----*\n\t// \t |\t\t |\n\t// 7 *\t\t * 3\n\t// |\t\t |\n\t// *----*----*\n\t// \t 6 5 4\n\t//\n\tprivate boundingBoxMaps = {\n\t\topposite: {\n\t\t\t0: 4,\n\t\t\t1: 5,\n\t\t\t2: 6,\n\t\t\t3: 7,\n\t\t\t4: 0,\n\t\t\t5: 1,\n\t\t\t6: 2,\n\t\t\t7: 3,\n\t\t},\n\t};\n\n\tprivate getClosestCoordinate(\n\t\tevent: TerraDrawMouseEvent,\n\t\tgeometry: Polygon | LineString | Point,\n\t) {\n\t\tconst closestCoordinate = {\n\t\t\tdist: Infinity,\n\t\t\tindex: -1,\n\t\t\tisFirstOrLastPolygonCoord: false,\n\t\t};\n\n\t\tlet geomCoordinates: Position[] | undefined;\n\n\t\tif (geometry.type === \"LineString\") {\n\t\t\tgeomCoordinates = geometry.coordinates;\n\t\t} else if (geometry.type === \"Polygon\") {\n\t\t\tgeomCoordinates = geometry.coordinates[0];\n\t\t} else {\n\t\t\t// We don't want to handle dragging\n\t\t\t// points here\n\t\t\treturn closestCoordinate;\n\t\t}\n\n\t\t// Look through the selected features coordinates\n\t\t// and try to find a coordinate that is draggable\n\t\tfor (let i = 0; i < geomCoordinates.length; i++) {\n\t\t\tconst coord = geomCoordinates[i];\n\t\t\tconst distance = this.pixelDistance.measure(event, coord);\n\n\t\t\tif (\n\t\t\t\tdistance < this.pointerDistance &&\n\t\t\t\tdistance < closestCoordinate.dist\n\t\t\t) {\n\t\t\t\t// We don't create a point for the final\n\t\t\t\t// polygon coord, so we must set it to the first\n\t\t\t\t// coordinate instead\n\t\t\t\tconst isFirstOrLastPolygonCoord =\n\t\t\t\t\tgeometry.type === \"Polygon\" &&\n\t\t\t\t\t(i === geomCoordinates.length - 1 || i === 0);\n\n\t\t\t\tclosestCoordinate.dist = distance;\n\t\t\t\tclosestCoordinate.index = isFirstOrLastPolygonCoord ? 0 : i;\n\t\t\t\tclosestCoordinate.isFirstOrLastPolygonCoord = isFirstOrLastPolygonCoord;\n\t\t\t}\n\t\t}\n\n\t\treturn closestCoordinate;\n\t}\n\n\tprivate isValidDragWebMercator(\n\t\tindex: BoundingBoxIndex,\n\t\tdistanceX: number,\n\t\tdistanceY: number,\n\t) {\n\t\tswitch (index) {\n\t\t\tcase 0:\n\t\t\t\tif (distanceX <= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif (distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (distanceX >= 0 || distanceY >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif (distanceX >= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tif (distanceX >= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tif (distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tif (distanceX <= 0 || distanceY <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tif (distanceX <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate getSelectedFeatureDataWebMercator() {\n\t\tif (!this.draggedCoordinate.id || this.draggedCoordinate.index === -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = this.getFeature(this.draggedCoordinate.id);\n\t\tif (!feature) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst updatedCoords = this.getNormalisedCoordinates(feature.geometry);\n\t\tconst boundingBox = this.getBBoxWebMercator(updatedCoords);\n\n\t\treturn {\n\t\t\tboundingBox,\n\t\t\tfeature,\n\t\t\tupdatedCoords,\n\t\t\tselectedCoordinate: updatedCoords[this.draggedCoordinate.index],\n\t\t};\n\t}\n\n\tprivate centerWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate centerFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { feature, boundingBox, updatedCoords, selectedCoordinate } =\n\t\t\tfeatureData;\n\n\t\tconst webMercatorOrigin = webMercatorCentroid(feature);\n\n\t\tif (!webMercatorOrigin) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleFixedWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet scale =\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorCursor) /\n\t\t\tcartesianDistance(webMercatorOrigin, webMercatorSelected);\n\n\t\tif (scale < 0) {\n\t\t\tscale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\tscale,\n\t\t\tscale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeFixedWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleFixedWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate oppositeWebMercatorDrag(event: TerraDrawMouseEvent) {\n\t\tconst featureData = this.getSelectedFeatureDataWebMercator();\n\t\tif (!featureData) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { boundingBox, updatedCoords, selectedCoordinate } = featureData;\n\n\t\tconst webMercatorSelected = lngLatToWebMercatorXY(\n\t\t\tselectedCoordinate[0],\n\t\t\tselectedCoordinate[1],\n\t\t);\n\n\t\tconst { oppositeBboxIndex, closestBBoxIndex } = this.getIndexesWebMercator(\n\t\t\tboundingBox,\n\t\t\twebMercatorSelected,\n\t\t);\n\n\t\tconst webMercatorOrigin = {\n\t\t\tx: boundingBox[oppositeBboxIndex][0],\n\t\t\ty: boundingBox[oppositeBboxIndex][1],\n\t\t};\n\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\tthis.scaleWebMercator({\n\t\t\tclosestBBoxIndex,\n\t\t\tupdatedCoords,\n\t\t\twebMercatorCursor,\n\t\t\twebMercatorSelected,\n\t\t\twebMercatorOrigin,\n\t\t});\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate scaleWebMercator({\n\t\tclosestBBoxIndex,\n\t\twebMercatorOrigin,\n\t\twebMercatorSelected,\n\t\twebMercatorCursor,\n\t\tupdatedCoords,\n\t}: {\n\t\tclosestBBoxIndex: BoundingBoxIndex;\n\t\tupdatedCoords: Position[];\n\t\twebMercatorCursor: CartesianPoint;\n\t\twebMercatorSelected: CartesianPoint;\n\t\twebMercatorOrigin: CartesianPoint;\n\t}) {\n\t\tconst cursorDistanceX = webMercatorOrigin.x - webMercatorCursor.x;\n\t\tconst cursorDistanceY = webMercatorOrigin.y - webMercatorCursor.y;\n\n\t\tconst valid = this.isValidDragWebMercator(\n\t\t\tclosestBBoxIndex,\n\t\t\tcursorDistanceX,\n\t\t\tcursorDistanceY,\n\t\t);\n\n\t\tif (!valid) {\n\t\t\treturn null;\n\t\t}\n\n\t\tlet xScale = 1;\n\t\tif (\n\t\t\tcursorDistanceX !== 0 &&\n\t\t\tclosestBBoxIndex !== 1 &&\n\t\t\tclosestBBoxIndex !== 5\n\t\t) {\n\t\t\tconst currentDistanceX = webMercatorOrigin.x - webMercatorSelected.x;\n\t\t\txScale = 1 - (currentDistanceX - cursorDistanceX) / cursorDistanceX;\n\t\t}\n\n\t\tlet yScale = 1;\n\t\tif (\n\t\t\tcursorDistanceY !== 0 &&\n\t\t\tclosestBBoxIndex !== 3 &&\n\t\t\tclosestBBoxIndex !== 7\n\t\t) {\n\t\t\tconst currentDistanceY = webMercatorOrigin.y - webMercatorSelected.y;\n\t\t\tyScale = 1 - (currentDistanceY - cursorDistanceY) / cursorDistanceY;\n\t\t}\n\n\t\tif (!this.validateScale(xScale, yScale)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (xScale < 0) {\n\t\t\txScale = this.minimumScale;\n\t\t}\n\n\t\tif (yScale < 0) {\n\t\t\tyScale = this.minimumScale;\n\t\t}\n\n\t\tthis.performWebMercatorScale(\n\t\t\tupdatedCoords,\n\t\t\twebMercatorOrigin.x,\n\t\t\twebMercatorOrigin.y,\n\t\t\txScale,\n\t\t\tyScale,\n\t\t);\n\n\t\treturn updatedCoords;\n\t}\n\n\tprivate getFeature(id: FeatureId) {\n\t\tif (this.draggedCoordinate.id === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst geometry = this.store.getGeometryCopy(id);\n\n\t\t// Update the geometry of the dragged feature\n\t\tif (geometry.type !== \"Polygon\" && geometry.type !== \"LineString\") {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst feature = {\n\t\t\tid,\n\t\t\ttype: \"Feature\",\n\t\t\tgeometry,\n\t\t\tproperties: {},\n\t\t} as Feature<Polygon | LineString>;\n\n\t\treturn feature;\n\t}\n\n\tprivate getNormalisedCoordinates(geometry: Polygon | LineString) {\n\t\t// Coordinates are either polygon or linestring at this point\n\t\treturn geometry.type === \"Polygon\"\n\t\t\t? geometry.coordinates[0]\n\t\t\t: geometry.coordinates;\n\t}\n\n\tprivate validateScale(xScale: number, yScale: number) {\n\t\tconst validX = !isNaN(xScale) && yScale < Number.MAX_SAFE_INTEGER;\n\t\tconst validY = !isNaN(yScale) && yScale < Number.MAX_SAFE_INTEGER;\n\n\t\treturn validX && validY;\n\t}\n\n\tprivate performWebMercatorScale(\n\t\tcoordinates: Position[],\n\t\toriginX: number,\n\t\toriginY: number,\n\t\txScale: number,\n\t\tyScale: number,\n\t) {\n\t\tcoordinates.forEach((coordinate) => {\n\t\t\tconst { x, y } = lngLatToWebMercatorXY(coordinate[0], coordinate[1]);\n\n\t\t\tconst updatedX = originX + (x - originX) * xScale;\n\t\t\tconst updatedY = originY + (y - originY) * yScale;\n\n\t\t\tconst { lng, lat } = webMercatorXYToLngLat(updatedX, updatedY);\n\n\t\t\tcoordinate[0] = lng;\n\t\t\tcoordinate[1] = lat;\n\t\t});\n\t}\n\n\tprivate getBBoxWebMercator(coordinates: Position[]) {\n\t\tconst bbox: [number, number, number, number] = [\n\t\t\tInfinity,\n\t\t\tInfinity,\n\t\t\t-Infinity,\n\t\t\t-Infinity,\n\t\t];\n\n\t\t// Convert from [lng, lat] -> [x, y]\n\t\tcoordinates = coordinates.map((coord) => {\n\t\t\tconst { x, y } = lngLatToWebMercatorXY(coord[0], coord[1]);\n\t\t\treturn [x, y];\n\t\t});\n\n\t\tcoordinates.forEach(([x, y]) => {\n\t\t\tif (x < bbox[0]) {\n\t\t\t\tbbox[0] = x;\n\t\t\t}\n\n\t\t\tif (y < bbox[1]) {\n\t\t\t\tbbox[1] = y;\n\t\t\t}\n\n\t\t\tif (x > bbox[2]) {\n\t\t\t\tbbox[2] = x;\n\t\t\t}\n\n\t\t\tif (y > bbox[3]) {\n\t\t\t\tbbox[3] = y;\n\t\t\t}\n\t\t});\n\n\t\tconst [west, south, east, north] = bbox;\n\n\t\t// Bounding box is represented as follows:\n\t\t//\n\t\t// 0 1 2\n\t\t// *----*----*\n\t\t// \t |\t\t |\n\t\t// 7 *\t\t * 3\n\t\t// |\t\t |\n\t\t// *----*----*\n\t\t// \t 6 5 4\n\t\t//\n\t\tconst topLeft = [west, north];\n\t\tconst topRight = [east, north];\n\t\tconst lowRight = [east, south];\n\t\tconst lowLeft = [west, south];\n\n\t\tconst midTop = [(west + east) / 2, north];\n\t\tconst midRight = [east, north + (south - north) / 2];\n\t\tconst midBottom = [(west + east) / 2, south];\n\t\tconst midLeft = [west, north + (south - north) / 2];\n\n\t\treturn [\n\t\t\ttopLeft, // 0\n\t\t\tmidTop, // 1\n\t\t\ttopRight, // 2\n\t\t\tmidRight, // 3\n\t\t\tlowRight, // 4\n\t\t\tmidBottom, // 5\n\t\t\tlowLeft, // 6\n\t\t\tmidLeft, // 7\n\t\t] as const;\n\t}\n\n\tprivate getIndexesWebMercator(\n\t\tboundingBox: BoundingBox,\n\t\tselectedXY: CartesianPoint,\n\t) {\n\t\tlet closestIndex: BoundingBoxIndex | undefined;\n\t\tlet closestDistance = Infinity;\n\n\t\tfor (let i = 0; i < boundingBox.length; i++) {\n\t\t\tconst distance = cartesianDistance(\n\t\t\t\t{ x: selectedXY.x, y: selectedXY.y },\n\t\t\t\t{ x: boundingBox[i][0], y: boundingBox[i][1] },\n\t\t\t);\n\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestIndex = i as BoundingBoxIndex;\n\t\t\t\tclosestDistance = distance;\n\t\t\t}\n\t\t}\n\n\t\tif (closestIndex === undefined) {\n\t\t\tthrow new Error(\"No closest coordinate found\");\n\t\t}\n\n\t\t// Depending on where what the origin is set to, we need to find the position to\n\t\t// scale from\n\t\tconst oppositeIndex = this.boundingBoxMaps[\"opposite\"][\n\t\t\tclosestIndex\n\t\t] as BoundingBoxIndex;\n\n\t\treturn {\n\t\t\toppositeBboxIndex: oppositeIndex,\n\t\t\tclosestBBoxIndex: closestIndex,\n\t\t} as const;\n\t}\n\n\t/**\n\t * @returns - true if the feature is being dragged (resized), false otherwise\n\t */\n\tpublic isDragging() {\n\t\treturn this.draggedCoordinate.id !== null;\n\t}\n\n\t/**\n\t * Starts the resizing of the feature\n\t * @param id - feature id of the feature that is being dragged\n\t * @param index - index of the coordinate that is being dragged\n\t * @returns - void\n\t */\n\tpublic startDragging(id: FeatureId, index: number) {\n\t\tthis.draggedCoordinate = {\n\t\t\tid,\n\t\t\tindex,\n\t\t};\n\t}\n\n\t/**\n\t * Stops the resizing of the feature\n\t * @returns - void\t *\n\t */\n\tpublic stopDragging() {\n\t\tthis.draggedCoordinate = {\n\t\t\tid: null,\n\t\t\tindex: -1,\n\t\t};\n\t}\n\n\t/**\n\t * Returns the index of the coordinate that is going to be dragged\n\t * @param event - cursor event\n\t * @param selectedId - feature id of the feature that is selected\n\t * @returns - the index to be dragged\n\t */\n\tpublic getDraggableIndex(\n\t\tevent: TerraDrawMouseEvent,\n\t\tselectedId: FeatureId,\n\t): number {\n\t\tconst geometry = this.store.getGeometryCopy(selectedId);\n\t\tconst closestCoordinate = this.getClosestCoordinate(event, geometry);\n\n\t\t// No coordinate was within the pointer distance\n\t\tif (closestCoordinate.index === -1) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn closestCoordinate.index;\n\t}\n\n\t/**\n\t * Resizes the feature based on the cursor event\n\t * @param event - cursor event\n\t * @param resizeOption - the resize option, either \"center\" or \"opposite\"\n\t * @returns - true is resize was successful, false otherwise\n\t */\n\tpublic drag(\n\t\tevent: TerraDrawMouseEvent,\n\t\tresizeOption: ResizeOptions,\n\t\tvalidateFeature?: Validation,\n\t): boolean {\n\t\tif (!this.draggedCoordinate.id) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst feature = this.getFeature(this.draggedCoordinate.id);\n\t\tif (!feature) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet updatedCoords: Position[] | null = null;\n\n\t\tif (resizeOption === \"center\") {\n\t\t\tupdatedCoords = this.centerWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"opposite\") {\n\t\t\tupdatedCoords = this.oppositeWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"center-fixed\") {\n\t\t\tupdatedCoords = this.centerFixedWebMercatorDrag(event);\n\t\t} else if (resizeOption === \"opposite-fixed\") {\n\t\t\tupdatedCoords = this.oppositeFixedWebMercatorDrag(event);\n\t\t}\n\n\t\tif (!updatedCoords) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Ensure that coordinate precision is maintained\n\t\tfor (let i = 0; i < updatedCoords.length; i++) {\n\t\t\tconst coordinate = updatedCoords[i];\n\t\t\tcoordinate[0] = limitPrecision(coordinate[0], this.coordinatePrecision);\n\t\t\tcoordinate[1] = limitPrecision(coordinate[1], this.coordinatePrecision);\n\n\t\t\t// Ensure the coordinate we are about to update with is valid\n\t\t\tif (!coordinatePrecisionIsValid(coordinate, this.coordinatePrecision)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Perform the update to the midpoints and selection points\n\t\tconst updatedMidPoints = this.midPoints.getUpdated(updatedCoords) || [];\n\t\tconst updatedSelectionPoints =\n\t\t\tthis.selectionPoints.getUpdated(updatedCoords) || [];\n\t\tconst updatedCoordinatePoints =\n\t\t\tthis.coordinatePoints.getUpdated(\n\t\t\t\tfeature.id as FeatureId,\n\t\t\t\tupdatedCoords,\n\t\t\t) || [];\n\n\t\tconst updatedGeometry = {\n\t\t\ttype: feature.geometry.type as \"Polygon\" | \"LineString\",\n\t\t\tcoordinates:\n\t\t\t\tfeature.geometry.type === \"Polygon\" ? [updatedCoords] : updatedCoords,\n\t\t} as GeoJSONStoreGeometries;\n\n\t\tif (validateFeature) {\n\t\t\tconst validationResult = validateFeature(\n\t\t\t\t{\n\t\t\t\t\tid: this.draggedCoordinate.id,\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t\tproperties: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tproject: this.config.project,\n\t\t\t\t\tunproject: this.config.unproject,\n\t\t\t\t\tcoordinatePrecision: this.config.coordinatePrecision,\n\t\t\t\t\tupdateType: UpdateTypes.Provisional,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Issue the update to the selected feature\n\t\tthis.store.updateGeometry([\n\t\t\t{\n\t\t\t\tid: this.draggedCoordinate.id,\n\t\t\t\tgeometry: updatedGeometry,\n\t\t\t},\n\t\t\t...updatedSelectionPoints,\n\t\t\t...updatedMidPoints,\n\t\t\t...updatedCoordinatePoints,\n\t\t]);\n\n\t\treturn true;\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawKeyboardEvent,\n\tSELECT_PROPERTIES,\n\tTerraDrawAdapterStyling,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tValidation,\n\tUpdateTypes,\n\tCOMMON_PROPERTIES,\n} from \"../../common\";\nimport { Point, Polygon, Position } from \"geojson\";\nimport {\n\tBaseModeOptions,\n\tCustomStyling,\n\tTerraDrawBaseSelectMode,\n} from \"../base.mode\";\nimport { MidPointBehavior } from \"./behaviors/midpoint.behavior\";\nimport { SelectionPointBehavior } 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\";\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;\n\t\t\tmidpoints?:\n\t\t\t| boolean\n\t\t\t| {\n\t\t\t\tdraggable?: boolean;\n\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\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\tprivate createOrUpdateCoordinatePoint(polygonId: FeatureId) {\n\t\tconst existingPolygonProps = this.store.getPropertiesCopy(polygonId);\n\n\t\tif (existingPolygonProps.coordinatePointIds) {\n\t\t\tthis.store.delete(existingPolygonProps.coordinatePointIds as FeatureId[]);\n\t\t}\n\n\t\tconst existingPolygon = this.store.getGeometryCopy(polygonId);\n\n\t\tconst coordinates = existingPolygon\n\t\t\t.coordinates[0] as Polygon[\"coordinates\"][0];\n\t\tconst coordinatePointIds = this.store.create(\n\t\t\tcoordinates.map((coordinate) => ({\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: this.mode,\n\t\t\t\t\t[COMMON_PROPERTIES.COORDINATE_POINT]: true,\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: polygonId,\n\t\t\t\tproperty: \"coordinatePointIds\",\n\t\t\t\tvalue: coordinatePointIds,\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\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.scaleFeature = new ScaleFeatureBehavior(\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);\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}\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:\n\t\t\t| {\n\t\t\t\tselectionPointFeatureId: string;\n\t\t\t\tindex: number;\n\t\t\t}\n\t\t\t| 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(id) as {\n\t\t\t\t\tselectionPointFeatureId: string;\n\t\t\t\t\tindex: number;\n\t\t\t\t};\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: \"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 (event.button === \"right\") {\n\t\t\tthis.onRightClick(event);\n\t\t\treturn;\n\t\t} else if (event.button === \"left\") {\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\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 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\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\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\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 snapping = Boolean(modeFlags.feature?.coordinates?.snappable);\n\t\t\tthis.dragCoordinate.drag(event, canSelfIntersect, validation, snapping);\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\t_: TerraDrawMouseEvent,\n\t\tsetMapDraggability: (enabled: boolean) => void,\n\t) {\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 = 30;\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 = 40;\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 = 10;\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 = 10;\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 = 10;\n\t\t\t\treturn styles;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n}\n","import { TerraDrawAdapterStyling } from \"../../common\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport { ModeTypes, TerraDrawBaseDrawMode } from \"../base.mode\";\n\ntype StaticModeStylingExt<T extends TerraDrawAdapterStyling> = {};\ntype StaticModeStyling = StaticModeStylingExt<TerraDrawAdapterStyling>;\n\nexport class TerraDrawStaticMode extends TerraDrawBaseDrawMode<StaticModeStyling> {\n\ttype = ModeTypes.Static;\n\tmode = \"static\" as const;\n\tstart() {}\n\tstop() {}\n\tonKeyUp() {}\n\tonKeyDown() {}\n\tonClick() {}\n\tonDragStart() {}\n\tonDrag() {}\n\tonDragEnd() {}\n\tonMouseMove() {}\n\tcleanUp() {}\n\tstyleFeature() {\n\t\treturn { ...getDefaultStyling() };\n\t}\n}\n","// ISC License\n// Copyright (c) 2018, Vladimir Agafonkin\n\nexport type CompareFunction<T> = (a: T, b: T) => number;\n\nexport function quickselect<T>(\n\tarr: T[],\n\tk: number,\n\tleft: number,\n\tright: number,\n\tcompare: CompareFunction<T>,\n) {\n\twhile (right > left) {\n\t\tif (right - left > 600) {\n\t\t\tconst n = right - left + 1;\n\t\t\tconst m = k - left + 1;\n\t\t\tconst z = Math.log(n);\n\t\t\tconst s = 0.5 * Math.exp((2 * z) / 3);\n\t\t\tconst sd =\n\t\t\t\t0.5 * Math.sqrt((z * s * (n - s)) / n) * (m - n / 2 < 0 ? -1 : 1);\n\t\t\tconst newLeft = Math.max(left, Math.floor(k - (m * s) / n + sd));\n\t\t\tconst newRight = Math.min(right, Math.floor(k + ((n - m) * s) / n + sd));\n\t\t\tquickselect(arr, k, newLeft, newRight, compare);\n\t\t}\n\n\t\tconst t = arr[k];\n\t\tlet i = left;\n\t\tlet j = right;\n\n\t\tswap(arr, left, k);\n\t\tif (compare(arr[right], t) > 0) swap(arr, left, right);\n\n\t\twhile (i < j) {\n\t\t\tswap(arr, i, j);\n\t\t\ti++;\n\t\t\tj--;\n\t\t\twhile (compare(arr[i], t) < 0) i++;\n\t\t\twhile (compare(arr[j], t) > 0) j--;\n\t\t}\n\n\t\tif (compare(arr[left], t) === 0) {\n\t\t\tswap(arr, left, j);\n\t\t} else {\n\t\t\tj++;\n\t\t\tswap(arr, j, right);\n\t\t}\n\n\t\tif (j <= k) left = j + 1;\n\t\tif (k <= j) right = j - 1;\n\t}\n}\n\nfunction swap<T>(arr: T[], i: number, j: number) {\n\tconst tmp = arr[i];\n\tarr[i] = arr[j];\n\tarr[j] = tmp;\n}\n","// Base on Rbush - https://github.com/mourner/rbush\n// MIT License\n// Copyright (c) 2016 Vladimir Agafonkin\n\nimport { CompareFunction, quickselect } from \"./quickselect\";\n\nexport type Node = {\n\tchildren: Node[];\n\theight: number;\n\tleaf: boolean;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n};\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node: Node, toBBox: (node: Node) => any) {\n\tdistBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(\n\tnode: Node,\n\tk: number,\n\tp: number,\n\ttoBBox: (node: Node) => Node,\n\tdestNode?: Node,\n) {\n\tif (!destNode) destNode = createNode([]);\n\tdestNode.minX = Infinity;\n\tdestNode.minY = Infinity;\n\tdestNode.maxX = -Infinity;\n\tdestNode.maxY = -Infinity;\n\n\tfor (let i = k; i < p; i++) {\n\t\tconst child = node.children[i];\n\t\textend(destNode, node.leaf ? toBBox(child) : child);\n\t}\n\n\treturn destNode;\n}\n\nfunction extend(a: Node, b: Node) {\n\ta.minX = Math.min(a.minX, b.minX);\n\ta.minY = Math.min(a.minY, b.minY);\n\ta.maxX = Math.max(a.maxX, b.maxX);\n\ta.maxY = Math.max(a.maxY, b.maxY);\n\treturn a;\n}\n\nfunction compareNodeMinX(a: Node, b: Node) {\n\treturn a.minX - b.minX;\n}\nfunction compareNodeMinY(a: Node, b: Node) {\n\treturn a.minY - b.minY;\n}\n\nfunction bboxArea(a: Node) {\n\treturn (a.maxX - a.minX) * (a.maxY - a.minY);\n}\nfunction bboxMargin(a: {\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}) {\n\treturn a.maxX - a.minX + (a.maxY - a.minY);\n}\n\nfunction enlargedArea(a: Node, b: Node) {\n\treturn (\n\t\t(Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n\t\t(Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY))\n\t);\n}\n\nfunction intersectionArea(a: Node, b: Node) {\n\tconst minX = Math.max(a.minX, b.minX);\n\tconst minY = Math.max(a.minY, b.minY);\n\tconst maxX = Math.min(a.maxX, b.maxX);\n\tconst maxY = Math.min(a.maxY, b.maxY);\n\n\treturn Math.max(0, maxX - minX) * Math.max(0, maxY - minY);\n}\n\nfunction contains(a: Node, b: Node) {\n\treturn (\n\t\ta.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY\n\t);\n}\n\nfunction intersects(a: Node, b: Node) {\n\treturn (\n\t\tb.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY\n\t);\n}\n\nfunction createNode(children: Node[]) {\n\treturn {\n\t\tchildren,\n\t\theight: 1,\n\t\tleaf: true,\n\t\tminX: Infinity,\n\t\tminY: Infinity,\n\t\tmaxX: -Infinity,\n\t\tmaxY: -Infinity,\n\t};\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect<T>(\n\tarr: T[],\n\tleft: number,\n\tright: number,\n\tn: number,\n\tcompare: CompareFunction<T>,\n) {\n\tconst stack = [left, right];\n\n\twhile (stack.length) {\n\t\tright = stack.pop() as number;\n\t\tleft = stack.pop() as number;\n\n\t\tif (right - left <= n) continue;\n\n\t\tconst mid = left + Math.ceil((right - left) / n / 2) * n;\n\t\tquickselect(arr, mid, left, right, compare);\n\n\t\tstack.push(left, mid, mid, right);\n\t}\n}\n\nexport class RBush {\n\tprivate _maxEntries: number;\n\tprivate _minEntries: number;\n\tprivate data!: Node;\n\n\tconstructor(maxEntries: number) {\n\t\t// max entries in a node is 9 by default; min node fill is 40% for best performance\n\t\tthis._maxEntries = Math.max(4, maxEntries);\n\t\tthis._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n\t\tthis.clear();\n\t}\n\n\tsearch(bbox: Node): Node[] {\n\t\tlet node = this.data;\n\t\tconst result: Node[] = [];\n\n\t\tif (!intersects(bbox, node)) {\n\t\t\treturn result;\n\t\t}\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst nodesToSearch = [];\n\n\t\twhile (node) {\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\t\t\t\tconst childBBox = node.leaf ? toBBox(child) : child;\n\n\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\tif (node.leaf) result.push(child);\n\t\t\t\t\telse if (contains(bbox, childBBox)) this._all(child, result);\n\t\t\t\t\telse nodesToSearch.push(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tcollides(bbox: Node) {\n\t\tlet node = this.data;\n\n\t\tconst intersect = intersects(bbox, node);\n\t\tif (intersect) {\n\t\t\tconst nodesToSearch = [];\n\t\t\twhile (node) {\n\t\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\t\tconst child = node.children[i];\n\t\t\t\t\tconst childBBox = node.leaf ? this.toBBox(child) : child;\n\n\t\t\t\t\tif (intersects(bbox, childBBox)) {\n\t\t\t\t\t\tif (node.leaf || contains(bbox, childBBox)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnodesToSearch.push(child);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tload(data: Node[]): void {\n\t\tif (data.length < this._minEntries) {\n\t\t\tfor (let i = 0; i < data.length; i++) {\n\t\t\t\tthis.insert(data[i]);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// recursively build the tree with the given data from scratch using OMT algorithm\n\t\tlet node = this._build(data.slice(), 0, data.length - 1, 0);\n\n\t\tif (!this.data.children.length) {\n\t\t\t// save as is if tree is empty\n\t\t\tthis.data = node;\n\t\t} else if (this.data.height === node.height) {\n\t\t\t// split root if trees have the same height\n\t\t\tthis._splitRoot(this.data, node);\n\t\t} else {\n\t\t\tif (this.data.height < node.height) {\n\t\t\t\t// swap trees if inserted one is bigger\n\t\t\t\tconst tmpNode = this.data;\n\t\t\t\tthis.data = node;\n\t\t\t\tnode = tmpNode;\n\t\t\t}\n\n\t\t\t// insert the small tree into the large tree at appropriate level\n\t\t\tthis._insert(node, this.data.height - node.height - 1, true);\n\t\t}\n\t}\n\n\tinsert(item: Node): void {\n\t\tthis._insert(item, this.data.height - 1);\n\t}\n\n\tclear(): void {\n\t\tthis.data = createNode([]);\n\t}\n\n\tremove(item: Node): void {\n\t\tlet node: Node | null = this.data;\n\t\tconst bbox = this.toBBox(item);\n\t\tconst path = [];\n\t\tconst indexes: number[] = [];\n\t\tlet i: number | undefined;\n\t\tlet parent: Node | undefined;\n\t\tlet goingUp = false;\n\n\t\t// depth-first iterative tree traversal\n\t\twhile (node || path.length) {\n\t\t\tif (!node) {\n\t\t\t\t// go up\n\t\t\t\tnode = path.pop() as Node;\n\t\t\t\tparent = path[path.length - 1];\n\t\t\t\ti = indexes.pop() as number;\n\t\t\t\tgoingUp = true;\n\t\t\t}\n\n\t\t\tif (node.leaf) {\n\t\t\t\t// check current node\n\n\t\t\t\tconst index = node.children.indexOf(item);\n\n\t\t\t\tif (index !== -1) {\n\t\t\t\t\t// item found, remove the item and condense tree upwards\n\t\t\t\t\tnode.children.splice(index, 1);\n\t\t\t\t\tpath.push(node);\n\t\t\t\t\tthis._condense(path);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!goingUp && !node.leaf && contains(node, bbox)) {\n\t\t\t\t// go down\n\t\t\t\tpath.push(node);\n\t\t\t\tindexes.push(i as number);\n\t\t\t\ti = 0;\n\t\t\t\tparent = node;\n\t\t\t\tnode = node.children[0];\n\t\t\t} else if (parent) {\n\t\t\t\t// go right\n\t\t\t\t(i as number)++;\n\t\t\t\tnode = parent.children[i as number];\n\t\t\t\tgoingUp = false;\n\t\t\t} else {\n\t\t\t\tnode = null; // nothing found\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate toBBox<T>(item: T): T {\n\t\treturn item;\n\t}\n\n\tprivate compareMinX(a: Node, b: Node) {\n\t\treturn a.minX - b.minX;\n\t}\n\tprivate compareMinY(a: Node, b: Node) {\n\t\treturn a.minY - b.minY;\n\t}\n\n\tprivate _all(node: Node, result: Node[]) {\n\t\tconst nodesToSearch = [];\n\t\twhile (node) {\n\t\t\tif (node.leaf) result.push(...node.children);\n\t\t\telse nodesToSearch.push(...node.children);\n\n\t\t\tnode = nodesToSearch.pop() as Node;\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate _build(items: Node[], left: number, right: number, height: number) {\n\t\tconst N = right - left + 1;\n\t\tlet M = this._maxEntries;\n\t\tlet node;\n\n\t\tif (N <= M) {\n\t\t\t// reached leaf level; return leaf\n\t\t\tnode = createNode(items.slice(left, right + 1));\n\t\t\tcalcBBox(node, this.toBBox);\n\t\t\treturn node;\n\t\t}\n\n\t\tif (!height) {\n\t\t\t// target height of the bulk-loaded tree\n\t\t\theight = Math.ceil(Math.log(N) / Math.log(M));\n\n\t\t\t// target number of root entries to maximize storage utilization\n\t\t\tM = Math.ceil(N / Math.pow(M, height - 1));\n\t\t}\n\n\t\tnode = createNode([]);\n\t\tnode.leaf = false;\n\t\tnode.height = height;\n\n\t\t// split the items into M mostly square tiles\n\n\t\tconst N2 = Math.ceil(N / M);\n\t\tconst N1 = N2 * Math.ceil(Math.sqrt(M));\n\n\t\tmultiSelect(items, left, right, N1, this.compareMinX);\n\n\t\tfor (let i = left; i <= right; i += N1) {\n\t\t\tconst right2 = Math.min(i + N1 - 1, right);\n\n\t\t\tmultiSelect(items, i, right2, N2, this.compareMinY);\n\n\t\t\tfor (let j = i; j <= right2; j += N2) {\n\t\t\t\tconst right3 = Math.min(j + N2 - 1, right2);\n\n\t\t\t\t// pack each entry recursively\n\t\t\t\tnode.children.push(this._build(items, j, right3, height - 1));\n\t\t\t}\n\t\t}\n\n\t\tcalcBBox(node, this.toBBox);\n\n\t\treturn node;\n\t}\n\n\tprivate _chooseSubtree(bbox: Node, node: Node, level: number, path: Node[]) {\n\t\twhile (true) {\n\t\t\tpath.push(node);\n\n\t\t\tif (node.leaf || path.length - 1 === level) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tlet minArea = Infinity;\n\t\t\tlet minEnlargement = Infinity;\n\t\t\tlet targetNode;\n\n\t\t\tfor (let i = 0; i < node.children.length; i++) {\n\t\t\t\tconst child = node.children[i];\n\n\t\t\t\tconst area = bboxArea(child);\n\t\t\t\tconst enlargement = enlargedArea(bbox, child) - area;\n\n\t\t\t\t// choose entry with the least area enlargement\n\n\t\t\t\tif (enlargement < minEnlargement) {\n\t\t\t\t\tminEnlargement = enlargement;\n\t\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t\t\ttargetNode = child;\n\t\t\t\t} else if (enlargement === minEnlargement) {\n\t\t\t\t\t// otherwise choose one with the smallest area\n\t\t\t\t\tif (area < minArea) {\n\t\t\t\t\t\tminArea = area;\n\t\t\t\t\t\ttargetNode = child;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnode = targetNode || node.children[0];\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate _insert(item: Node, level: number, isNode?: boolean) {\n\t\tconst bbox = isNode ? item : this.toBBox(item);\n\t\tconst insertPath: Node[] = [];\n\n\t\t// find the best node for accommodating the item, saving all nodes along the path too\n\t\tconst node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n\t\t// put the item into the node\n\t\tnode.children.push(item);\n\t\textend(node, bbox);\n\n\t\t// split on node overflow; propagate upwards if necessary\n\t\twhile (level >= 0) {\n\t\t\tif (insertPath[level].children.length > this._maxEntries) {\n\t\t\t\tthis._split(insertPath, level);\n\t\t\t\tlevel--;\n\t\t\t} else break;\n\t\t}\n\n\t\t// adjust bboxes along the insertion path\n\t\tthis._adjustParentBBoxes(bbox, insertPath, level);\n\t}\n\n\t// split overflowed node into two\n\tprivate _split(insertPath: Node[], level: number) {\n\t\tconst node = insertPath[level];\n\t\tconst M = node.children.length;\n\t\tconst m = this._minEntries;\n\n\t\tthis._chooseSplitAxis(node, m, M);\n\n\t\tconst splitIndex = this._chooseSplitIndex(node, m, M);\n\n\t\tconst newNode = createNode(\n\t\t\tnode.children.splice(splitIndex, node.children.length - splitIndex),\n\t\t);\n\t\tnewNode.height = node.height;\n\t\tnewNode.leaf = node.leaf;\n\n\t\tcalcBBox(node, this.toBBox);\n\t\tcalcBBox(newNode, this.toBBox);\n\n\t\tif (level) insertPath[level - 1].children.push(newNode);\n\t\telse this._splitRoot(node, newNode);\n\t}\n\n\tprivate _splitRoot(node: Node, newNode: Node) {\n\t\t// split root node\n\t\tthis.data = createNode([node, newNode]);\n\t\tthis.data.height = node.height + 1;\n\t\tthis.data.leaf = false;\n\t\tcalcBBox(this.data, this.toBBox);\n\t}\n\n\tprivate _chooseSplitIndex(node: Node, m: number, M: number) {\n\t\tlet index;\n\t\tlet minOverlap = Infinity;\n\t\tlet minArea = Infinity;\n\n\t\tfor (let i = m; i <= M - m; i++) {\n\t\t\tconst bbox1 = distBBox(node, 0, i, this.toBBox);\n\t\t\tconst bbox2 = distBBox(node, i, M, this.toBBox);\n\n\t\t\tconst overlap = intersectionArea(bbox1, bbox2);\n\t\t\tconst area = bboxArea(bbox1) + bboxArea(bbox2);\n\n\t\t\t// choose distribution with minimum overlap\n\t\t\tif (overlap < minOverlap) {\n\t\t\t\tminOverlap = overlap;\n\t\t\t\tindex = i;\n\n\t\t\t\tminArea = area < minArea ? area : minArea;\n\t\t\t} else if (overlap === minOverlap) {\n\t\t\t\t// otherwise choose distribution with minimum area\n\t\t\t\tif (area < minArea) {\n\t\t\t\t\tminArea = area;\n\t\t\t\t\tindex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn index || M - m;\n\t}\n\n\t// sorts node children by the best axis for split\n\tprivate _chooseSplitAxis(node: Node, m: number, M: number) {\n\t\tconst compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n\t\tconst compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n\t\tconst xMargin = this._allDistMargin(node, m, M, compareMinX);\n\t\tconst yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n\t\t// if total distributions margin value is minimal for x, sort by minX,\n\t\t// otherwise it's already sorted by minY\n\t\tif (xMargin < yMargin) {\n\t\t\tnode.children.sort(compareMinX);\n\t\t}\n\t}\n\n\t// total margin of all possible split distributions where each node is at least m full\n\tprivate _allDistMargin(\n\t\tnode: Node,\n\t\tm: number,\n\t\tM: number,\n\t\tcompare: CompareFunction<Node>,\n\t) {\n\t\tnode.children.sort(compare);\n\n\t\tconst toBBox = this.toBBox;\n\t\tconst leftBBox = distBBox(node, 0, m, toBBox);\n\t\tconst rightBBox = distBBox(node, M - m, M, toBBox);\n\t\tlet margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n\t\tfor (let i = m; i < M - m; i++) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(leftBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(leftBBox);\n\t\t}\n\n\t\tfor (let i = M - m - 1; i >= m; i--) {\n\t\t\tconst child = node.children[i];\n\t\t\textend(rightBBox, node.leaf ? toBBox(child) : child);\n\t\t\tmargin += bboxMargin(rightBBox);\n\t\t}\n\n\t\treturn margin;\n\t}\n\n\tprivate _adjustParentBBoxes(bbox: Node, path: Node[], level: number) {\n\t\t// adjust bboxes along the given tree path\n\t\tfor (let i = level; i >= 0; i--) {\n\t\t\textend(path[i], bbox);\n\t\t}\n\t}\n\n\tprivate _condense(path: Node[]) {\n\t\t// go through the path, removing empty nodes and updating bboxes\n\t\tfor (let i = path.length - 1, siblings; i >= 0; i--) {\n\t\t\tif (path[i].children.length === 0) {\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tsiblings = path[i - 1].children;\n\t\t\t\t\tsiblings.splice(siblings.indexOf(path[i]), 1);\n\t\t\t\t} else this.clear();\n\t\t\t} else {\n\t\t\t\tcalcBBox(path[i], this.toBBox);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Position } from \"geojson\";\nimport { FeatureId, GeoJSONStoreFeatures } from \"../store\";\nimport { RBush, Node } from \"./rbush\";\n\nexport class SpatialIndex {\n\tprivate tree: RBush;\n\tprivate idToNode: Map<FeatureId, Node>;\n\tprivate nodeToId: Map<Node, FeatureId>;\n\n\tconstructor(options?: { maxEntries: number }) {\n\t\tthis.tree = new RBush(\n\t\t\toptions && options.maxEntries ? options.maxEntries : 9,\n\t\t);\n\t\tthis.idToNode = new Map();\n\t\tthis.nodeToId = new Map();\n\t}\n\n\tprivate setMaps(feature: GeoJSONStoreFeatures, bbox: Node) {\n\t\tthis.idToNode.set(feature.id as FeatureId, bbox);\n\t\tthis.nodeToId.set(bbox, feature.id as FeatureId);\n\t}\n\n\tprivate toBBox(feature: GeoJSONStoreFeatures) {\n\t\tconst longitudes: number[] = [];\n\t\tconst latitudes: number[] = [];\n\n\t\tlet coordinates: Position[];\n\t\tif (feature.geometry.type === \"Polygon\") {\n\t\t\tcoordinates = feature.geometry.coordinates[0];\n\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\tcoordinates = feature.geometry.coordinates;\n\t\t} else if (feature.geometry.type === \"Point\") {\n\t\t\tcoordinates = [feature.geometry.coordinates];\n\t\t} else {\n\t\t\tthrow new Error(\"Not a valid feature to turn into a bounding box\");\n\t\t}\n\n\t\tfor (let i = 0; i < coordinates.length; i++) {\n\t\t\tlatitudes.push(coordinates[i][1]);\n\t\t\tlongitudes.push(coordinates[i][0]);\n\t\t}\n\n\t\tconst minLat = Math.min(...latitudes);\n\t\tconst maxLat = Math.max(...latitudes);\n\t\tconst minLng = Math.min(...longitudes);\n\t\tconst maxLng = Math.max(...longitudes);\n\n\t\treturn {\n\t\t\tminX: minLng,\n\t\t\tminY: minLat,\n\t\t\tmaxX: maxLng,\n\t\t\tmaxY: maxLat,\n\t\t} as Node;\n\t}\n\n\tinsert(feature: GeoJSONStoreFeatures): void {\n\t\tif (this.idToNode.get(String(feature.id))) {\n\t\t\tthrow new Error(\"Feature already exists\");\n\t\t}\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tload(features: GeoJSONStoreFeatures[]): void {\n\t\tconst load: Node[] = [];\n\t\tconst seenIds: Set<string> = new Set();\n\t\tfeatures.forEach((feature) => {\n\t\t\tconst bbox = this.toBBox(feature);\n\t\t\tthis.setMaps(feature, bbox);\n\t\t\tif (seenIds.has(String(feature.id))) {\n\t\t\t\tthrow new Error(`Duplicate feature ID found ${feature.id}`);\n\t\t\t}\n\t\t\tseenIds.add(String(feature.id));\n\t\t\tload.push(bbox);\n\t\t});\n\t\tthis.tree.load(load);\n\t}\n\n\tupdate(feature: GeoJSONStoreFeatures): void {\n\t\tthis.remove(feature.id as FeatureId);\n\t\tconst bbox = this.toBBox(feature);\n\t\tthis.setMaps(feature, bbox);\n\t\tthis.tree.insert(bbox);\n\t}\n\n\tremove(featureId: FeatureId): void {\n\t\tconst node = this.idToNode.get(featureId);\n\t\tif (!node) {\n\t\t\tthrow new Error(`${featureId} not inserted into the spatial index`);\n\t\t}\n\n\t\tthis.tree.remove(node);\n\t}\n\n\tclear(): void {\n\t\tthis.tree.clear();\n\t}\n\n\tsearch(feature: GeoJSONStoreFeatures): FeatureId[] {\n\t\tconst found = this.tree.search(this.toBBox(feature));\n\t\treturn found.map((node) => {\n\t\t\treturn this.nodeToId.get(node) as FeatureId;\n\t\t});\n\t}\n\n\tcollides(feature: GeoJSONStoreFeatures): boolean {\n\t\treturn this.tree.collides(this.toBBox(feature));\n\t}\n}\n","import { Feature, Point, Polygon, LineString } from \"geojson\";\nimport { uuid4 } from \"../util/id\";\nimport { SpatialIndex } from \"./spatial-index/spatial-index\";\nimport { isValidTimestamp } from \"./store-feature-validation\";\nimport { Validation } from \"../common\";\n\ntype JSON = string | number | boolean | null | JSONArray | JSONObject;\n\nexport interface JSONObject {\n\t[member: string]: JSON;\n}\ntype JSONArray = Array<JSON>;\n\ntype DefinedProperties = Record<string, JSON>;\n\nexport type GeoJSONStoreGeometries = Polygon | LineString | Point;\n\nexport type BBoxPolygon = Feature<Polygon, DefinedProperties>;\n\nexport type GeoJSONStoreFeatures = Feature<\n\tGeoJSONStoreGeometries,\n\tDefinedProperties\n>;\n\nexport type StoreValidation = {\n\tid?: FeatureId;\n} & ReturnType<Validation>;\n\ntype StoreChangeEvents = \"delete\" | \"create\" | \"update\" | \"styling\";\n\nexport type StoreChangeHandler = (\n\tids: FeatureId[],\n\tchange: StoreChangeEvents,\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<Id extends FeatureId = FeatureId> {\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 = () => {};\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): 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\t\tthis._onChange(changes, \"create\");\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) {\n\t\tthis._onChange = (ids, change) => {\n\t\t\tonChange(ids, change);\n\t\t};\n\t}\n\n\tgetGeometryCopy<T extends GeoJSONStoreGeometries>(id: FeatureId): T {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get geometry copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.geometry as T);\n\t}\n\n\tgetPropertiesCopy(id: FeatureId) {\n\t\tconst feature = this.store[id];\n\t\tif (!feature) {\n\t\t\tthrow new Error(\n\t\t\t\t`No feature with this id (${id}), can not get properties copy`,\n\t\t\t);\n\t\t}\n\t\treturn this.clone(feature.properties);\n\t}\n\n\tupdateProperty(\n\t\tpropertiesToUpdate: { id: FeatureId; property: string; value: JSON }[],\n\t): void {\n\t\tconst ids: FeatureId[] = [];\n\t\tpropertiesToUpdate.forEach(({ id, property, value }) => {\n\t\t\tconst feature = this.store[id];\n\n\t\t\tif (!feature) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No feature with this (${id}), can not update geometry`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tids.push(id);\n\n\t\t\tfeature.properties[property] = value;\n\n\t\t\t// Update the time the feature was updated\n\t\t\tif (this.tracked) {\n\t\t\t\tfeature.properties.updatedAt = +new Date();\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange(ids, \"update\");\n\t\t}\n\t}\n\n\tupdateGeometry(\n\t\tgeometriesToUpdate: { id: FeatureId; geometry: GeoJSONStoreGeometries }[],\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\");\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): 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\");\n\t\t}\n\n\t\treturn ids as Id[];\n\t}\n\n\tdelete(ids: FeatureId[]): 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 this id, can not delete\");\n\t\t\t}\n\t\t});\n\n\t\tif (this._onChange) {\n\t\t\tthis._onChange([...ids], \"delete\");\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 { 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","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} from \"../../common\";\nimport { Polygon } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport { webMercatorBearing } from \"../../geometry/measure/bearing\";\nimport { midpointCoordinate } from \"../../geometry/midpoint-coordinate\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { degreesToRadians } from \"../../geometry/helpers\";\nimport { determineHalfPlane } from \"../../geometry/determine-halfplane\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { calculateRelativeAngle } from \"../../geometry/calculate-relative-angle\";\n\ntype TerraDrawPolygonModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype PolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawPolygonModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawPolygonModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawAngledRectangleMode extends TerraDrawBaseDrawMode<PolygonStyling> {\n\tmode = \"angled-rectangle\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawPolygonModeKeyEvents = defaultKeyEvents;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawPolygonModeOptions<PolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawPolygonModeOptions<PolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst firstCoordinate = currentPolygonCoordinates[0];\n\t\t\tconst secondCoordinate = currentPolygonCoordinates[1];\n\t\t\tconst midpoint = midpointCoordinate(\n\t\t\t\tfirstCoordinate,\n\t\t\t\tsecondCoordinate,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t\tthis.project,\n\t\t\t\tthis.unproject,\n\t\t\t);\n\n\t\t\tconst A = lngLatToWebMercatorXY(firstCoordinate[0], firstCoordinate[1]);\n\t\t\tconst B = lngLatToWebMercatorXY(midpoint[0], midpoint[1]);\n\t\t\tconst C = lngLatToWebMercatorXY(secondCoordinate[0], secondCoordinate[1]);\n\t\t\tconst D = lngLatToWebMercatorXY(event.lng, event.lat);\n\n\t\t\t// Determine if the cursor is closer to A or C\n\t\t\tconst distanceToA = cartesianDistance(D, A);\n\t\t\tconst distanceToB = cartesianDistance(D, C);\n\t\t\tconst ACloserThanC = distanceToA < distanceToB ? true : false;\n\n\t\t\t// We need to work out if the cursor is closer to A or C and then calculate the angle\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst relativeAngle = calculateRelativeAngle(A, B, D);\n\t\t\tconst theta = ACloserThanC\n\t\t\t\t? 90 - relativeAngle\n\t\t\t\t: calculateRelativeAngle(A, B, D) - 90;\n\n\t\t\t// We want to calculate the adjacent i.e. the calculated distance\n\t\t\t// between the cursor and the opposing midpoint\n\t\t\tconst hypotenuse = cartesianDistance(B, D);\n\t\t\tconst adjacent = Math.cos(degreesToRadians(theta)) * hypotenuse;\n\n\t\t\t// Calculate the bearing between the first and second point\n\t\t\tconst firstAndSecondPointBearing = webMercatorBearing(A, C);\n\n\t\t\t// Determine which side of the line the cursor is on\n\t\t\tconst side = determineHalfPlane(A, C, D);\n\n\t\t\t// Determine which direction to draw the rectangle\n\t\t\tconst angle = side === \"right\" ? -90 : 90;\n\n\t\t\t// Calculate the third and fourth coordinates based on the cursor position\n\t\t\tconst rectangleAngle = firstAndSecondPointBearing + angle;\n\t\t\tconst thirdCoordinateXY = webMercatorDestination(\n\t\t\t\tA,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\t\t\tconst fourthCoordinateXY = webMercatorDestination(\n\t\t\t\tC,\n\t\t\t\tadjacent,\n\t\t\t\trectangleAngle,\n\t\t\t);\n\n\t\t\t// Convert the third and fourth coordinates back to lng/lat\n\t\t\tconst thirdCoordinate = webMercatorXYToLngLat(\n\t\t\t\tthirdCoordinateXY.x,\n\t\t\t\tthirdCoordinateXY.y,\n\t\t\t);\n\t\t\tconst fourthCoordinate = webMercatorXYToLngLat(\n\t\t\t\tfourthCoordinateXY.x,\n\t\t\t\tfourthCoordinateXY.y,\n\t\t\t);\n\n\t\t\t// The final coordinates\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\tcurrentPolygonCoordinates[1],\n\t\t\t\t[fourthCoordinate.lng, fourthCoordinate.lat],\n\t\t\t\t[thirdCoordinate.lng, thirdCoordinate.lat],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 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\tthis.currentId,\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\tthis.close();\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 = 10;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\n// Function to determine the relative position of a point to a line segment\nexport function determineHalfPlane(\n\tpoint: CartesianPoint,\n\tlineStart: CartesianPoint,\n\tlineEnd: CartesianPoint,\n): string {\n\t// Calculate the vectors\n\tconst vectorLine = { x: lineEnd.x - lineStart.x, y: lineEnd.y - lineStart.y };\n\tconst vectorPoint = { x: point.x - lineStart.x, y: point.y - lineStart.y };\n\n\t// Calculate the cross product\n\tconst crossProduct =\n\t\tvectorLine.x * vectorPoint.y - vectorLine.y * vectorPoint.x;\n\n\t// Use a small epsilon value to handle floating-point precision errors\n\tconst epsilon = 1e-10;\n\n\tif (crossProduct > epsilon) {\n\t\treturn \"left\";\n\t} else if (crossProduct < -epsilon) {\n\t\treturn \"right\";\n\t} else {\n\t\t// Technically on the line but we treat it as left\n\t\treturn \"left\";\n\t}\n}\n","import { CartesianPoint } from \"../common\";\n\nexport function isClockwiseWebMercator(\n\tcenter: CartesianPoint,\n\tsecondCoord: CartesianPoint,\n\tthirdCoord: CartesianPoint,\n): boolean {\n\t// Calculate the vectors\n\tconst vector1 = { x: secondCoord.x - center.x, y: secondCoord.y - center.y };\n\tconst vector2 = { x: thirdCoord.x - center.x, y: thirdCoord.y - center.y };\n\n\t// Calculate the cross product\n\tconst cross = vector1.x * vector2.y - vector1.y * vector2.x;\n\n\t// If the cross product is negative, the third point is on the right (clockwise)\n\t// If the cross product is positive, the third point is on the left (anticlockwise)\n\treturn cross <= 0;\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n} from \"../../common\";\nimport { Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { coordinatesIdentical } from \"../../geometry/coordinates-identical\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSectorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SectorPolygonStyling = {\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSectorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSectorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSectorMode extends TerraDrawBaseDrawMode<SectorPolygonStyling> {\n\tmode = \"sector\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSectorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSectorModeOptions<SectorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSectorModeOptions<SectorPolygonStyling>,\n\t) {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t);\n\t\tif (correctedGeometry) {\n\t\t\tthis.store.updateGeometry([\n\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t]);\n\t\t}\n\n\t\tconst finishedId = this.currentId;\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tthis.onFinish(finishedId, { mode: this.mode, action: \"draw\" });\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (this.currentId === undefined || this.currentCoordinate === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<Polygon>(\n\t\t\tthis.currentId,\n\t\t).coordinates[0];\n\n\t\tlet updatedCoordinates: Polygon[\"coordinates\"][0] | undefined;\n\n\t\tif (this.currentCoordinate === 1) {\n\t\t\t// We must add a very small epsilon value so that Mapbox GL\n\t\t\t// renders the polygon - There might be a cleaner solution?\n\t\t\tconst epsilon = 1 / Math.pow(10, this.coordinatePrecision - 1);\n\t\t\tconst offset = Math.max(0.000001, epsilon);\n\n\t\t\tupdatedCoordinates = [\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t\t[event.lng, event.lat],\n\t\t\t\t[event.lng, event.lat - offset],\n\t\t\t\tcurrentPolygonCoordinates[0],\n\t\t\t];\n\t\t} else if (this.currentCoordinate === 2) {\n\t\t\tconst center = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[1];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\t// Convert coordinates to Web Mercator\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate the radius (distance from center to second point in Web Mercator)\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [center]; // Start with the center (in WGS84)\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add the first coordinate to the polygon\n\t\t\tcoordinates.push(arcCoordOne);\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(center);\n\n\t\t\tupdatedCoordinates = [...coordinates];\n\t\t}\n\n\t\tif (updatedCoordinates) {\n\t\t\tthis.updatePolygonGeometry(\n\t\t\t\tthis.currentId,\n\t\t\t\tupdatedCoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentId = newId;\n\t\t\tthis.currentCoordinate++;\n\n\t\t\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 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\tthis.currentId,\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\tthis.close();\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 = 10;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n}\n","import {\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\tHexColorStyling,\n\tNumericStyling,\n\tCursor,\n\tUpdateTypes,\n} from \"../../common\";\nimport { LineString, Point, Polygon, Position } from \"geojson\";\nimport {\n\tTerraDrawBaseDrawMode,\n\tBaseModeOptions,\n\tCustomStyling,\n} from \"../base.mode\";\nimport { getDefaultStyling } from \"../../util/styling\";\nimport {\n\tFeatureId,\n\tGeoJSONStoreFeatures,\n\tStoreValidation,\n} from \"../../store/store\";\nimport { ValidateNonIntersectingPolygonFeature } from \"../../validations/polygon.validation\";\nimport { webMercatorDestination } from \"../../geometry/measure/destination\";\nimport {\n\tnormalizeBearing,\n\twebMercatorBearing,\n} from \"../../geometry/measure/bearing\";\nimport {\n\tlngLatToWebMercatorXY,\n\twebMercatorXYToLngLat,\n} from \"../../geometry/project/web-mercator\";\nimport { cartesianDistance } from \"../../geometry/measure/pixel-distance\";\nimport { isClockwiseWebMercator } from \"../../geometry/clockwise\";\nimport { limitPrecision } from \"../../geometry/limit-decimal-precision\";\nimport { ensureRightHandRule } from \"../../geometry/ensure-right-hand-rule\";\n\ntype TerraDrawSensorModeKeyEvents = {\n\tcancel?: KeyboardEvent[\"key\"] | null;\n\tfinish?: KeyboardEvent[\"key\"] | null;\n};\n\nconst defaultKeyEvents = { cancel: \"Escape\", finish: \"Enter\" };\n\ntype SensorPolygonStyling = {\n\tcenterPointColor: HexColorStyling;\n\tcenterPointWidth: NumericStyling;\n\tcenterPointOutlineColor: HexColorStyling;\n\tcenterPointOutlineWidth: NumericStyling;\n\tfillColor: HexColorStyling;\n\toutlineColor: HexColorStyling;\n\toutlineWidth: NumericStyling;\n\tfillOpacity: NumericStyling;\n};\n\ninterface Cursors {\n\tstart?: Cursor;\n\tclose?: Cursor;\n}\n\nconst defaultCursors = {\n\tstart: \"crosshair\",\n\tclose: \"pointer\",\n} as Required<Cursors>;\n\ninterface TerraDrawSensorModeOptions<T extends CustomStyling>\n\textends BaseModeOptions<T> {\n\tarcPoints?: number;\n\tpointerDistance?: number;\n\tkeyEvents?: TerraDrawSensorModeKeyEvents | null;\n\tcursors?: Cursors;\n}\n\nexport class TerraDrawSensorMode extends TerraDrawBaseDrawMode<SensorPolygonStyling> {\n\tmode = \"sensor\" as const;\n\n\tprivate currentCoordinate = 0;\n\tprivate currentId: FeatureId | undefined;\n\tprivate currentInitialArcId: FeatureId | undefined;\n\tprivate currentStartingPointId: FeatureId | undefined;\n\tprivate keyEvents: TerraDrawSensorModeKeyEvents = defaultKeyEvents;\n\tprivate direction: \"clockwise\" | \"anticlockwise\" | undefined;\n\tprivate arcPoints: number = 64;\n\n\t// Behaviors\n\tprivate cursors: Required<Cursors> = defaultCursors;\n\tprivate mouseMove = false;\n\n\tconstructor(options?: TerraDrawSensorModeOptions<SensorPolygonStyling>) {\n\t\tsuper(options, true);\n\t\tthis.updateOptions(options);\n\t}\n\n\toverride updateOptions(\n\t\toptions?: TerraDrawSensorModeOptions<SensorPolygonStyling>,\n\t): void {\n\t\tsuper.updateOptions(options);\n\n\t\tif (options?.cursors) {\n\t\t\tthis.cursors = { ...this.cursors, ...options.cursors };\n\t\t}\n\n\t\tif (options?.keyEvents === null) {\n\t\t\tthis.keyEvents = { cancel: null, finish: null };\n\t\t} else if (options?.keyEvents) {\n\t\t\tthis.keyEvents = { ...this.keyEvents, ...options.keyEvents };\n\t\t}\n\n\t\tif (options?.arcPoints) {\n\t\t\tthis.arcPoints = options.arcPoints;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\tif (this.currentStartingPointId === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst finishedCurrentStartingPointId = this.currentStartingPointId;\n\t\tconst finishedInitialArcId = this.currentInitialArcId;\n\t\tconst finishedCurrentId = this.currentId;\n\n\t\tif (finishedCurrentStartingPointId) {\n\t\t\tthis.store.delete([finishedCurrentStartingPointId]);\n\t\t}\n\n\t\tif (finishedInitialArcId) {\n\t\t\tthis.store.delete([finishedInitialArcId]);\n\t\t}\n\n\t\t// Fix right hand rule if necessary\n\t\tif (this.currentId) {\n\t\t\tconst correctedGeometry = ensureRightHandRule(\n\t\t\t\tthis.store.getGeometryCopy<Polygon>(this.currentId),\n\t\t\t);\n\t\t\tif (correctedGeometry) {\n\t\t\t\tthis.store.updateGeometry([\n\t\t\t\t\t{ id: this.currentId, geometry: correctedGeometry },\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\n\t\tthis.currentCoordinate = 0;\n\t\tthis.currentStartingPointId = undefined;\n\t\tthis.currentInitialArcId = undefined;\n\t\tthis.currentId = undefined;\n\t\tthis.direction = undefined;\n\n\t\t// Go back to started state\n\t\tif (this.state === \"drawing\") {\n\t\t\tthis.setStarted();\n\t\t}\n\n\t\tif (finishedCurrentId) {\n\t\t\tthis.onFinish(finishedCurrentId, { mode: this.mode, action: \"draw\" });\n\t\t}\n\t}\n\n\t/** @internal */\n\tstart() {\n\t\tthis.setStarted();\n\t\tthis.setCursor(this.cursors.start);\n\t}\n\n\t/** @internal */\n\tstop() {\n\t\tthis.cleanUp();\n\t\tthis.setStopped();\n\t\tthis.setCursor(\"unset\");\n\t}\n\n\t/** @internal */\n\tonMouseMove(event: TerraDrawMouseEvent) {\n\t\tthis.mouseMove = true;\n\t\tthis.setCursor(this.cursors.start);\n\n\t\tif (\n\t\t\tthis.currentInitialArcId === undefined ||\n\t\t\tthis.currentStartingPointId === undefined ||\n\t\t\tthis.currentCoordinate === 0\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentCoordinate === 2) {\n\t\t\tconst currentPolygonCoordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst arcCoordOne = currentPolygonCoordinates[0];\n\t\t\tconst arcCoordTwo = [event.lng, event.lat];\n\n\t\t\tconst webMercatorArcCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordOne[0],\n\t\t\t\tarcCoordOne[1],\n\t\t\t);\n\t\t\tconst webMercatorArcCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tarcCoordTwo[0],\n\t\t\t\tarcCoordTwo[1],\n\t\t\t);\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\n\t\t\t// We want to determine the direction of the sector, whether\n\t\t\t// it is clockwise or anticlockwise\n\t\t\tif (this.direction === undefined) {\n\t\t\t\tconst clockwise = isClockwiseWebMercator(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\twebMercatorArcCoordOne,\n\t\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t\t);\n\t\t\t\tthis.direction = clockwise ? \"clockwise\" : \"anticlockwise\";\n\t\t\t}\n\n\t\t\t// Calculate bearings for the second and third points in Web Mercator\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorArcCoordTwo,\n\t\t\t);\n\n\t\t\t// Generate points along the arc in Web Mercator\n\t\t\tconst numberOfPoints = this.arcPoints; // Number of points to approximate the arc\n\t\t\tconst coordinates: Position[] = [arcCoordOne];\n\n\t\t\t// Corrected version to calculate deltaBearing\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tlet deltaBearing;\n\t\t\tif (this.direction === \"anticlockwise\") {\n\t\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\t\tif (deltaBearing < 0) {\n\t\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst bearingStep =\n\t\t\t\t((this.direction === \"anticlockwise\" ? 1 : -1) * deltaBearing) /\n\t\t\t\tnumberOfPoints;\n\n\t\t\t// Add all the arc points\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tcoordinates.push(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.updateLineStringGeometry(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t\tcoordinates,\n\t\t\t\tUpdateTypes.Provisional,\n\t\t\t);\n\t\t} else if (this.currentCoordinate === 3) {\n\t\t\tconst coordinates = this.store.getGeometryCopy<LineString>(\n\t\t\t\tthis.currentInitialArcId,\n\t\t\t).coordinates;\n\n\t\t\tif (coordinates.length < 2) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// This shouldn't happen but we protect against it in case as we can't calculate if the cursor\n\t\t\t// is in the sector otherwise\n\t\t\tif (!this.direction) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst center = this.store.getGeometryCopy<Point>(\n\t\t\t\tthis.currentStartingPointId,\n\t\t\t).coordinates;\n\n\t\t\tconst firstCoord = coordinates[0];\n\t\t\tconst lastCoord = coordinates[coordinates.length - 1];\n\n\t\t\tconst webMercatorCursor = lngLatToWebMercatorXY(event.lng, event.lat);\n\t\t\tconst webMercatorCoordOne = lngLatToWebMercatorXY(\n\t\t\t\tfirstCoord[0],\n\t\t\t\tfirstCoord[1],\n\t\t\t);\n\t\t\tconst webMercatorCoordTwo = lngLatToWebMercatorXY(\n\t\t\t\tlastCoord[0],\n\t\t\t\tlastCoord[1],\n\t\t\t);\n\n\t\t\tconst webMercatorCenter = lngLatToWebMercatorXY(center[0], center[1]);\n\n\t\t\tconst innerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\n\t\t\tconst outerRadius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst hasLessThanZeroSize = outerRadius < innerRadius;\n\n\t\t\t// If the cursor is inside the inner radius, the depth of the sensor is always 0\n\t\t\tconst radiusCalculationPosition = hasLessThanZeroSize\n\t\t\t\t? webMercatorCoordOne\n\t\t\t\t: webMercatorCursor;\n\n\t\t\tconst cursorBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCursor,\n\t\t\t);\n\n\t\t\tconst startBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordOne,\n\t\t\t);\n\t\t\tconst endBearing = webMercatorBearing(\n\t\t\t\twebMercatorCenter,\n\t\t\t\twebMercatorCoordTwo,\n\t\t\t);\n\n\t\t\tconst normalizedStart = normalizeBearing(startBearing);\n\t\t\tconst normalizedEnd = normalizeBearing(endBearing);\n\t\t\tconst normalizedCursor = normalizeBearing(cursorBearing);\n\n\t\t\tconst notInSector = this.notInSector({\n\t\t\t\tnormalizedCursor,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t\tdirection: this.direction,\n\t\t\t});\n\n\t\t\t// If it's not a valid cursor movement then we don't update\n\t\t\tif (notInSector) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Calculate the delta bearing based on the direction\n\t\t\tconst deltaBearing = this.getDeltaBearing(\n\t\t\t\tthis.direction,\n\t\t\t\tnormalizedStart,\n\t\t\t\tnormalizedEnd,\n\t\t\t);\n\n\t\t\t// Number of points to approximate the arc\n\t\t\tconst numberOfPoints = this.arcPoints;\n\n\t\t\t// Calculate bearing step\n\t\t\tconst multiplier = this.direction === \"anticlockwise\" ? 1 : -1;\n\t\t\tconst bearingStep = (multiplier * deltaBearing) / numberOfPoints;\n\n\t\t\tconst radius = cartesianDistance(\n\t\t\t\twebMercatorCenter,\n\t\t\t\tradiusCalculationPosition,\n\t\t\t);\n\n\t\t\t// Add all the arc points\n\t\t\tconst finalArc = [];\n\t\t\tfor (let i = 0; i <= numberOfPoints; i++) {\n\t\t\t\tconst currentBearing = normalizedStart + i * bearingStep;\n\t\t\t\tconst pointOnArc = webMercatorDestination(\n\t\t\t\t\twebMercatorCenter,\n\t\t\t\t\tradius,\n\t\t\t\t\tcurrentBearing,\n\t\t\t\t);\n\t\t\t\tconst { lng, lat } = webMercatorXYToLngLat(pointOnArc.x, pointOnArc.y);\n\n\t\t\t\tconst nextCoord = [\n\t\t\t\t\tlimitPrecision(lng, this.coordinatePrecision),\n\t\t\t\t\tlimitPrecision(lat, this.coordinatePrecision),\n\t\t\t\t];\n\n\t\t\t\tconst notIdentical =\n\t\t\t\t\tnextCoord[0] !== coordinates[coordinates.length - 1][0] &&\n\t\t\t\t\tnextCoord[1] !== coordinates[coordinates.length - 1][1];\n\t\t\t\tif (notIdentical) {\n\t\t\t\t\tfinalArc.unshift(nextCoord);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcoordinates.push(...finalArc);\n\n\t\t\t// Close the polygon\n\t\t\tcoordinates.push(coordinates[0]);\n\n\t\t\t// If the polygon doesn't exist, create it\n\t\t\t// else update the existing geometry\n\t\t\tif (!this.currentId) {\n\t\t\t\t[this.currentId] = this.store.create([\n\t\t\t\t\t{\n\t\t\t\t\t\tgeometry: {\n\t\t\t\t\t\t\ttype: \"Polygon\",\n\t\t\t\t\t\t\tcoordinates: [coordinates],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\tthis.updatePolygonGeometry(\n\t\t\t\t\tthis.currentId,\n\t\t\t\t\tcoordinates,\n\t\t\t\t\tUpdateTypes.Provisional,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateLineStringGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: LineString[\"coordinates\"],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"LineString\",\n\t\t\tcoordinates,\n\t\t} as LineString;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\tprivate updatePolygonGeometry(\n\t\tid: FeatureId,\n\t\tcoordinates: Polygon[\"coordinates\"][0],\n\t\tupdateType: UpdateTypes,\n\t) {\n\t\tconst updatedGeometry = {\n\t\t\ttype: \"Polygon\",\n\t\t\tcoordinates: [coordinates],\n\t\t} as Polygon;\n\n\t\tif (this.validate) {\n\t\t\tconst validationResult = this.validate(\n\t\t\t\t{\n\t\t\t\t\ttype: \"Feature\",\n\t\t\t\t\tgeometry: updatedGeometry,\n\t\t\t\t} as GeoJSONStoreFeatures,\n\t\t\t\t{\n\t\t\t\t\tproject: this.project,\n\t\t\t\t\tunproject: this.unproject,\n\t\t\t\t\tcoordinatePrecision: this.coordinatePrecision,\n\t\t\t\t\tupdateType,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!validationResult.valid) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.store.updateGeometry([{ id, geometry: updatedGeometry }]);\n\n\t\treturn true;\n\t}\n\n\t/** @internal */\n\tonClick(event: TerraDrawMouseEvent) {\n\t\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 triggered 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 (this.currentCoordinate === 0) {\n\t\t\tconst [newId] = this.store.create([\n\t\t\t\t{\n\t\t\t\t\tgeometry: { type: \"Point\", coordinates: [event.lng, event.lat] },\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentStartingPointId = newId;\n\t\t\tthis.currentCoordinate++;\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.currentStartingPointId) {\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: \"LineString\",\n\t\t\t\t\t\tcoordinates: [\n\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t\t[event.lng, event.lat],\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tproperties: { mode: this.mode },\n\t\t\t\t},\n\t\t\t]);\n\t\t\tthis.currentInitialArcId = newId;\n\t\t\tthis.currentCoordinate++;\n\t\t} else if (this.currentCoordinate === 2 && this.currentStartingPointId) {\n\t\t\tthis.currentCoordinate++;\n\t\t\t// pass\n\t\t} else if (this.currentCoordinate === 3 && this.currentStartingPointId) {\n\t\t\tthis.close();\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 = 10;\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 = 10;\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 = 20;\n\t\t\t}\n\t\t}\n\n\t\treturn styles;\n\t}\n\n\tvalidateFeature(feature: unknown): StoreValidation {\n\t\treturn this.validateModeFeature(feature, (baseValidatedFeature) =>\n\t\t\tValidateNonIntersectingPolygonFeature(\n\t\t\t\tbaseValidatedFeature,\n\t\t\t\tthis.coordinatePrecision,\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate getDeltaBearing(\n\t\tdirection: \"anticlockwise\" | \"clockwise\",\n\t\tnormalizedStart: number,\n\t\tnormalizedEnd: number,\n\t) {\n\t\tlet deltaBearing;\n\t\tif (direction === \"anticlockwise\") {\n\t\t\tdeltaBearing = normalizedEnd - normalizedStart;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t} else {\n\t\t\tdeltaBearing = normalizedStart - normalizedEnd;\n\t\t\tif (deltaBearing < 0) {\n\t\t\t\tdeltaBearing += 360; // Adjust for wrap-around\n\t\t\t}\n\t\t}\n\t\treturn deltaBearing;\n\t}\n\n\tprivate notInSector({\n\t\tnormalizedCursor,\n\t\tnormalizedStart,\n\t\tnormalizedEnd,\n\t\tdirection,\n\t}: {\n\t\tnormalizedCursor: number;\n\t\tnormalizedStart: number;\n\t\tnormalizedEnd: number;\n\t\tdirection: \"clockwise\" | \"anticlockwise\";\n\t}) {\n\t\tif (direction === \"clockwise\") {\n\t\t\t// Handle clockwise direction\n\t\t\tif (normalizedStart <= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart &&\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor >= normalizedStart ||\n\t\t\t\t\tnormalizedCursor <= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Handle anticlockwise direction\n\t\t\tif (normalizedStart >= normalizedEnd) {\n\t\t\t\t// Standard case (no wrap-around)\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart &&\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Handle wrap-around across 360 degrees\n\t\t\t\treturn (\n\t\t\t\t\tnormalizedCursor <= normalizedStart ||\n\t\t\t\t\tnormalizedCursor >= normalizedEnd\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n","export class AdapterListener<Callback extends (...args: any[]) => any> {\n\tpublic name: string;\n\tpublic callback: (...args: any[]) => any;\n\tpublic registered = false;\n\tpublic register: any;\n\tpublic unregister: any;\n\n\t/**\n\t * Creates a new AdapterListener instance with the provided configuration.\n\t *\n\t * @param {Object} config - The configuration object for the listener.\n\t * @param {string} config.name - The name of the event listener.\n\t * @param {Function} config.callback - The callback function to be called when the event is triggered.\n\t * @param {Function} config.unregister - The function to unregister the event listeners.\n\t * @param {Function} config.register - The function to register the event listeners.\n\t */\n\tconstructor({\n\t\tname,\n\t\tcallback,\n\t\tunregister,\n\t\tregister,\n\t}: {\n\t\tname: string;\n\t\tcallback: Callback;\n\t\tunregister: (callbacks: Callback) => void;\n\t\tregister: (callback: Callback) => void;\n\t}) {\n\t\tthis.name = name;\n\n\t\t// Function to register the event listeners\n\t\tthis.register = () => {\n\t\t\tif (!this.registered) {\n\t\t\t\tthis.registered = true;\n\t\t\t\tregister(callback);\n\t\t\t}\n\t\t};\n\n\t\t// Function to unregister the event listeners\n\t\tthis.unregister = () => {\n\t\t\tif (this.register) {\n\t\t\t\tthis.registered = false;\n\t\t\t\tunregister(callback);\n\t\t\t}\n\t\t};\n\n\t\tthis.callback = callback;\n\t}\n}\n","import {\n\tProject,\n\tUnproject,\n\tTerraDrawCallbacks,\n\tTerraDrawChanges,\n\tTerraDrawMouseEvent,\n\tSetCursor,\n\tTerraDrawStylingFunction,\n\tGetLngLatFromEvent,\n\tTerraDrawAdapter,\n} from \"../common\";\nimport { limitPrecision } from \"../geometry/limit-decimal-precision\";\nimport { cartesianDistance } from \"../geometry/measure/pixel-distance\";\nimport { AdapterListener } from \"./adapter-listener\";\n\ntype BasePointerListener = (event: PointerEvent) => void;\ntype BaseKeyboardListener = (event: KeyboardEvent) => void;\ntype BaseMouseListener = (event: MouseEvent) => void;\n\nexport type BaseAdapterConfig = {\n\tcoordinatePrecision?: number;\n\tminPixelDragDistanceDrawing?: number;\n\tminPixelDragDistance?: number;\n\tminPixelDragDistanceSelecting?: number;\n};\n\nexport abstract class TerraDrawBaseAdapter implements TerraDrawAdapter {\n\tconstructor(config: BaseAdapterConfig) {\n\t\tthis._minPixelDragDistance =\n\t\t\ttypeof config.minPixelDragDistance === \"number\"\n\t\t\t\t? config.minPixelDragDistance\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceSelecting =\n\t\t\ttypeof config.minPixelDragDistanceSelecting === \"number\"\n\t\t\t\t? config.minPixelDragDistanceSelecting\n\t\t\t\t: 1;\n\n\t\tthis._minPixelDragDistanceDrawing =\n\t\t\ttypeof config.minPixelDragDistanceDrawing === \"number\"\n\t\t\t\t? config.minPixelDragDistanceDrawing\n\t\t\t\t: 8;\n\n\t\tthis._coordinatePrecision =\n\t\t\ttypeof config.coordinatePrecision === \"number\"\n\t\t\t\t? config.coordinatePrecision\n\t\t\t\t: 9;\n\t}\n\n\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): 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};\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\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\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\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\t\tthis.clear();\n\t}\n\n\tpublic abstract clear(): void;\n\n\tpublic abstract project(...args: Parameters<Project>): ReturnType<Project>;\n\n\tpublic abstract unproject(\n\t\t...args: Parameters<Unproject>\n\t): ReturnType<Unproject>;\n\n\tpublic abstract setCursor(\n\t\t...args: Parameters<SetCursor>\n\t): ReturnType<SetCursor>;\n\n\tpublic abstract getLngLatFromEvent(\n\t\t...event: Parameters<GetLngLatFromEvent>\n\t): ReturnType<GetLngLatFromEvent>;\n\n\tpublic abstract setDraggability(enabled: boolean): void;\n\n\tpublic abstract setDoubleClickToZoom(enabled: boolean): void;\n\n\tpublic abstract render(\n\t\tchanges: TerraDrawChanges,\n\t\tstyling: TerraDrawStylingFunction,\n\t): void;\n}\n","import {\n\tValidationReasonModeMismatch,\n\tValidationReasonFeatureNotPolygon,\n} from \"./validations/common-validations\";\nimport { ValidationReasonFeatureLessThanMinSize } from \"./validations/min-size.validation\";\nimport {\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n} from \"./validations/not-self-intersecting.validation\";\nimport {\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n} from \"./validations/point.validation\";\nimport {\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n} from \"./validations/polygon.validation\";\n\nexport const ValidationReasons = {\n\tValidationReasonFeatureNotPoint,\n\tValidationReasonFeatureInvalidCoordinates,\n\tValidationReasonFeatureInvalidCoordinatePrecision,\n\tValidationReasonFeatureNotPolygon,\n\tValidationReasonFeatureHasHoles,\n\tValidationReasonFeatureLessThanFourCoordinates,\n\tValidationReasonFeatureHasInvalidCoordinates,\n\tValidationReasonFeatureCoordinatesNotClosed,\n\tValidationReasonFeatureNotPolygonOrLineString,\n\tValidationReasonFeatureSelfIntersects,\n\tValidationReasonFeatureLessThanMinSize,\n\tValidationReasonModeMismatch,\n};\n","/**\n * @module terra-draw\n */\nimport {\n\tTerraDrawAdapter,\n\tTerraDrawAdapterStyling,\n\tGetLngLatFromEvent,\n\tProject,\n\tSetCursor,\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tUnproject,\n\tHexColor,\n\tTerraDrawKeyboardEvent,\n\tTerraDrawMouseEvent,\n\tSELECT_PROPERTIES,\n\tOnFinishContext,\n} from \"./common\";\nimport {\n\tCustomStyling,\n\tModeTypes,\n\tTerraDrawBaseDrawMode,\n\tTerraDrawBaseSelectMode,\n} from \"./modes/base.mode\";\nimport { TerraDrawCircleMode } from \"./modes/circle/circle.mode\";\nimport { TerraDrawFreehandMode } from \"./modes/freehand/freehand.mode\";\nimport { TerraDrawLineStringMode } from \"./modes/linestring/linestring.mode\";\nimport { TerraDrawPointMode } from \"./modes/point/point.mode\";\nimport { TerraDrawPolygonMode } from \"./modes/polygon/polygon.mode\";\nimport { TerraDrawRectangleMode } from \"./modes/rectangle/rectangle.mode\";\nimport { TerraDrawRenderMode } from \"./modes/render/render.mode\";\nimport { TerraDrawSelectMode } from \"./modes/select/select.mode\";\nimport { TerraDrawStaticMode } from \"./modes/static/static.mode\";\nimport {\n\tBBoxPolygon,\n\tFeatureId,\n\tGeoJSONStore,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tIdStrategy,\n\tStoreChangeHandler,\n\tStoreValidation,\n} from \"./store/store\";\nimport { BehaviorConfig } from \"./modes/base.behavior\";\nimport { cartesianDistance } from \"./geometry/measure/pixel-distance\";\nimport { pixelDistanceToLine } from \"./geometry/measure/pixel-distance-to-line\";\nimport { Position } from \"geojson\";\nimport { pointInPolygon } from \"./geometry/boolean/point-in-polygon\";\nimport { createBBoxFromPoint } from \"./geometry/shape/create-bbox\";\nimport { ValidateMinAreaSquareMeters } from \"./validations/min-size.validation\";\nimport { ValidateMaxAreaSquareMeters } from \"./validations/max-size.validation\";\nimport { ValidateNotSelfIntersecting } from \"./validations/not-self-intersecting.validation\";\nimport { TerraDrawAngledRectangleMode } from \"./modes/angled-rectangle/angled-rectangle.mode\";\nimport { TerraDrawSectorMode } from \"./modes/sector/sector.mode\";\nimport { TerraDrawSensorMode } from \"./modes/sensor/sensor.mode\";\nimport * as TerraDrawExtend from \"./extend\";\nimport { hasModeProperty } from \"./store/store-feature-validation\";\nimport { ValidationReasons } from \"./validation-reasons\";\n\n// Helper type to determine the instance type of a class\ntype InstanceType<T extends new (...args: any[]) => any> = T extends new (\n\t...args: any[]\n) => infer R\n\t? R\n\t: never;\n\ntype FinishListener = (id: FeatureId, context: OnFinishContext) => void;\ntype ChangeListener = (ids: FeatureId[], type: string) => void;\ntype SelectListener = (id: FeatureId) => void;\ntype DeselectListener = () => void;\n\ninterface TerraDrawEventListeners {\n\tready: () => void;\n\tfinish: FinishListener;\n\tchange: ChangeListener;\n\tselect: SelectListener;\n\tdeselect: DeselectListener;\n}\n\ntype TerraDrawEvents = keyof TerraDrawEventListeners;\n\nclass TerraDraw {\n\tprivate _modes: {\n\t\t[mode: string]: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\t};\n\tprivate _mode: TerraDrawBaseDrawMode<any> | TerraDrawBaseSelectMode<any>;\n\tprivate _adapter: TerraDrawAdapter;\n\tprivate _enabled = false;\n\tprivate _store: GeoJSONStore;\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<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 = (ids, event) => {\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);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged(ids);\n\n\t\t\tif (event === \"create\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: changed,\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: [],\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"update\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"delete\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: ids, unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t} else if (event === \"styling\") {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: [] },\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onSelect = (selectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.select.forEach((listener) => {\n\t\t\t\tlistener(selectedId);\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([selectedId]);\n\n\t\t\tthis._adapter.render(\n\t\t\t\t{ created: [], deletedIds: [], unchanged, updated: changed },\n\t\t\t\tthis.getModeStyles(),\n\t\t\t);\n\t\t};\n\n\t\tconst onDeselect = (deselectedId: string) => {\n\t\t\tif (!this._enabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._eventListeners.deselect.forEach((listener) => {\n\t\t\t\tlistener();\n\t\t\t});\n\n\t\t\tconst { changed, unchanged } = getChanged([deselectedId]);\n\n\t\t\t// onDeselect can be called after a delete call which means that\n\t\t\t// you are deselecting a feature that has been deleted. We\n\t\t\t// double check here to ensure that the feature still exists.\n\t\t\tif (changed) {\n\t\t\t\tthis._adapter.render(\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated: [],\n\t\t\t\t\t\tdeletedIds: [],\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tupdated: changed,\n\t\t\t\t\t},\n\t\t\t\t\tthis.getModeStyles(),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\t// Register stores and callbacks\n\t\tObject.keys(this._modes).forEach((modeId) => {\n\t\t\tthis._modes[modeId].register({\n\t\t\t\tmode: modeId,\n\t\t\t\tstore: this._store,\n\t\t\t\tsetCursor: this._adapter.setCursor.bind(this._adapter),\n\t\t\t\tproject: this._adapter.project.bind(this._adapter),\n\t\t\t\tunproject: this._adapter.unproject.bind(this._adapter),\n\t\t\t\tsetDoubleClickToZoom: this._adapter.setDoubleClickToZoom.bind(\n\t\t\t\t\tthis._adapter,\n\t\t\t\t),\n\t\t\t\tonChange: onChange,\n\t\t\t\tonSelect: onSelect,\n\t\t\t\tonDeselect: onDeselect,\n\t\t\t\tonFinish: onFinish,\n\t\t\t\tcoordinatePrecision: this._adapter.getCoordinatePrecision(),\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate checkEnabled() {\n\t\tif (!this._enabled) {\n\t\t\tthrow new Error(\"Terra Draw is not enabled\");\n\t\t}\n\t}\n\n\tprivate getModeStyles() {\n\t\tconst modeStyles: {\n\t\t\t[key: string]: (feature: GeoJSONStoreFeatures) => TerraDrawAdapterStyling;\n\t\t} = {};\n\n\t\tObject.keys(this._modes).forEach((mode) => {\n\t\t\tmodeStyles[mode] = (feature: GeoJSONStoreFeatures) => {\n\t\t\t\t// If the feature is selected, we want to use the select mode styling\n\t\t\t\tif (\n\t\t\t\t\tthis._instanceSelectMode &&\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTED]\n\t\t\t\t) {\n\t\t\t\t\treturn this._modes[this._instanceSelectMode].styleFeature.bind(\n\t\t\t\t\t\tthis._modes[this._instanceSelectMode],\n\t\t\t\t\t)(feature);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise use regular styling\n\t\t\t\treturn this._modes[mode].styleFeature.bind(this._modes[mode])(feature);\n\t\t\t};\n\t\t});\n\t\treturn modeStyles;\n\t}\n\n\tprivate featuresAtLocation(\n\t\t{\n\t\t\tlng,\n\t\t\tlat,\n\t\t}: {\n\t\t\tlng: number;\n\t\t\tlat: number;\n\t\t},\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst pointerDistance =\n\t\t\toptions && options.pointerDistance !== undefined\n\t\t\t\t? options.pointerDistance\n\t\t\t\t: 30; // default is 30px\n\n\t\tconst ignoreSelectFeatures =\n\t\t\toptions && options.ignoreSelectFeatures !== undefined\n\t\t\t\t? options.ignoreSelectFeatures\n\t\t\t\t: true;\n\n\t\tconst unproject = this._adapter.unproject.bind(this._adapter);\n\t\tconst project = this._adapter.project.bind(this._adapter);\n\n\t\tconst inputPoint = project(lng, lat);\n\n\t\tconst bbox = createBBoxFromPoint({\n\t\t\tunproject,\n\t\t\tpoint: inputPoint,\n\t\t\tpointerDistance,\n\t\t});\n\n\t\tconst features = this._store.search(bbox as BBoxPolygon);\n\n\t\t// TODO: This is designed to work in a similar way as FeatureAtPointerEvent\n\t\t// perhaps at some point we could figure out how to unify them\n\t\treturn features.filter((feature) => {\n\t\t\tif (\n\t\t\t\tignoreSelectFeatures &&\n\t\t\t\t(feature.properties[SELECT_PROPERTIES.MID_POINT] ||\n\t\t\t\t\tfeature.properties[SELECT_PROPERTIES.SELECTION_POINT])\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (feature.geometry.type === \"Point\") {\n\t\t\t\tconst pointCoordinates = feature.geometry.coordinates;\n\t\t\t\tconst pointXY = project(pointCoordinates[0], pointCoordinates[1]);\n\t\t\t\tconst distance = cartesianDistance(inputPoint, pointXY);\n\t\t\t\treturn distance < pointerDistance;\n\t\t\t} else if (feature.geometry.type === \"LineString\") {\n\t\t\t\tconst coordinates: Position[] = feature.geometry.coordinates;\n\n\t\t\t\tfor (let i = 0; i < coordinates.length - 1; i++) {\n\t\t\t\t\tconst coord = coordinates[i];\n\t\t\t\t\tconst nextCoord = coordinates[i + 1];\n\t\t\t\t\tconst distanceToLine = pixelDistanceToLine(\n\t\t\t\t\t\tinputPoint,\n\t\t\t\t\t\tproject(coord[0], coord[1]),\n\t\t\t\t\t\tproject(nextCoord[0], nextCoord[1]),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (distanceToLine < pointerDistance) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\tconst lngLatInsidePolygon = pointInPolygon(\n\t\t\t\t\t[lng, lat],\n\t\t\t\t\tfeature.geometry.coordinates,\n\t\t\t\t);\n\n\t\t\t\tif (lngLatInsidePolygon) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate getSelectMode() {\n\t\tthis.checkEnabled();\n\n\t\tif (!this._instanceSelectMode) {\n\t\t\tthrow new Error(\"No select mode defined in instance\");\n\t\t}\n\n\t\tconst currentMode = this.getMode();\n\n\t\t// If we're not already in the select mode, we switch to it\n\t\tif (currentMode !== this._instanceSelectMode) {\n\t\t\tthis.setMode(this._instanceSelectMode);\n\t\t}\n\n\t\tconst selectMode = this._modes[\n\t\t\tthis._instanceSelectMode\n\t\t] as TerraDrawBaseSelectMode<any>;\n\n\t\treturn selectMode;\n\t}\n\n\t/**\n\t * @deprecated This method is scheduled for removal in the next major version. Instead use the 'updateModeOptions' method passing the\n\t * styles property in the options object, and this will dynamically update the styles for the mode.\n\t *\n\t * Allows the setting of a style for a given mode\n\t *\n\t * @param mode - The mode you wish to set a style for\n\t * @param styles - The styles you wish to set for the mode - this is\n\t * the same as the initialisation style schema\n\t */\n\tsetModeStyles<Styling extends Record<string, number | HexColor>>(\n\t\tmode: string,\n\t\tstyles: Styling,\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\t// TODO: Not sure why this fails TypeScript with TerraDrawBaseSelectMode?\n\t\t(this._modes[mode] as TerraDrawBaseDrawMode<any>).styles = styles;\n\t}\n\n\t/**\n\t * Allow updating of the current options passed to the mode dynamically\n\t * after the mode has been started. You can also use this method to update styles\n\t * as these are passed from the options object.\n\t * @param mode - the mode name you wish to update (the mode name is the public 'mode' property of the mode class)\n\t * @param options - the options object - this allows _partial_ updating of the modes options (i.e. you do not need to pass the whole options object)\n\t */\n\tupdateModeOptions<Mode extends { new (...args: any[]): any }>(\n\t\tmode: InstanceType<Mode>[\"mode\"],\n\t\toptions: ConstructorParameters<Mode>[0],\n\t) {\n\t\tthis.checkEnabled();\n\t\tif (!this._modes[mode]) {\n\t\t\tthrow new Error(\"No mode with this name present\");\n\t\t}\n\n\t\tthis._modes[mode].updateOptions(\n\t\t\toptions as TerraDrawExtend.BaseModeOptions<any>,\n\t\t);\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of all given features\n\t *\n\t * @returns An array of all given Feature Geometries in the instances store\n\t */\n\tgetSnapshot() {\n\t\t// This is a read only method so we do not need to check if enabled\n\t\treturn this._store.copyAll();\n\t}\n\n\t/**\n\t * Allows the user to get a snapshot (copy) of a given feature by id\n\t *\n\t * @returns A copy of the feature geometry in the instances store\n\t */\n\tgetSnapshotFeature(id: FeatureId) {\n\t\tif (!this._store.has(id)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._store.copy(id);\n\t}\n\n\t/**\n\t * Removes all data from the current store and removes any rendered layers\n\t * via the registering the adapter.\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 * 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\t\tthis._store.delete(ids);\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 selectMdode = this.getSelectMode();\n\t\tselectMdode.selectFeature(id);\n\t}\n\n\t/**\n\t * Provides the ability to programmatically deselect a feature using the instances provided select mode.\n\t * If not select mode is provided in the instance, an error will be thrown. If the instance is not currently\n\t * in the select mode, it will switch to it.\n\t * @param id - the id of the feature to deselect\n\t */\n\tdeselectFeature(id: FeatureId) {\n\t\tconst selectMode = this.getSelectMode();\n\t\tselectMode.deselectFeature(id);\n\t}\n\n\t/**\n\t * Returns the next feature id from the store - defaults to UUID4 unless you have\n\t * set a custom idStrategy. This method can be useful if you are needing creating features\n\t * outside of the Terra Draw instance but want to add them in to the store.\n\t * @returns a id, either number of string based on whatever the configured idStrategy is\n\t *\n\t */\n\tgetFeatureId(): FeatureId {\n\t\treturn this._store.getId();\n\t}\n\n\t/**\n\t * Returns true or false depending on if the Terra Draw instance has a feature with a given id\n\t * @returns a boolean determining if the instance has a feature with the given id\n\t */\n\thasFeature(id: FeatureId): boolean {\n\t\treturn this._store.has(id);\n\t}\n\n\t/**\n\t * A method for adding features to the store. This method will validate the features\n\t * returning an array of validation results. Features must match one of the modes enabled\n\t * in the instance.\n\t * @param features - an array of GeoJSON features\n\t * @returns an array of validation results\n\t */\n\taddFeatures(features: GeoJSONStoreFeatures[]): StoreValidation[] {\n\t\tthis.checkEnabled();\n\n\t\tif (features.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this._store.load(\n\t\t\tfeatures,\n\t\t\t(feature) => {\n\t\t\t\t// If the feature has a mode property, we use that to validate the feature\n\t\t\t\tif (hasModeProperty(feature)) {\n\t\t\t\t\tconst featureMode = feature.properties.mode;\n\t\t\t\t\tconst modeToAddTo = this._modes[featureMode];\n\n\t\t\t\t\t// if the mode does not exist, we return false\n\t\t\t\t\tif (!modeToAddTo) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\t\t\tvalid: false,\n\t\t\t\t\t\t\treason: `${featureMode} mode is not in the list of instantiated modes`,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// use the inbuilt validation of the mode\n\t\t\t\t\tconst validation = modeToAddTo.validateFeature.bind(modeToAddTo);\n\t\t\t\t\tconst validationResult = validation(feature);\n\t\t\t\t\tconst valid = validationResult.valid;\n\t\t\t\t\tconst reason = validationResult.reason\n\t\t\t\t\t\t? validationResult.reason\n\t\t\t\t\t\t: !validationResult.valid\n\t\t\t\t\t\t\t? \"Feature is invalid\"\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\t\tvalid,\n\t\t\t\t\t\treason,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// If the feature does not have a mode property, we return false\n\t\t\t\treturn {\n\t\t\t\t\tid: (feature as { id?: FeatureId }).id,\n\t\t\t\t\tvalid: false,\n\t\t\t\t\treason: \"Mode property does not exist\",\n\t\t\t\t};\n\t\t\t},\n\t\t\t(feature) => {\n\t\t\t\tif (hasModeProperty(feature)) {\n\t\t\t\t\tconst featureMode = feature.properties.mode;\n\t\t\t\t\tconst modeToAddTo = this._modes[featureMode];\n\t\t\t\t\tif (modeToAddTo && modeToAddTo.afterFeatureAdded) {\n\t\t\t\t\t\tmodeToAddTo.afterFeatureAdded(feature);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t);\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\tthis._enabled = true;\n\t\tthis._adapter.register({\n\t\t\tonReady: () => {\n\t\t\t\tthis._eventListeners.ready.forEach((listener) => {\n\t\t\t\t\tlistener();\n\t\t\t\t});\n\t\t\t},\n\t\t\tgetState: () => {\n\t\t\t\treturn this._mode.state;\n\t\t\t},\n\t\t\tonClick: (event) => {\n\t\t\t\tthis._mode.onClick(event);\n\t\t\t},\n\t\t\tonMouseMove: (event) => {\n\t\t\t\tthis._mode.onMouseMove(event);\n\t\t\t},\n\t\t\tonKeyDown: (event) => {\n\t\t\t\tthis._mode.onKeyDown(event);\n\t\t\t},\n\t\t\tonKeyUp: (event) => {\n\t\t\t\tthis._mode.onKeyUp(event);\n\t\t\t},\n\t\t\tonDragStart: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragStart(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDrag: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDrag(event, setMapDraggability);\n\t\t\t},\n\t\t\tonDragEnd: (event, setMapDraggability) => {\n\t\t\t\tthis._mode.onDragEnd(event, setMapDraggability);\n\t\t\t},\n\t\t\tonClear: () => {\n\t\t\t\t// Ensure that the mode resets its state\n\t\t\t\t// as it may be storing feature ids internally in it's instance\n\t\t\t\tthis._mode.cleanUp();\n\n\t\t\t\t// Remove all features from the store\n\t\t\t\tthis._store.clear();\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Gets the features at a given longitude and latitude.\n\t * Will return point and linestrings that are a given pixel distance\n\t * away from the lng/lat and any polygons which contain it.\n\t */\n\tgetFeaturesAtLngLat(\n\t\tlngLat: { lng: number; lat: number },\n\t\toptions?: { pointerDistance: number; ignoreSelectFeatures: boolean },\n\t) {\n\t\tconst { lng, lat } = lngLat;\n\n\t\treturn this.featuresAtLocation(\n\t\t\t{\n\t\t\t\tlng,\n\t\t\t\tlat,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Takes a given pointer event and will return point and linestrings that are\n\t * a given pixel distance away from the longitude/latitude, and any polygons which contain it.\n\t */\n\tgetFeaturesAtPointerEvent(\n\t\tevent: PointerEvent | MouseEvent,\n\t\toptions?: { pointerDistance?: number; ignoreSelectFeatures?: boolean },\n\t) {\n\t\tconst getLngLatFromEvent = this._adapter.getLngLatFromEvent.bind(\n\t\t\tthis._adapter,\n\t\t);\n\n\t\tconst lngLat = getLngLatFromEvent(event);\n\n\t\t// If the pointer event is outside the container or the underlying library is\n\t\t// not ready we can get null as a returned value\n\t\tif (lngLat === null) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this.featuresAtLocation(lngLat, options);\n\t}\n\n\t/**\n\t * A method for stopping Terra Draw. Will clear the store, deregister the adapter and\n\t * remove any rendered layers in the process.\n\t */\n\tstop() {\n\t\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\n\t// Modes\n\tTerraDrawSelectMode,\n\tTerraDrawPointMode,\n\tTerraDrawLineStringMode,\n\tTerraDrawPolygonMode,\n\tTerraDrawCircleMode,\n\tTerraDrawFreehandMode,\n\tTerraDrawRenderMode,\n\tTerraDrawRectangleMode,\n\tTerraDrawAngledRectangleMode,\n\tTerraDrawSectorMode,\n\tTerraDrawSensorMode,\n\n\t// Types that are required for 3rd party developers to extend\n\tTerraDrawExtend,\n\n\t// TerraDrawBaseMode\n\tBehaviorConfig,\n\tGeoJSONStoreFeatures,\n\tGeoJSONStoreGeometries,\n\tHexColor,\n\tTerraDrawMouseEvent,\n\tTerraDrawAdapterStyling,\n\tTerraDrawKeyboardEvent,\n\n\t// TerraDrawBaseAdapter\n\tTerraDrawChanges,\n\tTerraDrawStylingFunction,\n\tProject,\n\tUnproject,\n\tSetCursor,\n\tGetLngLatFromEvent,\n\n\t// Validations\n\tValidateMinAreaSquareMeters,\n\tValidateMaxAreaSquareMeters,\n\tValidateNotSelfIntersecting,\n\tValidationReasons,\n};\n"],"names":["UpdateTypes","SELECT_PROPERTIES","SELECTED","MID_POINT","SELECTION_POINT","COMMON_PROPERTIES","isObject","feature","Boolean","Array","isArray","hasModeProperty","properties","isValidTimestamp","timestamp","isNaN","Date","valueOf","dateIsValid","ValidationReasonFeatureNotPolygon","ValidationReasonModeMismatch","ModeTypes","TerraDrawBaseDrawMode","state","this","_state","_","Error","styles","_styles","styling","onStyleChange","registerBehaviors","behaviorConfig","constructor","options","willCallUpdateOptionsInParentClass","behaviors","validate","pointerDistance","coordinatePrecision","store","projection","setDoubleClickToZoom","unproject","project","setCursor","type","Drawing","mode","updateOptions","_extends","validation","setDrawing","setStarted","setStopped","register","config","registerOnChange","onChange","onSelect","onDeselect","onFinish","validateFeature","performFeatureValidation","afterFeatureAdded","validStoreFeature","isValidId","error","id","geometry","includes","coordinates","valid","reason","isValidStoreFeature","idStrategy","updateType","Provisional","validateModeFeature","modeValidationFn","finishedId","context","deselectedId","selectedId","onKeyDown","event","onKeyUp","onMouseMove","onClick","onDragStart","setMapDraggability","onDrag","onDragEnd","getHexColorStylingValue","value","defaultValue","getStylingValue","getNumericStylingValue","undefined","TerraDrawBaseSelectMode","args","Select","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","length","edge0","ring1","edge1","ifInteresctionAddToOutput","isOutside","frac","start0","end0","start1","end1","intersection","equalArrays","x0","y0","x1","y1","x2","y2","x3","y3","denom","intersect","frac0","frac1","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","super","clickCount","currentCircleId","keyEvents","cursors","startingRadiusKilometers","cursorMovedAfterInitialCursorDown","close","currentGeometry","getGeometryCopy","Finish","action","stop","cleanUp","startingCircle","createdId","create","updateCircle","key","cleanUpId","delete","_unused","styleFeature","polygonFillColor","polygonOutlineColor","polygonOutlineWidth","polygonFillOpacity","pointColor","pointOutlineColor","pointOutlineWidth","pointWidth","lineStringColor","lineStringWidth","zIndex","fillColor","outlineColor","outlineWidth","fillOpacity","baseValidatedFeature","newRadius","updatedCircle","distortion","source","target","geodesicDistance","calculateWebMercatorDistortion","radiusMeters","angle","dx","dy","wx","wy","circleWebMercator","updateGeometry","updateProperty","property","cartesianDistance","ensureRightHandRule","polygon","isFollowingRightHandRule","outerRing","sum","followsRightHandRule","reverse","TerraDrawFreehandMode","startingClick","currentId","closingPointId","minDistance","preventPointsNearClose","autoClose","autoCloseTimeout","hasLeftStartingPoint","preventNewFeature","correctedGeometry","currentLineGeometry","previousIndex","previousLng","previousLat","containerX","containerY","closingLng","closingLat","closingX","closingY","setTimeout","pop","newGeometry","COMMON_PROPERTIES_CLOSING_POINT","cleanUpClosingPointId","getDefaultStyling","closingPointWidth","closingPointColor","closingPointOutlineColor","closingPointOutlineWidth","TerraDrawModeBehavior","createBBoxFromPoint","point","halfDist","map","c","ClickBoundingBoxBehavior","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","normalizeBearing","lineSliceAlong","coords","startDist","stopDist","slice","origCoordsLength","overshot","direction","interpolated","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","v1x","v1y","v1z","v2x","v2y","v2z","dot","acos","min","max","lngLatToVector","vectorToLngLat","nearestPointOnSegment","posA","posB","posC","C","Cx","Cy","Cz","D","E","F","cross","g","h","t","I1","I2","angleAB","angleAI1","angleBI1","angleAI2","angleBI2","I","findNearestPointOnLine","pointA","pointB","lineVector","LineSnappingBehavior","boundingBox","lines","nearest","lngLat","inputCoordinate","closestPoint","closestDistance","lineIndex","startPosition","stopPosition","intersectPosition","intersectDistance","indexOf","webMercatorNearestPointOnLine","nearestPointOnLine","dragStart","dragEnd","TerraDrawLineStringMode","currentCoordinate","snapping","mouseMove","insertCoordinates","lastCommitedCoordinates","snappedPointId","editable","editedFeatureId","editedFeatureCoordinateIndex","editedSnapType","editedInsertIndex","editedPointId","coordinateSnapping","insertPoint","lineSnapping","updateGeometries","Commit","closingPointCoordinate","updatedGeometry","geometries","generateInsertCoordinates","startCoord","endCoord","strategy","segmentDistance","insertedCoordinates","createLine","startingCoord","firstUpdateToLine","updatedCoord","currentCoordinates","pointId","initialLineCoordinates","updateToLine","cursorXY","updatedLineCoordinates","snappedCoordinate","snapCoordinate","COMMON_PROPERTIES_SNAPPING_POINT","onRightClick","coordinateIndex","lineStringFilter","splice","onLeftClick","updatedCoordinate","button","lineSnapped","coordinateSnapped","COMMON_PROPERTIES_EDITED","featureCopy","newLineStringGeometry","getPropertiesCopy","cleanupClosingPointId","isClosingPoint","snappingPointColor","snappingPointWidth","snappingPointOutlineColor","snappingPointOutlineWidth","_this$snapping","_this$snapping2","toCoordinate","toCustom","ValidationReasonFeatureNotPoint","ValidationReasonFeatureInvalidCoordinates","ValidationReasonFeatureInvalidCoordinatePrecision","ValidatePointFeature","TerraDrawPointMode","nearestPointFeature","getNearestPointFeature","isEdited","editedPointWidth","editedPointColor","editedPointOutlineColor","editedPointOutlineWidth","clickedFeature","distanceToFeature","ClosingPointsBehavior","_startEndPoints","ids","concat","selectedCoords","update","updatedCoordinates","opening","closing","distancePrevious","isClosing","isPreviousClosing","CoordinatePointBehavior","createOrUpdate","existingFeature","existingProperties","existingFeatureProps","coordinatePointIds","existingCoordinates","existingCoordinatePoints","deleteCoordinatePoints","createPoints","setFeatureCoordinatePoints","deletePointsByFeatureIds","deleteIfPresent","getUpdated","featureProperties","COMMON_PROPERTIES_COORDINATE_POINT","TerraDrawPolygonMode","showCoordinatePoints","coordinatePoints","closingPoints","copyAllWhere","featuresWithCoordinates","currentPolygonCoordinates","updatePolygonGeometry","epsilon","offset","_this$snapping3","toLine","snapped","getCurrentGeometrySnapshot","polygonFilter","shift","newId","currentPolygonGeometry","updatedPolygon","createPolygon","featureCoordinates","newPolygonGeometry","editedPoint","coordinatePoint","pointType","styleMap","width","color","closingPoint","snappingPoint","coordinatePointWidth","coordinatePointColor","coordinatePointOutlineColor","coordinatePointOutlineWidth","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","geodesicMidpointCoordinate","midpoint","getMidPointCoordinates","featureCoords","midPointCoords","mid","MidPointBehavior","selectionPointBehavior","coordinatePointBehavior","_midPoints","insert","midPointId","midPoint","midPointFeatureId","midPointSegment","has","getMidPoints","updatedMidPointCoord","SelectionPointBehavior","_selectionPoints","geometryType","selectionPoints","getCoordinatesAsPoints","selectionPoint","selectionPointFeatureId","index","getOneUpdated","pointInPolygon","rings","inside","len","ring","j","len2","k","p1","p","p2","pixelDistanceToLine","linePointOne","linePointTwo","square","dist2","w","distToSegmentSquared","l2","FeatureAtPointerEventBehavior","createClickBoundingBox","find","hasSelection","clickedPoint","clickedLineString","clickedMidPoint","clickedPolygon","clickedPointDistance","clickedLineStringDistance","clickedMidPointDistance","nextCoord","distanceToLine","DragFeatureBehavior","featuresAtCursorEvent","midPoints","draggedFeatureId","dragPosition","startDragging","stopDragging","isDragging","canDrag","drag","cursorCoord","updatedCoords","upToCoord","updatedLng","updatedLat","webMercatorDragPosition","webMercatorCursorCoord","webMercatorCoordinate","updatedX","updatedY","updatedSelectionPoints","updatedMidPoints","updatedCoordinatePoints","DragCoordinateBehavior","draggedCoordinate","getClosestCoordinate","closestCoordinate","isFirstOrLastPolygonCoord","geomCoordinates","getDraggableIndex","allowSelfIntersection","lastCoordIndex","updatedSelectionPoint","centroid","geojson","xSum","ySum","rhumbDistance","DeltaLambda","webMercatorCentroid","webMercatorCoordinates","area","centroidX","centroidY","n","crossProduct","calculatePolygonCentroid","lineString","totalX","totalY","calculateLineStringMidpoint","RotateFeatureBehavior","lastBearing","reset","rotate","mouseCoord","transformRotateWebMercator","angleRad","webMercatorCoords","reduce","acc","rotatedCoordinates","pivot","pointCoords","finalAngle","newCoords","transformRotate","ScaleFeatureBehavior","lastDistance","scale","originWebMercator","selectedWebMercator","factor","scaledCoordinates","transformScaleWebMercator","axis","originalDistance","newCoord","transformScale","DragCoordinateResizeBehavior","minimumScale","boundingBoxMaps","opposite","isValidDragWebMercator","distanceX","distanceY","getSelectedFeatureDataWebMercator","getFeature","getNormalisedCoordinates","getBBoxWebMercator","selectedCoordinate","centerWebMercatorDrag","featureData","webMercatorOrigin","webMercatorSelected","closestBBoxIndex","getIndexesWebMercator","webMercatorCursor","scaleWebMercator","centerFixedWebMercatorDrag","scaleFixedWebMercator","performWebMercatorScale","oppositeFixedWebMercatorDrag","oppositeBboxIndex","oppositeWebMercatorDrag","cursorDistanceX","cursorDistanceY","xScale","yScale","validateScale","validX","MAX_SAFE_INTEGER","validY","originX","originY","west","south","east","north","selectedXY","closestIndex","resizeOption","deselect","pointerOver","insertMidpoint","TerraDrawSelectMode","allowManualDeselection","dragEventThrottle","dragEventCount","selected","flags","validations","coordinateSnap","featuresAtMouseEvent","dragFeature","dragCoordinate","rotateFeature","scaleFeature","dragCoordinateResizeFeature","createOrUpdateCoordinatePoint","polygonId","existingPolygonProps","existingPolygon","selectFeature","select","setSelecting","deselectFeature","updateSelectedFeatures","deleteSelected","clickedSelectionPointProps","clickedFeatureDistance","modeFlags","deletable","deletePoints","midpoints","fromCursor","previouslySelectedId","canScale","every","heldKeys","canRotate","preventDefaultKeyEvent","isRotationKeys","isScaleKeys","preventDefault","draggable","resizable","draggableCoordinateIndex","draggedMidPoint","draggableCoordinateIndexAfterInsert","canSelfIntersect","selfIntersectable","rotateable","scaleable","_modeFlags$feature","snappable","nearbyMidPoint","nearbySelectionPoint","featureUnderPointer","selectionPointColor","selectionPointOutlineColor","selectionPointWidth","selectionPointOutlineWidth","midPointColor","midPointOutlineColor","midPointWidth","midPointOutlineWidth","selectedPolygonColor","selectedPolygonOutlineWidth","selectedPolygonOutlineColor","selectedPolygonFillOpacity","selectedLineStringColor","selectedLineStringWidth","selectedPointWidth","selectedPointColor","selectedPointOutlineColor","selectedPointOutlineWidth","TerraDrawStaticMode","Static","quickselect","arr","left","right","compare","m","s","sd","swap","tmp","calcBBox","node","toBBox","distBBox","children","destNode","createNode","minX","minY","maxX","maxY","child","extend","leaf","compareNodeMinX","compareNodeMinY","bboxArea","bboxMargin","intersectionArea","contains","intersects","height","multiSelect","stack","ceil","RBush","maxEntries","_maxEntries","_minEntries","data","clear","result","nodesToSearch","childBBox","_all","collides","load","_build","_splitRoot","tmpNode","_insert","item","remove","path","indexes","parent","goingUp","_condense","compareMinX","compareMinY","items","N","M","N2","N1","right2","right3","_chooseSubtree","level","targetNode","minArea","minEnlargement","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","set","longitudes","latitudes","minLat","maxLat","get","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","Object","keys","equals","size","polygonAreaSquareMeters","total","ringArea","FACTOR","PI_OVER_180","coordsLength","ValidationReasonFeatureLessThanMinSize","ValidateMinAreaSquareMeters","minSize","ValidateMaxAreaSquareMeters","maxSize","ValidationReasonFeatureNotPolygonOrLineString","ValidationReasonFeatureSelfIntersects","ValidateNotSelfIntersecting","calculateRelativeAngle","bearingAB","relativeAngle","TerraDrawAngledRectangleMode","firstCoordinate","ACloserThanC","hypotenuse","adjacent","rectangleAngle","lineStart","lineEnd","determineHalfPlane","thirdCoordinateXY","fourthCoordinateXY","thirdCoordinate","fourthCoordinate","isClockwiseWebMercator","secondCoord","thirdCoord","TerraDrawSectorMode","arcPoints","arcCoordOne","arcCoordTwo","webMercatorCenter","webMercatorArcCoordOne","webMercatorArcCoordTwo","clockwise","radius","startBearing","endBearing","normalizedStart","normalizedEnd","deltaBearing","bearingStep","pointOnArc","TerraDrawSensorMode","currentInitialArcId","currentStartingPointId","finishedCurrentStartingPointId","finishedInitialArcId","finishedCurrentId","updateLineStringGeometry","lastCoord","webMercatorCoordOne","webMercatorCoordTwo","innerRadius","radiusCalculationPosition","cursorBearing","normalizedCursor","notInSector","getDeltaBearing","finalArc","unshift","centerPointColor","centerPointWidth","centerPointOutlineColor","centerPointOutlineWidth","AdapterListener","name","callback","unregister","registered","_minPixelDragDistance","_minPixelDragDistanceDrawing","_minPixelDragDistanceSelecting","_lastDrawEvent","_coordinatePrecision","_heldKeys","_listeners","_dragState","_currentModeCallbacks","minPixelDragDistance","minPixelDragDistanceSelecting","minPixelDragDistanceDrawing","getButton","getMapElementXYPosition","mapElement","getMapEventElement","top","getBoundingClientRect","clientX","clientY","getDrawEventFromEvent","latLng","getLngLatFromEvent","callbacks","getAdapterListeners","listener","getCoordinatePrecision","isPrimary","drawEvent","addEventListener","removeEventListener","lastEventXY","currentEventXY","modeState","getState","pixelDistanceToCheck","isMicroDrag","enabled","setDraggability","bind","ValidationReasons","TerraDraw","_modes","_mode","_adapter","_enabled","_store","_eventListeners","_instanceSelectMode","adapter","duplicateModeTracker","modesMap","modes","modeMap","currentMode","modeKeys","static","ready","getChanged","changed","unchanged","render","created","deletedIds","updated","getModeStyles","modeId","checkEnabled","modeStyles","featuresAtLocation","ignoreSelectFeatures","inputPoint","pointCoordinates","pointXY","getSelectMode","getMode","setMode","setModeStyles","updateModeOptions","getSnapshot","getSnapshotFeature","removeFeatures","getFeatureId","hasFeature","addFeatures","featureMode","modeToAddTo","onReady","onClear","getFeaturesAtLngLat","getFeaturesAtPointerEvent","on","listeners","off"],"mappings":"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"}
|