leaflet-polydraw 0.9.4 → 0.9.6

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.
@@ -14,11 +14,11 @@ const subtractLineOptions = { "opacity": 1, "smoothFactor": 0, "noClip": true, "
14
14
  const polygonOptions = { "smoothFactor": 0.3, "noClip": true };
15
15
  const holeOptions = { "weight": 2, "opacity": 1, "fillOpacity": 0.5 };
16
16
  const polygonCreation = { "method": "concaveman", "simplification": { "mode": "simple", "tolerance": 1e-5, "highQuality": false } };
17
- const simplification = { "simplifyTolerance": { "tolerance": 1e-4, "highQuality": false, "mutate": false }, "dynamicMode": { "fractionGuard": 0.9, "multipiler": 2 } };
17
+ const simplification = { "simplifyTolerance": { "tolerance": 1e-4, "highQuality": false, "mutate": false }, "dynamicMode": { "fractionGuard": 0.9, "multiplier": 2 } };
18
18
  const menuOperations = { "simplify": { "processHoles": true }, "doubleElbows": { "processHoles": true }, "bbox": { "processHoles": true } };
19
19
  const boundingBox = { "addMidPointMarkers": true };
20
20
  const bezier$1 = { "resolution": 1e4, "sharpness": 0.75 };
21
- const colors = { "dragPolygons": { "subtract": "#D9460F" }, "p2p": { "closingMarker": "#4CAF50" }, "edgeHover": "#7a9441", "edgeDeletion": { "hover": "#D9460F" }, "polyline": "#50622b", "subtractLine": "#50622b", "polygon": { "border": "#50622b", "fill": "#b4cd8a" }, "hole": { "border": "#aa0000", "fill": "#ffcccc" }, "styles": { "controlButton": { "backgroundColor": "#fff", "color": "#000" }, "controlButtonHover": { "backgroundColor": "#f4f4f4" }, "controlButtonActive": { "backgroundColor": "rgb(128, 218, 255)", "color": "#fff" }, "indicatorActive": { "backgroundColor": "#ffcc00" }, "p2pMarker": { "backgroundColor": "#fff", "borderColor": "#50622b" } } };
21
+ const colors = { "dragPolygons": { "subtract": "#D9460F" }, "p2p": { "closingMarker": "#4CAF50" }, "edgeHover": "#7a9441", "edgeDeletion": { "hover": "#D9460F" }, "polyline": "#50622b", "subtractLine": "#D9460F", "polygon": { "border": "#50622b", "fill": "#b4cd8a" }, "hole": { "border": "#aa0000", "fill": "#ffcccc" }, "styles": { "controlButton": { "backgroundColor": "#fff", "color": "#000" }, "controlButtonHover": { "backgroundColor": "#f4f4f4" }, "controlButtonActive": { "backgroundColor": "rgb(128, 218, 255)", "color": "#fff" }, "indicatorActive": { "backgroundColor": "#ffcc00" }, "p2pMarker": { "backgroundColor": "#fff", "borderColor": "#50622b" } } };
22
22
  const defaultConfig = {
23
23
  mergePolygons,
24
24
  kinks: kinks$1,
@@ -59,6 +59,174 @@ var MarkerPosition = /* @__PURE__ */ ((MarkerPosition2) => {
59
59
  MarkerPosition2[MarkerPosition2["Hole"] = 8] = "Hole";
60
60
  return MarkerPosition2;
61
61
  })(MarkerPosition || {});
62
+ const EARTH_RADIUS = {
63
+ /**
64
+ * Mean radius in meters - good enough for this tool's precision requirements
65
+ * Used for distance calculations and area conversions
66
+ */
67
+ MEAN_METERS: 6371e3,
68
+ /** Mean radius in kilometers */
69
+ MEAN_KILOMETERS: 6371,
70
+ /** Mean radius in miles */
71
+ MEAN_MILES: 3959
72
+ // WGS84 ellipsoid values (more precise but overkill for this application)
73
+ // WGS84_SEMI_MAJOR_AXIS: 6378137.0, // meters
74
+ // WGS84_SEMI_MINOR_AXIS: 6356752.314245, // meters
75
+ // WGS84_FLATTENING: 1 / 298.257223563,
76
+ };
77
+ const MATH = {
78
+ /** Degrees to radians conversion factor */
79
+ DEG_TO_RAD: Math.PI / 180,
80
+ /** Radians to degrees conversion factor */
81
+ RAD_TO_DEG: 180 / Math.PI
82
+ };
83
+ function point$1(coordinates, properties = {}) {
84
+ return {
85
+ type: "Feature",
86
+ geometry: {
87
+ type: "Point",
88
+ coordinates
89
+ },
90
+ properties
91
+ };
92
+ }
93
+ function lineString$1(coordinates, properties = {}) {
94
+ return {
95
+ type: "Feature",
96
+ geometry: {
97
+ type: "LineString",
98
+ coordinates
99
+ },
100
+ properties
101
+ };
102
+ }
103
+ function polygon$1(coordinates, properties = {}) {
104
+ return {
105
+ type: "Feature",
106
+ geometry: {
107
+ type: "Polygon",
108
+ coordinates
109
+ },
110
+ properties
111
+ };
112
+ }
113
+ function multiPolygon$1(coordinates, properties = {}) {
114
+ return {
115
+ type: "Feature",
116
+ geometry: {
117
+ type: "MultiPolygon",
118
+ coordinates
119
+ },
120
+ properties
121
+ };
122
+ }
123
+ function featureCollection$1(features) {
124
+ return {
125
+ type: "FeatureCollection",
126
+ features
127
+ };
128
+ }
129
+ function getCoords$1(feature2) {
130
+ if (feature2.geometry.type === "Polygon") {
131
+ return [feature2.geometry.coordinates];
132
+ } else if (feature2.geometry.type === "MultiPolygon") {
133
+ return feature2.geometry.coordinates;
134
+ }
135
+ throw new Error("Feature must be a Polygon or MultiPolygon");
136
+ }
137
+ function bbox$1(feature2) {
138
+ let minX = Infinity;
139
+ let minY = Infinity;
140
+ let maxX = -Infinity;
141
+ let maxY = -Infinity;
142
+ const processCoordinates = (coords) => {
143
+ if (Array.isArray(coords[0])) {
144
+ coords.forEach(processCoordinates);
145
+ } else {
146
+ const [x, y] = coords;
147
+ minX = Math.min(minX, x);
148
+ minY = Math.min(minY, y);
149
+ maxX = Math.max(maxX, x);
150
+ maxY = Math.max(maxY, y);
151
+ }
152
+ };
153
+ processCoordinates(feature2.geometry.coordinates);
154
+ return [minX, minY, maxX, maxY];
155
+ }
156
+ function bboxPolygon(bboxCoords) {
157
+ const [minX, minY, maxX, maxY] = bboxCoords;
158
+ return polygon$1([
159
+ [
160
+ [minX, minY],
161
+ [maxX, minY],
162
+ [maxX, maxY],
163
+ [minX, maxY],
164
+ [minX, minY]
165
+ ]
166
+ ]);
167
+ }
168
+ function distance$1(from, to, units = "kilometers") {
169
+ const fromCoords = Array.isArray(from) ? from : from.geometry.coordinates;
170
+ const toCoords = Array.isArray(to) ? to : to.geometry.coordinates;
171
+ const [lon1, lat1] = fromCoords;
172
+ const [lon2, lat2] = toCoords;
173
+ const R = units === "miles" ? EARTH_RADIUS.MEAN_MILES : units === "meters" ? EARTH_RADIUS.MEAN_METERS : EARTH_RADIUS.MEAN_KILOMETERS;
174
+ const dLat = toRadians(lat2 - lat1);
175
+ const dLon = toRadians(lon2 - lon1);
176
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
177
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
178
+ return R * c;
179
+ }
180
+ function midpoint(point1, point2) {
181
+ const coords1 = Array.isArray(point1) ? point1 : point1.geometry.coordinates;
182
+ const coords2 = Array.isArray(point2) ? point2 : point2.geometry.coordinates;
183
+ const [lon1, lat1] = coords1;
184
+ const [lon2, lat2] = coords2;
185
+ const midLon = (lon1 + lon2) / 2;
186
+ const midLat = (lat1 + lat2) / 2;
187
+ return point$1([midLon, midLat]);
188
+ }
189
+ function area$1(feature2) {
190
+ const coords = getCoords$1(feature2);
191
+ let totalArea = 0;
192
+ for (const polygon2 of coords) {
193
+ for (let i = 0; i < polygon2.length; i++) {
194
+ const ring = polygon2[i];
195
+ const ringArea2 = calculateRingArea(ring);
196
+ totalArea += i === 0 ? Math.abs(ringArea2) : -Math.abs(ringArea2);
197
+ }
198
+ }
199
+ return Math.abs(totalArea);
200
+ }
201
+ function centroid$1(feature2) {
202
+ const coords = getCoords$1(feature2);
203
+ let totalX = 0;
204
+ let totalY = 0;
205
+ let totalPoints = 0;
206
+ for (const polygon2 of coords) {
207
+ for (const ring of polygon2) {
208
+ for (const coord of ring) {
209
+ totalX += coord[0];
210
+ totalY += coord[1];
211
+ totalPoints++;
212
+ }
213
+ }
214
+ }
215
+ return point$1([totalX / totalPoints, totalY / totalPoints]);
216
+ }
217
+ function toRadians(degrees2) {
218
+ return degrees2 * MATH.DEG_TO_RAD;
219
+ }
220
+ function calculateRingArea(ring) {
221
+ let area2 = 0;
222
+ const n = ring.length;
223
+ for (let i = 0; i < n - 1; i++) {
224
+ const [x12, y12] = ring[i];
225
+ const [x2, y2] = ring[i + 1];
226
+ area2 += x12 * y2 - x2 * y12;
227
+ }
228
+ return Math.abs(area2) * 0.5 * Math.pow(EARTH_RADIUS.MEAN_METERS * MATH.DEG_TO_RAD, 2);
229
+ }
62
230
  var earthRadius = 63710088e-1;
63
231
  var factors = {
64
232
  centimeters: earthRadius * 100,
@@ -179,10 +347,6 @@ function lengthToRadians(distance2, units = "kilometers") {
179
347
  }
180
348
  return distance2 / factor;
181
349
  }
182
- function radiansToDegrees(radians2) {
183
- const normalisedRadians = radians2 % (2 * Math.PI);
184
- return normalisedRadians * 180 / Math.PI;
185
- }
186
350
  function degreesToRadians(degrees2) {
187
351
  const normalisedDegrees = degrees2 % 360;
188
352
  return normalisedDegrees * Math.PI / 180;
@@ -1221,7 +1385,6 @@ function centroid(geojson, options = {}) {
1221
1385
  );
1222
1386
  return point([xSum / len, ySum / len], options.properties);
1223
1387
  }
1224
- var turf_centroid_default = centroid;
1225
1388
  function getCoord(coord) {
1226
1389
  if (!coord) {
1227
1390
  throw new Error("coord is required");
@@ -4517,7 +4680,6 @@ function bbox(geojson, options = {}) {
4517
4680
  });
4518
4681
  return result;
4519
4682
  }
4520
- var turf_bbox_default = bbox;
4521
4683
  function center(geojson, options = {}) {
4522
4684
  const ext = bbox(geojson);
4523
4685
  const x = (ext[0] + ext[2]) / 2;
@@ -14140,7 +14302,6 @@ function ringArea(coords) {
14140
14302
  }
14141
14303
  return total * FACTOR;
14142
14304
  }
14143
- var turf_area_default = area;
14144
14305
  const epsilon = 11102230246251565e-32;
14145
14306
  const splitter = 134217729;
14146
14307
  const resulterrbound = (3 + 8 * epsilon) * epsilon;
@@ -15027,63 +15188,6 @@ function unkinkPolygon(geojson) {
15027
15188
  return featureCollection(features);
15028
15189
  }
15029
15190
  var turf_unkink_polygon_default = unkinkPolygon;
15030
- function bearing(start, end, options = {}) {
15031
- if (options.final === true) {
15032
- return calculateFinalBearing(start, end);
15033
- }
15034
- const coordinates1 = getCoord(start);
15035
- const coordinates2 = getCoord(end);
15036
- const lon1 = degreesToRadians(coordinates1[0]);
15037
- const lon2 = degreesToRadians(coordinates2[0]);
15038
- const lat1 = degreesToRadians(coordinates1[1]);
15039
- const lat2 = degreesToRadians(coordinates2[1]);
15040
- const a = Math.sin(lon2 - lon1) * Math.cos(lat2);
15041
- const b = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
15042
- return radiansToDegrees(Math.atan2(a, b));
15043
- }
15044
- function calculateFinalBearing(start, end) {
15045
- let bear = bearing(end, start);
15046
- bear = (bear + 180) % 360;
15047
- return bear;
15048
- }
15049
- function destination(origin, distance2, bearing2, options = {}) {
15050
- const coordinates1 = getCoord(origin);
15051
- const longitude1 = degreesToRadians(coordinates1[0]);
15052
- const latitude1 = degreesToRadians(coordinates1[1]);
15053
- const bearingRad = degreesToRadians(bearing2);
15054
- const radians2 = lengthToRadians(distance2, options.units);
15055
- const latitude2 = Math.asin(
15056
- Math.sin(latitude1) * Math.cos(radians2) + Math.cos(latitude1) * Math.sin(radians2) * Math.cos(bearingRad)
15057
- );
15058
- const longitude2 = longitude1 + Math.atan2(
15059
- Math.sin(bearingRad) * Math.sin(radians2) * Math.cos(latitude1),
15060
- Math.cos(radians2) - Math.sin(latitude1) * Math.sin(latitude2)
15061
- );
15062
- const lng = radiansToDegrees(longitude2);
15063
- const lat = radiansToDegrees(latitude2);
15064
- return point([lng, lat], options.properties);
15065
- }
15066
- function distance(from, to, options = {}) {
15067
- var coordinates1 = getCoord(from);
15068
- var coordinates2 = getCoord(to);
15069
- var dLat = degreesToRadians(coordinates2[1] - coordinates1[1]);
15070
- var dLon = degreesToRadians(coordinates2[0] - coordinates1[0]);
15071
- var lat1 = degreesToRadians(coordinates1[1]);
15072
- var lat2 = degreesToRadians(coordinates2[1]);
15073
- var a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
15074
- return radiansToLength(
15075
- 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
15076
- options.units
15077
- );
15078
- }
15079
- var turf_distance_default = distance;
15080
- function midpoint(point1, point2) {
15081
- const dist = distance(point1, point2);
15082
- const heading = bearing(point1, point2);
15083
- const midpoint2 = destination(point1, dist / 2, heading);
15084
- return midpoint2;
15085
- }
15086
- var turf_midpoint_default = midpoint;
15087
15191
  function booleanPointOnLine(pt, line, options = {}) {
15088
15192
  const ptCoords = getCoord(pt);
15089
15193
  const lineCoords = getCoords(line);
@@ -15508,27 +15612,19 @@ function booleanEqual(feature1, feature2, options = {}) {
15508
15612
  });
15509
15613
  }
15510
15614
  var turf_boolean_equal_default = booleanEqual;
15511
- function bboxPolygon(bbox2, options = {}) {
15512
- const west = Number(bbox2[0]);
15513
- const south = Number(bbox2[1]);
15514
- const east = Number(bbox2[2]);
15515
- const north = Number(bbox2[3]);
15516
- if (bbox2.length === 6) {
15517
- throw new Error(
15518
- "@turf/bbox-polygon does not support BBox with 6 positions"
15519
- );
15520
- }
15521
- const lowLeft = [west, south];
15522
- const topLeft = [west, north];
15523
- const topRight = [east, north];
15524
- const lowRight = [east, south];
15525
- return polygon(
15526
- [[lowLeft, lowRight, topRight, topLeft, lowLeft]],
15527
- options.properties,
15528
- { bbox: bbox2, id: options.id }
15615
+ function distance(from, to, options = {}) {
15616
+ var coordinates1 = getCoord(from);
15617
+ var coordinates2 = getCoord(to);
15618
+ var dLat = degreesToRadians(coordinates2[1] - coordinates1[1]);
15619
+ var dLon = degreesToRadians(coordinates2[0] - coordinates1[0]);
15620
+ var lat1 = degreesToRadians(coordinates1[1]);
15621
+ var lat2 = degreesToRadians(coordinates2[1]);
15622
+ var a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
15623
+ return radiansToLength(
15624
+ 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
15625
+ options.units
15529
15626
  );
15530
15627
  }
15531
- var turf_bbox_polygon_default = bboxPolygon;
15532
15628
  var __defProp2 = Object.defineProperty;
15533
15629
  var __defProps = Object.defineProperties;
15534
15630
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
@@ -15842,113 +15938,366 @@ function length(geojson, options = {}) {
15842
15938
  );
15843
15939
  }
15844
15940
  var turf_length_default = length;
15845
- class TurfHelper {
15846
- constructor(config) {
15847
- __publicField(this, "config", defaultConfig);
15848
- this.config = { ...defaultConfig, ...config };
15849
- }
15850
- union(poly1, poly2) {
15851
- try {
15852
- const fc = featureCollection([poly1, poly2]);
15853
- const u2 = turf_union_default(fc);
15854
- return u2 ? this.getTurfPolygon(u2) : null;
15855
- } catch (error) {
15856
- console.warn("Error in union:", error instanceof Error ? error.message : String(error));
15857
- return null;
15858
- }
15859
- }
15941
+ const isTouchDevice = () => "ontouchstart" in window || navigator.maxTouchPoints > 0;
15942
+ function isTestEnvironment() {
15943
+ return typeof vitest !== "undefined";
15944
+ }
15945
+ class PolyDrawUtil {
15860
15946
  /**
15861
- * Create polygon from drawing trace using configured method
15947
+ * Gets the bounds of the polygon with optional padding.
15948
+ * @param polygon Array of LatLng points.
15949
+ * @param padding Padding factor.
15950
+ * @returns The LatLngBounds.
15862
15951
  */
15863
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15864
- createPolygonFromTrace(feature2) {
15865
- var _a2;
15866
- const method = ((_a2 = this.config.polygonCreation) == null ? void 0 : _a2.method) || "concaveman";
15867
- switch (method) {
15868
- case "concaveman":
15869
- return this.turfConcaveman(feature2);
15870
- case "convex":
15871
- return this.createConvexPolygon(feature2);
15872
- case "direct":
15873
- return this.createDirectPolygon(feature2);
15874
- case "buffer":
15875
- return this.createBufferedPolygon(feature2);
15876
- default:
15877
- console.warn(`Unknown polygon creation method: ${method}, falling back to concaveman`);
15878
- return this.turfConcaveman(feature2);
15952
+ static getBounds(polygon2, padding = 0) {
15953
+ const tmpLatLng = [];
15954
+ polygon2.forEach((ll) => {
15955
+ if (isNaN(ll.lat) || isNaN(ll.lng)) ;
15956
+ tmpLatLng.push(ll);
15957
+ });
15958
+ const polyLine = new L.Polyline(tmpLatLng);
15959
+ const bounds = polyLine.getBounds();
15960
+ if (padding !== 0) {
15961
+ return bounds.pad(padding);
15879
15962
  }
15963
+ return bounds;
15880
15964
  }
15881
- /**
15882
- * Original concaveman implementation
15883
- */
15884
- turfConcaveman(feature2) {
15885
- const points = turf_explode_default(feature2);
15886
- const coordinates = points.features.map((f) => f.geometry.coordinates);
15887
- return multiPolygon([[concaveman(coordinates)]]);
15965
+ }
15966
+ class Compass {
15967
+ constructor(minLat = 0, minLng = 0, maxLat = 0, maxLng = 0) {
15968
+ __publicField(this, "direction", {
15969
+ East: new L.LatLng(0, 0),
15970
+ North: new L.LatLng(0, 0),
15971
+ NorthEast: new L.LatLng(0, 0),
15972
+ NorthWest: new L.LatLng(0, 0),
15973
+ South: new L.LatLng(0, 0),
15974
+ SouthEast: new L.LatLng(0, 0),
15975
+ SouthWest: new L.LatLng(0, 0),
15976
+ West: new L.LatLng(0, 0)
15977
+ });
15978
+ this.direction.North = new L.LatLng(maxLat, (minLng + maxLng) / 2);
15979
+ this.direction.NorthEast = new L.LatLng(maxLat, maxLng);
15980
+ this.direction.East = new L.LatLng((minLat + maxLat) / 2, maxLng);
15981
+ this.direction.SouthEast = new L.LatLng(minLat, maxLng);
15982
+ this.direction.South = new L.LatLng(minLat, (minLng + maxLng) / 2);
15983
+ this.direction.SouthWest = new L.LatLng(minLat, minLng);
15984
+ this.direction.West = new L.LatLng((minLat + maxLat) / 2, minLng);
15985
+ this.direction.NorthWest = new L.LatLng(maxLat, minLng);
15888
15986
  }
15889
- /**
15890
- * Create convex hull polygon (simplest, fewest edges)
15891
- */
15892
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15893
- createConvexPolygon(feature2) {
15894
- const points = turf_explode_default(feature2);
15895
- const convexHull = turf_convex_default(points);
15896
- if (!convexHull) {
15897
- return this.createDirectPolygon(feature2);
15987
+ getDirection(direction) {
15988
+ switch (direction) {
15989
+ case MarkerPosition.SouthWest:
15990
+ return this.direction.SouthWest;
15991
+ case MarkerPosition.West:
15992
+ return this.direction.West;
15993
+ case MarkerPosition.NorthWest:
15994
+ return this.direction.NorthWest;
15995
+ case MarkerPosition.North:
15996
+ return this.direction.North;
15997
+ case MarkerPosition.NorthEast:
15998
+ return this.direction.NorthEast;
15999
+ case MarkerPosition.East:
16000
+ return this.direction.East;
16001
+ case MarkerPosition.SouthEast:
16002
+ return this.direction.SouthEast;
16003
+ case MarkerPosition.South:
16004
+ return this.direction.South;
16005
+ default:
16006
+ throw new Error();
15898
16007
  }
15899
- return this.getTurfPolygon(convexHull);
15900
16008
  }
15901
- /**
15902
- * Create polygon directly from line coordinates (moderate edge count)
15903
- */
15904
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15905
- createDirectPolygon(feature2) {
15906
- let coordinates;
15907
- if (feature2.geometry.type === "LineString") {
15908
- coordinates = feature2.geometry.coordinates;
15909
- } else if (feature2.geometry.type === "Polygon") {
15910
- coordinates = feature2.geometry.coordinates[0];
15911
- } else {
15912
- const points = turf_explode_default(feature2);
15913
- coordinates = points.features.map((f) => f.geometry.coordinates);
16009
+ getPositions(startPosition = MarkerPosition.SouthWest, clockwise = false, addClosingNode = true) {
16010
+ const positions = [];
16011
+ const posArray = this.getPositionAsArray(startPosition, clockwise);
16012
+ posArray.forEach((v) => {
16013
+ positions.push([v.lng, v.lat]);
16014
+ });
16015
+ if (addClosingNode) {
16016
+ positions.push([posArray[0].lng, posArray[0].lat]);
15914
16017
  }
15915
- if (coordinates.length > 0) {
15916
- const first = coordinates[0];
15917
- const last = coordinates[coordinates.length - 1];
15918
- if (first[0] !== last[0] || first[1] !== last[1]) {
15919
- coordinates.push([first[0], first[1]]);
15920
- }
16018
+ return positions;
16019
+ }
16020
+ getPositionAsArray(startPosition = MarkerPosition.NorthEast, clockwise = false) {
16021
+ const positions = [];
16022
+ if (clockwise) {
16023
+ positions.push(this.direction.SouthWest);
16024
+ positions.push(this.direction.West);
16025
+ positions.push(this.direction.NorthWest);
16026
+ positions.push(this.direction.North);
16027
+ positions.push(this.direction.NorthEast);
16028
+ positions.push(this.direction.East);
16029
+ positions.push(this.direction.SouthEast);
16030
+ positions.push(this.direction.South);
16031
+ } else {
16032
+ positions.push(this.direction.SouthWest);
16033
+ positions.push(this.direction.South);
16034
+ positions.push(this.direction.SouthEast);
16035
+ positions.push(this.direction.East);
16036
+ positions.push(this.direction.NorthEast);
16037
+ positions.push(this.direction.North);
16038
+ positions.push(this.direction.NorthWest);
16039
+ positions.push(this.direction.West);
15921
16040
  }
15922
- if (coordinates.length < 4) {
15923
- console.warn("Not enough points for direct polygon, falling back to concaveman");
15924
- return this.turfConcaveman(feature2);
16041
+ if (startPosition !== MarkerPosition.SouthWest) {
16042
+ const chunk = positions.splice(0, startPosition);
16043
+ chunk.forEach((v, i) => {
16044
+ positions.splice(startPosition + i, 0, v);
16045
+ });
15925
16046
  }
15926
- return multiPolygon([[coordinates]]);
16047
+ return positions;
15927
16048
  }
15928
- /**
15929
- * Create polygon using buffer method (smooth curves)
15930
- */
15931
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15932
- createBufferedPolygon(feature2) {
15933
- try {
15934
- let line;
15935
- if (feature2.geometry.type === "LineString") {
15936
- line = feature2;
15937
- } else {
15938
- const points = turf_explode_default(feature2);
15939
- const coordinates = points.features.map((f) => f.geometry.coordinates);
15940
- line = lineString(coordinates);
15941
- }
15942
- const buffered = turf_buffer_default(line, 1e-3, { units: "kilometers" });
15943
- if (!buffered) {
15944
- return this.createDirectPolygon(feature2);
15945
- }
15946
- return this.getTurfPolygon(buffered);
16049
+ }
16050
+ class Perimeter {
16051
+ constructor(length2, config) {
16052
+ __publicField(this, "metricLength", "");
16053
+ __publicField(this, "metricUnit", "");
16054
+ __publicField(this, "imperialLength", "");
16055
+ __publicField(this, "imperialUnit", "");
16056
+ if (length2 !== null || length2 !== void 0) {
16057
+ if (length2 === 0) {
16058
+ if (config.markers.markerInfoIcon.usePerimeterMinValue) {
16059
+ this.metricLength = config.markers.markerInfoIcon.values.min.metric;
16060
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16061
+ this.imperialLength = config.markers.markerInfoIcon.values.min.imperial;
16062
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.feet;
16063
+ } else {
16064
+ this.metricLength = config.markers.markerInfoIcon.values.unknown.metric;
16065
+ this.metricUnit = config.markers.markerInfoIcon.units.unknownUnit;
16066
+ this.imperialLength = config.markers.markerInfoIcon.values.unknown.imperial;
16067
+ this.imperialUnit = config.markers.markerInfoIcon.units.unknownUnit;
16068
+ }
16069
+ } else if (length2 < 100) {
16070
+ this.metricLength = (Math.ceil(length2 / 10) * 10).toString();
16071
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16072
+ } else if (length2 < 500) {
16073
+ this.metricLength = (Math.ceil(length2 / 50) * 50).toString();
16074
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16075
+ } else if (length2 < 1e3) {
16076
+ this.metricLength = (Math.ceil(length2 / 100) * 100).toString();
16077
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16078
+ } else if (length2 < 1e4) {
16079
+ this.metricLength = (Math.ceil(length2 / 100) * 100 / 1e3).toFixed(1);
16080
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.km;
16081
+ } else {
16082
+ this.metricLength = (Math.ceil(length2 / 1e3) * 1e3 / 1e3).toString();
16083
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.km;
16084
+ }
16085
+ const inch = length2 / 0.0254;
16086
+ const feet = inch / 12;
16087
+ const yards = feet / 3;
16088
+ const miles = yards / 1760;
16089
+ if (length2 < 1e3 / 2.54) {
16090
+ this.imperialLength = (Math.ceil(feet / 10) * 10).toString();
16091
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.feet;
16092
+ } else if (length2 < 1e3 / 2.54 * 3) {
16093
+ this.imperialLength = (Math.ceil(yards / 10) * 10).toString();
16094
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.yards;
16095
+ } else if (length2 < 1609) {
16096
+ this.imperialLength = miles.toFixed(2);
16097
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
16098
+ } else if (length2 < 16093) {
16099
+ this.imperialLength = miles.toFixed(1);
16100
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
16101
+ } else {
16102
+ this.imperialLength = miles.toFixed(0);
16103
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
16104
+ }
16105
+ }
16106
+ }
16107
+ }
16108
+ class Area {
16109
+ constructor(sqrMeterArea, config) {
16110
+ __publicField(this, "metricArea", "");
16111
+ __publicField(this, "metricUnit", "");
16112
+ __publicField(this, "imperialArea", "");
16113
+ __publicField(this, "imperialUnit", "");
16114
+ const area2 = sqrMeterArea;
16115
+ const onlyMetrics = config.markers.markerInfoIcon.units.metric.onlyMetrics;
16116
+ if (area2 !== null || area2 !== void 0) {
16117
+ if (area2 === 0) {
16118
+ this.metricArea = "-";
16119
+ this.metricUnit = config.markers.markerInfoIcon.units.unknownUnit;
16120
+ this.imperialArea = "-";
16121
+ this.imperialUnit = config.markers.markerInfoIcon.units.unknownUnit;
16122
+ } else if (area2 < 1e4) {
16123
+ this.metricArea = Math.round(area2).toString();
16124
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.m2;
16125
+ } else if (area2 < 1e5) {
16126
+ if (onlyMetrics) {
16127
+ this.metricArea = (area2 / 1e6).toFixed(2);
16128
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
16129
+ } else {
16130
+ this.metricArea = (area2 / 1e3).toFixed(1);
16131
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.daa;
16132
+ }
16133
+ } else if (area2 < 1e7) {
16134
+ if (onlyMetrics) {
16135
+ this.metricArea = (area2 / 1e6).toFixed(2);
16136
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
16137
+ } else {
16138
+ this.metricArea = Math.round(area2 / 1e3).toString();
16139
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.daa;
16140
+ }
16141
+ } else if (area2 < 1e8) {
16142
+ if (onlyMetrics) {
16143
+ this.metricArea = (area2 / 1e6).toFixed(1);
16144
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
16145
+ } else {
16146
+ this.metricArea = Math.round(area2 / 1e4).toString();
16147
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.ha;
16148
+ }
16149
+ } else {
16150
+ this.metricArea = Math.round(area2 / 1e6).toString();
16151
+ this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
16152
+ }
16153
+ const inch2 = area2 * 1550;
16154
+ const feet2 = inch2 * 69444e-7;
16155
+ const yards2 = feet2 * 0.11111;
16156
+ const acres = yards2 * 20661e-8;
16157
+ const miles2 = yards2 * 32283e-11;
16158
+ if (area2 < 92.9) {
16159
+ this.imperialArea = Math.round(feet2).toString();
16160
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.feet2;
16161
+ } else if (area2 < 836.14) {
16162
+ this.imperialArea = yards2.toFixed(0);
16163
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.yards2;
16164
+ } else if (area2 < 40469.6) {
16165
+ this.imperialArea = acres.toFixed(2);
16166
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
16167
+ } else if (area2 < 404696) {
16168
+ this.imperialArea = acres.toFixed(1);
16169
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
16170
+ } else if (area2 < 4046960) {
16171
+ this.imperialArea = acres.toFixed(0);
16172
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
16173
+ } else if (area2 < 25900404) {
16174
+ this.imperialArea = miles2.toFixed(2);
16175
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
16176
+ } else if (area2 < 259004040) {
16177
+ this.imperialArea = miles2.toFixed(1);
16178
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
16179
+ } else {
16180
+ this.imperialArea = miles2.toFixed(0);
16181
+ this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
16182
+ }
16183
+ }
16184
+ }
16185
+ }
16186
+ class TurfHelper {
16187
+ constructor(config) {
16188
+ __publicField(this, "config", defaultConfig);
16189
+ this.config = { ...defaultConfig, ...config };
16190
+ }
16191
+ union(poly1, poly2) {
16192
+ try {
16193
+ const fc = featureCollection$1([poly1, poly2]);
16194
+ const u2 = turf_union_default(fc);
16195
+ return u2 ? this.getTurfPolygon(u2) : null;
15947
16196
  } catch (error) {
15948
- console.warn(
15949
- "Buffer polygon creation failed:",
15950
- error instanceof Error ? error.message : String(error)
15951
- );
16197
+ if (!isTestEnvironment()) {
16198
+ console.warn("Error in union:", error instanceof Error ? error.message : String(error));
16199
+ }
16200
+ return null;
16201
+ }
16202
+ }
16203
+ /**
16204
+ * Create polygon from drawing trace using configured method
16205
+ */
16206
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16207
+ createPolygonFromTrace(feature2) {
16208
+ var _a2;
16209
+ const method = ((_a2 = this.config.polygonCreation) == null ? void 0 : _a2.method) || "concaveman";
16210
+ switch (method) {
16211
+ case "concaveman":
16212
+ return this.turfConcaveman(feature2);
16213
+ case "convex":
16214
+ return this.createConvexPolygon(feature2);
16215
+ case "direct":
16216
+ return this.createDirectPolygon(feature2);
16217
+ case "buffer":
16218
+ return this.createBufferedPolygon(feature2);
16219
+ default:
16220
+ if (!isTestEnvironment()) {
16221
+ console.warn(`Unknown polygon creation method: ${method}, falling back to concaveman`);
16222
+ }
16223
+ return this.turfConcaveman(feature2);
16224
+ }
16225
+ }
16226
+ /**
16227
+ * Original concaveman implementation
16228
+ */
16229
+ turfConcaveman(feature2) {
16230
+ const points = turf_explode_default(feature2);
16231
+ const coordinates = points.features.map((f) => f.geometry.coordinates);
16232
+ return multiPolygon$1([[concaveman(coordinates)]]);
16233
+ }
16234
+ /**
16235
+ * Create convex hull polygon (simplest, fewest edges)
16236
+ */
16237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16238
+ createConvexPolygon(feature2) {
16239
+ const points = turf_explode_default(feature2);
16240
+ const convexHull = turf_convex_default(points);
16241
+ if (!convexHull) {
16242
+ return this.createDirectPolygon(feature2);
16243
+ }
16244
+ return this.getTurfPolygon(convexHull);
16245
+ }
16246
+ /**
16247
+ * Create polygon directly from line coordinates (moderate edge count)
16248
+ */
16249
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16250
+ createDirectPolygon(feature2) {
16251
+ let coordinates;
16252
+ if (feature2.geometry.type === "LineString") {
16253
+ coordinates = feature2.geometry.coordinates;
16254
+ } else if (feature2.geometry.type === "Polygon") {
16255
+ coordinates = feature2.geometry.coordinates[0];
16256
+ } else {
16257
+ const points = turf_explode_default(feature2);
16258
+ coordinates = points.features.map((f) => f.geometry.coordinates);
16259
+ }
16260
+ if (coordinates.length > 0) {
16261
+ const first = coordinates[0];
16262
+ const last = coordinates[coordinates.length - 1];
16263
+ if (first[0] !== last[0] || first[1] !== last[1]) {
16264
+ coordinates.push([first[0], first[1]]);
16265
+ }
16266
+ }
16267
+ if (coordinates.length < 4) {
16268
+ if (!isTestEnvironment()) {
16269
+ console.warn("Not enough points for direct polygon, falling back to concaveman");
16270
+ }
16271
+ return this.turfConcaveman(feature2);
16272
+ }
16273
+ return multiPolygon$1([[coordinates]]);
16274
+ }
16275
+ /**
16276
+ * Create polygon using buffer method (smooth curves)
16277
+ */
16278
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16279
+ createBufferedPolygon(feature2) {
16280
+ try {
16281
+ let line;
16282
+ if (feature2.geometry.type === "LineString") {
16283
+ line = feature2;
16284
+ } else {
16285
+ const points = turf_explode_default(feature2);
16286
+ const coordinates = points.features.map((f) => f.geometry.coordinates);
16287
+ line = lineString$1(coordinates);
16288
+ }
16289
+ const buffered = turf_buffer_default(line, 1e-3, { units: "kilometers" });
16290
+ if (!buffered) {
16291
+ return this.createDirectPolygon(feature2);
16292
+ }
16293
+ return this.getTurfPolygon(buffered);
16294
+ } catch (error) {
16295
+ if (!isTestEnvironment()) {
16296
+ console.warn(
16297
+ "Buffer polygon creation failed:",
16298
+ error instanceof Error ? error.message : String(error)
16299
+ );
16300
+ }
15952
16301
  return this.createDirectPolygon(feature2);
15953
16302
  }
15954
16303
  }
@@ -15972,9 +16321,9 @@ class TurfHelper {
15972
16321
  } else {
15973
16322
  let simplified = turf_simplify_default(polygon2, tolerance);
15974
16323
  const fractionGuard = this.config.simplification.dynamicMode.fractionGuard;
15975
- const multipiler = this.config.simplification.dynamicMode.multipiler;
16324
+ const multiplier = this.config.simplification.dynamicMode.multiplier;
15976
16325
  while (simplified.geometry.coordinates[0][0].length > 4 && simplified.geometry.coordinates[0][0].length / (numOfEdges + 2) > fractionGuard) {
15977
- tolerance.tolerance = tolerance.tolerance * multipiler;
16326
+ tolerance.tolerance = tolerance.tolerance * multiplier;
15978
16327
  simplified = turf_simplify_default(polygon2, tolerance);
15979
16328
  }
15980
16329
  return simplified;
@@ -15982,7 +16331,9 @@ class TurfHelper {
15982
16331
  } else if (simplificationMode === "none") {
15983
16332
  return polygon2;
15984
16333
  } else {
15985
- console.warn(`Unknown simplification mode: ${simplificationMode}, falling back to simple`);
16334
+ if (!isTestEnvironment()) {
16335
+ console.warn(`Unknown simplification mode: ${simplificationMode}, falling back to simple`);
16336
+ }
15986
16337
  const tolerance = {
15987
16338
  tolerance: 1e-4,
15988
16339
  highQuality: false,
@@ -15994,14 +16345,14 @@ class TurfHelper {
15994
16345
  getTurfPolygon(polygon2) {
15995
16346
  let turfPolygon;
15996
16347
  if (polygon2.geometry.type === "Polygon") {
15997
- turfPolygon = multiPolygon([polygon2.geometry.coordinates]);
16348
+ turfPolygon = multiPolygon$1([polygon2.geometry.coordinates]);
15998
16349
  } else {
15999
- turfPolygon = multiPolygon(polygon2.geometry.coordinates);
16350
+ turfPolygon = multiPolygon$1(polygon2.geometry.coordinates);
16000
16351
  }
16001
16352
  return turfPolygon;
16002
16353
  }
16003
16354
  getMultiPolygon(polygonArray) {
16004
- return multiPolygon(polygonArray);
16355
+ return multiPolygon$1(polygonArray);
16005
16356
  }
16006
16357
  getKinks(feature2) {
16007
16358
  try {
@@ -16010,7 +16361,9 @@ class TurfHelper {
16010
16361
  }
16011
16362
  const cleanedFeature = this.removeDuplicateVertices(feature2);
16012
16363
  if (!cleanedFeature || !cleanedFeature.geometry || !cleanedFeature.geometry.coordinates) {
16013
- console.warn("Feature became invalid after cleaning in getKinks");
16364
+ if (!isTestEnvironment()) {
16365
+ console.warn("Feature became invalid after cleaning in getKinks");
16366
+ }
16014
16367
  return [feature2];
16015
16368
  }
16016
16369
  const hasHoles = this.polygonHasHoles(cleanedFeature);
@@ -16025,15 +16378,17 @@ class TurfHelper {
16025
16378
  return coordinates;
16026
16379
  }
16027
16380
  } catch (error) {
16028
- console.warn(
16029
- "Error processing kinks:",
16030
- error instanceof Error ? error.message : String(error)
16031
- );
16381
+ if (!isTestEnvironment()) {
16382
+ console.warn(
16383
+ "Error processing kinks:",
16384
+ error instanceof Error ? error.message : String(error)
16385
+ );
16386
+ }
16032
16387
  return [feature2];
16033
16388
  }
16034
16389
  }
16035
16390
  getCoords(feature2) {
16036
- return getCoords(feature2);
16391
+ return getCoords$1(feature2);
16037
16392
  }
16038
16393
  hasKinks(feature2) {
16039
16394
  const k = turf_kinks_default(feature2);
@@ -16044,13 +16399,15 @@ class TurfHelper {
16044
16399
  */
16045
16400
  getConvexHull(polygon2) {
16046
16401
  try {
16047
- const fc = featureCollection([polygon2]);
16402
+ const fc = featureCollection$1([polygon2]);
16048
16403
  return turf_convex_default(fc);
16049
16404
  } catch (error) {
16050
- console.warn(
16051
- "Error in getConvexHull:",
16052
- error instanceof Error ? error.message : String(error)
16053
- );
16405
+ if (!isTestEnvironment()) {
16406
+ console.warn(
16407
+ "Error in getConvexHull:",
16408
+ error instanceof Error ? error.message : String(error)
16409
+ );
16410
+ }
16054
16411
  return null;
16055
16412
  }
16056
16413
  }
@@ -16058,9 +16415,9 @@ class TurfHelper {
16058
16415
  * Calculate midpoint between two LatLngLiteral points
16059
16416
  */
16060
16417
  getMidpoint(point1, point2) {
16061
- const p1 = point([point1.lng, point1.lat]);
16062
- const p2 = point([point2.lng, point2.lat]);
16063
- const mp = turf_midpoint_default(p1, p2);
16418
+ const p1 = point$1([point1.lng, point1.lat]);
16419
+ const p2 = point$1([point2.lng, point2.lat]);
16420
+ const mp = midpoint(p1, p2);
16064
16421
  return {
16065
16422
  lat: mp.geometry.coordinates[1],
16066
16423
  lng: mp.geometry.coordinates[0]
@@ -16069,14 +16426,32 @@ class TurfHelper {
16069
16426
  polygonIntersect(polygon2, latlngs) {
16070
16427
  try {
16071
16428
  if (!polygon2 || !polygon2.geometry || !polygon2.geometry.coordinates || !latlngs || !latlngs.geometry || !latlngs.geometry.coordinates) {
16072
- console.warn("Invalid features passed to polygonIntersect");
16429
+ if (!isTestEnvironment()) {
16430
+ console.warn("Invalid features passed to polygonIntersect");
16431
+ }
16432
+ return false;
16433
+ }
16434
+ const validateCoordinates = (coords) => {
16435
+ if (!Array.isArray(coords)) return false;
16436
+ for (const ring of coords) {
16437
+ if (!Array.isArray(ring)) return false;
16438
+ for (const coord of ring) {
16439
+ if (!Array.isArray(coord) || coord.length < 2) return false;
16440
+ if (coord.some((c) => c === null || c === void 0 || !isFinite(c))) {
16441
+ return false;
16442
+ }
16443
+ }
16444
+ }
16445
+ return true;
16446
+ };
16447
+ if (!validateCoordinates(polygon2.geometry.coordinates) || !validateCoordinates(latlngs.geometry.coordinates)) {
16073
16448
  return false;
16074
16449
  }
16075
16450
  try {
16076
- const fc = featureCollection([polygon2, latlngs]);
16451
+ const fc = featureCollection$1([polygon2, latlngs]);
16077
16452
  const intersection3 = turf_intersect_default(fc);
16078
16453
  if (intersection3 && intersection3.geometry && (intersection3.geometry.type === "Polygon" || intersection3.geometry.type === "MultiPolygon")) {
16079
- const polygonArea2 = turf_area_default(intersection3);
16454
+ const polygonArea2 = area$1(intersection3);
16080
16455
  if (polygonArea2 > 1e-6) {
16081
16456
  return true;
16082
16457
  }
@@ -16099,16 +16474,28 @@ class TurfHelper {
16099
16474
  } catch (error) {
16100
16475
  }
16101
16476
  try {
16102
- const coords1 = getCoords(polygon2);
16103
- const coords2 = getCoords(latlngs);
16477
+ const coords1 = getCoords$1(polygon2);
16478
+ const coords2 = getCoords$1(latlngs);
16104
16479
  for (const ring1 of coords1) {
16105
16480
  const outerRing1 = ring1[0];
16481
+ if (!outerRing1 || outerRing1.length < 2) continue;
16106
16482
  for (let i = 0; i < outerRing1.length - 1; i++) {
16107
- const line1 = lineString([outerRing1[i], outerRing1[i + 1]]);
16483
+ const coord1 = outerRing1[i];
16484
+ const coord2 = outerRing1[i + 1];
16485
+ if (!coord1 || !coord2 || !Array.isArray(coord1) || !Array.isArray(coord2) || coord1.length < 2 || coord2.length < 2 || coord1.some((c) => c === null || c === void 0 || !isFinite(c)) || coord2.some((c) => c === null || c === void 0 || !isFinite(c))) {
16486
+ continue;
16487
+ }
16488
+ const line1 = lineString$1([coord1, coord2]);
16108
16489
  for (const ring2 of coords2) {
16109
16490
  const outerRing2 = ring2[0];
16491
+ if (!outerRing2 || outerRing2.length < 2) continue;
16110
16492
  for (let j = 0; j < outerRing2.length - 1; j++) {
16111
- const line2 = lineString([outerRing2[j], outerRing2[j + 1]]);
16493
+ const coord3 = outerRing2[j];
16494
+ const coord4 = outerRing2[j + 1];
16495
+ if (!coord3 || !coord4 || !Array.isArray(coord3) || !Array.isArray(coord4) || coord3.length < 2 || coord4.length < 2 || coord3.some((c) => c === null || c === void 0 || !isFinite(c)) || coord4.some((c) => c === null || c === void 0 || !isFinite(c))) {
16496
+ continue;
16497
+ }
16498
+ const line2 = lineString$1([coord3, coord4]);
16112
16499
  try {
16113
16500
  const intersection3 = turf_line_intersect_default(line1, line2);
16114
16501
  if (intersection3 && intersection3.features && intersection3.features.length > 0) {
@@ -16124,42 +16511,48 @@ class TurfHelper {
16124
16511
  }
16125
16512
  try {
16126
16513
  } catch (error) {
16514
+ if (!isTestEnvironment()) {
16515
+ console.warn(
16516
+ "Error in bounding box check:",
16517
+ error instanceof Error ? error.message : String(error)
16518
+ );
16519
+ }
16520
+ }
16521
+ return false;
16522
+ } catch (error) {
16523
+ if (!isTestEnvironment()) {
16127
16524
  console.warn(
16128
- "Error in bounding box check:",
16525
+ "Error in polygonIntersect:",
16129
16526
  error instanceof Error ? error.message : String(error)
16130
16527
  );
16131
16528
  }
16132
16529
  return false;
16133
- } catch (error) {
16134
- console.warn(
16135
- "Error in polygonIntersect:",
16136
- error instanceof Error ? error.message : String(error)
16137
- );
16138
- return false;
16139
16530
  }
16140
16531
  }
16141
16532
  getIntersection(poly1, poly2) {
16142
16533
  try {
16143
- const fc = featureCollection([poly1, poly2]);
16534
+ const fc = featureCollection$1([poly1, poly2]);
16144
16535
  const result = turf_intersect_default(fc);
16145
16536
  if (result && result.geometry && (result.geometry.type === "Polygon" || result.geometry.type === "MultiPolygon")) {
16146
16537
  return result;
16147
16538
  }
16148
16539
  return null;
16149
16540
  } catch (error) {
16150
- console.warn(
16151
- "Error in getIntersection:",
16152
- error instanceof Error ? error.message : String(error)
16153
- );
16541
+ if (!isTestEnvironment()) {
16542
+ console.warn(
16543
+ "Error in getIntersection:",
16544
+ error instanceof Error ? error.message : String(error)
16545
+ );
16546
+ }
16154
16547
  return null;
16155
16548
  }
16156
16549
  }
16157
16550
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16158
16551
  getDistance(point1, point2) {
16159
- return turf_distance_default(point1, point2);
16552
+ return distance$1(point1, point2);
16160
16553
  }
16161
16554
  isWithin(polygon1, polygon2) {
16162
- return turf_boolean_within_default(polygon([polygon1]), polygon([polygon2]));
16555
+ return turf_boolean_within_default(polygon$1([polygon1]), polygon$1([polygon2]));
16163
16556
  }
16164
16557
  /**
16165
16558
  * Check if one polygon is completely within another polygon
@@ -16168,16 +16561,16 @@ class TurfHelper {
16168
16561
  try {
16169
16562
  return turf_boolean_within_default(innerPolygon, outerPolygon);
16170
16563
  } catch (error) {
16171
- const innerCoords = getCoords(innerPolygon);
16172
- const outerCoords = getCoords(outerPolygon);
16564
+ const innerCoords = getCoords$1(innerPolygon);
16565
+ const outerCoords = getCoords$1(outerPolygon);
16173
16566
  for (const innerRing of innerCoords) {
16174
16567
  for (const ring of innerRing) {
16175
16568
  for (const coord of ring) {
16176
- const pt = point(coord);
16569
+ const pt = point$1(coord);
16177
16570
  let isInside = false;
16178
16571
  for (const outerRing of outerCoords) {
16179
16572
  for (const outerRingCoords of outerRing) {
16180
- const outerPoly = polygon([outerRingCoords]);
16573
+ const outerPoly = polygon$1([outerRingCoords]);
16181
16574
  if (turf_boolean_point_in_polygon_default(pt, outerPoly)) {
16182
16575
  isInside = true;
16183
16576
  break;
@@ -16204,14 +16597,14 @@ class TurfHelper {
16204
16597
  return pt;
16205
16598
  }
16206
16599
  if (Array.isArray(pt) && pt.length >= 2 && typeof pt[0] === "number" && typeof pt[1] === "number") {
16207
- return point(pt);
16600
+ return point$1(pt);
16208
16601
  }
16209
16602
  if (typeof (pt == null ? void 0 : pt.lat) === "number" && typeof (pt == null ? void 0 : pt.lng) === "number") {
16210
16603
  const p = pt;
16211
- return point([p.lng, p.lat]);
16604
+ return point$1([p.lng, p.lat]);
16212
16605
  }
16213
16606
  if (((_b2 = pt == null ? void 0 : pt.geometry) == null ? void 0 : _b2.coordinates) && Array.isArray(pt.geometry.coordinates)) {
16214
- return point(pt.geometry.coordinates);
16607
+ return point$1(pt.geometry.coordinates);
16215
16608
  }
16216
16609
  throw new Error("Unsupported point format provided to toPointFeature");
16217
16610
  }
@@ -16237,12 +16630,12 @@ class TurfHelper {
16237
16630
  return turf_boolean_equal_default(polygon1, polygon2);
16238
16631
  }
16239
16632
  convertToBoundingBoxPolygon(polygon2) {
16240
- const bboxCoords = turf_bbox_default(polygon2.geometry);
16241
- const bboxPoly = turf_bbox_polygon_default(bboxCoords);
16633
+ const bboxCoords = bbox$1(polygon2);
16634
+ const bboxPoly = bboxPolygon(bboxCoords);
16242
16635
  return bboxPoly;
16243
16636
  }
16244
16637
  polygonToMultiPolygon(poly) {
16245
- const multi = multiPolygon([poly.geometry.coordinates]);
16638
+ const multi = multiPolygon$1([poly.geometry.coordinates]);
16246
16639
  return multi;
16247
16640
  }
16248
16641
  injectPointToPolygon(polygon2, point2, ringIndex) {
@@ -16298,15 +16691,17 @@ class TurfHelper {
16298
16691
  }
16299
16692
  polygonDifference(polygon1, polygon2) {
16300
16693
  try {
16301
- const fc = featureCollection([polygon1, polygon2]);
16694
+ const fc = featureCollection$1([polygon1, polygon2]);
16302
16695
  const diff = turf_difference_default(fc);
16303
16696
  const result = diff ? this.getTurfPolygon(diff) : null;
16304
16697
  return result;
16305
16698
  } catch (error) {
16306
- console.warn(
16307
- "Error in polygonDifference:",
16308
- error instanceof Error ? error.message : String(error)
16309
- );
16699
+ if (!isTestEnvironment()) {
16700
+ console.warn(
16701
+ "Error in polygonDifference:",
16702
+ error instanceof Error ? error.message : String(error)
16703
+ );
16704
+ }
16310
16705
  return null;
16311
16706
  }
16312
16707
  }
@@ -16332,18 +16727,29 @@ class TurfHelper {
16332
16727
  getCoord(point2) {
16333
16728
  return [point2.lng, point2.lat];
16334
16729
  }
16730
+ /**
16731
+ * Create a GeoJSON polygon feature from coordinates.
16732
+ * This method provides access to the turf polygon helper function
16733
+ * while keeping all turf imports centralized in this file.
16734
+ *
16735
+ * @param coordinates - Array of coordinate rings (outer ring + holes)
16736
+ * @returns GeoJSON Feature<Polygon>
16737
+ */
16738
+ createPolygon(coordinates) {
16739
+ return polygon$1(coordinates);
16740
+ }
16335
16741
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16336
16742
  getFeaturePointCollection(points) {
16337
16743
  const pts = [];
16338
16744
  points.forEach((v) => {
16339
- const p = point([v.lng, v.lat], {});
16745
+ const p = point$1([v.lng, v.lat], {});
16340
16746
  pts.push(p);
16341
16747
  });
16342
- const fc = featureCollection(pts);
16748
+ const fc = featureCollection$1(pts);
16343
16749
  return fc;
16344
16750
  }
16345
16751
  getPolygonArea(poly) {
16346
- const polygonArea2 = turf_area_default(poly);
16752
+ const polygonArea2 = area$1(poly);
16347
16753
  return polygonArea2;
16348
16754
  }
16349
16755
  getPolygonPerimeter(poly) {
@@ -16361,7 +16767,7 @@ class TurfHelper {
16361
16767
  const p1 = points[i];
16362
16768
  const p2 = points[(i + 1) % effectiveLen];
16363
16769
  doubleized.push(new L.LatLng(p1.lat, p1.lng));
16364
- const midPoint = turf_midpoint_default(point([p1.lng, p1.lat]), point([p2.lng, p2.lat]));
16770
+ const midPoint = midpoint(point$1([p1.lng, p1.lat]), point$1([p2.lng, p2.lat]));
16365
16771
  doubleized.push(
16366
16772
  new L.LatLng(midPoint.geometry.coordinates[1], midPoint.geometry.coordinates[0])
16367
16773
  );
@@ -16393,10 +16799,12 @@ class TurfHelper {
16393
16799
  }
16394
16800
  return false;
16395
16801
  } catch (error) {
16396
- console.warn(
16397
- "Error checking for holes:",
16398
- error instanceof Error ? error.message : String(error)
16399
- );
16802
+ if (!isTestEnvironment()) {
16803
+ console.warn(
16804
+ "Error checking for holes:",
16805
+ error instanceof Error ? error.message : String(error)
16806
+ );
16807
+ }
16400
16808
  return false;
16401
16809
  }
16402
16810
  }
@@ -16458,10 +16866,12 @@ class TurfHelper {
16458
16866
  }
16459
16867
  return [feature2];
16460
16868
  } catch (error) {
16461
- console.warn(
16462
- "Error in getKinksWithHolePreservation:",
16463
- error instanceof Error ? error.message : String(error)
16464
- );
16869
+ if (!isTestEnvironment()) {
16870
+ console.warn(
16871
+ "Error in getKinksWithHolePreservation:",
16872
+ error instanceof Error ? error.message : String(error)
16873
+ );
16874
+ }
16465
16875
  return [feature2];
16466
16876
  }
16467
16877
  }
@@ -16495,10 +16905,12 @@ class TurfHelper {
16495
16905
  }
16496
16906
  return false;
16497
16907
  } catch (error) {
16498
- console.warn(
16499
- "Error checking complete hole traversal:",
16500
- error instanceof Error ? error.message : String(error)
16501
- );
16908
+ if (!isTestEnvironment()) {
16909
+ console.warn(
16910
+ "Error checking complete hole traversal:",
16911
+ error instanceof Error ? error.message : String(error)
16912
+ );
16913
+ }
16502
16914
  return false;
16503
16915
  }
16504
16916
  }
@@ -16530,10 +16942,12 @@ class TurfHelper {
16530
16942
  }
16531
16943
  return null;
16532
16944
  } catch (error) {
16533
- console.warn(
16534
- "Error finding self-intersection line:",
16535
- error instanceof Error ? error.message : String(error)
16536
- );
16945
+ if (!isTestEnvironment()) {
16946
+ console.warn(
16947
+ "Error finding self-intersection line:",
16948
+ error instanceof Error ? error.message : String(error)
16949
+ );
16950
+ }
16537
16951
  return null;
16538
16952
  }
16539
16953
  }
@@ -16545,18 +16959,20 @@ class TurfHelper {
16545
16959
  if (line.length < 2) return false;
16546
16960
  const lineStart = line[0];
16547
16961
  const lineEnd = line[line.length - 1];
16548
- const holePolygon = polygon([hole]);
16549
- const startInHole = turf_boolean_point_in_polygon_default(point(lineStart), holePolygon);
16550
- const endInHole = turf_boolean_point_in_polygon_default(point(lineEnd), holePolygon);
16962
+ const holePolygon = polygon$1([hole]);
16963
+ const startInHole = turf_boolean_point_in_polygon_default(point$1(lineStart), holePolygon);
16964
+ const endInHole = turf_boolean_point_in_polygon_default(point$1(lineEnd), holePolygon);
16551
16965
  if (startInHole !== endInHole) {
16552
16966
  return true;
16553
16967
  }
16554
16968
  return false;
16555
16969
  } catch (error) {
16556
- console.warn(
16557
- "Error checking line hole traversal:",
16558
- error instanceof Error ? error.message : String(error)
16559
- );
16970
+ if (!isTestEnvironment()) {
16971
+ console.warn(
16972
+ "Error checking line hole traversal:",
16973
+ error instanceof Error ? error.message : String(error)
16974
+ );
16975
+ }
16560
16976
  return false;
16561
16977
  }
16562
16978
  }
@@ -16565,29 +16981,31 @@ class TurfHelper {
16565
16981
  */
16566
16982
  holeIsCutByKinks(outerRing, hole) {
16567
16983
  try {
16568
- const outerPolygon = polygon([outerRing]);
16569
- const holePolygon = polygon([hole]);
16984
+ const outerPolygon = polygon$1([outerRing]);
16985
+ const holePolygon = polygon$1([hole]);
16570
16986
  const kinkFeatures = turf_kinks_default(outerPolygon);
16571
16987
  if (kinkFeatures.features.length === 0) return false;
16572
16988
  for (const kink of kinkFeatures.features) {
16573
16989
  const kinkPt = kink.geometry.coordinates;
16574
16990
  try {
16575
- const d = turf_distance_default(point(kinkPt), turf_centroid_default(holePolygon));
16991
+ const d = distance$1(point$1(kinkPt), centroid$1(holePolygon));
16576
16992
  if (d < 0.01) {
16577
16993
  return true;
16578
16994
  }
16579
- if (turf_boolean_point_in_polygon_default(point(kinkPt), holePolygon)) {
16995
+ if (turf_boolean_point_in_polygon_default(point$1(kinkPt), holePolygon)) {
16580
16996
  return true;
16581
16997
  }
16582
16998
  } catch {
16583
- if (turf_boolean_point_in_polygon_default(point(kinkPt), holePolygon)) {
16999
+ if (turf_boolean_point_in_polygon_default(point$1(kinkPt), holePolygon)) {
16584
17000
  return true;
16585
17001
  }
16586
17002
  }
16587
17003
  }
16588
17004
  return false;
16589
17005
  } catch (error) {
16590
- console.warn("Error checking hole cut by kinks:", error.message);
17006
+ if (!isTestEnvironment()) {
17007
+ console.warn("Error checking hole cut by kinks:", error.message);
17008
+ }
16591
17009
  return false;
16592
17010
  }
16593
17011
  }
@@ -16616,16 +17034,16 @@ class TurfHelper {
16616
17034
  if (holes.length === 0) {
16617
17035
  return false;
16618
17036
  }
16619
- const outerPolygon = polygon([outerRing]);
17037
+ const outerPolygon = polygon$1([outerRing]);
16620
17038
  for (const hole of holes) {
16621
- const holePolygon = polygon([hole]);
17039
+ const holePolygon = polygon$1([hole]);
16622
17040
  const intersection3 = this.getIntersection(outerPolygon, holePolygon);
16623
17041
  if (intersection3) {
16624
17042
  return true;
16625
17043
  }
16626
17044
  for (let i = 0; i < outerRing.length - 1; i++) {
16627
17045
  const pt = outerRing[i];
16628
- const pointInHole = turf_boolean_point_in_polygon_default(point(pt), holePolygon);
17046
+ const pointInHole = turf_boolean_point_in_polygon_default(point$1(pt), holePolygon);
16629
17047
  if (pointInHole) {
16630
17048
  return true;
16631
17049
  }
@@ -16658,10 +17076,12 @@ class TurfHelper {
16658
17076
  });
16659
17077
  return resultPolygons;
16660
17078
  } catch (error) {
16661
- console.warn(
16662
- "Error handling complete hole traversal:",
16663
- error instanceof Error ? error.message : String(error)
16664
- );
17079
+ if (!isTestEnvironment()) {
17080
+ console.warn(
17081
+ "Error handling complete hole traversal:",
17082
+ error instanceof Error ? error.message : String(error)
17083
+ );
17084
+ }
16665
17085
  try {
16666
17086
  const fallbackPolygon = {
16667
17087
  ...outerPolygon,
@@ -16685,7 +17105,7 @@ class TurfHelper {
16685
17105
  try {
16686
17106
  let resultPolygon = basePolygon;
16687
17107
  for (const hole of holes) {
16688
- const holePolygon = polygon([hole]);
17108
+ const holePolygon = polygon$1([hole]);
16689
17109
  const intersection3 = this.getIntersection(holePolygon, resultPolygon);
16690
17110
  if (intersection3) {
16691
17111
  const difference22 = this.polygonDifference(resultPolygon, holePolygon);
@@ -16702,7 +17122,7 @@ class TurfHelper {
16702
17122
  geometry: { type: "Polygon", coordinates: coords },
16703
17123
  properties: {}
16704
17124
  };
16705
- const polygonArea2 = turf_area_default(poly);
17125
+ const polygonArea2 = area$1(poly);
16706
17126
  if (polygonArea2 > largestArea) {
16707
17127
  largestArea = polygonArea2;
16708
17128
  largestPolygon = poly;
@@ -16713,341 +17133,113 @@ class TurfHelper {
16713
17133
  }
16714
17134
  }
16715
17135
  } else {
16716
- }
16717
- } else {
16718
- }
16719
- }
16720
- return resultPolygon;
16721
- } catch (error) {
16722
- console.warn(
16723
- "Error subtracting intersecting holes:",
16724
- error instanceof Error ? error.message : String(error)
16725
- );
16726
- return basePolygon;
16727
- }
16728
- }
16729
- /**
16730
- * Remove duplicate vertices from a polygon to prevent turf errors
16731
- */
16732
- removeDuplicateVertices(feature2) {
16733
- if (!feature2 || !feature2.geometry || !feature2.geometry.coordinates) {
16734
- console.warn("Invalid feature passed to removeDuplicateVertices");
16735
- return feature2;
16736
- }
16737
- const cleanCoordinates = (coords) => {
16738
- if (!coords || coords.length < 3) {
16739
- console.warn("Invalid coordinates array - need at least 3 points for a polygon");
16740
- return coords || [];
16741
- }
16742
- const cleaned = [];
16743
- const tolerance = 1e-6;
16744
- for (let i = 0; i < coords.length; i++) {
16745
- const current = coords[i];
16746
- const next = coords[(i + 1) % coords.length];
16747
- if (!current || !Array.isArray(current) || current.length < 2 || !next || !Array.isArray(next) || next.length < 2) {
16748
- continue;
16749
- }
16750
- const latDiff = Math.abs(current[1] - next[1]);
16751
- const lngDiff = Math.abs(current[0] - next[0]);
16752
- if (latDiff > tolerance || lngDiff > tolerance) {
16753
- cleaned.push(current);
16754
- }
16755
- }
16756
- if (cleaned.length < 3) {
16757
- console.warn("After cleaning, polygon has less than 3 points");
16758
- return coords;
16759
- }
16760
- if (cleaned.length > 0) {
16761
- const first = cleaned[0];
16762
- const last = cleaned[cleaned.length - 1];
16763
- const latDiff = Math.abs(first[1] - last[1]);
16764
- const lngDiff = Math.abs(first[0] - last[0]);
16765
- if (latDiff > tolerance || lngDiff > tolerance) {
16766
- cleaned.push([first[0], first[1]]);
16767
- }
16768
- }
16769
- return cleaned;
16770
- };
16771
- try {
16772
- if (feature2.geometry.type === "Polygon") {
16773
- const cleanedCoords = feature2.geometry.coordinates.map((ring) => cleanCoordinates(ring));
16774
- if (cleanedCoords.some((ring) => ring.length < 4)) {
16775
- console.warn("Cleaned polygon has invalid ring with less than 4 coordinates");
16776
- return feature2;
16777
- }
16778
- return {
16779
- ...feature2,
16780
- geometry: {
16781
- ...feature2.geometry,
16782
- coordinates: cleanedCoords
16783
- }
16784
- };
16785
- } else if (feature2.geometry.type === "MultiPolygon") {
16786
- const cleanedCoords = feature2.geometry.coordinates.map(
16787
- (polygon2) => polygon2.map((ring) => cleanCoordinates(ring))
16788
- );
16789
- if (cleanedCoords.some((polygon2) => polygon2.some((ring) => ring.length < 4))) {
16790
- console.warn("Cleaned multipolygon has invalid ring with less than 4 coordinates");
16791
- return feature2;
16792
- }
16793
- return {
16794
- ...feature2,
16795
- geometry: {
16796
- ...feature2.geometry,
16797
- coordinates: cleanedCoords
16798
- }
16799
- };
16800
- }
16801
- } catch (error) {
16802
- console.warn(
16803
- "Error in removeDuplicateVertices:",
16804
- error instanceof Error ? error.message : String(error)
16805
- );
16806
- return feature2;
16807
- }
16808
- return feature2;
16809
- }
16810
- }
16811
- const isTouchDevice = () => "ontouchstart" in window || navigator.maxTouchPoints > 0;
16812
- class PolyDrawUtil {
16813
- /**
16814
- * Gets the bounds of the polygon with optional padding.
16815
- * @param polygon Array of LatLng points.
16816
- * @param padding Padding factor.
16817
- * @returns The LatLngBounds.
16818
- */
16819
- static getBounds(polygon2, padding = 0) {
16820
- const tmpLatLng = [];
16821
- polygon2.forEach((ll) => {
16822
- if (isNaN(ll.lat) || isNaN(ll.lng)) ;
16823
- tmpLatLng.push(ll);
16824
- });
16825
- const polyLine = new L.Polyline(tmpLatLng);
16826
- const bounds = polyLine.getBounds();
16827
- if (padding !== 0) {
16828
- return bounds.pad(padding);
16829
- }
16830
- return bounds;
16831
- }
16832
- }
16833
- class Compass {
16834
- constructor(minLat = 0, minLng = 0, maxLat = 0, maxLng = 0) {
16835
- __publicField(this, "direction", {
16836
- East: new L.LatLng(0, 0),
16837
- North: new L.LatLng(0, 0),
16838
- NorthEast: new L.LatLng(0, 0),
16839
- NorthWest: new L.LatLng(0, 0),
16840
- South: new L.LatLng(0, 0),
16841
- SouthEast: new L.LatLng(0, 0),
16842
- SouthWest: new L.LatLng(0, 0),
16843
- West: new L.LatLng(0, 0)
16844
- });
16845
- this.direction.North = new L.LatLng(maxLat, (minLng + maxLng) / 2);
16846
- this.direction.NorthEast = new L.LatLng(maxLat, maxLng);
16847
- this.direction.East = new L.LatLng((minLat + maxLat) / 2, maxLng);
16848
- this.direction.SouthEast = new L.LatLng(minLat, maxLng);
16849
- this.direction.South = new L.LatLng(minLat, (minLng + maxLng) / 2);
16850
- this.direction.SouthWest = new L.LatLng(minLat, minLng);
16851
- this.direction.West = new L.LatLng((minLat + maxLat) / 2, minLng);
16852
- this.direction.NorthWest = new L.LatLng(maxLat, minLng);
16853
- }
16854
- getDirection(direction) {
16855
- switch (direction) {
16856
- case MarkerPosition.SouthWest:
16857
- return this.direction.SouthWest;
16858
- case MarkerPosition.West:
16859
- return this.direction.West;
16860
- case MarkerPosition.NorthWest:
16861
- return this.direction.NorthWest;
16862
- case MarkerPosition.North:
16863
- return this.direction.North;
16864
- case MarkerPosition.NorthEast:
16865
- return this.direction.NorthEast;
16866
- case MarkerPosition.East:
16867
- return this.direction.East;
16868
- case MarkerPosition.SouthEast:
16869
- return this.direction.SouthEast;
16870
- case MarkerPosition.South:
16871
- return this.direction.South;
16872
- default:
16873
- throw new Error();
16874
- }
16875
- }
16876
- getPositions(startPosition = MarkerPosition.SouthWest, clockwise = false, addClosingNode = true) {
16877
- const positions = [];
16878
- const posArray = this.getPositionAsArray(startPosition, clockwise);
16879
- posArray.forEach((v) => {
16880
- positions.push([v.lng, v.lat]);
16881
- });
16882
- if (addClosingNode) {
16883
- positions.push([posArray[0].lng, posArray[0].lat]);
16884
- }
16885
- return positions;
16886
- }
16887
- getPositionAsArray(startPosition = MarkerPosition.NorthEast, clockwise = false) {
16888
- const positions = [];
16889
- if (clockwise) {
16890
- positions.push(this.direction.SouthWest);
16891
- positions.push(this.direction.West);
16892
- positions.push(this.direction.NorthWest);
16893
- positions.push(this.direction.North);
16894
- positions.push(this.direction.NorthEast);
16895
- positions.push(this.direction.East);
16896
- positions.push(this.direction.SouthEast);
16897
- positions.push(this.direction.South);
16898
- } else {
16899
- positions.push(this.direction.SouthWest);
16900
- positions.push(this.direction.South);
16901
- positions.push(this.direction.SouthEast);
16902
- positions.push(this.direction.East);
16903
- positions.push(this.direction.NorthEast);
16904
- positions.push(this.direction.North);
16905
- positions.push(this.direction.NorthWest);
16906
- positions.push(this.direction.West);
16907
- }
16908
- if (startPosition !== MarkerPosition.SouthWest) {
16909
- const chunk = positions.splice(0, startPosition);
16910
- chunk.forEach((v, i) => {
16911
- positions.splice(startPosition + i, 0, v);
16912
- });
16913
- }
16914
- return positions;
16915
- }
16916
- }
16917
- class Perimeter {
16918
- constructor(length2, config) {
16919
- __publicField(this, "metricLength", "");
16920
- __publicField(this, "metricUnit", "");
16921
- __publicField(this, "imperialLength", "");
16922
- __publicField(this, "imperialUnit", "");
16923
- if (length2 !== null || length2 !== void 0) {
16924
- if (length2 === 0) {
16925
- if (config.markers.markerInfoIcon.usePerimeterMinValue) {
16926
- this.metricLength = config.markers.markerInfoIcon.values.min.metric;
16927
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16928
- this.imperialLength = config.markers.markerInfoIcon.values.min.imperial;
16929
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.feet;
16930
- } else {
16931
- this.metricLength = config.markers.markerInfoIcon.values.unknown.metric;
16932
- this.metricUnit = config.markers.markerInfoIcon.units.unknownUnit;
16933
- this.imperialLength = config.markers.markerInfoIcon.values.unknown.imperial;
16934
- this.imperialUnit = config.markers.markerInfoIcon.units.unknownUnit;
16935
- }
16936
- } else if (length2 < 100) {
16937
- this.metricLength = (Math.ceil(length2 / 10) * 10).toString();
16938
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16939
- } else if (length2 < 500) {
16940
- this.metricLength = (Math.ceil(length2 / 50) * 50).toString();
16941
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16942
- } else if (length2 < 1e3) {
16943
- this.metricLength = (Math.ceil(length2 / 100) * 100).toString();
16944
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.m;
16945
- } else if (length2 < 1e4) {
16946
- this.metricLength = (Math.ceil(length2 / 100) * 100 / 1e3).toFixed(1);
16947
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.km;
16948
- } else {
16949
- this.metricLength = (Math.ceil(length2 / 1e3) * 1e3 / 1e3).toString();
16950
- this.metricUnit = config.markers.markerInfoIcon.units.metric.perimeter.km;
16951
- }
16952
- const inch = length2 / 0.0254;
16953
- const feet = inch / 12;
16954
- const yards = feet / 3;
16955
- const miles = yards / 1760;
16956
- if (length2 < 1e3 / 2.54) {
16957
- this.imperialLength = (Math.ceil(feet / 10) * 10).toString();
16958
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.feet;
16959
- } else if (length2 < 1e3 / 2.54 * 3) {
16960
- this.imperialLength = (Math.ceil(yards / 10) * 10).toString();
16961
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.yards;
16962
- } else if (length2 < 1609) {
16963
- this.imperialLength = miles.toFixed(2);
16964
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
16965
- } else if (length2 < 16093) {
16966
- this.imperialLength = miles.toFixed(1);
16967
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
16968
- } else {
16969
- this.imperialLength = miles.toFixed(0);
16970
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.perimeter.miles;
17136
+ }
17137
+ } else {
17138
+ }
17139
+ }
17140
+ return resultPolygon;
17141
+ } catch (error) {
17142
+ if (!isTestEnvironment()) {
17143
+ console.warn(
17144
+ "Error subtracting intersecting holes:",
17145
+ error instanceof Error ? error.message : String(error)
17146
+ );
16971
17147
  }
17148
+ return basePolygon;
16972
17149
  }
16973
17150
  }
16974
- }
16975
- class Area {
16976
- constructor(sqrMeterArea, config) {
16977
- __publicField(this, "metricArea", "");
16978
- __publicField(this, "metricUnit", "");
16979
- __publicField(this, "imperialArea", "");
16980
- __publicField(this, "imperialUnit", "");
16981
- const area2 = sqrMeterArea;
16982
- const onlyMetrics = config.markers.markerInfoIcon.units.metric.onlyMetrics;
16983
- if (area2 !== null || area2 !== void 0) {
16984
- if (area2 === 0) {
16985
- this.metricArea = "-";
16986
- this.metricUnit = config.markers.markerInfoIcon.units.unknownUnit;
16987
- this.imperialArea = "-";
16988
- this.imperialUnit = config.markers.markerInfoIcon.units.unknownUnit;
16989
- } else if (area2 < 1e4) {
16990
- this.metricArea = Math.round(area2).toString();
16991
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.m2;
16992
- } else if (area2 < 1e5) {
16993
- if (onlyMetrics) {
16994
- this.metricArea = (area2 / 1e6).toFixed(2);
16995
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
16996
- } else {
16997
- this.metricArea = (area2 / 1e3).toFixed(1);
16998
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.daa;
17151
+ /**
17152
+ * Remove duplicate vertices from a polygon to prevent turf errors
17153
+ */
17154
+ removeDuplicateVertices(feature2) {
17155
+ if (!feature2 || !feature2.geometry || !feature2.geometry.coordinates) {
17156
+ if (!isTestEnvironment()) {
17157
+ console.warn("Invalid feature passed to removeDuplicateVertices");
17158
+ }
17159
+ return feature2;
17160
+ }
17161
+ const cleanCoordinates = (coords) => {
17162
+ if (!coords || coords.length < 3) {
17163
+ if (!isTestEnvironment()) {
17164
+ console.warn("Invalid coordinates array - need at least 3 points for a polygon");
16999
17165
  }
17000
- } else if (area2 < 1e7) {
17001
- if (onlyMetrics) {
17002
- this.metricArea = (area2 / 1e6).toFixed(2);
17003
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
17004
- } else {
17005
- this.metricArea = Math.round(area2 / 1e3).toString();
17006
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.daa;
17166
+ return coords || [];
17167
+ }
17168
+ const cleaned = [];
17169
+ const tolerance = 1e-6;
17170
+ for (let i = 0; i < coords.length; i++) {
17171
+ const current = coords[i];
17172
+ const next = coords[(i + 1) % coords.length];
17173
+ if (!current || !Array.isArray(current) || current.length < 2 || !next || !Array.isArray(next) || next.length < 2) {
17174
+ continue;
17007
17175
  }
17008
- } else if (area2 < 1e8) {
17009
- if (onlyMetrics) {
17010
- this.metricArea = (area2 / 1e6).toFixed(1);
17011
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
17012
- } else {
17013
- this.metricArea = Math.round(area2 / 1e4).toString();
17014
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.ha;
17176
+ const latDiff = Math.abs(current[1] - next[1]);
17177
+ const lngDiff = Math.abs(current[0] - next[0]);
17178
+ if (latDiff > tolerance || lngDiff > tolerance) {
17179
+ cleaned.push(current);
17015
17180
  }
17016
- } else {
17017
- this.metricArea = Math.round(area2 / 1e6).toString();
17018
- this.metricUnit = config.markers.markerInfoIcon.units.metric.area.km2;
17019
17181
  }
17020
- const inch2 = area2 * 1550;
17021
- const feet2 = inch2 * 69444e-7;
17022
- const yards2 = feet2 * 0.11111;
17023
- const acres = yards2 * 20661e-8;
17024
- const miles2 = yards2 * 32283e-11;
17025
- if (area2 < 92.9) {
17026
- this.imperialArea = Math.round(feet2).toString();
17027
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.feet2;
17028
- } else if (area2 < 836.14) {
17029
- this.imperialArea = yards2.toFixed(0);
17030
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.yards2;
17031
- } else if (area2 < 40469.6) {
17032
- this.imperialArea = acres.toFixed(2);
17033
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
17034
- } else if (area2 < 404696) {
17035
- this.imperialArea = acres.toFixed(1);
17036
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
17037
- } else if (area2 < 4046960) {
17038
- this.imperialArea = acres.toFixed(0);
17039
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.acres;
17040
- } else if (area2 < 25900404) {
17041
- this.imperialArea = miles2.toFixed(2);
17042
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
17043
- } else if (area2 < 259004040) {
17044
- this.imperialArea = miles2.toFixed(1);
17045
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
17046
- } else {
17047
- this.imperialArea = miles2.toFixed(0);
17048
- this.imperialUnit = config.markers.markerInfoIcon.units.imperial.area.miles2;
17182
+ if (cleaned.length < 3) {
17183
+ if (!isTestEnvironment()) {
17184
+ console.warn("After cleaning, polygon has less than 3 points");
17185
+ }
17186
+ return coords;
17187
+ }
17188
+ if (cleaned.length > 0) {
17189
+ const first = cleaned[0];
17190
+ const last = cleaned[cleaned.length - 1];
17191
+ const latDiff = Math.abs(first[1] - last[1]);
17192
+ const lngDiff = Math.abs(first[0] - last[0]);
17193
+ if (latDiff > tolerance || lngDiff > tolerance) {
17194
+ cleaned.push([first[0], first[1]]);
17195
+ }
17196
+ }
17197
+ return cleaned;
17198
+ };
17199
+ try {
17200
+ if (feature2.geometry.type === "Polygon") {
17201
+ const cleanedCoords = feature2.geometry.coordinates.map((ring) => cleanCoordinates(ring));
17202
+ if (cleanedCoords.some((ring) => ring.length < 4)) {
17203
+ if (!isTestEnvironment()) {
17204
+ console.warn("Cleaned polygon has invalid ring with less than 4 coordinates");
17205
+ }
17206
+ return feature2;
17207
+ }
17208
+ return {
17209
+ ...feature2,
17210
+ geometry: {
17211
+ ...feature2.geometry,
17212
+ coordinates: cleanedCoords
17213
+ }
17214
+ };
17215
+ } else if (feature2.geometry.type === "MultiPolygon") {
17216
+ const cleanedCoords = feature2.geometry.coordinates.map(
17217
+ (polygon2) => polygon2.map((ring) => cleanCoordinates(ring))
17218
+ );
17219
+ if (cleanedCoords.some((polygon2) => polygon2.some((ring) => ring.length < 4))) {
17220
+ if (!isTestEnvironment()) {
17221
+ console.warn("Cleaned multipolygon has invalid ring with less than 4 coordinates");
17222
+ }
17223
+ return feature2;
17224
+ }
17225
+ return {
17226
+ ...feature2,
17227
+ geometry: {
17228
+ ...feature2.geometry,
17229
+ coordinates: cleanedCoords
17230
+ }
17231
+ };
17232
+ }
17233
+ } catch (error) {
17234
+ if (!isTestEnvironment()) {
17235
+ console.warn(
17236
+ "Error in removeDuplicateVertices:",
17237
+ error instanceof Error ? error.message : String(error)
17238
+ );
17049
17239
  }
17240
+ return feature2;
17050
17241
  }
17242
+ return feature2;
17051
17243
  }
17052
17244
  }
17053
17245
  function createButtons(container, subContainer, config, onActivateToggle, onDrawClick, onSubtractClick, onEraseClick, onPointToPointClick) {
@@ -17117,15 +17309,14 @@ class PolygonUtil {
17117
17309
  * @returns The center LatLng.
17118
17310
  */
17119
17311
  static getCenter(polygon2) {
17120
- const pi2 = Math.PI;
17121
17312
  let x = 0;
17122
17313
  let y = 0;
17123
17314
  let z = 0;
17124
17315
  polygon2.forEach((v) => {
17125
17316
  let lat1 = v.lat;
17126
17317
  let lon1 = v.lng;
17127
- lat1 = lat1 * pi2 / 180;
17128
- lon1 = lon1 * pi2 / 180;
17318
+ lat1 = lat1 * MATH.DEG_TO_RAD;
17319
+ lon1 = lon1 * MATH.DEG_TO_RAD;
17129
17320
  x += Math.cos(lat1) * Math.cos(lon1);
17130
17321
  y += Math.cos(lat1) * Math.sin(lon1);
17131
17322
  z += Math.sin(lat1);
@@ -17133,8 +17324,8 @@ class PolygonUtil {
17133
17324
  let lng = Math.atan2(y, x);
17134
17325
  const hyp = Math.sqrt(x * x + y * y);
17135
17326
  let lat = Math.atan2(z, hyp);
17136
- lat = lat * 180 / pi2;
17137
- lng = lng * 180 / pi2;
17327
+ lat = lat * MATH.RAD_TO_DEG;
17328
+ lng = lng * MATH.RAD_TO_DEG;
17138
17329
  const center2 = { lat, lng };
17139
17330
  return center2;
17140
17331
  }
@@ -17690,9 +17881,10 @@ class PolygonDrawManager {
17690
17881
  if ("latlng" in event && event.latlng) {
17691
17882
  this.tracer.addLatLng(event.latlng);
17692
17883
  } else if ("touches" in event && event.touches && event.touches.length > 0) {
17884
+ const rect = this.map.getContainer().getBoundingClientRect();
17693
17885
  const latlng = this.map.containerPointToLatLng([
17694
- event.touches[0].clientX,
17695
- event.touches[0].clientY
17886
+ event.touches[0].clientX - rect.x,
17887
+ event.touches[0].clientY - rect.y
17696
17888
  ]);
17697
17889
  this.tracer.addLatLng(latlng);
17698
17890
  }
@@ -17855,7 +18047,9 @@ class PolygonDrawManager {
17855
18047
  isPointToPoint: true
17856
18048
  });
17857
18049
  } catch (error) {
17858
- console.warn("Error completing point-to-point polygon:", error);
18050
+ if (!isTestEnvironment()) {
18051
+ console.warn("Error completing point-to-point polygon:", error);
18052
+ }
17859
18053
  this.clearP2pMarkers();
17860
18054
  this.resetTracer();
17861
18055
  }
@@ -19228,7 +19422,9 @@ class PolygonInteractionManager {
19228
19422
  }
19229
19423
  markerDrag(featureGroup) {
19230
19424
  if (!this._activeMarker) {
19231
- console.warn("No active marker set for dragging.");
19425
+ if (!isTestEnvironment()) {
19426
+ console.warn("No active marker set for dragging.");
19427
+ }
19232
19428
  return;
19233
19429
  }
19234
19430
  const newPos = [];
@@ -19236,6 +19432,12 @@ class PolygonInteractionManager {
19236
19432
  let hole = [];
19237
19433
  const layers = featureGroup.getLayers();
19238
19434
  const polygonLayer = layers.find((l) => l instanceof L.Polygon);
19435
+ if (!polygonLayer) {
19436
+ if (!isTestEnvironment()) {
19437
+ console.warn("No polygon found in feature group for marker drag.");
19438
+ }
19439
+ return;
19440
+ }
19239
19441
  const posarrays = polygonLayer.getLatLngs();
19240
19442
  let length2 = 0;
19241
19443
  const markers2 = layers.filter((layer) => layer instanceof L.Marker);
@@ -19322,14 +19524,20 @@ class PolygonInteractionManager {
19322
19524
  this.eventManager.emit("polydraw:polygon:updated", {
19323
19525
  operation: "markerDrag",
19324
19526
  polygon: this.turfHelper.getTurfPolygon(polygon2),
19325
- allowMerge: true
19527
+ allowMerge: true,
19528
+ // Allow intelligent merging for intersections
19529
+ intelligentMerge: true
19530
+ // Flag for smart merging logic
19326
19531
  });
19327
19532
  }
19328
19533
  } else {
19329
19534
  this.eventManager.emit("polydraw:polygon:updated", {
19330
19535
  operation: "markerDrag",
19331
19536
  polygon: feature2,
19332
- allowMerge: true
19537
+ allowMerge: true,
19538
+ // Allow intelligent merging for intersections
19539
+ intelligentMerge: true
19540
+ // Flag for smart merging logic
19333
19541
  });
19334
19542
  }
19335
19543
  }
@@ -19343,14 +19551,16 @@ class PolygonInteractionManager {
19343
19551
  this.eventManager.emit("polydraw:polygon:updated", {
19344
19552
  operation: "markerDrag",
19345
19553
  polygon: this.turfHelper.getTurfPolygon(polygon2),
19346
- allowMerge: true
19554
+ allowMerge: false
19555
+ // Fixed: prevent merging during vertex drag
19347
19556
  });
19348
19557
  }
19349
19558
  } else {
19350
19559
  this.eventManager.emit("polydraw:polygon:updated", {
19351
19560
  operation: "markerDrag",
19352
19561
  polygon: feature2,
19353
- allowMerge: true
19562
+ allowMerge: false
19563
+ // Fixed: prevent merging during vertex drag
19354
19564
  });
19355
19565
  }
19356
19566
  }
@@ -19612,7 +19822,9 @@ class PolygonInteractionManager {
19612
19822
  }
19613
19823
  }
19614
19824
  } catch (differenceError) {
19615
- console.warn("Failed to perform difference operation:", differenceError);
19825
+ if (!isTestEnvironment()) {
19826
+ console.warn("Failed to perform difference operation:", differenceError);
19827
+ }
19616
19828
  this.eventManager.emit("polydraw:polygon:updated", {
19617
19829
  operation: "modifierSubtractFallback",
19618
19830
  polygon: existingPolygon,
@@ -19620,12 +19832,16 @@ class PolygonInteractionManager {
19620
19832
  });
19621
19833
  }
19622
19834
  } catch (error) {
19623
- console.warn("Error in modifier subtract operation:", error);
19835
+ if (!isTestEnvironment()) {
19836
+ console.warn("Error in modifier subtract operation:", error);
19837
+ }
19624
19838
  }
19625
19839
  });
19626
19840
  this.polygonInformation.createPolygonInformationStorage(this.getFeatureGroups());
19627
19841
  } catch (error) {
19628
- console.warn("Error in performModifierSubtract:", error);
19842
+ if (!isTestEnvironment()) {
19843
+ console.warn("Error in performModifierSubtract:", error);
19844
+ }
19629
19845
  }
19630
19846
  }
19631
19847
  getEdgeDeletionModifierKey() {
@@ -19944,10 +20160,12 @@ class PolygonInteractionManager {
19944
20160
  }
19945
20161
  return polygonLayer.toGeoJSON();
19946
20162
  } catch (error) {
19947
- if (error instanceof Error) {
19948
- console.warn("Error getting polygon GeoJSON from feature group:", error.message);
19949
- } else {
19950
- console.warn("Error getting polygon GeoJSON from feature group:", error);
20163
+ if (!isTestEnvironment()) {
20164
+ if (error instanceof Error) {
20165
+ console.warn("Error getting polygon GeoJSON from feature group:", error.message);
20166
+ } else {
20167
+ console.warn("Error getting polygon GeoJSON from feature group:", error);
20168
+ }
19951
20169
  }
19952
20170
  return {
19953
20171
  type: "Feature",
@@ -20006,10 +20224,12 @@ class PolygonInteractionManager {
20006
20224
  }
20007
20225
  return totalPerimeter * 1e3;
20008
20226
  } catch (error) {
20009
- if (error instanceof Error) {
20010
- console.warn("Error calculating total polygon perimeter:", error.message);
20011
- } else {
20012
- console.warn("Error calculating total polygon perimeter:", error);
20227
+ if (!isTestEnvironment()) {
20228
+ if (error instanceof Error) {
20229
+ console.warn("Error calculating total polygon perimeter:", error.message);
20230
+ } else {
20231
+ console.warn("Error calculating total polygon perimeter:", error);
20232
+ }
20013
20233
  }
20014
20234
  return this.turfHelper.getPolygonPerimeter(polygonGeoJSON) * 1e3;
20015
20235
  }
@@ -20125,9 +20345,13 @@ class PolygonMutationManager {
20125
20345
  */
20126
20346
  async handlePolygonModified(data) {
20127
20347
  const shouldSimplify = data.operation !== "addVertex" && data.operation !== "markerDrag" && data.operation !== "polygonDrag";
20348
+ let allowMerge = data.allowMerge;
20349
+ if (data.intelligentMerge && data.operation === "markerDrag") {
20350
+ allowMerge = this.shouldAllowIntelligentMerge(data.polygon);
20351
+ }
20128
20352
  const options = {
20129
20353
  simplify: shouldSimplify,
20130
- noMerge: !data.allowMerge,
20354
+ noMerge: !allowMerge,
20131
20355
  visualOptimizationLevel: data.optimizationLevel || 0
20132
20356
  };
20133
20357
  await this.addPolygon(data.polygon, options);
@@ -20187,6 +20411,10 @@ class PolygonMutationManager {
20187
20411
  async addPolygon(latlngs, options = {}) {
20188
20412
  const { noMerge = false } = options;
20189
20413
  try {
20414
+ const isInsideHole = this.isPolygonInsideExistingHole(latlngs);
20415
+ if (isInsideHole) {
20416
+ return await this.addPolygonLayer(latlngs, options);
20417
+ }
20190
20418
  if (this.config.mergePolygons && !noMerge && this.getFeatureGroups().length > 0 && !this.config.kinks) {
20191
20419
  return await this.mergePolygon(latlngs, options);
20192
20420
  } else {
@@ -20290,19 +20518,7 @@ class PolygonMutationManager {
20290
20518
  let markerLatlngs;
20291
20519
  try {
20292
20520
  const rawLatLngs = polygon2.getLatLngs();
20293
- if (Array.isArray(rawLatLngs) && rawLatLngs.length > 0) {
20294
- if (Array.isArray(rawLatLngs[0])) {
20295
- if (Array.isArray(rawLatLngs[0][0])) {
20296
- markerLatlngs = rawLatLngs[0];
20297
- } else {
20298
- markerLatlngs = rawLatLngs;
20299
- }
20300
- } else {
20301
- markerLatlngs = [rawLatLngs];
20302
- }
20303
- } else {
20304
- markerLatlngs = [];
20305
- }
20521
+ markerLatlngs = this.normalizePolygonCoordinates(rawLatLngs);
20306
20522
  } catch (error) {
20307
20523
  markerLatlngs = [];
20308
20524
  }
@@ -20326,7 +20542,7 @@ class PolygonMutationManager {
20326
20542
  if (ringIndex === 0) {
20327
20543
  this.interactionManager.addMarkers(latLngLiterals, featureGroup);
20328
20544
  } else {
20329
- const holePolyline = L.polyline(polygonRing, {
20545
+ const holePolyline = L.polyline(latLngLiterals, {
20330
20546
  color: this.config.colors.hole.border,
20331
20547
  weight: this.config.holeOptions.weight || 2,
20332
20548
  opacity: this.config.holeOptions.opacity || 1,
@@ -20459,6 +20675,124 @@ class PolygonMutationManager {
20459
20675
  };
20460
20676
  }
20461
20677
  }
20678
+ /**
20679
+ * Determine if intelligent merging should be allowed for a polygon
20680
+ * This checks if the polygon actually intersects with existing polygons
20681
+ */
20682
+ shouldAllowIntelligentMerge(polygon2) {
20683
+ try {
20684
+ for (const featureGroup of this.getFeatureGroups()) {
20685
+ try {
20686
+ const featureCollection2 = featureGroup.toGeoJSON();
20687
+ if (!featureCollection2 || !featureCollection2.features || !featureCollection2.features[0]) {
20688
+ continue;
20689
+ }
20690
+ const existingFeature = featureCollection2.features[0];
20691
+ if (!existingFeature.geometry || !existingFeature.geometry.coordinates) {
20692
+ continue;
20693
+ }
20694
+ const existingPolygon = this.turfHelper.getTurfPolygon(existingFeature);
20695
+ if (this.geometryManager.checkPolygonIntersection(existingPolygon, polygon2)) {
20696
+ return true;
20697
+ }
20698
+ } catch (error) {
20699
+ continue;
20700
+ }
20701
+ }
20702
+ return false;
20703
+ } catch (error) {
20704
+ return false;
20705
+ }
20706
+ }
20707
+ /**
20708
+ * Check if a polygon is completely inside a hole of an existing polygon
20709
+ * This prevents incorrect merging when drawing polygons inside holes
20710
+ */
20711
+ isPolygonInsideExistingHole(newPolygon) {
20712
+ try {
20713
+ for (const featureGroup of this.getFeatureGroups()) {
20714
+ try {
20715
+ const featureCollection2 = featureGroup.toGeoJSON();
20716
+ if (!featureCollection2 || !featureCollection2.features || !featureCollection2.features[0]) {
20717
+ continue;
20718
+ }
20719
+ const existingFeature = featureCollection2.features[0];
20720
+ if (!existingFeature.geometry || !existingFeature.geometry.coordinates) {
20721
+ continue;
20722
+ }
20723
+ let hasHoles = false;
20724
+ let holes = [];
20725
+ if (existingFeature.geometry.type === "Polygon") {
20726
+ hasHoles = existingFeature.geometry.coordinates.length > 1;
20727
+ if (hasHoles) {
20728
+ holes = existingFeature.geometry.coordinates.slice(1);
20729
+ }
20730
+ } else if (existingFeature.geometry.type === "MultiPolygon") {
20731
+ for (const polygonCoords of existingFeature.geometry.coordinates) {
20732
+ if (polygonCoords.length > 1) {
20733
+ hasHoles = true;
20734
+ holes.push(...polygonCoords.slice(1));
20735
+ }
20736
+ }
20737
+ }
20738
+ if (hasHoles && holes.length > 0) {
20739
+ for (const holeCoords of holes) {
20740
+ try {
20741
+ const holePolygon = this.turfHelper.createPolygon([holeCoords]);
20742
+ if (this.turfHelper.isPolygonCompletelyWithin(newPolygon, holePolygon)) {
20743
+ return true;
20744
+ }
20745
+ } catch (error) {
20746
+ continue;
20747
+ }
20748
+ }
20749
+ }
20750
+ } catch (error) {
20751
+ continue;
20752
+ }
20753
+ }
20754
+ return false;
20755
+ } catch (error) {
20756
+ return false;
20757
+ }
20758
+ }
20759
+ /**
20760
+ * Normalize polygon coordinates to handle complex nested structures
20761
+ * This fixes the bug where markers are missing when drawing polygons inside holes
20762
+ */
20763
+ normalizePolygonCoordinates(rawLatLngs) {
20764
+ if (!Array.isArray(rawLatLngs) || rawLatLngs.length === 0) {
20765
+ return [];
20766
+ }
20767
+ const isLatLngLike = (obj) => {
20768
+ return obj !== null && typeof obj === "object" && "lat" in obj && "lng" in obj && typeof obj.lat === "number" && typeof obj.lng === "number";
20769
+ };
20770
+ const flattenToRings = (coords) => {
20771
+ if (!Array.isArray(coords)) {
20772
+ return [];
20773
+ }
20774
+ if (coords.length > 0 && isLatLngLike(coords[0])) {
20775
+ return [coords];
20776
+ }
20777
+ const result = [];
20778
+ for (const item of coords) {
20779
+ if (Array.isArray(item)) {
20780
+ if (item.length > 0 && isLatLngLike(item[0])) {
20781
+ result.push(item);
20782
+ } else {
20783
+ const flattened = flattenToRings(item);
20784
+ result.push(...flattened);
20785
+ }
20786
+ }
20787
+ }
20788
+ return result;
20789
+ };
20790
+ try {
20791
+ return flattenToRings(rawLatLngs);
20792
+ } catch (error) {
20793
+ return [];
20794
+ }
20795
+ }
20462
20796
  /**
20463
20797
  * Create a polygon from GeoJSON feature
20464
20798
  */
@@ -20479,11 +20813,16 @@ class PolygonMutationManager {
20479
20813
  */
20480
20814
  getPolygon(latlngs) {
20481
20815
  const polygon2 = L.GeoJSON.geometryToLayer(latlngs);
20482
- polygon2.setStyle({
20816
+ const polygonStyle = {
20483
20817
  ...this.config.polygonOptions,
20484
20818
  color: this.config.colors.polygon.border,
20485
- fillColor: this.config.colors.polygon.fill
20486
- });
20819
+ fillColor: this.config.colors.polygon.fill,
20820
+ // Force these values to ensure they override any default styling
20821
+ weight: this.config.polygonOptions.weight || 2,
20822
+ opacity: this.config.polygonOptions.opacity || 1,
20823
+ fillOpacity: this.config.polygonOptions.fillOpacity || 0.2
20824
+ };
20825
+ polygon2.setStyle(polygonStyle);
20487
20826
  polygon2._polydrawUniqueId = L.Util.stamp(polygon2) + "_" + Date.now();
20488
20827
  delete polygon2._polydrawDragData;
20489
20828
  delete polygon2._polydrawOriginalLatLngs;
@@ -20529,8 +20868,10 @@ class PolygonMutationManager {
20529
20868
  }
20530
20869
  return polygon2.toGeoJSON();
20531
20870
  } catch (error) {
20532
- if (error instanceof Error) {
20533
- console.warn("Error getting complete polygon GeoJSON from feature group:", error.message);
20871
+ if (!isTestEnvironment()) {
20872
+ if (error instanceof Error) {
20873
+ console.warn("Error getting complete polygon GeoJSON from feature group:", error.message);
20874
+ }
20534
20875
  }
20535
20876
  return {
20536
20877
  type: "Feature",
@@ -21093,10 +21434,15 @@ class Polydraw extends L.Control {
21093
21434
  L.DomEvent.on(container, "click", L.DomEvent.stopPropagation);
21094
21435
  container.style.display = "flex";
21095
21436
  container.style.flexDirection = "column-reverse";
21437
+ container.style.pointerEvents = "auto";
21438
+ container.style.position = "relative";
21439
+ container.style.zIndex = "1000";
21096
21440
  this.subContainer = L.DomUtil.create("div", "sub-buttons", container);
21097
21441
  this.subContainer.style.maxHeight = "0px";
21098
21442
  this.subContainer.style.overflow = "hidden";
21099
21443
  this.subContainer.style.transition = "max-height 0.3s ease";
21444
+ this.subContainer.style.pointerEvents = "auto";
21445
+ this.subContainer.style.position = "relative";
21100
21446
  createButtons(
21101
21447
  container,
21102
21448
  this.subContainer,
@@ -21107,6 +21453,7 @@ class Polydraw extends L.Control {
21107
21453
  this._handleEraseClick,
21108
21454
  this._handlePointToPointClick
21109
21455
  );
21456
+ this.ensureButtonTouchResponsiveness(container);
21110
21457
  const uiUpdateListener = (mode) => {
21111
21458
  const drawButton = container.querySelector(".icon-draw");
21112
21459
  const subtractButton = container.querySelector(".icon-subtract");
@@ -21345,9 +21692,21 @@ class Polydraw extends L.Control {
21345
21692
  * @param enableScrollWheelZoom - Whether to enable scroll wheel zoom.
21346
21693
  */
21347
21694
  setLeafletMapEvents(enableDragging, enableDoubleClickZoom, enableScrollWheelZoom) {
21348
- enableDragging ? this.map.dragging.enable() : this.map.dragging.disable();
21349
- enableDoubleClickZoom ? this.map.doubleClickZoom.enable() : this.map.doubleClickZoom.disable();
21350
- enableScrollWheelZoom ? this.map.scrollWheelZoom.enable() : this.map.scrollWheelZoom.disable();
21695
+ if (enableDragging) {
21696
+ this.map.dragging.enable();
21697
+ } else {
21698
+ this.map.dragging.disable();
21699
+ }
21700
+ if (enableDoubleClickZoom) {
21701
+ this.map.doubleClickZoom.enable();
21702
+ } else {
21703
+ this.map.doubleClickZoom.disable();
21704
+ }
21705
+ if (enableScrollWheelZoom) {
21706
+ this.map.scrollWheelZoom.enable();
21707
+ } else {
21708
+ this.map.scrollWheelZoom.disable();
21709
+ }
21351
21710
  }
21352
21711
  /**
21353
21712
  * Resets the tracer polyline by clearing its LatLngs.
@@ -21409,9 +21768,10 @@ class Polydraw extends L.Control {
21409
21768
  if ("latlng" in event && event.latlng) {
21410
21769
  clickLatLng = event.latlng;
21411
21770
  } else if ("touches" in event && event.touches && event.touches.length > 0) {
21771
+ const rect = this.map.getContainer().getBoundingClientRect();
21412
21772
  clickLatLng = this.map.containerPointToLatLng([
21413
- event.touches[0].clientX,
21414
- event.touches[0].clientY
21773
+ event.touches[0].clientX - rect.x,
21774
+ event.touches[0].clientY - rect.y
21415
21775
  ]);
21416
21776
  }
21417
21777
  if (!clickLatLng) {
@@ -21435,9 +21795,10 @@ class Polydraw extends L.Control {
21435
21795
  if ("latlng" in event && event.latlng) {
21436
21796
  this.tracer.addLatLng(event.latlng);
21437
21797
  } else if ("touches" in event && event.touches && event.touches.length > 0) {
21798
+ const rect = this.map.getContainer().getBoundingClientRect();
21438
21799
  const latlng = this.map.containerPointToLatLng([
21439
- event.touches[0].clientX,
21440
- event.touches[0].clientY
21800
+ event.touches[0].clientX - rect.x,
21801
+ event.touches[0].clientY - rect.y
21441
21802
  ]);
21442
21803
  this.tracer.addLatLng(latlng);
21443
21804
  }
@@ -21626,6 +21987,25 @@ class Polydraw extends L.Control {
21626
21987
  return event.ctrlKey;
21627
21988
  }
21628
21989
  }
21990
+ /**
21991
+ * Ensures all buttons have proper touch responsiveness for Firefox Android
21992
+ * @param container - The main control container element
21993
+ */
21994
+ ensureButtonTouchResponsiveness(container) {
21995
+ const buttons = container.querySelectorAll("a");
21996
+ buttons.forEach((button) => {
21997
+ button.style.pointerEvents = "auto";
21998
+ button.style.touchAction = "manipulation";
21999
+ button.style.position = "relative";
22000
+ button.style.zIndex = "1";
22001
+ const touchHandler = (e) => {
22002
+ e.stopPropagation();
22003
+ e.target.style.pointerEvents = "auto";
22004
+ };
22005
+ button.addEventListener("touchstart", touchHandler, { passive: true });
22006
+ button.addEventListener("touchend", touchHandler, { passive: true });
22007
+ });
22008
+ }
21629
22009
  /**
21630
22010
  * Updates the visual indicator on the activate button to show if there are active polygons.
21631
22011
  */