-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbeam.js
119 lines (104 loc) · 3.11 KB
/
beam.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/** @import * as Replicad from 'replicad' */
export const defaultParams = {
gridSpacingInMm: 20,
lengthInGrids: 5,
fastenerDiameterInMm: 8,
outerFilletInMm: 2,
holeFilletInMm: 0.5,
useHexiholes: true,
}
/**
* @param {typeof defaultParams} params
*/
export default function main(params) {
const { drawCircle, drawRoundedRectangle, combineFinderFilters, EdgeFinder } = replicad
const {
gridSpacingInMm,
lengthInGrids,
fastenerDiameterInMm,
outerFilletInMm,
holeFilletInMm,
useHexiholes,
} = params
const lengthInMm = lengthInGrids * gridSpacingInMm
let beam = /** @type Replicad.Solid */ (
drawRoundedRectangle(gridSpacingInMm, gridSpacingInMm, outerFilletInMm)
.sketchOnPlane('YZ')
.extrude(lengthInMm)
)
const drawHole = useHexiholes
? (/** @type number */ radius) => drawHexihole({ radius })
: drawCircle
for (let gridIndex = 0; gridIndex < lengthInGrids; gridIndex++) {
const holeY = /** @type Replicad.Solid */ (
drawHole((1 / 2) * fastenerDiameterInMm)
.sketchOnPlane('XZ', -(1 / 2) * gridSpacingInMm)
.extrude(gridSpacingInMm)
.translateX((1 / 2 + gridIndex) * gridSpacingInMm)
)
const holeZ = /** @type Replicad.Solid */ (
drawHole((1 / 2) * fastenerDiameterInMm)
.sketchOnPlane('XY', -(1 / 2) * gridSpacingInMm)
.extrude(gridSpacingInMm)
.translateX((1 / 2 + gridIndex) * gridSpacingInMm)
)
beam = beam.cut(holeY).cut(holeZ)
}
const [filters] = combineFinderFilters([
{
// @ts-ignore
filter: new EdgeFinder().either([
(f) => f.inPlane('YZ', 0),
(f) => f.inPlane('YZ', lengthInMm),
]),
radius: outerFilletInMm,
},
{
// @ts-ignore
filter: new EdgeFinder(),
radius: holeFilletInMm,
},
])
beam = beam.fillet(filters)
return {
shape: beam,
}
}
/**
* @param {object} options
* @param {number} options.radius
* @param {'v-bottom' | 'flat-bottom'} [options.orientation]
*/
function drawHexihole(options) {
// https://en.wikipedia.org/wiki/Hexagon#Regular_hexagon
// The common length of the sides equals the radius of the circumscribed circle or circumcircle,
// which equals (2/sqrt(3)) times the apothem (radius of the inscribed circle).
const { radius: inscribedRadius, orientation } = options
const circumscribedRadius = inscribedRadius * (2 / Math.sqrt(3))
return drawHexagon({ radius: circumscribedRadius, orientation })
}
/**
* @param {object} options
* @param {number} options.radius
* @param {'v-bottom' | 'flat-bottom'} [options.orientation]
*/
function drawHexagon(options) {
const { draw } = replicad
const { radius, orientation = 'v-bottom' } = options
/** @type {[number, number]} */
let startPoint
/** @type {number} */
let startAngle
if (orientation === 'v-bottom') {
startPoint = [0, -radius]
startAngle = 30
} else {
startPoint = [radius, 0]
startAngle = 120
}
let pen = draw().movePointerTo(startPoint)
for (let sideIndex = 0; sideIndex < 6; sideIndex++) {
pen = pen.polarLine(radius, sideIndex * 60 + startAngle)
}
return pen.close()
}