@itwin/editor-frontend 4.5.0-dev.9 → 4.6.0-dev.0
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 +46 -1
- package/LICENSE.md +1 -1
- package/README.md +0 -29
- package/lib/cjs/CreateElementTool.d.ts +64 -2
- package/lib/cjs/CreateElementTool.d.ts.map +1 -1
- package/lib/cjs/CreateElementTool.js +65 -4
- package/lib/cjs/CreateElementTool.js.map +1 -1
- package/lib/cjs/EditTool.d.ts +5 -0
- package/lib/cjs/EditTool.d.ts.map +1 -1
- package/lib/cjs/EditTool.js +10 -14
- package/lib/cjs/EditTool.js.map +1 -1
- package/lib/cjs/EditToolIpc.d.ts +1 -5
- package/lib/cjs/EditToolIpc.d.ts.map +1 -1
- package/lib/cjs/EditToolIpc.js +1 -5
- package/lib/cjs/EditToolIpc.js.map +1 -1
- package/lib/cjs/ModifyElementTool.js.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
- package/lib/cjs/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/cjs/TransformElementsTool.d.ts +17 -98
- package/lib/cjs/TransformElementsTool.d.ts.map +1 -1
- package/lib/cjs/TransformElementsTool.js +15 -412
- package/lib/cjs/TransformElementsTool.js.map +1 -1
- package/lib/cjs/UndoRedoTool.js.map +1 -1
- package/lib/cjs/editor-frontend.d.ts +0 -6
- package/lib/cjs/editor-frontend.d.ts.map +1 -1
- package/lib/cjs/editor-frontend.js +0 -6
- package/lib/cjs/editor-frontend.js.map +1 -1
- package/lib/esm/CreateElementTool.d.ts +64 -2
- package/lib/esm/CreateElementTool.d.ts.map +1 -1
- package/lib/esm/CreateElementTool.js +65 -4
- package/lib/esm/CreateElementTool.js.map +1 -1
- package/lib/esm/EditTool.d.ts +5 -0
- package/lib/esm/EditTool.d.ts.map +1 -1
- package/lib/esm/EditTool.js +10 -14
- package/lib/esm/EditTool.js.map +1 -1
- package/lib/esm/EditToolIpc.d.ts +1 -5
- package/lib/esm/EditToolIpc.d.ts.map +1 -1
- package/lib/esm/EditToolIpc.js +0 -4
- package/lib/esm/EditToolIpc.js.map +1 -1
- package/lib/esm/ModifyElementTool.js.map +1 -1
- package/lib/esm/ProjectLocation/ProjectExtentsDecoration.js.map +1 -1
- package/lib/esm/ProjectLocation/ProjectGeolocation.js.map +1 -1
- package/lib/esm/TransformElementsTool.d.ts +17 -98
- package/lib/esm/TransformElementsTool.d.ts.map +1 -1
- package/lib/esm/TransformElementsTool.js +16 -413
- package/lib/esm/TransformElementsTool.js.map +1 -1
- package/lib/esm/UndoRedoTool.js.map +1 -1
- package/lib/esm/editor-frontend.d.ts +0 -6
- package/lib/esm/editor-frontend.d.ts.map +1 -1
- package/lib/esm/editor-frontend.js +0 -6
- package/lib/esm/editor-frontend.js.map +1 -1
- package/lib/public/locales/en/Editor.json +79 -490
- package/package.json +14 -14
- package/lib/cjs/DeleteElementsTool.d.ts +0 -14
- package/lib/cjs/DeleteElementsTool.d.ts.map +0 -1
- package/lib/cjs/DeleteElementsTool.js +0 -42
- package/lib/cjs/DeleteElementsTool.js.map +0 -1
- package/lib/cjs/ElementGeometryTool.d.ts +0 -148
- package/lib/cjs/ElementGeometryTool.d.ts.map +0 -1
- package/lib/cjs/ElementGeometryTool.js +0 -705
- package/lib/cjs/ElementGeometryTool.js.map +0 -1
- package/lib/cjs/ModifyCurveTools.d.ts +0 -140
- package/lib/cjs/ModifyCurveTools.d.ts.map +0 -1
- package/lib/cjs/ModifyCurveTools.js +0 -777
- package/lib/cjs/ModifyCurveTools.js.map +0 -1
- package/lib/cjs/SketchTools.d.ts +0 -308
- package/lib/cjs/SketchTools.d.ts.map +0 -1
- package/lib/cjs/SketchTools.js +0 -1708
- package/lib/cjs/SketchTools.js.map +0 -1
- package/lib/cjs/SolidModelingTools.d.ts +0 -381
- package/lib/cjs/SolidModelingTools.d.ts.map +0 -1
- package/lib/cjs/SolidModelingTools.js +0 -1453
- package/lib/cjs/SolidModelingTools.js.map +0 -1
- package/lib/cjs/SolidPrimitiveTools.d.ts +0 -322
- package/lib/cjs/SolidPrimitiveTools.d.ts.map +0 -1
- package/lib/cjs/SolidPrimitiveTools.js +0 -1376
- package/lib/cjs/SolidPrimitiveTools.js.map +0 -1
- package/lib/esm/DeleteElementsTool.d.ts +0 -14
- package/lib/esm/DeleteElementsTool.d.ts.map +0 -1
- package/lib/esm/DeleteElementsTool.js +0 -39
- package/lib/esm/DeleteElementsTool.js.map +0 -1
- package/lib/esm/ElementGeometryTool.d.ts +0 -148
- package/lib/esm/ElementGeometryTool.d.ts.map +0 -1
- package/lib/esm/ElementGeometryTool.js +0 -697
- package/lib/esm/ElementGeometryTool.js.map +0 -1
- package/lib/esm/ModifyCurveTools.d.ts +0 -140
- package/lib/esm/ModifyCurveTools.d.ts.map +0 -1
- package/lib/esm/ModifyCurveTools.js +0 -772
- package/lib/esm/ModifyCurveTools.js.map +0 -1
- package/lib/esm/SketchTools.d.ts +0 -308
- package/lib/esm/SketchTools.d.ts.map +0 -1
- package/lib/esm/SketchTools.js +0 -1704
- package/lib/esm/SketchTools.js.map +0 -1
- package/lib/esm/SolidModelingTools.d.ts +0 -381
- package/lib/esm/SolidModelingTools.d.ts.map +0 -1
- package/lib/esm/SolidModelingTools.js +0 -1445
- package/lib/esm/SolidModelingTools.js.map +0 -1
- package/lib/esm/SolidPrimitiveTools.d.ts +0 -322
- package/lib/esm/SolidPrimitiveTools.d.ts.map +0 -1
- package/lib/esm/SolidPrimitiveTools.js +0 -1372
- package/lib/esm/SolidPrimitiveTools.js.map +0 -1
|
@@ -1,772 +0,0 @@
|
|
|
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 { DialogProperty, PropertyDescriptionHelper } from "@itwin/appui-abstract";
|
|
6
|
-
import { CompressedId64Set } from "@itwin/core-bentley";
|
|
7
|
-
import { BentleyError, Code, ElementGeometry, ElementGeometryOpcode, } from "@itwin/core-common";
|
|
8
|
-
import { AccuDrawHintBuilder, IModelApp, LengthDescription, NotifyMessageDetails, OutputMessagePriority, } from "@itwin/core-frontend";
|
|
9
|
-
import { AngleSweep, Arc3d, AxisOrder, CurveChainWithDistanceIndex, CurveCollection, CurvePrimitive, FrameBuilder, Geometry, JointOptions, LineSegment3d, LineString3d, Loop, Matrix3d, Path, Plane3dByOriginAndUnitNormal, RegionBinaryOpType, RegionOps, UnionRegion, Vector3d, } from "@itwin/core-geometry";
|
|
10
|
-
import { editorBuiltInCmdIds } from "@itwin/editor-common";
|
|
11
|
-
import { EditTools } from "./EditTool";
|
|
12
|
-
import { basicManipulationIpc } from "./EditToolIpc";
|
|
13
|
-
import { ModifyElementWithDynamicsTool } from "./ModifyElementTool";
|
|
14
|
-
/** @alpha */
|
|
15
|
-
export class CurveData {
|
|
16
|
-
constructor(props, params, geom) {
|
|
17
|
-
this.props = props;
|
|
18
|
-
this.params = params;
|
|
19
|
-
this.geom = geom;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
/** @alpha Base class for modifying all types of curve geometry. */
|
|
23
|
-
export class ModifyCurveTool extends ModifyElementWithDynamicsTool {
|
|
24
|
-
async startCommand() {
|
|
25
|
-
if (undefined !== this._startedCmd)
|
|
26
|
-
return this._startedCmd;
|
|
27
|
-
return EditTools.startCommand({ commandId: editorBuiltInCmdIds.cmdBasicManipulation, iModelKey: this.iModel.key });
|
|
28
|
-
}
|
|
29
|
-
static isSingleCurve(info) {
|
|
30
|
-
const it = new ElementGeometry.Iterator(info);
|
|
31
|
-
it.requestWorldCoordinates();
|
|
32
|
-
for (const entry of it) {
|
|
33
|
-
const geom = entry.toGeometryQuery();
|
|
34
|
-
if (undefined === geom)
|
|
35
|
-
return;
|
|
36
|
-
if ("curvePrimitive" === geom.geometryCategory) {
|
|
37
|
-
return { curve: geom, params: entry.geomParams };
|
|
38
|
-
}
|
|
39
|
-
else if ("curveCollection" === geom.geometryCategory) {
|
|
40
|
-
return { curve: geom, params: entry.geomParams };
|
|
41
|
-
}
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
static isInPlane(curve, plane) {
|
|
47
|
-
if ("curvePrimitive" === curve.geometryCategory)
|
|
48
|
-
return curve.isInPlane(plane);
|
|
49
|
-
if (!curve.children)
|
|
50
|
-
return false;
|
|
51
|
-
for (const child of curve.children) {
|
|
52
|
-
if (child instanceof CurvePrimitive) {
|
|
53
|
-
if (!child.isInPlane(plane))
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
else if (child instanceof CurveCollection) {
|
|
57
|
-
if (!this.isInPlane(child, plane))
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
acceptCurve(_curve) { return true; }
|
|
64
|
-
modifyCurve(_ev, _isAccept) { return undefined; }
|
|
65
|
-
async getCurveData(id) {
|
|
66
|
-
try {
|
|
67
|
-
this._startedCmd = await this.startCommand();
|
|
68
|
-
const reject = [ElementGeometryOpcode.Polyface, ElementGeometryOpcode.SolidPrimitive, ElementGeometryOpcode.BsplineSurface, ElementGeometryOpcode.BRep];
|
|
69
|
-
const info = await basicManipulationIpc.requestElementGeometry(id, { maxDisplayable: 1, reject, geometry: { curves: true, surfaces: true, solids: false } });
|
|
70
|
-
if (undefined === info)
|
|
71
|
-
return undefined;
|
|
72
|
-
const data = ModifyCurveTool.isSingleCurve(info);
|
|
73
|
-
if (undefined === data)
|
|
74
|
-
return undefined;
|
|
75
|
-
if (!this.acceptCurve(data.curve))
|
|
76
|
-
return undefined;
|
|
77
|
-
const props = await this.iModel.elements.loadProps(id);
|
|
78
|
-
if (undefined === props)
|
|
79
|
-
return undefined;
|
|
80
|
-
return new CurveData(props, data.params, data.curve);
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err)));
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async doAcceptElementForOperation(id) {
|
|
88
|
-
return (undefined !== await this.getCurveData(id));
|
|
89
|
-
}
|
|
90
|
-
async onAgendaModified() {
|
|
91
|
-
this.curveData = undefined;
|
|
92
|
-
if (this.agenda.isEmpty)
|
|
93
|
-
return;
|
|
94
|
-
const id = this.agenda.elements[this.agenda.length - 1];
|
|
95
|
-
this.curveData = await this.getCurveData(id);
|
|
96
|
-
}
|
|
97
|
-
setupAccuDraw() {
|
|
98
|
-
const hints = new AccuDrawHintBuilder();
|
|
99
|
-
hints.enableSmartRotation = true;
|
|
100
|
-
hints.sendHints(false);
|
|
101
|
-
}
|
|
102
|
-
getGeometryProps(ev, isAccept) {
|
|
103
|
-
if (undefined === this.curveData)
|
|
104
|
-
return;
|
|
105
|
-
const geom = this.modifyCurve(ev, isAccept);
|
|
106
|
-
if (undefined === geom)
|
|
107
|
-
return;
|
|
108
|
-
const builder = new ElementGeometry.Builder();
|
|
109
|
-
builder.setLocalToWorldFromPlacement(this.curveData.props.placement);
|
|
110
|
-
if (!builder.appendGeometryParamsChange(this.curveData.params))
|
|
111
|
-
return;
|
|
112
|
-
if (!builder.appendGeometryQuery(geom))
|
|
113
|
-
return;
|
|
114
|
-
return { format: "flatbuffer", data: builder.entries };
|
|
115
|
-
}
|
|
116
|
-
getElementProps(ev) {
|
|
117
|
-
if (undefined === this.curveData)
|
|
118
|
-
return;
|
|
119
|
-
if (!this.wantModifyOriginal) {
|
|
120
|
-
// Create result as new element with same model and category as original...
|
|
121
|
-
const classFullName = (ev.viewport?.view.is3d() ? "Generic:PhysicalObject" : "BisCore:DrawingGraphic");
|
|
122
|
-
return { classFullName, model: this.curveData.props.model, category: this.curveData.props.category, code: Code.createEmpty(), placement: this.curveData.props.placement };
|
|
123
|
-
}
|
|
124
|
-
return this.curveData.props;
|
|
125
|
-
}
|
|
126
|
-
async doUpdateElement(elemProps) {
|
|
127
|
-
try {
|
|
128
|
-
this._startedCmd = await this.startCommand();
|
|
129
|
-
if (undefined === elemProps.id) {
|
|
130
|
-
const repeatOperation = this.wantContinueWithPreviousResult;
|
|
131
|
-
if (repeatOperation)
|
|
132
|
-
this.agenda.clear();
|
|
133
|
-
const newId = await basicManipulationIpc.insertGeometricElement(elemProps);
|
|
134
|
-
if (repeatOperation && this.agenda.add(newId))
|
|
135
|
-
await this.onAgendaModified();
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
await basicManipulationIpc.updateGeometricElement(elemProps);
|
|
139
|
-
}
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."));
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
get wantModifyOriginal() { return true; }
|
|
148
|
-
get wantContinueWithPreviousResult() { return false; }
|
|
149
|
-
async onProcessComplete() {
|
|
150
|
-
// Don't restart tool want to continue operation using previous result...
|
|
151
|
-
if (this.wantContinueWithPreviousResult && !this.agenda.isEmpty && undefined !== this.curveData)
|
|
152
|
-
return;
|
|
153
|
-
return super.onProcessComplete();
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/** @alpha Tool for applying an offset to paths and loops. */
|
|
157
|
-
class OffsetCurveTool extends ModifyCurveTool {
|
|
158
|
-
get useDistanceProperty() {
|
|
159
|
-
if (!this._useDistanceProperty)
|
|
160
|
-
this._useDistanceProperty = new DialogProperty(PropertyDescriptionHelper.buildLockPropertyDescription("useOffsetDistance"), false);
|
|
161
|
-
return this._useDistanceProperty;
|
|
162
|
-
}
|
|
163
|
-
get useDistance() { return this.useDistanceProperty.value; }
|
|
164
|
-
set useDistance(value) { this.useDistanceProperty.value = value; }
|
|
165
|
-
get distanceProperty() {
|
|
166
|
-
if (!this._distanceProperty)
|
|
167
|
-
this._distanceProperty = new DialogProperty(new LengthDescription("offsetDistance", EditTools.translate("OffsetCurve.Label.Distance")), 0.1, undefined, !this.useDistance);
|
|
168
|
-
return this._distanceProperty;
|
|
169
|
-
}
|
|
170
|
-
get distance() { return this.distanceProperty.value; }
|
|
171
|
-
set distance(value) { this.distanceProperty.value = value; }
|
|
172
|
-
get makeCopyProperty() {
|
|
173
|
-
if (!this._makeCopyProperty)
|
|
174
|
-
this._makeCopyProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("offsetCopy", EditTools.translate("OffsetCurve.Label.MakeCopy")), false);
|
|
175
|
-
return this._makeCopyProperty;
|
|
176
|
-
}
|
|
177
|
-
get makeCopy() { return this.makeCopyProperty.value; }
|
|
178
|
-
set makeCopy(value) { this.makeCopyProperty.value = value; }
|
|
179
|
-
getToolSettingPropertyLocked(property) {
|
|
180
|
-
return (property === this.useDistanceProperty ? this.distanceProperty : undefined);
|
|
181
|
-
}
|
|
182
|
-
async applyToolSettingPropertyChange(updatedValue) {
|
|
183
|
-
return this.changeToolSettingPropertyValue(updatedValue);
|
|
184
|
-
}
|
|
185
|
-
supplyToolSettingsProperties() {
|
|
186
|
-
this.initializeToolSettingPropertyValues([this.makeCopyProperty, this.useDistanceProperty, this.distanceProperty]);
|
|
187
|
-
const toolSettings = new Array();
|
|
188
|
-
// ensure controls are enabled/disabled based on current lock property state
|
|
189
|
-
this.distanceProperty.isDisabled = !this.useDistance;
|
|
190
|
-
const useDistanceLock = this.useDistanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 });
|
|
191
|
-
toolSettings.push(this.distanceProperty.toDialogItem({ rowPriority: 1, columnIndex: 1 }, useDistanceLock));
|
|
192
|
-
toolSettings.push(this.makeCopyProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
|
|
193
|
-
return toolSettings;
|
|
194
|
-
}
|
|
195
|
-
acceptCurve(curve) {
|
|
196
|
-
if ("curvePrimitive" === curve.geometryCategory)
|
|
197
|
-
return true;
|
|
198
|
-
return (curve.isOpenPath || curve.isClosedPath);
|
|
199
|
-
}
|
|
200
|
-
modifyCurve(ev, isAccept) {
|
|
201
|
-
if (undefined === ev.viewport)
|
|
202
|
-
return undefined;
|
|
203
|
-
const geom = this.curveData?.geom;
|
|
204
|
-
if (undefined === geom)
|
|
205
|
-
return undefined;
|
|
206
|
-
const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
|
|
207
|
-
const localToWorld = FrameBuilder.createRightHandedFrame(matrix?.getColumn(2), geom);
|
|
208
|
-
if (undefined === localToWorld)
|
|
209
|
-
return undefined;
|
|
210
|
-
const worldToLocal = localToWorld.inverse();
|
|
211
|
-
if (undefined === worldToLocal)
|
|
212
|
-
return undefined;
|
|
213
|
-
const geomXY = ((geom instanceof CurvePrimitive) ? Path.create(geom) : geom).cloneTransformed(worldToLocal);
|
|
214
|
-
if (undefined === geomXY)
|
|
215
|
-
return undefined;
|
|
216
|
-
const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
|
|
217
|
-
if (undefined === spacePoint)
|
|
218
|
-
return undefined;
|
|
219
|
-
worldToLocal.multiplyPoint3d(spacePoint, spacePoint);
|
|
220
|
-
spacePoint.z = 0.0;
|
|
221
|
-
const closeDetail = geomXY.closestPoint(spacePoint);
|
|
222
|
-
if (undefined === closeDetail?.curve)
|
|
223
|
-
return undefined;
|
|
224
|
-
const unitZ = Vector3d.unitZ();
|
|
225
|
-
const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
|
|
226
|
-
const unitY = unitZ.unitCrossProduct(unitX);
|
|
227
|
-
if (undefined === unitY)
|
|
228
|
-
return undefined;
|
|
229
|
-
let distance = closeDetail.point.distance(spacePoint);
|
|
230
|
-
const refDir = Vector3d.createStartEnd(closeDetail.point, spacePoint);
|
|
231
|
-
if (refDir.dotProduct(unitY) < 0.0)
|
|
232
|
-
distance = -distance;
|
|
233
|
-
let offset = 0.0;
|
|
234
|
-
if (this.useDistance) {
|
|
235
|
-
offset = this.distance;
|
|
236
|
-
if ((offset < 0.0 && distance > 0.0) || (offset > 0.0 && distance < 0.0))
|
|
237
|
-
offset = -offset;
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
offset = distance;
|
|
241
|
-
}
|
|
242
|
-
if (Math.abs(offset) < Geometry.smallMetricDistance)
|
|
243
|
-
return undefined;
|
|
244
|
-
if (offset !== this.distance) {
|
|
245
|
-
this.distance = offset;
|
|
246
|
-
this.syncToolSettingPropertyValue(this.distanceProperty);
|
|
247
|
-
if (isAccept)
|
|
248
|
-
this.saveToolSettingPropertyValue(this.distanceProperty, this.distanceProperty.dialogItemValue);
|
|
249
|
-
}
|
|
250
|
-
const jointOptions = new JointOptions(offset);
|
|
251
|
-
jointOptions.preserveEllipticalArcs = true;
|
|
252
|
-
const offsetGeom = RegionOps.constructCurveXYOffset(geomXY, jointOptions);
|
|
253
|
-
if (undefined === offsetGeom)
|
|
254
|
-
return undefined;
|
|
255
|
-
if (!offsetGeom.tryTransformInPlace(localToWorld))
|
|
256
|
-
return undefined;
|
|
257
|
-
if (geom instanceof CurvePrimitive && offsetGeom instanceof Path && 1 === offsetGeom.children.length)
|
|
258
|
-
return offsetGeom.getChild(0); // Don't create path for offset of single open curve...
|
|
259
|
-
return offsetGeom;
|
|
260
|
-
}
|
|
261
|
-
get wantModifyOriginal() {
|
|
262
|
-
return !this.makeCopy;
|
|
263
|
-
}
|
|
264
|
-
get wantContinueWithPreviousResult() {
|
|
265
|
-
return !this.wantModifyOriginal;
|
|
266
|
-
}
|
|
267
|
-
setupAccuDraw() {
|
|
268
|
-
const hints = new AccuDrawHintBuilder();
|
|
269
|
-
if (this.agenda.isEmpty) {
|
|
270
|
-
hints.enableSmartRotation = true;
|
|
271
|
-
}
|
|
272
|
-
else if (undefined !== this.anchorPoint && undefined !== this.targetView) {
|
|
273
|
-
const geom = this.curveData?.geom;
|
|
274
|
-
const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(this.anchorPoint, false) : geom?.closestPoint(this.anchorPoint);
|
|
275
|
-
if (undefined !== closeDetail?.curve) {
|
|
276
|
-
const unitX = closeDetail.curve.fractionToPointAndUnitTangent(closeDetail.fraction).direction;
|
|
277
|
-
if (undefined !== unitX) {
|
|
278
|
-
const matrix = AccuDrawHintBuilder.getCurrentRotation(this.targetView, true, true);
|
|
279
|
-
const localToWorld = FrameBuilder.createRightHandedFrame(matrix?.getColumn(2), geom);
|
|
280
|
-
if (undefined !== localToWorld) {
|
|
281
|
-
const unitZ = localToWorld.matrix.getColumn(2);
|
|
282
|
-
const frame = Matrix3d.createRigidFromColumns(unitX, unitZ, AxisOrder.XZY);
|
|
283
|
-
if (undefined !== frame) {
|
|
284
|
-
hints.setOrigin(closeDetail.point);
|
|
285
|
-
hints.setMatrix(frame);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
hints.sendHints(false);
|
|
292
|
-
}
|
|
293
|
-
provideToolAssistance(_mainInstrText, _additionalInstr) {
|
|
294
|
-
let mainMsg;
|
|
295
|
-
if (!this.agenda.isEmpty)
|
|
296
|
-
mainMsg = EditTools.translate("OffsetCurve.Prompts.DefineOffset");
|
|
297
|
-
super.provideToolAssistance(mainMsg);
|
|
298
|
-
}
|
|
299
|
-
async onRestartTool() {
|
|
300
|
-
const tool = new OffsetCurveTool();
|
|
301
|
-
if (!await tool.run())
|
|
302
|
-
return this.exitTool();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
OffsetCurveTool.toolId = "OffsetCurve";
|
|
306
|
-
OffsetCurveTool.iconSpec = "icon-scale"; // Need better icon...
|
|
307
|
-
export { OffsetCurveTool };
|
|
308
|
-
/** @alpha Tool for opening loops and splitting paths. */
|
|
309
|
-
class BreakCurveTool extends ModifyCurveTool {
|
|
310
|
-
constructor() {
|
|
311
|
-
super(...arguments);
|
|
312
|
-
this.modifyOriginal = true;
|
|
313
|
-
}
|
|
314
|
-
get wantDynamics() { return false; }
|
|
315
|
-
get wantModifyOriginal() { return this.modifyOriginal; }
|
|
316
|
-
acceptCurve(curve) {
|
|
317
|
-
if ("curvePrimitive" === curve.geometryCategory)
|
|
318
|
-
return true;
|
|
319
|
-
return (curve.isOpenPath || curve.isClosedPath);
|
|
320
|
-
}
|
|
321
|
-
doBreakCurve(ev) {
|
|
322
|
-
this.resultA = this.resultB = undefined;
|
|
323
|
-
if (undefined === ev.viewport)
|
|
324
|
-
return;
|
|
325
|
-
const geom = this.curveData?.geom;
|
|
326
|
-
if (undefined === geom)
|
|
327
|
-
return;
|
|
328
|
-
const closeDetail = (geom instanceof CurvePrimitive) ? geom.closestPoint(ev.point, false) : geom.closestPoint(ev.point);
|
|
329
|
-
if (undefined === closeDetail?.curve)
|
|
330
|
-
return;
|
|
331
|
-
const selectedStart = (closeDetail.fraction <= Geometry.smallFraction);
|
|
332
|
-
const selectedEnd = (closeDetail.fraction >= (1.0 - Geometry.smallFraction));
|
|
333
|
-
if (geom instanceof CurvePrimitive) {
|
|
334
|
-
if (selectedStart || selectedEnd)
|
|
335
|
-
return; // split is no-op...
|
|
336
|
-
this.resultA = geom.clonePartialCurve(0.0, closeDetail.fraction);
|
|
337
|
-
this.resultB = geom.clonePartialCurve(closeDetail.fraction, 1.0);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
else if (geom instanceof Path) {
|
|
341
|
-
const firstCurve = geom.children[0];
|
|
342
|
-
const lastCurve = geom.children[geom.children.length - 1];
|
|
343
|
-
if ((closeDetail.curve === firstCurve && selectedStart) || (closeDetail.curve === lastCurve && selectedEnd))
|
|
344
|
-
return; // split is no-op...
|
|
345
|
-
let beforeCurve = true;
|
|
346
|
-
const resultA = Path.create();
|
|
347
|
-
const resultB = Path.create();
|
|
348
|
-
for (const curve of geom.children) {
|
|
349
|
-
if (curve === closeDetail.curve) {
|
|
350
|
-
if (selectedStart) {
|
|
351
|
-
resultB.children.push(curve.clone());
|
|
352
|
-
}
|
|
353
|
-
else if (selectedEnd) {
|
|
354
|
-
resultA.children.push(curve.clone());
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
const curveA = curve.clonePartialCurve(0.0, closeDetail.fraction);
|
|
358
|
-
if (undefined !== curveA)
|
|
359
|
-
resultA.children.push(curveA);
|
|
360
|
-
const curveB = curve.clonePartialCurve(closeDetail.fraction, 1.0);
|
|
361
|
-
if (undefined !== curveB)
|
|
362
|
-
resultB.children.push(curveB);
|
|
363
|
-
}
|
|
364
|
-
beforeCurve = false;
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
if (beforeCurve)
|
|
368
|
-
resultA.children.push(curve.clone());
|
|
369
|
-
else
|
|
370
|
-
resultB.children.push(curve.clone());
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
this.resultA = resultA;
|
|
374
|
-
this.resultB = resultB;
|
|
375
|
-
}
|
|
376
|
-
else if (geom instanceof Loop) {
|
|
377
|
-
const closeIndex = geom.children.findIndex((child) => child === closeDetail.curve);
|
|
378
|
-
if (-1 === closeIndex)
|
|
379
|
-
return;
|
|
380
|
-
const endIndex = closeIndex + geom.children.length;
|
|
381
|
-
const resultA = Path.create(); // Result is always a single path...
|
|
382
|
-
if (selectedStart) {
|
|
383
|
-
resultA.children.push(closeDetail.curve.clone());
|
|
384
|
-
}
|
|
385
|
-
else if (!selectedEnd) {
|
|
386
|
-
const curveB = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 1.0);
|
|
387
|
-
if (undefined !== curveB)
|
|
388
|
-
resultA.children.push(curveB);
|
|
389
|
-
}
|
|
390
|
-
for (let index = closeIndex; index < endIndex; ++index) {
|
|
391
|
-
const curve = geom.cyclicCurvePrimitive(index);
|
|
392
|
-
if (undefined === curve || curve === closeDetail.curve)
|
|
393
|
-
continue;
|
|
394
|
-
resultA.children.push(curve.clone());
|
|
395
|
-
}
|
|
396
|
-
if (selectedEnd) {
|
|
397
|
-
resultA.children.push(closeDetail.curve.clone());
|
|
398
|
-
}
|
|
399
|
-
else if (!selectedStart) {
|
|
400
|
-
const curveA = closeDetail.curve.clonePartialCurve(0.0, closeDetail.fraction);
|
|
401
|
-
if (undefined !== curveA)
|
|
402
|
-
resultA.children.push(curveA);
|
|
403
|
-
}
|
|
404
|
-
this.resultA = resultA;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
modifyCurve(_ev, _isAccept) {
|
|
408
|
-
return (this.wantModifyOriginal ? this.resultA : this.resultB);
|
|
409
|
-
}
|
|
410
|
-
async processAgenda(ev) {
|
|
411
|
-
this.doBreakCurve(ev);
|
|
412
|
-
if (undefined === this.resultA || !await this.applyAgendaOperation(ev))
|
|
413
|
-
return;
|
|
414
|
-
if (undefined !== this.resultB) {
|
|
415
|
-
this.modifyOriginal = false;
|
|
416
|
-
await this.applyAgendaOperation(ev);
|
|
417
|
-
}
|
|
418
|
-
return this.saveChanges();
|
|
419
|
-
}
|
|
420
|
-
provideToolAssistance(_mainInstrText, _additionalInstr) {
|
|
421
|
-
let mainMsg;
|
|
422
|
-
if (this.agenda.isEmpty)
|
|
423
|
-
mainMsg = EditTools.translate("BreakCurve.Prompts.IdentifyBreak");
|
|
424
|
-
super.provideToolAssistance(mainMsg);
|
|
425
|
-
}
|
|
426
|
-
async onRestartTool() {
|
|
427
|
-
const tool = new BreakCurveTool();
|
|
428
|
-
if (!await tool.run())
|
|
429
|
-
return this.exitTool();
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
BreakCurveTool.toolId = "BreakCurve";
|
|
433
|
-
BreakCurveTool.iconSpec = "icon-scale"; // Need better icon...
|
|
434
|
-
export { BreakCurveTool };
|
|
435
|
-
/** @alpha Tool to extend or trim a path or open curve */
|
|
436
|
-
class ExtendCurveTool extends ModifyCurveTool {
|
|
437
|
-
get wantAgendaAppearanceOverride() { return true; }
|
|
438
|
-
acceptCurve(curve) {
|
|
439
|
-
if ("curvePrimitive" === curve.geometryCategory)
|
|
440
|
-
return curve.isExtensibleFractionSpace;
|
|
441
|
-
return curve.isOpenPath;
|
|
442
|
-
}
|
|
443
|
-
extendCurve(geom, pickPoint, spacePoint) {
|
|
444
|
-
const pickDetail = geom.closestPoint(pickPoint, false);
|
|
445
|
-
if (undefined === pickDetail?.curve)
|
|
446
|
-
return undefined;
|
|
447
|
-
const closeDetail = geom.closestPoint(spacePoint, true);
|
|
448
|
-
if (undefined === closeDetail?.curve)
|
|
449
|
-
return undefined;
|
|
450
|
-
if (closeDetail.curve instanceof Arc3d) {
|
|
451
|
-
if (pickDetail.fraction > 0.5 && closeDetail.fraction < 0.0) {
|
|
452
|
-
const smallArc = closeDetail.curve.clonePartialCurve(closeDetail.fraction, 0.0);
|
|
453
|
-
smallArc.sweep.cloneComplement(false, smallArc.sweep);
|
|
454
|
-
return smallArc;
|
|
455
|
-
}
|
|
456
|
-
else if (pickDetail.fraction <= 0.5 && closeDetail.fraction > 1.0) {
|
|
457
|
-
const smallArc = closeDetail.curve.clonePartialCurve(1.0, closeDetail.fraction);
|
|
458
|
-
smallArc.sweep.cloneComplement(false, smallArc.sweep);
|
|
459
|
-
return smallArc;
|
|
460
|
-
}
|
|
461
|
-
else if (Math.abs(pickDetail.fraction > 0.5 ? closeDetail.fraction : 1.0 - closeDetail.fraction) < Geometry.smallFraction) {
|
|
462
|
-
const fullArc = closeDetail.curve.clone();
|
|
463
|
-
fullArc.sweep = AngleSweep.create360();
|
|
464
|
-
return fullArc;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
return geom.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
|
|
468
|
-
}
|
|
469
|
-
extendPathEnd(geom, closeDetail, isStart) {
|
|
470
|
-
if (undefined === closeDetail.curve)
|
|
471
|
-
return undefined;
|
|
472
|
-
const curve = closeDetail.curve.clonePartialCurve(isStart ? closeDetail.fraction : 0.0, isStart ? 1.0 : closeDetail.fraction);
|
|
473
|
-
if (undefined === curve)
|
|
474
|
-
return undefined;
|
|
475
|
-
if (curve instanceof Arc3d && closeDetail.curve instanceof Arc3d && (curve.sweep.isCCW !== closeDetail.curve.sweep.isCCW))
|
|
476
|
-
curve.sweep.cloneComplement(true, curve.sweep); // Preserve current sweep direction...
|
|
477
|
-
const result = geom.clone();
|
|
478
|
-
result.children[isStart ? 0 : geom.children.length - 1] = curve;
|
|
479
|
-
return result;
|
|
480
|
-
}
|
|
481
|
-
extendPath(geom, pickPoint, spacePoint) {
|
|
482
|
-
if (geom.children.length < 2)
|
|
483
|
-
return this.extendCurve(geom.children[0], pickPoint, spacePoint);
|
|
484
|
-
const pathAsPrimitive = CurveChainWithDistanceIndex.createCapture(geom);
|
|
485
|
-
const closeDetail = pathAsPrimitive.closestPoint(spacePoint, true);
|
|
486
|
-
if (undefined === closeDetail?.curve || undefined === closeDetail.childDetail?.curve)
|
|
487
|
-
return undefined;
|
|
488
|
-
if (undefined !== this.modifyingEnd) {
|
|
489
|
-
if (closeDetail.childDetail.curve === this.modifyingEnd) {
|
|
490
|
-
this.modifyingEnd = undefined; // Ok to unlock extending first/last curve in path...
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
const pathEndDetail = this.modifyingEnd.closestPoint(spacePoint, true);
|
|
494
|
-
if (undefined === pathEndDetail?.curve)
|
|
495
|
-
return undefined;
|
|
496
|
-
return this.extendPathEnd(geom, pathEndDetail, (pathEndDetail.curve === geom.children[0]));
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
// NOTE: Special case extend instead of using CurveChainWithDistanceIndex.clonePartialCurve...
|
|
500
|
-
if (closeDetail.fraction < 0.0) {
|
|
501
|
-
this.modifyingEnd = closeDetail.childDetail.curve;
|
|
502
|
-
return this.extendPathEnd(geom, closeDetail.childDetail, true);
|
|
503
|
-
}
|
|
504
|
-
else if (closeDetail.fraction > 1.0) {
|
|
505
|
-
this.modifyingEnd = closeDetail.childDetail.curve;
|
|
506
|
-
return this.extendPathEnd(geom, closeDetail.childDetail, false);
|
|
507
|
-
}
|
|
508
|
-
const pickDetail = pathAsPrimitive.closestPoint(pickPoint, false);
|
|
509
|
-
if (undefined === pickDetail?.curve)
|
|
510
|
-
return undefined;
|
|
511
|
-
const result = pathAsPrimitive.clonePartialCurve(pickDetail.fraction > 0.5 ? 0.0 : 1.0, closeDetail.fraction);
|
|
512
|
-
if (undefined === result)
|
|
513
|
-
return undefined;
|
|
514
|
-
return Path.create(...result.path.children);
|
|
515
|
-
}
|
|
516
|
-
modifyCurve(ev, _isAccept) {
|
|
517
|
-
if (undefined === ev.viewport || undefined === this.anchorPoint)
|
|
518
|
-
return undefined;
|
|
519
|
-
const geom = this.curveData?.geom;
|
|
520
|
-
if (undefined === geom)
|
|
521
|
-
return undefined;
|
|
522
|
-
const matrix = AccuDrawHintBuilder.getCurrentRotation(ev.viewport, true, true);
|
|
523
|
-
const localToWorld = FrameBuilder.createRightHandedFrame(matrix?.getColumn(2), geom);
|
|
524
|
-
if (undefined === localToWorld)
|
|
525
|
-
return undefined;
|
|
526
|
-
const worldToLocal = localToWorld.inverse();
|
|
527
|
-
if (undefined === worldToLocal)
|
|
528
|
-
return undefined;
|
|
529
|
-
const spacePoint = AccuDrawHintBuilder.projectPointToPlaneInView(ev.point, localToWorld.getOrigin(), localToWorld.matrix.getColumn(2), ev.viewport);
|
|
530
|
-
if (undefined === spacePoint)
|
|
531
|
-
return undefined;
|
|
532
|
-
if (geom instanceof CurvePrimitive)
|
|
533
|
-
return this.extendCurve(geom, this.anchorPoint, spacePoint);
|
|
534
|
-
else if (geom instanceof Path)
|
|
535
|
-
return this.extendPath(geom, this.anchorPoint, spacePoint);
|
|
536
|
-
return undefined;
|
|
537
|
-
}
|
|
538
|
-
async onAgendaModified() {
|
|
539
|
-
IModelApp.accuSnap.neverFlash(this.agenda.elements); // Don't flash snapped segment for better preview when trimming curve/path...
|
|
540
|
-
return super.onAgendaModified();
|
|
541
|
-
}
|
|
542
|
-
setupAccuDraw() {
|
|
543
|
-
const hints = new AccuDrawHintBuilder();
|
|
544
|
-
if (this.agenda.isEmpty) {
|
|
545
|
-
hints.enableSmartRotation = true;
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
const geom = this.curveData?.geom;
|
|
549
|
-
if (undefined === geom || undefined === this.anchorPoint)
|
|
550
|
-
return;
|
|
551
|
-
let pickDetail;
|
|
552
|
-
if (geom instanceof CurvePrimitive)
|
|
553
|
-
pickDetail = geom.closestPoint(this.anchorPoint, false);
|
|
554
|
-
else if (geom instanceof Path)
|
|
555
|
-
pickDetail = CurveChainWithDistanceIndex.createCapture(geom).closestPoint(this.anchorPoint, false);
|
|
556
|
-
if (undefined === pickDetail?.curve)
|
|
557
|
-
return;
|
|
558
|
-
const curve = (undefined !== pickDetail.childDetail?.curve ? pickDetail.childDetail?.curve : pickDetail.curve);
|
|
559
|
-
if (curve instanceof Arc3d) {
|
|
560
|
-
const matrix = curve.matrixClone();
|
|
561
|
-
matrix.normalizeColumnsInPlace();
|
|
562
|
-
hints.setOrigin(curve.center);
|
|
563
|
-
hints.setMatrix(matrix);
|
|
564
|
-
hints.setModePolar();
|
|
565
|
-
}
|
|
566
|
-
else if (curve instanceof LineSegment3d) {
|
|
567
|
-
hints.setOrigin(pickDetail.fraction > 0.5 ? curve.point0Ref : curve.point1Ref);
|
|
568
|
-
hints.setXAxis(Vector3d.createStartEnd(pickDetail.fraction > 0.5 ? curve.point0Ref : curve.point1Ref, pickDetail.fraction > 0.5 ? curve.point1Ref : curve.point0Ref));
|
|
569
|
-
hints.setModeRectangular();
|
|
570
|
-
}
|
|
571
|
-
else if (curve instanceof LineString3d) {
|
|
572
|
-
if (curve.numPoints() > 1) {
|
|
573
|
-
hints.setOrigin(curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 2 : 1));
|
|
574
|
-
hints.setXAxis(Vector3d.createStartEnd(curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 2 : 1), curve.packedPoints.getPoint3dAtUncheckedPointIndex(pickDetail.fraction > 0.5 ? curve.numPoints() - 1 : 0)));
|
|
575
|
-
}
|
|
576
|
-
hints.setModeRectangular();
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
579
|
-
const ray = curve.fractionToPointAndUnitTangent(pickDetail.fraction > 0.5 ? 0.0 : 1.0);
|
|
580
|
-
hints.setOrigin(ray.origin);
|
|
581
|
-
hints.setXAxis(ray.direction);
|
|
582
|
-
hints.setModeRectangular();
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
hints.sendHints(false);
|
|
586
|
-
}
|
|
587
|
-
provideToolAssistance(_mainInstrText, _additionalInstr) {
|
|
588
|
-
let mainMsg;
|
|
589
|
-
if (this.agenda.isEmpty)
|
|
590
|
-
mainMsg = EditTools.translate("ExtendCurve.Prompts.IdentifyEnd");
|
|
591
|
-
super.provideToolAssistance(mainMsg);
|
|
592
|
-
}
|
|
593
|
-
async onRestartTool() {
|
|
594
|
-
const tool = new ExtendCurveTool();
|
|
595
|
-
if (!await tool.run())
|
|
596
|
-
return this.exitTool();
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
ExtendCurveTool.toolId = "ExtendCurve";
|
|
600
|
-
ExtendCurveTool.iconSpec = "icon-scale"; // Need better icon...
|
|
601
|
-
export { ExtendCurveTool };
|
|
602
|
-
/** @alpha */
|
|
603
|
-
export var RegionBooleanMode;
|
|
604
|
-
(function (RegionBooleanMode) {
|
|
605
|
-
/** Create region from union of all input regions */
|
|
606
|
-
RegionBooleanMode[RegionBooleanMode["Unite"] = 0] = "Unite";
|
|
607
|
-
/** Create region from subtraction from the first input region */
|
|
608
|
-
RegionBooleanMode[RegionBooleanMode["Subtract"] = 1] = "Subtract";
|
|
609
|
-
/** Create region from intersection of all input regions */
|
|
610
|
-
RegionBooleanMode[RegionBooleanMode["Intersect"] = 2] = "Intersect";
|
|
611
|
-
})(RegionBooleanMode || (RegionBooleanMode = {}));
|
|
612
|
-
/** @alpha Tool to unite, subtract, or intersect planar regions. */
|
|
613
|
-
class RegionBooleanTool extends ModifyCurveTool {
|
|
614
|
-
get makeCopyProperty() {
|
|
615
|
-
if (!this._makeCopyProperty)
|
|
616
|
-
this._makeCopyProperty = new DialogProperty(PropertyDescriptionHelper.buildToggleDescription("regionBooleanKeep", EditTools.translate("RegionBoolean.Label.KeepOriginal")), false);
|
|
617
|
-
return this._makeCopyProperty;
|
|
618
|
-
}
|
|
619
|
-
get makeCopy() { return this.makeCopyProperty.value; }
|
|
620
|
-
set makeCopy(value) { this.makeCopyProperty.value = value; }
|
|
621
|
-
static modeMessage(str) { return EditTools.translate(`RegionBoolean.Mode.${str}`); }
|
|
622
|
-
get modeProperty() {
|
|
623
|
-
if (!this._modeProperty)
|
|
624
|
-
this._modeProperty = new DialogProperty(PropertyDescriptionHelper.buildEnumPicklistEditorDescription("regionBooleanMode", EditTools.translate("RegionBoolean.Label.Mode"), RegionBooleanTool.getModeChoices()), RegionBooleanMode.Unite);
|
|
625
|
-
return this._modeProperty;
|
|
626
|
-
}
|
|
627
|
-
get mode() { return this.modeProperty.value; }
|
|
628
|
-
set mode(mode) { this.modeProperty.value = mode; }
|
|
629
|
-
get clearSelectionSet() { return false; } // Don't clear for subtract so that mode can be changed...
|
|
630
|
-
get allowSelectionSet() { return RegionBooleanMode.Subtract !== this.mode; }
|
|
631
|
-
get allowDragSelect() { return RegionBooleanMode.Subtract !== this.mode; }
|
|
632
|
-
get controlKeyContinuesSelection() { return true; }
|
|
633
|
-
get requiredElementCount() { return 2; }
|
|
634
|
-
get wantAccuSnap() { return false; }
|
|
635
|
-
get wantDynamics() { return false; }
|
|
636
|
-
get wantModifyOriginal() { return !this.makeCopy; }
|
|
637
|
-
async onAgendaModified() { } // No intermediate result preview, defer to processAgenda...
|
|
638
|
-
acceptCurve(curve) {
|
|
639
|
-
if ("curvePrimitive" === curve.geometryCategory)
|
|
640
|
-
return false;
|
|
641
|
-
return curve.isAnyRegionType;
|
|
642
|
-
}
|
|
643
|
-
regionBinaryOp() {
|
|
644
|
-
switch (this.mode) {
|
|
645
|
-
case RegionBooleanMode.Subtract:
|
|
646
|
-
return RegionBinaryOpType.AMinusB;
|
|
647
|
-
case RegionBooleanMode.Intersect:
|
|
648
|
-
return RegionBinaryOpType.Intersection;
|
|
649
|
-
default:
|
|
650
|
-
return RegionBinaryOpType.Union;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
regionFromSignedLoops(loops) {
|
|
654
|
-
switch (loops.negativeAreaLoops.length) {
|
|
655
|
-
case 0:
|
|
656
|
-
return undefined;
|
|
657
|
-
case 1:
|
|
658
|
-
return loops.negativeAreaLoops[0];
|
|
659
|
-
default:
|
|
660
|
-
return RegionOps.sortOuterAndHoleLoopsXY(loops.negativeAreaLoops);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
regionBooleanXY(tools, op) {
|
|
664
|
-
if (tools.length < 2)
|
|
665
|
-
return undefined;
|
|
666
|
-
const loopsA = (RegionBinaryOpType.Union !== op ? tools[0] : tools);
|
|
667
|
-
const loopsB = (RegionBinaryOpType.Union !== op ? tools.slice(1) : undefined);
|
|
668
|
-
// TODO: Need to be able to specify group operation for loopsB to correctly support intersect w/o doing 2 at time...
|
|
669
|
-
const areas = RegionOps.regionBooleanXY(loopsA, loopsB, op);
|
|
670
|
-
if (undefined === areas)
|
|
671
|
-
return undefined;
|
|
672
|
-
// TODO: Holes are expected to be returned as negative area loops but currently are not...
|
|
673
|
-
const loops = RegionOps.constructAllXYRegionLoops(areas);
|
|
674
|
-
if (1 === loops.length)
|
|
675
|
-
return this.regionFromSignedLoops(loops[0]);
|
|
676
|
-
if (loops.length > 1) {
|
|
677
|
-
const unionRegion = UnionRegion.create();
|
|
678
|
-
for (const loop of loops) {
|
|
679
|
-
const child = this.regionFromSignedLoops(loop);
|
|
680
|
-
if (undefined === child)
|
|
681
|
-
continue;
|
|
682
|
-
unionRegion.tryAddChild(child);
|
|
683
|
-
}
|
|
684
|
-
if (unionRegion.children.length > 1)
|
|
685
|
-
return unionRegion;
|
|
686
|
-
}
|
|
687
|
-
return undefined;
|
|
688
|
-
}
|
|
689
|
-
async doRegionBoolean(_ev) {
|
|
690
|
-
this.curveData = undefined;
|
|
691
|
-
if (this.agenda.length < this.requiredElementCount)
|
|
692
|
-
return;
|
|
693
|
-
const targetData = await this.getCurveData(this.agenda.elements[0]);
|
|
694
|
-
if (undefined === targetData?.geom)
|
|
695
|
-
return;
|
|
696
|
-
const targetLocalToWorld = FrameBuilder.createRightHandedFrame(undefined, targetData.geom);
|
|
697
|
-
if (undefined === targetLocalToWorld)
|
|
698
|
-
return;
|
|
699
|
-
const targetWorldToLocal = targetLocalToWorld.inverse();
|
|
700
|
-
if (undefined === targetWorldToLocal)
|
|
701
|
-
return;
|
|
702
|
-
const targetPlane = Plane3dByOriginAndUnitNormal.create(targetLocalToWorld.getOrigin(), targetLocalToWorld.matrix.getColumn(2));
|
|
703
|
-
if (undefined === targetPlane)
|
|
704
|
-
return;
|
|
705
|
-
if (!targetData.geom.tryTransformInPlace(targetWorldToLocal))
|
|
706
|
-
return;
|
|
707
|
-
const tools = [targetData.geom];
|
|
708
|
-
for (const id of this.agenda.elements) {
|
|
709
|
-
if (id === targetData.props.id)
|
|
710
|
-
continue;
|
|
711
|
-
const curveData = await this.getCurveData(id);
|
|
712
|
-
if (undefined === curveData?.geom)
|
|
713
|
-
return;
|
|
714
|
-
if (!ModifyCurveTool.isInPlane(curveData.geom, targetPlane)) {
|
|
715
|
-
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, EditTools.translate("RegionBoolean.Error.NonCoplanar")));
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
if (!curveData.geom.tryTransformInPlace(targetWorldToLocal))
|
|
719
|
-
return;
|
|
720
|
-
tools.push(curveData.geom);
|
|
721
|
-
}
|
|
722
|
-
const result = this.regionBooleanXY(tools, this.regionBinaryOp());
|
|
723
|
-
if (undefined === result || !result.tryTransformInPlace(targetLocalToWorld))
|
|
724
|
-
return;
|
|
725
|
-
this.curveData = targetData;
|
|
726
|
-
this.curveData.geom = result;
|
|
727
|
-
}
|
|
728
|
-
modifyCurve(_ev, _isAccept) {
|
|
729
|
-
return this.curveData?.geom;
|
|
730
|
-
}
|
|
731
|
-
async applyAgendaOperation(ev) {
|
|
732
|
-
if (!await super.applyAgendaOperation(ev))
|
|
733
|
-
return false;
|
|
734
|
-
if (this.wantModifyOriginal && this.agenda.length > 1)
|
|
735
|
-
await basicManipulationIpc.deleteElements(CompressedId64Set.sortAndCompress(this.agenda.elements.slice(1)));
|
|
736
|
-
return true;
|
|
737
|
-
}
|
|
738
|
-
async processAgenda(ev) {
|
|
739
|
-
await this.doRegionBoolean(ev);
|
|
740
|
-
return super.processAgenda(ev);
|
|
741
|
-
}
|
|
742
|
-
async onRestartTool() {
|
|
743
|
-
const tool = new RegionBooleanTool();
|
|
744
|
-
if (!await tool.run())
|
|
745
|
-
return this.exitTool();
|
|
746
|
-
}
|
|
747
|
-
async applyToolSettingPropertyChange(updatedValue) {
|
|
748
|
-
if (!this.changeToolSettingPropertyValue(updatedValue))
|
|
749
|
-
return false;
|
|
750
|
-
if (this.modeProperty.name === updatedValue.propertyName)
|
|
751
|
-
await this.onReinitialize();
|
|
752
|
-
return true;
|
|
753
|
-
}
|
|
754
|
-
supplyToolSettingsProperties() {
|
|
755
|
-
this.initializeToolSettingPropertyValues([this.makeCopyProperty, this.modeProperty]);
|
|
756
|
-
const toolSettings = new Array();
|
|
757
|
-
toolSettings.push(this.modeProperty.toDialogItem({ rowPriority: 1, columnIndex: 0 }));
|
|
758
|
-
toolSettings.push(this.makeCopyProperty.toDialogItem({ rowPriority: 2, columnIndex: 0 }));
|
|
759
|
-
return toolSettings;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
RegionBooleanTool.toolId = "RegionBoolean";
|
|
763
|
-
RegionBooleanTool.iconSpec = "icon-scale"; // Need better icon...
|
|
764
|
-
RegionBooleanTool.getModeChoices = () => {
|
|
765
|
-
return [
|
|
766
|
-
{ label: RegionBooleanTool.modeMessage("Unite"), value: RegionBooleanMode.Unite },
|
|
767
|
-
{ label: RegionBooleanTool.modeMessage("Subtract"), value: RegionBooleanMode.Subtract },
|
|
768
|
-
{ label: RegionBooleanTool.modeMessage("Intersect"), value: RegionBooleanMode.Intersect },
|
|
769
|
-
];
|
|
770
|
-
};
|
|
771
|
-
export { RegionBooleanTool };
|
|
772
|
-
//# sourceMappingURL=ModifyCurveTools.js.map
|