RepliCAD

Форк
0
/
addThickness.ts 
322 строки · 7.9 Кб
1
import { getOC } from "./oclib";
2
import {
3
  Solid,
4
  cast,
5
  downcast,
6
  Face,
7
  Shape3D,
8
  isShape3D,
9
  isWire,
10
  Wire,
11
  Edge,
12
} from "./shapes";
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";
17
import {
18
  Handle_Law_Function,
19
  Law_Linear,
20
  Law_S,
21
  TopoDS_Shape,
22
} from "replicad-opencascadejs";
23

24
export const basicFaceExtrusion = (face: Face, extrusionVec: Vector): Solid => {
25
  const oc = getOC();
26
  const solidBuilder = new oc.BRepPrimAPI_MakePrism_1(
27
    face.wrapped,
28
    extrusionVec.wrapped,
29
    false,
30
    true
31
  );
32
  const solid = new Solid(downcast(solidBuilder.Shape()));
33
  solidBuilder.delete();
34
  return solid;
35
};
36

37
export const revolution = (
38
  face: Face,
39
  center: Point = [0, 0, 0],
40
  direction: Point = [0, 0, 1],
41
  angle = 360
42
): Shape3D => {
43
  const oc = getOC();
44
  const ax = makeAx1(center, direction);
45

46
  const revolBuilder = new oc.BRepPrimAPI_MakeRevol_1(
47
    face.wrapped,
48
    ax,
49
    angle * DEG2RAD,
50
    false
51
  );
52

53
  const shape = cast(revolBuilder.Shape());
54
  ax.delete();
55
  revolBuilder.delete();
56

57
  if (!isShape3D(shape)) throw new Error("Could not revolve to a 3d shape");
58
  return shape;
59
};
60

61
export interface GenericSweepConfig {
62
  frenet?: boolean;
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;
69
}
70

71
function genericSweep(
72
  wire: Wire,
73
  spine: Wire,
74
  sweepConfig: GenericSweepConfig,
75
  shellMode: true
76
): [Shape3D, Wire, Wire];
77
function genericSweep(
78
  wire: Wire,
79
  spine: Wire,
80
  sweepConfig: GenericSweepConfig,
81
  shellMode?: false
82
): Shape3D;
83
function genericSweep(
84
  wire: Wire,
85
  spine: Wire,
86
  {
87
    frenet = false,
88
    auxiliarySpine,
89
    law = null,
90
    transitionMode = "right",
91
    withContact,
92
    support,
93
    forceProfileSpineOthogonality,
94
  }: GenericSweepConfig = {},
95
  shellMode = false
96
): Shape3D | [Shape3D, Wire, Wire] {
97
  const oc = getOC();
98
  const withCorrection =
99
    transitionMode === "round" ? true : !!forceProfileSpineOthogonality;
100
  const sweepBuilder = new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped);
101

102
  if (transitionMode) {
103
    const mode = {
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);
109
  }
110

111
  if (support) {
112
    sweepBuilder.SetMode_4(support);
113
  } else if (frenet) {
114
    sweepBuilder.SetMode_1(frenet);
115
  }
116
  if (auxiliarySpine) {
117
    sweepBuilder.SetMode_5(
118
      auxiliarySpine.wrapped,
119
      false,
120
      oc.BRepFill_TypeOfContact.BRepFill_NoContact as any
121
    );
122
  }
123

124
  if (!law) sweepBuilder.Add_1(wire.wrapped, !!withContact, withCorrection);
125
  else sweepBuilder.SetLaw_1(wire.wrapped, law, !!withContact, withCorrection);
126

127
  const progress = new oc.Message_ProgressRange_1();
128
  sweepBuilder.Build(progress);
129
  if (!shellMode) {
130
    sweepBuilder.MakeSolid();
131
  }
132
  const shape = cast(sweepBuilder.Shape());
133
  if (!isShape3D(shape)) throw new Error("Could not sweep to a 3d shape");
134

135
  if (shellMode) {
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];
143
  }
144

145
  sweepBuilder.delete();
146
  progress.delete();
147
  return shape;
148
}
149

150
export { genericSweep };
151

152
export interface ExtrusionProfile {
153
  profile?: "s-curve" | "linear";
154
  endFactor?: number;
155
}
156

157
const buildLawFromProfile = (
158
  extrusionLength: number,
159
  { profile, endFactor = 1 }: ExtrusionProfile
160
): Handle_Law_Function => {
161
  let law: Law_S | Law_Linear;
162
  const oc = getOC();
163

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);
170
  } else {
171
    throw new Error("Could not generate a law function");
172
  }
173

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);
177
};
178

179
export const supportExtrude = (
180
  wire: Wire,
181
  center: Point,
182
  normal: Point,
183
  support: TopoDS_Shape
184
): Shape3D => {
185
  const centerVec = new Vector(center);
186
  const normalVec = new Vector(normal);
187

188
  const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
189
  const spine = assembleWire([mainSpineEdge]);
190

191
  return genericSweep(wire, spine, { support });
192
};
193

194
function complexExtrude(
195
  wire: Wire,
196
  center: Point,
197
  normal: Point,
198
  profileShape: ExtrusionProfile | undefined,
199
  shellMode: true
200
): [Shape3D, Wire, Wire];
201
function complexExtrude(
202
  wire: Wire,
203
  center: Point,
204
  normal: Point,
205
  profileShape?: ExtrusionProfile,
206
  shellMode?: false
207
): Shape3D;
208
function complexExtrude(
209
  wire: Wire,
210
  center: Point,
211
  normal: Point,
212
  profileShape?: ExtrusionProfile,
213
  shellMode = false
214
): Shape3D | [Shape3D, Wire, Wire] {
215
  const centerVec = new Vector(center);
216
  const normalVec = new Vector(normal);
217

218
  const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
219
  const spine = assembleWire([mainSpineEdge]);
220

221
  const law = profileShape
222
    ? buildLawFromProfile(normalVec.Length, profileShape)
223
    : null;
224

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);
229

230
  return shape;
231
}
232

233
export { complexExtrude };
234

235
function twistExtrude(
236
  wire: Wire,
237
  angleDegrees: number,
238
  center: Point,
239
  normal: Point,
240
  profileShape?: ExtrusionProfile,
241
  shellMode?: false
242
): Shape3D;
243
function twistExtrude(
244
  wire: Wire,
245
  angleDegrees: number,
246
  center: Point,
247
  normal: Point,
248
  profileShape: ExtrusionProfile | undefined,
249
  shellMode: true
250
): [Shape3D, Wire, Wire];
251
function twistExtrude(
252
  wire: Wire,
253
  angleDegrees: number,
254
  center: Point,
255
  normal: Point,
256
  profileShape?: ExtrusionProfile,
257
  shellMode = false
258
): Shape3D | [Shape3D, Wire, Wire] {
259
  const centerVec = new Vector(center);
260
  const normalVec = new Vector(normal);
261

262
  const mainSpineEdge = makeLine(centerVec, centerVec.add(normalVec));
263
  const spine = assembleWire([mainSpineEdge]);
264

265
  const pitch = (360.0 / angleDegrees) * normalVec.Length;
266
  const radius = 1;
267

268
  const auxiliarySpine = makeHelix(
269
    pitch,
270
    normalVec.Length,
271
    radius,
272
    center,
273
    normal
274
  );
275

276
  const law = profileShape
277
    ? buildLawFromProfile(normalVec.Length, profileShape)
278
    : null;
279

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);
284

285
  return shape;
286
}
287
export { twistExtrude };
288

289
export interface LoftConfig {
290
  ruled?: boolean;
291
  startPoint?: Point;
292
  endPoint?: Point;
293
}
294

295
export const loft = (
296
  wires: Wire[],
297
  { ruled = true, startPoint, endPoint }: LoftConfig = {},
298
  returnShell = false
299
): Shape3D => {
300
  const oc = getOC();
301
  const [r, gc] = localGC();
302

303
  const loftBuilder = r(
304
    new oc.BRepOffsetAPI_ThruSections(!returnShell, ruled, 1e-6)
305
  );
306

307
  if (startPoint) {
308
    loftBuilder.AddVertex(r(makeVertex(startPoint)).wrapped);
309
  }
310
  wires.forEach((w) => loftBuilder.AddWire(w.wrapped));
311
  if (endPoint) {
312
    loftBuilder.AddVertex(r(makeVertex(endPoint)).wrapped);
313
  }
314

315
  const progress = r(new oc.Message_ProgressRange_1());
316
  loftBuilder.Build(progress);
317
  const shape = cast(loftBuilder.Shape());
318
  gc();
319

320
  if (!isShape3D(shape)) throw new Error("Could not loft to a 3d shape");
321
  return shape;
322
};
323

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.