fluidcad 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +2 -2
  2. package/lib/dist/common/shape-factory.d.ts +1 -1
  3. package/lib/dist/oc/boolean-ops.d.ts +2 -2
  4. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  5. package/package.json +3 -2
  6. package/lib/dist/constraints/constraint.d.ts +0 -11
  7. package/lib/dist/constraints/constraint.js +0 -51
  8. package/lib/dist/constraints/outside.d.ts +0 -3
  9. package/lib/dist/constraints/outside.js +0 -4
  10. package/lib/dist/core/2d/aslot.d.ts +0 -12
  11. package/lib/dist/core/2d/aslot.js +0 -40
  12. package/lib/dist/core/2d/crect.d.ts +0 -12
  13. package/lib/dist/core/2d/crect.js +0 -74
  14. package/lib/dist/core/2d/face-maker.d.ts +0 -13
  15. package/lib/dist/core/2d/face-maker.js +0 -119
  16. package/lib/dist/core/2d/face-maker2.d.ts +0 -6
  17. package/lib/dist/core/2d/face-maker2.js +0 -54
  18. package/lib/dist/core/region.d.ts +0 -13
  19. package/lib/dist/core/region.js +0 -18
  20. package/lib/dist/features/2d/amove.d.ts +0 -14
  21. package/lib/dist/features/2d/amove.js +0 -33
  22. package/lib/dist/features/2d/constraints/constraint.d.ts +0 -11
  23. package/lib/dist/features/2d/constraints/constraint.js +0 -49
  24. package/lib/dist/features/2d/constraints/outside.d.ts +0 -3
  25. package/lib/dist/features/2d/constraints/outside.js +0 -4
  26. package/lib/dist/features/2d/tarc-two-circles.d.ts +0 -18
  27. package/lib/dist/features/2d/tarc-two-circles.js +0 -61
  28. package/lib/dist/features/2d/tcircle-three-tan.d.ts +0 -13
  29. package/lib/dist/features/2d/tcircle-three-tan.js +0 -33
  30. package/lib/dist/features/2d/tcircle-two-tan.d.ts +0 -13
  31. package/lib/dist/features/2d/tcircle-two-tan.js +0 -33
  32. package/lib/dist/features/Extrude.d.ts +0 -1
  33. package/lib/dist/features/Extrude.js +0 -1
  34. package/lib/dist/features/cut-base.d.ts +0 -49
  35. package/lib/dist/features/cut-base.js +0 -312
  36. package/lib/dist/features/cut-symmetric.d.ts +0 -23
  37. package/lib/dist/features/cut-symmetric.js +0 -119
  38. package/lib/dist/features/cut-two-distances.d.ts +0 -24
  39. package/lib/dist/features/cut-two-distances.js +0 -110
  40. package/lib/dist/features/cut.d.ts +0 -27
  41. package/lib/dist/features/cut.js +0 -101
  42. package/lib/dist/features/extrude-symmetric.d.ts +0 -28
  43. package/lib/dist/features/extrude-symmetric.js +0 -177
  44. package/lib/dist/features/region2d.d.ts +0 -25
  45. package/lib/dist/features/region2d.js +0 -185
  46. package/lib/dist/features/repeat-circular2d.d.ts +0 -17
  47. package/lib/dist/features/repeat-circular2d.js +0 -90
  48. package/lib/dist/features/repeat-linear2d.d.ts +0 -17
  49. package/lib/dist/features/repeat-linear2d.js +0 -114
  50. package/lib/dist/features/revolve-options.d.ts +0 -6
  51. package/lib/dist/features/revolve-options.js +0 -1
  52. package/lib/dist/features/split.d.ts +0 -14
  53. package/lib/dist/features/split.js +0 -74
  54. package/lib/dist/features/state-scene-object.d.ts +0 -15
  55. package/lib/dist/features/state-scene-object.js +0 -44
  56. package/lib/dist/features/state-select.d.ts +0 -21
  57. package/lib/dist/features/state-select.js +0 -73
  58. package/lib/dist/features/translate2d.d.ts +0 -16
  59. package/lib/dist/features/translate2d.js +0 -61
  60. package/lib/dist/filters/all-filter.d.ts +0 -8
  61. package/lib/dist/filters/all-filter.js +0 -12
  62. package/lib/dist/filters/near-point-filter.d.ts +0 -11
  63. package/lib/dist/filters/near-point-filter.js +0 -33
  64. package/lib/dist/helpers/resolve-filters.d.ts +0 -6
  65. package/lib/dist/helpers/resolve-filters.js +0 -25
  66. package/lib/dist/math/axis.test.d.ts +0 -1
  67. package/lib/dist/math/axis.test.js +0 -287
  68. package/lib/dist/math/coordinate-system.test.d.ts +0 -1
  69. package/lib/dist/math/coordinate-system.test.js +0 -308
  70. package/lib/dist/math/matrix4.test.d.ts +0 -1
  71. package/lib/dist/math/matrix4.test.js +0 -357
  72. package/lib/dist/math/plane.test.d.ts +0 -1
  73. package/lib/dist/math/plane.test.js +0 -398
  74. package/lib/dist/math/point.test.d.ts +0 -1
  75. package/lib/dist/math/point.test.js +0 -385
  76. package/lib/dist/math/quaternion.test.d.ts +0 -1
  77. package/lib/dist/math/quaternion.test.js +0 -278
  78. package/lib/dist/math/vector3d.test.d.ts +0 -1
  79. package/lib/dist/math/vector3d.test.js +0 -276
  80. package/lib/dist/oc/constraint-resolver.d.ts +0 -7
  81. package/lib/dist/oc/constraint-resolver.js +0 -31
  82. package/lib/dist/oc/constraints/curve-constraint-solver.d.ts +0 -1
  83. package/lib/dist/oc/constraints/curve-constraint-solver.js +0 -2
  84. package/lib/dist/oc/constraints/geometric-constraint-solver.d.ts +0 -1
  85. package/lib/dist/oc/constraints/geometric-constraint-solver.js +0 -5
  86. package/lib/dist/oc/face-maker.d.ts +0 -14
  87. package/lib/dist/oc/face-maker.js +0 -191
  88. package/lib/dist/oc/measure.d.ts +0 -21
  89. package/lib/dist/oc/measure.js +0 -256
  90. package/lib/dist/oc/tangent-circle-solver.d.ts +0 -17
  91. package/lib/dist/oc/tangent-circle-solver.js +0 -72
  92. package/lib/dist/oc/tangent-line-solver.d.ts +0 -17
  93. package/lib/dist/oc/tangent-line-solver.js +0 -83
  94. package/lib/dist/oc/tangent-solver.d.ts +0 -14
  95. package/lib/dist/oc/tangent-solver.js +0 -199
  96. package/lib/dist/rendering/builder-context.d.ts +0 -16
  97. package/lib/dist/rendering/builder-context.js +0 -63
  98. package/lib/dist/tests/extrude.test.d.ts +0 -1
  99. package/lib/dist/tests/extrude.test.js +0 -48
  100. package/lib/dist/tests/features/copy.test.d.ts +0 -1
  101. package/lib/dist/tests/features/copy.test.js +0 -158
  102. package/lib/dist/tests/features/dispose.test.d.ts +0 -1
  103. package/lib/dist/tests/features/dispose.test.js +0 -189
  104. package/lib/dist/tests/features/part-pick.test.d.ts +0 -1
  105. package/lib/dist/tests/features/part-pick.test.js +0 -73
  106. package/lib/dist/tests/features/part-repeat.test.d.ts +0 -1
  107. package/lib/dist/tests/features/part-repeat.test.js +0 -109
  108. package/server/dist/fluidcad-server.d.ts +0 -32
  109. package/server/dist/fluidcad-server.js +0 -150
  110. package/server/dist/index.d.ts +0 -1
  111. package/server/dist/index.js +0 -290
  112. package/server/dist/routes/actions.d.ts +0 -3
  113. package/server/dist/routes/actions.js +0 -100
  114. package/server/dist/routes/export.d.ts +0 -3
  115. package/server/dist/routes/export.js +0 -55
  116. package/server/dist/routes/properties.d.ts +0 -3
  117. package/server/dist/routes/properties.js +0 -46
  118. package/server/dist/routes/screenshot.d.ts +0 -2
  119. package/server/dist/routes/screenshot.js +0 -76
  120. package/server/dist/vite-manager.d.ts +0 -10
  121. package/server/dist/vite-manager.js +0 -64
  122. package/server/dist/ws-protocol.d.ts +0 -138
  123. package/server/dist/ws-protocol.js +0 -4
@@ -1,24 +0,0 @@
1
- import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
- import { Extrudable } from "../helpers/types.js";
3
- import { CutBase } from "./cut-base.js";
4
- export declare class CutTwoDistances extends CutBase {
5
- distance1: number;
6
- distance2: number;
7
- constructor(distance1: number, distance2: number, extrudable?: Extrudable);
8
- build(context: BuildSceneObjectContext): void;
9
- getDependencies(): SceneObject[];
10
- createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
11
- compareTo(other: CutTwoDistances): boolean;
12
- edges(...indices: number[]): SceneObject;
13
- getUniqueType(): string;
14
- serialize(): {
15
- extrudable: any;
16
- distance1: number;
17
- distance2: number;
18
- draft: [number, number];
19
- endOffset: number;
20
- fusionScope: import("./extrude-options.js").FusionScope;
21
- picking: true;
22
- pickPoints: number[][];
23
- };
24
- }
@@ -1,110 +0,0 @@
1
- import { Extruder } from "./simple-extruder.js";
2
- import { BooleanOps } from "../oc/boolean-ops.js";
3
- import { ShapeOps } from "../oc/shape-ops.js";
4
- import { LazySelectionSceneObject } from "./lazy-scene-object.js";
5
- import { CutBase } from "./cut-base.js";
6
- import { FaceMaker2 } from "../oc/face-maker2.js";
7
- export class CutTwoDistances extends CutBase {
8
- distance1;
9
- distance2;
10
- constructor(distance1, distance2, extrudable) {
11
- super(extrudable);
12
- this.distance1 = distance1;
13
- this.distance2 = distance2;
14
- }
15
- build(context) {
16
- const plane = this.extrudable.getPlane();
17
- const pickedFaces = this.resolvePickedFaces(plane);
18
- if (pickedFaces !== null && pickedFaces.length === 0) {
19
- return;
20
- }
21
- const scope = this.resolveFusionScope(context.getSceneObjects());
22
- const sceneObjects = new Map();
23
- for (const obj of scope) {
24
- const shapes = obj.getShapes({}, 'solid');
25
- if (shapes.length === 0) {
26
- continue;
27
- }
28
- sceneObjects.set(obj, shapes);
29
- }
30
- const faces = pickedFaces ?? FaceMaker2.getRegions(this.extrudable.getGeometries(), plane);
31
- // Positive distance = reverse normal direction, negate before passing to Extruder
32
- const extruder1 = new Extruder(faces, plane, -this.distance1, this.getDraft(), this.getEndOffset());
33
- const extrusions1 = extruder1.extrude();
34
- const extruder2 = new Extruder(faces, plane, this.distance2, this.getDraft(), this.getEndOffset());
35
- const extrusions2 = extruder2.extrude();
36
- const all = [...extrusions1, ...extrusions2];
37
- const { result: toolShapes } = BooleanOps.fuse(all);
38
- this.extrudable.removeShapes(this);
39
- const shapeObjectMap = new Map();
40
- for (const [obj, shapes] of sceneObjects) {
41
- for (const shape of shapes) {
42
- shapeObjectMap.set(shape, obj);
43
- }
44
- }
45
- const stock = Array.from(shapeObjectMap.keys());
46
- const cutResult = BooleanOps.cutMultiShape(stock, toolShapes, plane, this.distance1);
47
- const cleanedShapes = [];
48
- for (const shape of stock) {
49
- const list = cutResult.modified(shape);
50
- if (list.length) {
51
- for (const newShape of list) {
52
- const s = ShapeOps.cleanShape(newShape);
53
- this.addShape(s);
54
- cleanedShapes.push(s);
55
- }
56
- const obj = shapeObjectMap.get(shape);
57
- obj.removeShape(shape, this);
58
- }
59
- }
60
- this.classifyCutResult(stock, cleanedShapes, plane, this.distance1);
61
- }
62
- getDependencies() {
63
- return this.extrudable ? [this.extrudable] : [];
64
- }
65
- createCopy(remap) {
66
- const extrudable = this.extrudable
67
- ? (remap.get(this.extrudable) || this.extrudable)
68
- : undefined;
69
- return new CutTwoDistances(this.distance1, this.distance2, extrudable).syncWith(this);
70
- }
71
- compareTo(other) {
72
- if (!(other instanceof CutTwoDistances)) {
73
- return false;
74
- }
75
- if (!super.compareTo(other)) {
76
- return false;
77
- }
78
- if (this.distance1 !== other.distance1 || this.distance2 !== other.distance2) {
79
- return false;
80
- }
81
- return true;
82
- }
83
- edges(...indices) {
84
- const suffix = indices.length > 0 ? `section-edges-${indices.join('-')}` : 'section-edges';
85
- return new LazySelectionSceneObject(`${this.getOrder()}-cut-two-distances-${suffix}`, (parent) => {
86
- const edges = parent.getState('section-edges') || [];
87
- if (indices.length === 0) {
88
- return edges;
89
- }
90
- return indices.filter(i => i >= 0 && i < edges.length).map(i => edges[i]);
91
- }, this);
92
- }
93
- getUniqueType() {
94
- return 'cut-by-two-distances';
95
- }
96
- serialize() {
97
- return {
98
- extrudable: this.extrudable.serialize(),
99
- distance1: this.distance1,
100
- distance2: this.distance2,
101
- draft: this.getDraft(),
102
- endOffset: this.getEndOffset(),
103
- fusionScope: this.getFusionScope(),
104
- picking: this.isPicking() || undefined,
105
- pickPoints: this.isPicking()
106
- ? this._pickPoints.map(p => { const pt = p.asPoint2D(); return [pt.x, pt.y]; })
107
- : undefined,
108
- };
109
- }
110
- }
@@ -1,27 +0,0 @@
1
- import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
- import { ExtrudeOptions } from "./extrude-options.js";
3
- import { Extrudable } from "../helpers/types.js";
4
- export interface CutOptions extends ExtrudeOptions {
5
- }
6
- export type CutDirection = 'normal' | 'reversed' | 'symmetric';
7
- export type CutRotation = {
8
- x?: number;
9
- y?: number;
10
- };
11
- export declare class Cut extends SceneObject {
12
- private extrudable;
13
- distance: number;
14
- options: CutOptions;
15
- isThroughAll: boolean;
16
- constructor(extrudable: Extrudable, distance: number, options?: CutOptions);
17
- build(context: BuildSceneObjectContext): void;
18
- clone(): SceneObject[];
19
- compareTo(other: Cut): boolean;
20
- getType(): string;
21
- serialize(): {
22
- extrudable: any;
23
- distance: number;
24
- isThroughAll: boolean;
25
- options: CutOptions;
26
- };
27
- }
@@ -1,101 +0,0 @@
1
- import { SceneObject } from "../common/scene-object.js";
2
- import { ExtrudeThroughAll } from "./infinite-extrude.js";
3
- import { Sketch } from "./2d/sketch.js";
4
- import { FaceMaker } from "../core/2d/face-maker.js";
5
- import { Extruder } from "./simple-extruder.js";
6
- import { BooleanOps } from "../oc/boolean-ops.js";
7
- import { ShapeOps } from "../oc/shape-ops.js";
8
- export class Cut extends SceneObject {
9
- extrudable;
10
- distance;
11
- options;
12
- isThroughAll = false;
13
- constructor(extrudable, distance, options = {}) {
14
- super();
15
- this.extrudable = extrudable;
16
- this.distance = distance;
17
- this.options = options;
18
- this.isThroughAll = this.distance === 0;
19
- }
20
- build(context) {
21
- let sceneObjects;
22
- sceneObjects = new Map();
23
- for (const obj of context.getSceneObjects()) {
24
- const shapes = obj.getShapes(false, 'solid');
25
- if (shapes.length === 0) {
26
- continue;
27
- }
28
- sceneObjects.set(obj, shapes);
29
- }
30
- console.log('Cut: Scene objects for cut:', Array.from(sceneObjects.keys()).map(o => o.getType()));
31
- let distance = this.distance === 0 ? 0 : -this.distance;
32
- let extrusionShapes = [];
33
- if (this.isThroughAll) {
34
- const extrudeThroughAll = new ExtrudeThroughAll(this.extrudable, false, true);
35
- extrusionShapes = extrudeThroughAll.build();
36
- }
37
- else {
38
- const wires = this.extrudable.getGeometries();
39
- const faces = FaceMaker.getFaces(wires, this.extrudable.getPlane());
40
- const plane = this.extrudable.getPlane();
41
- const extruder = new Extruder(faces, plane, distance, this.options);
42
- extrusionShapes = extruder.extrude();
43
- }
44
- this.extrudable.removeShapes(this);
45
- const shapeObjectMap = new Map();
46
- for (const [obj, shapes] of sceneObjects) {
47
- for (const shape of shapes) {
48
- shapeObjectMap.set(shape, obj);
49
- }
50
- }
51
- const stock = Array.from(shapeObjectMap.keys());
52
- console.log('Cut: Stock shapes count:', stock.length);
53
- const toBeRemoved = extrusionShapes;
54
- console.log('Cut: Stock shapes count:', stock.length);
55
- console.log('Cut: To be removed shapes count:', toBeRemoved.length);
56
- const cutResult = BooleanOps.cutMultiShape(stock, toBeRemoved);
57
- for (const shape of stock) {
58
- const list = cutResult.modified(shape);
59
- console.log('Cut: Modified shapes for shape:', list.length);
60
- if (list.length) {
61
- for (const newShape of list) {
62
- const s = ShapeOps.cleanShape(newShape);
63
- console.log('Cut: Adding modified shape:', s);
64
- this.addShape(s);
65
- }
66
- const obj = shapeObjectMap.get(shape);
67
- obj.removeShape(shape, this);
68
- }
69
- console.log('Cut: Shape modified count:', list.length);
70
- }
71
- }
72
- clone() {
73
- const extrudableClone = this.extrudable.clone();
74
- const extrudable = extrudableClone.find(c => c instanceof Sketch);
75
- const cutClone = new Cut(extrudable, this.distance, this.options);
76
- return [...extrudableClone, cutClone];
77
- }
78
- compareTo(other) {
79
- if (!(other instanceof Cut)) {
80
- return false;
81
- }
82
- if (this.distance !== other.distance) {
83
- return false;
84
- }
85
- if (JSON.stringify(this.options || {}) !== JSON.stringify(other.options || {})) {
86
- return false;
87
- }
88
- return true;
89
- }
90
- getType() {
91
- return "cut";
92
- }
93
- serialize() {
94
- return {
95
- extrudable: this.extrudable.serialize(),
96
- distance: this.distance,
97
- isThroughAll: this.isThroughAll,
98
- options: this.options
99
- };
100
- }
101
- }
@@ -1,28 +0,0 @@
1
- import { BuildSceneObjectContext } from "../common/scene-object.js";
2
- import { ExtrudeOptions } from "./extrude-options.js";
3
- import { ExtrudeBase } from "./extrude-base.js";
4
- import { SceneObject } from "../common/scene-object.js";
5
- import { Extrudable } from "../helpers/types.js";
6
- export declare class ExtrudeSymmetric extends ExtrudeBase {
7
- extrudable: Extrudable;
8
- distance?: number;
9
- options: ExtrudeOptions;
10
- constructor(extrudable: Extrudable, distance?: number, options?: ExtrudeOptions);
11
- build(context: BuildSceneObjectContext): void;
12
- private applyDraft;
13
- private doExtrude;
14
- private getUniqueName;
15
- startFace(...indices: number[]): SceneObject;
16
- endFace(...indices: number[]): SceneObject;
17
- startEdge(...indices: number[]): SceneObject;
18
- endEdge(...indices: number[]): SceneObject;
19
- sideFace(...indices: number[]): SceneObject;
20
- compareTo(other: ExtrudeSymmetric): boolean;
21
- getUniqueType(): string;
22
- serialize(): {
23
- extrudables: any;
24
- distance: number;
25
- symmetric: boolean;
26
- options: ExtrudeOptions;
27
- };
28
- }
@@ -1,177 +0,0 @@
1
- import { rad } from "../helpers/math-helpers.js";
2
- import { ExtrudeBase } from "./extrude-base.js";
3
- import { fuseWithSceneObjects } from "../helpers/scene-helpers.js";
4
- import { FaceMaker } from "../core/2d/face-maker.js";
5
- import { ExtrudeOps } from "../oc/extrude-ops.js";
6
- import { ShapeOps } from "../oc/shape-ops.js";
7
- import { BooleanOps } from "../oc/boolean-ops.js";
8
- import { Explorer } from "../oc/explorer.js";
9
- import { LazySceneObject } from "./lazy-scene-object.js";
10
- export class ExtrudeSymmetric extends ExtrudeBase {
11
- extrudable;
12
- distance;
13
- options;
14
- constructor(extrudable, distance, options = {}) {
15
- super(options);
16
- this.extrudable = extrudable;
17
- this.distance = distance;
18
- this.options = options;
19
- }
20
- build(context) {
21
- let solids = [];
22
- const sceneObjects = context.getSceneObjects();
23
- const wires = this.extrudable.getGeometries();
24
- const faces = FaceMaker.getFaces(wires, this.extrudable.getPlane());
25
- console.log("Extruding faces:", faces);
26
- const plane = this.extrudable.getPlane();
27
- const hasDraft = !!this.options?.draft;
28
- let startFaces = [];
29
- let endFaces = [];
30
- let sideFaces = [];
31
- if (hasDraft) {
32
- let vec = plane.normal.multiply(this.distance / 2);
33
- for (const face of faces) {
34
- let { solid, firstFace, lastFace } = this.doExtrude(face, vec);
35
- solid = this.applyDraft(solid, firstFace, lastFace, plane);
36
- const center = face.center();
37
- const mirrored = ShapeOps.mirrorShape(solid, center);
38
- const fused = BooleanOps.fuseShapes(solid, mirrored);
39
- const solidFaces = Explorer.findFacesWrapped(fused);
40
- for (const f of solidFaces) {
41
- if (f.getShape().IsSame(firstFace.getShape())) {
42
- startFaces.push(f);
43
- }
44
- else if (f.getShape().IsSame(lastFace.getShape())) {
45
- endFaces.push(f);
46
- }
47
- else {
48
- sideFaces.push(f);
49
- }
50
- }
51
- solids.push(fused);
52
- }
53
- }
54
- else {
55
- let vec = plane.normal.multiply(this.distance);
56
- const translateVec = vec.multiply(-0.5);
57
- for (const face of faces) {
58
- let { solid, firstFace, lastFace } = this.doExtrude(face, vec);
59
- solid = ShapeOps.translateShape(solid, translateVec);
60
- const solidFaces = Explorer.findFacesWrapped(solid);
61
- for (const f of solidFaces) {
62
- // here we use IsPartner instead of IsSame because the place location has changed after translation
63
- if (f.getShape().IsPartner(firstFace.getShape())) {
64
- startFaces.push(f);
65
- }
66
- else if (f.getShape().IsPartner(lastFace.getShape())) {
67
- endFaces.push(f);
68
- }
69
- else {
70
- sideFaces.push(f);
71
- }
72
- }
73
- solids.push(solid);
74
- }
75
- }
76
- this.setState('start-faces', startFaces);
77
- this.setState('end-faces', endFaces);
78
- this.setState('side-faces', sideFaces);
79
- this.extrudable.removeShapes(this);
80
- if (this.options?.mergeScope === 'none' || solids.length === 0 || sceneObjects?.length === 0) {
81
- const fusionResult = fuseWithSceneObjects(sceneObjects, solids);
82
- solids = fusionResult.extrusions;
83
- for (const modifiedShape of fusionResult.modifiedShapes) {
84
- modifiedShape.object.removeShape(modifiedShape.shape, this);
85
- }
86
- }
87
- this.addShapes(solids);
88
- }
89
- applyDraft(solid, firstFace, lastFace, plane) {
90
- if (this.options.draft instanceof Array) {
91
- throw new Error("Draft with two angles for start and end faces is supported only for extrusions with two distances");
92
- }
93
- const angle = this.options.draft;
94
- return ExtrudeOps.applyDraftOnSideFaces(solid, firstFace, lastFace, plane, rad(angle));
95
- }
96
- doExtrude(shape, vector) {
97
- const { solid: rawSolid, firstFace, lastFace } = ExtrudeOps.makePrismFromVec(shape, vector);
98
- const solid = ShapeOps.cleanShape(rawSolid);
99
- return { solid, firstFace, lastFace };
100
- }
101
- getUniqueName(suffix) {
102
- return `${this.getOrder()}-${this.getUniqueType()}-${suffix}`;
103
- }
104
- startFace(...indices) {
105
- const suffix = indices.length > 0 ? `start-faces-${indices.join('-')}` : 'start-faces';
106
- return new LazySceneObject(`${this.getUniqueName(suffix)}`, () => {
107
- const faces = this.getState('start-faces') || [];
108
- if (indices.length === 0)
109
- return faces.length > 0 ? [faces[0]] : [];
110
- return indices.filter(i => i >= 0 && i < faces.length).map(i => faces[i]);
111
- });
112
- }
113
- endFace(...indices) {
114
- const suffix = indices.length > 0 ? `end-faces-${indices.join('-')}` : 'end-faces';
115
- return new LazySceneObject(`${this.getUniqueName(suffix)}`, () => {
116
- const faces = this.getState('end-faces') || [];
117
- if (indices.length === 0)
118
- return faces.length > 0 ? [faces[0]] : [];
119
- return indices.filter(i => i >= 0 && i < faces.length).map(i => faces[i]);
120
- });
121
- }
122
- startEdge(...indices) {
123
- const suffix = indices.length > 0 ? `start-edges-${indices.join('-')}` : 'start-edges';
124
- return new LazySceneObject(`${this.getUniqueName(suffix)}`, () => {
125
- const faces = this.getState('start-faces') || [];
126
- const edges = faces.flatMap(f => f.getEdges());
127
- if (indices.length === 0)
128
- return edges.length > 0 ? [edges[0]] : [];
129
- return indices.filter(i => i >= 0 && i < edges.length).map(i => edges[i]);
130
- });
131
- }
132
- endEdge(...indices) {
133
- const suffix = indices.length > 0 ? `end-edges-${indices.join('-')}` : 'end-edges';
134
- return new LazySceneObject(`${this.getUniqueName(suffix)}`, () => {
135
- const faces = this.getState('end-faces') || [];
136
- const edges = faces.flatMap(f => f.getEdges());
137
- if (indices.length === 0)
138
- return edges.length > 0 ? [edges[0]] : [];
139
- return indices.filter(i => i >= 0 && i < edges.length).map(i => edges[i]);
140
- });
141
- }
142
- sideFace(...indices) {
143
- const suffix = indices.length > 0 ? `side-faces-${indices.join('-')}` : 'side-faces';
144
- return new LazySceneObject(`${this.getUniqueName(suffix)}`, () => {
145
- const faces = this.getState('side-faces') || [];
146
- if (indices.length === 0)
147
- return faces.length > 0 ? [faces[0]] : [];
148
- return indices.filter(i => i >= 0 && i < faces.length).map(i => faces[i]);
149
- });
150
- }
151
- compareTo(other) {
152
- if (!(other instanceof ExtrudeSymmetric)) {
153
- return false;
154
- }
155
- if (this.distance !== other.distance) {
156
- return false;
157
- }
158
- if (JSON.stringify(this.options || {}) !== JSON.stringify(other.options || {})) {
159
- return false;
160
- }
161
- if (!this.extrudable.compareTo(other.extrudable)) {
162
- return false;
163
- }
164
- return true;
165
- }
166
- getUniqueType() {
167
- return 'extrude-symmetric';
168
- }
169
- serialize() {
170
- return {
171
- extrudables: this.extrudable.serialize(),
172
- distance: this.distance,
173
- symmetric: true,
174
- options: this.options
175
- };
176
- }
177
- }
@@ -1,25 +0,0 @@
1
- import { SceneObject } from "../common/scene-object.js";
2
- import { Edge } from "../common/edge.js";
3
- import { Wire } from "../common/wire.js";
4
- import { Extrudable } from "../helpers/types.js";
5
- import { LazyVertex } from "./lazy-vertex.js";
6
- import { GeometrySceneObject } from "./2d/geometry.js";
7
- export declare class Region2D extends SceneObject implements Extrudable {
8
- private _points;
9
- private _extrudable;
10
- constructor(extrudable: Extrudable);
11
- points(...ps: LazyVertex[]): this;
12
- isExtrudable(): boolean;
13
- build(): void;
14
- getGeometries(): (Wire | Edge)[];
15
- getGeometriesWithOwner(): Map<Wire | Edge, GeometrySceneObject>;
16
- getPlane(): import("../math/plane.js").Plane;
17
- getDependencies(): SceneObject[];
18
- createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
19
- compareTo(other: Region2D): boolean;
20
- getType(): string;
21
- serialize(): {
22
- plane: any;
23
- selections: any;
24
- };
25
- }
@@ -1,185 +0,0 @@
1
- import { SceneObject } from "../common/scene-object.js";
2
- import { FaceOps } from "../oc/face-ops.js";
3
- import { Explorer } from "../oc/explorer.js";
4
- import { ShapeOps } from "../oc/shape-ops.js";
5
- export class Region2D extends SceneObject {
6
- _points = [];
7
- _extrudable;
8
- constructor(extrudable) {
9
- super();
10
- this._extrudable = extrudable;
11
- }
12
- points(...ps) {
13
- this._points = ps;
14
- return this;
15
- }
16
- isExtrudable() {
17
- return true;
18
- }
19
- build() {
20
- const plane = this._extrudable.getPlane();
21
- const shapes = this._extrudable.getGeometries();
22
- const allFaces = FaceOps.buildPlanarFaces(shapes, plane);
23
- if (allFaces.length === 0) {
24
- return;
25
- }
26
- // Compute bounding box diagonals for disambiguation (smallest face wins)
27
- const faceDiagonals = allFaces.map(face => {
28
- const bbox = ShapeOps.getBoundingBox(face);
29
- return Math.sqrt((bbox.maxX - bbox.minX) ** 2 +
30
- (bbox.maxY - bbox.minY) ** 2);
31
- });
32
- // Match each user point to the smallest face containing it
33
- const selectedIndices = new Set();
34
- const pointForFace = new Map();
35
- for (const lazyPoint of this._points) {
36
- const point2d = lazyPoint.asPoint2D();
37
- const point3d = plane.localToWorld(point2d);
38
- let bestIdx = -1;
39
- let bestDiag = Infinity;
40
- for (let i = 0; i < allFaces.length; i++) {
41
- if (FaceOps.isPointInsideFace(point3d, allFaces[i])) {
42
- if (faceDiagonals[i] < bestDiag) {
43
- bestDiag = faceDiagonals[i];
44
- bestIdx = i;
45
- }
46
- }
47
- }
48
- if (bestIdx >= 0) {
49
- selectedIndices.add(bestIdx);
50
- // Store rounded values to match what handleInsertPoint writes to source code
51
- pointForFace.set(bestIdx, [
52
- Math.round(point2d.x * 100) / 100,
53
- Math.round(point2d.y * 100) / 100,
54
- ]);
55
- }
56
- }
57
- // Determine nesting: find holes for each selected face
58
- const holesFor = new Map();
59
- for (const selIdx of selectedIndices) {
60
- const holes = [];
61
- for (let i = 0; i < allFaces.length; i++) {
62
- if (i === selIdx || selectedIndices.has(i)) {
63
- continue;
64
- }
65
- const innerWires = Explorer.findWiresWrapped(allFaces[i]);
66
- if (innerWires.length > 0) {
67
- const firstVertex = innerWires[0].getFirstVertex();
68
- if (firstVertex && FaceOps.isPointInsideFace(firstVertex.toPoint(), allFaces[selIdx])) {
69
- holes.push(i);
70
- }
71
- }
72
- }
73
- if (holes.length > 0) {
74
- holesFor.set(selIdx, holes);
75
- }
76
- }
77
- // Extract wires for getGeometries() BEFORE drilling (which mutates wires in-place)
78
- const resultWires = [];
79
- for (const selIdx of selectedIndices) {
80
- const wires = Explorer.findWiresWrapped(allFaces[selIdx]);
81
- if (wires.length > 0) {
82
- resultWires.push(wires[0]);
83
- }
84
- }
85
- for (const [, holeIndices] of holesFor) {
86
- for (const hi of holeIndices) {
87
- const wires = Explorer.findWiresWrapped(allFaces[hi]);
88
- if (wires.length > 0) {
89
- resultWires.push(wires[0]);
90
- }
91
- }
92
- }
93
- this.setState('result-wires', resultWires);
94
- // Build drilled faces for selected regions with holes
95
- const drilledFaces = new Map();
96
- for (const [selIdx, holeIndices] of holesFor) {
97
- const outerWires = Explorer.findWiresWrapped(allFaces[selIdx]);
98
- if (outerWires.length === 0) {
99
- continue;
100
- }
101
- const outerWire = outerWires[0];
102
- const holeWires = [];
103
- for (const hi of holeIndices) {
104
- const wires = Explorer.findWiresWrapped(allFaces[hi]);
105
- if (wires.length > 0) {
106
- wires[0].getShape().Reverse();
107
- holeWires.push(wires[0]);
108
- }
109
- }
110
- if (holeWires.length > 0) {
111
- drilledFaces.set(selIdx, FaceOps.makeFaceWithHoles(outerWire, holeWires));
112
- }
113
- }
114
- // Add ALL faces as shapes (for rendering/raycasting)
115
- // Selected faces that have holes are replaced with drilled versions
116
- for (let i = 0; i < allFaces.length; i++) {
117
- const face = drilledFaces.has(i) ? drilledFaces.get(i) : allFaces[i];
118
- this.addShape(face);
119
- }
120
- // Build selection mapping: map shape indices to their selection state
121
- const addedShapes = this.getOwnShapes({ excludeMeta: false, excludeGuide: false });
122
- const selections = [];
123
- for (let i = 0; i < addedShapes.length; i++) {
124
- if (selectedIndices.has(i) && pointForFace.has(i)) {
125
- selections.push({
126
- shapeId: addedShapes[i].id,
127
- point: pointForFace.get(i),
128
- });
129
- }
130
- }
131
- this.setState('selections', selections);
132
- this.setState('all-face-count', allFaces.length);
133
- this.setState('selected-indices', [...selectedIndices]);
134
- }
135
- getGeometries() {
136
- return this.getState('result-wires') || [];
137
- }
138
- getGeometriesWithOwner() {
139
- const result = new Map();
140
- for (const wire of this.getGeometries()) {
141
- result.set(wire, this);
142
- }
143
- return result;
144
- }
145
- getPlane() {
146
- return this._extrudable.getPlane();
147
- }
148
- getDependencies() {
149
- return [this._extrudable];
150
- }
151
- createCopy(remap) {
152
- const extrudable = (remap.get(this._extrudable) || this._extrudable);
153
- const copy = new Region2D(extrudable);
154
- if (this._points.length > 0) {
155
- copy.points(...this._points);
156
- }
157
- return copy;
158
- }
159
- compareTo(other) {
160
- if (!(other instanceof Region2D)) {
161
- return false;
162
- }
163
- if (!super.compareTo(other)) {
164
- return false;
165
- }
166
- if (this._points.length !== other._points.length) {
167
- return false;
168
- }
169
- for (let i = 0; i < this._points.length; i++) {
170
- if (!this._points[i].compareTo(other._points[i])) {
171
- return false;
172
- }
173
- }
174
- return true;
175
- }
176
- getType() {
177
- return "region";
178
- }
179
- serialize() {
180
- return {
181
- plane: this._extrudable.serialize?.()?.plane || null,
182
- selections: this.getState('selections') || [],
183
- };
184
- }
185
- }