@mlightcad/cad-simple-viewer 1.6.1 → 1.6.2

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.
Files changed (125) hide show
  1. package/dist/cad-simple-viewer.js +5714 -4936
  2. package/dist/cad-simple-viewer.umd.cjs +180 -29
  3. package/lib/app/AcApSettingManager.d.ts.map +1 -1
  4. package/lib/app/AcApSettingManager.js +1 -0
  5. package/lib/app/AcApSettingManager.js.map +1 -1
  6. package/lib/command/draw/AcApArcCmd.d.ts.map +1 -1
  7. package/lib/command/draw/AcApArcCmd.js +28 -312
  8. package/lib/command/draw/AcApArcCmd.js.map +1 -1
  9. package/lib/command/draw/AcApCircleCmd.d.ts.map +1 -1
  10. package/lib/command/draw/AcApCircleCmd.js +10 -42
  11. package/lib/command/draw/AcApCircleCmd.js.map +1 -1
  12. package/lib/command/markup/AcApMarkupTextCmd.d.ts.map +1 -1
  13. package/lib/command/markup/AcApMarkupTextCmd.js +8 -2
  14. package/lib/command/markup/AcApMarkupTextCmd.js.map +1 -1
  15. package/lib/command/markup/AcApMarkupTextEdit.d.ts.map +1 -1
  16. package/lib/command/markup/AcApMarkupTextEdit.js +3 -1
  17. package/lib/command/markup/AcApMarkupTextEdit.js.map +1 -1
  18. package/lib/command/markup/AcApMarkupUtil.d.ts.map +1 -1
  19. package/lib/command/markup/AcApMarkupUtil.js +3 -2
  20. package/lib/command/markup/AcApMarkupUtil.js.map +1 -1
  21. package/lib/command/measure/AcApMeasureArcCmd.d.ts +22 -25
  22. package/lib/command/measure/AcApMeasureArcCmd.d.ts.map +1 -1
  23. package/lib/command/measure/AcApMeasureArcCmd.js +480 -256
  24. package/lib/command/measure/AcApMeasureArcCmd.js.map +1 -1
  25. package/lib/command/measure/AcApMeasureArcLock.d.ts +40 -0
  26. package/lib/command/measure/AcApMeasureArcLock.d.ts.map +1 -0
  27. package/lib/command/measure/AcApMeasureArcLock.js +226 -0
  28. package/lib/command/measure/AcApMeasureArcLock.js.map +1 -0
  29. package/lib/command/measure/AcApMeasurementGeometry.d.ts.map +1 -1
  30. package/lib/command/measure/AcApMeasurementGeometry.js +9 -9
  31. package/lib/command/measure/AcApMeasurementGeometry.js.map +1 -1
  32. package/lib/command/measure/AcApMeasurementSidecar.d.ts.map +1 -1
  33. package/lib/command/measure/AcApMeasurementSidecar.js +12 -7
  34. package/lib/command/measure/AcApMeasurementSidecar.js.map +1 -1
  35. package/lib/command/measure/AcApMeasurementStore.d.ts +2 -0
  36. package/lib/command/measure/AcApMeasurementStore.d.ts.map +1 -1
  37. package/lib/command/measure/AcApMeasurementStore.js +4 -0
  38. package/lib/command/measure/AcApMeasurementStore.js.map +1 -1
  39. package/lib/command/measure/AcApMeasurementTypes.d.ts +6 -0
  40. package/lib/command/measure/AcApMeasurementTypes.d.ts.map +1 -1
  41. package/lib/command/measure/entity/AcApMeasureArcEntity.d.ts +24 -22
  42. package/lib/command/measure/entity/AcApMeasureArcEntity.d.ts.map +1 -1
  43. package/lib/command/measure/entity/AcApMeasureArcEntity.js +104 -41
  44. package/lib/command/measure/entity/AcApMeasureArcEntity.js.map +1 -1
  45. package/lib/command/measure/entity/AcApMeasureDrawUtil.d.ts +35 -38
  46. package/lib/command/measure/entity/AcApMeasureDrawUtil.d.ts.map +1 -1
  47. package/lib/command/measure/entity/AcApMeasureDrawUtil.js +42 -53
  48. package/lib/command/measure/entity/AcApMeasureDrawUtil.js.map +1 -1
  49. package/lib/command/measure/entity/AcApMeasureEntityFactory.d.ts.map +1 -1
  50. package/lib/command/measure/entity/AcApMeasureEntityFactory.js +1 -1
  51. package/lib/command/measure/entity/AcApMeasureEntityFactory.js.map +1 -1
  52. package/lib/command/modify/AcApEraseCmd.d.ts +1 -0
  53. package/lib/command/modify/AcApEraseCmd.d.ts.map +1 -1
  54. package/lib/command/modify/AcApEraseCmd.js +4 -2
  55. package/lib/command/modify/AcApEraseCmd.js.map +1 -1
  56. package/lib/editor/grip/AcEdGripEditSession.d.ts.map +1 -1
  57. package/lib/editor/grip/AcEdGripEditSession.js +2 -0
  58. package/lib/editor/grip/AcEdGripEditSession.js.map +1 -1
  59. package/lib/editor/input/AcEdOsnapCenterMarks.d.ts +23 -0
  60. package/lib/editor/input/AcEdOsnapCenterMarks.d.ts.map +1 -0
  61. package/lib/editor/input/AcEdOsnapCenterMarks.js +240 -0
  62. package/lib/editor/input/AcEdOsnapCenterMarks.js.map +1 -0
  63. package/lib/editor/input/AcEdOsnapResolver.d.ts +18 -0
  64. package/lib/editor/input/AcEdOsnapResolver.d.ts.map +1 -1
  65. package/lib/editor/input/AcEdOsnapResolver.js +159 -10
  66. package/lib/editor/input/AcEdOsnapResolver.js.map +1 -1
  67. package/lib/editor/input/marker/AcEdMarker.d.ts +1 -1
  68. package/lib/editor/input/marker/AcEdMarker.d.ts.map +1 -1
  69. package/lib/editor/input/marker/AcEdMarker.js +11 -1
  70. package/lib/editor/input/marker/AcEdMarker.js.map +1 -1
  71. package/lib/editor/input/marker/AcEdOSnapMarkerManager.d.ts +17 -1
  72. package/lib/editor/input/marker/AcEdOSnapMarkerManager.d.ts.map +1 -1
  73. package/lib/editor/input/marker/AcEdOSnapMarkerManager.js +71 -10
  74. package/lib/editor/input/marker/AcEdOSnapMarkerManager.js.map +1 -1
  75. package/lib/editor/input/ui/AcEdFloatingInput.d.ts.map +1 -1
  76. package/lib/editor/input/ui/AcEdFloatingInput.js +4 -0
  77. package/lib/editor/input/ui/AcEdFloatingInput.js.map +1 -1
  78. package/lib/i18n/cs/jig.d.ts +3 -0
  79. package/lib/i18n/cs/jig.d.ts.map +1 -1
  80. package/lib/i18n/cs/jig.js +6 -3
  81. package/lib/i18n/cs/jig.js.map +1 -1
  82. package/lib/i18n/en/jig.d.ts +3 -0
  83. package/lib/i18n/en/jig.d.ts.map +1 -1
  84. package/lib/i18n/en/jig.js +6 -3
  85. package/lib/i18n/en/jig.js.map +1 -1
  86. package/lib/i18n/tr/jig.d.ts +3 -0
  87. package/lib/i18n/tr/jig.d.ts.map +1 -1
  88. package/lib/i18n/tr/jig.js +6 -3
  89. package/lib/i18n/tr/jig.js.map +1 -1
  90. package/lib/i18n/zh/jig.d.ts +3 -0
  91. package/lib/i18n/zh/jig.d.ts.map +1 -1
  92. package/lib/i18n/zh/jig.js +6 -3
  93. package/lib/i18n/zh/jig.js.map +1 -1
  94. package/lib/service/AcApEntityService.d.ts +4 -2
  95. package/lib/service/AcApEntityService.d.ts.map +1 -1
  96. package/lib/service/AcApEntityService.js +14 -10
  97. package/lib/service/AcApEntityService.js.map +1 -1
  98. package/lib/ui/AcApDrawStyle.d.ts +19 -1
  99. package/lib/ui/AcApDrawStyle.d.ts.map +1 -1
  100. package/lib/ui/AcApDrawStyle.js +22 -1
  101. package/lib/ui/AcApDrawStyle.js.map +1 -1
  102. package/lib/ui/AcApDrawStyleToolbar.d.ts +12 -7
  103. package/lib/ui/AcApDrawStyleToolbar.d.ts.map +1 -1
  104. package/lib/ui/AcApDrawStyleToolbar.js +173 -52
  105. package/lib/ui/AcApDrawStyleToolbar.js.map +1 -1
  106. package/lib/util/AcApCssColor.d.ts +8 -0
  107. package/lib/util/AcApCssColor.d.ts.map +1 -0
  108. package/lib/util/AcApCssColor.js +20 -0
  109. package/lib/util/AcApCssColor.js.map +1 -0
  110. package/lib/util/AcApMeasurementUtil.d.ts.map +1 -1
  111. package/lib/util/AcApMeasurementUtil.js +3 -2
  112. package/lib/util/AcApMeasurementUtil.js.map +1 -1
  113. package/lib/util/AcApScreenHitTest.d.ts +5 -1
  114. package/lib/util/AcApScreenHitTest.d.ts.map +1 -1
  115. package/lib/util/AcApScreenHitTest.js +9 -3
  116. package/lib/util/AcApScreenHitTest.js.map +1 -1
  117. package/lib/util/index.d.ts +1 -0
  118. package/lib/util/index.d.ts.map +1 -1
  119. package/lib/util/index.js +1 -0
  120. package/lib/util/index.js.map +1 -1
  121. package/lib/view/AcTrView2d.d.ts +6 -1
  122. package/lib/view/AcTrView2d.d.ts.map +1 -1
  123. package/lib/view/AcTrView2d.js +62 -34
  124. package/lib/view/AcTrView2d.js.map +1 -1
  125. package/package.json +5 -5
@@ -13,6 +13,17 @@ var __extends = (this && this.__extends) || (function () {
13
13
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
14
  };
15
15
  })();
16
+ var __assign = (this && this.__assign) || function () {
17
+ __assign = Object.assign || function(t) {
18
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
19
+ s = arguments[i];
20
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
21
+ t[p] = s[p];
22
+ }
23
+ return t;
24
+ };
25
+ return __assign.apply(this, arguments);
26
+ };
16
27
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
28
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
29
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -49,6 +60,31 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
49
60
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
61
  }
51
62
  };
63
+ var __read = (this && this.__read) || function (o, n) {
64
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
65
+ if (!m) return o;
66
+ var i = m.call(o), r, ar = [], e;
67
+ try {
68
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
69
+ }
70
+ catch (error) { e = { error: error }; }
71
+ finally {
72
+ try {
73
+ if (r && !r.done && (m = i["return"])) m.call(i);
74
+ }
75
+ finally { if (e) throw e.error; }
76
+ }
77
+ return ar;
78
+ };
79
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
80
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
81
+ if (ar || !(i in from)) {
82
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
83
+ ar[i] = from[i];
84
+ }
85
+ }
86
+ return to.concat(ar || Array.prototype.slice.call(from));
87
+ };
52
88
  var __values = (this && this.__values) || function(o) {
53
89
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
54
90
  if (m) return m.call(o);
@@ -60,109 +96,158 @@ var __values = (this && this.__values) || function(o) {
60
96
  };
61
97
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
62
98
  };
63
- import { AcDbArc, AcDbCircle } from '@mlightcad/data-model';
64
- import { AcTrHtmlBadge, AcTrHtmlCanvasOverlay, AcTrHtmlDot, AcTrHtmlSnapIndicator } from '@mlightcad/three-renderer';
99
+ import { AcGeCircArc2d, AcGeMathUtil } from '@mlightcad/data-model';
100
+ import { AcTrHtmlBadge, AcTrHtmlDot, AcTrHtmlSnapIndicator } from '@mlightcad/three-renderer';
101
+ import { AcApDocManager } from '../../app';
65
102
  import { AcEdCommand, AcEdCorsorType, AcEdOpenMode, AcEdPreviewJig, AcEdPromptPointOptions, AcEdPromptStatus, AcEdViewMode } from '../../editor';
66
103
  import { AcApI18n } from '../../i18n';
67
- import { acapCssColor, acapGetCurrentMeasurementStyle, acapGetMeasurementColor, acapMeasurementCanvasLineWidth, formatMeasurementLength } from '../../util';
104
+ import { acapGetCurrentMeasurementStyle, acapGetMeasurementColor, acapGetMeasurementFontSize, acapGetMeasurementLineWeight, acapMeasurementCanvasLineWidth, formatMeasurementLength } from '../../util';
105
+ import { AcApHtmlLivePreview, acapStrokeLivePolyline, acapStrokeLiveSegment } from '../overlay/AcApHtmlLivePreview';
106
+ import { inwardLockAlignment, isBetterLockCandidate, lockCurvesFromEntity, pointLiesOnCircle, sameCircleGeom } from './AcApMeasureArcLock';
68
107
  import { MEASUREMENT_LIVE_LAYER } from './AcApMeasurementStore';
69
- import { AcApMeasureArcEntity } from './entity';
70
- /** Returns the world point snapped to the nearest point on the circle circumference */
71
- function snapToCircle(p, g) {
72
- var angle = Math.atan2(p.y - g.cy, p.x - g.cx);
108
+ import { AcApMeasureArcEntity, strokeMeasureArcOnContext } from './entity';
109
+ /** Screen-pixel aperture for locking the first pick onto a CIRCLE/ARC stroke. */
110
+ var SNAP_SCREEN_PX = 20;
111
+ /** Minimum angular move (radians) before the locked-arc sweep direction is chosen. */
112
+ var DIR_LOCK_RAD = 0.02;
113
+ /**
114
+ * Wraps an angle delta into (−π, π].
115
+ */
116
+ function wrapAngleToPi(delta) {
117
+ return AcGeMathUtil.normalizeAngle(delta + Math.PI) - Math.PI;
118
+ }
119
+ /**
120
+ * Sweep on `g` from `start` to `end`.
121
+ *
122
+ * Default is counter-clockwise so the arc can grow past 180° without
123
+ * jumping to the complementary minor arc. `clockwise` selects that
124
+ * complementary direction (Ctrl toggle).
125
+ */
126
+ function lockedSweep(start, end, g, clockwise) {
127
+ var a1 = Math.atan2(start.y - g.cy, start.x - g.cx);
128
+ var a2 = Math.atan2(end.y - g.cy, end.x - g.cx);
129
+ var span = AcGeMathUtil.normalizeAngle(clockwise ? a1 - a2 : a2 - a1);
130
+ if (!(span > 1e-10) || span >= Math.PI * 2 - 1e-10)
131
+ return undefined;
132
+ var mid = clockwise ? a1 - span / 2 : a1 + span / 2;
73
133
  return {
74
- x: g.cx + g.r * Math.cos(angle),
75
- y: g.cy + g.r * Math.sin(angle),
76
- z: 0
134
+ through: { x: g.cx + g.r * Math.cos(mid), y: g.cy + g.r * Math.sin(mid) },
135
+ length: span * g.r
77
136
  };
78
137
  }
79
- /** Returns the shorter arc length between two points on a circle */
80
- function shortArcLength(p1, p2, g) {
81
- var a1 = Math.atan2(p1.y - g.cy, p1.x - g.cx);
82
- var a2 = Math.atan2(p2.y - g.cy, p2.x - g.cx);
83
- var norm = function (a) {
84
- return ((a % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
85
- };
86
- var span = norm(a2 - a1);
87
- return Math.min(span, 2 * Math.PI - span) * g.r;
138
+ function toPoint2(p) {
139
+ return { x: p.x, y: p.y };
88
140
  }
89
- /** World midpoint of the shorter arc between two circle points */
90
- function shortArcMid(p1, p2, g) {
91
- var a1 = Math.atan2(p1.y - g.cy, p1.x - g.cx);
92
- var a2 = Math.atan2(p2.y - g.cy, p2.x - g.cx);
93
- var norm = function (a) {
94
- return ((a % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
95
- };
96
- var ccwSpan = norm(a2 - a1);
97
- var mid = ccwSpan <= Math.PI ? a1 + ccwSpan / 2 : a1 - (2 * Math.PI - ccwSpan) / 2;
98
- return { x: g.cx + g.r * Math.cos(mid), y: g.cy + g.r * Math.sin(mid), z: 0 };
141
+ function circleGeomFromArc(arc) {
142
+ return { cx: arc.center.x, cy: arc.center.y, r: arc.radius };
99
143
  }
100
144
  /**
101
- * Draws the arc between two snapped circle points onto a canvas element.
102
- * Uses screen-space angles so the Y-axis flip is handled automatically.
145
+ * Projects `p` onto the circle circumference. If `p` is the center, the
146
+ * point at angle 0 is returned.
147
+ */
148
+ function snapToCircle(p, g) {
149
+ var dx = p.x - g.cx;
150
+ var dy = p.y - g.cy;
151
+ var d = Math.hypot(dx, dy);
152
+ if (!(d > 0))
153
+ return { x: g.cx + g.r, y: g.cy, z: 0 };
154
+ var s = g.r / d;
155
+ return { x: g.cx + dx * s, y: g.cy + dy * s, z: 0 };
156
+ }
157
+ /**
158
+ * Picks the CIRCLE / ARC / polyline-bulge stroke closest to `p` in screen space.
159
+ *
160
+ * Distance is measured to the drawn curve (not the complementary full circle)
161
+ * so a click on a gap or a straight polyline chord does not lock.
162
+ *
163
+ * @returns Geometry and the nearest point on that stroke, or `null`.
103
164
  */
104
- function drawArcOnCanvas(canvas, view, g, p1, p2, color, lineWidth) {
105
- if (lineWidth === void 0) { lineWidth = 4; }
106
- var rect = view.canvas.getBoundingClientRect();
107
- var dpr = window.devicePixelRatio || 1;
108
- var w = Math.round(rect.width);
109
- var h = Math.round(rect.height);
110
- var origin = view.canvasToContainer({ x: 0, y: 0 });
111
- canvas.style.left = "".concat(origin.x, "px");
112
- canvas.style.top = "".concat(origin.y, "px");
113
- canvas.style.width = "".concat(w, "px");
114
- canvas.style.height = "".concat(h, "px");
115
- if (canvas.width !== w * dpr || canvas.height !== h * dpr) {
116
- canvas.width = w * dpr;
117
- canvas.height = h * dpr;
165
+ function pickCircleGeomAtPoint(context, p) {
166
+ var e_1, _a, e_2, _b;
167
+ var blockTable = context.doc.database.tables.blockTable;
168
+ // OSNAP may have pulled `p` onto a shared polyline vertex. Score against
169
+ // the live cursor so the lock follows whichever arc the mouse is nearer.
170
+ var mouse = context.view.curPos;
171
+ var seen = new Set();
172
+ var hits = __spreadArray(__spreadArray([], __read(context.view.pick(mouse, SNAP_SCREEN_PX)), false), __read(context.view.pick(p, SNAP_SCREEN_PX)), false).filter(function (hit) {
173
+ if (seen.has(hit.id))
174
+ return false;
175
+ seen.add(hit.id);
176
+ return true;
177
+ });
178
+ var cursorScreen = context.view.worldToScreen(mouse);
179
+ var pick = { x: mouse.x, y: mouse.y, z: 0 };
180
+ var best = null;
181
+ var bestScreen = SNAP_SCREEN_PX;
182
+ var bestAlign = -Infinity;
183
+ try {
184
+ for (var hits_1 = __values(hits), hits_1_1 = hits_1.next(); !hits_1_1.done; hits_1_1 = hits_1.next()) {
185
+ var hit = hits_1_1.value;
186
+ var entity = blockTable.getEntityById(hit.id);
187
+ if (!entity)
188
+ continue;
189
+ try {
190
+ for (var _c = (e_2 = void 0, __values(lockCurvesFromEntity(entity))), _d = _c.next(); !_d.done; _d = _c.next()) {
191
+ var curve = _d.value;
192
+ if (!(curve.radius > 0))
193
+ continue;
194
+ var nearest = curve.nearestPoint(pick);
195
+ var nearScreen = context.view.worldToScreen(nearest);
196
+ var screenDist = Math.hypot(cursorScreen.x - nearScreen.x, cursorScreen.y - nearScreen.y);
197
+ if (screenDist > SNAP_SCREEN_PX)
198
+ continue;
199
+ var align = inwardLockAlignment(curve, { x: nearest.x, y: nearest.y }, { x: mouse.x, y: mouse.y });
200
+ if (!best ||
201
+ isBetterLockCandidate(screenDist * screenDist, align, bestScreen * bestScreen, bestAlign)) {
202
+ bestScreen = screenDist;
203
+ bestAlign = align;
204
+ var geom = circleGeomFromArc(curve);
205
+ best = {
206
+ geom: geom,
207
+ snapped: { x: nearest.x, y: nearest.y, z: 0 }
208
+ };
209
+ }
210
+ }
211
+ }
212
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
213
+ finally {
214
+ try {
215
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
216
+ }
217
+ finally { if (e_2) throw e_2.error; }
218
+ }
219
+ }
118
220
  }
119
- var ctx = canvas.getContext('2d');
120
- if (!ctx)
121
- return;
122
- ctx.clearRect(0, 0, canvas.width, canvas.height);
123
- ctx.save();
124
- ctx.scale(dpr, dpr);
125
- var sc = view.worldToScreen({ x: g.cx, y: g.cy });
126
- var ss = view.worldToScreen(p1);
127
- var se = view.worldToScreen(p2);
128
- var screenR = Math.hypot(ss.x - sc.x, ss.y - sc.y);
129
- var sa = Math.atan2(ss.y - sc.y, ss.x - sc.x);
130
- var ea = Math.atan2(se.y - sc.y, se.x - sc.x);
131
- var norm = function (a) {
132
- return ((a % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
133
- };
134
- var cwSpan = norm(ea - sa);
135
- var antiClockwise = cwSpan > Math.PI;
136
- ctx.beginPath();
137
- ctx.arc(sc.x, sc.y, screenR, sa, ea, antiClockwise);
138
- ctx.strokeStyle = acapCssColor(color);
139
- ctx.lineWidth = lineWidth;
140
- ctx.stroke();
141
- ctx.restore();
221
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
222
+ finally {
223
+ try {
224
+ if (hits_1_1 && !hits_1_1.done && (_a = hits_1.return)) _a.call(hits_1);
225
+ }
226
+ finally { if (e_1) throw e_1.error; }
227
+ }
228
+ return best;
142
229
  }
143
230
  /**
144
231
  * Commit an arc-length measurement overlay (also used when importing a sidecar).
145
232
  */
146
- export function placeArcMeasurement(view, db, geom, start, end, style, options) {
147
- AcApMeasureArcEntity.create(geom, start, end, style, options).commit(view, db);
233
+ export function placeArcMeasurement(view, db, geom, start, through, end, style, options) {
234
+ AcApMeasureArcEntity.create(geom, start, end, style, __assign(__assign({}, options), { through: through })).commit(view, db);
148
235
  }
149
236
  /**
150
- * Jig for the first point: shows a small square snap indicator when the
151
- * cursor hovers over a circle or arc entity. Notifies the caller via onSnap.
237
+ * First-point jig: square snap indicator when the cursor is on a CIRCLE/ARC
238
+ * or a polyline bulge.
152
239
  */
153
240
  var AcApArcSnapJig = /** @class */ (function (_super) {
154
241
  __extends(AcApArcSnapJig, _super);
155
- function AcApArcSnapJig(context, color, onSnap) {
242
+ function AcApArcSnapJig(context, color) {
156
243
  var _this = _super.call(this, context.view) || this;
157
244
  _this._ctx = context;
158
- _this._onSnap = onSnap;
159
- var o = { x: 0, y: 0, z: 0 };
160
245
  _this._indicatorId = "live-arc-snap-".concat(Date.now());
161
246
  _this._htManager = context.view.htmlTransientManager;
162
247
  _this._indicator = new AcTrHtmlSnapIndicator({
163
248
  id: _this._indicatorId,
164
249
  color: color,
165
- worldPosition: o,
250
+ worldPosition: { x: 0, y: 0, z: 0 },
166
251
  layer: MEASUREMENT_LIVE_LAYER,
167
252
  layoutId: context.view.activeLayoutBtrId
168
253
  });
@@ -179,59 +264,13 @@ var AcApArcSnapJig = /** @class */ (function (_super) {
179
264
  configurable: true
180
265
  });
181
266
  AcApArcSnapJig.prototype.update = function (p) {
182
- var e_1, _a;
183
- var hits = this._ctx.view.pick(p);
184
- var modelSpace = this._ctx.doc.database.tables.blockTable.modelSpace;
185
- // Collect all circle/arc candidates, then pick the one whose
186
- // circumference is closest to the cursor (fixes wrong-arc selection
187
- // when multiple arcs overlap in the pick area).
188
- var bestGeom = null;
189
- var bestDist = Number.MAX_VALUE;
190
- try {
191
- for (var hits_1 = __values(hits), hits_1_1 = hits_1.next(); !hits_1_1.done; hits_1_1 = hits_1.next()) {
192
- var hit = hits_1_1.value;
193
- var entity = modelSpace.getIdAt(hit.id);
194
- var geom = null;
195
- if (entity instanceof AcDbCircle) {
196
- geom = { cx: entity.center.x, cy: entity.center.y, r: entity.radius };
197
- }
198
- else if (entity instanceof AcDbArc) {
199
- geom = { cx: entity.center.x, cy: entity.center.y, r: entity.radius };
200
- }
201
- if (geom) {
202
- // Distance from cursor to circumference
203
- var distToCenter = Math.hypot(p.x - geom.cx, p.y - geom.cy);
204
- var distToCircumference = Math.abs(distToCenter - geom.r);
205
- if (distToCircumference < bestDist) {
206
- bestDist = distToCircumference;
207
- bestGeom = geom;
208
- }
209
- }
210
- }
211
- }
212
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
213
- finally {
214
- try {
215
- if (hits_1_1 && !hits_1_1.done && (_a = hits_1.return)) _a.call(hits_1);
216
- }
217
- finally { if (e_1) throw e_1.error; }
218
- }
219
- if (bestGeom) {
220
- // Only snap when cursor is close enough to the circumference in
221
- // screen space (20 px threshold) — prevents snapping from far away.
222
- var snapped = snapToCircle(p, bestGeom);
223
- var cursorScreen = this._ctx.view.worldToScreen(p);
224
- var snapScreen = this._ctx.view.worldToScreen(snapped);
225
- var screenDist = Math.hypot(cursorScreen.x - snapScreen.x, cursorScreen.y - snapScreen.y);
226
- if (screenDist <= 20) {
227
- this._indicator.setPosition(snapped);
228
- this._indicator.object.visible = true;
229
- this._onSnap(bestGeom, snapped);
230
- return;
231
- }
267
+ var hit = pickCircleGeomAtPoint(this._ctx, p);
268
+ if (hit) {
269
+ this._indicator.setPosition(hit.snapped);
270
+ this._indicator.object.visible = true;
271
+ return;
232
272
  }
233
273
  this._indicator.object.visible = false;
234
- this._onSnap(null, null);
235
274
  };
236
275
  AcApArcSnapJig.prototype.end = function () {
237
276
  _super.prototype.end.call(this);
@@ -240,29 +279,54 @@ var AcApArcSnapJig = /** @class */ (function (_super) {
240
279
  return AcApArcSnapJig;
241
280
  }(AcEdPreviewJig));
242
281
  /**
243
- * Jig for the second point: snaps cursor to the known circle, shows the
244
- * square snap indicator, and fires onMove with the already-snapped point.
282
+ * End-point jig when a circle is already locked: cursor stays on the
283
+ * circumference, with a live arc preview (major or minor) and length badge.
284
+ *
285
+ * Sweep direction follows the first mouse movement past a small angle
286
+ * threshold, so dragging past 180° keeps the same side. Ctrl (the same
287
+ * sticky toggle as the ARC command) flips to the complementary sweep.
245
288
  */
246
- var AcApArcEndSnapJig = /** @class */ (function (_super) {
247
- __extends(AcApArcEndSnapJig, _super);
248
- function AcApArcEndSnapJig(view, geom, color, onMove) {
249
- var _this = _super.call(this, view) || this;
289
+ var AcApArcLockedEndJig = /** @class */ (function (_super) {
290
+ __extends(AcApArcLockedEndJig, _super);
291
+ function AcApArcLockedEndJig(context, db, geom, start, color) {
292
+ var _this = _super.call(this, context.view) || this;
293
+ /**
294
+ * Clockwise vs CCW chosen from the first significant mouse move.
295
+ * `null` until that move; preview then defaults to CCW.
296
+ */
297
+ _this._baseClockwise = null;
298
+ _this._ctx = context;
299
+ _this._view = context.view;
250
300
  _this._geom = geom;
251
- _this._onMove = onMove;
252
- var o = { x: 0, y: 0, z: 0 };
301
+ _this._start = toPoint2(start);
302
+ _this._db = db;
303
+ _this._color = color;
304
+ _this._lastAngle = Math.atan2(start.y - geom.cy, start.x - geom.cx);
305
+ _this._htManager = _this._view.htmlTransientManager;
253
306
  _this._indicatorId = "live-arc-end-snap-".concat(Date.now());
254
- _this._htManager = view.htmlTransientManager;
255
307
  _this._indicator = new AcTrHtmlSnapIndicator({
256
308
  id: _this._indicatorId,
257
309
  color: color,
258
- worldPosition: o,
310
+ worldPosition: start,
259
311
  layer: MEASUREMENT_LIVE_LAYER,
260
- layoutId: view.activeLayoutBtrId
312
+ layoutId: _this._view.activeLayoutBtrId
261
313
  });
262
314
  _this._htManager.add(_this._indicator);
315
+ _this._badgeId = "live-arc-locked-badge-".concat(Date.now());
316
+ _this._badge = new AcTrHtmlBadge({
317
+ id: _this._badgeId,
318
+ color: color,
319
+ worldPosition: start,
320
+ layer: MEASUREMENT_LIVE_LAYER,
321
+ layoutId: _this._view.activeLayoutBtrId,
322
+ fontSize: acapGetMeasurementFontSize()
323
+ });
324
+ _this._badge.object.visible = false;
325
+ _this._htManager.add(_this._badge);
326
+ _this._preview = new AcApHtmlLivePreview(_this._view, "live-arc-locked-".concat(Date.now()), MEASUREMENT_LIVE_LAYER);
263
327
  return _this;
264
328
  }
265
- Object.defineProperty(AcApArcEndSnapJig.prototype, "entity", {
329
+ Object.defineProperty(AcApArcLockedEndJig.prototype, "entity", {
266
330
  /** HTML-only preview — no CAD transient. */
267
331
  get: function () {
268
332
  return null;
@@ -270,35 +334,195 @@ var AcApArcEndSnapJig = /** @class */ (function (_super) {
270
334
  enumerable: false,
271
335
  configurable: true
272
336
  });
273
- AcApArcEndSnapJig.prototype.update = function (p) {
274
- var snapped = snapToCircle(p, this._geom);
337
+ Object.defineProperty(AcApArcLockedEndJig.prototype, "geom", {
338
+ /**
339
+ * Circle currently locked for the end pick. May switch between polyline
340
+ * bulge segments that share the start vertex as the cursor moves.
341
+ */
342
+ get: function () {
343
+ return this._geom;
344
+ },
345
+ enumerable: false,
346
+ configurable: true
347
+ });
348
+ Object.defineProperty(AcApArcLockedEndJig.prototype, "clockwise", {
349
+ /**
350
+ * Effective sweep direction after mouse-lock XOR the Ctrl sticky toggle.
351
+ */
352
+ get: function () {
353
+ var _a;
354
+ return ((_a = this._baseClockwise) !== null && _a !== void 0 ? _a : false) !== this._isCtrlFlipped();
355
+ },
356
+ enumerable: false,
357
+ configurable: true
358
+ });
359
+ AcApArcLockedEndJig.prototype._isCtrlFlipped = function () {
360
+ return AcApDocManager.instance.editor.getInputToggles().ctrlArcFlip;
361
+ };
362
+ AcApArcLockedEndJig.prototype._trackSweepDirection = function (end) {
363
+ var angle = Math.atan2(end.y - this._geom.cy, end.x - this._geom.cx);
364
+ if (this._baseClockwise == null) {
365
+ var delta = wrapAngleToPi(angle - this._lastAngle);
366
+ if (Math.abs(delta) > DIR_LOCK_RAD) {
367
+ this._baseClockwise = delta < 0;
368
+ }
369
+ }
370
+ this._lastAngle = angle;
371
+ };
372
+ AcApArcLockedEndJig.prototype.update = function (p) {
373
+ var _this = this;
374
+ var mouse = this._view.curPos;
375
+ var hit = pickCircleGeomAtPoint(this._ctx, p);
376
+ if (hit &&
377
+ pointLiesOnCircle(this._start, hit.geom) &&
378
+ !sameCircleGeom(this._geom, hit.geom)) {
379
+ this._geom = hit.geom;
380
+ this._baseClockwise = null;
381
+ this._lastAngle = Math.atan2(this._start.y - hit.geom.cy, this._start.x - hit.geom.cx);
382
+ }
383
+ var snapped = snapToCircle(mouse, this._geom);
384
+ var end = toPoint2(snapped);
385
+ this._trackSweepDirection(end);
386
+ this._color = acapGetMeasurementColor(this._db);
275
387
  this._indicator.setPosition(snapped);
276
- this._indicator.object.visible = true;
277
- this._onMove(snapped);
388
+ this._badge.setColor(this._color);
389
+ this._badge.setFontSize(acapGetMeasurementFontSize());
390
+ var lineWidth = acapMeasurementCanvasLineWidth(acapGetMeasurementLineWeight());
391
+ var sweep = lockedSweep(this._start, end, this._geom, this.clockwise);
392
+ this._preview.acapSetDraw(function (ctx, view) {
393
+ strokeMeasureArcOnContext(ctx, view, _this._geom, _this._start, end, _this._color, lineWidth, sweep === null || sweep === void 0 ? void 0 : sweep.through);
394
+ });
395
+ if (!sweep) {
396
+ this._badge.object.visible = false;
397
+ return;
398
+ }
399
+ this._badge.setText(formatMeasurementLength(this._db, sweep.length));
400
+ this._badge.setPosition(sweep.through);
401
+ this._badge.object.visible = true;
278
402
  };
279
- AcApArcEndSnapJig.prototype.end = function () {
403
+ AcApArcLockedEndJig.prototype.end = function () {
280
404
  _super.prototype.end.call(this);
405
+ this._preview.acapDispose();
281
406
  this._htManager.remove(this._indicatorId);
407
+ this._htManager.remove(this._badgeId);
282
408
  };
283
- return AcApArcEndSnapJig;
409
+ return AcApArcLockedEndJig;
284
410
  }(AcEdPreviewJig));
285
411
  /**
286
- * Command that measures the length of an arc on an existing circle or arc entity.
287
- *
288
- * Uses a two-phase pick flow that mirrors AutoCAD's arc-length measurement:
289
- *
290
- * 1. **Phase 1 — entity snap**: The user hovers over a circle or arc in the
291
- * drawing. A square snap indicator appears on the circumference and the
292
- * entity geometry is captured. Clicking confirms the start point.
412
+ * Rubber-band jig for picking the through point: solid HTML preview from start
413
+ * to cursor.
414
+ */
415
+ var AcApMeasureArcThroughJig = /** @class */ (function (_super) {
416
+ __extends(AcApMeasureArcThroughJig, _super);
417
+ function AcApMeasureArcThroughJig(view, start, color) {
418
+ var _this = _super.call(this, view) || this;
419
+ _this._start = start;
420
+ _this._cursor = start;
421
+ _this._color = color;
422
+ _this._preview = new AcApHtmlLivePreview(view, "live-arc-through-".concat(Date.now()), MEASUREMENT_LIVE_LAYER);
423
+ return _this;
424
+ }
425
+ Object.defineProperty(AcApMeasureArcThroughJig.prototype, "entity", {
426
+ /** HTML-only preview — no CAD transient. */
427
+ get: function () {
428
+ return null;
429
+ },
430
+ enumerable: false,
431
+ configurable: true
432
+ });
433
+ AcApMeasureArcThroughJig.prototype.update = function (p) {
434
+ var _this = this;
435
+ this._cursor = p;
436
+ var lineWidth = acapMeasurementCanvasLineWidth(acapGetMeasurementLineWeight());
437
+ this._preview.acapSetDraw(function (ctx, view) {
438
+ acapStrokeLiveSegment(ctx, view, _this._start, _this._cursor, _this._color, lineWidth);
439
+ });
440
+ };
441
+ AcApMeasureArcThroughJig.prototype.end = function () {
442
+ _super.prototype.end.call(this);
443
+ this._preview.acapDispose();
444
+ };
445
+ return AcApMeasureArcThroughJig;
446
+ }(AcEdPreviewJig));
447
+ /**
448
+ * Preview jig for picking the end point: live arc stroke (or polyline fallback
449
+ * when the three points are collinear) plus a length badge.
450
+ */
451
+ var AcApMeasureArcEndJig = /** @class */ (function (_super) {
452
+ __extends(AcApMeasureArcEndJig, _super);
453
+ function AcApMeasureArcEndJig(view, db, start, through, color) {
454
+ var _this = _super.call(this, view) || this;
455
+ _this._view = view;
456
+ _this._start = toPoint2(start);
457
+ _this._through = toPoint2(through);
458
+ _this._end = toPoint2(through);
459
+ _this._color = color;
460
+ _this._db = db;
461
+ _this._badgeId = "live-arc-badge-".concat(Date.now());
462
+ _this._htManager = _this._view.htmlTransientManager;
463
+ _this._badge = new AcTrHtmlBadge({
464
+ id: _this._badgeId,
465
+ color: color,
466
+ worldPosition: start,
467
+ layer: MEASUREMENT_LIVE_LAYER,
468
+ layoutId: _this._view.activeLayoutBtrId,
469
+ fontSize: acapGetMeasurementFontSize()
470
+ });
471
+ _this._badge.object.visible = false;
472
+ _this._htManager.add(_this._badge);
473
+ _this._preview = new AcApHtmlLivePreview(_this._view, "live-arc-end-".concat(Date.now()), MEASUREMENT_LIVE_LAYER);
474
+ return _this;
475
+ }
476
+ Object.defineProperty(AcApMeasureArcEndJig.prototype, "entity", {
477
+ /** HTML-only preview — no CAD transient. */
478
+ get: function () {
479
+ return null;
480
+ },
481
+ enumerable: false,
482
+ configurable: true
483
+ });
484
+ AcApMeasureArcEndJig.prototype.update = function (p) {
485
+ var _this = this;
486
+ this._end = toPoint2(p);
487
+ this._color = acapGetMeasurementColor(this._db);
488
+ this._badge.setColor(this._color);
489
+ this._badge.setFontSize(acapGetMeasurementFontSize());
490
+ var lineWidth = acapMeasurementCanvasLineWidth(acapGetMeasurementLineWeight());
491
+ var arc = AcGeCircArc2d.tryCreateByThreePoints(this._start, this._through, this._end);
492
+ var geom = arc ? circleGeomFromArc(arc) : null;
493
+ this._preview.acapSetDraw(function (ctx, view) {
494
+ if (!geom) {
495
+ acapStrokeLivePolyline(ctx, view, [_this._start, _this._through, _this._end], _this._color, lineWidth);
496
+ return;
497
+ }
498
+ strokeMeasureArcOnContext(ctx, view, geom, _this._start, _this._end, _this._color, lineWidth, _this._through);
499
+ });
500
+ if (!arc) {
501
+ this._badge.object.visible = false;
502
+ return;
503
+ }
504
+ this._badge.setText(formatMeasurementLength(this._db, arc.length));
505
+ this._badge.setPosition(arc.midPoint);
506
+ this._badge.object.visible = true;
507
+ };
508
+ AcApMeasureArcEndJig.prototype.end = function () {
509
+ _super.prototype.end.call(this);
510
+ this._preview.acapDispose();
511
+ this._htManager.remove(this._badgeId);
512
+ };
513
+ return AcApMeasureArcEndJig;
514
+ }(AcEdPreviewJig));
515
+ /**
516
+ * Command that measures arc length.
293
517
  *
294
- * 2. **Phase 2 end point**: The same square indicator follows the cursor,
295
- * always locked to the captured circle. A canvas overlay draws the shorter
296
- * arc between the start and current position in real time, together with a
297
- * live badge showing the arc length.
518
+ * If the first pick lands on a CIRCLE, ARC, or polyline bulge, subsequent
519
+ * picks lock onto that circumference (two-point sweep). Sweep direction
520
+ * follows the first mouse movement so arcs greater than 180 degrees stay on
521
+ * the same side; Ctrl flips to the complementary (major/minor) arc. Otherwise
522
+ * three world points (start, a point on the arc, end) define a free-form arc.
298
523
  *
299
- * Persistent overlays are placed via {@link AcTrHtmlTransientManager} for dots
300
- * and badge. The arc canvas is managed with a viewChanged listener cleaned up
301
- * via {@link commitMeasurementGroup}.
524
+ * Interactive preview is HTML-only. The committed overlay is placed via
525
+ * {@link placeArcMeasurement}.
302
526
  */
303
527
  var AcApMeasureArcCmd = /** @class */ (function (_super) {
304
528
  __extends(AcApMeasureArcCmd, _super);
@@ -309,7 +533,7 @@ var AcApMeasureArcCmd = /** @class */ (function (_super) {
309
533
  }
310
534
  AcApMeasureArcCmd.prototype.execute = function (context) {
311
535
  return __awaiter(this, void 0, void 0, function () {
312
- var editor, db, color, style, canvasLineWidth, liveId, arcOverlay, htManager;
536
+ var editor, db, color, view;
313
537
  var _this = this;
314
538
  return __generator(this, function (_a) {
315
539
  switch (_a.label) {
@@ -317,113 +541,58 @@ var AcApMeasureArcCmd = /** @class */ (function (_super) {
317
541
  editor = context.view.editor;
318
542
  db = context.doc.database;
319
543
  color = acapGetMeasurementColor(db);
320
- style = acapGetCurrentMeasurementStyle(db);
321
- canvasLineWidth = acapMeasurementCanvasLineWidth(style.lineWeight);
322
- liveId = "live-arc-".concat(Date.now());
323
- arcOverlay = new AcTrHtmlCanvasOverlay({
324
- id: "".concat(liveId, "-canvas"),
325
- container: context.view.container,
326
- layer: MEASUREMENT_LIVE_LAYER,
327
- layoutId: context.view.activeLayoutBtrId
328
- });
329
- htManager = context.view.htmlTransientManager;
330
- htManager.add(arcOverlay);
544
+ view = context.view;
331
545
  return [4 /*yield*/, context.view.withMode(AcEdViewMode.SELECTION, function () {
332
546
  return editor.withCursor(AcEdCorsorType.Crosshair, function () { return __awaiter(_this, void 0, void 0, function () {
333
- var snapGeom, snappedStart, snapJig, p1Prompt, p1Result, _a, geom, start, liveDotId, liveBadgeId, liveBadge, redrawPreview, onViewChangedPreview, cleanupLivePreview, onMove, p2Prompt, p2Raw, p2Result, _b, end;
334
- return __generator(this, function (_c) {
335
- switch (_c.label) {
547
+ var startPrompt, startResult, start, lock, startOnLock, throughPrompt, throughResult, through, endPrompt, endResult, end, start2, through2, end2, measured;
548
+ return __generator(this, function (_a) {
549
+ switch (_a.label) {
336
550
  case 0:
337
- snapGeom = null;
338
- snappedStart = null;
339
- snapJig = new AcApArcSnapJig(context, color, function (geom, snapped) {
340
- snapGeom = geom;
341
- snappedStart = snapped;
342
- });
343
- p1Prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.startPoint'));
344
- p1Prompt.jig = snapJig;
345
- _c.label = 1;
551
+ editor.resetInputToggles();
552
+ startPrompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.startPoint'));
553
+ startPrompt.jig = new AcApArcSnapJig(context, color);
554
+ return [4 /*yield*/, editor.getPoint(startPrompt)];
346
555
  case 1:
347
- _c.trys.push([1, 3, , 4]);
348
- return [4 /*yield*/, editor.getPoint(p1Prompt)];
349
- case 2:
350
- p1Result = _c.sent();
351
- if (p1Result.status !== AcEdPromptStatus.OK) {
352
- htManager.remove(arcOverlay.id);
556
+ startResult = _a.sent();
557
+ if (startResult.status !== AcEdPromptStatus.OK)
353
558
  return [2 /*return*/];
354
- }
355
- return [3 /*break*/, 4];
356
- case 3:
357
- _a = _c.sent();
358
- htManager.remove(arcOverlay.id);
559
+ start = startResult.value;
560
+ lock = pickCircleGeomAtPoint(context, start);
561
+ if (!lock) return [3 /*break*/, 3];
562
+ startOnLock = pointLiesOnCircle(toPoint2(start), lock.geom)
563
+ ? start
564
+ : lock.snapped;
565
+ return [4 /*yield*/, this.commitLockedArc(context, view, db, color, lock.geom, startOnLock)];
566
+ case 2:
567
+ _a.sent();
359
568
  return [2 /*return*/];
569
+ case 3:
570
+ throughPrompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.throughPoint'));
571
+ throughPrompt.useBasePoint = true;
572
+ throughPrompt.jig = new AcApMeasureArcThroughJig(context.view, start, color);
573
+ return [4 /*yield*/, editor.getPoint(throughPrompt)];
360
574
  case 4:
361
- if (!snapGeom || !snappedStart) {
362
- htManager.remove(arcOverlay.id);
575
+ throughResult = _a.sent();
576
+ if (throughResult.status !== AcEdPromptStatus.OK)
363
577
  return [2 /*return*/];
364
- }
365
- geom = snapGeom;
366
- start = snappedStart;
367
- liveDotId = "".concat(liveId, "-dot1");
368
- liveBadgeId = "".concat(liveId, "-badge");
369
- htManager.add(new AcTrHtmlDot({
370
- id: liveDotId,
371
- color: color,
372
- worldPosition: start,
373
- layer: MEASUREMENT_LIVE_LAYER,
374
- layoutId: context.view.activeLayoutBtrId
375
- }));
376
- liveBadge = new AcTrHtmlBadge({
377
- id: liveBadgeId,
378
- color: color,
379
- worldPosition: start,
380
- layer: MEASUREMENT_LIVE_LAYER,
381
- layoutId: context.view.activeLayoutBtrId,
382
- fontSize: style.fontSize
383
- });
384
- liveBadge.object.visible = false;
385
- htManager.add(liveBadge);
386
- redrawPreview = function () {
387
- return drawArcOnCanvas(arcOverlay.canvas, context.view, geom, start, start, color, canvasLineWidth);
388
- };
389
- onViewChangedPreview = function () { return redrawPreview(); };
390
- context.view.events.viewChanged.addEventListener(onViewChangedPreview);
391
- cleanupLivePreview = function () {
392
- htManager.remove(liveDotId);
393
- htManager.remove(liveBadgeId);
394
- htManager.remove(arcOverlay.id);
395
- context.view.events.viewChanged.removeEventListener(onViewChangedPreview);
396
- };
397
- onMove = function (snapped) {
398
- drawArcOnCanvas(arcOverlay.canvas, context.view, geom, start, snapped, color, canvasLineWidth);
399
- var len = shortArcLength(start, snapped, geom);
400
- liveBadge.setText(formatMeasurementLength(db, len));
401
- liveBadge.setPosition(shortArcMid(start, snapped, geom));
402
- liveBadge.object.visible = true;
403
- };
404
- p2Prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.endPoint'));
405
- p2Prompt.jig = new AcApArcEndSnapJig(context.view, geom, color, onMove);
406
- _c.label = 5;
578
+ through = throughResult.value;
579
+ endPrompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.endPoint'));
580
+ endPrompt.jig = new AcApMeasureArcEndJig(context.view, db, start, through, color);
581
+ return [4 /*yield*/, editor.getPoint(endPrompt)];
407
582
  case 5:
408
- _c.trys.push([5, 7, , 8]);
409
- return [4 /*yield*/, editor.getPoint(p2Prompt)];
410
- case 6:
411
- p2Result = _c.sent();
412
- if (p2Result.status !== AcEdPromptStatus.OK) {
413
- cleanupLivePreview();
583
+ endResult = _a.sent();
584
+ if (endResult.status !== AcEdPromptStatus.OK)
585
+ return [2 /*return*/];
586
+ end = endResult.value;
587
+ start2 = toPoint2(start);
588
+ through2 = toPoint2(through);
589
+ end2 = toPoint2(end);
590
+ measured = AcGeCircArc2d.tryCreateByThreePoints(start2, through2, end2);
591
+ if (!measured) {
592
+ this.showMessage(AcApI18n.t('jig.measureArc.invalidPoints'), 'warning');
414
593
  return [2 /*return*/];
415
594
  }
416
- p2Raw = p2Result.value;
417
- return [3 /*break*/, 8];
418
- case 7:
419
- _b = _c.sent();
420
- cleanupLivePreview();
421
- return [2 /*return*/];
422
- case 8:
423
- // Clean up construction-phase elements
424
- cleanupLivePreview();
425
- end = snapToCircle(p2Raw, geom);
426
- placeArcMeasurement(context.view, db, geom, start, end, acapGetCurrentMeasurementStyle(db));
595
+ placeArcMeasurement(view, db, circleGeomFromArc(measured), start2, through2, end2, acapGetCurrentMeasurementStyle(db));
427
596
  return [2 /*return*/];
428
597
  }
429
598
  });
@@ -436,6 +605,61 @@ var AcApMeasureArcCmd = /** @class */ (function (_super) {
436
605
  });
437
606
  });
438
607
  };
608
+ /**
609
+ * Two-point locked-arc flow after the start pick landed on a CIRCLE, ARC,
610
+ * or polyline bulge.
611
+ *
612
+ * Sweep direction follows the cursor; Ctrl toggles the complementary arc.
613
+ */
614
+ AcApMeasureArcCmd.prototype.commitLockedArc = function (context, view, db, color, geom, start) {
615
+ return __awaiter(this, void 0, void 0, function () {
616
+ var htManager, liveDotId, endPrompt, jig, endRaw, endResult, geomNow, start2, end2, sweep;
617
+ return __generator(this, function (_a) {
618
+ switch (_a.label) {
619
+ case 0:
620
+ context.view.editor.resetInputToggles();
621
+ htManager = view.htmlTransientManager;
622
+ liveDotId = "live-arc-locked-dot-".concat(Date.now());
623
+ htManager.add(new AcTrHtmlDot({
624
+ id: liveDotId,
625
+ color: color,
626
+ worldPosition: start,
627
+ layer: MEASUREMENT_LIVE_LAYER,
628
+ layoutId: view.activeLayoutBtrId
629
+ }));
630
+ endPrompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureArc.lockedEndPoint'));
631
+ jig = new AcApArcLockedEndJig(context, db, geom, start, color);
632
+ endPrompt.jig = jig;
633
+ _a.label = 1;
634
+ case 1:
635
+ _a.trys.push([1, , 3, 4]);
636
+ return [4 /*yield*/, context.view.editor.getPoint(endPrompt)];
637
+ case 2:
638
+ endResult = _a.sent();
639
+ if (endResult.status !== AcEdPromptStatus.OK)
640
+ return [2 /*return*/];
641
+ endRaw = endResult.value;
642
+ return [3 /*break*/, 4];
643
+ case 3:
644
+ htManager.remove(liveDotId);
645
+ return [7 /*endfinally*/];
646
+ case 4:
647
+ if (!endRaw)
648
+ return [2 /*return*/];
649
+ geomNow = jig.geom;
650
+ start2 = toPoint2(start);
651
+ end2 = toPoint2(snapToCircle(endRaw, geomNow));
652
+ sweep = lockedSweep(start2, end2, geomNow, jig.clockwise);
653
+ if (!sweep) {
654
+ this.showMessage(AcApI18n.t('jig.measureArc.invalidPoints'), 'warning');
655
+ return [2 /*return*/];
656
+ }
657
+ placeArcMeasurement(view, db, geomNow, start2, sweep.through, end2, acapGetCurrentMeasurementStyle(db));
658
+ return [2 /*return*/];
659
+ }
660
+ });
661
+ });
662
+ };
439
663
  return AcApMeasureArcCmd;
440
664
  }(AcEdCommand));
441
665
  export { AcApMeasureArcCmd };