@orbat-mapper/tactical-draw 0.2.0-alpha.3 → 0.2.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +29 -21
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1006,6 +1006,7 @@ function runVariableLengthDraw(options) {
|
|
|
1006
1006
|
const max = metadata.maxCoordinates;
|
|
1007
1007
|
const rule = metadata.rule;
|
|
1008
1008
|
const trailingFixed = rule?.trailingFixedSlots ?? 0;
|
|
1009
|
+
const closedRing = rule?.closedRing ?? false;
|
|
1009
1010
|
const ruleMin = rule?.minimumUserPoints;
|
|
1010
1011
|
const guideEnabled = (guideOpt ?? true) && !shouldSuppressGuide(metadata);
|
|
1011
1012
|
const isAreaKind = metadata.geometry === "area";
|
|
@@ -1097,20 +1098,20 @@ function runVariableLengthDraw(options) {
|
|
|
1097
1098
|
if (ctx.settled) return;
|
|
1098
1099
|
const pos = roundControlPoint(event.coordinate);
|
|
1099
1100
|
const lastSpineIdx = committed.length - 1 - trailingFixed;
|
|
1101
|
+
const finishIndices = closedRing && lastSpineIdx > 0 ? [lastSpineIdx, 0] : [lastSpineIdx];
|
|
1100
1102
|
for (let i = 0; i < committed.length; i++) if (positionsEqual(pos, committed[i])) {
|
|
1101
|
-
if (i
|
|
1103
|
+
if (finishIndices.includes(i) && canCommitNow()) ctx.commit(buildSnapshot);
|
|
1102
1104
|
return;
|
|
1103
1105
|
}
|
|
1104
|
-
if (lastSpineIdx >= 0 && canCommitNow()) {
|
|
1105
|
-
const
|
|
1106
|
-
if (
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
}
|
|
1106
|
+
if (lastSpineIdx >= 0 && canCommitNow()) for (const finishIndex of finishIndices) {
|
|
1107
|
+
const finishPixel = adapter.getPixelFromCoordinate(committed[finishIndex]);
|
|
1108
|
+
if (!finishPixel) continue;
|
|
1109
|
+
const tol = mapEventHitTolerance(event.originalEvent);
|
|
1110
|
+
const dx = event.pixel[0] - finishPixel[0];
|
|
1111
|
+
const dy = event.pixel[1] - finishPixel[1];
|
|
1112
|
+
if (dx * dx + dy * dy <= tol * tol) {
|
|
1113
|
+
ctx.commit(buildSnapshot);
|
|
1114
|
+
return;
|
|
1114
1115
|
}
|
|
1115
1116
|
}
|
|
1116
1117
|
if (typeof max === "number" && committed.length >= max) return;
|
|
@@ -1351,7 +1352,7 @@ function segmentMidpoint(a, b) {
|
|
|
1351
1352
|
* are emitted for it here. Returns `[]` for an empty control-point list.
|
|
1352
1353
|
*/
|
|
1353
1354
|
function buildHandleSet(controlPoints, modes, options = {}) {
|
|
1354
|
-
const { includeMidpoints = true, trailingFixedSlots = 0 } = options;
|
|
1355
|
+
const { includeMidpoints = true, trailingFixedSlots = 0, closedRing = false } = options;
|
|
1355
1356
|
const handles = [];
|
|
1356
1357
|
const wantsReshape = modes.includes("reshape");
|
|
1357
1358
|
if (wantsReshape || modes.includes("delete")) {
|
|
@@ -1361,12 +1362,15 @@ function buildHandleSet(controlPoints, modes, options = {}) {
|
|
|
1361
1362
|
position: [...controlPoints[i]]
|
|
1362
1363
|
});
|
|
1363
1364
|
if (wantsReshape && includeMidpoints) {
|
|
1364
|
-
const
|
|
1365
|
-
for (let i = 0; i <
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1365
|
+
const edgeCount = closedRing && trailingFixedSlots === 0 && controlPoints.length >= 3 ? controlPoints.length : controlPoints.length - 1 - trailingFixedSlots;
|
|
1366
|
+
for (let i = 0; i < edgeCount; i++) {
|
|
1367
|
+
const end = (i + 1) % controlPoints.length;
|
|
1368
|
+
handles.push({
|
|
1369
|
+
kind: "midpoint",
|
|
1370
|
+
index: i,
|
|
1371
|
+
position: segmentMidpoint(controlPoints[i], controlPoints[end])
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1370
1374
|
}
|
|
1371
1375
|
}
|
|
1372
1376
|
if (modes.includes("translate")) {
|
|
@@ -1552,7 +1556,8 @@ function beginHandleDrag(args) {
|
|
|
1552
1556
|
if (hit.kind === "vertex") return begun("vertex", preDragPoints, dragOnePoint(preDragPoints, hit.index));
|
|
1553
1557
|
if (hit.kind === "midpoint") {
|
|
1554
1558
|
const insertIndex = hit.index + 1;
|
|
1555
|
-
const
|
|
1559
|
+
const segmentEndIndex = (hit.index + 1) % preDragPoints.length;
|
|
1560
|
+
const mid = segmentMidpoint(preDragPoints[hit.index], preDragPoints[segmentEndIndex]);
|
|
1556
1561
|
const insertedBase = [
|
|
1557
1562
|
...preDragPoints.slice(0, insertIndex),
|
|
1558
1563
|
mid,
|
|
@@ -1662,6 +1667,7 @@ function runEdit(opts) {
|
|
|
1662
1667
|
const rule = metadata.rule;
|
|
1663
1668
|
const midpointHandlesEnabled = rule?.canonicalPointCount === void 0;
|
|
1664
1669
|
const trailingFixedSlots = rule?.trailingFixedSlots ?? 0;
|
|
1670
|
+
const closedRing = rule?.closedRing ?? false;
|
|
1665
1671
|
const guideEnabled = (guideOpt ?? true) && !shouldSuppressGuide(metadata);
|
|
1666
1672
|
const isAreaKind = metadata.geometry === "area";
|
|
1667
1673
|
const requestedModes = normaliseModes(initialModes);
|
|
@@ -1732,7 +1738,8 @@ function runEdit(opts) {
|
|
|
1732
1738
|
if (ctx.settled) return;
|
|
1733
1739
|
let handles = buildHandleSet(workingPoints, modes, {
|
|
1734
1740
|
includeMidpoints: midpointHandlesEnabled,
|
|
1735
|
-
trailingFixedSlots
|
|
1741
|
+
trailingFixedSlots,
|
|
1742
|
+
closedRing
|
|
1736
1743
|
});
|
|
1737
1744
|
if (activeDrag?.fsm.kind === "rotate" && rotateHandleOverride) {
|
|
1738
1745
|
const override = rotateHandleOverride;
|
|
@@ -2083,7 +2090,8 @@ function runEdit(opts) {
|
|
|
2083
2090
|
const tol = info?.hitTolerance ?? HANDLE_HIT_TOLERANCE_PX;
|
|
2084
2091
|
const hit = pickHandle(buildHandleSet(workingPoints, modes, {
|
|
2085
2092
|
includeMidpoints: midpointHandlesEnabled,
|
|
2086
|
-
trailingFixedSlots
|
|
2093
|
+
trailingFixedSlots,
|
|
2094
|
+
closedRing
|
|
2087
2095
|
}), pixel, tol, (lonLat) => driver.toPixel(lonLat));
|
|
2088
2096
|
if (!hit) return;
|
|
2089
2097
|
if (modes.includes("delete")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.4",
|
|
4
4
|
"description": "Engine-agnostic draw/edit core for tactical control measures (MIL-STD-2525 / APP-6). The MapAdapter ABI and bring-your-own-engine entry point for the tactical-draw package family.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@orbat-mapper/control-measures": "^0.2.0-alpha.
|
|
41
|
+
"@orbat-mapper/control-measures": "^0.2.0-alpha.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@arethetypeswrong/core": "^0.18.3",
|