@itwin/editor-frontend 3.0.0-dev.133 → 3.0.0-dev.138
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/lib/cjs/ElementGeometryTool.d.ts +7 -1
- package/lib/cjs/ElementGeometryTool.d.ts.map +1 -1
- package/lib/cjs/ElementGeometryTool.js +43 -5
- package/lib/cjs/ElementGeometryTool.js.map +1 -1
- package/lib/cjs/SolidModelingTools.d.ts +25 -13
- package/lib/cjs/SolidModelingTools.d.ts.map +1 -1
- package/lib/cjs/SolidModelingTools.js +99 -55
- package/lib/cjs/SolidModelingTools.js.map +1 -1
- package/lib/esm/ElementGeometryTool.d.ts +7 -1
- package/lib/esm/ElementGeometryTool.d.ts.map +1 -1
- package/lib/esm/ElementGeometryTool.js +44 -6
- package/lib/esm/ElementGeometryTool.js.map +1 -1
- package/lib/esm/SolidModelingTools.d.ts +25 -13
- package/lib/esm/SolidModelingTools.d.ts.map +1 -1
- package/lib/esm/SolidModelingTools.js +99 -57
- package/lib/esm/SolidModelingTools.js.map +1 -1
- package/package.json +13 -13
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
/** @packageDocumentation
|
|
6
6
|
* @module Editing
|
|
7
7
|
*/
|
|
8
|
-
import { BooleanMode, ChamferMode, CutDepthMode, CutDirectionMode, EmbossDirectionMode, ProfileClosure, SubEntityType } from "@itwin/editor-common";
|
|
8
|
+
import { BooleanMode, BRepEntityType, ChamferMode, CutDepthMode, CutDirectionMode, EmbossDirectionMode, ProfileClosure, SubEntityType } from "@itwin/editor-common";
|
|
9
9
|
import { ColorDef, ElementGeometry } from "@itwin/core-common";
|
|
10
|
-
import { Angle, Geometry, LineString3d, Point3d, Vector3d } from "@itwin/core-geometry";
|
|
11
|
-
import { AccuDrawHintBuilder, EventHandled, GraphicType } from "@itwin/core-frontend";
|
|
10
|
+
import { Angle, Geometry, LineString3d, Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry";
|
|
11
|
+
import { AccuDraw, AccuDrawHintBuilder, EventHandled, GraphicType, TentativeOrAccuSnap } from "@itwin/core-frontend";
|
|
12
12
|
import { computeChordToleranceFromPoint } from "./CreateElementTool";
|
|
13
13
|
import { ElementGeometryCacheTool, isSameSubEntity, LocateSubEntityTool, SubEntityData } from "./ElementGeometryTool";
|
|
14
14
|
/** @alpha Base class for tools that perform boolean operations on a set of elements. */
|
|
@@ -675,6 +675,7 @@ export class ImprintSolidElementsTool extends LocateSubEntityTool {
|
|
|
675
675
|
this.points.push(ev.point.clone());
|
|
676
676
|
if (!ev.isControlKey)
|
|
677
677
|
break;
|
|
678
|
+
this.setupAndPromptForNextAction();
|
|
678
679
|
return EventHandled.No;
|
|
679
680
|
}
|
|
680
681
|
default:
|
|
@@ -715,7 +716,7 @@ export class ImprintSolidElementsTool extends LocateSubEntityTool {
|
|
|
715
716
|
}
|
|
716
717
|
ImprintSolidElementsTool.toolId = "ImprintSolids";
|
|
717
718
|
ImprintSolidElementsTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
718
|
-
/** @alpha
|
|
719
|
+
/** @alpha Base class for tools to identify edges of solids and surfaces and apply blends. */
|
|
719
720
|
export class BlendEdgesTool extends LocateSubEntityTool {
|
|
720
721
|
constructor() {
|
|
721
722
|
super(...arguments);
|
|
@@ -862,39 +863,81 @@ export class ChamferEdgesTool extends BlendEdgesTool {
|
|
|
862
863
|
}
|
|
863
864
|
ChamferEdgesTool.toolId = "ChamferEdges";
|
|
864
865
|
ChamferEdgesTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
865
|
-
/** @alpha
|
|
866
|
-
export class
|
|
867
|
-
constructor() {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
866
|
+
/** @alpha */
|
|
867
|
+
export class ProfileLocationData {
|
|
868
|
+
constructor(point, orientation) {
|
|
869
|
+
this.point = point;
|
|
870
|
+
this.orientation = orientation;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
/** @alpha Base class for picking profiles (open paths and regions) or faces of solids. */
|
|
874
|
+
export class LocateFaceOrProfileTool extends LocateSubEntityTool {
|
|
875
|
+
get wantGeometrySummary() { return true; }
|
|
876
|
+
wantSubEntityType(type) {
|
|
877
|
+
switch (type) {
|
|
878
|
+
case SubEntityType.Face:
|
|
879
|
+
case SubEntityType.Edge:
|
|
880
|
+
// Choose all faces or all edges...
|
|
881
|
+
return (0 === this._acceptedSubEntities.length || this._acceptedSubEntities[0].props.type === type);
|
|
882
|
+
default:
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
873
885
|
}
|
|
874
|
-
get wantDynamics() { return true; }
|
|
875
|
-
get wantAccuSnap() { return this.isDynamicsStarted; }
|
|
876
|
-
// TODO: Sweep open path to surface, sweep surface to solid...
|
|
877
886
|
get geometryCacheFilter() {
|
|
878
|
-
return { parts: true, curves:
|
|
887
|
+
return { parts: true, curves: true, surfaces: true, solids: true, other: false };
|
|
888
|
+
}
|
|
889
|
+
async doPickSubEntities(id, ev) {
|
|
890
|
+
const hits = await super.doPickSubEntities(id, ev);
|
|
891
|
+
if (undefined === hits)
|
|
892
|
+
return hits;
|
|
893
|
+
// Only want edges from wire bodies...
|
|
894
|
+
const accept = (BRepEntityType.Wire === this.getBRepEntityTypeForSubEntity(id, hits[0].subEntity) ? SubEntityType.Edge : SubEntityType.Face);
|
|
895
|
+
return hits.filter((hit) => { return accept === hit.subEntity.type; });
|
|
879
896
|
}
|
|
880
897
|
async createSubEntityData(id, hit) {
|
|
881
898
|
const data = await super.createSubEntityData(id, hit);
|
|
882
|
-
|
|
883
|
-
|
|
899
|
+
// Prefer orientation from snap to take entire path curve as well as placement z into account...
|
|
900
|
+
const snap = TentativeOrAccuSnap.getCurrentSnap(false);
|
|
901
|
+
const point = (id === (snap === null || snap === void 0 ? void 0 : snap.sourceId) && snap.isHot ? snap.snapPoint : Point3d.fromJSON(hit.point));
|
|
902
|
+
const matrix = (id === (snap === null || snap === void 0 ? void 0 : snap.sourceId) ? AccuDraw.getSnapRotation(snap, undefined) : undefined);
|
|
903
|
+
const invMatrix = matrix === null || matrix === void 0 ? void 0 : matrix.inverse(); // getSnapRotation returns row matrix...
|
|
904
|
+
if (undefined !== invMatrix)
|
|
905
|
+
data.toolData = new ProfileLocationData(point, invMatrix);
|
|
906
|
+
else
|
|
907
|
+
data.toolData = new ProfileLocationData(point, undefined !== hit.normal ? Vector3d.fromJSON(hit.normal) : Vector3d.unitZ());
|
|
884
908
|
return data;
|
|
885
909
|
}
|
|
910
|
+
drawSubEntity(context, subEntity, accepted) {
|
|
911
|
+
const id = this.getCurrentElement();
|
|
912
|
+
if (undefined !== id && BRepEntityType.Solid !== this.getBRepEntityTypeForSubEntity(id, subEntity.props))
|
|
913
|
+
return; // Operation will be applied to wire or sheet body, don't display sub-entity...
|
|
914
|
+
super.drawSubEntity(context, subEntity, accepted);
|
|
915
|
+
}
|
|
886
916
|
drawAcceptedSubEntities(context) {
|
|
887
917
|
var _a;
|
|
888
918
|
super.drawAcceptedSubEntities(context);
|
|
889
|
-
// Show pick point on last identified face
|
|
890
|
-
const
|
|
891
|
-
if (undefined ===
|
|
919
|
+
// Show pick point on last identified face...
|
|
920
|
+
const profileData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
|
|
921
|
+
if (undefined === profileData)
|
|
892
922
|
return;
|
|
893
923
|
const builder = context.createGraphic({ type: GraphicType.WorldOverlay });
|
|
894
924
|
builder.setSymbology(context.viewport.getContrastToBackgroundColor(), ColorDef.black, 10);
|
|
895
|
-
builder.addPointString([
|
|
925
|
+
builder.addPointString([profileData.point]);
|
|
896
926
|
context.addDecorationFromBuilder(builder);
|
|
897
927
|
}
|
|
928
|
+
}
|
|
929
|
+
/** @alpha Identify faces of solids and surfaces to translate. */
|
|
930
|
+
export class SweepFacesTool extends LocateFaceOrProfileTool {
|
|
931
|
+
constructor() {
|
|
932
|
+
super(...arguments);
|
|
933
|
+
// TODO: Tool settings for sweep distance...
|
|
934
|
+
this.useDistance = false;
|
|
935
|
+
this.distance = 0.1;
|
|
936
|
+
this.addSmoothFaces = false;
|
|
937
|
+
}
|
|
938
|
+
get wantDynamics() { return true; }
|
|
939
|
+
get wantAccuSnap() { return true; }
|
|
940
|
+
get wantSubEntitySnap() { return true; }
|
|
898
941
|
async getSmoothFaces(id, face) {
|
|
899
942
|
try {
|
|
900
943
|
// NOTE: For sweep/translation, it makes sense to limit smooth to immediately adjacent...
|
|
@@ -908,10 +951,10 @@ export class SweepFacesTool extends LocateSubEntityTool {
|
|
|
908
951
|
var _a;
|
|
909
952
|
if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
|
|
910
953
|
return undefined;
|
|
911
|
-
const
|
|
912
|
-
if (undefined ===
|
|
954
|
+
const profileData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
|
|
955
|
+
if (undefined === profileData)
|
|
913
956
|
return undefined;
|
|
914
|
-
const path = Vector3d.createStartEnd(
|
|
957
|
+
const path = Vector3d.createStartEnd(profileData.point, ev.point);
|
|
915
958
|
if (this.useDistance && undefined === path.scaleToLength(this.distance, path))
|
|
916
959
|
return undefined;
|
|
917
960
|
if (path.magnitude() < Geometry.smallMetricDistance)
|
|
@@ -925,20 +968,24 @@ export class SweepFacesTool extends LocateSubEntityTool {
|
|
|
925
968
|
requestId: `${this.toolId}:${id}`,
|
|
926
969
|
writeChanges: isAccept ? true : undefined,
|
|
927
970
|
};
|
|
928
|
-
const
|
|
971
|
+
const subEntities = this.getAcceptedSubEntities();
|
|
972
|
+
const params = { path };
|
|
973
|
+
if (SubEntityType.Edge === subEntities[0].type || BRepEntityType.Solid !== this.getBRepEntityTypeForSubEntity(id, subEntities[0])) {
|
|
974
|
+
return await ElementGeometryCacheTool.callCommand("sweepFaces", id, params, opts);
|
|
975
|
+
}
|
|
929
976
|
if (this.addSmoothFaces) {
|
|
930
977
|
const allSmoothFaces = [];
|
|
931
|
-
for (const face of
|
|
978
|
+
for (const face of subEntities) {
|
|
932
979
|
const smoothFaces = await this.getSmoothFaces(id, face);
|
|
933
980
|
if (undefined !== smoothFaces)
|
|
934
981
|
allSmoothFaces.push(...smoothFaces);
|
|
935
982
|
}
|
|
936
983
|
for (const smooth of allSmoothFaces) {
|
|
937
|
-
if (undefined ===
|
|
938
|
-
|
|
984
|
+
if (undefined === subEntities.find((selected) => isSameSubEntity(selected, smooth)))
|
|
985
|
+
subEntities.unshift(smooth); // Preserve last selected entry as reference face...
|
|
939
986
|
}
|
|
940
987
|
}
|
|
941
|
-
|
|
988
|
+
params.faces = subEntities;
|
|
942
989
|
return await ElementGeometryCacheTool.callCommand("sweepFaces", id, params, opts);
|
|
943
990
|
}
|
|
944
991
|
catch (err) {
|
|
@@ -949,16 +996,16 @@ export class SweepFacesTool extends LocateSubEntityTool {
|
|
|
949
996
|
var _a;
|
|
950
997
|
if (!this.haveAcceptedSubEntities)
|
|
951
998
|
return;
|
|
952
|
-
const
|
|
953
|
-
if (undefined ===
|
|
999
|
+
const profileData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
|
|
1000
|
+
if (undefined === profileData)
|
|
954
1001
|
return;
|
|
955
1002
|
const hints = new AccuDrawHintBuilder();
|
|
956
1003
|
hints.setOriginFixed = true;
|
|
957
1004
|
hints.setLockY = true;
|
|
958
1005
|
hints.setLockZ = true;
|
|
959
1006
|
hints.setModeRectangular();
|
|
960
|
-
hints.setOrigin(
|
|
961
|
-
hints.setXAxis2(
|
|
1007
|
+
hints.setOrigin(profileData.point);
|
|
1008
|
+
hints.setXAxis2(profileData.orientation instanceof Matrix3d ? profileData.orientation.getColumn(2) : profileData.orientation);
|
|
962
1009
|
hints.sendHints(false);
|
|
963
1010
|
}
|
|
964
1011
|
async onRestartTool() {
|
|
@@ -970,28 +1017,16 @@ export class SweepFacesTool extends LocateSubEntityTool {
|
|
|
970
1017
|
SweepFacesTool.toolId = "SweepFaces";
|
|
971
1018
|
SweepFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
|
|
972
1019
|
/** @alpha Identify faces of solids and surfaces to revolve. */
|
|
973
|
-
export class SpinFacesTool extends
|
|
1020
|
+
export class SpinFacesTool extends LocateFaceOrProfileTool {
|
|
974
1021
|
constructor() {
|
|
975
1022
|
super(...arguments);
|
|
976
|
-
this.points = [];
|
|
977
1023
|
// TODO: Tool settings for sweep angle...
|
|
978
1024
|
this.sweep = Angle.piOver2Radians;
|
|
1025
|
+
this.points = [];
|
|
979
1026
|
}
|
|
980
1027
|
get wantDynamics() { return true; }
|
|
981
|
-
get wantAccuSnap() { return
|
|
982
|
-
|
|
983
|
-
get geometryCacheFilter() {
|
|
984
|
-
return { parts: true, curves: false, surfaces: true, solids: true, other: false };
|
|
985
|
-
}
|
|
986
|
-
getSubEntityFilter() {
|
|
987
|
-
return { nonPlanarFaces: true };
|
|
988
|
-
}
|
|
989
|
-
async createSubEntityData(id, hit) {
|
|
990
|
-
const data = await super.createSubEntityData(id, hit);
|
|
991
|
-
if (undefined !== hit.point && undefined !== hit.normal)
|
|
992
|
-
data.toolData = FaceLocationData.create(hit.point, hit.normal);
|
|
993
|
-
return data;
|
|
994
|
-
}
|
|
1028
|
+
get wantAccuSnap() { return true; }
|
|
1029
|
+
get wantSubEntitySnap() { return true; }
|
|
995
1030
|
async applyAgendaOperation(ev, isAccept) {
|
|
996
1031
|
if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities || this.points.length < (isAccept ? 2 : 1))
|
|
997
1032
|
return undefined;
|
|
@@ -1009,8 +1044,12 @@ export class SpinFacesTool extends LocateSubEntityTool {
|
|
|
1009
1044
|
requestId: `${this.toolId}:${id}`,
|
|
1010
1045
|
writeChanges: isAccept ? true : undefined,
|
|
1011
1046
|
};
|
|
1012
|
-
const
|
|
1013
|
-
const params = {
|
|
1047
|
+
const subEntities = this.getAcceptedSubEntities();
|
|
1048
|
+
const params = { origin, direction, angle };
|
|
1049
|
+
if (SubEntityType.Edge === subEntities[0].type || BRepEntityType.Solid !== this.getBRepEntityTypeForSubEntity(id, subEntities[0])) {
|
|
1050
|
+
return await ElementGeometryCacheTool.callCommand("spinFaces", id, params, opts);
|
|
1051
|
+
}
|
|
1052
|
+
params.faces = subEntities;
|
|
1014
1053
|
let result = await ElementGeometryCacheTool.callCommand("spinFaces", id, params, opts);
|
|
1015
1054
|
// Spun face can be used to create a pocket...retry with negative sweep...
|
|
1016
1055
|
if (undefined === result) {
|
|
@@ -1035,7 +1074,7 @@ export class SpinFacesTool extends LocateSubEntityTool {
|
|
|
1035
1074
|
super.onDynamicFrame(ev, context);
|
|
1036
1075
|
}
|
|
1037
1076
|
async gatherInput(ev) {
|
|
1038
|
-
if (this.
|
|
1077
|
+
if (!this.wantAdditionalSubEntities)
|
|
1039
1078
|
this.points.push(ev.point.clone());
|
|
1040
1079
|
return super.gatherInput(ev);
|
|
1041
1080
|
}
|
|
@@ -1046,13 +1085,16 @@ export class SpinFacesTool extends LocateSubEntityTool {
|
|
|
1046
1085
|
var _a;
|
|
1047
1086
|
if (!this.haveAcceptedSubEntities || 0 !== this.points.length)
|
|
1048
1087
|
return;
|
|
1049
|
-
const
|
|
1050
|
-
if (undefined ===
|
|
1088
|
+
const profileData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
|
|
1089
|
+
if (undefined === profileData)
|
|
1051
1090
|
return;
|
|
1052
1091
|
const hints = new AccuDrawHintBuilder();
|
|
1053
1092
|
hints.setModeRectangular();
|
|
1054
|
-
hints.setOrigin(
|
|
1055
|
-
|
|
1093
|
+
hints.setOrigin(profileData.point);
|
|
1094
|
+
if (profileData.orientation instanceof Matrix3d)
|
|
1095
|
+
hints.setMatrix(profileData.orientation);
|
|
1096
|
+
else
|
|
1097
|
+
hints.setNormal(profileData.orientation);
|
|
1056
1098
|
hints.sendHints(false);
|
|
1057
1099
|
}
|
|
1058
1100
|
async onRestartTool() {
|