@itwin/editor-frontend 3.0.0-dev.128 → 3.0.0-dev.133

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.
@@ -7,7 +7,7 @@
7
7
  * @module Editing
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.ChamferEdgesTool = exports.RoundEdgesTool = exports.BlendEdgesTool = exports.ImprintSolidElementsTool = exports.ImprintSolidMethod = exports.HollowFacesTool = exports.OffsetFacesTool = exports.FaceLocationData = exports.LoftProfilesTool = exports.SweepAlongPathTool = exports.EmbossSolidElementsTool = exports.CutSolidElementsTool = exports.ThickenSheetElementsTool = exports.SewSheetElementsTool = exports.IntersectSolidElementsTool = exports.SubtractSolidElementsTool = exports.UniteSolidElementsTool = exports.BooleanOperationTool = void 0;
10
+ exports.SpinFacesTool = exports.SweepFacesTool = exports.ChamferEdgesTool = exports.RoundEdgesTool = exports.BlendEdgesTool = exports.ImprintSolidElementsTool = exports.ImprintSolidMethod = exports.DeleteSubEntitiesTool = exports.HollowFacesTool = exports.OffsetFacesTool = exports.FaceLocationData = exports.LoftProfilesTool = exports.SweepAlongPathTool = exports.EmbossSolidElementsTool = exports.CutSolidElementsTool = exports.ThickenSheetElementsTool = exports.SewSheetElementsTool = exports.IntersectSolidElementsTool = exports.SubtractSolidElementsTool = exports.UniteSolidElementsTool = exports.BooleanOperationTool = void 0;
11
11
  const editor_common_1 = require("@itwin/editor-common");
12
12
  const core_common_1 = require("@itwin/core-common");
13
13
  const core_geometry_1 = require("@itwin/core-geometry");
@@ -367,6 +367,13 @@ class FaceLocationData {
367
367
  exports.FaceLocationData = FaceLocationData;
368
368
  /** @alpha Identify faces of solids and surfaces to offset. */
369
369
  class OffsetFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
370
+ constructor() {
371
+ super(...arguments);
372
+ // TODO: Tool settings for offset distance...
373
+ this.useOffset = false;
374
+ this.offset = 0.1;
375
+ this.addSmoothFaces = false;
376
+ }
370
377
  get wantDynamics() { return true; }
371
378
  get wantAccuSnap() { return this.isDynamicsStarted; }
372
379
  get geometryCacheFilter() {
@@ -390,6 +397,15 @@ class OffsetFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
390
397
  builder.addPointString([faceData.point]);
391
398
  context.addDecorationFromBuilder(builder);
392
399
  }
400
+ async getSmoothFaces(id, face) {
401
+ try {
402
+ // NOTE: For offset, include all smoothly connected faces, not just adjacent...
403
+ return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("getConnectedSubEntities", id, face, editor_common_1.SubEntityType.Face, { smoothFaces: true });
404
+ }
405
+ catch (err) {
406
+ return undefined;
407
+ }
408
+ }
393
409
  async applyAgendaOperation(ev, isAccept) {
394
410
  var _a;
395
411
  if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
@@ -401,6 +417,8 @@ class OffsetFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
401
417
  if (undefined === projPt)
402
418
  return undefined;
403
419
  const offsetDir = core_geometry_1.Vector3d.createStartEnd(faceData.point, projPt);
420
+ if (this.useOffset && undefined === offsetDir.scaleToLength(this.offset, offsetDir))
421
+ return undefined;
404
422
  let offset = offsetDir.magnitude();
405
423
  if (offset < core_geometry_1.Geometry.smallMetricDistance)
406
424
  return undefined;
@@ -408,14 +426,28 @@ class OffsetFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
408
426
  offset = -offset;
409
427
  try {
410
428
  this._startedCmd = await this.startCommand();
411
- const params = { faces: this.getAcceptedSubEntities(), distances: offset };
429
+ const id = this.agenda.elements[0];
430
+ const faces = this.getAcceptedSubEntities();
431
+ if (this.addSmoothFaces) {
432
+ const allSmoothFaces = [];
433
+ for (const face of faces) {
434
+ const smoothFaces = await this.getSmoothFaces(id, face);
435
+ if (undefined !== smoothFaces)
436
+ allSmoothFaces.push(...smoothFaces);
437
+ }
438
+ for (const smooth of allSmoothFaces) {
439
+ if (undefined === faces.find((selected) => (0, ElementGeometryTool_1.isSameSubEntity)(selected, smooth)))
440
+ faces.unshift(smooth); // Preserve last selected entry as reference face...
441
+ }
442
+ }
443
+ const params = { faces, distances: offset };
412
444
  const opts = {
413
445
  wantGraphic: isAccept ? undefined : true,
414
446
  chordTolerance: (0, CreateElementTool_1.computeChordToleranceFromPoint)(ev.viewport, ev.point),
415
- requestId: `${this.toolId}:${this.agenda.elements[0]}`,
447
+ requestId: `${this.toolId}:${id}`,
416
448
  writeChanges: isAccept ? true : undefined,
417
449
  };
418
- return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("offsetFaces", this.agenda.elements[0], params, opts);
450
+ return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("offsetFaces", id, params, opts);
419
451
  }
420
452
  catch (err) {
421
453
  return undefined;
@@ -484,6 +516,73 @@ class HollowFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
484
516
  exports.HollowFacesTool = HollowFacesTool;
485
517
  HollowFacesTool.toolId = "HollowFaces";
486
518
  HollowFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
519
+ /** @alpha Identify faces or edges for removal by growing surrounding faces. */
520
+ class DeleteSubEntitiesTool extends ElementGeometryTool_1.LocateSubEntityTool {
521
+ wantSubEntityType(type) {
522
+ switch (type) {
523
+ case editor_common_1.SubEntityType.Face:
524
+ case editor_common_1.SubEntityType.Edge:
525
+ // Choose all faces or all edges...
526
+ return (0 === this._acceptedSubEntities.length || this._acceptedSubEntities[0].props.type === type);
527
+ default:
528
+ return false;
529
+ }
530
+ }
531
+ getMaximumSubEntityHits(type) {
532
+ if (!this.wantSubEntityType(type))
533
+ return 0;
534
+ // Only return single closest edge, avoids having to test for redundant edges on reset...
535
+ return (editor_common_1.SubEntityType.Edge === type ? 1 : 25);
536
+ }
537
+ get geometryCacheFilter() {
538
+ return { parts: true, curves: false, surfaces: true, solids: true, other: false };
539
+ }
540
+ async doPickSubEntities(id, ev) {
541
+ const hits = await super.doPickSubEntities(id, ev);
542
+ if (undefined === hits)
543
+ return hits;
544
+ // Don't allow reset to select a back edge...
545
+ if (editor_common_1.SubEntityType.Face === hits[0].subEntity.type)
546
+ return hits.filter((hit) => { return editor_common_1.SubEntityType.Face === hit.subEntity.type; });
547
+ try {
548
+ const accept = await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("isRedundantEdge", id, hits[0].subEntity);
549
+ if (accept)
550
+ return hits;
551
+ if (hits.length > 1 && editor_common_1.SubEntityType.Face === hits[1].subEntity.type)
552
+ return hits.slice(1); // Accept face of rejected edge...
553
+ return undefined;
554
+ }
555
+ catch (err) {
556
+ return undefined;
557
+ }
558
+ }
559
+ async applyAgendaOperation(ev, isAccept) {
560
+ if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
561
+ return undefined;
562
+ try {
563
+ this._startedCmd = await this.startCommand();
564
+ const params = { subEntities: this.getAcceptedSubEntities() };
565
+ const opts = {
566
+ wantGraphic: isAccept ? undefined : true,
567
+ chordTolerance: (0, CreateElementTool_1.computeChordToleranceFromPoint)(ev.viewport, ev.point),
568
+ requestId: `${this.toolId}:${this.agenda.elements[0]}`,
569
+ writeChanges: isAccept ? true : undefined,
570
+ };
571
+ return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("deleteSubEntities", this.agenda.elements[0], params, opts);
572
+ }
573
+ catch (err) {
574
+ return undefined;
575
+ }
576
+ }
577
+ async onRestartTool() {
578
+ const tool = new DeleteSubEntitiesTool();
579
+ if (!await tool.run())
580
+ return this.exitTool();
581
+ }
582
+ }
583
+ exports.DeleteSubEntitiesTool = DeleteSubEntitiesTool;
584
+ DeleteSubEntitiesTool.toolId = "DeleteSubEntities";
585
+ DeleteSubEntitiesTool.iconSpec = "icon-move"; // TODO: Need better icon...
487
586
  /** @alpha */
488
587
  var ImprintSolidMethod;
489
588
  (function (ImprintSolidMethod) {
@@ -784,4 +883,207 @@ class ChamferEdgesTool extends BlendEdgesTool {
784
883
  exports.ChamferEdgesTool = ChamferEdgesTool;
785
884
  ChamferEdgesTool.toolId = "ChamferEdges";
786
885
  ChamferEdgesTool.iconSpec = "icon-move"; // TODO: Need better icon...
886
+ /** @alpha Identify faces of solids and surfaces to translate. */
887
+ class SweepFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
888
+ constructor() {
889
+ super(...arguments);
890
+ // TODO: Tool settings for sweep distance...
891
+ this.useDistance = false;
892
+ this.distance = 0.1;
893
+ this.addSmoothFaces = false;
894
+ }
895
+ get wantDynamics() { return true; }
896
+ get wantAccuSnap() { return this.isDynamicsStarted; }
897
+ // TODO: Sweep open path to surface, sweep surface to solid...
898
+ get geometryCacheFilter() {
899
+ return { parts: true, curves: false, surfaces: true, solids: true, other: false };
900
+ }
901
+ async createSubEntityData(id, hit) {
902
+ const data = await super.createSubEntityData(id, hit);
903
+ if (undefined !== hit.point && undefined !== hit.normal)
904
+ data.toolData = FaceLocationData.create(hit.point, hit.normal);
905
+ return data;
906
+ }
907
+ drawAcceptedSubEntities(context) {
908
+ var _a;
909
+ super.drawAcceptedSubEntities(context);
910
+ // Show pick point on last identified face, offset direction/distance will be computed from this location...
911
+ const faceData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
912
+ if (undefined === faceData)
913
+ return;
914
+ const builder = context.createGraphic({ type: core_frontend_1.GraphicType.WorldOverlay });
915
+ builder.setSymbology(context.viewport.getContrastToBackgroundColor(), core_common_1.ColorDef.black, 10);
916
+ builder.addPointString([faceData.point]);
917
+ context.addDecorationFromBuilder(builder);
918
+ }
919
+ async getSmoothFaces(id, face) {
920
+ try {
921
+ // NOTE: For sweep/translation, it makes sense to limit smooth to immediately adjacent...
922
+ return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("getConnectedSubEntities", id, face, editor_common_1.SubEntityType.Face, { smoothFaces: true, adjacentFaces: true });
923
+ }
924
+ catch (err) {
925
+ return undefined;
926
+ }
927
+ }
928
+ async applyAgendaOperation(ev, isAccept) {
929
+ var _a;
930
+ if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities)
931
+ return undefined;
932
+ const faceData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
933
+ if (undefined === faceData)
934
+ return undefined;
935
+ const path = core_geometry_1.Vector3d.createStartEnd(faceData.point, ev.point);
936
+ if (this.useDistance && undefined === path.scaleToLength(this.distance, path))
937
+ return undefined;
938
+ if (path.magnitude() < core_geometry_1.Geometry.smallMetricDistance)
939
+ return undefined;
940
+ try {
941
+ this._startedCmd = await this.startCommand();
942
+ const id = this.agenda.elements[0];
943
+ const opts = {
944
+ wantGraphic: isAccept ? undefined : true,
945
+ chordTolerance: (0, CreateElementTool_1.computeChordToleranceFromPoint)(ev.viewport, ev.point),
946
+ requestId: `${this.toolId}:${id}`,
947
+ writeChanges: isAccept ? true : undefined,
948
+ };
949
+ const faces = this.getAcceptedSubEntities();
950
+ if (this.addSmoothFaces) {
951
+ const allSmoothFaces = [];
952
+ for (const face of faces) {
953
+ const smoothFaces = await this.getSmoothFaces(id, face);
954
+ if (undefined !== smoothFaces)
955
+ allSmoothFaces.push(...smoothFaces);
956
+ }
957
+ for (const smooth of allSmoothFaces) {
958
+ if (undefined === faces.find((selected) => (0, ElementGeometryTool_1.isSameSubEntity)(selected, smooth)))
959
+ faces.unshift(smooth); // Preserve last selected entry as reference face...
960
+ }
961
+ }
962
+ const params = { faces, path };
963
+ return await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("sweepFaces", id, params, opts);
964
+ }
965
+ catch (err) {
966
+ return undefined;
967
+ }
968
+ }
969
+ setupAccuDraw() {
970
+ var _a;
971
+ if (!this.haveAcceptedSubEntities)
972
+ return;
973
+ const faceData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
974
+ if (undefined === faceData)
975
+ return;
976
+ const hints = new core_frontend_1.AccuDrawHintBuilder();
977
+ hints.setOriginFixed = true;
978
+ hints.setLockY = true;
979
+ hints.setLockZ = true;
980
+ hints.setModeRectangular();
981
+ hints.setOrigin(faceData.point);
982
+ hints.setXAxis2(faceData.normal);
983
+ hints.sendHints(false);
984
+ }
985
+ async onRestartTool() {
986
+ const tool = new SweepFacesTool();
987
+ if (!await tool.run())
988
+ return this.exitTool();
989
+ }
990
+ }
991
+ exports.SweepFacesTool = SweepFacesTool;
992
+ SweepFacesTool.toolId = "SweepFaces";
993
+ SweepFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
994
+ /** @alpha Identify faces of solids and surfaces to revolve. */
995
+ class SpinFacesTool extends ElementGeometryTool_1.LocateSubEntityTool {
996
+ constructor() {
997
+ super(...arguments);
998
+ this.points = [];
999
+ // TODO: Tool settings for sweep angle...
1000
+ this.sweep = core_geometry_1.Angle.piOver2Radians;
1001
+ }
1002
+ get wantDynamics() { return true; }
1003
+ get wantAccuSnap() { return this.isDynamicsStarted || (this.haveAcceptedSubEntities && !this.isControlDown); }
1004
+ // TODO: Spin open path to surface, spin surface to solid...
1005
+ get geometryCacheFilter() {
1006
+ return { parts: true, curves: false, surfaces: true, solids: true, other: false };
1007
+ }
1008
+ getSubEntityFilter() {
1009
+ return { nonPlanarFaces: true };
1010
+ }
1011
+ async createSubEntityData(id, hit) {
1012
+ const data = await super.createSubEntityData(id, hit);
1013
+ if (undefined !== hit.point && undefined !== hit.normal)
1014
+ data.toolData = FaceLocationData.create(hit.point, hit.normal);
1015
+ return data;
1016
+ }
1017
+ async applyAgendaOperation(ev, isAccept) {
1018
+ if (undefined === ev.viewport || this.agenda.isEmpty || !this.haveAcceptedSubEntities || this.points.length < (isAccept ? 2 : 1))
1019
+ return undefined;
1020
+ const direction = core_geometry_1.Vector3d.createStartEnd(this.points[0], isAccept ? this.points[1] : ev.point);
1021
+ if (direction.magnitude() < core_geometry_1.Geometry.smallMetricDistance)
1022
+ return undefined;
1023
+ const origin = this.points[0];
1024
+ const angle = core_geometry_1.Angle.createRadians(this.sweep);
1025
+ try {
1026
+ this._startedCmd = await this.startCommand();
1027
+ const id = this.agenda.elements[0];
1028
+ const opts = {
1029
+ wantGraphic: isAccept ? undefined : true,
1030
+ chordTolerance: (0, CreateElementTool_1.computeChordToleranceFromPoint)(ev.viewport, ev.point),
1031
+ requestId: `${this.toolId}:${id}`,
1032
+ writeChanges: isAccept ? true : undefined,
1033
+ };
1034
+ const faces = this.getAcceptedSubEntities();
1035
+ const params = { faces, origin, direction, angle };
1036
+ let result = await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("spinFaces", id, params, opts);
1037
+ // Spun face can be used to create a pocket...retry with negative sweep...
1038
+ if (undefined === result) {
1039
+ angle.setRadians(-angle.radians);
1040
+ result = await ElementGeometryTool_1.ElementGeometryCacheTool.callCommand("spinFaces", id, params, opts);
1041
+ }
1042
+ return result;
1043
+ }
1044
+ catch (err) {
1045
+ return undefined;
1046
+ }
1047
+ }
1048
+ onDynamicFrame(ev, context) {
1049
+ if (0 === this.points.length)
1050
+ return;
1051
+ const pts = this.points.slice();
1052
+ pts.push(ev.point.clone());
1053
+ const builder = context.createGraphic({ type: core_frontend_1.GraphicType.WorldOverlay });
1054
+ builder.setSymbology(context.viewport.getContrastToBackgroundColor(), core_common_1.ColorDef.black, 3);
1055
+ builder.addLineString(pts);
1056
+ context.addGraphic(builder.finish());
1057
+ super.onDynamicFrame(ev, context);
1058
+ }
1059
+ async gatherInput(ev) {
1060
+ if (this.haveAcceptedSubEntities)
1061
+ this.points.push(ev.point.clone());
1062
+ return super.gatherInput(ev);
1063
+ }
1064
+ get wantAdditionalInput() {
1065
+ return super.wantAdditionalInput || this.points.length < 2;
1066
+ }
1067
+ setupAccuDraw() {
1068
+ var _a;
1069
+ if (!this.haveAcceptedSubEntities || 0 !== this.points.length)
1070
+ return;
1071
+ const faceData = (_a = this.getAcceptedSubEntityData()) === null || _a === void 0 ? void 0 : _a.toolData;
1072
+ if (undefined === faceData)
1073
+ return;
1074
+ const hints = new core_frontend_1.AccuDrawHintBuilder();
1075
+ hints.setModeRectangular();
1076
+ hints.setOrigin(faceData.point);
1077
+ hints.setNormal(faceData.normal);
1078
+ hints.sendHints(false);
1079
+ }
1080
+ async onRestartTool() {
1081
+ const tool = new SpinFacesTool();
1082
+ if (!await tool.run())
1083
+ return this.exitTool();
1084
+ }
1085
+ }
1086
+ exports.SpinFacesTool = SpinFacesTool;
1087
+ SpinFacesTool.toolId = "SpinFaces";
1088
+ SpinFacesTool.iconSpec = "icon-move"; // TODO: Need better icon...
787
1089
  //# sourceMappingURL=SolidModelingTools.js.map