leaflet-polydraw 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -13
- package/dist/polydraw.es.js +1243 -693
- package/dist/polydraw.es.js.map +1 -1
- package/dist/polydraw.umd.min.js +1 -1
- package/dist/polydraw.umd.min.js.map +1 -1
- package/dist/types/coordinate-utils.d.ts.map +1 -1
- package/dist/types/geometry-utils.d.ts.map +1 -1
- package/dist/types/managers/event-manager.d.ts +76 -4
- package/dist/types/managers/event-manager.d.ts.map +1 -1
- package/dist/types/managers/polygon-draw-manager.d.ts +2 -1
- package/dist/types/managers/polygon-draw-manager.d.ts.map +1 -1
- package/dist/types/managers/polygon-geometry-manager.d.ts +0 -16
- package/dist/types/managers/polygon-geometry-manager.d.ts.map +1 -1
- package/dist/types/managers/polygon-interaction-manager.d.ts +10 -5
- package/dist/types/managers/polygon-interaction-manager.d.ts.map +1 -1
- package/dist/types/managers/polygon-mutation-manager.d.ts +28 -9
- package/dist/types/managers/polygon-mutation-manager.d.ts.map +1 -1
- package/dist/types/map-state.d.ts.map +1 -1
- package/dist/types/polydraw.d.ts +160 -7
- package/dist/types/polydraw.d.ts.map +1 -1
- package/dist/types/styles/dynamic-styles.d.ts +3 -0
- package/dist/types/styles/dynamic-styles.d.ts.map +1 -0
- package/dist/types/turf-helper.d.ts +15 -4
- package/dist/types/turf-helper.d.ts.map +1 -1
- package/dist/types/types/polydraw-interfaces.d.ts +96 -10
- package/dist/types/types/polydraw-interfaces.d.ts.map +1 -1
- package/package.json +9 -3
package/dist/polydraw.es.js
CHANGED
|
@@ -7,18 +7,19 @@ const touchSupport = true;
|
|
|
7
7
|
const mergePolygons = true;
|
|
8
8
|
const kinks$1 = false;
|
|
9
9
|
const modes = { "draw": true, "subtract": true, "deleteAll": true, "p2p": true, "attachElbow": true, "dragElbow": true, "dragPolygons": true, "edgeDeletion": true };
|
|
10
|
-
const dragPolygons = { "realTimeUpdate": false, "showDragHandle": false, "opacity": 0.7, "dragCursor": "move", "hoverCursor": "grab", "markerBehavior": "hide", "markerAnimationDuration": 200, "autoMergeOnIntersect": true, "autoHoleOnContained": false, "dragInteractionBehavior": "auto", "modifierSubtract": { "enabled": true, "keys": { "windows": "ctrlKey", "mac": "metaKey", "linux": "ctrlKey" }, "
|
|
11
|
-
const edgeDeletion = { "enabled": true, "
|
|
12
|
-
const markers = { "deleteMarker": true, "infoMarker": true, "menuMarker": true, "coordsTitle": true, "zIndexOffset": 0, "markerIcon": { "styleClasses": ["polygon-marker"], "zIndexOffset": null }, "holeIcon": { "styleClasses": ["polygon-marker", "hole"], "zIndexOffset": null }, "markerInfoIcon": { "position": 3, "showArea": true, "showPerimeter": true, "useMetrics": true, "usePerimeterMinValue": false, "areaLabel": "Area", "perimeterLabel": "Perimeter", "values": { "min": { "metric": "50", "imperial": "100" }, "unknown": { "metric": "-", "imperial": "-" } }, "units": { "unknownUnit": "", "metric": { "onlyMetrics": true, "perimeter": { "m": "m", "km": "km" }, "area": { "m2": "m²", "km2": "km²", "daa": "daa", "ha": "ha" } }, "imperial": { "perimeter": { "feet": "ft", "yards": "yd", "miles": "mi" }, "area": { "feet2": "ft²", "yards2": "yd²", "acres": "ac", "miles2": "mi²" } } }, "styleClasses": ["polygon-marker", "info"], "zIndexOffset": 1e4 }, "markerMenuIcon": { "position": 7, "styleClasses": ["polygon-marker", "menu"], "zIndexOffset": 1e4 }, "markerDeleteIcon": { "position": 5, "styleClasses": ["polygon-marker", "delete"], "zIndexOffset": 1e4 }, "visualOptimization": { "sharpAngleThreshold": 30, "thresholdBoundingBox": 0.05, "thresholdDistance": 0.05, "useDistance": true, "useBoundingBox": false, "useAngles": false } };
|
|
13
|
-
const polyLineOptions = { "
|
|
14
|
-
const subtractLineOptions = { "
|
|
15
|
-
const polygonOptions = { "smoothFactor": 0.3, "
|
|
16
|
-
const holeOptions = { "
|
|
10
|
+
const dragPolygons = { "realTimeUpdate": false, "showDragHandle": false, "opacity": 0.7, "dragCursor": "move", "hoverCursor": "grab", "markerBehavior": "hide", "markerAnimationDuration": 200, "autoMergeOnIntersect": true, "autoHoleOnContained": false, "dragInteractionBehavior": "auto", "modifierSubtract": { "enabled": true, "keys": { "windows": "ctrlKey", "mac": "metaKey", "linux": "ctrlKey" }, "hideMarkersOnDrag": true } };
|
|
11
|
+
const edgeDeletion = { "enabled": true, "keys": { "windows": "ctrlKey", "mac": "metaKey", "linux": "ctrlKey" }, "confirmDeletion": false, "minVertices": 3 };
|
|
12
|
+
const markers = { "deleteMarker": true, "infoMarker": true, "menuMarker": true, "coordsTitle": true, "zIndexOffset": 0, "markerIcon": { "styleClasses": ["polygon-marker"], "zIndexOffset": null }, "holeIcon": { "styleClasses": ["polygon-marker", "hole"], "zIndexOffset": null }, "markerInfoIcon": { "position": 3, "showArea": true, "showPerimeter": true, "useMetrics": true, "usePerimeterMinValue": false, "areaLabel": "Area", "perimeterLabel": "Perimeter", "values": { "min": { "metric": "50", "imperial": "100" }, "unknown": { "metric": "-", "imperial": "-" } }, "units": { "unknownUnit": "", "metric": { "onlyMetrics": true, "perimeter": { "m": "m", "km": "km" }, "area": { "m2": "m²", "km2": "km²", "daa": "daa", "ha": "ha" } }, "imperial": { "perimeter": { "feet": "ft", "yards": "yd", "miles": "mi" }, "area": { "feet2": "ft²", "yards2": "yd²", "acres": "ac", "miles2": "mi²" } } }, "styleClasses": ["polygon-marker", "info"], "zIndexOffset": 1e4 }, "markerMenuIcon": { "position": 7, "styleClasses": ["polygon-marker", "menu"], "zIndexOffset": 1e4 }, "markerDeleteIcon": { "position": 5, "styleClasses": ["polygon-marker", "delete"], "zIndexOffset": 1e4 }, "holeMarkers": { "menuMarker": false, "deleteMarker": true, "infoMarker": false }, "visualOptimization": { "sharpAngleThreshold": 30, "thresholdBoundingBox": 0.05, "thresholdDistance": 0.05, "useDistance": true, "useBoundingBox": false, "useAngles": false } };
|
|
13
|
+
const polyLineOptions = { "opacity": 1, "smoothFactor": 0, "noClip": true, "clickable": false, "weight": 2 };
|
|
14
|
+
const subtractLineOptions = { "opacity": 1, "smoothFactor": 0, "noClip": true, "clickable": false, "weight": 2 };
|
|
15
|
+
const polygonOptions = { "smoothFactor": 0.3, "noClip": true };
|
|
16
|
+
const holeOptions = { "weight": 2, "opacity": 1, "fillOpacity": 0.5 };
|
|
17
17
|
const polygonCreation = { "method": "concaveman", "simplification": { "mode": "simple", "tolerance": 1e-5, "highQuality": false } };
|
|
18
18
|
const simplification = { "simplifyTolerance": { "tolerance": 1e-4, "highQuality": false, "mutate": false }, "dynamicMode": { "fractionGuard": 0.9, "multipiler": 2 } };
|
|
19
19
|
const menuOperations = { "simplify": { "processHoles": true }, "doubleElbows": { "processHoles": true }, "bbox": { "processHoles": true } };
|
|
20
20
|
const boundingBox = { "addMidPointMarkers": true };
|
|
21
21
|
const bezier$1 = { "resolution": 1e4, "sharpness": 0.75 };
|
|
22
|
+
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" } } };
|
|
22
23
|
const defaultConfig = {
|
|
23
24
|
touchSupport,
|
|
24
25
|
mergePolygons,
|
|
@@ -35,7 +36,8 @@ const defaultConfig = {
|
|
|
35
36
|
simplification,
|
|
36
37
|
menuOperations,
|
|
37
38
|
boundingBox,
|
|
38
|
-
bezier: bezier$1
|
|
39
|
+
bezier: bezier$1,
|
|
40
|
+
colors
|
|
39
41
|
};
|
|
40
42
|
var DrawMode = /* @__PURE__ */ ((DrawMode2) => {
|
|
41
43
|
DrawMode2[DrawMode2["Off"] = 0] = "Off";
|
|
@@ -190,7 +192,7 @@ function degreesToRadians(degrees2) {
|
|
|
190
192
|
function isNumber(num) {
|
|
191
193
|
return !isNaN(num) && num !== null && !Array.isArray(num);
|
|
192
194
|
}
|
|
193
|
-
function isObject(input) {
|
|
195
|
+
function isObject$1(input) {
|
|
194
196
|
return input !== null && typeof input === "object" && !Array.isArray(input);
|
|
195
197
|
}
|
|
196
198
|
function getCoord(coord) {
|
|
@@ -1498,6 +1500,161 @@ function coordsToLine(coords, properties) {
|
|
|
1498
1500
|
}
|
|
1499
1501
|
return lineString(coords[0], properties);
|
|
1500
1502
|
}
|
|
1503
|
+
var __defProp$1 = Object.defineProperty;
|
|
1504
|
+
var __name = (target, value) => __defProp$1(target, "name", { value, configurable: true });
|
|
1505
|
+
var _GeojsonEquality = class _GeojsonEquality2 {
|
|
1506
|
+
constructor(opts) {
|
|
1507
|
+
this.direction = false;
|
|
1508
|
+
this.compareProperties = true;
|
|
1509
|
+
var _a2, _b2, _c;
|
|
1510
|
+
this.precision = 10 ** -((_a2 = opts == null ? void 0 : opts.precision) != null ? _a2 : 17);
|
|
1511
|
+
this.direction = (_b2 = opts == null ? void 0 : opts.direction) != null ? _b2 : false;
|
|
1512
|
+
this.compareProperties = (_c = opts == null ? void 0 : opts.compareProperties) != null ? _c : true;
|
|
1513
|
+
}
|
|
1514
|
+
compare(g1, g2) {
|
|
1515
|
+
if (g1.type !== g2.type) {
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
if (!sameLength(g1, g2)) {
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
switch (g1.type) {
|
|
1522
|
+
case "Point":
|
|
1523
|
+
return this.compareCoord(g1.coordinates, g2.coordinates);
|
|
1524
|
+
case "LineString":
|
|
1525
|
+
return this.compareLine(g1.coordinates, g2.coordinates);
|
|
1526
|
+
case "Polygon":
|
|
1527
|
+
return this.comparePolygon(g1, g2);
|
|
1528
|
+
case "GeometryCollection":
|
|
1529
|
+
return this.compareGeometryCollection(g1, g2);
|
|
1530
|
+
case "Feature":
|
|
1531
|
+
return this.compareFeature(g1, g2);
|
|
1532
|
+
case "FeatureCollection":
|
|
1533
|
+
return this.compareFeatureCollection(g1, g2);
|
|
1534
|
+
default:
|
|
1535
|
+
if (g1.type.startsWith("Multi")) {
|
|
1536
|
+
const g1s = explode$1(g1);
|
|
1537
|
+
const g2s = explode$1(
|
|
1538
|
+
g2
|
|
1539
|
+
);
|
|
1540
|
+
return g1s.every(
|
|
1541
|
+
(g1part) => g2s.some((g2part) => this.compare(g1part, g2part))
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
return false;
|
|
1546
|
+
}
|
|
1547
|
+
compareCoord(c1, c2) {
|
|
1548
|
+
return c1.length === c2.length && c1.every((c, i) => Math.abs(c - c2[i]) < this.precision);
|
|
1549
|
+
}
|
|
1550
|
+
compareLine(path1, path2, ind = 0, isPoly = false) {
|
|
1551
|
+
if (!sameLength(path1, path2)) {
|
|
1552
|
+
return false;
|
|
1553
|
+
}
|
|
1554
|
+
const p1 = path1;
|
|
1555
|
+
let p2 = path2;
|
|
1556
|
+
if (isPoly && !this.compareCoord(p1[0], p2[0])) {
|
|
1557
|
+
const startIndex = this.fixStartIndex(p2, p1);
|
|
1558
|
+
if (!startIndex) {
|
|
1559
|
+
return false;
|
|
1560
|
+
} else {
|
|
1561
|
+
p2 = startIndex;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
const sameDirection = this.compareCoord(p1[ind], p2[ind]);
|
|
1565
|
+
if (this.direction || sameDirection) {
|
|
1566
|
+
return this.comparePath(p1, p2);
|
|
1567
|
+
} else {
|
|
1568
|
+
if (this.compareCoord(p1[ind], p2[p2.length - (1 + ind)])) {
|
|
1569
|
+
return this.comparePath(p1.slice().reverse(), p2);
|
|
1570
|
+
}
|
|
1571
|
+
return false;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
fixStartIndex(sourcePath, targetPath) {
|
|
1575
|
+
let correctPath, ind = -1;
|
|
1576
|
+
for (let i = 0; i < sourcePath.length; i++) {
|
|
1577
|
+
if (this.compareCoord(sourcePath[i], targetPath[0])) {
|
|
1578
|
+
ind = i;
|
|
1579
|
+
break;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
if (ind >= 0) {
|
|
1583
|
+
correctPath = [].concat(
|
|
1584
|
+
sourcePath.slice(ind, sourcePath.length),
|
|
1585
|
+
sourcePath.slice(1, ind + 1)
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
return correctPath;
|
|
1589
|
+
}
|
|
1590
|
+
comparePath(p1, p2) {
|
|
1591
|
+
return p1.every((c, i) => this.compareCoord(c, p2[i]));
|
|
1592
|
+
}
|
|
1593
|
+
comparePolygon(g1, g2) {
|
|
1594
|
+
if (this.compareLine(g1.coordinates[0], g2.coordinates[0], 1, true)) {
|
|
1595
|
+
const holes1 = g1.coordinates.slice(1, g1.coordinates.length);
|
|
1596
|
+
const holes2 = g2.coordinates.slice(1, g2.coordinates.length);
|
|
1597
|
+
return holes1.every(
|
|
1598
|
+
(h1) => holes2.some((h2) => this.compareLine(h1, h2, 1, true))
|
|
1599
|
+
);
|
|
1600
|
+
}
|
|
1601
|
+
return false;
|
|
1602
|
+
}
|
|
1603
|
+
compareGeometryCollection(g1, g2) {
|
|
1604
|
+
return sameLength(g1.geometries, g2.geometries) && this.compareBBox(g1, g2) && g1.geometries.every((g, i) => this.compare(g, g2.geometries[i]));
|
|
1605
|
+
}
|
|
1606
|
+
compareFeature(g1, g2) {
|
|
1607
|
+
return g1.id === g2.id && (this.compareProperties ? equal(g1.properties, g2.properties) : true) && this.compareBBox(g1, g2) && this.compare(g1.geometry, g2.geometry);
|
|
1608
|
+
}
|
|
1609
|
+
compareFeatureCollection(g1, g2) {
|
|
1610
|
+
return sameLength(g1.features, g2.features) && this.compareBBox(g1, g2) && g1.features.every((f, i) => this.compare(f, g2.features[i]));
|
|
1611
|
+
}
|
|
1612
|
+
compareBBox(g1, g2) {
|
|
1613
|
+
return Boolean(!g1.bbox && !g2.bbox) || (g1.bbox && g2.bbox ? this.compareCoord(g1.bbox, g2.bbox) : false);
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
__name(_GeojsonEquality, "GeojsonEquality");
|
|
1617
|
+
var GeojsonEquality = _GeojsonEquality;
|
|
1618
|
+
function sameLength(g1, g2) {
|
|
1619
|
+
return g1.coordinates ? g1.coordinates.length === g2.coordinates.length : g1.length === g2.length;
|
|
1620
|
+
}
|
|
1621
|
+
__name(sameLength, "sameLength");
|
|
1622
|
+
function explode$1(g) {
|
|
1623
|
+
return g.coordinates.map((part) => ({
|
|
1624
|
+
type: g.type.replace("Multi", ""),
|
|
1625
|
+
coordinates: part
|
|
1626
|
+
}));
|
|
1627
|
+
}
|
|
1628
|
+
__name(explode$1, "explode");
|
|
1629
|
+
function geojsonEquality(g1, g2, opts) {
|
|
1630
|
+
const eq = new GeojsonEquality(opts);
|
|
1631
|
+
return eq.compare(g1, g2);
|
|
1632
|
+
}
|
|
1633
|
+
__name(geojsonEquality, "geojsonEquality");
|
|
1634
|
+
function equal(object1, object2) {
|
|
1635
|
+
if (object1 === null && object2 === null) {
|
|
1636
|
+
return true;
|
|
1637
|
+
}
|
|
1638
|
+
if (object1 === null || object2 === null) {
|
|
1639
|
+
return false;
|
|
1640
|
+
}
|
|
1641
|
+
const objKeys1 = Object.keys(object1);
|
|
1642
|
+
const objKeys2 = Object.keys(object2);
|
|
1643
|
+
if (objKeys1.length !== objKeys2.length) return false;
|
|
1644
|
+
for (var key of objKeys1) {
|
|
1645
|
+
const value1 = object1[key];
|
|
1646
|
+
const value2 = object2[key];
|
|
1647
|
+
const isObjects = isObject(value1) && isObject(value2);
|
|
1648
|
+
if (isObjects && !equal(value1, value2) || !isObjects && value1 !== value2) {
|
|
1649
|
+
return false;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
return true;
|
|
1653
|
+
}
|
|
1654
|
+
__name(equal, "equal");
|
|
1655
|
+
var isObject = /* @__PURE__ */ __name((object) => {
|
|
1656
|
+
return object != null && typeof object === "object";
|
|
1657
|
+
}, "isObject");
|
|
1501
1658
|
function cleanCoords(geojson, options = {}) {
|
|
1502
1659
|
var mutate = typeof options === "object" ? options.mutate : options;
|
|
1503
1660
|
if (!geojson) throw new Error("geojson is required");
|
|
@@ -1611,6 +1768,19 @@ function isPointOnLineSegment(start, end, point2) {
|
|
|
1611
1768
|
return dxl > 0 ? startX <= x && x <= endX : endX <= x && x <= startX;
|
|
1612
1769
|
else return dyl > 0 ? startY <= y && y <= endY : endY <= y && y <= startY;
|
|
1613
1770
|
}
|
|
1771
|
+
function booleanEqual(feature1, feature2, options = {}) {
|
|
1772
|
+
let precision2 = options.precision;
|
|
1773
|
+
precision2 = precision2 === void 0 || precision2 === null || isNaN(precision2) ? 6 : precision2;
|
|
1774
|
+
if (typeof precision2 !== "number" || !(precision2 >= 0)) {
|
|
1775
|
+
throw new Error("precision must be a positive number");
|
|
1776
|
+
}
|
|
1777
|
+
const type1 = getGeom(feature1).type;
|
|
1778
|
+
const type2 = getGeom(feature2).type;
|
|
1779
|
+
if (type1 !== type2) return false;
|
|
1780
|
+
return geojsonEquality(cleanCoords(feature1), cleanCoords(feature2), {
|
|
1781
|
+
precision: precision2
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1614
1784
|
function quickselect(arr, k, left, right, compare2) {
|
|
1615
1785
|
quickselectStep(arr, k, left || 0, right || arr.length - 1, compare2 || defaultCompare$1);
|
|
1616
1786
|
}
|
|
@@ -15011,7 +15181,7 @@ function simplify(points, tolerance, highestQuality) {
|
|
|
15011
15181
|
function simplify2(geojson, options = {}) {
|
|
15012
15182
|
var _a2, _b2, _c;
|
|
15013
15183
|
options = options != null ? options : {};
|
|
15014
|
-
if (!isObject(options)) throw new Error("options is invalid");
|
|
15184
|
+
if (!isObject$1(options)) throw new Error("options is invalid");
|
|
15015
15185
|
const tolerance = (_a2 = options.tolerance) != null ? _a2 : 1;
|
|
15016
15186
|
const highQuality = (_b2 = options.highQuality) != null ? _b2 : false;
|
|
15017
15187
|
const mutate = (_c = options.mutate) != null ? _c : false;
|
|
@@ -15878,22 +16048,16 @@ class TurfHelper {
|
|
|
15878
16048
|
} catch (error) {
|
|
15879
16049
|
}
|
|
15880
16050
|
try {
|
|
15881
|
-
const
|
|
15882
|
-
const
|
|
15883
|
-
for (const
|
|
15884
|
-
|
|
15885
|
-
|
|
15886
|
-
if (booleanPointInPolygon(point$1, polygon2)) {
|
|
15887
|
-
return true;
|
|
15888
|
-
}
|
|
16051
|
+
const points1 = explode(polygon2);
|
|
16052
|
+
const points2 = explode(latlngs);
|
|
16053
|
+
for (const point2 of points2.features) {
|
|
16054
|
+
if (booleanPointInPolygon(point2, polygon2)) {
|
|
16055
|
+
return true;
|
|
15889
16056
|
}
|
|
15890
16057
|
}
|
|
15891
|
-
for (const
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
if (booleanPointInPolygon(point$1, latlngs)) {
|
|
15895
|
-
return true;
|
|
15896
|
-
}
|
|
16058
|
+
for (const point2 of points1.features) {
|
|
16059
|
+
if (booleanPointInPolygon(point2, latlngs)) {
|
|
16060
|
+
return true;
|
|
15897
16061
|
}
|
|
15898
16062
|
}
|
|
15899
16063
|
} catch (error) {
|
|
@@ -15984,12 +16148,47 @@ class TurfHelper {
|
|
|
15984
16148
|
return true;
|
|
15985
16149
|
}
|
|
15986
16150
|
}
|
|
16151
|
+
/**
|
|
16152
|
+
* Normalize various point-like inputs into a GeoJSON Feature<Point>.
|
|
16153
|
+
* Supports GeoJSON Feature<Point>, Turf Position [lng, lat], and Leaflet LatLngLiteral.
|
|
16154
|
+
*/
|
|
16155
|
+
toPointFeature(point$1) {
|
|
16156
|
+
var _a2, _b2;
|
|
16157
|
+
if ((point$1 == null ? void 0 : point$1.type) === "Feature" && ((_a2 = point$1.geometry) == null ? void 0 : _a2.type) === "Point") {
|
|
16158
|
+
return point$1;
|
|
16159
|
+
}
|
|
16160
|
+
if (Array.isArray(point$1) && point$1.length >= 2 && typeof point$1[0] === "number" && typeof point$1[1] === "number") {
|
|
16161
|
+
return point(point$1);
|
|
16162
|
+
}
|
|
16163
|
+
if (typeof (point$1 == null ? void 0 : point$1.lat) === "number" && typeof (point$1 == null ? void 0 : point$1.lng) === "number") {
|
|
16164
|
+
const p = point$1;
|
|
16165
|
+
return point([p.lng, p.lat]);
|
|
16166
|
+
}
|
|
16167
|
+
if (((_b2 = point$1 == null ? void 0 : point$1.geometry) == null ? void 0 : _b2.coordinates) && Array.isArray(point$1.geometry.coordinates)) {
|
|
16168
|
+
return point(point$1.geometry.coordinates);
|
|
16169
|
+
}
|
|
16170
|
+
throw new Error("Unsupported point format provided to toPointFeature");
|
|
16171
|
+
}
|
|
16172
|
+
/**
|
|
16173
|
+
* Check if a point lies within a polygon.
|
|
16174
|
+
* Accepts Feature<Point>, Turf Position [lng, lat], or Leaflet LatLngLiteral.
|
|
16175
|
+
* This normalization prevents noisy console warnings in tests.
|
|
16176
|
+
*/
|
|
16177
|
+
isPointInsidePolygon(point2, polygon2) {
|
|
16178
|
+
try {
|
|
16179
|
+
const pointFeature = this.toPointFeature(point2);
|
|
16180
|
+
return booleanPointInPolygon(pointFeature, polygon2);
|
|
16181
|
+
} catch (error) {
|
|
16182
|
+
return false;
|
|
16183
|
+
}
|
|
16184
|
+
}
|
|
15987
16185
|
/**
|
|
15988
16186
|
* Checks if two polygons are equal.
|
|
15989
16187
|
* @param polygon1 First polygon.
|
|
15990
16188
|
* @param polygon2 Second polygon.
|
|
15991
16189
|
*/
|
|
15992
16190
|
equalPolygons(polygon1, polygon2) {
|
|
16191
|
+
return booleanEqual(polygon1, polygon2);
|
|
15993
16192
|
}
|
|
15994
16193
|
convertToBoundingBoxPolygon(polygon2) {
|
|
15995
16194
|
const bbox$1 = bbox(polygon2.geometry);
|
|
@@ -16000,37 +16199,31 @@ class TurfHelper {
|
|
|
16000
16199
|
const multi = multiPolygon([poly.geometry.coordinates]);
|
|
16001
16200
|
return multi;
|
|
16002
16201
|
}
|
|
16003
|
-
injectPointToPolygon(polygon2, point2) {
|
|
16202
|
+
injectPointToPolygon(polygon2, point2, ringIndex) {
|
|
16004
16203
|
const newPoly = JSON.parse(JSON.stringify(polygon2));
|
|
16204
|
+
let targetRing;
|
|
16005
16205
|
if (newPoly.geometry.type === "MultiPolygon") {
|
|
16006
|
-
|
|
16007
|
-
let minDistance = Infinity;
|
|
16008
|
-
let insertIndex = 0;
|
|
16009
|
-
for (let i = 0; i < coordinates.length - 1; i++) {
|
|
16010
|
-
const edgeStart = coordinates[i];
|
|
16011
|
-
const edgeEnd = coordinates[i + 1];
|
|
16012
|
-
const distance2 = this.distanceToLineSegment(point2, edgeStart, edgeEnd);
|
|
16013
|
-
if (distance2 < minDistance) {
|
|
16014
|
-
minDistance = distance2;
|
|
16015
|
-
insertIndex = i + 1;
|
|
16016
|
-
}
|
|
16017
|
-
}
|
|
16018
|
-
coordinates.splice(insertIndex, 0, point2);
|
|
16206
|
+
targetRing = newPoly.geometry.coordinates[0][ringIndex];
|
|
16019
16207
|
} else if (newPoly.geometry.type === "Polygon") {
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16208
|
+
targetRing = newPoly.geometry.coordinates[ringIndex];
|
|
16209
|
+
} else {
|
|
16210
|
+
return newPoly;
|
|
16211
|
+
}
|
|
16212
|
+
if (!targetRing) {
|
|
16213
|
+
return newPoly;
|
|
16214
|
+
}
|
|
16215
|
+
let minDistance = Infinity;
|
|
16216
|
+
let insertIndex = 0;
|
|
16217
|
+
for (let i = 0; i < targetRing.length - 1; i++) {
|
|
16218
|
+
const edgeStart = targetRing[i];
|
|
16219
|
+
const edgeEnd = targetRing[i + 1];
|
|
16220
|
+
const distance2 = this.distanceToLineSegment(point2, edgeStart, edgeEnd);
|
|
16221
|
+
if (distance2 < minDistance) {
|
|
16222
|
+
minDistance = distance2;
|
|
16223
|
+
insertIndex = i + 1;
|
|
16031
16224
|
}
|
|
16032
|
-
coordinates.splice(insertIndex, 0, point2);
|
|
16033
16225
|
}
|
|
16226
|
+
targetRing.splice(insertIndex, 0, point2);
|
|
16034
16227
|
return newPoly;
|
|
16035
16228
|
}
|
|
16036
16229
|
distanceToLineSegment(point2, lineStart, lineEnd) {
|
|
@@ -17285,11 +17478,10 @@ class EventManager {
|
|
|
17285
17478
|
* @param callback - The callback to execute when the event is emitted.
|
|
17286
17479
|
*/
|
|
17287
17480
|
on(event, callback) {
|
|
17288
|
-
var _a2;
|
|
17289
17481
|
if (!this.eventListeners.has(event)) {
|
|
17290
17482
|
this.eventListeners.set(event, []);
|
|
17291
17483
|
}
|
|
17292
|
-
|
|
17484
|
+
this.eventListeners.get(event).push(callback);
|
|
17293
17485
|
}
|
|
17294
17486
|
/**
|
|
17295
17487
|
* Unregister an event listener.
|
|
@@ -17297,13 +17489,11 @@ class EventManager {
|
|
|
17297
17489
|
* @param callback - The specific callback to remove.
|
|
17298
17490
|
*/
|
|
17299
17491
|
off(event, callback) {
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
17304
|
-
|
|
17305
|
-
listeners.splice(index, 1);
|
|
17306
|
-
}
|
|
17492
|
+
const listeners = this.eventListeners.get(event);
|
|
17493
|
+
if (listeners) {
|
|
17494
|
+
const index = listeners.indexOf(callback);
|
|
17495
|
+
if (index > -1) {
|
|
17496
|
+
listeners.splice(index, 1);
|
|
17307
17497
|
}
|
|
17308
17498
|
}
|
|
17309
17499
|
}
|
|
@@ -17315,7 +17505,9 @@ class EventManager {
|
|
|
17315
17505
|
emit(event, data) {
|
|
17316
17506
|
var _a2;
|
|
17317
17507
|
if (this.eventListeners.has(event)) {
|
|
17318
|
-
(_a2 = this.eventListeners.get(event)) == null ? void 0 : _a2.forEach((callback) =>
|
|
17508
|
+
(_a2 = this.eventListeners.get(event)) == null ? void 0 : _a2.forEach((callback) => {
|
|
17509
|
+
callback(data);
|
|
17510
|
+
});
|
|
17319
17511
|
}
|
|
17320
17512
|
}
|
|
17321
17513
|
}
|
|
@@ -17514,6 +17706,7 @@ class PolygonDrawManager {
|
|
|
17514
17706
|
// Point-to-Point drawing state
|
|
17515
17707
|
__publicField(this, "p2pMarkers", []);
|
|
17516
17708
|
__publicField(this, "isModifierKeyHeld", false);
|
|
17709
|
+
__publicField(this, "markerModifierHandlers", /* @__PURE__ */ new WeakMap());
|
|
17517
17710
|
this.turfHelper = dependencies.turfHelper;
|
|
17518
17711
|
this.map = dependencies.map;
|
|
17519
17712
|
this.config = dependencies.config;
|
|
@@ -17543,7 +17736,7 @@ class PolygonDrawManager {
|
|
|
17543
17736
|
if (!tracerGeoJSON || !tracerGeoJSON.geometry || !tracerGeoJSON.geometry.coordinates || tracerGeoJSON.geometry.coordinates.length < 3) {
|
|
17544
17737
|
return {
|
|
17545
17738
|
success: false,
|
|
17546
|
-
error: "Not enough points to form a valid polygon"
|
|
17739
|
+
error: "Not enough points to form a valid polygon. Event: " + JSON.stringify(event)
|
|
17547
17740
|
};
|
|
17548
17741
|
}
|
|
17549
17742
|
let geoPos;
|
|
@@ -17552,13 +17745,13 @@ class PolygonDrawManager {
|
|
|
17552
17745
|
} catch (error) {
|
|
17553
17746
|
return {
|
|
17554
17747
|
success: false,
|
|
17555
|
-
error: error instanceof Error ? error.message : "Failed to create polygon from trace"
|
|
17748
|
+
error: (error instanceof Error ? error.message : "Failed to create polygon from trace") + ". Event: " + JSON.stringify(event)
|
|
17556
17749
|
};
|
|
17557
17750
|
}
|
|
17558
17751
|
if (!geoPos || !geoPos.geometry || !geoPos.geometry.coordinates || geoPos.geometry.coordinates.length === 0) {
|
|
17559
17752
|
return {
|
|
17560
17753
|
success: false,
|
|
17561
|
-
error: "Invalid polygon created from trace"
|
|
17754
|
+
error: "Invalid polygon created from trace. Event: " + JSON.stringify(event)
|
|
17562
17755
|
};
|
|
17563
17756
|
}
|
|
17564
17757
|
this.eventManager.emit("polydraw:polygon:created", {
|
|
@@ -17624,8 +17817,8 @@ class PolygonDrawManager {
|
|
|
17624
17817
|
if (this.p2pMarkers.length >= 3) {
|
|
17625
17818
|
const element = pointMarker.getElement();
|
|
17626
17819
|
if (element) {
|
|
17627
|
-
element.style.backgroundColor =
|
|
17628
|
-
element.style.borderColor =
|
|
17820
|
+
element.style.backgroundColor = this.config.colors.p2p.closingMarker;
|
|
17821
|
+
element.style.borderColor = this.config.colors.p2p.closingMarker;
|
|
17629
17822
|
element.style.cursor = "pointer";
|
|
17630
17823
|
element.title = "Click to close polygon";
|
|
17631
17824
|
}
|
|
@@ -17749,7 +17942,7 @@ class PolygonDrawManager {
|
|
|
17749
17942
|
if (this.p2pMarkers.length >= 2) {
|
|
17750
17943
|
try {
|
|
17751
17944
|
this.tracer.setStyle({
|
|
17752
|
-
color: this.config.
|
|
17945
|
+
color: this.config.colors.polyline,
|
|
17753
17946
|
dashArray: "5, 5"
|
|
17754
17947
|
});
|
|
17755
17948
|
} catch (error) {
|
|
@@ -17819,8 +18012,8 @@ class PolygonDrawManager {
|
|
|
17819
18012
|
if (this.p2pMarkers.length >= 3) {
|
|
17820
18013
|
const element2 = firstMarker.getElement();
|
|
17821
18014
|
if (element2) {
|
|
17822
|
-
element2.style.backgroundColor =
|
|
17823
|
-
element2.style.borderColor =
|
|
18015
|
+
element2.style.backgroundColor = this.config.colors.p2p.closingMarker;
|
|
18016
|
+
element2.style.borderColor = this.config.colors.p2p.closingMarker;
|
|
17824
18017
|
element2.style.cursor = "pointer";
|
|
17825
18018
|
element2.title = "Click to close polygon";
|
|
17826
18019
|
}
|
|
@@ -17871,7 +18064,7 @@ class PolygonDrawManager {
|
|
|
17871
18064
|
}
|
|
17872
18065
|
}
|
|
17873
18066
|
};
|
|
17874
|
-
marker
|
|
18067
|
+
this.markerModifierHandlers.set(marker, checkModifierAndUpdate);
|
|
17875
18068
|
document.addEventListener("keydown", checkModifierAndUpdate);
|
|
17876
18069
|
document.addEventListener("keyup", checkModifierAndUpdate);
|
|
17877
18070
|
element.addEventListener("mousemove", checkModifierAndUpdate);
|
|
@@ -17882,12 +18075,12 @@ class PolygonDrawManager {
|
|
|
17882
18075
|
container.style.cursor = "";
|
|
17883
18076
|
} catch (error) {
|
|
17884
18077
|
}
|
|
17885
|
-
const handler = marker
|
|
18078
|
+
const handler = this.markerModifierHandlers.get(marker);
|
|
17886
18079
|
if (handler) {
|
|
17887
18080
|
document.removeEventListener("keydown", handler);
|
|
17888
18081
|
document.removeEventListener("keyup", handler);
|
|
17889
18082
|
element.removeEventListener("mousemove", handler);
|
|
17890
|
-
delete
|
|
18083
|
+
this.markerModifierHandlers.delete(marker);
|
|
17891
18084
|
}
|
|
17892
18085
|
}
|
|
17893
18086
|
}
|
|
@@ -17938,7 +18131,7 @@ class PolygonGeometryManager {
|
|
|
17938
18131
|
geometry: { type: "Point", coordinates: coord },
|
|
17939
18132
|
properties: {}
|
|
17940
18133
|
};
|
|
17941
|
-
if (this.turfHelper.
|
|
18134
|
+
if (this.turfHelper.isPointInsidePolygon(point2, polygon1)) {
|
|
17942
18135
|
return true;
|
|
17943
18136
|
}
|
|
17944
18137
|
}
|
|
@@ -17950,7 +18143,7 @@ class PolygonGeometryManager {
|
|
|
17950
18143
|
geometry: { type: "Point", coordinates: coord },
|
|
17951
18144
|
properties: {}
|
|
17952
18145
|
};
|
|
17953
|
-
if (this.turfHelper.
|
|
18146
|
+
if (this.turfHelper.isPointInsidePolygon(point2, polygon2)) {
|
|
17954
18147
|
return true;
|
|
17955
18148
|
}
|
|
17956
18149
|
}
|
|
@@ -17966,19 +18159,8 @@ class PolygonGeometryManager {
|
|
|
17966
18159
|
try {
|
|
17967
18160
|
let result = newPolygon;
|
|
17968
18161
|
for (const polygon2 of polygons) {
|
|
17969
|
-
const
|
|
17970
|
-
|
|
17971
|
-
const donutPolygon = this.createDonutPolygon(result, polygon2);
|
|
17972
|
-
if (donutPolygon) {
|
|
17973
|
-
result = donutPolygon;
|
|
17974
|
-
} else {
|
|
17975
|
-
const union3 = this.turfHelper.union(result, polygon2);
|
|
17976
|
-
result = union3;
|
|
17977
|
-
}
|
|
17978
|
-
} else {
|
|
17979
|
-
const union3 = this.turfHelper.union(result, polygon2);
|
|
17980
|
-
result = union3;
|
|
17981
|
-
}
|
|
18162
|
+
const union3 = this.turfHelper.union(result, polygon2);
|
|
18163
|
+
result = union3;
|
|
17982
18164
|
}
|
|
17983
18165
|
return {
|
|
17984
18166
|
success: true,
|
|
@@ -18289,93 +18471,6 @@ class PolygonGeometryManager {
|
|
|
18289
18471
|
return null;
|
|
18290
18472
|
}
|
|
18291
18473
|
}
|
|
18292
|
-
/**
|
|
18293
|
-
* Determine if two polygons should create a donut instead of a regular union
|
|
18294
|
-
*/
|
|
18295
|
-
shouldCreateDonutPolygon(polygon1, polygon2) {
|
|
18296
|
-
try {
|
|
18297
|
-
return false;
|
|
18298
|
-
} catch (error) {
|
|
18299
|
-
console.warn("Error in shouldCreateDonutPolygon:", error.message);
|
|
18300
|
-
return false;
|
|
18301
|
-
}
|
|
18302
|
-
}
|
|
18303
|
-
/**
|
|
18304
|
-
* Create a donut polygon from two intersecting polygons
|
|
18305
|
-
*/
|
|
18306
|
-
createDonutPolygon(polygon1, polygon2) {
|
|
18307
|
-
try {
|
|
18308
|
-
const area1 = this.turfHelper.getPolygonArea(polygon1);
|
|
18309
|
-
const area2 = this.turfHelper.getPolygonArea(polygon2);
|
|
18310
|
-
let outerPolygon;
|
|
18311
|
-
let innerPolygon;
|
|
18312
|
-
if (area1 > area2) {
|
|
18313
|
-
outerPolygon = polygon1;
|
|
18314
|
-
innerPolygon = polygon2;
|
|
18315
|
-
} else {
|
|
18316
|
-
outerPolygon = polygon2;
|
|
18317
|
-
innerPolygon = polygon1;
|
|
18318
|
-
}
|
|
18319
|
-
const innerWithinOuter = this.turfHelper.isPolygonCompletelyWithin(
|
|
18320
|
-
innerPolygon,
|
|
18321
|
-
outerPolygon
|
|
18322
|
-
);
|
|
18323
|
-
if (innerWithinOuter) {
|
|
18324
|
-
return this.createDonutFromContainment(outerPolygon, innerPolygon);
|
|
18325
|
-
} else {
|
|
18326
|
-
return this.createDonutFromIntersection(outerPolygon, innerPolygon);
|
|
18327
|
-
}
|
|
18328
|
-
} catch (error) {
|
|
18329
|
-
console.warn("Error in createDonutPolygon:", error.message);
|
|
18330
|
-
return null;
|
|
18331
|
-
}
|
|
18332
|
-
}
|
|
18333
|
-
/**
|
|
18334
|
-
* Create donut when one polygon is completely within another
|
|
18335
|
-
*/
|
|
18336
|
-
createDonutFromContainment(outerPolygon, innerPolygon) {
|
|
18337
|
-
try {
|
|
18338
|
-
const outerCoords = this.turfHelper.getCoords(outerPolygon);
|
|
18339
|
-
const innerCoords = this.turfHelper.getCoords(innerPolygon);
|
|
18340
|
-
const donutCoords = [
|
|
18341
|
-
outerCoords[0][0],
|
|
18342
|
-
// Outer ring
|
|
18343
|
-
innerCoords[0][0]
|
|
18344
|
-
// Inner ring as hole
|
|
18345
|
-
];
|
|
18346
|
-
return {
|
|
18347
|
-
type: "Feature",
|
|
18348
|
-
geometry: {
|
|
18349
|
-
type: "Polygon",
|
|
18350
|
-
coordinates: donutCoords
|
|
18351
|
-
},
|
|
18352
|
-
properties: {}
|
|
18353
|
-
};
|
|
18354
|
-
} catch (error) {
|
|
18355
|
-
console.warn("Error in createDonutFromContainment:", error.message);
|
|
18356
|
-
return null;
|
|
18357
|
-
}
|
|
18358
|
-
}
|
|
18359
|
-
/**
|
|
18360
|
-
* Create donut from intersecting polygons (C-to-O scenario)
|
|
18361
|
-
*/
|
|
18362
|
-
createDonutFromIntersection(polygon1, polygon2) {
|
|
18363
|
-
try {
|
|
18364
|
-
const union3 = this.turfHelper.union(polygon1, polygon2);
|
|
18365
|
-
if (!union3) {
|
|
18366
|
-
return null;
|
|
18367
|
-
}
|
|
18368
|
-
const intersection3 = this.turfHelper.getIntersection(polygon1, polygon2);
|
|
18369
|
-
if (!intersection3) {
|
|
18370
|
-
return union3;
|
|
18371
|
-
}
|
|
18372
|
-
const donut = this.turfHelper.polygonDifference(union3, intersection3);
|
|
18373
|
-
return donut;
|
|
18374
|
-
} catch (error) {
|
|
18375
|
-
console.warn("Error in createDonutFromIntersection:", error.message);
|
|
18376
|
-
return null;
|
|
18377
|
-
}
|
|
18378
|
-
}
|
|
18379
18474
|
}
|
|
18380
18475
|
class IconFactory {
|
|
18381
18476
|
/**
|
|
@@ -18390,6 +18485,8 @@ class IconFactory {
|
|
|
18390
18485
|
}
|
|
18391
18486
|
class PolygonInteractionManager {
|
|
18392
18487
|
constructor(dependencies, featureGroupAccess) {
|
|
18488
|
+
__publicField(this, "markerFeatureGroupMap", /* @__PURE__ */ new WeakMap());
|
|
18489
|
+
__publicField(this, "markerModifierHandlers", /* @__PURE__ */ new WeakMap());
|
|
18393
18490
|
__publicField(this, "_activeMarker", null);
|
|
18394
18491
|
__publicField(this, "isDraggingMarker", false);
|
|
18395
18492
|
__publicField(this, "turfHelper");
|
|
@@ -18413,7 +18510,7 @@ class PolygonInteractionManager {
|
|
|
18413
18510
|
const polygon2 = this.currentDragPolygon;
|
|
18414
18511
|
const dragData = polygon2._polydrawDragData;
|
|
18415
18512
|
const eventToCheck = e.originalEvent && "metaKey" in e.originalEvent ? e.originalEvent : e;
|
|
18416
|
-
const currentModifierState = this.
|
|
18513
|
+
const currentModifierState = this.detectDragSubtractModifierKey(eventToCheck);
|
|
18417
18514
|
if (currentModifierState !== this.currentModifierDragMode) {
|
|
18418
18515
|
this.handleModifierToggleDuringDrag(eventToCheck);
|
|
18419
18516
|
}
|
|
@@ -18458,8 +18555,8 @@ class PolygonInteractionManager {
|
|
|
18458
18555
|
if (!this.isModifierKeyHeld) return;
|
|
18459
18556
|
const element = e.target;
|
|
18460
18557
|
if (element) {
|
|
18461
|
-
element.style.backgroundColor =
|
|
18462
|
-
element.style.borderColor =
|
|
18558
|
+
element.style.backgroundColor = this.config.colors.edgeDeletion.hover;
|
|
18559
|
+
element.style.borderColor = this.config.colors.edgeDeletion.hover;
|
|
18463
18560
|
element.classList.add("edge-deletion-hover");
|
|
18464
18561
|
}
|
|
18465
18562
|
});
|
|
@@ -18519,7 +18616,7 @@ class PolygonInteractionManager {
|
|
|
18519
18616
|
zIndexOffset: this.config.markers.markerIcon.zIndexOffset ?? this.config.markers.zIndexOffset
|
|
18520
18617
|
});
|
|
18521
18618
|
featureGroup.addLayer(marker).addTo(this.map);
|
|
18522
|
-
marker
|
|
18619
|
+
this.markerFeatureGroupMap.set(marker, featureGroup);
|
|
18523
18620
|
marker.on("add", () => {
|
|
18524
18621
|
const el2 = marker.getElement();
|
|
18525
18622
|
if (el2) el2.style.pointerEvents = "auto";
|
|
@@ -18536,7 +18633,7 @@ class PolygonInteractionManager {
|
|
|
18536
18633
|
this._activeMarker = marker;
|
|
18537
18634
|
});
|
|
18538
18635
|
marker.on("dragend", (e) => {
|
|
18539
|
-
const fg = marker
|
|
18636
|
+
const fg = this.markerFeatureGroupMap.get(marker);
|
|
18540
18637
|
if (this.modeManager.canPerformAction("markerDrag") && fg) {
|
|
18541
18638
|
this.markerDragEnd(fg);
|
|
18542
18639
|
}
|
|
@@ -18560,7 +18657,7 @@ class PolygonInteractionManager {
|
|
|
18560
18657
|
e.stopPropagation();
|
|
18561
18658
|
marker.fire("click");
|
|
18562
18659
|
if (this.isDraggingMarker && !isSpecialMarker) {
|
|
18563
|
-
const fg = marker
|
|
18660
|
+
const fg = this.markerFeatureGroupMap.get(marker);
|
|
18564
18661
|
if (this.modeManager.canPerformAction("markerDrag") && fg) {
|
|
18565
18662
|
this.markerDragEnd(fg);
|
|
18566
18663
|
}
|
|
@@ -18660,12 +18757,11 @@ class PolygonInteractionManager {
|
|
|
18660
18757
|
this._activeMarker = marker;
|
|
18661
18758
|
});
|
|
18662
18759
|
marker.on("click", (e) => {
|
|
18663
|
-
var _a2;
|
|
18664
18760
|
if (this.modeManager.isInOffMode()) {
|
|
18665
|
-
if (this.
|
|
18666
|
-
const
|
|
18667
|
-
if (
|
|
18668
|
-
this.elbowClicked(e,
|
|
18761
|
+
if (this.isEdgeDeletionModifierKeyPressed(e.originalEvent)) {
|
|
18762
|
+
const polygonLayer = featureGroup.getLayers().find((layer) => layer instanceof L.Polygon);
|
|
18763
|
+
if (polygonLayer) {
|
|
18764
|
+
this.elbowClicked(e, polygonLayer, marker.getLatLng());
|
|
18669
18765
|
}
|
|
18670
18766
|
} else {
|
|
18671
18767
|
if (i === deleteMarkerIdx && this.config.markers.deleteMarker) {
|
|
@@ -18686,88 +18782,291 @@ class PolygonInteractionManager {
|
|
|
18686
18782
|
}
|
|
18687
18783
|
}
|
|
18688
18784
|
/**
|
|
18689
|
-
* Add hole markers to a polygon feature group
|
|
18785
|
+
* Add hole markers to a polygon feature group, with configurable special markers.
|
|
18690
18786
|
*/
|
|
18691
18787
|
addHoleMarkers(latlngs, featureGroup) {
|
|
18788
|
+
var _a2, _b2, _c;
|
|
18789
|
+
const holeMenuEnabled = ((_a2 = this.config.markers.holeMarkers) == null ? void 0 : _a2.menuMarker) ?? false;
|
|
18790
|
+
const holeDeleteEnabled = ((_b2 = this.config.markers.holeMarkers) == null ? void 0 : _b2.deleteMarker) ?? false;
|
|
18791
|
+
const holeInfoEnabled = ((_c = this.config.markers.holeMarkers) == null ? void 0 : _c.infoMarker) ?? false;
|
|
18792
|
+
let menuMarkerIdx = this.getMarkerIndex(latlngs, this.config.markers.markerMenuIcon.position);
|
|
18793
|
+
let deleteMarkerIdx = this.getMarkerIndex(
|
|
18794
|
+
latlngs,
|
|
18795
|
+
this.config.markers.markerDeleteIcon.position
|
|
18796
|
+
);
|
|
18797
|
+
let infoMarkerIdx = this.getMarkerIndex(latlngs, this.config.markers.markerInfoIcon.position);
|
|
18798
|
+
const separatedIndices = this.ensureMarkerSeparation(latlngs.length, {
|
|
18799
|
+
menu: { index: menuMarkerIdx, enabled: holeMenuEnabled },
|
|
18800
|
+
delete: { index: deleteMarkerIdx, enabled: holeDeleteEnabled },
|
|
18801
|
+
info: { index: infoMarkerIdx, enabled: holeInfoEnabled }
|
|
18802
|
+
});
|
|
18803
|
+
menuMarkerIdx = separatedIndices.menu;
|
|
18804
|
+
deleteMarkerIdx = separatedIndices.delete;
|
|
18805
|
+
infoMarkerIdx = separatedIndices.info;
|
|
18692
18806
|
latlngs.forEach((latlng, i) => {
|
|
18693
|
-
|
|
18807
|
+
let iconClasses = this.config.markers.holeIcon.styleClasses;
|
|
18808
|
+
if (i === menuMarkerIdx && holeMenuEnabled) {
|
|
18809
|
+
iconClasses = this.config.markers.markerMenuIcon.styleClasses;
|
|
18810
|
+
}
|
|
18811
|
+
if (i === deleteMarkerIdx && holeDeleteEnabled) {
|
|
18812
|
+
iconClasses = this.config.markers.markerDeleteIcon.styleClasses;
|
|
18813
|
+
}
|
|
18814
|
+
if (i === infoMarkerIdx && holeInfoEnabled) {
|
|
18815
|
+
iconClasses = this.config.markers.markerInfoIcon.styleClasses;
|
|
18816
|
+
}
|
|
18694
18817
|
const processedClasses = Array.isArray(iconClasses) ? iconClasses : [iconClasses];
|
|
18818
|
+
const isSpecialMarker = i === menuMarkerIdx && holeMenuEnabled || i === deleteMarkerIdx && holeDeleteEnabled || i === infoMarkerIdx && holeInfoEnabled;
|
|
18695
18819
|
const marker = new L.Marker(latlng, {
|
|
18696
18820
|
icon: this.createDivIcon(processedClasses),
|
|
18697
|
-
draggable:
|
|
18698
|
-
title: this.getLatLngInfoString(latlng),
|
|
18821
|
+
draggable: this.config.modes.dragElbow,
|
|
18822
|
+
title: this.config.markers.coordsTitle ? this.getLatLngInfoString(latlng) : "",
|
|
18699
18823
|
zIndexOffset: this.config.markers.holeIcon.zIndexOffset ?? this.config.markers.zIndexOffset
|
|
18700
18824
|
});
|
|
18701
18825
|
featureGroup.addLayer(marker).addTo(this.map);
|
|
18826
|
+
this.markerFeatureGroupMap.set(marker, featureGroup);
|
|
18702
18827
|
marker.on("add", () => {
|
|
18703
|
-
const
|
|
18704
|
-
if (
|
|
18828
|
+
const el2 = marker.getElement();
|
|
18829
|
+
if (el2) el2.style.pointerEvents = "auto";
|
|
18705
18830
|
});
|
|
18706
18831
|
marker.on("click", (e) => {
|
|
18707
|
-
var
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
|
|
18711
|
-
|
|
18712
|
-
L.DomEvent.stopPropagation(e);
|
|
18832
|
+
var _a3, _b3;
|
|
18833
|
+
if (this.isDraggingMarker) {
|
|
18834
|
+
(_b3 = (_a3 = e.originalEvent) == null ? void 0 : _a3.stopPropagation) == null ? void 0 : _b3.call(_a3);
|
|
18835
|
+
L.DomEvent.stopPropagation(e);
|
|
18836
|
+
}
|
|
18713
18837
|
});
|
|
18714
|
-
marker.on("
|
|
18715
|
-
this.
|
|
18838
|
+
marker.on("dragstart", () => {
|
|
18839
|
+
this.isDraggingMarker = true;
|
|
18840
|
+
this._activeMarker = marker;
|
|
18716
18841
|
});
|
|
18717
18842
|
marker.on("dragend", (e) => {
|
|
18718
|
-
this.
|
|
18843
|
+
const fg = this.markerFeatureGroupMap.get(marker);
|
|
18844
|
+
if (this.modeManager.canPerformAction("markerDrag") && fg) {
|
|
18845
|
+
this.markerDragEnd(fg);
|
|
18846
|
+
}
|
|
18847
|
+
this._activeMarker = null;
|
|
18848
|
+
L.DomEvent.stopPropagation(e);
|
|
18849
|
+
setTimeout(() => {
|
|
18850
|
+
this.isDraggingMarker = false;
|
|
18851
|
+
}, 10);
|
|
18719
18852
|
});
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
|
|
18728
|
-
|
|
18729
|
-
|
|
18730
|
-
|
|
18731
|
-
|
|
18732
|
-
|
|
18733
|
-
|
|
18734
|
-
|
|
18735
|
-
|
|
18853
|
+
const el = marker.getElement();
|
|
18854
|
+
if (el) {
|
|
18855
|
+
el.addEventListener(
|
|
18856
|
+
"touchstart",
|
|
18857
|
+
(e) => {
|
|
18858
|
+
e.stopPropagation();
|
|
18859
|
+
},
|
|
18860
|
+
{ passive: true }
|
|
18861
|
+
);
|
|
18862
|
+
el.addEventListener("touchend", (e) => {
|
|
18863
|
+
e.preventDefault();
|
|
18864
|
+
e.stopPropagation();
|
|
18865
|
+
marker.fire("click");
|
|
18866
|
+
if (this.isDraggingMarker && !isSpecialMarker) {
|
|
18867
|
+
const fg = this.markerFeatureGroupMap.get(marker);
|
|
18868
|
+
if (this.modeManager.canPerformAction("markerDrag") && fg) {
|
|
18869
|
+
this.markerDragEnd(fg);
|
|
18870
|
+
}
|
|
18736
18871
|
}
|
|
18737
|
-
|
|
18738
|
-
|
|
18739
|
-
} else {
|
|
18740
|
-
processedRings = rawLatLngs[0];
|
|
18741
|
-
}
|
|
18742
|
-
} else if (rawLatLngs[0] && typeof rawLatLngs[0] === "object" && "lat" in rawLatLngs[0]) {
|
|
18743
|
-
processedRings = [rawLatLngs];
|
|
18744
|
-
} else {
|
|
18745
|
-
processedRings = [rawLatLngs];
|
|
18872
|
+
this._activeMarker = null;
|
|
18873
|
+
});
|
|
18746
18874
|
}
|
|
18747
|
-
|
|
18748
|
-
|
|
18749
|
-
|
|
18750
|
-
|
|
18751
|
-
for (let i = 0; i < ring.length; i++) {
|
|
18752
|
-
const edgeStart = ring[i];
|
|
18753
|
-
const edgeEnd = ring[(i + 1) % ring.length];
|
|
18754
|
-
if (edgeStart.lat === edgeEnd.lat && edgeStart.lng === edgeEnd.lng) {
|
|
18755
|
-
continue;
|
|
18875
|
+
if (i === menuMarkerIdx || i === deleteMarkerIdx || i === infoMarkerIdx) {
|
|
18876
|
+
const element = marker.getElement();
|
|
18877
|
+
if (element) {
|
|
18878
|
+
element.style.zIndex = "10000";
|
|
18756
18879
|
}
|
|
18757
|
-
|
|
18758
|
-
|
|
18759
|
-
|
|
18760
|
-
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
|
|
18880
|
+
}
|
|
18881
|
+
if (this.config.modes.dragElbow) {
|
|
18882
|
+
const createDragHandler = (fg) => () => {
|
|
18883
|
+
if (this.modeManager.canPerformAction("markerDrag")) {
|
|
18884
|
+
this.markerDrag(fg);
|
|
18885
|
+
}
|
|
18886
|
+
};
|
|
18887
|
+
marker.on("drag", createDragHandler(featureGroup));
|
|
18888
|
+
}
|
|
18889
|
+
if (i === menuMarkerIdx && holeMenuEnabled) {
|
|
18890
|
+
marker.options.zIndexOffset = this.config.markers.markerMenuIcon.zIndexOffset ?? this.config.markers.zIndexOffset;
|
|
18891
|
+
marker.on("click", () => {
|
|
18892
|
+
const ring = latlngs.map((pt) => [pt.lng, pt.lat]);
|
|
18893
|
+
ring.push(ring[0]);
|
|
18894
|
+
const holePolygon = {
|
|
18895
|
+
type: "Feature",
|
|
18896
|
+
properties: {},
|
|
18897
|
+
geometry: {
|
|
18898
|
+
type: "Polygon",
|
|
18899
|
+
coordinates: [ring]
|
|
18900
|
+
}
|
|
18901
|
+
};
|
|
18902
|
+
const centerOfMass2 = PolygonUtil.getCenterOfMass(holePolygon);
|
|
18903
|
+
const menuPopup = this.generateMenuMarkerPopup(latlngs, featureGroup);
|
|
18904
|
+
menuPopup.setLatLng(centerOfMass2).openOn(this.map);
|
|
18905
|
+
});
|
|
18906
|
+
marker.on("popupopen", (e) => {
|
|
18907
|
+
const popup = e.popup;
|
|
18908
|
+
const popupContent = popup.getElement();
|
|
18909
|
+
if (!popupContent) return;
|
|
18910
|
+
setTimeout(() => {
|
|
18911
|
+
const mapContainer = this.map.getContainer();
|
|
18912
|
+
const mapBounds = mapContainer.getBoundingClientRect();
|
|
18913
|
+
const popupBounds = popupContent.getBoundingClientRect();
|
|
18914
|
+
if (popupBounds.left < mapBounds.left) {
|
|
18915
|
+
popupContent.style.transform = `translateX(${mapBounds.left - popupBounds.left}px)`;
|
|
18916
|
+
} else if (popupBounds.right > mapBounds.right) {
|
|
18917
|
+
popupContent.style.transform = `translateX(${mapBounds.right - popupBounds.right}px)`;
|
|
18918
|
+
}
|
|
18919
|
+
}, 0);
|
|
18920
|
+
const container = this.map.getContainer();
|
|
18921
|
+
if (container) {
|
|
18922
|
+
container.style.touchAction = "manipulation";
|
|
18923
|
+
}
|
|
18924
|
+
});
|
|
18925
|
+
marker.on("popupclose", () => {
|
|
18926
|
+
const container = this.map.getContainer();
|
|
18927
|
+
if (container) {
|
|
18928
|
+
container.style.touchAction = "";
|
|
18929
|
+
}
|
|
18930
|
+
});
|
|
18931
|
+
}
|
|
18932
|
+
if (i === infoMarkerIdx && holeInfoEnabled) {
|
|
18933
|
+
const ring = latlngs.map((latlng2) => [latlng2.lng, latlng2.lat]);
|
|
18934
|
+
ring.push(ring[0]);
|
|
18935
|
+
const holePolygon = {
|
|
18936
|
+
type: "Feature",
|
|
18937
|
+
properties: {},
|
|
18938
|
+
geometry: {
|
|
18939
|
+
type: "Polygon",
|
|
18940
|
+
coordinates: [ring]
|
|
18941
|
+
}
|
|
18942
|
+
};
|
|
18943
|
+
const area2 = this.turfHelper.getPolygonArea(holePolygon);
|
|
18944
|
+
const perimeter = this.turfHelper.getPolygonPerimeter(holePolygon) * 1e3;
|
|
18945
|
+
marker.options.zIndexOffset = this.config.markers.markerInfoIcon.zIndexOffset ?? this.config.markers.zIndexOffset;
|
|
18946
|
+
marker.on("click", () => {
|
|
18947
|
+
const infoPopup = this.generateInfoMarkerPopup(area2, perimeter);
|
|
18948
|
+
infoPopup.setLatLng(latlng).openOn(this.map);
|
|
18949
|
+
});
|
|
18950
|
+
}
|
|
18951
|
+
marker.on("mousedown", (e) => {
|
|
18952
|
+
if (!this.modeManager.isInOffMode()) {
|
|
18953
|
+
L.DomEvent.stopPropagation(e);
|
|
18954
|
+
this.map.fire("mousedown", e);
|
|
18955
|
+
}
|
|
18956
|
+
this._activeMarker = marker;
|
|
18957
|
+
});
|
|
18958
|
+
marker.on("click", (e) => {
|
|
18959
|
+
if (this.modeManager.isInOffMode()) {
|
|
18960
|
+
if (this.isEdgeDeletionModifierKeyPressed(e.originalEvent)) {
|
|
18961
|
+
const polygonLayer = featureGroup.getLayers().find((layer) => layer instanceof L.Polygon);
|
|
18962
|
+
if (polygonLayer) {
|
|
18963
|
+
this.elbowClicked(e, polygonLayer, marker.getLatLng());
|
|
18964
|
+
}
|
|
18965
|
+
} else {
|
|
18966
|
+
if (i === deleteMarkerIdx && holeDeleteEnabled) {
|
|
18967
|
+
this.map.closePopup();
|
|
18968
|
+
const parentPolygon = featureGroup.getLayers().find((layer) => layer instanceof L.Polygon);
|
|
18969
|
+
if (parentPolygon) {
|
|
18970
|
+
const rawLatLngs = parentPolygon.getLatLngs();
|
|
18971
|
+
let rings = [];
|
|
18972
|
+
if (Array.isArray(rawLatLngs) && rawLatLngs.length > 0) {
|
|
18973
|
+
if (Array.isArray(rawLatLngs[0])) {
|
|
18974
|
+
const first = rawLatLngs[0];
|
|
18975
|
+
if (Array.isArray(first) && Array.isArray(first[0])) {
|
|
18976
|
+
rings = rawLatLngs[0];
|
|
18977
|
+
} else {
|
|
18978
|
+
rings = rawLatLngs;
|
|
18979
|
+
}
|
|
18980
|
+
} else {
|
|
18981
|
+
rings = [rawLatLngs];
|
|
18982
|
+
}
|
|
18983
|
+
}
|
|
18984
|
+
const target = marker.getLatLng();
|
|
18985
|
+
let holeIndex = -1;
|
|
18986
|
+
for (let r = 1; r < rings.length; r++) {
|
|
18987
|
+
if (rings[r].some((p) => p.lat === target.lat && p.lng === target.lng)) {
|
|
18988
|
+
holeIndex = r;
|
|
18989
|
+
break;
|
|
18990
|
+
}
|
|
18991
|
+
}
|
|
18992
|
+
if (holeIndex > 0) {
|
|
18993
|
+
const newRings = rings.filter((_, idx) => idx !== holeIndex);
|
|
18994
|
+
const coords = newRings.map((ring) => {
|
|
18995
|
+
const arr = ring.map((ll) => [ll.lng, ll.lat]);
|
|
18996
|
+
if (arr.length > 0) {
|
|
18997
|
+
const firstPt = arr[0];
|
|
18998
|
+
const lastPt = arr[arr.length - 1];
|
|
18999
|
+
if (firstPt[0] !== lastPt[0] || firstPt[1] !== lastPt[1]) {
|
|
19000
|
+
arr.push([firstPt[0], firstPt[1]]);
|
|
19001
|
+
}
|
|
19002
|
+
}
|
|
19003
|
+
return arr;
|
|
19004
|
+
});
|
|
19005
|
+
const newPolygon = this.turfHelper.getMultiPolygon([coords]);
|
|
19006
|
+
this.removeFeatureGroup(featureGroup);
|
|
19007
|
+
this.eventManager.emit("polydraw:polygon:updated", {
|
|
19008
|
+
operation: "removeHole",
|
|
19009
|
+
polygon: newPolygon
|
|
19010
|
+
});
|
|
19011
|
+
}
|
|
19012
|
+
}
|
|
19013
|
+
}
|
|
19014
|
+
}
|
|
19015
|
+
}
|
|
19016
|
+
});
|
|
19017
|
+
marker.on("mouseover", () => this.onMarkerHoverForEdgeDeletion(marker, true));
|
|
19018
|
+
marker.on("mouseout", () => this.onMarkerHoverForEdgeDeletion(marker, false));
|
|
19019
|
+
});
|
|
19020
|
+
}
|
|
19021
|
+
/**
|
|
19022
|
+
* Add edge click listeners to a polygon
|
|
19023
|
+
*/
|
|
19024
|
+
addEdgeClickListeners(polygon2, featureGroup) {
|
|
19025
|
+
const rawLatLngs = polygon2.getLatLngs();
|
|
19026
|
+
let processedRings;
|
|
19027
|
+
if (Array.isArray(rawLatLngs) && rawLatLngs.length > 0) {
|
|
19028
|
+
if (Array.isArray(rawLatLngs[0])) {
|
|
19029
|
+
if (Array.isArray(rawLatLngs[0][0]) && rawLatLngs[0][0].length > 0) {
|
|
19030
|
+
const firstCoord = rawLatLngs[0][0][0];
|
|
19031
|
+
if (firstCoord && typeof firstCoord === "object" && "lat" in firstCoord) {
|
|
19032
|
+
processedRings = rawLatLngs[0];
|
|
19033
|
+
} else {
|
|
19034
|
+
processedRings = rawLatLngs[0];
|
|
19035
|
+
}
|
|
19036
|
+
} else if (rawLatLngs[0][0] && typeof rawLatLngs[0][0] === "object" && "lat" in rawLatLngs[0][0]) {
|
|
19037
|
+
processedRings = rawLatLngs;
|
|
19038
|
+
} else {
|
|
19039
|
+
processedRings = rawLatLngs[0];
|
|
19040
|
+
}
|
|
19041
|
+
} else if (rawLatLngs[0] && typeof rawLatLngs[0] === "object" && "lat" in rawLatLngs[0]) {
|
|
19042
|
+
processedRings = [rawLatLngs];
|
|
19043
|
+
} else {
|
|
19044
|
+
processedRings = [rawLatLngs];
|
|
19045
|
+
}
|
|
19046
|
+
} else {
|
|
19047
|
+
return;
|
|
19048
|
+
}
|
|
19049
|
+
processedRings.forEach((ring, ringIndex) => {
|
|
19050
|
+
for (let i = 0; i < ring.length; i++) {
|
|
19051
|
+
const edgeStart = ring[i];
|
|
19052
|
+
const edgeEnd = ring[(i + 1) % ring.length];
|
|
19053
|
+
if (edgeStart.lat === edgeEnd.lat && edgeStart.lng === edgeEnd.lng) {
|
|
19054
|
+
continue;
|
|
19055
|
+
}
|
|
19056
|
+
const edgePolyline = L.polyline([edgeStart, edgeEnd], {
|
|
19057
|
+
color: "transparent",
|
|
19058
|
+
weight: 10,
|
|
19059
|
+
opacity: 0,
|
|
19060
|
+
interactive: true
|
|
19061
|
+
});
|
|
19062
|
+
edgePolyline._polydrawEdgeInfo = {
|
|
19063
|
+
ringIndex,
|
|
19064
|
+
edgeIndex: i,
|
|
19065
|
+
startPoint: edgeStart,
|
|
19066
|
+
endPoint: edgeEnd,
|
|
19067
|
+
parentPolygon: polygon2,
|
|
19068
|
+
parentFeatureGroup: featureGroup
|
|
19069
|
+
};
|
|
18771
19070
|
edgePolyline.on("click", (e) => {
|
|
18772
19071
|
this.onEdgeClick(e, edgePolyline);
|
|
18773
19072
|
});
|
|
@@ -18801,9 +19100,9 @@ class PolygonInteractionManager {
|
|
|
18801
19100
|
if (!this.modeManager.canPerformAction("polygonDrag")) {
|
|
18802
19101
|
return;
|
|
18803
19102
|
}
|
|
18804
|
-
L.DomEvent.stopPropagation(e);
|
|
18805
|
-
L.DomEvent.preventDefault(e);
|
|
18806
|
-
const isModifierPressed = this.
|
|
19103
|
+
L.DomEvent.stopPropagation(e.originalEvent);
|
|
19104
|
+
L.DomEvent.preventDefault(e.originalEvent);
|
|
19105
|
+
const isModifierPressed = this.detectDragSubtractModifierKey(e.originalEvent);
|
|
18807
19106
|
this.currentModifierDragMode = isModifierPressed;
|
|
18808
19107
|
this.isModifierKeyHeld = isModifierPressed;
|
|
18809
19108
|
polygon2._polydrawDragData.isDragging = true;
|
|
@@ -18919,10 +19218,11 @@ class PolygonInteractionManager {
|
|
|
18919
19218
|
}
|
|
18920
19219
|
const poly = parentPolygon.toGeoJSON();
|
|
18921
19220
|
if (poly.geometry.type === "MultiPolygon" || poly.geometry.type === "Polygon") {
|
|
18922
|
-
const newPolygon = this.turfHelper.injectPointToPolygon(
|
|
18923
|
-
|
|
18924
|
-
newPoint.lat
|
|
18925
|
-
|
|
19221
|
+
const newPolygon = this.turfHelper.injectPointToPolygon(
|
|
19222
|
+
poly,
|
|
19223
|
+
[newPoint.lng, newPoint.lat],
|
|
19224
|
+
edgeInfo.ringIndex
|
|
19225
|
+
);
|
|
18926
19226
|
if (newPolygon) {
|
|
18927
19227
|
const polydrawPolygon = parentPolygon;
|
|
18928
19228
|
const optimizationLevel = polydrawPolygon._polydrawOptimizationLevel || 0;
|
|
@@ -18942,7 +19242,7 @@ class PolygonInteractionManager {
|
|
|
18942
19242
|
highlightEdgeOnHover(edgePolyline, isHovering) {
|
|
18943
19243
|
if (isHovering) {
|
|
18944
19244
|
edgePolyline.setStyle({
|
|
18945
|
-
color:
|
|
19245
|
+
color: this.config.colors.edgeHover,
|
|
18946
19246
|
weight: 4,
|
|
18947
19247
|
opacity: 1
|
|
18948
19248
|
});
|
|
@@ -18954,49 +19254,79 @@ class PolygonInteractionManager {
|
|
|
18954
19254
|
});
|
|
18955
19255
|
}
|
|
18956
19256
|
}
|
|
18957
|
-
elbowClicked(e,
|
|
18958
|
-
if (!this.config.modes.edgeDeletion)
|
|
18959
|
-
|
|
18960
|
-
|
|
18961
|
-
|
|
19257
|
+
elbowClicked(e, polygonLayer, forcedLatLng) {
|
|
19258
|
+
if (!this.config.modes.edgeDeletion) return;
|
|
19259
|
+
if (!this.isEdgeDeletionModifierKeyPressed(e.originalEvent)) return;
|
|
19260
|
+
const clickedLatLng = forcedLatLng ?? e.latlng;
|
|
19261
|
+
const rawLatLngs = polygonLayer.getLatLngs();
|
|
19262
|
+
let rings = [];
|
|
19263
|
+
if (Array.isArray(rawLatLngs) && rawLatLngs.length > 0) {
|
|
19264
|
+
if (Array.isArray(rawLatLngs[0])) {
|
|
19265
|
+
const first = rawLatLngs[0];
|
|
19266
|
+
if (Array.isArray(first) && Array.isArray(first[0])) {
|
|
19267
|
+
rings = rawLatLngs[0];
|
|
19268
|
+
} else {
|
|
19269
|
+
rings = rawLatLngs;
|
|
19270
|
+
}
|
|
19271
|
+
} else {
|
|
19272
|
+
rings = [rawLatLngs];
|
|
19273
|
+
}
|
|
19274
|
+
} else {
|
|
18962
19275
|
return;
|
|
18963
19276
|
}
|
|
18964
|
-
const clickedLatLng = e.latlng;
|
|
18965
|
-
const allRings = poly.geometry.coordinates[0];
|
|
18966
19277
|
let targetRingIndex = -1;
|
|
18967
19278
|
let targetVertexIndex = -1;
|
|
18968
|
-
for (let
|
|
18969
|
-
const ring =
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
19279
|
+
for (let r = 0; r < rings.length; r++) {
|
|
19280
|
+
const ring = rings[r];
|
|
19281
|
+
for (let v = 0; v < ring.length; v++) {
|
|
19282
|
+
const p = ring[v];
|
|
19283
|
+
if (p.lat === clickedLatLng.lat && p.lng === clickedLatLng.lng) {
|
|
19284
|
+
targetRingIndex = r;
|
|
19285
|
+
targetVertexIndex = v;
|
|
19286
|
+
break;
|
|
19287
|
+
}
|
|
18977
19288
|
}
|
|
19289
|
+
if (targetRingIndex !== -1) break;
|
|
18978
19290
|
}
|
|
18979
19291
|
if (targetRingIndex === -1 || targetVertexIndex === -1) {
|
|
18980
19292
|
return;
|
|
18981
19293
|
}
|
|
18982
|
-
const targetRing =
|
|
18983
|
-
if (targetRing.length <=
|
|
19294
|
+
const targetRing = rings[targetRingIndex];
|
|
19295
|
+
if (targetRing.length <= 3) {
|
|
18984
19296
|
return;
|
|
18985
19297
|
}
|
|
18986
|
-
const
|
|
18987
|
-
if (
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
19298
|
+
const newRings = rings.map((ring, idx) => {
|
|
19299
|
+
if (idx !== targetRingIndex) return ring.slice();
|
|
19300
|
+
const nr = ring.slice();
|
|
19301
|
+
nr.splice(targetVertexIndex, 1);
|
|
19302
|
+
return nr;
|
|
19303
|
+
});
|
|
19304
|
+
const coords = newRings.map((ring) => {
|
|
19305
|
+
const arr = ring.map((ll) => [ll.lng, ll.lat]);
|
|
19306
|
+
if (arr.length > 0) {
|
|
19307
|
+
const first = arr[0];
|
|
19308
|
+
const last = arr[arr.length - 1];
|
|
19309
|
+
if (first[0] !== last[0] || first[1] !== last[1]) {
|
|
19310
|
+
arr.push([first[0], first[1]]);
|
|
19311
|
+
}
|
|
18993
19312
|
}
|
|
19313
|
+
return arr;
|
|
18994
19314
|
});
|
|
18995
|
-
|
|
19315
|
+
let currentFeatureGroup = null;
|
|
19316
|
+
for (const fg of this.getFeatureGroups()) {
|
|
19317
|
+
let found = false;
|
|
19318
|
+
fg.eachLayer((layer) => {
|
|
19319
|
+
if (layer === polygonLayer) found = true;
|
|
19320
|
+
});
|
|
19321
|
+
if (found) {
|
|
19322
|
+
currentFeatureGroup = fg;
|
|
19323
|
+
break;
|
|
19324
|
+
}
|
|
19325
|
+
}
|
|
18996
19326
|
if (currentFeatureGroup) {
|
|
18997
19327
|
this.removeFeatureGroup(currentFeatureGroup);
|
|
18998
19328
|
}
|
|
18999
|
-
const newPolygon = this.turfHelper.getMultiPolygon([
|
|
19329
|
+
const newPolygon = this.turfHelper.getMultiPolygon([coords]);
|
|
19000
19330
|
this.eventManager.emit("polydraw:polygon:updated", {
|
|
19001
19331
|
operation: "removeVertex",
|
|
19002
19332
|
polygon: newPolygon
|
|
@@ -19007,7 +19337,7 @@ class PolygonInteractionManager {
|
|
|
19007
19337
|
const featureCollection2 = featureGroup.toGeoJSON();
|
|
19008
19338
|
if (featureCollection2 && featureCollection2.features && featureCollection2.features[0]) {
|
|
19009
19339
|
const feature2 = featureCollection2.features[0];
|
|
19010
|
-
if (
|
|
19340
|
+
if (this.turfHelper.equalPolygons(feature2, poly)) {
|
|
19011
19341
|
return featureGroup;
|
|
19012
19342
|
}
|
|
19013
19343
|
}
|
|
@@ -19022,10 +19352,11 @@ class PolygonInteractionManager {
|
|
|
19022
19352
|
const newPos = [];
|
|
19023
19353
|
let testarray = [];
|
|
19024
19354
|
let hole = [];
|
|
19025
|
-
const
|
|
19026
|
-
const
|
|
19355
|
+
const layers = featureGroup.getLayers();
|
|
19356
|
+
const polygonLayer = layers.find((l) => l instanceof L.Polygon);
|
|
19357
|
+
const posarrays = polygonLayer.getLatLngs();
|
|
19027
19358
|
let length2 = 0;
|
|
19028
|
-
const markers2 =
|
|
19359
|
+
const markers2 = layers.filter((layer) => layer instanceof L.Marker);
|
|
19029
19360
|
if (posarrays.length > 1) {
|
|
19030
19361
|
for (let index = 0; index < posarrays.length; index++) {
|
|
19031
19362
|
testarray = [];
|
|
@@ -19050,7 +19381,7 @@ class PolygonInteractionManager {
|
|
|
19050
19381
|
}
|
|
19051
19382
|
newPos.push(hole);
|
|
19052
19383
|
} else {
|
|
19053
|
-
length2 += posarrays[index - 1]
|
|
19384
|
+
length2 += posarrays[index - 1].length;
|
|
19054
19385
|
for (let j = length2; j < posarrays[index][0].length + length2; j++) {
|
|
19055
19386
|
if (markers2[j]) {
|
|
19056
19387
|
testarray.push(markers2[j].getLatLng());
|
|
@@ -19091,7 +19422,7 @@ class PolygonInteractionManager {
|
|
|
19091
19422
|
}
|
|
19092
19423
|
newPos.push(hole);
|
|
19093
19424
|
}
|
|
19094
|
-
|
|
19425
|
+
polygonLayer.setLatLngs(newPos);
|
|
19095
19426
|
}
|
|
19096
19427
|
async markerDragEnd(featureGroup) {
|
|
19097
19428
|
this.polygonInformation.deletePolygonInformationStorage();
|
|
@@ -19100,7 +19431,7 @@ class PolygonInteractionManager {
|
|
|
19100
19431
|
return;
|
|
19101
19432
|
}
|
|
19102
19433
|
this.removeFeatureGroup(featureGroup);
|
|
19103
|
-
if (featureCollection2.features[0].geometry.
|
|
19434
|
+
if (featureCollection2.features[0].geometry.type === "MultiPolygon") {
|
|
19104
19435
|
for (const element of featureCollection2.features[0].geometry.coordinates) {
|
|
19105
19436
|
const feature2 = this.turfHelper.getMultiPolygon([element]);
|
|
19106
19437
|
if (this.turfHelper.hasKinks(feature2)) {
|
|
@@ -19121,9 +19452,9 @@ class PolygonInteractionManager {
|
|
|
19121
19452
|
}
|
|
19122
19453
|
}
|
|
19123
19454
|
} else {
|
|
19124
|
-
const feature2 = this.turfHelper.getMultiPolygon(
|
|
19455
|
+
const feature2 = this.turfHelper.getMultiPolygon([
|
|
19125
19456
|
featureCollection2.features[0].geometry.coordinates
|
|
19126
|
-
);
|
|
19457
|
+
]);
|
|
19127
19458
|
if (this.turfHelper.hasKinks(feature2)) {
|
|
19128
19459
|
const unkink = this.turfHelper.getKinks(feature2);
|
|
19129
19460
|
for (const polygon2 of unkink) {
|
|
@@ -19132,11 +19463,6 @@ class PolygonInteractionManager {
|
|
|
19132
19463
|
polygon: this.turfHelper.getTurfPolygon(polygon2),
|
|
19133
19464
|
allowMerge: true
|
|
19134
19465
|
});
|
|
19135
|
-
this.eventManager.emit("polydraw:polygon:updated", {
|
|
19136
|
-
operation: "markerDrag",
|
|
19137
|
-
polygon: this.turfHelper.getTurfPolygon(polygon2),
|
|
19138
|
-
allowMerge: true
|
|
19139
|
-
});
|
|
19140
19466
|
}
|
|
19141
19467
|
} else {
|
|
19142
19468
|
this.eventManager.emit("polydraw:polygon:updated", {
|
|
@@ -19144,11 +19470,6 @@ class PolygonInteractionManager {
|
|
|
19144
19470
|
polygon: feature2,
|
|
19145
19471
|
allowMerge: true
|
|
19146
19472
|
});
|
|
19147
|
-
this.eventManager.emit("polydraw:polygon:updated", {
|
|
19148
|
-
operation: "markerDrag",
|
|
19149
|
-
polygon: feature2,
|
|
19150
|
-
allowMerge: true
|
|
19151
|
-
});
|
|
19152
19473
|
}
|
|
19153
19474
|
}
|
|
19154
19475
|
this.polygonInformation.createPolygonInformationStorage(this.getFeatureGroups());
|
|
@@ -19156,17 +19477,11 @@ class PolygonInteractionManager {
|
|
|
19156
19477
|
offsetPolygonCoordinates(latLngs, offsetLat, offsetLng) {
|
|
19157
19478
|
if (!latLngs) return latLngs;
|
|
19158
19479
|
if (Array.isArray(latLngs[0])) {
|
|
19159
|
-
return latLngs.map((ring) => this.offsetPolygonCoordinates(ring, offsetLat, offsetLng));
|
|
19160
|
-
} else if (latLngs.lat !== void 0 && latLngs.lng !== void 0) {
|
|
19161
|
-
return {
|
|
19162
|
-
lat: latLngs.lat + offsetLat,
|
|
19163
|
-
lng: latLngs.lng + offsetLng
|
|
19164
|
-
};
|
|
19165
|
-
} else {
|
|
19166
19480
|
return latLngs.map(
|
|
19167
|
-
(
|
|
19481
|
+
(ring) => this.offsetPolygonCoordinates(ring, offsetLat, offsetLng)
|
|
19168
19482
|
);
|
|
19169
19483
|
}
|
|
19484
|
+
return latLngs.map((p) => L.latLng(p.lat + offsetLat, p.lng + offsetLng));
|
|
19170
19485
|
}
|
|
19171
19486
|
updateMarkersAndHoleLinesDuringDrag(polygon2, offsetLat, offsetLng) {
|
|
19172
19487
|
try {
|
|
@@ -19195,7 +19510,8 @@ class PolygonInteractionManager {
|
|
|
19195
19510
|
if (layer instanceof L.Marker) {
|
|
19196
19511
|
polygon2._polydrawOriginalMarkerPositions.set(layer, layer.getLatLng());
|
|
19197
19512
|
} else if (layer instanceof L.Polyline && !(layer instanceof L.Polygon)) {
|
|
19198
|
-
|
|
19513
|
+
const latLngs = layer.getLatLngs();
|
|
19514
|
+
polygon2._polydrawOriginalHoleLinePositions.set(layer, latLngs);
|
|
19199
19515
|
}
|
|
19200
19516
|
});
|
|
19201
19517
|
}
|
|
@@ -19212,10 +19528,16 @@ class PolygonInteractionManager {
|
|
|
19212
19528
|
} else if (layer instanceof L.Polyline && !(layer instanceof L.Polygon)) {
|
|
19213
19529
|
const originalPositions = polygon2._polydrawOriginalHoleLinePositions.get(layer);
|
|
19214
19530
|
if (originalPositions) {
|
|
19215
|
-
|
|
19216
|
-
|
|
19217
|
-
|
|
19218
|
-
|
|
19531
|
+
let newLatLngs;
|
|
19532
|
+
if (Array.isArray(originalPositions[0])) {
|
|
19533
|
+
newLatLngs = originalPositions.map(
|
|
19534
|
+
(ring) => ring.map((latlng) => L.latLng(latlng.lat + offsetLat, latlng.lng + offsetLng))
|
|
19535
|
+
);
|
|
19536
|
+
} else {
|
|
19537
|
+
newLatLngs = originalPositions.map(
|
|
19538
|
+
(latlng) => L.latLng(latlng.lat + offsetLat, latlng.lng + offsetLng)
|
|
19539
|
+
);
|
|
19540
|
+
}
|
|
19219
19541
|
layer.setLatLngs(newLatLngs);
|
|
19220
19542
|
}
|
|
19221
19543
|
}
|
|
@@ -19256,7 +19578,17 @@ class PolygonInteractionManager {
|
|
|
19256
19578
|
} catch (error) {
|
|
19257
19579
|
}
|
|
19258
19580
|
}
|
|
19259
|
-
|
|
19581
|
+
getDragSubtractModifierKey() {
|
|
19582
|
+
const { keys } = this.config.dragPolygons.modifierSubtract;
|
|
19583
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
19584
|
+
const isMac = userAgent.includes("mac");
|
|
19585
|
+
const isWindows = userAgent.includes("windows");
|
|
19586
|
+
if (isMac && keys.mac) return keys.mac;
|
|
19587
|
+
if (isWindows && keys.windows) return keys.windows;
|
|
19588
|
+
if (keys.linux) return keys.linux;
|
|
19589
|
+
return isMac ? "metaKey" : "ctrlKey";
|
|
19590
|
+
}
|
|
19591
|
+
detectDragSubtractModifierKey(event) {
|
|
19260
19592
|
var _a2, _b2;
|
|
19261
19593
|
if (!((_b2 = (_a2 = this.config.dragPolygons) == null ? void 0 : _a2.modifierSubtract) == null ? void 0 : _b2.enabled)) {
|
|
19262
19594
|
return false;
|
|
@@ -19264,13 +19596,8 @@ class PolygonInteractionManager {
|
|
|
19264
19596
|
if (isTouchDevice()) {
|
|
19265
19597
|
return false;
|
|
19266
19598
|
}
|
|
19267
|
-
const
|
|
19268
|
-
|
|
19269
|
-
if (isMac) {
|
|
19270
|
-
return event.metaKey;
|
|
19271
|
-
} else {
|
|
19272
|
-
return event.ctrlKey;
|
|
19273
|
-
}
|
|
19599
|
+
const modifierKey = this.getDragSubtractModifierKey();
|
|
19600
|
+
return !!event[modifierKey];
|
|
19274
19601
|
}
|
|
19275
19602
|
setSubtractVisualMode(polygon2, enabled) {
|
|
19276
19603
|
if (!polygon2 || !polygon2.setStyle) {
|
|
@@ -19279,11 +19606,11 @@ class PolygonInteractionManager {
|
|
|
19279
19606
|
try {
|
|
19280
19607
|
if (enabled) {
|
|
19281
19608
|
polygon2.setStyle({
|
|
19282
|
-
color: this.config.dragPolygons.
|
|
19609
|
+
color: this.config.colors.dragPolygons.subtract
|
|
19283
19610
|
});
|
|
19284
19611
|
} else {
|
|
19285
19612
|
polygon2.setStyle({
|
|
19286
|
-
color: this.config.
|
|
19613
|
+
color: this.config.colors.polygon.border
|
|
19287
19614
|
});
|
|
19288
19615
|
}
|
|
19289
19616
|
this.updateMarkerColorsForSubtractMode(polygon2, enabled);
|
|
@@ -19316,8 +19643,8 @@ class PolygonInteractionManager {
|
|
|
19316
19643
|
element.style.display = "none";
|
|
19317
19644
|
element.classList.add("subtract-mode-hidden");
|
|
19318
19645
|
} else {
|
|
19319
|
-
element.style.backgroundColor = this.config.dragPolygons.
|
|
19320
|
-
element.style.borderColor = this.config.dragPolygons.
|
|
19646
|
+
element.style.backgroundColor = this.config.colors.dragPolygons.subtract;
|
|
19647
|
+
element.style.borderColor = this.config.colors.dragPolygons.subtract;
|
|
19321
19648
|
element.classList.add("subtract-mode");
|
|
19322
19649
|
}
|
|
19323
19650
|
} else {
|
|
@@ -19337,7 +19664,7 @@ class PolygonInteractionManager {
|
|
|
19337
19664
|
}
|
|
19338
19665
|
}
|
|
19339
19666
|
handleModifierToggleDuringDrag(event) {
|
|
19340
|
-
const isModifierPressed = this.
|
|
19667
|
+
const isModifierPressed = this.detectDragSubtractModifierKey(event);
|
|
19341
19668
|
this.currentModifierDragMode = isModifierPressed;
|
|
19342
19669
|
this.isModifierKeyHeld = isModifierPressed;
|
|
19343
19670
|
if (this.currentDragPolygon) {
|
|
@@ -19367,8 +19694,11 @@ class PolygonInteractionManager {
|
|
|
19367
19694
|
const existingPolygon = this.turfHelper.getTurfPolygon(firstFeature);
|
|
19368
19695
|
try {
|
|
19369
19696
|
const intersection3 = this.turfHelper.getIntersection(existingPolygon, draggedPolygon);
|
|
19370
|
-
if (intersection3 && intersection3.geometry && intersection3.geometry
|
|
19371
|
-
|
|
19697
|
+
if (intersection3 && intersection3.geometry && "coordinates" in intersection3.geometry) {
|
|
19698
|
+
const coords = intersection3.geometry.coordinates;
|
|
19699
|
+
if (coords.length > 0) {
|
|
19700
|
+
intersectingFeatureGroups.push(featureGroup);
|
|
19701
|
+
}
|
|
19372
19702
|
}
|
|
19373
19703
|
} catch (intersectError) {
|
|
19374
19704
|
try {
|
|
@@ -19428,28 +19758,39 @@ class PolygonInteractionManager {
|
|
|
19428
19758
|
boundingBoxesOverlap(bbox1, bbox2) {
|
|
19429
19759
|
return !(bbox1[2] < bbox2[0] || bbox2[2] < bbox1[0] || bbox1[3] < bbox2[1] || bbox2[3] < bbox1[1]);
|
|
19430
19760
|
}
|
|
19431
|
-
|
|
19761
|
+
isDragSubtractModifierKeyPressed(event) {
|
|
19432
19762
|
if (isTouchDevice()) {
|
|
19433
19763
|
return false;
|
|
19434
19764
|
}
|
|
19765
|
+
const modifierKey = this.getDragSubtractModifierKey();
|
|
19766
|
+
return !!event[modifierKey];
|
|
19767
|
+
}
|
|
19768
|
+
getEdgeDeletionModifierKey() {
|
|
19769
|
+
const { keys } = this.config.edgeDeletion;
|
|
19435
19770
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
19436
19771
|
const isMac = userAgent.includes("mac");
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19772
|
+
const isWindows = userAgent.includes("windows");
|
|
19773
|
+
if (isMac && keys.mac) return keys.mac;
|
|
19774
|
+
if (isWindows && keys.windows) return keys.windows;
|
|
19775
|
+
if (keys.linux) return keys.linux;
|
|
19776
|
+
return isMac ? "metaKey" : "ctrlKey";
|
|
19777
|
+
}
|
|
19778
|
+
isEdgeDeletionModifierKeyPressed(event) {
|
|
19779
|
+
if (isTouchDevice()) {
|
|
19780
|
+
return false;
|
|
19441
19781
|
}
|
|
19782
|
+
const modifierKey = this.getEdgeDeletionModifierKey();
|
|
19783
|
+
return !!event[modifierKey];
|
|
19442
19784
|
}
|
|
19443
19785
|
onMarkerHoverForEdgeDeletion(marker, isHovering) {
|
|
19444
19786
|
const element = marker.getElement();
|
|
19445
19787
|
if (!element) return;
|
|
19446
19788
|
if (isHovering) {
|
|
19447
19789
|
const checkModifierAndUpdate = (e) => {
|
|
19448
|
-
|
|
19449
|
-
const isModifierPressed = this.detectModifierKey(e);
|
|
19790
|
+
const isModifierPressed = this.isEdgeDeletionModifierKeyPressed(e);
|
|
19450
19791
|
if (isModifierPressed) {
|
|
19451
|
-
element.style.backgroundColor =
|
|
19452
|
-
element.style.borderColor =
|
|
19792
|
+
element.style.backgroundColor = this.config.colors.edgeDeletion.hover;
|
|
19793
|
+
element.style.borderColor = this.config.colors.edgeDeletion.hover;
|
|
19453
19794
|
element.classList.add("edge-deletion-hover");
|
|
19454
19795
|
try {
|
|
19455
19796
|
const container = this.map.getContainer();
|
|
@@ -19469,7 +19810,7 @@ class PolygonInteractionManager {
|
|
|
19469
19810
|
};
|
|
19470
19811
|
const initialEvent = new MouseEvent("mouseover");
|
|
19471
19812
|
checkModifierAndUpdate(initialEvent);
|
|
19472
|
-
marker
|
|
19813
|
+
this.markerModifierHandlers.set(marker, checkModifierAndUpdate);
|
|
19473
19814
|
document.addEventListener("keydown", checkModifierAndUpdate);
|
|
19474
19815
|
document.addEventListener("keyup", checkModifierAndUpdate);
|
|
19475
19816
|
element.addEventListener("mousemove", checkModifierAndUpdate);
|
|
@@ -19482,12 +19823,12 @@ class PolygonInteractionManager {
|
|
|
19482
19823
|
container.style.cursor = "";
|
|
19483
19824
|
} catch (error) {
|
|
19484
19825
|
}
|
|
19485
|
-
const handler = marker
|
|
19826
|
+
const handler = this.markerModifierHandlers.get(marker);
|
|
19486
19827
|
if (handler) {
|
|
19487
19828
|
document.removeEventListener("keydown", handler);
|
|
19488
19829
|
document.removeEventListener("keyup", handler);
|
|
19489
19830
|
element.removeEventListener("mousemove", handler);
|
|
19490
|
-
delete
|
|
19831
|
+
this.markerModifierHandlers.delete(marker);
|
|
19491
19832
|
}
|
|
19492
19833
|
}
|
|
19493
19834
|
}
|
|
@@ -19507,7 +19848,10 @@ class PolygonInteractionManager {
|
|
|
19507
19848
|
};
|
|
19508
19849
|
const targetPoint = this.turfHelper.getCoord(latLngPoint);
|
|
19509
19850
|
const fc = this.turfHelper.getFeaturePointCollection(latlngs);
|
|
19510
|
-
const nearestPointIdx = this.turfHelper.getNearestPointIndex(
|
|
19851
|
+
const nearestPointIdx = this.turfHelper.getNearestPointIndex(
|
|
19852
|
+
targetPoint,
|
|
19853
|
+
fc
|
|
19854
|
+
);
|
|
19511
19855
|
return nearestPointIdx;
|
|
19512
19856
|
}
|
|
19513
19857
|
ensureMarkerSeparation(polygonLength, markers2) {
|
|
@@ -19722,7 +20066,11 @@ class PolygonInteractionManager {
|
|
|
19722
20066
|
}
|
|
19723
20067
|
return polygon2.toGeoJSON();
|
|
19724
20068
|
} catch (error) {
|
|
19725
|
-
|
|
20069
|
+
if (error instanceof Error) {
|
|
20070
|
+
console.warn("Error getting polygon GeoJSON from feature group:", error.message);
|
|
20071
|
+
} else {
|
|
20072
|
+
console.warn("Error getting polygon GeoJSON from feature group:", error);
|
|
20073
|
+
}
|
|
19726
20074
|
return {
|
|
19727
20075
|
type: "Feature",
|
|
19728
20076
|
geometry: {
|
|
@@ -19780,7 +20128,11 @@ class PolygonInteractionManager {
|
|
|
19780
20128
|
}
|
|
19781
20129
|
return totalPerimeter * 1e3;
|
|
19782
20130
|
} catch (error) {
|
|
19783
|
-
|
|
20131
|
+
if (error instanceof Error) {
|
|
20132
|
+
console.warn("Error calculating total polygon perimeter:", error.message);
|
|
20133
|
+
} else {
|
|
20134
|
+
console.warn("Error calculating total polygon perimeter:", error);
|
|
20135
|
+
}
|
|
19784
20136
|
return this.turfHelper.getPolygonPerimeter(polygonGeoJSON) * 1e3;
|
|
19785
20137
|
}
|
|
19786
20138
|
}
|
|
@@ -19901,7 +20253,7 @@ class PolygonMutationManager {
|
|
|
19901
20253
|
this.subtractPolygon(data.subtractPolygon);
|
|
19902
20254
|
});
|
|
19903
20255
|
this.eventManager.on("polydraw:polygon:deleted", () => {
|
|
19904
|
-
this.emit("polygonDeleted");
|
|
20256
|
+
this.emit("polygonDeleted", void 0);
|
|
19905
20257
|
});
|
|
19906
20258
|
}
|
|
19907
20259
|
/**
|
|
@@ -19920,11 +20272,10 @@ class PolygonMutationManager {
|
|
|
19920
20272
|
* Handle menu actions from interaction manager
|
|
19921
20273
|
*/
|
|
19922
20274
|
async handleMenuAction(data) {
|
|
19923
|
-
const
|
|
19924
|
-
|
|
19925
|
-
this.removeFeatureGroupInternal(featureGroup);
|
|
20275
|
+
const completePolygonGeoJSON = this.getCompletePolygonFromFeatureGroup(data.featureGroup);
|
|
20276
|
+
this.removeFeatureGroupInternal(data.featureGroup);
|
|
19926
20277
|
let result;
|
|
19927
|
-
switch (action) {
|
|
20278
|
+
switch (data.action) {
|
|
19928
20279
|
case "simplify": {
|
|
19929
20280
|
result = this.geometryManager.simplifyPolygon(completePolygonGeoJSON);
|
|
19930
20281
|
break;
|
|
@@ -19970,7 +20321,8 @@ class PolygonMutationManager {
|
|
|
19970
20321
|
* Add a polygon with optional merging logic
|
|
19971
20322
|
*/
|
|
19972
20323
|
async addPolygon(latlngs, options = {}) {
|
|
19973
|
-
const {
|
|
20324
|
+
const { noMerge = false } = options;
|
|
20325
|
+
const { simplify: simplify3 = true } = options;
|
|
19974
20326
|
try {
|
|
19975
20327
|
if (this.config.mergePolygons && !noMerge && this.getFeatureGroups().length > 0 && !this.config.kinks) {
|
|
19976
20328
|
return await this.mergePolygon(latlngs, options);
|
|
@@ -20095,9 +20447,11 @@ class PolygonMutationManager {
|
|
|
20095
20447
|
this.interactionManager.addMarkers(polyElement, featureGroup);
|
|
20096
20448
|
} else {
|
|
20097
20449
|
const holePolyline = L.polyline(polyElement, {
|
|
20098
|
-
color: this.config.
|
|
20450
|
+
color: this.config.colors.hole.border,
|
|
20099
20451
|
weight: this.config.holeOptions.weight || 2,
|
|
20100
|
-
opacity: this.config.holeOptions.opacity || 1
|
|
20452
|
+
opacity: this.config.holeOptions.opacity || 1,
|
|
20453
|
+
fillColor: this.config.colors.hole.fill,
|
|
20454
|
+
fillOpacity: this.config.holeOptions.fillOpacity || 0.5
|
|
20101
20455
|
});
|
|
20102
20456
|
featureGroup.addLayer(holePolyline);
|
|
20103
20457
|
this.interactionManager.addHoleMarkers(polyElement, featureGroup);
|
|
@@ -20148,18 +20502,23 @@ class PolygonMutationManager {
|
|
|
20148
20502
|
if (!firstFeature.geometry || !firstFeature.geometry.coordinates) {
|
|
20149
20503
|
return;
|
|
20150
20504
|
}
|
|
20151
|
-
if (firstFeature.geometry.coordinates
|
|
20152
|
-
firstFeature.geometry.coordinates.forEach(
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20505
|
+
if (this.isPositionArrayofArrays(firstFeature.geometry.coordinates)) {
|
|
20506
|
+
firstFeature.geometry.coordinates.forEach(
|
|
20507
|
+
(element) => {
|
|
20508
|
+
try {
|
|
20509
|
+
const feature2 = this.turfHelper.getMultiPolygon([element]);
|
|
20510
|
+
polyIntersection = this.geometryManager.checkPolygonIntersection(
|
|
20511
|
+
feature2,
|
|
20512
|
+
latlngs
|
|
20513
|
+
);
|
|
20514
|
+
if (polyIntersection) {
|
|
20515
|
+
intersectingFeatureGroups.push(featureGroup);
|
|
20516
|
+
polygonFeature.push(feature2);
|
|
20517
|
+
}
|
|
20518
|
+
} catch (error) {
|
|
20159
20519
|
}
|
|
20160
|
-
} catch (error) {
|
|
20161
20520
|
}
|
|
20162
|
-
|
|
20521
|
+
);
|
|
20163
20522
|
} else {
|
|
20164
20523
|
try {
|
|
20165
20524
|
const feature2 = this.turfHelper.getTurfPolygon(firstFeature);
|
|
@@ -20221,12 +20580,31 @@ class PolygonMutationManager {
|
|
|
20221
20580
|
};
|
|
20222
20581
|
}
|
|
20223
20582
|
}
|
|
20583
|
+
/**
|
|
20584
|
+
* Create a polygon from GeoJSON feature
|
|
20585
|
+
*/
|
|
20586
|
+
isPositionArrayofArrays(arr) {
|
|
20587
|
+
if (!Array.isArray(arr) || arr.length === 0) return false;
|
|
20588
|
+
const first = arr[0];
|
|
20589
|
+
if (!Array.isArray(first) || first.length === 0) return false;
|
|
20590
|
+
const second = first[0];
|
|
20591
|
+
if (!Array.isArray(second) || second.length === 0) return false;
|
|
20592
|
+
const leaf = second[0];
|
|
20593
|
+
return this.isPosition(leaf);
|
|
20594
|
+
}
|
|
20595
|
+
isPosition(val) {
|
|
20596
|
+
return Array.isArray(val) && val.length >= 2 && val.every((n) => typeof n === "number");
|
|
20597
|
+
}
|
|
20224
20598
|
/**
|
|
20225
20599
|
* Create a polygon from GeoJSON feature
|
|
20226
20600
|
*/
|
|
20227
20601
|
getPolygon(latlngs) {
|
|
20228
20602
|
const polygon2 = L.GeoJSON.geometryToLayer(latlngs);
|
|
20229
|
-
polygon2.setStyle(
|
|
20603
|
+
polygon2.setStyle({
|
|
20604
|
+
...this.config.polygonOptions,
|
|
20605
|
+
color: this.config.colors.polygon.border,
|
|
20606
|
+
fillColor: this.config.colors.polygon.fill
|
|
20607
|
+
});
|
|
20230
20608
|
polygon2._polydrawUniqueId = L.Util.stamp(polygon2) + "_" + Date.now();
|
|
20231
20609
|
delete polygon2._polydrawDragData;
|
|
20232
20610
|
delete polygon2._polydrawOriginalLatLngs;
|
|
@@ -20424,9 +20802,9 @@ class PolygonMutationManager {
|
|
|
20424
20802
|
ensureMarkerSeparation(polygonLength, markers2) {
|
|
20425
20803
|
var _a2, _b2, _c;
|
|
20426
20804
|
return {
|
|
20427
|
-
menu: ((_a2 = markers2.menu) == null ? void 0 : _a2.index)
|
|
20428
|
-
delete: ((_b2 = markers2.delete) == null ? void 0 : _b2.index)
|
|
20429
|
-
info: ((_c = markers2.info) == null ? void 0 : _c.index)
|
|
20805
|
+
menu: ((_a2 = markers2.menu) == null ? void 0 : _a2.index) ?? 0,
|
|
20806
|
+
delete: ((_b2 = markers2.delete) == null ? void 0 : _b2.index) ?? 1,
|
|
20807
|
+
info: ((_c = markers2.info) == null ? void 0 : _c.index) ?? 2
|
|
20430
20808
|
};
|
|
20431
20809
|
}
|
|
20432
20810
|
findAlternativeMarkerPosition(polygonLength, originalIndex, usedIndices) {
|
|
@@ -20534,6 +20912,21 @@ class PolygonMutationManager {
|
|
|
20534
20912
|
}
|
|
20535
20913
|
}
|
|
20536
20914
|
}
|
|
20915
|
+
function injectDynamicStyles(config) {
|
|
20916
|
+
const style = document.createElement("style");
|
|
20917
|
+
style.innerHTML = `
|
|
20918
|
+
.leaflet-control a { background-color: ${config.colors.styles.controlButton.backgroundColor}; color: ${config.colors.styles.controlButton.color}; display: flex; align-items: center; justify-content: center; }
|
|
20919
|
+
.leaflet-control a:hover { background-color: ${config.colors.styles.controlButtonHover.backgroundColor}; }
|
|
20920
|
+
.leaflet-control a.active { background-color: ${config.colors.styles.controlButtonActive.backgroundColor}; color: ${config.colors.styles.controlButtonActive.color}; }
|
|
20921
|
+
.polydraw-indicator-active { background-color: ${config.colors.styles.indicatorActive.backgroundColor} !important; }
|
|
20922
|
+
.crosshair-cursor-enabled { cursor: crosshair !important; }
|
|
20923
|
+
.crosshair-cursor-enabled * { cursor: crosshair !important; }
|
|
20924
|
+
.leaflet-polydraw-p2p-marker { background-color: ${config.colors.styles.p2pMarker.backgroundColor}; border: 2px solid ${config.colors.styles.p2pMarker.borderColor}; border-radius: 50%; box-sizing: border-box; }
|
|
20925
|
+
.leaflet-polydraw-p2p-first-marker { position: relative; }
|
|
20926
|
+
.leaflet-polydraw-p2p-first-marker:hover { transform: scale(1.5); transition: all 0.2s ease; }
|
|
20927
|
+
`;
|
|
20928
|
+
document.head.appendChild(style);
|
|
20929
|
+
}
|
|
20537
20930
|
class Polydraw extends L.Control {
|
|
20538
20931
|
constructor(options) {
|
|
20539
20932
|
super(options);
|
|
@@ -20558,133 +20951,38 @@ class Polydraw extends L.Control {
|
|
|
20558
20951
|
__publicField(this, "_boundTouchEnd");
|
|
20559
20952
|
__publicField(this, "_boundTouchStart");
|
|
20560
20953
|
/**
|
|
20561
|
-
*
|
|
20954
|
+
* Updates map interactions based on the current drawing mode.
|
|
20562
20955
|
*/
|
|
20563
|
-
__publicField(this, "
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20956
|
+
__publicField(this, "_handleActivateToggle", () => {
|
|
20957
|
+
const container = this.getContainer();
|
|
20958
|
+
if (!container) return;
|
|
20959
|
+
const activate = container.querySelector(".icon-activate");
|
|
20960
|
+
if (L.DomUtil.hasClass(activate, "active")) {
|
|
20961
|
+
L.DomUtil.removeClass(activate, "active");
|
|
20962
|
+
if (this.subContainer) {
|
|
20963
|
+
this.subContainer.style.maxHeight = "0px";
|
|
20964
|
+
}
|
|
20965
|
+
} else {
|
|
20966
|
+
L.DomUtil.addClass(activate, "active");
|
|
20967
|
+
if (this.subContainer) {
|
|
20968
|
+
this.subContainer.style.maxHeight = "250px";
|
|
20969
|
+
}
|
|
20570
20970
|
}
|
|
20971
|
+
this.updateActivateButtonIndicator();
|
|
20571
20972
|
});
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
const element = e.target;
|
|
20577
|
-
if (element) {
|
|
20578
|
-
element.style.backgroundColor = "";
|
|
20579
|
-
element.style.borderColor = "";
|
|
20580
|
-
element.classList.remove("edge-deletion-hover");
|
|
20973
|
+
__publicField(this, "_handleDrawClick", (e) => {
|
|
20974
|
+
if (e) {
|
|
20975
|
+
e.preventDefault();
|
|
20976
|
+
e.stopPropagation();
|
|
20581
20977
|
}
|
|
20582
|
-
|
|
20583
|
-
|
|
20584
|
-
|
|
20585
|
-
this.loadExternalConfig(options.configPath, options == null ? void 0 : options.config);
|
|
20586
|
-
} else {
|
|
20587
|
-
this.config = { ...defaultConfig, ...(options == null ? void 0 : options.config) || {} };
|
|
20588
|
-
this.initializeComponents();
|
|
20589
|
-
}
|
|
20590
|
-
}
|
|
20591
|
-
async loadExternalConfig(configPath, inlineConfig) {
|
|
20592
|
-
try {
|
|
20593
|
-
const response = await fetch(configPath);
|
|
20594
|
-
if (!response.ok) {
|
|
20595
|
-
throw new Error(
|
|
20596
|
-
`Failed to load config from ${configPath}: ${response.status} ${response.statusText}`
|
|
20597
|
-
);
|
|
20598
|
-
}
|
|
20599
|
-
const externalConfig = await response.json();
|
|
20600
|
-
this.config = {
|
|
20601
|
-
...defaultConfig,
|
|
20602
|
-
...externalConfig,
|
|
20603
|
-
...inlineConfig || {}
|
|
20604
|
-
};
|
|
20605
|
-
this.initializeComponents();
|
|
20606
|
-
} catch (error) {
|
|
20607
|
-
console.warn(
|
|
20608
|
-
"Failed to load external config, falling back to default + inline config:",
|
|
20609
|
-
error
|
|
20610
|
-
);
|
|
20611
|
-
this.config = { ...defaultConfig, ...inlineConfig || {} };
|
|
20612
|
-
this.initializeComponents();
|
|
20613
|
-
}
|
|
20614
|
-
}
|
|
20615
|
-
initializeComponents() {
|
|
20616
|
-
this.turfHelper = new TurfHelper(this.config);
|
|
20617
|
-
this.mapStateService = new MapStateService();
|
|
20618
|
-
this.eventManager = new EventManager();
|
|
20619
|
-
this.polygonInformation = new PolygonInformationService(this.mapStateService);
|
|
20620
|
-
this.modeManager = new ModeManager(this.config, this.eventManager);
|
|
20621
|
-
this.polygonInformation.onPolygonInfoUpdated((_k) => {
|
|
20622
|
-
this.updateActivateButtonIndicator();
|
|
20623
|
-
});
|
|
20624
|
-
this._boundKeyDownHandler = this.handleKeyDown.bind(this);
|
|
20625
|
-
this.polygonMutationManager = null;
|
|
20626
|
-
this.polygonDrawManager = null;
|
|
20627
|
-
}
|
|
20628
|
-
onAdd(_map) {
|
|
20629
|
-
_map._onResize = () => {
|
|
20630
|
-
};
|
|
20631
|
-
if (L.Browser.touch && L.Browser.mobile) {
|
|
20632
|
-
_map.tap = false;
|
|
20633
|
-
}
|
|
20634
|
-
this.map = _map;
|
|
20635
|
-
const style = document.createElement("style");
|
|
20636
|
-
style.innerHTML = `
|
|
20637
|
-
.leaflet-control a { background-color: #fff; color: #000; display: flex; align-items: center; justify-content: center; }
|
|
20638
|
-
.leaflet-control a:hover { background-color: #f4f4f4; }
|
|
20639
|
-
.leaflet-control a.active { background-color:rgb(128, 218, 255); color: #fff; }
|
|
20640
|
-
.polydraw-indicator-active { background-color: #ffcc00 !important; }
|
|
20641
|
-
.crosshair-cursor-enabled { cursor: crosshair !important; }
|
|
20642
|
-
.crosshair-cursor-enabled * { cursor: crosshair !important; }
|
|
20643
|
-
.leaflet-polydraw-p2p-marker { background-color: #fff; border: 2px solid #50622b; border-radius: 50%; box-sizing: border-box; }
|
|
20644
|
-
.leaflet-polydraw-p2p-first-marker { position: relative; }
|
|
20645
|
-
.leaflet-polydraw-p2p-first-marker:hover { transform: scale(1.5); transition: all 0.2s ease; }
|
|
20646
|
-
`;
|
|
20647
|
-
document.head.appendChild(style);
|
|
20648
|
-
this.setupKeyboardHandlers();
|
|
20649
|
-
const container = L.DomUtil.create("div", "leaflet-control leaflet-bar");
|
|
20650
|
-
L.DomEvent.disableClickPropagation(container);
|
|
20651
|
-
L.DomEvent.on(container, "mousedown", L.DomEvent.stopPropagation);
|
|
20652
|
-
L.DomEvent.on(container, "touchstart", L.DomEvent.stopPropagation);
|
|
20653
|
-
L.DomEvent.on(container, "click", L.DomEvent.stopPropagation);
|
|
20654
|
-
container.style.display = "flex";
|
|
20655
|
-
container.style.flexDirection = "column-reverse";
|
|
20656
|
-
this.subContainer = L.DomUtil.create("div", "sub-buttons", container);
|
|
20657
|
-
this.subContainer.style.maxHeight = "0px";
|
|
20658
|
-
this.subContainer.style.overflow = "hidden";
|
|
20659
|
-
this.subContainer.style.transition = "max-height 0.3s ease";
|
|
20660
|
-
const onActivateToggle = () => {
|
|
20661
|
-
const activate = container.querySelector(".icon-activate");
|
|
20662
|
-
if (L.DomUtil.hasClass(activate, "active")) {
|
|
20663
|
-
L.DomUtil.removeClass(activate, "active");
|
|
20664
|
-
if (this.subContainer) {
|
|
20665
|
-
this.subContainer.style.maxHeight = "0px";
|
|
20666
|
-
}
|
|
20667
|
-
} else {
|
|
20668
|
-
L.DomUtil.addClass(activate, "active");
|
|
20669
|
-
if (this.subContainer) {
|
|
20670
|
-
this.subContainer.style.maxHeight = "250px";
|
|
20671
|
-
}
|
|
20672
|
-
}
|
|
20673
|
-
this.updateActivateButtonIndicator();
|
|
20674
|
-
};
|
|
20675
|
-
const onDrawClick = (e) => {
|
|
20676
|
-
if (e) {
|
|
20677
|
-
e.preventDefault();
|
|
20678
|
-
e.stopPropagation();
|
|
20679
|
-
}
|
|
20680
|
-
if (this.modeManager.getCurrentMode() === DrawMode.Add) {
|
|
20681
|
-
this.setDrawMode(DrawMode.Off);
|
|
20682
|
-
return;
|
|
20978
|
+
if (this.modeManager.getCurrentMode() === DrawMode.Add) {
|
|
20979
|
+
this.setDrawMode(DrawMode.Off);
|
|
20980
|
+
return;
|
|
20683
20981
|
}
|
|
20684
20982
|
this.setDrawMode(DrawMode.Add);
|
|
20685
20983
|
this.polygonInformation.saveCurrentState();
|
|
20686
|
-
};
|
|
20687
|
-
|
|
20984
|
+
});
|
|
20985
|
+
__publicField(this, "_handleSubtractClick", (e) => {
|
|
20688
20986
|
if (e) {
|
|
20689
20987
|
e.preventDefault();
|
|
20690
20988
|
e.stopPropagation();
|
|
@@ -20695,8 +20993,8 @@ class Polydraw extends L.Control {
|
|
|
20695
20993
|
}
|
|
20696
20994
|
this.setDrawMode(DrawMode.Subtract);
|
|
20697
20995
|
this.polygonInformation.saveCurrentState();
|
|
20698
|
-
};
|
|
20699
|
-
|
|
20996
|
+
});
|
|
20997
|
+
__publicField(this, "_handleEraseClick", (e) => {
|
|
20700
20998
|
this.map.closePopup();
|
|
20701
20999
|
if (e) {
|
|
20702
21000
|
e.preventDefault();
|
|
@@ -20706,8 +21004,8 @@ class Polydraw extends L.Control {
|
|
|
20706
21004
|
return;
|
|
20707
21005
|
}
|
|
20708
21006
|
this.removeAllFeatureGroups();
|
|
20709
|
-
};
|
|
20710
|
-
|
|
21007
|
+
});
|
|
21008
|
+
__publicField(this, "_handlePointToPointClick", (e) => {
|
|
20711
21009
|
if (e) {
|
|
20712
21010
|
e.preventDefault();
|
|
20713
21011
|
e.stopPropagation();
|
|
@@ -20718,16 +21016,213 @@ class Polydraw extends L.Control {
|
|
|
20718
21016
|
}
|
|
20719
21017
|
this.setDrawMode(DrawMode.PointToPoint);
|
|
20720
21018
|
this.polygonInformation.saveCurrentState();
|
|
21019
|
+
});
|
|
21020
|
+
/**
|
|
21021
|
+
* Handle marker hover when modifier key is held - event handler version
|
|
21022
|
+
*/
|
|
21023
|
+
__publicField(this, "onMarkerHoverForEdgeDeletionEvent", (e) => {
|
|
21024
|
+
if (!this.isModifierKeyHeld) return;
|
|
21025
|
+
const element = e.target;
|
|
21026
|
+
if (element) {
|
|
21027
|
+
element.style.backgroundColor = this.config.colors.edgeDeletion.hover;
|
|
21028
|
+
element.style.borderColor = this.config.colors.edgeDeletion.hover;
|
|
21029
|
+
element.classList.add("edge-deletion-hover");
|
|
21030
|
+
}
|
|
21031
|
+
});
|
|
21032
|
+
/**
|
|
21033
|
+
* Handle marker leave when modifier key is held - event handler version
|
|
21034
|
+
*/
|
|
21035
|
+
__publicField(this, "onMarkerLeaveForEdgeDeletionEvent", (e) => {
|
|
21036
|
+
const element = e.target;
|
|
21037
|
+
if (element) {
|
|
21038
|
+
element.style.backgroundColor = "";
|
|
21039
|
+
element.style.borderColor = "";
|
|
21040
|
+
element.classList.remove("edge-deletion-hover");
|
|
21041
|
+
}
|
|
21042
|
+
});
|
|
21043
|
+
this.config = defaultConfig;
|
|
21044
|
+
if (options == null ? void 0 : options.configPath) {
|
|
21045
|
+
this.loadExternalConfig(options.configPath, options == null ? void 0 : options.config);
|
|
21046
|
+
} else {
|
|
21047
|
+
this.config = { ...defaultConfig, ...(options == null ? void 0 : options.config) || {} };
|
|
21048
|
+
this.initializeComponents();
|
|
21049
|
+
}
|
|
21050
|
+
}
|
|
21051
|
+
/**
|
|
21052
|
+
* Method called when the control is added to the map.
|
|
21053
|
+
* It initializes the control, creates the UI, and sets up event listeners.
|
|
21054
|
+
* @param _map - The map instance.
|
|
21055
|
+
* @returns The control's container element.
|
|
21056
|
+
*/
|
|
21057
|
+
onAdd(_map) {
|
|
21058
|
+
const extendedMap = _map;
|
|
21059
|
+
const browser = L.Browser;
|
|
21060
|
+
extendedMap._onResize = () => {
|
|
20721
21061
|
};
|
|
21062
|
+
if (browser.touch && browser.mobile) {
|
|
21063
|
+
extendedMap.tap = false;
|
|
21064
|
+
}
|
|
21065
|
+
this.map = _map;
|
|
21066
|
+
this.setupKeyboardHandlers();
|
|
21067
|
+
const container = L.DomUtil.create("div", "leaflet-control leaflet-bar");
|
|
21068
|
+
this.initializeUI(container);
|
|
21069
|
+
this.createTracer();
|
|
21070
|
+
this.initializeManagers();
|
|
21071
|
+
this.setupEventListeners();
|
|
21072
|
+
return container;
|
|
21073
|
+
}
|
|
21074
|
+
/**
|
|
21075
|
+
* Method called when the control is removed from the map.
|
|
21076
|
+
* It handles the cleanup of layers, events, and handlers.
|
|
21077
|
+
* @param _map - The map instance, unused but required by the L.Control interface.
|
|
21078
|
+
*/
|
|
21079
|
+
onRemove(_map) {
|
|
21080
|
+
this.removeKeyboardHandlers();
|
|
21081
|
+
if (this.tracer) {
|
|
21082
|
+
this.map.removeLayer(this.tracer);
|
|
21083
|
+
}
|
|
21084
|
+
this.removeAllFeatureGroups();
|
|
21085
|
+
}
|
|
21086
|
+
/**
|
|
21087
|
+
* Adds the control to the given map.
|
|
21088
|
+
* @param map - The map instance.
|
|
21089
|
+
* @returns The current instance of the control.
|
|
21090
|
+
*/
|
|
21091
|
+
addTo(map) {
|
|
21092
|
+
super.addTo(map);
|
|
21093
|
+
return this;
|
|
21094
|
+
}
|
|
21095
|
+
/**
|
|
21096
|
+
* Returns the array of feature groups currently managed by the control.
|
|
21097
|
+
* @returns An array of L.FeatureGroup objects.
|
|
21098
|
+
*/
|
|
21099
|
+
getFeatureGroups() {
|
|
21100
|
+
return this.arrayOfFeatureGroups;
|
|
21101
|
+
}
|
|
21102
|
+
/**
|
|
21103
|
+
* Adds a predefined polygon to the map.
|
|
21104
|
+
* @param geographicBorders - An array of LatLng arrays representing the polygon's coordinates.
|
|
21105
|
+
* @param options - Optional parameters, including visual optimization level.
|
|
21106
|
+
*/
|
|
21107
|
+
async addPredefinedPolygon(geographicBorders, options) {
|
|
21108
|
+
if (!geographicBorders || geographicBorders.length === 0) {
|
|
21109
|
+
throw new Error("Cannot add empty polygon array");
|
|
21110
|
+
}
|
|
21111
|
+
if (!this.map) {
|
|
21112
|
+
throw new Error("Map not initialized");
|
|
21113
|
+
}
|
|
21114
|
+
if (!this.polygonMutationManager) {
|
|
21115
|
+
throw new Error("PolygonMutationManager not initialized");
|
|
21116
|
+
}
|
|
21117
|
+
const visualOptimizationLevel = (options == null ? void 0 : options.visualOptimizationLevel) ?? 0;
|
|
21118
|
+
for (const [groupIndex, group] of geographicBorders.entries()) {
|
|
21119
|
+
if (!group || !group[0] || group[0].length < 4) {
|
|
21120
|
+
throw new Error(
|
|
21121
|
+
`Invalid polygon data at index ${groupIndex}: A polygon must have at least 3 unique vertices.`
|
|
21122
|
+
);
|
|
21123
|
+
}
|
|
21124
|
+
try {
|
|
21125
|
+
const coords = group.map((ring) => ring.map((latlng) => [latlng.lng, latlng.lat]));
|
|
21126
|
+
const polygon2 = this.turfHelper.getMultiPolygon([coords]);
|
|
21127
|
+
const result = await this.polygonMutationManager.addPolygon(polygon2, {
|
|
21128
|
+
simplify: false,
|
|
21129
|
+
noMerge: false,
|
|
21130
|
+
visualOptimizationLevel
|
|
21131
|
+
});
|
|
21132
|
+
if (!result.success) {
|
|
21133
|
+
console.error("Error adding polygon via manager:", result.error);
|
|
21134
|
+
throw new Error(result.error || "Failed to add polygon");
|
|
21135
|
+
}
|
|
21136
|
+
this.polygonInformation.createPolygonInformationStorage(this.arrayOfFeatureGroups);
|
|
21137
|
+
} catch (error) {
|
|
21138
|
+
console.error("Error adding auto polygon:", error);
|
|
21139
|
+
throw error;
|
|
21140
|
+
}
|
|
21141
|
+
}
|
|
21142
|
+
}
|
|
21143
|
+
/**
|
|
21144
|
+
* Sets the current drawing mode.
|
|
21145
|
+
* @param mode - The drawing mode to set.
|
|
21146
|
+
*/
|
|
21147
|
+
setDrawMode(mode) {
|
|
21148
|
+
const previousMode = this.drawMode;
|
|
21149
|
+
this._updateDrawModeState(mode);
|
|
21150
|
+
if (previousMode === DrawMode.PointToPoint && mode !== DrawMode.PointToPoint) {
|
|
21151
|
+
this.polygonDrawManager.clearP2pMarkers();
|
|
21152
|
+
this.stopDraw();
|
|
21153
|
+
} else if (mode === DrawMode.Off) {
|
|
21154
|
+
this.stopDraw();
|
|
21155
|
+
} else if (mode !== DrawMode.PointToPoint) {
|
|
21156
|
+
this.stopDraw();
|
|
21157
|
+
}
|
|
21158
|
+
if (this.map) {
|
|
21159
|
+
this._updateUIAfterDrawModeChange(mode);
|
|
21160
|
+
this._updateMapInteractions();
|
|
21161
|
+
}
|
|
21162
|
+
}
|
|
21163
|
+
/**
|
|
21164
|
+
* Returns the current drawing mode.
|
|
21165
|
+
* @returns The current DrawMode.
|
|
21166
|
+
*/
|
|
21167
|
+
getDrawMode() {
|
|
21168
|
+
return this.modeManager.getCurrentMode();
|
|
21169
|
+
}
|
|
21170
|
+
/**
|
|
21171
|
+
* Registers an event listener for a given event type.
|
|
21172
|
+
* @param event - The event type to listen for.
|
|
21173
|
+
* @param callback - The callback function to execute when the event is triggered.
|
|
21174
|
+
*/
|
|
21175
|
+
on(event, callback) {
|
|
21176
|
+
this.eventManager.on(event, callback);
|
|
21177
|
+
}
|
|
21178
|
+
/**
|
|
21179
|
+
* Unregisters an event listener for a given event type.
|
|
21180
|
+
* @param event - The event type to stop listening for.
|
|
21181
|
+
* @param callback - The callback function to remove.
|
|
21182
|
+
*/
|
|
21183
|
+
off(event, callback) {
|
|
21184
|
+
this.eventManager.off(event, callback);
|
|
21185
|
+
}
|
|
21186
|
+
/**
|
|
21187
|
+
* Removes all feature groups from the map and clears the internal storage.
|
|
21188
|
+
*/
|
|
21189
|
+
removeAllFeatureGroups() {
|
|
21190
|
+
this.arrayOfFeatureGroups.forEach((featureGroups) => {
|
|
21191
|
+
try {
|
|
21192
|
+
this.map.removeLayer(featureGroups);
|
|
21193
|
+
} catch (error) {
|
|
21194
|
+
}
|
|
21195
|
+
});
|
|
21196
|
+
this.arrayOfFeatureGroups.length = 0;
|
|
21197
|
+
this.polygonInformation.deletePolygonInformationStorage();
|
|
21198
|
+
this.polygonInformation.updatePolygons();
|
|
21199
|
+
this.updateActivateButtonIndicator();
|
|
21200
|
+
}
|
|
21201
|
+
/**
|
|
21202
|
+
* Initializes the user interface, creates DOM elements, sets up buttons, and injects styles.
|
|
21203
|
+
* @param container - The main control container element.
|
|
21204
|
+
*/
|
|
21205
|
+
initializeUI(container) {
|
|
21206
|
+
injectDynamicStyles(this.config);
|
|
21207
|
+
L.DomEvent.disableClickPropagation(container);
|
|
21208
|
+
L.DomEvent.on(container, "mousedown", L.DomEvent.stopPropagation);
|
|
21209
|
+
L.DomEvent.on(container, "touchstart", L.DomEvent.stopPropagation);
|
|
21210
|
+
L.DomEvent.on(container, "click", L.DomEvent.stopPropagation);
|
|
21211
|
+
container.style.display = "flex";
|
|
21212
|
+
container.style.flexDirection = "column-reverse";
|
|
21213
|
+
this.subContainer = L.DomUtil.create("div", "sub-buttons", container);
|
|
21214
|
+
this.subContainer.style.maxHeight = "0px";
|
|
21215
|
+
this.subContainer.style.overflow = "hidden";
|
|
21216
|
+
this.subContainer.style.transition = "max-height 0.3s ease";
|
|
20722
21217
|
createButtons(
|
|
20723
21218
|
container,
|
|
20724
21219
|
this.subContainer,
|
|
20725
21220
|
this.config,
|
|
20726
|
-
|
|
20727
|
-
|
|
20728
|
-
|
|
20729
|
-
|
|
20730
|
-
|
|
21221
|
+
this._handleActivateToggle,
|
|
21222
|
+
this._handleDrawClick,
|
|
21223
|
+
this._handleSubtractClick,
|
|
21224
|
+
this._handleEraseClick,
|
|
21225
|
+
this._handlePointToPointClick
|
|
20731
21226
|
);
|
|
20732
21227
|
const uiUpdateListener = (mode) => {
|
|
20733
21228
|
const drawButton = container.querySelector(".icon-draw");
|
|
@@ -20736,28 +21231,11 @@ class Polydraw extends L.Control {
|
|
|
20736
21231
|
if (subtractButton) subtractButton.classList.toggle("active", mode === DrawMode.Subtract);
|
|
20737
21232
|
};
|
|
20738
21233
|
this.drawModeListeners.push(uiUpdateListener);
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20743
|
-
|
|
20744
|
-
this.polygonDrawManager = new PolygonDrawManager({
|
|
20745
|
-
turfHelper: this.turfHelper,
|
|
20746
|
-
map: this.map,
|
|
20747
|
-
config: this.config,
|
|
20748
|
-
modeManager: this.modeManager,
|
|
20749
|
-
eventManager: this.eventManager,
|
|
20750
|
-
tracer: this.tracer
|
|
20751
|
-
});
|
|
20752
|
-
this.polygonMutationManager = new PolygonMutationManager({
|
|
20753
|
-
turfHelper: this.turfHelper,
|
|
20754
|
-
polygonInformation: this.polygonInformation,
|
|
20755
|
-
map: this.map,
|
|
20756
|
-
config: this.config,
|
|
20757
|
-
modeManager: this.modeManager,
|
|
20758
|
-
eventManager: this.eventManager,
|
|
20759
|
-
getFeatureGroups: () => this.arrayOfFeatureGroups
|
|
20760
|
-
});
|
|
21234
|
+
}
|
|
21235
|
+
/**
|
|
21236
|
+
* Attaches listeners to polygonMutationManager and eventManager.
|
|
21237
|
+
*/
|
|
21238
|
+
setupEventListeners() {
|
|
20761
21239
|
this.polygonMutationManager.on("polygonOperationComplete", (data) => {
|
|
20762
21240
|
this.updateActivateButtonIndicator();
|
|
20763
21241
|
this.modeManager.updateStateForMode(DrawMode.Off);
|
|
@@ -20799,123 +21277,147 @@ class Polydraw extends L.Control {
|
|
|
20799
21277
|
this.stopDraw();
|
|
20800
21278
|
this.setDrawMode(DrawMode.Off);
|
|
20801
21279
|
});
|
|
20802
|
-
return container;
|
|
20803
21280
|
}
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20810
|
-
|
|
20811
|
-
|
|
20812
|
-
|
|
20813
|
-
|
|
20814
|
-
|
|
21281
|
+
/**
|
|
21282
|
+
* Initializes and adds the tracer polyline to the map.
|
|
21283
|
+
*/
|
|
21284
|
+
createTracer() {
|
|
21285
|
+
this.tracer = L.polyline([], {
|
|
21286
|
+
...this.config.polyLineOptions,
|
|
21287
|
+
color: this.config.colors.polyline
|
|
21288
|
+
});
|
|
21289
|
+
try {
|
|
21290
|
+
this.tracer.addTo(this.map);
|
|
21291
|
+
} catch (error) {
|
|
20815
21292
|
}
|
|
20816
|
-
this.removeAllFeatureGroups();
|
|
20817
21293
|
}
|
|
20818
|
-
|
|
20819
|
-
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
|
|
20829
|
-
|
|
20830
|
-
|
|
20831
|
-
|
|
20832
|
-
|
|
20833
|
-
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
20838
|
-
|
|
20839
|
-
|
|
20840
|
-
|
|
20841
|
-
|
|
20842
|
-
|
|
20843
|
-
|
|
20844
|
-
|
|
20845
|
-
|
|
20846
|
-
|
|
20847
|
-
|
|
20848
|
-
|
|
20849
|
-
|
|
20850
|
-
|
|
21294
|
+
/**
|
|
21295
|
+
* Sets up PolygonDrawManager and PolygonMutationManager with the map.
|
|
21296
|
+
*/
|
|
21297
|
+
initializeManagers() {
|
|
21298
|
+
this.polygonDrawManager = new PolygonDrawManager({
|
|
21299
|
+
turfHelper: this.turfHelper,
|
|
21300
|
+
map: this.map,
|
|
21301
|
+
config: this.config,
|
|
21302
|
+
modeManager: this.modeManager,
|
|
21303
|
+
eventManager: this.eventManager,
|
|
21304
|
+
tracer: this.tracer
|
|
21305
|
+
});
|
|
21306
|
+
this.polygonMutationManager = new PolygonMutationManager({
|
|
21307
|
+
turfHelper: this.turfHelper,
|
|
21308
|
+
polygonInformation: this.polygonInformation,
|
|
21309
|
+
map: this.map,
|
|
21310
|
+
config: this.config,
|
|
21311
|
+
modeManager: this.modeManager,
|
|
21312
|
+
eventManager: this.eventManager,
|
|
21313
|
+
getFeatureGroups: () => this.arrayOfFeatureGroups
|
|
21314
|
+
});
|
|
21315
|
+
}
|
|
21316
|
+
/**
|
|
21317
|
+
* Loads an external configuration file and merges it with the default and inline configs.
|
|
21318
|
+
* @param configPath - The path to the external configuration file.
|
|
21319
|
+
* @param inlineConfig - An optional inline configuration object.
|
|
21320
|
+
*/
|
|
21321
|
+
async loadExternalConfig(configPath, inlineConfig) {
|
|
21322
|
+
try {
|
|
21323
|
+
const response = await fetch(configPath);
|
|
21324
|
+
if (!response.ok) {
|
|
21325
|
+
throw new Error(
|
|
21326
|
+
`Failed to load config from ${configPath}: ${response.status} ${response.statusText}`
|
|
21327
|
+
);
|
|
20851
21328
|
}
|
|
21329
|
+
const externalConfig = await response.json();
|
|
21330
|
+
this.config = {
|
|
21331
|
+
...defaultConfig,
|
|
21332
|
+
...externalConfig,
|
|
21333
|
+
...inlineConfig || {}
|
|
21334
|
+
};
|
|
21335
|
+
this.initializeComponents();
|
|
21336
|
+
} catch (error) {
|
|
21337
|
+
console.warn(
|
|
21338
|
+
"Failed to load external config, falling back to default + inline config:",
|
|
21339
|
+
error
|
|
21340
|
+
);
|
|
21341
|
+
this.config = { ...defaultConfig, ...inlineConfig || {} };
|
|
21342
|
+
this.initializeComponents();
|
|
20852
21343
|
}
|
|
20853
21344
|
}
|
|
20854
|
-
|
|
20855
|
-
|
|
21345
|
+
/**
|
|
21346
|
+
* Initializes the core components of the Polydraw control.
|
|
21347
|
+
*/
|
|
21348
|
+
/**
|
|
21349
|
+
* Updates the state of the drawing mode.
|
|
21350
|
+
* @param mode - The new drawing mode.
|
|
21351
|
+
*/
|
|
21352
|
+
_updateDrawModeState(mode) {
|
|
20856
21353
|
this.drawMode = mode;
|
|
20857
21354
|
this.modeManager.updateStateForMode(mode);
|
|
20858
21355
|
this.emitDrawModeChanged();
|
|
20859
21356
|
this.updateMarkerDraggableState();
|
|
20860
|
-
|
|
20861
|
-
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
20865
|
-
|
|
20866
|
-
|
|
21357
|
+
}
|
|
21358
|
+
/**
|
|
21359
|
+
* Updates the UI after a change in the drawing mode.
|
|
21360
|
+
* @param mode - The new drawing mode.
|
|
21361
|
+
*/
|
|
21362
|
+
_updateUIAfterDrawModeChange(mode) {
|
|
21363
|
+
const shouldShowCrosshair = this.modeManager.shouldShowCrosshairCursor();
|
|
21364
|
+
if (shouldShowCrosshair) {
|
|
21365
|
+
L.DomUtil.addClass(this.map.getContainer(), "crosshair-cursor-enabled");
|
|
21366
|
+
} else {
|
|
21367
|
+
L.DomUtil.removeClass(this.map.getContainer(), "crosshair-cursor-enabled");
|
|
20867
21368
|
}
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
this.
|
|
20883
|
-
|
|
20884
|
-
|
|
20885
|
-
|
|
20886
|
-
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
color: "#D9460F",
|
|
20894
|
-
dashArray: null
|
|
20895
|
-
// Reset to solid line
|
|
20896
|
-
});
|
|
20897
|
-
break;
|
|
20898
|
-
case DrawMode.PointToPoint:
|
|
20899
|
-
this.tracer.setStyle({
|
|
20900
|
-
color: defaultConfig.polyLineOptions.color,
|
|
20901
|
-
dashArray: "5, 5"
|
|
20902
|
-
});
|
|
20903
|
-
break;
|
|
20904
|
-
}
|
|
20905
|
-
} catch (error) {
|
|
21369
|
+
try {
|
|
21370
|
+
switch (mode) {
|
|
21371
|
+
case DrawMode.Off:
|
|
21372
|
+
this.tracer.setStyle({ color: "" });
|
|
21373
|
+
break;
|
|
21374
|
+
case DrawMode.Add:
|
|
21375
|
+
this.tracer.setStyle({
|
|
21376
|
+
color: this.config.colors.polyline,
|
|
21377
|
+
dashArray: null
|
|
21378
|
+
// Reset to solid line
|
|
21379
|
+
});
|
|
21380
|
+
break;
|
|
21381
|
+
case DrawMode.Subtract:
|
|
21382
|
+
this.tracer.setStyle({
|
|
21383
|
+
color: this.config.colors.subtractLine,
|
|
21384
|
+
dashArray: null
|
|
21385
|
+
// Reset to solid line
|
|
21386
|
+
});
|
|
21387
|
+
break;
|
|
21388
|
+
case DrawMode.PointToPoint:
|
|
21389
|
+
this.tracer.setStyle({
|
|
21390
|
+
color: this.config.colors.polyline,
|
|
21391
|
+
dashArray: "5, 5"
|
|
21392
|
+
});
|
|
21393
|
+
break;
|
|
20906
21394
|
}
|
|
20907
|
-
|
|
21395
|
+
} catch (error) {
|
|
20908
21396
|
}
|
|
20909
21397
|
}
|
|
20910
|
-
|
|
20911
|
-
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
this.
|
|
21398
|
+
_updateMapInteractions() {
|
|
21399
|
+
const mapDragEnabled = this.modeManager.canPerformAction("mapDrag");
|
|
21400
|
+
const mapZoomEnabled = this.modeManager.canPerformAction("mapZoom");
|
|
21401
|
+
const mapDoubleClickEnabled = this.modeManager.canPerformAction("mapDoubleClickZoom");
|
|
21402
|
+
this.events(this.drawMode !== DrawMode.Off);
|
|
21403
|
+
this.setLeafletMapEvents(mapDragEnabled, mapDoubleClickEnabled, mapZoomEnabled);
|
|
20915
21404
|
}
|
|
20916
|
-
|
|
20917
|
-
this.
|
|
21405
|
+
initializeComponents() {
|
|
21406
|
+
this.turfHelper = new TurfHelper(this.config);
|
|
21407
|
+
this.mapStateService = new MapStateService();
|
|
21408
|
+
this.eventManager = new EventManager();
|
|
21409
|
+
this.polygonInformation = new PolygonInformationService(this.mapStateService);
|
|
21410
|
+
this.modeManager = new ModeManager(this.config, this.eventManager);
|
|
21411
|
+
this.polygonInformation.onPolygonInfoUpdated((_k) => {
|
|
21412
|
+
this.updateActivateButtonIndicator();
|
|
21413
|
+
});
|
|
21414
|
+
this._boundKeyDownHandler = this.handleKeyDown.bind(this);
|
|
21415
|
+
this.polygonMutationManager = null;
|
|
21416
|
+
this.polygonDrawManager = null;
|
|
20918
21417
|
}
|
|
21418
|
+
/**
|
|
21419
|
+
* Emits an event to notify listeners that the drawing mode has changed.
|
|
21420
|
+
*/
|
|
20919
21421
|
emitDrawModeChanged() {
|
|
20920
21422
|
this.eventManager.emit("polydraw:mode:change", {
|
|
20921
21423
|
mode: this.modeManager.getCurrentMode()
|
|
@@ -20948,30 +21450,34 @@ class Polydraw extends L.Control {
|
|
|
20948
21450
|
});
|
|
20949
21451
|
});
|
|
20950
21452
|
}
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
this.map.removeLayer(featureGroups);
|
|
20955
|
-
} catch (error) {
|
|
20956
|
-
}
|
|
20957
|
-
});
|
|
20958
|
-
this.arrayOfFeatureGroups.length = 0;
|
|
20959
|
-
this.polygonInformation.deletePolygonInformationStorage();
|
|
20960
|
-
this.polygonInformation.updatePolygons();
|
|
20961
|
-
this.updateActivateButtonIndicator();
|
|
20962
|
-
}
|
|
21453
|
+
/**
|
|
21454
|
+
* Stops the current drawing operation and resets the tracer.
|
|
21455
|
+
*/
|
|
20963
21456
|
stopDraw() {
|
|
20964
21457
|
this.resetTracker();
|
|
20965
21458
|
this.drawStartedEvents(false);
|
|
20966
21459
|
}
|
|
21460
|
+
/**
|
|
21461
|
+
* Enables or disables Leaflet's default map interactions.
|
|
21462
|
+
* @param enableDragging - Whether to enable map dragging.
|
|
21463
|
+
* @param enableDoubleClickZoom - Whether to enable double-click zoom.
|
|
21464
|
+
* @param enableScrollWheelZoom - Whether to enable scroll wheel zoom.
|
|
21465
|
+
*/
|
|
20967
21466
|
setLeafletMapEvents(enableDragging, enableDoubleClickZoom, enableScrollWheelZoom) {
|
|
20968
21467
|
enableDragging ? this.map.dragging.enable() : this.map.dragging.disable();
|
|
20969
21468
|
enableDoubleClickZoom ? this.map.doubleClickZoom.enable() : this.map.doubleClickZoom.disable();
|
|
20970
21469
|
enableScrollWheelZoom ? this.map.scrollWheelZoom.enable() : this.map.scrollWheelZoom.disable();
|
|
20971
21470
|
}
|
|
21471
|
+
/**
|
|
21472
|
+
* Resets the tracer polyline by clearing its LatLngs.
|
|
21473
|
+
*/
|
|
20972
21474
|
resetTracker() {
|
|
20973
21475
|
this.tracer.setLatLngs([]);
|
|
20974
21476
|
}
|
|
21477
|
+
/**
|
|
21478
|
+
* Attaches or detaches the mouse move and mouse up event listeners for drawing.
|
|
21479
|
+
* @param onoff - A boolean indicating whether to attach or detach the events.
|
|
21480
|
+
*/
|
|
20975
21481
|
drawStartedEvents(onoff) {
|
|
20976
21482
|
const onoroff = onoff ? "on" : "off";
|
|
20977
21483
|
this.map[onoroff]("mousemove", this.mouseMove, this);
|
|
@@ -20990,6 +21496,57 @@ class Polydraw extends L.Control {
|
|
|
20990
21496
|
}
|
|
20991
21497
|
}
|
|
20992
21498
|
}
|
|
21499
|
+
/**
|
|
21500
|
+
* Attaches or detaches the main drawing event listeners.
|
|
21501
|
+
* @param onoff - A boolean indicating whether to attach or detach the events.
|
|
21502
|
+
*/
|
|
21503
|
+
events(onoff) {
|
|
21504
|
+
const onoroff = onoff ? "on" : "off";
|
|
21505
|
+
this.map[onoroff]("mousedown", this.mouseDown, this);
|
|
21506
|
+
this.map[onoroff]("dblclick", this.handleDoubleClick, this);
|
|
21507
|
+
if (onoff) {
|
|
21508
|
+
this._boundTouchStart = (e) => this.mouseDown(e);
|
|
21509
|
+
this.map.getContainer().addEventListener("touchstart", this._boundTouchStart, { passive: false });
|
|
21510
|
+
} else {
|
|
21511
|
+
if (this._boundTouchStart) {
|
|
21512
|
+
this.map.getContainer().removeEventListener("touchstart", this._boundTouchStart);
|
|
21513
|
+
}
|
|
21514
|
+
}
|
|
21515
|
+
}
|
|
21516
|
+
/**
|
|
21517
|
+
* Handles the mouse down event to start a drawing operation.
|
|
21518
|
+
* @param event - The mouse or touch event.
|
|
21519
|
+
*/
|
|
21520
|
+
mouseDown(event) {
|
|
21521
|
+
if ("cancelable" in event && event.cancelable) {
|
|
21522
|
+
event.preventDefault();
|
|
21523
|
+
}
|
|
21524
|
+
if (this.modeManager.isInOffMode()) {
|
|
21525
|
+
return;
|
|
21526
|
+
}
|
|
21527
|
+
let clickLatLng;
|
|
21528
|
+
if ("latlng" in event && event.latlng) {
|
|
21529
|
+
clickLatLng = event.latlng;
|
|
21530
|
+
} else if ("touches" in event && event.touches && event.touches.length > 0) {
|
|
21531
|
+
clickLatLng = this.map.containerPointToLatLng([
|
|
21532
|
+
event.touches[0].clientX,
|
|
21533
|
+
event.touches[0].clientY
|
|
21534
|
+
]);
|
|
21535
|
+
}
|
|
21536
|
+
if (!clickLatLng) {
|
|
21537
|
+
return;
|
|
21538
|
+
}
|
|
21539
|
+
if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint) {
|
|
21540
|
+
this.polygonDrawManager.handlePointToPointClick(clickLatLng);
|
|
21541
|
+
return;
|
|
21542
|
+
}
|
|
21543
|
+
this.tracer.setLatLngs([clickLatLng]);
|
|
21544
|
+
this.startDraw();
|
|
21545
|
+
}
|
|
21546
|
+
/**
|
|
21547
|
+
* Handles the mouse move event to draw the tracer polyline.
|
|
21548
|
+
* @param event - The mouse or touch event.
|
|
21549
|
+
*/
|
|
20993
21550
|
mouseMove(event) {
|
|
20994
21551
|
if ("cancelable" in event && event.cancelable) {
|
|
20995
21552
|
event.preventDefault();
|
|
@@ -21004,33 +21561,10 @@ class Polydraw extends L.Control {
|
|
|
21004
21561
|
this.tracer.addLatLng(latlng);
|
|
21005
21562
|
}
|
|
21006
21563
|
}
|
|
21007
|
-
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
const result = await this.polygonMutationManager.addPolygon(geoPos, {
|
|
21012
|
-
simplify: true,
|
|
21013
|
-
noMerge: false
|
|
21014
|
-
});
|
|
21015
|
-
if (!result.success) {
|
|
21016
|
-
console.error("Error adding polygon via manager:", result.error);
|
|
21017
|
-
}
|
|
21018
|
-
break;
|
|
21019
|
-
}
|
|
21020
|
-
case DrawMode.Subtract: {
|
|
21021
|
-
const subtractResult = await this.polygonMutationManager.subtractPolygon(geoPos);
|
|
21022
|
-
if (!subtractResult.success) {
|
|
21023
|
-
console.error("Error subtracting polygon via manager:", subtractResult.error);
|
|
21024
|
-
}
|
|
21025
|
-
break;
|
|
21026
|
-
}
|
|
21027
|
-
default:
|
|
21028
|
-
break;
|
|
21029
|
-
}
|
|
21030
|
-
} catch (error) {
|
|
21031
|
-
console.error("Error in mouseUpLeave polygon operation:", error);
|
|
21032
|
-
}
|
|
21033
|
-
}
|
|
21564
|
+
/**
|
|
21565
|
+
* Handles the mouse up event to complete a drawing operation.
|
|
21566
|
+
* @param event - The mouse or touch event.
|
|
21567
|
+
*/
|
|
21034
21568
|
async mouseUpLeave(event) {
|
|
21035
21569
|
if ("cancelable" in event && event.cancelable) {
|
|
21036
21570
|
event.preventDefault();
|
|
@@ -21080,57 +21614,62 @@ class Polydraw extends L.Control {
|
|
|
21080
21614
|
}
|
|
21081
21615
|
this.polygonInformation.createPolygonInformationStorage(this.arrayOfFeatureGroups);
|
|
21082
21616
|
}
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
this.
|
|
21090
|
-
|
|
21091
|
-
|
|
21092
|
-
|
|
21617
|
+
/**
|
|
21618
|
+
* Handles the completion of a freehand drawing operation.
|
|
21619
|
+
* @param geoPos - The GeoJSON feature representing the drawn polygon.
|
|
21620
|
+
*/
|
|
21621
|
+
async handleFreehandDrawCompletion(geoPos) {
|
|
21622
|
+
try {
|
|
21623
|
+
switch (this.modeManager.getCurrentMode()) {
|
|
21624
|
+
case DrawMode.Add: {
|
|
21625
|
+
const result = await this.polygonMutationManager.addPolygon(geoPos, {
|
|
21626
|
+
simplify: true,
|
|
21627
|
+
noMerge: false
|
|
21628
|
+
});
|
|
21629
|
+
if (!result.success) {
|
|
21630
|
+
console.error("Error adding polygon via manager:", result.error);
|
|
21631
|
+
}
|
|
21632
|
+
break;
|
|
21633
|
+
}
|
|
21634
|
+
case DrawMode.Subtract: {
|
|
21635
|
+
const subtractResult = await this.polygonMutationManager.subtractPolygon(geoPos);
|
|
21636
|
+
if (!subtractResult.success) {
|
|
21637
|
+
console.error("Error subtracting polygon via manager:", subtractResult.error);
|
|
21638
|
+
}
|
|
21639
|
+
break;
|
|
21640
|
+
}
|
|
21641
|
+
default:
|
|
21642
|
+
break;
|
|
21093
21643
|
}
|
|
21644
|
+
} catch (error) {
|
|
21645
|
+
console.error("Error in mouseUpLeave polygon operation:", error);
|
|
21094
21646
|
}
|
|
21095
21647
|
}
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
}
|
|
21100
|
-
if (this.modeManager.isInOffMode()) {
|
|
21101
|
-
return;
|
|
21102
|
-
}
|
|
21103
|
-
let clickLatLng;
|
|
21104
|
-
if ("latlng" in event && event.latlng) {
|
|
21105
|
-
clickLatLng = event.latlng;
|
|
21106
|
-
} else if ("touches" in event && event.touches && event.touches.length > 0) {
|
|
21107
|
-
clickLatLng = this.map.containerPointToLatLng([
|
|
21108
|
-
event.touches[0].clientX,
|
|
21109
|
-
event.touches[0].clientY
|
|
21110
|
-
]);
|
|
21111
|
-
}
|
|
21112
|
-
if (!clickLatLng) {
|
|
21113
|
-
return;
|
|
21114
|
-
}
|
|
21115
|
-
if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint) {
|
|
21116
|
-
this.polygonDrawManager.handlePointToPointClick(clickLatLng);
|
|
21117
|
-
return;
|
|
21118
|
-
}
|
|
21119
|
-
this.tracer.setLatLngs([clickLatLng]);
|
|
21120
|
-
this.startDraw();
|
|
21121
|
-
}
|
|
21648
|
+
/**
|
|
21649
|
+
* Starts a drawing operation by attaching the necessary event listeners.
|
|
21650
|
+
*/
|
|
21122
21651
|
startDraw() {
|
|
21123
21652
|
this.drawStartedEvents(true);
|
|
21124
21653
|
}
|
|
21654
|
+
/**
|
|
21655
|
+
* Sets up the keyboard event handlers for the document.
|
|
21656
|
+
*/
|
|
21125
21657
|
setupKeyboardHandlers() {
|
|
21126
21658
|
this._boundKeyUpHandler = this.handleKeyUp.bind(this);
|
|
21127
21659
|
document.addEventListener("keydown", this._boundKeyDownHandler);
|
|
21128
21660
|
document.addEventListener("keyup", this._boundKeyUpHandler);
|
|
21129
21661
|
}
|
|
21662
|
+
/**
|
|
21663
|
+
* Removes the keyboard event handlers from the document.
|
|
21664
|
+
*/
|
|
21130
21665
|
removeKeyboardHandlers() {
|
|
21131
21666
|
document.removeEventListener("keydown", this._boundKeyDownHandler);
|
|
21132
21667
|
document.removeEventListener("keyup", this._boundKeyUpHandler);
|
|
21133
21668
|
}
|
|
21669
|
+
/**
|
|
21670
|
+
* Handles the key down event for keyboard shortcuts.
|
|
21671
|
+
* @param e - The keyboard event.
|
|
21672
|
+
*/
|
|
21134
21673
|
handleKeyDown(e) {
|
|
21135
21674
|
if (e.key === "Escape") {
|
|
21136
21675
|
if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint) {
|
|
@@ -21144,6 +21683,10 @@ class Polydraw extends L.Control {
|
|
|
21144
21683
|
this.updateAllMarkersForEdgeDeletion(true);
|
|
21145
21684
|
}
|
|
21146
21685
|
}
|
|
21686
|
+
/**
|
|
21687
|
+
* Handles the key up event for keyboard shortcuts.
|
|
21688
|
+
* @param e - The keyboard event.
|
|
21689
|
+
*/
|
|
21147
21690
|
handleKeyUp(e) {
|
|
21148
21691
|
const isModifierPressed = this.isModifierKeyPressed(e);
|
|
21149
21692
|
if (!isModifierPressed && this.isModifierKeyHeld) {
|
|
@@ -21180,6 +21723,10 @@ class Polydraw extends L.Control {
|
|
|
21180
21723
|
element.style.borderColor = "";
|
|
21181
21724
|
}
|
|
21182
21725
|
}
|
|
21726
|
+
/**
|
|
21727
|
+
* Handles the double-click event for point-to-point drawing.
|
|
21728
|
+
* @param e - The mouse event.
|
|
21729
|
+
*/
|
|
21183
21730
|
handleDoubleClick(e) {
|
|
21184
21731
|
if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint) {
|
|
21185
21732
|
return;
|
|
@@ -21198,6 +21745,9 @@ class Polydraw extends L.Control {
|
|
|
21198
21745
|
return event.ctrlKey;
|
|
21199
21746
|
}
|
|
21200
21747
|
}
|
|
21748
|
+
/**
|
|
21749
|
+
* Updates the visual indicator on the activate button to show if there are active polygons.
|
|
21750
|
+
*/
|
|
21201
21751
|
updateActivateButtonIndicator() {
|
|
21202
21752
|
if (typeof this.getContainer !== "function") {
|
|
21203
21753
|
return;
|