@itwin/editor-frontend 3.4.0-dev.43 → 3.4.0-dev.44

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 (80) hide show
  1. package/lib/cjs/CreateElementTool.d.ts +100 -100
  2. package/lib/cjs/CreateElementTool.js +327 -327
  3. package/lib/cjs/CreateElementTool.js.map +1 -1
  4. package/lib/cjs/DeleteElementsTool.d.ts +15 -15
  5. package/lib/cjs/DeleteElementsTool.js +40 -40
  6. package/lib/cjs/DeleteElementsTool.js.map +1 -1
  7. package/lib/cjs/EditTool.d.ts +37 -37
  8. package/lib/cjs/EditTool.js +135 -135
  9. package/lib/cjs/EditTool.js.map +1 -1
  10. package/lib/cjs/ElementGeometryTool.d.ts +148 -148
  11. package/lib/cjs/ElementGeometryTool.js +708 -708
  12. package/lib/cjs/ElementGeometryTool.js.map +1 -1
  13. package/lib/cjs/ModifyCurveTools.d.ts +118 -118
  14. package/lib/cjs/ModifyCurveTools.js +668 -668
  15. package/lib/cjs/ModifyCurveTools.js.map +1 -1
  16. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.d.ts +137 -137
  17. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js +821 -821
  18. package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
  19. package/lib/cjs/ProjectLocation/ProjectGeolocation.d.ts +135 -135
  20. package/lib/cjs/ProjectLocation/ProjectGeolocation.js +507 -507
  21. package/lib/cjs/ProjectLocation/ProjectGeolocation.js.map +1 -1
  22. package/lib/cjs/SketchTools.d.ts +306 -306
  23. package/lib/cjs/SketchTools.js +1707 -1707
  24. package/lib/cjs/SketchTools.js.map +1 -1
  25. package/lib/cjs/SolidModelingTools.d.ts +380 -380
  26. package/lib/cjs/SolidModelingTools.js +1459 -1459
  27. package/lib/cjs/SolidModelingTools.js.map +1 -1
  28. package/lib/cjs/SolidPrimitiveTools.d.ts +254 -254
  29. package/lib/cjs/SolidPrimitiveTools.js +1095 -1095
  30. package/lib/cjs/SolidPrimitiveTools.js.map +1 -1
  31. package/lib/cjs/TransformElementsTool.d.ts +166 -166
  32. package/lib/cjs/TransformElementsTool.js +654 -654
  33. package/lib/cjs/TransformElementsTool.js.map +1 -1
  34. package/lib/cjs/UndoRedoTool.d.ts +16 -16
  35. package/lib/cjs/UndoRedoTool.js +42 -42
  36. package/lib/cjs/UndoRedoTool.js.map +1 -1
  37. package/lib/cjs/editor-frontend.d.ts +15 -15
  38. package/lib/cjs/editor-frontend.js +31 -31
  39. package/lib/cjs/editor-frontend.js.map +1 -1
  40. package/lib/esm/CreateElementTool.d.ts +100 -100
  41. package/lib/esm/CreateElementTool.js +319 -319
  42. package/lib/esm/CreateElementTool.js.map +1 -1
  43. package/lib/esm/DeleteElementsTool.d.ts +15 -15
  44. package/lib/esm/DeleteElementsTool.js +36 -36
  45. package/lib/esm/DeleteElementsTool.js.map +1 -1
  46. package/lib/esm/EditTool.d.ts +37 -37
  47. package/lib/esm/EditTool.js +131 -131
  48. package/lib/esm/EditTool.js.map +1 -1
  49. package/lib/esm/ElementGeometryTool.d.ts +148 -148
  50. package/lib/esm/ElementGeometryTool.js +700 -700
  51. package/lib/esm/ElementGeometryTool.js.map +1 -1
  52. package/lib/esm/ModifyCurveTools.d.ts +118 -118
  53. package/lib/esm/ModifyCurveTools.js +660 -660
  54. package/lib/esm/ModifyCurveTools.js.map +1 -1
  55. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.d.ts +137 -137
  56. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js +813 -813
  57. package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
  58. package/lib/esm/ProjectLocation/ProjectGeolocation.d.ts +135 -135
  59. package/lib/esm/ProjectLocation/ProjectGeolocation.js +501 -501
  60. package/lib/esm/ProjectLocation/ProjectGeolocation.js.map +1 -1
  61. package/lib/esm/SketchTools.d.ts +306 -306
  62. package/lib/esm/SketchTools.js +1697 -1697
  63. package/lib/esm/SketchTools.js.map +1 -1
  64. package/lib/esm/SolidModelingTools.d.ts +380 -380
  65. package/lib/esm/SolidModelingTools.js +1434 -1434
  66. package/lib/esm/SolidModelingTools.js.map +1 -1
  67. package/lib/esm/SolidPrimitiveTools.d.ts +254 -254
  68. package/lib/esm/SolidPrimitiveTools.js +1086 -1086
  69. package/lib/esm/SolidPrimitiveTools.js.map +1 -1
  70. package/lib/esm/TransformElementsTool.d.ts +166 -166
  71. package/lib/esm/TransformElementsTool.js +646 -646
  72. package/lib/esm/TransformElementsTool.js.map +1 -1
  73. package/lib/esm/UndoRedoTool.d.ts +16 -16
  74. package/lib/esm/UndoRedoTool.js +36 -36
  75. package/lib/esm/UndoRedoTool.js.map +1 -1
  76. package/lib/esm/editor-frontend.d.ts +15 -15
  77. package/lib/esm/editor-frontend.js +19 -19
  78. package/lib/esm/editor-frontend.js.map +1 -1
  79. package/lib/public/locales/en/Editor.json +448 -448
  80. package/package.json +15 -15
@@ -1,661 +1,661 @@
1
- /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
- * See LICENSE.md in the project root for license terms and full copyright notice.
4
- *--------------------------------------------------------------------------------------------*/
5
- import { AccuDrawHintBuilder, ElementSetTool, IModelApp, LengthDescription, NotifyMessageDetails, OutputMessagePriority } from "@itwin/core-frontend";
6
- import { BentleyError, Code, ElementGeometry, ElementGeometryOpcode, FeatureAppearance } from "@itwin/core-common";
7
- import { EditTools } from "./EditTool";
8
- import { AngleSweep, Arc3d, AxisOrder, CurvePrimitive, FrameBuilder, Geometry, JointOptions, LineSegment3d, LineString3d, Loop, Matrix3d, Path, RegionOps, Vector3d } from "@itwin/core-geometry";
9
- import { editorBuiltInCmdIds } from "@itwin/editor-common";
10
- import { computeChordToleranceFromPoint, DynamicGraphicsProvider } from "./CreateElementTool";
11
- import { DialogProperty, PropertyDescriptionHelper } from "@itwin/appui-abstract";
12
- import { Id64 } from "@itwin/core-bentley";
13
- /** @alpha */
14
- export class CurveData {
15
- constructor(props, params, geom) {
16
- this.props = props;
17
- this.params = params;
18
- this.geom = geom;
19
- }
20
- }
21
- /** @alpha Base class for applying an offset to path and loops. */
22
- export class ModifyCurveTool extends ElementSetTool {
23
- constructor() {
24
- super(...arguments);
25
- this._checkedIds = new Map();
26
- this._firstResult = true;
27
- }
28
- allowView(_vp) { return true; }
29
- isCompatibleViewport(vp, isSelectedViewChange) { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); }
30
- async startCommand() {
31
- if (undefined !== this._startedCmd)
32
- return this._startedCmd;
33
- return EditTools.startCommand(editorBuiltInCmdIds.cmdBasicManipulation, this.iModel.key);
34
- }
35
- static callCommand(method, ...args) {
36
- return EditTools.callCommand(method, ...args);
37
- }
38
- agendaAppearance(isDynamics) {
39
- if (isDynamics) {
40
- if (undefined === this._agendaAppearanceDynamic)
41
- this._agendaAppearanceDynamic = FeatureAppearance.fromTransparency(0.0);
42
- return this._agendaAppearanceDynamic;
43
- }
44
- if (undefined === this._agendaAppearanceDefault)
45
- this._agendaAppearanceDefault = FeatureAppearance.fromTransparency(0.9);
46
- return this._agendaAppearanceDefault;
47
- }
48
- get wantAgendaAppearanceOverride() { return false; }
49
- addFeatureOverrides(overrides, _vp) {
50
- if (this.agenda.isEmpty)
51
- return;
52
- const appearance = this.agendaAppearance(false);
53
- this.agenda.elements.forEach((elementId) => { overrides.override({ elementId, appearance }); });
54
- }
55
- updateAgendaAppearanceProvider(drop) {
56
- if (!this.wantAgendaAppearanceOverride)
57
- return;
58
- for (const vp of IModelApp.viewManager) {
59
- if (!this.allowView(vp))
60
- continue;
61
- if (drop || this.agenda.isEmpty)
62
- vp.dropFeatureOverrideProvider(this);
63
- else if (!vp.addFeatureOverrideProvider(this))
64
- vp.setFeatureOverrideProviderChanged();
65
- }
66
- }
67
- clearGraphics() {
68
- if (undefined === this._graphicsProvider)
69
- return;
70
- this._graphicsProvider.cleanupGraphic();
71
- this._graphicsProvider = undefined;
72
- }
73
- async createGraphics(ev) {
74
- if (!IModelApp.viewManager.inDynamicsMode)
75
- return; // Don't need to create graphic if dynamics aren't yet active...
76
- const geometry = this.getGeometryProps(ev, false);
77
- if (undefined === geometry)
78
- return;
79
- const elemProps = this.getElementProps(ev);
80
- if (undefined === (elemProps === null || elemProps === void 0 ? void 0 : elemProps.placement))
81
- return;
82
- if (undefined === this._graphicsProvider) {
83
- if (this._firstResult) {
84
- this.updateAgendaAppearanceProvider();
85
- this._firstResult = false;
86
- }
87
- this._graphicsProvider = new DynamicGraphicsProvider(this.iModel, this.toolId);
88
- }
89
- // Set chord tolerance for non-linear curve primitives...
90
- if (ev.viewport)
91
- this._graphicsProvider.chordTolerance = computeChordToleranceFromPoint(ev.viewport, ev.point);
92
- await this._graphicsProvider.createGraphic(elemProps.category, elemProps.placement, geometry);
93
- }
94
- static isSingleCurve(info) {
95
- const it = new ElementGeometry.Iterator(info);
96
- it.requestWorldCoordinates();
97
- for (const entry of it) {
98
- const geom = entry.toGeometryQuery();
99
- if (undefined === geom)
100
- return;
101
- if ("curvePrimitive" === geom.geometryCategory) {
102
- return { curve: geom, params: entry.geomParams };
103
- }
104
- else if ("curveCollection" === geom.geometryCategory) {
105
- return { curve: geom, params: entry.geomParams };
106
- }
107
- break;
108
- }
109
- return;
110
- }
111
- acceptCurve(_curve) { return true; }
112
- modifyCurve(_ev, _isAccept) { return undefined; }
113
- async getCurveData(id) {
114
- try {
115
- this._startedCmd = await this.startCommand();
116
- const reject = [ElementGeometryOpcode.Polyface, ElementGeometryOpcode.SolidPrimitive, ElementGeometryOpcode.BsplineSurface, ElementGeometryOpcode.BRep];
117
- const info = await ModifyCurveTool.callCommand("requestElementGeometry", id, { maxDisplayable: 1, reject, geometry: { curves: true, surfaces: true, solids: false } });
118
- if (undefined === info)
119
- return undefined;
120
- const data = ModifyCurveTool.isSingleCurve(info);
121
- if (undefined === data)
122
- return undefined;
123
- if (!this.acceptCurve(data.curve))
124
- return undefined;
125
- const props = await this.iModel.elements.loadProps(id);
126
- if (undefined === props)
127
- return undefined;
128
- return new CurveData(props, data.params, data.curve);
129
- }
130
- catch (err) {
131
- IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err)));
132
- return undefined;
133
- }
134
- }
135
- onGeometryFilterChanged() { this._checkedIds.clear(); }
136
- async acceptElementForOperation(id) {
137
- if (Id64.isInvalid(id) || Id64.isTransient(id))
138
- return false;
139
- let accept = this._checkedIds.get(id);
140
- if (undefined === accept) {
141
- if (this.agenda.isEmpty && this._checkedIds.size > 1000)
142
- this._checkedIds.clear(); // Limit auto-locate cache size to something reasonable...
143
- accept = (undefined !== await this.getCurveData(id));
144
- this._checkedIds.set(id, accept);
145
- }
146
- return accept;
147
- }
148
- async isElementValidForOperation(hit, out) {
149
- if (!await super.isElementValidForOperation(hit, out))
150
- return false;
151
- return this.acceptElementForOperation(hit.sourceId);
152
- }
153
- async onAgendaModified() {
154
- this.curveData = undefined;
155
- if (this.agenda.isEmpty)
156
- return;
157
- const id = this.agenda.elements[this.agenda.length - 1];
158
- this.curveData = await this.getCurveData(id);
159
- }
160
- onDynamicFrame(_ev, context) {
161
- if (undefined !== this._graphicsProvider)
162
- this._graphicsProvider.addGraphic(context);
163
- }
164
- async onMouseMotion(ev) {
165
- return this.createGraphics(ev);
166
- }
167
- setupAccuDraw() {
168
- const hints = new AccuDrawHintBuilder();
169
- hints.enableSmartRotation = true;
170
- hints.sendHints(false);
171
- }
172
- setupAndPromptForNextAction() {
173
- this.setupAccuDraw();
174
- super.setupAndPromptForNextAction();
175
- }
176
- getGeometryProps(ev, isAccept) {
177
- if (undefined === this.curveData)
178
- return;
179
- const offset = this.modifyCurve(ev, isAccept);
180
- if (undefined === offset)
181
- return;
182
- const builder = new ElementGeometry.Builder();
183
- builder.setLocalToWorldFromPlacement(this.curveData.props.placement);
184
- if (!builder.appendGeometryParamsChange(this.curveData.params))
185
- return;
186
- if (!builder.appendGeometryQuery(offset))
187
- return;
188
- return { format: "flatbuffer", data: builder.entries };
189
- }
190
- getElementProps(ev) {
191
- var _a;
192
- if (undefined === this.curveData)
193
- return;
194
- if (!this.wantModifyOriginal) {
195
- // Create result as new element with same model and category as original...
196
- const classFullName = (((_a = ev.viewport) === null || _a === void 0 ? void 0 : _a.view.is3d()) ? "Generic:PhysicalObject" : "BisCore:DrawingGraphic");
197
- return { classFullName, model: this.curveData.props.model, category: this.curveData.props.category, code: Code.createEmpty(), placement: this.curveData.props.placement };
198
- }
199
- return this.curveData.props;
200
- }
201
- async applyAgendaOperation(ev) {
202
- const geometry = this.getGeometryProps(ev, true);
203
- if (undefined === geometry)
204
- return false;
205
- const elemProps = this.getElementProps(ev);
206
- if (undefined === elemProps)
207
- return false;
208
- if ("flatbuffer" === geometry.format)
209
- elemProps.elementGeometryBuilderParams = { entryArray: geometry.data };
210
- else
211
- elemProps.geom = geometry.data;
212
- try {
213
- this._startedCmd = await this.startCommand();
214
- if (undefined === elemProps.id) {
215
- const repeatOperation = this.wantContinueWithPreviousResult;
216
- if (repeatOperation)
217
- this.agenda.clear();
218
- const newId = await ModifyCurveTool.callCommand("insertGeometricElement", elemProps);
219
- if (repeatOperation && this.agenda.add(newId))
220
- await this.onAgendaModified();
221
- }
222
- else {
223
- await ModifyCurveTool.callCommand("updateGeometricElement", elemProps);
224
- }
225
- return true;
226
- }
227
- catch (err) {
228
- IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."));
229
- return false;
230
- }
231
- }
232
- async processAgenda(ev) {
233
- if (await this.applyAgendaOperation(ev))
234
- return this.saveChanges();
235
- }
236
- get wantModifyOriginal() { return true; }
237
- get wantContinueWithPreviousResult() { return false; }
238
- async onProcessComplete() {
239
- // Don't restart tool want to continue operation using previous result...
240
- if (this.wantContinueWithPreviousResult && !this.agenda.isEmpty && undefined !== this.curveData)
241
- return;
242
- return super.onProcessComplete();
243
- }
244
- async onUnsuspend() {
245
- if (!this._firstResult)
246
- this.updateAgendaAppearanceProvider();
247
- return super.onUnsuspend();
248
- }
249
- async onSuspend() {
250
- if (!this._firstResult)
251
- this.updateAgendaAppearanceProvider(true);
252
- return super.onSuspend();
253
- }
254
- async onPostInstall() {
255
- await super.onPostInstall();
256
- if (this.wantAgendaAppearanceOverride)
257
- this.agenda.manageHiliteState = false;
258
- }
259
- async onCleanup() {
260
- this.clearGraphics();
261
- this.updateAgendaAppearanceProvider(true);
262
- return super.onCleanup();
263
- }
264
- }
265
- /** @alpha Tool for applying an offset to paths and loops. */
266
- export class OffsetCurveTool extends ModifyCurveTool {
267
- get wantAccuSnap() { return true; }
268
- get wantDynamics() { return true; }
269
- get useDistanceProperty() {
270
- if (!this._useDistanceProperty)
271
- this._useDistanceProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
272
- return this._useDistanceProperty;
273
- }
274
- get useDistance() { return this.useDistanceProperty.value; }
275
- set useDistance(value) { this.useDistanceProperty.value = value; }
276
- get distanceProperty() {
277
- if (!this._distanceProperty)
278
- this._distanceProperty = new DialogProperty(new LengthDescription("offsetDistance", EditTools.translate("OffsetCurve.Label.Distance")), 0.1, undefined, !this.useDistance);
279
- return this._distanceProperty;
280
- }
281
- get distance() { return this.distanceProperty.value; }
282
- set distance(value) { this.distanceProperty.value = value; }
283
- get makeCopyProperty() {
284
- if (!this._makeCopyProperty)
285
- this._makeCopyProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("offsetCopy", EditTools.translate("OffsetCurve.Label.MakeCopy")), false);
286
- return this._makeCopyProperty;
287
- }
288
- get makeCopy() { return this.makeCopyProperty.value; }
289
- set makeCopy(value) { this.makeCopyProperty.value = value; }
290
- getToolSettingPropertyLocked(property) {
291
- return (property === this.useDistanceProperty ? this.distanceProperty : undefined);
292
- }
293
- async applyToolSettingPropertyChange(updatedValue) {
294
- return this.changeToolSettingPropertyValue(updatedValue);
295
- }
296
- supplyToolSettingsProperties() {
297
- this.initializeToolSettingPropertyValues([this.makeCopyProperty, this.useDistanceProperty, this.distanceProperty]);
298
- const toolSettings = new Array();
299
- // ensure controls are enabled/disabled based on current lock property state
300
- this.distanceProperty.isDisabled = !this.useDistance;
301
- const useDistanceLock = this.useDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
302
- toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 1 }, useDistanceLock));
303
- toolSettings.push(this.makeCopyProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
304
- return toolSettings;
305
- }
306
- acceptCurve(curve) {
307
- if ("curvePrimitive" === curve.geometryCategory)
308
- return true;
309
- switch (curve.curveCollectionType) {
310
- case "path":
311
- case "loop":
312
- return true;
313
- default:
314
- return false;
315
- }
316
- }
317
- modifyCurve(ev, isAccept) {
318
- var _a;
319
- if (undefined === ev.viewport)
320
- return undefined;
321
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
322
- if (undefined === geom)
323
- return undefined;
324
- const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
325
- const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
326
- if (undefined === localToWorld)
327
- return undefined;
328
- const worldToLocal = localToWorld.inverse();
329
- if (undefined === worldToLocal)
330
- return undefined;
331
- const geomXY = ((geom instanceof CurvePrimitive) ? Path.create(geom) : geom).cloneTransformed(worldToLocal);
332
- if (undefined === geomXY)
333
- return undefined;
334
- const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
335
- if (undefined === spacePoint)
336
- return undefined;
337
- worldToLocal.multiplyPoint3d(spacePoint, spacePoint);
338
- spacePoint.z = 0.0;
339
- const closeDetail = geomXY.closestPoint(spacePoint);
340
- if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
341
- return undefined;
342
- const unitZ = Vector3d.unitZ();
343
- const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
344
- const unitY = unitZ.unitCrossProduct(unitX);
345
- if (undefined === unitY)
346
- return undefined;
347
- let distance = closeDetail.point.distance(spacePoint);
348
- const refDir = Vector3d.createStartEnd(closeDetail.point, spacePoint);
349
- if (refDir.dotProduct(unitY) < 0.0)
350
- distance = -distance;
351
- let offset = 0.0;
352
- if (this.useDistance) {
353
- offset = this.distance;
354
- if ((offset < 0.0 && distance > 0.0) || (offset > 0.0 && distance < 0.0))
355
- offset = -offset;
356
- }
357
- else {
358
- offset = distance;
359
- }
360
- if (Math.abs(offset) < Geometry.smallMetricDistance)
361
- return undefined;
362
- if (offset !== this.distance) {
363
- this.distance = offset;
364
- this.syncToolSettingPropertyValue(this.distanceProperty);
365
- if (isAccept)
366
- this.saveToolSettingPropertyValue(this.distanceProperty, this.distanceProperty.dialogItemValue);
367
- }
368
- const jointOptions = new JointOptions(offset);
369
- jointOptions.preserveEllipticalArcs = true;
370
- const offsetGeom = RegionOps.constructCurveXYOffset(geomXY, jointOptions);
371
- if (undefined === offsetGeom)
372
- return undefined;
373
- if (!offsetGeom.tryTransformInPlace(localToWorld))
374
- return undefined;
375
- if (geom instanceof CurvePrimitive && offsetGeom instanceof Path && 1 === offsetGeom.children.length)
376
- return offsetGeom.getChild(0); // Don't create path for offset of single open curve...
377
- return offsetGeom;
378
- }
379
- get wantModifyOriginal() {
380
- return !this.makeCopy;
381
- }
382
- get wantContinueWithPreviousResult() {
383
- return !this.wantModifyOriginal;
384
- }
385
- setupAccuDraw() {
386
- var _a;
387
- const hints = new AccuDrawHintBuilder();
388
- if (this.agenda.isEmpty) {
389
- hints.enableSmartRotation = true;
390
- }
391
- else if (undefined !== this.anchorPoint && undefined !== this.targetView) {
392
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
393
- const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(this.anchorPoint, false) : geom === null || geom === void 0 ? void 0 : geom.closestPoint(this.anchorPoint);
394
- if (undefined !== (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve)) {
395
- const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
396
- if (undefined !== unitX) {
397
- const matrix = AccuDrawHintBuilder.getCurrentRotation(this.targetView, true, true);
398
- const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
399
- if (undefined !== localToWorld) {
400
- const unitZ = localToWorld.matrix.getColumn(2);
401
- const frame = Matrix3d.createRigidFromColumns(unitX, unitZ, AxisOrder.XZY);
402
- if (undefined !== frame) {
403
- hints.setOrigin(closeDetail.point);
404
- hints.setMatrix(frame);
405
- }
406
- }
407
- }
408
- }
409
- }
410
- hints.sendHints(false);
411
- }
412
- provideToolAssistance(_mainInstrText, _additionalInstr) {
413
- let mainMsg;
414
- if (!this.agenda.isEmpty)
415
- mainMsg = EditTools.translate("OffsetCurve.Prompts.DefineOffset");
416
- super.provideToolAssistance(mainMsg);
417
- }
418
- async onRestartTool() {
419
- const tool = new OffsetCurveTool();
420
- if (!await tool.run())
421
- return this.exitTool();
422
- }
423
- }
424
- OffsetCurveTool.toolId = "OffsetCurve";
425
- OffsetCurveTool.iconSpec = "icon-scale"; // Need better icon...
426
- /** @alpha Tool for opening loops and splitting paths. */
427
- export class BreakCurveTool extends ModifyCurveTool {
428
- constructor() {
429
- super(...arguments);
430
- this.modifyOriginal = true;
431
- }
432
- get wantAccuSnap() { return true; }
433
- get wantModifyOriginal() { return this.modifyOriginal; }
434
- acceptCurve(curve) {
435
- if ("curvePrimitive" === curve.geometryCategory)
436
- return true;
437
- switch (curve.curveCollectionType) {
438
- case "path":
439
- case "loop":
440
- return true;
441
- default:
442
- return false;
443
- }
444
- }
445
- doBreakCurve(ev) {
446
- var _a;
447
- this.resultA = this.resultB = undefined;
448
- if (undefined === ev.viewport)
449
- return;
450
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
451
- if (undefined === geom)
452
- return;
453
- const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(ev.point, false) : geom.closestPoint(ev.point);
454
- if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
455
- return;
456
- const selectedStart = (closeDetail.fraction <= Geometry.smallFraction);
457
- const selectedEnd = (closeDetail.fraction >= (1.0 - Geometry.smallFraction));
458
- if (geom instanceof CurvePrimitive) {
459
- if (selectedStart || selectedEnd)
460
- return; // split is no-op...
461
- this.resultA = geom.clonePartialCurve(0.0, closeDetail.fraction);
462
- this.resultB = geom.clonePartialCurve(closeDetail.fraction, 1.0);
463
- return;
464
- }
465
- else if (geom instanceof Path) {
466
- const firstCurve = geom.children[0];
467
- const lastCurve = geom.children[geom.children.length - 1];
468
- if ((closeDetail.curve === firstCurve && selectedStart) || (closeDetail.curve === lastCurve && selectedEnd))
469
- return; // split is no-op...
470
- let beforeCurve = true;
471
- const resultA = Path.create();
472
- const resultB = Path.create();
473
- for (const curve of geom.children) {
474
- if (curve === closeDetail.curve) {
475
- if (selectedStart) {
476
- resultB.children.push(curve.clone());
477
- }
478
- else if (selectedEnd) {
479
- resultA.children.push(curve.clone());
480
- }
481
- else {
482
- const curveA = curve.clonePartialCurve(0.0, closeDetail.fraction);
483
- if (undefined !== curveA)
484
- resultA.children.push(curveA);
485
- const curveB = curve.clonePartialCurve(closeDetail.fraction, 1.0);
486
- if (undefined !== curveB)
487
- resultB.children.push(curveB);
488
- }
489
- beforeCurve = false;
490
- }
491
- else {
492
- if (beforeCurve)
493
- resultA.children.push(curve.clone());
494
- else
495
- resultB.children.push(curve.clone());
496
- }
497
- }
498
- this.resultA = resultA;
499
- this.resultB = resultB;
500
- }
501
- else if (geom instanceof Loop) {
502
- const closeIndex = geom.children.findIndex((child) => child === closeDetail.curve);
503
- if (-1 === closeIndex)
504
- return;
505
- const endIndex = closeIndex + geom.children.length;
506
- const resultA = Path.create(); // Result is always a single path...
507
- if (selectedStart) {
508
- resultA.children.push(closeDetail.curve.clone());
509
- }
510
- else if (!selectedEnd) {
511
- const curveB = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 1.0);
512
- if (undefined !== curveB)
513
- resultA.children.push(curveB);
514
- }
515
- for (let index = closeIndex; index < endIndex; ++index) {
516
- const curve = geom.cyclicCurvePrimitive(index);
517
- if (undefined === curve || curve === closeDetail.curve)
518
- continue;
519
- resultA.children.push(curve.clone());
520
- }
521
- if (selectedEnd) {
522
- resultA.children.push(closeDetail.curve.clone());
523
- }
524
- else if (!selectedStart) {
525
- const curveA = closeDetail.curve.clonePartialCurve(0.0, closeDetail.fraction);
526
- if (undefined !== curveA)
527
- resultA.children.push(curveA);
528
- }
529
- this.resultA = resultA;
530
- }
531
- }
532
- modifyCurve(_ev, _isAccept) {
533
- return (this.wantModifyOriginal ? this.resultA : this.resultB);
534
- }
535
- async processAgenda(ev) {
536
- this.doBreakCurve(ev);
537
- if (undefined === this.resultA || !await this.applyAgendaOperation(ev))
538
- return;
539
- if (undefined !== this.resultB) {
540
- this.modifyOriginal = false;
541
- await this.applyAgendaOperation(ev);
542
- }
543
- return this.saveChanges();
544
- }
545
- provideToolAssistance(_mainInstrText, _additionalInstr) {
546
- let mainMsg;
547
- if (this.agenda.isEmpty)
548
- mainMsg = EditTools.translate("BreakCurve.Prompts.IdentifyBreak");
549
- super.provideToolAssistance(mainMsg);
550
- }
551
- async onRestartTool() {
552
- const tool = new BreakCurveTool();
553
- if (!await tool.run())
554
- return this.exitTool();
555
- }
556
- }
557
- BreakCurveTool.toolId = "BreakCurve";
558
- BreakCurveTool.iconSpec = "icon-scale"; // Need better icon...
559
- /** @alpha Tool for extending/shortening curves. */
560
- export class ExtendCurveTool extends ModifyCurveTool {
561
- get wantAccuSnap() { return true; }
562
- get wantDynamics() { return true; }
563
- get wantAgendaAppearanceOverride() { return true; }
564
- acceptCurve(curve) {
565
- if ("curvePrimitive" !== curve.geometryCategory)
566
- return false;
567
- return curve.isExtensibleFractionSpace;
568
- }
569
- modifyCurve(ev, _isAccept) {
570
- var _a;
571
- if (undefined === ev.viewport || undefined === this.anchorPoint)
572
- return undefined;
573
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
574
- if (undefined === geom)
575
- return undefined;
576
- const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
577
- const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
578
- if (undefined === localToWorld)
579
- return undefined;
580
- const worldToLocal = localToWorld.inverse();
581
- if (undefined === worldToLocal)
582
- return undefined;
583
- const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
584
- if (undefined === spacePoint)
585
- return undefined;
586
- const pickDetail = geom.closestPoint(this.anchorPoint, false);
587
- if (undefined === (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve))
588
- return undefined;
589
- const closeDetail = geom.closestPoint(spacePoint, true);
590
- if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
591
- return undefined;
592
- if (closeDetail.curve instanceof Arc3d) {
593
- if (pickDetail.fraction > 0.5 && closeDetail.fraction < 0.0) {
594
- const smallArc = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 0.0);
595
- smallArc.sweep.cloneComplement(false, smallArc.sweep);
596
- return smallArc;
597
- }
598
- else if (pickDetail.fraction <= 0.5 && closeDetail.fraction > 1.0) {
599
- const smallArc = closeDetail.curve.clonePartialCurve(1.0, closeDetail.fraction);
600
- smallArc.sweep.cloneComplement(false, smallArc.sweep);
601
- return smallArc;
602
- }
603
- else if (Math.abs(pickDetail.fraction > 0.5 ? closeDetail.fraction : 1.0 - closeDetail.fraction) < Geometry.smallFraction) {
604
- const fullArc = closeDetail.curve.clone();
605
- fullArc.sweep = AngleSweep.create360();
606
- return fullArc;
607
- }
608
- }
609
- return closeDetail.curve.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
610
- }
611
- setupAccuDraw() {
612
- var _a;
613
- const hints = new AccuDrawHintBuilder();
614
- if (this.agenda.isEmpty) {
615
- hints.enableSmartRotation = true;
616
- }
617
- else {
618
- const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
619
- if (undefined === geom || "curvePrimitive" !== geom.geometryCategory)
620
- return;
621
- if (geom instanceof Arc3d) {
622
- const matrix = geom.matrixClone();
623
- matrix.normalizeColumnsInPlace();
624
- hints.setOrigin(geom.center);
625
- hints.setMatrix(matrix);
626
- hints.setModePolar();
627
- }
628
- else if (geom instanceof LineSegment3d) {
629
- const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
630
- if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve)) {
631
- hints.setOrigin(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref);
632
- hints.setXAxis(Vector3d.createStartEnd(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref, pickDetail.fraction > 0.5 ? geom.point1Ref : geom.point0Ref));
633
- }
634
- hints.setModeRectangular();
635
- }
636
- else if (geom instanceof LineString3d) {
637
- const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
638
- if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve) && geom.numPoints() > 1) {
639
- hints.setOrigin(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1));
640
- hints.setXAxis(Vector3d.createStartEnd(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1), geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 1 : 0)));
641
- }
642
- hints.setModeRectangular();
643
- }
644
- }
645
- hints.sendHints(false);
646
- }
647
- provideToolAssistance(_mainInstrText, _additionalInstr) {
648
- let mainMsg;
649
- if (this.agenda.isEmpty)
650
- mainMsg = EditTools.translate("ExtendCurve.Prompts.IdentifyEnd");
651
- super.provideToolAssistance(mainMsg);
652
- }
653
- async onRestartTool() {
654
- const tool = new ExtendCurveTool();
655
- if (!await tool.run())
656
- return this.exitTool();
657
- }
658
- }
659
- ExtendCurveTool.toolId = "ExtendCurve";
660
- ExtendCurveTool.iconSpec = "icon-scale"; // Need better icon...
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { AccuDrawHintBuilder, ElementSetTool, IModelApp, LengthDescription, NotifyMessageDetails, OutputMessagePriority } from "@itwin/core-frontend";
6
+ import { BentleyError, Code, ElementGeometry, ElementGeometryOpcode, FeatureAppearance } from "@itwin/core-common";
7
+ import { EditTools } from "./EditTool";
8
+ import { AngleSweep, Arc3d, AxisOrder, CurvePrimitive, FrameBuilder, Geometry, JointOptions, LineSegment3d, LineString3d, Loop, Matrix3d, Path, RegionOps, Vector3d } from "@itwin/core-geometry";
9
+ import { editorBuiltInCmdIds } from "@itwin/editor-common";
10
+ import { computeChordToleranceFromPoint, DynamicGraphicsProvider } from "./CreateElementTool";
11
+ import { DialogProperty, PropertyDescriptionHelper } from "@itwin/appui-abstract";
12
+ import { Id64 } from "@itwin/core-bentley";
13
+ /** @alpha */
14
+ export class CurveData {
15
+ constructor(props, params, geom) {
16
+ this.props = props;
17
+ this.params = params;
18
+ this.geom = geom;
19
+ }
20
+ }
21
+ /** @alpha Base class for applying an offset to path and loops. */
22
+ export class ModifyCurveTool extends ElementSetTool {
23
+ constructor() {
24
+ super(...arguments);
25
+ this._checkedIds = new Map();
26
+ this._firstResult = true;
27
+ }
28
+ allowView(_vp) { return true; }
29
+ isCompatibleViewport(vp, isSelectedViewChange) { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); }
30
+ async startCommand() {
31
+ if (undefined !== this._startedCmd)
32
+ return this._startedCmd;
33
+ return EditTools.startCommand(editorBuiltInCmdIds.cmdBasicManipulation, this.iModel.key);
34
+ }
35
+ static callCommand(method, ...args) {
36
+ return EditTools.callCommand(method, ...args);
37
+ }
38
+ agendaAppearance(isDynamics) {
39
+ if (isDynamics) {
40
+ if (undefined === this._agendaAppearanceDynamic)
41
+ this._agendaAppearanceDynamic = FeatureAppearance.fromTransparency(0.0);
42
+ return this._agendaAppearanceDynamic;
43
+ }
44
+ if (undefined === this._agendaAppearanceDefault)
45
+ this._agendaAppearanceDefault = FeatureAppearance.fromTransparency(0.9);
46
+ return this._agendaAppearanceDefault;
47
+ }
48
+ get wantAgendaAppearanceOverride() { return false; }
49
+ addFeatureOverrides(overrides, _vp) {
50
+ if (this.agenda.isEmpty)
51
+ return;
52
+ const appearance = this.agendaAppearance(false);
53
+ this.agenda.elements.forEach((elementId) => { overrides.override({ elementId, appearance }); });
54
+ }
55
+ updateAgendaAppearanceProvider(drop) {
56
+ if (!this.wantAgendaAppearanceOverride)
57
+ return;
58
+ for (const vp of IModelApp.viewManager) {
59
+ if (!this.allowView(vp))
60
+ continue;
61
+ if (drop || this.agenda.isEmpty)
62
+ vp.dropFeatureOverrideProvider(this);
63
+ else if (!vp.addFeatureOverrideProvider(this))
64
+ vp.setFeatureOverrideProviderChanged();
65
+ }
66
+ }
67
+ clearGraphics() {
68
+ if (undefined === this._graphicsProvider)
69
+ return;
70
+ this._graphicsProvider.cleanupGraphic();
71
+ this._graphicsProvider = undefined;
72
+ }
73
+ async createGraphics(ev) {
74
+ if (!IModelApp.viewManager.inDynamicsMode)
75
+ return; // Don't need to create graphic if dynamics aren't yet active...
76
+ const geometry = this.getGeometryProps(ev, false);
77
+ if (undefined === geometry)
78
+ return;
79
+ const elemProps = this.getElementProps(ev);
80
+ if (undefined === (elemProps === null || elemProps === void 0 ? void 0 : elemProps.placement))
81
+ return;
82
+ if (undefined === this._graphicsProvider) {
83
+ if (this._firstResult) {
84
+ this.updateAgendaAppearanceProvider();
85
+ this._firstResult = false;
86
+ }
87
+ this._graphicsProvider = new DynamicGraphicsProvider(this.iModel, this.toolId);
88
+ }
89
+ // Set chord tolerance for non-linear curve primitives...
90
+ if (ev.viewport)
91
+ this._graphicsProvider.chordTolerance = computeChordToleranceFromPoint(ev.viewport, ev.point);
92
+ await this._graphicsProvider.createGraphic(elemProps.category, elemProps.placement, geometry);
93
+ }
94
+ static isSingleCurve(info) {
95
+ const it = new ElementGeometry.Iterator(info);
96
+ it.requestWorldCoordinates();
97
+ for (const entry of it) {
98
+ const geom = entry.toGeometryQuery();
99
+ if (undefined === geom)
100
+ return;
101
+ if ("curvePrimitive" === geom.geometryCategory) {
102
+ return { curve: geom, params: entry.geomParams };
103
+ }
104
+ else if ("curveCollection" === geom.geometryCategory) {
105
+ return { curve: geom, params: entry.geomParams };
106
+ }
107
+ break;
108
+ }
109
+ return;
110
+ }
111
+ acceptCurve(_curve) { return true; }
112
+ modifyCurve(_ev, _isAccept) { return undefined; }
113
+ async getCurveData(id) {
114
+ try {
115
+ this._startedCmd = await this.startCommand();
116
+ const reject = [ElementGeometryOpcode.Polyface, ElementGeometryOpcode.SolidPrimitive, ElementGeometryOpcode.BsplineSurface, ElementGeometryOpcode.BRep];
117
+ const info = await ModifyCurveTool.callCommand("requestElementGeometry", id, { maxDisplayable: 1, reject, geometry: { curves: true, surfaces: true, solids: false } });
118
+ if (undefined === info)
119
+ return undefined;
120
+ const data = ModifyCurveTool.isSingleCurve(info);
121
+ if (undefined === data)
122
+ return undefined;
123
+ if (!this.acceptCurve(data.curve))
124
+ return undefined;
125
+ const props = await this.iModel.elements.loadProps(id);
126
+ if (undefined === props)
127
+ return undefined;
128
+ return new CurveData(props, data.params, data.curve);
129
+ }
130
+ catch (err) {
131
+ IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err)));
132
+ return undefined;
133
+ }
134
+ }
135
+ onGeometryFilterChanged() { this._checkedIds.clear(); }
136
+ async acceptElementForOperation(id) {
137
+ if (Id64.isInvalid(id) || Id64.isTransient(id))
138
+ return false;
139
+ let accept = this._checkedIds.get(id);
140
+ if (undefined === accept) {
141
+ if (this.agenda.isEmpty && this._checkedIds.size > 1000)
142
+ this._checkedIds.clear(); // Limit auto-locate cache size to something reasonable...
143
+ accept = (undefined !== await this.getCurveData(id));
144
+ this._checkedIds.set(id, accept);
145
+ }
146
+ return accept;
147
+ }
148
+ async isElementValidForOperation(hit, out) {
149
+ if (!await super.isElementValidForOperation(hit, out))
150
+ return false;
151
+ return this.acceptElementForOperation(hit.sourceId);
152
+ }
153
+ async onAgendaModified() {
154
+ this.curveData = undefined;
155
+ if (this.agenda.isEmpty)
156
+ return;
157
+ const id = this.agenda.elements[this.agenda.length - 1];
158
+ this.curveData = await this.getCurveData(id);
159
+ }
160
+ onDynamicFrame(_ev, context) {
161
+ if (undefined !== this._graphicsProvider)
162
+ this._graphicsProvider.addGraphic(context);
163
+ }
164
+ async onMouseMotion(ev) {
165
+ return this.createGraphics(ev);
166
+ }
167
+ setupAccuDraw() {
168
+ const hints = new AccuDrawHintBuilder();
169
+ hints.enableSmartRotation = true;
170
+ hints.sendHints(false);
171
+ }
172
+ setupAndPromptForNextAction() {
173
+ this.setupAccuDraw();
174
+ super.setupAndPromptForNextAction();
175
+ }
176
+ getGeometryProps(ev, isAccept) {
177
+ if (undefined === this.curveData)
178
+ return;
179
+ const offset = this.modifyCurve(ev, isAccept);
180
+ if (undefined === offset)
181
+ return;
182
+ const builder = new ElementGeometry.Builder();
183
+ builder.setLocalToWorldFromPlacement(this.curveData.props.placement);
184
+ if (!builder.appendGeometryParamsChange(this.curveData.params))
185
+ return;
186
+ if (!builder.appendGeometryQuery(offset))
187
+ return;
188
+ return { format: "flatbuffer", data: builder.entries };
189
+ }
190
+ getElementProps(ev) {
191
+ var _a;
192
+ if (undefined === this.curveData)
193
+ return;
194
+ if (!this.wantModifyOriginal) {
195
+ // Create result as new element with same model and category as original...
196
+ const classFullName = (((_a = ev.viewport) === null || _a === void 0 ? void 0 : _a.view.is3d()) ? "Generic:PhysicalObject" : "BisCore:DrawingGraphic");
197
+ return { classFullName, model: this.curveData.props.model, category: this.curveData.props.category, code: Code.createEmpty(), placement: this.curveData.props.placement };
198
+ }
199
+ return this.curveData.props;
200
+ }
201
+ async applyAgendaOperation(ev) {
202
+ const geometry = this.getGeometryProps(ev, true);
203
+ if (undefined === geometry)
204
+ return false;
205
+ const elemProps = this.getElementProps(ev);
206
+ if (undefined === elemProps)
207
+ return false;
208
+ if ("flatbuffer" === geometry.format)
209
+ elemProps.elementGeometryBuilderParams = { entryArray: geometry.data };
210
+ else
211
+ elemProps.geom = geometry.data;
212
+ try {
213
+ this._startedCmd = await this.startCommand();
214
+ if (undefined === elemProps.id) {
215
+ const repeatOperation = this.wantContinueWithPreviousResult;
216
+ if (repeatOperation)
217
+ this.agenda.clear();
218
+ const newId = await ModifyCurveTool.callCommand("insertGeometricElement", elemProps);
219
+ if (repeatOperation && this.agenda.add(newId))
220
+ await this.onAgendaModified();
221
+ }
222
+ else {
223
+ await ModifyCurveTool.callCommand("updateGeometricElement", elemProps);
224
+ }
225
+ return true;
226
+ }
227
+ catch (err) {
228
+ IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."));
229
+ return false;
230
+ }
231
+ }
232
+ async processAgenda(ev) {
233
+ if (await this.applyAgendaOperation(ev))
234
+ return this.saveChanges();
235
+ }
236
+ get wantModifyOriginal() { return true; }
237
+ get wantContinueWithPreviousResult() { return false; }
238
+ async onProcessComplete() {
239
+ // Don't restart tool want to continue operation using previous result...
240
+ if (this.wantContinueWithPreviousResult && !this.agenda.isEmpty && undefined !== this.curveData)
241
+ return;
242
+ return super.onProcessComplete();
243
+ }
244
+ async onUnsuspend() {
245
+ if (!this._firstResult)
246
+ this.updateAgendaAppearanceProvider();
247
+ return super.onUnsuspend();
248
+ }
249
+ async onSuspend() {
250
+ if (!this._firstResult)
251
+ this.updateAgendaAppearanceProvider(true);
252
+ return super.onSuspend();
253
+ }
254
+ async onPostInstall() {
255
+ await super.onPostInstall();
256
+ if (this.wantAgendaAppearanceOverride)
257
+ this.agenda.manageHiliteState = false;
258
+ }
259
+ async onCleanup() {
260
+ this.clearGraphics();
261
+ this.updateAgendaAppearanceProvider(true);
262
+ return super.onCleanup();
263
+ }
264
+ }
265
+ /** @alpha Tool for applying an offset to paths and loops. */
266
+ export class OffsetCurveTool extends ModifyCurveTool {
267
+ get wantAccuSnap() { return true; }
268
+ get wantDynamics() { return true; }
269
+ get useDistanceProperty() {
270
+ if (!this._useDistanceProperty)
271
+ this._useDistanceProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
272
+ return this._useDistanceProperty;
273
+ }
274
+ get useDistance() { return this.useDistanceProperty.value; }
275
+ set useDistance(value) { this.useDistanceProperty.value = value; }
276
+ get distanceProperty() {
277
+ if (!this._distanceProperty)
278
+ this._distanceProperty = new DialogProperty(new LengthDescription("offsetDistance", EditTools.translate("OffsetCurve.Label.Distance")), 0.1, undefined, !this.useDistance);
279
+ return this._distanceProperty;
280
+ }
281
+ get distance() { return this.distanceProperty.value; }
282
+ set distance(value) { this.distanceProperty.value = value; }
283
+ get makeCopyProperty() {
284
+ if (!this._makeCopyProperty)
285
+ this._makeCopyProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("offsetCopy", EditTools.translate("OffsetCurve.Label.MakeCopy")), false);
286
+ return this._makeCopyProperty;
287
+ }
288
+ get makeCopy() { return this.makeCopyProperty.value; }
289
+ set makeCopy(value) { this.makeCopyProperty.value = value; }
290
+ getToolSettingPropertyLocked(property) {
291
+ return (property === this.useDistanceProperty ? this.distanceProperty : undefined);
292
+ }
293
+ async applyToolSettingPropertyChange(updatedValue) {
294
+ return this.changeToolSettingPropertyValue(updatedValue);
295
+ }
296
+ supplyToolSettingsProperties() {
297
+ this.initializeToolSettingPropertyValues([this.makeCopyProperty, this.useDistanceProperty, this.distanceProperty]);
298
+ const toolSettings = new Array();
299
+ // ensure controls are enabled/disabled based on current lock property state
300
+ this.distanceProperty.isDisabled = !this.useDistance;
301
+ const useDistanceLock = this.useDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
302
+ toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 1 }, useDistanceLock));
303
+ toolSettings.push(this.makeCopyProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
304
+ return toolSettings;
305
+ }
306
+ acceptCurve(curve) {
307
+ if ("curvePrimitive" === curve.geometryCategory)
308
+ return true;
309
+ switch (curve.curveCollectionType) {
310
+ case "path":
311
+ case "loop":
312
+ return true;
313
+ default:
314
+ return false;
315
+ }
316
+ }
317
+ modifyCurve(ev, isAccept) {
318
+ var _a;
319
+ if (undefined === ev.viewport)
320
+ return undefined;
321
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
322
+ if (undefined === geom)
323
+ return undefined;
324
+ const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
325
+ const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
326
+ if (undefined === localToWorld)
327
+ return undefined;
328
+ const worldToLocal = localToWorld.inverse();
329
+ if (undefined === worldToLocal)
330
+ return undefined;
331
+ const geomXY = ((geom instanceof CurvePrimitive) ? Path.create(geom) : geom).cloneTransformed(worldToLocal);
332
+ if (undefined === geomXY)
333
+ return undefined;
334
+ const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
335
+ if (undefined === spacePoint)
336
+ return undefined;
337
+ worldToLocal.multiplyPoint3d(spacePoint, spacePoint);
338
+ spacePoint.z = 0.0;
339
+ const closeDetail = geomXY.closestPoint(spacePoint);
340
+ if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
341
+ return undefined;
342
+ const unitZ = Vector3d.unitZ();
343
+ const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
344
+ const unitY = unitZ.unitCrossProduct(unitX);
345
+ if (undefined === unitY)
346
+ return undefined;
347
+ let distance = closeDetail.point.distance(spacePoint);
348
+ const refDir = Vector3d.createStartEnd(closeDetail.point, spacePoint);
349
+ if (refDir.dotProduct(unitY) < 0.0)
350
+ distance = -distance;
351
+ let offset = 0.0;
352
+ if (this.useDistance) {
353
+ offset = this.distance;
354
+ if ((offset < 0.0 && distance > 0.0) || (offset > 0.0 && distance < 0.0))
355
+ offset = -offset;
356
+ }
357
+ else {
358
+ offset = distance;
359
+ }
360
+ if (Math.abs(offset) < Geometry.smallMetricDistance)
361
+ return undefined;
362
+ if (offset !== this.distance) {
363
+ this.distance = offset;
364
+ this.syncToolSettingPropertyValue(this.distanceProperty);
365
+ if (isAccept)
366
+ this.saveToolSettingPropertyValue(this.distanceProperty, this.distanceProperty.dialogItemValue);
367
+ }
368
+ const jointOptions = new JointOptions(offset);
369
+ jointOptions.preserveEllipticalArcs = true;
370
+ const offsetGeom = RegionOps.constructCurveXYOffset(geomXY, jointOptions);
371
+ if (undefined === offsetGeom)
372
+ return undefined;
373
+ if (!offsetGeom.tryTransformInPlace(localToWorld))
374
+ return undefined;
375
+ if (geom instanceof CurvePrimitive && offsetGeom instanceof Path && 1 === offsetGeom.children.length)
376
+ return offsetGeom.getChild(0); // Don't create path for offset of single open curve...
377
+ return offsetGeom;
378
+ }
379
+ get wantModifyOriginal() {
380
+ return !this.makeCopy;
381
+ }
382
+ get wantContinueWithPreviousResult() {
383
+ return !this.wantModifyOriginal;
384
+ }
385
+ setupAccuDraw() {
386
+ var _a;
387
+ const hints = new AccuDrawHintBuilder();
388
+ if (this.agenda.isEmpty) {
389
+ hints.enableSmartRotation = true;
390
+ }
391
+ else if (undefined !== this.anchorPoint && undefined !== this.targetView) {
392
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
393
+ const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(this.anchorPoint, false) : geom === null || geom === void 0 ? void 0 : geom.closestPoint(this.anchorPoint);
394
+ if (undefined !== (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve)) {
395
+ const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
396
+ if (undefined !== unitX) {
397
+ const matrix = AccuDrawHintBuilder.getCurrentRotation(this.targetView, true, true);
398
+ const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
399
+ if (undefined !== localToWorld) {
400
+ const unitZ = localToWorld.matrix.getColumn(2);
401
+ const frame = Matrix3d.createRigidFromColumns(unitX, unitZ, AxisOrder.XZY);
402
+ if (undefined !== frame) {
403
+ hints.setOrigin(closeDetail.point);
404
+ hints.setMatrix(frame);
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
410
+ hints.sendHints(false);
411
+ }
412
+ provideToolAssistance(_mainInstrText, _additionalInstr) {
413
+ let mainMsg;
414
+ if (!this.agenda.isEmpty)
415
+ mainMsg = EditTools.translate("OffsetCurve.Prompts.DefineOffset");
416
+ super.provideToolAssistance(mainMsg);
417
+ }
418
+ async onRestartTool() {
419
+ const tool = new OffsetCurveTool();
420
+ if (!await tool.run())
421
+ return this.exitTool();
422
+ }
423
+ }
424
+ OffsetCurveTool.toolId = "OffsetCurve";
425
+ OffsetCurveTool.iconSpec = "icon-scale"; // Need better icon...
426
+ /** @alpha Tool for opening loops and splitting paths. */
427
+ export class BreakCurveTool extends ModifyCurveTool {
428
+ constructor() {
429
+ super(...arguments);
430
+ this.modifyOriginal = true;
431
+ }
432
+ get wantAccuSnap() { return true; }
433
+ get wantModifyOriginal() { return this.modifyOriginal; }
434
+ acceptCurve(curve) {
435
+ if ("curvePrimitive" === curve.geometryCategory)
436
+ return true;
437
+ switch (curve.curveCollectionType) {
438
+ case "path":
439
+ case "loop":
440
+ return true;
441
+ default:
442
+ return false;
443
+ }
444
+ }
445
+ doBreakCurve(ev) {
446
+ var _a;
447
+ this.resultA = this.resultB = undefined;
448
+ if (undefined === ev.viewport)
449
+ return;
450
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
451
+ if (undefined === geom)
452
+ return;
453
+ const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(ev.point, false) : geom.closestPoint(ev.point);
454
+ if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
455
+ return;
456
+ const selectedStart = (closeDetail.fraction <= Geometry.smallFraction);
457
+ const selectedEnd = (closeDetail.fraction >= (1.0 - Geometry.smallFraction));
458
+ if (geom instanceof CurvePrimitive) {
459
+ if (selectedStart || selectedEnd)
460
+ return; // split is no-op...
461
+ this.resultA = geom.clonePartialCurve(0.0, closeDetail.fraction);
462
+ this.resultB = geom.clonePartialCurve(closeDetail.fraction, 1.0);
463
+ return;
464
+ }
465
+ else if (geom instanceof Path) {
466
+ const firstCurve = geom.children[0];
467
+ const lastCurve = geom.children[geom.children.length - 1];
468
+ if ((closeDetail.curve === firstCurve && selectedStart) || (closeDetail.curve === lastCurve && selectedEnd))
469
+ return; // split is no-op...
470
+ let beforeCurve = true;
471
+ const resultA = Path.create();
472
+ const resultB = Path.create();
473
+ for (const curve of geom.children) {
474
+ if (curve === closeDetail.curve) {
475
+ if (selectedStart) {
476
+ resultB.children.push(curve.clone());
477
+ }
478
+ else if (selectedEnd) {
479
+ resultA.children.push(curve.clone());
480
+ }
481
+ else {
482
+ const curveA = curve.clonePartialCurve(0.0, closeDetail.fraction);
483
+ if (undefined !== curveA)
484
+ resultA.children.push(curveA);
485
+ const curveB = curve.clonePartialCurve(closeDetail.fraction, 1.0);
486
+ if (undefined !== curveB)
487
+ resultB.children.push(curveB);
488
+ }
489
+ beforeCurve = false;
490
+ }
491
+ else {
492
+ if (beforeCurve)
493
+ resultA.children.push(curve.clone());
494
+ else
495
+ resultB.children.push(curve.clone());
496
+ }
497
+ }
498
+ this.resultA = resultA;
499
+ this.resultB = resultB;
500
+ }
501
+ else if (geom instanceof Loop) {
502
+ const closeIndex = geom.children.findIndex((child) => child === closeDetail.curve);
503
+ if (-1 === closeIndex)
504
+ return;
505
+ const endIndex = closeIndex + geom.children.length;
506
+ const resultA = Path.create(); // Result is always a single path...
507
+ if (selectedStart) {
508
+ resultA.children.push(closeDetail.curve.clone());
509
+ }
510
+ else if (!selectedEnd) {
511
+ const curveB = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 1.0);
512
+ if (undefined !== curveB)
513
+ resultA.children.push(curveB);
514
+ }
515
+ for (let index = closeIndex; index < endIndex; ++index) {
516
+ const curve = geom.cyclicCurvePrimitive(index);
517
+ if (undefined === curve || curve === closeDetail.curve)
518
+ continue;
519
+ resultA.children.push(curve.clone());
520
+ }
521
+ if (selectedEnd) {
522
+ resultA.children.push(closeDetail.curve.clone());
523
+ }
524
+ else if (!selectedStart) {
525
+ const curveA = closeDetail.curve.clonePartialCurve(0.0, closeDetail.fraction);
526
+ if (undefined !== curveA)
527
+ resultA.children.push(curveA);
528
+ }
529
+ this.resultA = resultA;
530
+ }
531
+ }
532
+ modifyCurve(_ev, _isAccept) {
533
+ return (this.wantModifyOriginal ? this.resultA : this.resultB);
534
+ }
535
+ async processAgenda(ev) {
536
+ this.doBreakCurve(ev);
537
+ if (undefined === this.resultA || !await this.applyAgendaOperation(ev))
538
+ return;
539
+ if (undefined !== this.resultB) {
540
+ this.modifyOriginal = false;
541
+ await this.applyAgendaOperation(ev);
542
+ }
543
+ return this.saveChanges();
544
+ }
545
+ provideToolAssistance(_mainInstrText, _additionalInstr) {
546
+ let mainMsg;
547
+ if (this.agenda.isEmpty)
548
+ mainMsg = EditTools.translate("BreakCurve.Prompts.IdentifyBreak");
549
+ super.provideToolAssistance(mainMsg);
550
+ }
551
+ async onRestartTool() {
552
+ const tool = new BreakCurveTool();
553
+ if (!await tool.run())
554
+ return this.exitTool();
555
+ }
556
+ }
557
+ BreakCurveTool.toolId = "BreakCurve";
558
+ BreakCurveTool.iconSpec = "icon-scale"; // Need better icon...
559
+ /** @alpha Tool for extending/shortening curves. */
560
+ export class ExtendCurveTool extends ModifyCurveTool {
561
+ get wantAccuSnap() { return true; }
562
+ get wantDynamics() { return true; }
563
+ get wantAgendaAppearanceOverride() { return true; }
564
+ acceptCurve(curve) {
565
+ if ("curvePrimitive" !== curve.geometryCategory)
566
+ return false;
567
+ return curve.isExtensibleFractionSpace;
568
+ }
569
+ modifyCurve(ev, _isAccept) {
570
+ var _a;
571
+ if (undefined === ev.viewport || undefined === this.anchorPoint)
572
+ return undefined;
573
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
574
+ if (undefined === geom)
575
+ return undefined;
576
+ const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
577
+ const localToWorld = FrameBuilder.createRightHandedFrame(matrix === null || matrix === void 0 ? void 0 : matrix.getColumn(2), geom);
578
+ if (undefined === localToWorld)
579
+ return undefined;
580
+ const worldToLocal = localToWorld.inverse();
581
+ if (undefined === worldToLocal)
582
+ return undefined;
583
+ const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
584
+ if (undefined === spacePoint)
585
+ return undefined;
586
+ const pickDetail = geom.closestPoint(this.anchorPoint, false);
587
+ if (undefined === (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve))
588
+ return undefined;
589
+ const closeDetail = geom.closestPoint(spacePoint, true);
590
+ if (undefined === (closeDetail === null || closeDetail === void 0 ? void 0 : closeDetail.curve))
591
+ return undefined;
592
+ if (closeDetail.curve instanceof Arc3d) {
593
+ if (pickDetail.fraction > 0.5 && closeDetail.fraction < 0.0) {
594
+ const smallArc = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 0.0);
595
+ smallArc.sweep.cloneComplement(false, smallArc.sweep);
596
+ return smallArc;
597
+ }
598
+ else if (pickDetail.fraction <= 0.5 && closeDetail.fraction > 1.0) {
599
+ const smallArc = closeDetail.curve.clonePartialCurve(1.0, closeDetail.fraction);
600
+ smallArc.sweep.cloneComplement(false, smallArc.sweep);
601
+ return smallArc;
602
+ }
603
+ else if (Math.abs(pickDetail.fraction > 0.5 ? closeDetail.fraction : 1.0 - closeDetail.fraction) < Geometry.smallFraction) {
604
+ const fullArc = closeDetail.curve.clone();
605
+ fullArc.sweep = AngleSweep.create360();
606
+ return fullArc;
607
+ }
608
+ }
609
+ return closeDetail.curve.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
610
+ }
611
+ setupAccuDraw() {
612
+ var _a;
613
+ const hints = new AccuDrawHintBuilder();
614
+ if (this.agenda.isEmpty) {
615
+ hints.enableSmartRotation = true;
616
+ }
617
+ else {
618
+ const geom = (_a = this.curveData) === null || _a === void 0 ? void 0 : _a.geom;
619
+ if (undefined === geom || "curvePrimitive" !== geom.geometryCategory)
620
+ return;
621
+ if (geom instanceof Arc3d) {
622
+ const matrix = geom.matrixClone();
623
+ matrix.normalizeColumnsInPlace();
624
+ hints.setOrigin(geom.center);
625
+ hints.setMatrix(matrix);
626
+ hints.setModePolar();
627
+ }
628
+ else if (geom instanceof LineSegment3d) {
629
+ const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
630
+ if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve)) {
631
+ hints.setOrigin(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref);
632
+ hints.setXAxis(Vector3d.createStartEnd(pickDetail.fraction > 0.5 ? geom.point0Ref : geom.point1Ref, pickDetail.fraction > 0.5 ? geom.point1Ref : geom.point0Ref));
633
+ }
634
+ hints.setModeRectangular();
635
+ }
636
+ else if (geom instanceof LineString3d) {
637
+ const pickDetail = (undefined !== this.anchorPoint ? geom.closestPoint(this.anchorPoint, false) : undefined);
638
+ if (undefined !== (pickDetail === null || pickDetail === void 0 ? void 0 : pickDetail.curve) && geom.numPoints() > 1) {
639
+ hints.setOrigin(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1));
640
+ hints.setXAxis(Vector3d.createStartEnd(geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 2 : 1), geom.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? geom.numPoints() - 1 : 0)));
641
+ }
642
+ hints.setModeRectangular();
643
+ }
644
+ }
645
+ hints.sendHints(false);
646
+ }
647
+ provideToolAssistance(_mainInstrText, _additionalInstr) {
648
+ let mainMsg;
649
+ if (this.agenda.isEmpty)
650
+ mainMsg = EditTools.translate("ExtendCurve.Prompts.IdentifyEnd");
651
+ super.provideToolAssistance(mainMsg);
652
+ }
653
+ async onRestartTool() {
654
+ const tool = new ExtendCurveTool();
655
+ if (!await tool.run())
656
+ return this.exitTool();
657
+ }
658
+ }
659
+ ExtendCurveTool.toolId = "ExtendCurve";
660
+ ExtendCurveTool.iconSpec = "icon-scale"; // Need better icon...
661
661
  //# sourceMappingURL=ModifyCurveTools.js.map