1
import { getOC } from "./oclib";
13
import { makeLine, makeHelix, assembleWire, makeVertex } from "./shapeHelpers";
14
import { localGC } from "./register";
15
import { Vector, makeAx1, Point } from "./geom";
16
import { DEG2RAD } from "./constants";
22
} from "replicad-opencascadejs";
24
export const basicFaceExtrusion = (face: Face, extrusionVec: Vector): Solid => {
26
const solidBuilder = new oc.BRepPrimAPI_MakePrism_1(
32
const solid = new Solid(downcast(solidBuilder.Shape()));
33
solidBuilder.delete();
37
export const revolution = (
39
center: Point = [0, 0, 0],
40
direction: Point = [0, 0, 1],
44
const ax = makeAx1(center, direction);
46
const revolBuilder = new oc.BRepPrimAPI_MakeRevol_1(
53
const shape = cast(revolBuilder.Shape());
55
revolBuilder.delete();
57
if (!isShape3D(shape)) throw new Error("Could not revolve to a 3d shape");
61
export interface GenericSweepConfig {
63
auxiliarySpine?: Wire | Edge;
64
law?: null | Handle_Law_Function;
65
transitionMode?: "right" | "transformed" | "round";
66
withContact?: boolean;
67
support?: TopoDS_Shape;
68
forceProfileSpineOthogonality?: boolean;
74
sweepConfig: GenericSweepConfig,
76
): [Shape3D, Wire, Wire];
80
sweepConfig: GenericSweepConfig,
90
transitionMode = "right",
93
forceProfileSpineOthogonality,
94
}: GenericSweepConfig = {},
96
): Shape3D | [Shape3D, Wire, Wire] {
98
const withCorrection =
99
transitionMode === "round" ? true : !!forceProfileSpineOthogonality;
100
const sweepBuilder = new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped);
102
if (transitionMode) {
104
transformed: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_Transformed,
105
round: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_RoundCorner,
106
right: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_RightCorner,
107
}[transitionMode] as any;
108
if (mode) sweepBuilder.SetTransitionMode(mode);
112
sweepBuilder.SetMode_4(support);
114
sweepBuilder.SetMode_1(frenet);
116
if (auxiliarySpine) {
117
sweepBuilder.SetMode_5(
118
auxiliarySpine.wrapped,
120
oc.BRepFill_TypeOfContact.BRepFill_NoContact as any
124
if (!law) sweepBuilder.Add_1(wire.wrapped, !!withContact, withCorrection);
125
else sweepBuilder.SetLaw_1(wire.wrapped, law, !!withContact, withCorrection);
127
const progress = new oc.Message_ProgressRange_1();
128
sweepBuilder.Build(progress);
130
sweepBuilder.MakeSolid();
132
const shape = cast(sweepBuilder.Shape());
133
if (!isShape3D(shape)) throw new Error("Could not sweep to a 3d shape");
136
const startWire = cast(sweepBuilder.FirstShape());
137
const endWire = cast(sweepBuilder.LastShape());
138
if (!isWire(startWire))
139
throw new Error("Could not sweep with one start wire");
140
if (!isWire(endWire)) throw new Error("Could not sweep with one end wire");
141
sweepBuilder.delete();
142
return [shape, startWire, endWire];
145
sweepBuilder.delete();
150
export { genericSweep };
152
export interface ExtrusionProfile {
153
profile?: "s-curve" | "linear";
157
const buildLawFromProfile = (
158
extrusionLength: number,
159
{ profile, endFactor = 1 }: ExtrusionProfile
160
): Handle_Law_Function => {
161
let law: Law_S | Law_Linear;
164
if (profile === "s-curve") {
165
law = new oc.Law_S();
166
law.Set_1(0, 1, extrusionLength, endFactor);
167
} else if (profile === "linear") {
168
law = new oc.Law_Linear();
169
law.Set(0, 1, extrusionLength, endFactor);
171
throw new Error("Could not generate a law function");
174
// This is an API compatibility issue
175
// We might want to fix this in a way or another
176
return law.Trim(0, extrusionLength, 1e-6);
179
export const supportExtrude = (
183
support: TopoDS_Shape
185
const centerVec = new Vector(center);
186
const normalVec = new Vector(normal);
188
const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
189
const spine = assembleWire([mainSpineEdge]);
191
return genericSweep(wire, spine, { support });
194
function complexExtrude(
198
profileShape: ExtrusionProfile | undefined,
200
): [Shape3D, Wire, Wire];
201
function complexExtrude(
205
profileShape?: ExtrusionProfile,
208
function complexExtrude(
212
profileShape?: ExtrusionProfile,
214
): Shape3D | [Shape3D, Wire, Wire] {
215
const centerVec = new Vector(center);
216
const normalVec = new Vector(normal);
218
const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
219
const spine = assembleWire([mainSpineEdge]);
221
const law = profileShape
222
? buildLawFromProfile(normalVec.Length, profileShape)
225
// The ternary operator is here only to make typescript happy
226
const shape = shellMode
227
? genericSweep(wire, spine, { law }, shellMode)
228
: genericSweep(wire, spine, { law }, shellMode);
233
export { complexExtrude };
235
function twistExtrude(
237
angleDegrees: number,
240
profileShape?: ExtrusionProfile,
243
function twistExtrude(
245
angleDegrees: number,
248
profileShape: ExtrusionProfile | undefined,
250
): [Shape3D, Wire, Wire];
251
function twistExtrude(
253
angleDegrees: number,
256
profileShape?: ExtrusionProfile,
258
): Shape3D | [Shape3D, Wire, Wire] {
259
const centerVec = new Vector(center);
260
const normalVec = new Vector(normal);
262
const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
263
const spine = assembleWire([mainSpineEdge]);
265
const pitch = (360.0 / angleDegrees) * normalVec.Length;
268
const auxiliarySpine = makeHelix(
276
const law = profileShape
277
? buildLawFromProfile(normalVec.Length, profileShape)
280
// The ternary operator is here only to make typescript happy
281
const shape = shellMode
282
? genericSweep(wire, spine, { auxiliarySpine, law }, shellMode)
283
: genericSweep(wire, spine, { auxiliarySpine, law }, shellMode);
287
export { twistExtrude };
289
export interface LoftConfig {
297
{ ruled = true, startPoint, endPoint }: LoftConfig = {},
301
const [r, gc] = localGC();
303
const loftBuilder = r(
304
new oc.BRepOffsetAPI_ThruSections(!returnShell, ruled, 1e-6)
308
loftBuilder.AddVertex(r(makeVertex(startPoint)).wrapped);
310
wires.forEach((w) => loftBuilder.AddWire(w.wrapped));
312
loftBuilder.AddVertex(r(makeVertex(endPoint)).wrapped);
315
const progress = r(new oc.Message_ProgressRange_1());
316
loftBuilder.Build(progress);
317
const shape = cast(loftBuilder.Shape());
320
if (!isShape3D(shape)) throw new Error("Could not loft to a 3d shape");