jscad-electronics 0.0.185 → 0.0.187

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/README.md CHANGED
@@ -50,6 +50,35 @@ This example creates a 3D model of an SOT-23-3P component with extruded pads.
50
50
 
51
51
  ## Available Components
52
52
 
53
+ ### Cable meshes
54
+
55
+ `jscad-electronics/cables` creates indexed, colored triangle meshes for USB-C,
56
+ JST SH/PH, and NEMA 5-15P to IEC C13 cables. Pass a physical definition from
57
+ cableprinter and an already resolved path in millimeters (+Z up):
58
+
59
+ ```ts
60
+ import { createCableMeshes } from "jscad-electronics/cables"
61
+ import { parseCableString } from "@tscircuit/cableprinter"
62
+
63
+ const meshes = createCableMeshes({
64
+ definition: parseCableString("jst_ph_pins4"),
65
+ path: resolvedPath,
66
+ })
67
+ ```
68
+
69
+ The first and last path samples are cable exit centers. Connector poses follow
70
+ the endpoint tangents; bundle wires follow parallel-transported frames. Each
71
+ mesh provides `positions`, `indices`, `color`, `name`, and `smooth`. Connector
72
+ details include hollow shells/sockets, contacts, and strain reliefs. Physical
73
+ definitions, route generation and sagging remain separate from this renderer.
74
+ The cables entrypoint does not import React or a viewer.
75
+
76
+ Cable visual regression tests live in `tests/snapshots/cable-meshes.test.ts`.
77
+ They render local meshes with poppygl: all four cable types and mating faces,
78
+ JST SH/PH pin-count comparisons, and spatial paths viewed from both sides.
79
+ Annotations use `@tscircuit/alphabet`. Regenerate these six PNGs explicitly with
80
+ `BUN_UPDATE_SNAPSHOTS=1 bun test tests/snapshots/cable-meshes.test.ts`.
81
+
53
82
  jscad-electronics includes models for various components, including:
54
83
 
55
84
  - Resistors (0402, 0603, 0805)
@@ -0,0 +1,52 @@
1
+ type CablePoint = [number, number, number];
2
+ type CableColor = [number, number, number, number];
3
+ type ConnectorBody = {
4
+ bodyWidth: number;
5
+ bodyHeight: number;
6
+ bodyDepth: number;
7
+ };
8
+ type CableConnectorSpec = ConnectorBody & ({
9
+ kind: "usb_c_plug";
10
+ shellWidth: number;
11
+ shellHeight: number;
12
+ shellDepth: number;
13
+ } | {
14
+ kind: "jst_sh_housing" | "jst_ph_housing";
15
+ pinCount: number;
16
+ pitch: number;
17
+ } | {
18
+ kind: "nema_5_15p" | "iec_c13";
19
+ });
20
+ /** Structural subset of a cableprinter definition; no runtime spec dependency. */
21
+ type CableGeometryDefinition = {
22
+ connectorA: CableConnectorSpec;
23
+ connectorB: CableConnectorSpec;
24
+ crossSection: {
25
+ kind: "round_jacket";
26
+ diameter: number;
27
+ color: string;
28
+ } | {
29
+ kind: "wire_bundle";
30
+ wirePitch: number;
31
+ wires: {
32
+ diameter: number;
33
+ color: string;
34
+ }[];
35
+ };
36
+ };
37
+ type CableMesh = {
38
+ name: string;
39
+ positions: number[];
40
+ indices: number[];
41
+ color: CableColor;
42
+ smooth: boolean;
43
+ };
44
+
45
+ /** Mesh generation only. Path samples are already resolved in world millimeters, +Z up. */
46
+ declare function createCableMeshes({ definition, path, radialSegments, }: {
47
+ definition: CableGeometryDefinition;
48
+ path: CablePoint[];
49
+ radialSegments?: number;
50
+ }): CableMesh[];
51
+
52
+ export { type CableColor, type CableConnectorSpec, type CableGeometryDefinition, type CableMesh, type CablePoint, createCableMeshes };
package/dist/cables.js ADDED
@@ -0,0 +1,582 @@
1
+ // lib/cables/connector-meshes.ts
2
+ import jscad2 from "@jscad/modeling";
3
+
4
+ // lib/cables/geometry-to-mesh.ts
5
+ import jscad from "@jscad/modeling";
6
+
7
+ // lib/cables/path-frames.ts
8
+ var add = (a, b) => [
9
+ a[0] + b[0],
10
+ a[1] + b[1],
11
+ a[2] + b[2]
12
+ ];
13
+ var subtract = (a, b) => [
14
+ a[0] - b[0],
15
+ a[1] - b[1],
16
+ a[2] - b[2]
17
+ ];
18
+ var scale = (point, factor) => [
19
+ point[0] * factor,
20
+ point[1] * factor,
21
+ point[2] * factor
22
+ ];
23
+ var dot = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
24
+ var cross = (a, b) => [
25
+ a[1] * b[2] - a[2] * b[1],
26
+ a[2] * b[0] - a[0] * b[2],
27
+ a[0] * b[1] - a[1] * b[0]
28
+ ];
29
+ function normalize(point) {
30
+ const length = Math.hypot(...point);
31
+ if (length < 1e-10)
32
+ throw new Error(
33
+ "Cable path must not contain coincident points or a reversing tangent"
34
+ );
35
+ return scale(point, 1 / length);
36
+ }
37
+ function createCablePathFrames(path) {
38
+ if (path.length < 2 || path.some((point) => point.length !== 3 || !point.every(Number.isFinite))) {
39
+ throw new Error("Cable path needs at least two finite 3D points");
40
+ }
41
+ const segments = path.slice(1).map((point, index) => normalize(subtract(point, path[index])));
42
+ const tangents = path.map(
43
+ (_, index) => index === 0 ? segments[0] : index === path.length - 1 ? segments.at(-1) : normalize(add(segments[index - 1], segments[index]))
44
+ );
45
+ const initialUp = Math.abs(tangents[0][2]) > 0.95 ? [0, 1, 0] : [0, 0, 1];
46
+ let normal = normalize(cross(initialUp, tangents[0]));
47
+ return tangents.map((tangent, index) => {
48
+ if (index > 0) {
49
+ const previousTangent = tangents[index - 1];
50
+ const axis = cross(previousTangent, tangent);
51
+ const sine = Math.hypot(...axis);
52
+ const cosine = Math.max(-1, Math.min(1, dot(previousTangent, tangent)));
53
+ if (sine > 1e-10) {
54
+ const unitAxis = scale(axis, 1 / sine);
55
+ normal = normalize(
56
+ add(
57
+ add(scale(normal, cosine), scale(cross(unitAxis, normal), sine)),
58
+ scale(unitAxis, dot(unitAxis, normal) * (1 - cosine))
59
+ )
60
+ );
61
+ }
62
+ }
63
+ return {
64
+ point: path[index],
65
+ tangent,
66
+ normal,
67
+ binormal: normalize(cross(tangent, normal))
68
+ };
69
+ });
70
+ }
71
+
72
+ // lib/cables/geometry-to-mesh.ts
73
+ function geometryToCableMesh({
74
+ geometry,
75
+ color,
76
+ name
77
+ }) {
78
+ const triangles = jscad.geometries.geom3.toPolygons(geometry);
79
+ const positions = [];
80
+ const indices = [];
81
+ const vertices = /* @__PURE__ */ new Map();
82
+ for (const triangle of triangles) {
83
+ const polygonIndices = [];
84
+ for (const point of triangle.vertices) {
85
+ const key = point.map((coordinate) => coordinate.toFixed(8)).join(",");
86
+ let index = vertices.get(key);
87
+ if (index === void 0) {
88
+ index = positions.length / 3;
89
+ positions.push(...point);
90
+ vertices.set(key, index);
91
+ }
92
+ polygonIndices.push(index);
93
+ }
94
+ for (let side = 1; side < polygonIndices.length - 1; side++) {
95
+ indices.push(
96
+ polygonIndices[0],
97
+ polygonIndices[side],
98
+ polygonIndices[side + 1]
99
+ );
100
+ }
101
+ }
102
+ return { name, positions, indices, color, smooth: false };
103
+ }
104
+ function placeConnectorMesh({
105
+ mesh,
106
+ frame,
107
+ wireExitDepth,
108
+ isEnd
109
+ }) {
110
+ const tangent = scale(frame.tangent, isEnd ? -1 : 1);
111
+ const binormal = isEnd ? scale(frame.binormal, -1) : frame.binormal;
112
+ const origin = add(frame.point, scale(tangent, -wireExitDepth));
113
+ const positions = [];
114
+ for (let index = 0; index < mesh.positions.length; index += 3) {
115
+ positions.push(
116
+ ...add(
117
+ origin,
118
+ add(
119
+ add(
120
+ scale(frame.normal, mesh.positions[index]),
121
+ scale(binormal, mesh.positions[index + 1])
122
+ ),
123
+ scale(tangent, mesh.positions[index + 2])
124
+ )
125
+ )
126
+ );
127
+ }
128
+ return { ...mesh, positions };
129
+ }
130
+
131
+ // lib/cables/connector-meshes.ts
132
+ var { cuboid, roundedCuboid, cylinder, roundedRectangle, polygon, sphere } = jscad2.primitives;
133
+ var { extrudeLinear } = jscad2.extrusions;
134
+ var { translate, rotateY } = jscad2.transforms;
135
+ var { subtract: subtract2, union } = jscad2.booleans;
136
+ var plastic = [0.055, 0.07, 0.09, 1];
137
+ var housing = [0.86, 0.84, 0.75, 1];
138
+ var metal = [0.6, 0.64, 0.7, 1];
139
+ var brass = [0.66, 0.46, 0.18, 1];
140
+ function connectorWireExitDepth(connector) {
141
+ if (connector.kind === "usb_c_plug")
142
+ return connector.shellDepth + connector.bodyDepth;
143
+ if (connector.kind === "nema_5_15p") return 19.05 + connector.bodyDepth;
144
+ return connector.bodyDepth;
145
+ }
146
+ function createJstMeshes(connector) {
147
+ const {
148
+ bodyWidth: width,
149
+ bodyHeight: height,
150
+ bodyDepth: depth,
151
+ pinCount,
152
+ pitch
153
+ } = connector;
154
+ const opening = pitch === 1 ? 0.55 : 1.05;
155
+ const holes = Array.from({ length: pinCount }, (_, index) => {
156
+ const x = (index - (pinCount - 1) / 2) * pitch;
157
+ return cuboid({
158
+ size: [opening, opening * 1.35, depth - 0.6],
159
+ center: [x, 0, (depth - 0.6) / 2 - 0.02]
160
+ });
161
+ });
162
+ const backHoles = Array.from(
163
+ { length: pinCount },
164
+ (_, index) => cylinder({
165
+ radius: pitch * 0.34,
166
+ height: 1.3,
167
+ segments: 16,
168
+ center: [(index - (pinCount - 1) / 2) * pitch, 0, depth - 0.5]
169
+ })
170
+ );
171
+ const latchCut = cuboid({
172
+ size: [width * 0.45, 0.5, depth * 0.5],
173
+ center: [0, height / 2, depth * 0.65]
174
+ });
175
+ const body = subtract2(
176
+ roundedCuboid({
177
+ size: [width, height, depth],
178
+ center: [0, 0, depth / 2],
179
+ roundRadius: 0.1,
180
+ segments: 8
181
+ }),
182
+ ...holes,
183
+ ...backHoles,
184
+ latchCut,
185
+ ...Array.from(
186
+ { length: pinCount },
187
+ (_, index) => cuboid({
188
+ size: [opening * 0.8, height * 0.7, depth * 0.24],
189
+ center: [(index - (pinCount - 1) / 2) * pitch, height / 2, depth * 0.7]
190
+ })
191
+ )
192
+ );
193
+ const contacts = Array.from({ length: pinCount }, (_, index) => {
194
+ const x = (index - (pinCount - 1) / 2) * pitch;
195
+ return geometryToCableMesh({
196
+ name: `contact-${index + 1}`,
197
+ color: metal,
198
+ geometry: subtract2(
199
+ cuboid({
200
+ size: [opening * 0.92, opening * 1.25, depth * 0.65],
201
+ center: [x, 0, depth * 0.45]
202
+ }),
203
+ cuboid({
204
+ size: [
205
+ opening * 0.92 - 0.12,
206
+ opening * 1.25 - 0.12,
207
+ depth * 0.65 + 0.2
208
+ ],
209
+ center: [x, 0, depth * 0.45]
210
+ })
211
+ )
212
+ });
213
+ });
214
+ return [
215
+ geometryToCableMesh({ geometry: body, color: housing, name: "housing" }),
216
+ ...contacts
217
+ ];
218
+ }
219
+ function createUsbMeshes(connector) {
220
+ const {
221
+ shellWidth,
222
+ shellHeight,
223
+ shellDepth,
224
+ bodyWidth,
225
+ bodyHeight,
226
+ bodyDepth
227
+ } = connector;
228
+ const shell = subtract2(
229
+ extrudeLinear(
230
+ { height: shellDepth },
231
+ roundedRectangle({
232
+ size: [shellWidth, shellHeight],
233
+ roundRadius: shellHeight / 2 - 0.02,
234
+ segments: 32
235
+ })
236
+ ),
237
+ translate(
238
+ [0, 0, -0.1],
239
+ extrudeLinear(
240
+ { height: shellDepth + 0.2 },
241
+ roundedRectangle({
242
+ size: [shellWidth - 0.4, shellHeight - 0.4],
243
+ roundRadius: (shellHeight - 0.4) / 2 - 0.02,
244
+ segments: 32
245
+ })
246
+ )
247
+ )
248
+ );
249
+ const liner = subtract2(
250
+ extrudeLinear(
251
+ { height: shellDepth },
252
+ roundedRectangle({
253
+ size: [shellWidth - 0.41, shellHeight - 0.41],
254
+ roundRadius: 0.85,
255
+ segments: 32
256
+ })
257
+ ),
258
+ translate(
259
+ [0, 0, -0.1],
260
+ extrudeLinear(
261
+ { height: shellDepth - 0.3 },
262
+ roundedRectangle({
263
+ size: [shellWidth - 0.8, shellHeight - 0.8],
264
+ roundRadius: 0.65,
265
+ segments: 32
266
+ })
267
+ )
268
+ )
269
+ );
270
+ const body = roundedCuboid({
271
+ size: [bodyWidth, bodyHeight, bodyDepth],
272
+ center: [0, 0, shellDepth + bodyDepth / 2],
273
+ roundRadius: Math.min(1.3, bodyHeight / 4),
274
+ segments: 16
275
+ });
276
+ const contacts = Array.from(
277
+ { length: 24 },
278
+ (_, index) => cuboid({
279
+ size: [0.22, 0.08, 3.5],
280
+ center: [(index % 12 - 5.5) * 0.5, index < 12 ? 0.77 : -0.77, 2.6]
281
+ })
282
+ );
283
+ return [
284
+ geometryToCableMesh({ geometry: body, color: plastic, name: "overmold" }),
285
+ geometryToCableMesh({ geometry: shell, color: metal, name: "shell" }),
286
+ geometryToCableMesh({
287
+ geometry: liner,
288
+ color: [0.025, 0.026, 0.03, 1],
289
+ name: "liner"
290
+ }),
291
+ ...contacts.map(
292
+ (geometry, index) => geometryToCableMesh({
293
+ geometry,
294
+ color: brass,
295
+ name: `contact-${index + 1}`
296
+ })
297
+ )
298
+ ];
299
+ }
300
+ function createMainsMeshes(connector) {
301
+ const { bodyWidth, bodyHeight, bodyDepth, kind } = connector;
302
+ const faceDepth = kind === "nema_5_15p" ? 19.05 : 0;
303
+ let body = roundedCuboid({
304
+ size: [bodyWidth, bodyHeight, bodyDepth],
305
+ center: [0, 0, faceDepth + bodyDepth / 2],
306
+ roundRadius: 2,
307
+ segments: 16
308
+ });
309
+ if (kind === "nema_5_15p") {
310
+ const blades = [-6.35, 6.35].map((x) => {
311
+ const blade = cuboid({
312
+ size: [1.524, 6.35, 15.875],
313
+ center: [x, 2.7, 19.05 - 15.875 / 2]
314
+ });
315
+ const hole = translate(
316
+ [x, 2.7, 7.3],
317
+ rotateY(
318
+ Math.PI / 2,
319
+ cylinder({ radius: 1.1, height: 3, segments: 20 })
320
+ )
321
+ );
322
+ return subtract2(blade, hole);
323
+ });
324
+ const ground = union(
325
+ cylinder({
326
+ radius: 2.38125,
327
+ height: 19.05 - 2.38125,
328
+ center: [0, -9.20625, (19.05 + 2.38125) / 2],
329
+ segments: 32
330
+ }),
331
+ sphere({ radius: 2.38125, center: [0, -9.20625, 2.38125], segments: 32 })
332
+ );
333
+ return [
334
+ geometryToCableMesh({
335
+ geometry: body,
336
+ color: plastic,
337
+ name: "plug-body"
338
+ }),
339
+ ...blades.map(
340
+ (geometry, index) => geometryToCableMesh({
341
+ geometry,
342
+ color: brass,
343
+ name: `blade-${index + 1}`
344
+ })
345
+ ),
346
+ geometryToCableMesh({
347
+ geometry: ground,
348
+ color: brass,
349
+ name: "ground-pin"
350
+ })
351
+ ];
352
+ }
353
+ const recess = translate(
354
+ [0, 0, -0.1],
355
+ extrudeLinear(
356
+ { height: 3.2 },
357
+ polygon({
358
+ points: [
359
+ [-9, -6],
360
+ [9, -6],
361
+ [9, 2],
362
+ [5, 6],
363
+ [-5, 6],
364
+ [-9, 2]
365
+ ]
366
+ })
367
+ )
368
+ );
369
+ const sockets = [
370
+ [-4.4, -1.8, 8],
371
+ [4.4, -1.8, 8],
372
+ [0, 3.1, 8]
373
+ ];
374
+ body = subtract2(
375
+ body,
376
+ recess,
377
+ ...sockets.map((center) => cuboid({ size: [2.3, 3.4, 16.2], center }))
378
+ );
379
+ return [
380
+ geometryToCableMesh({
381
+ geometry: body,
382
+ color: plastic,
383
+ name: "appliance-body"
384
+ }),
385
+ ...sockets.map(
386
+ ([x, y], index) => geometryToCableMesh({
387
+ geometry: cuboid({ size: [0.15, 2.8, 6], center: [x - 1.05, y, 7.8] }),
388
+ color: brass,
389
+ name: `socket-contact-${index + 1}`
390
+ })
391
+ )
392
+ ];
393
+ }
394
+ function createConnectorMeshes({
395
+ connector,
396
+ jacketDiameter
397
+ }) {
398
+ const meshes = connector.kind === "usb_c_plug" ? createUsbMeshes(connector) : "pinCount" in connector ? createJstMeshes(connector) : createMainsMeshes(connector);
399
+ if (jacketDiameter !== void 0) {
400
+ const exit = connectorWireExitDepth(connector);
401
+ const boot = union(
402
+ cylinder({
403
+ radius: jacketDiameter / 2 + 0.15,
404
+ height: 5,
405
+ center: [0, 0, exit + 2.5],
406
+ segments: 32
407
+ }),
408
+ ...Array.from(
409
+ { length: 7 },
410
+ (_, index) => cylinder({
411
+ radius: jacketDiameter / 2 + 0.8 - index * 0.06,
412
+ height: 0.28,
413
+ center: [0, 0, exit + 0.4 + index * 0.7],
414
+ segments: 32
415
+ })
416
+ )
417
+ );
418
+ meshes.push(
419
+ geometryToCableMesh({
420
+ geometry: boot,
421
+ color: plastic,
422
+ name: "strain-relief"
423
+ })
424
+ );
425
+ }
426
+ return meshes;
427
+ }
428
+
429
+ // lib/cables/sweep-round-cable.ts
430
+ function sweepRoundCable({
431
+ frames,
432
+ diameter,
433
+ offset = 0,
434
+ radialSegments,
435
+ color,
436
+ name
437
+ }) {
438
+ const positions = [];
439
+ const indices = [];
440
+ for (const frame of frames) {
441
+ const center = add(frame.point, scale(frame.normal, offset));
442
+ for (let side = 0; side < radialSegments; side++) {
443
+ const angle = side * Math.PI * 2 / radialSegments;
444
+ positions.push(
445
+ ...add(
446
+ center,
447
+ add(
448
+ scale(frame.normal, diameter * Math.cos(angle) / 2),
449
+ scale(frame.binormal, diameter * Math.sin(angle) / 2)
450
+ )
451
+ )
452
+ );
453
+ }
454
+ }
455
+ for (let ring = 0; ring < frames.length - 1; ring++) {
456
+ for (let side = 0; side < radialSegments; side++) {
457
+ const a = ring * radialSegments + side;
458
+ const b = ring * radialSegments + (side + 1) % radialSegments;
459
+ const c = a + radialSegments;
460
+ const d = b + radialSegments;
461
+ indices.push(a, b, c, b, d, c);
462
+ }
463
+ }
464
+ const startCenter = positions.length / 3;
465
+ positions.push(...add(frames[0].point, scale(frames[0].normal, offset)));
466
+ const endCenter = positions.length / 3;
467
+ positions.push(
468
+ ...add(frames.at(-1).point, scale(frames.at(-1).normal, offset))
469
+ );
470
+ const lastRing = (frames.length - 1) * radialSegments;
471
+ for (let side = 0; side < radialSegments; side++) {
472
+ const next = (side + 1) % radialSegments;
473
+ indices.push(
474
+ startCenter,
475
+ next,
476
+ side,
477
+ endCenter,
478
+ lastRing + side,
479
+ lastRing + next
480
+ );
481
+ }
482
+ return { name, positions, indices, color, smooth: true };
483
+ }
484
+
485
+ // lib/cables/create-cable-meshes.ts
486
+ function parseCableColor(color) {
487
+ if (!/^#[a-f\d]{6}$/i.test(color))
488
+ throw new Error("Cable colors must be six-digit hex strings");
489
+ return [
490
+ parseInt(color.slice(1, 3), 16) / 255,
491
+ parseInt(color.slice(3, 5), 16) / 255,
492
+ parseInt(color.slice(5, 7), 16) / 255,
493
+ 1
494
+ ];
495
+ }
496
+ function validateCableDefinition(definition) {
497
+ for (const connector of [definition.connectorA, definition.connectorB]) {
498
+ const dimensions = [
499
+ connector.bodyWidth,
500
+ connector.bodyHeight,
501
+ connector.bodyDepth
502
+ ];
503
+ if (connector.kind === "usb_c_plug")
504
+ dimensions.push(
505
+ connector.shellWidth,
506
+ connector.shellHeight,
507
+ connector.shellDepth
508
+ );
509
+ if (dimensions.some(
510
+ (dimension) => !Number.isFinite(dimension) || dimension <= 0
511
+ ))
512
+ throw new Error("Connector dimensions must be finite and positive");
513
+ if ("pinCount" in connector && (!Number.isInteger(connector.pinCount) || connector.pinCount < 2 || !Number.isFinite(connector.pitch) || connector.pitch <= 0))
514
+ throw new Error(
515
+ "JST connectors need a positive pitch and at least two contacts"
516
+ );
517
+ }
518
+ const crossSection = definition.crossSection;
519
+ const diameters = crossSection.kind === "round_jacket" ? [crossSection.diameter] : crossSection.wires.map((wire) => wire.diameter);
520
+ if (diameters.length === 0 || diameters.some((diameter) => !Number.isFinite(diameter) || diameter <= 0))
521
+ throw new Error("Cable diameters must be finite and positive");
522
+ if (crossSection.kind === "wire_bundle") {
523
+ if (!Number.isFinite(crossSection.wirePitch) || crossSection.wires.some((wire) => wire.diameter > crossSection.wirePitch))
524
+ throw new Error("Insulated bundle wires must not overlap");
525
+ for (const connector of [definition.connectorA, definition.connectorB]) {
526
+ if (!("pinCount" in connector) || connector.pinCount !== crossSection.wires.length)
527
+ throw new Error("Bundle wire count must match connector contact count");
528
+ }
529
+ }
530
+ }
531
+ function createCableMeshes({
532
+ definition,
533
+ path,
534
+ radialSegments = 24
535
+ }) {
536
+ validateCableDefinition(definition);
537
+ if (!Number.isInteger(radialSegments) || radialSegments < 8 || radialSegments > 128)
538
+ throw new Error("radialSegments must be an integer from 8 to 128");
539
+ const frames = createCablePathFrames(path);
540
+ const crossSection = definition.crossSection;
541
+ const jacketDiameter = crossSection.kind === "round_jacket" ? crossSection.diameter : void 0;
542
+ const meshes = crossSection.kind === "round_jacket" ? [
543
+ sweepRoundCable({
544
+ frames,
545
+ diameter: crossSection.diameter,
546
+ radialSegments,
547
+ color: parseCableColor(crossSection.color),
548
+ name: "jacket"
549
+ })
550
+ ] : crossSection.wires.map(
551
+ (wire, index) => sweepRoundCable({
552
+ frames,
553
+ diameter: wire.diameter,
554
+ offset: (index - (crossSection.wires.length - 1) / 2) * crossSection.wirePitch,
555
+ radialSegments,
556
+ color: parseCableColor(wire.color),
557
+ name: `wire-${index + 1}`
558
+ })
559
+ );
560
+ for (const [index, connector] of [
561
+ definition.connectorA,
562
+ definition.connectorB
563
+ ].entries()) {
564
+ const frame = index === 0 ? frames[0] : frames.at(-1);
565
+ const parts = createConnectorMeshes({ connector, jacketDiameter });
566
+ meshes.push(
567
+ ...parts.map(
568
+ (mesh) => placeConnectorMesh({
569
+ mesh: { ...mesh, name: `${index === 0 ? "A" : "B"}-${mesh.name}` },
570
+ frame,
571
+ isEnd: index === 1,
572
+ wireExitDepth: connectorWireExitDepth(connector)
573
+ })
574
+ )
575
+ );
576
+ }
577
+ return meshes;
578
+ }
579
+ export {
580
+ createCableMeshes
581
+ };
582
+ //# sourceMappingURL=cables.js.map