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