/
solid.scad
84 lines (75 loc) · 2.9 KB
/
solid.scad
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
include <../constants.scad>
use <../util.scad>
use <../math/affine.scad>
use <../math/coordinates.scad>
use <plane.scad>
function prismPts(sides, sideLen, height, center=false) = [
let(poly = xyToXYZ(polygonPts(sides, sideLen)))
each for(_z = [if (center) [-height/2, height/2] else [0, height]].x)
translatePts(z=_z, pts=poly)
];
// TODO Refactor to us a prismFaces() function like torus().
module prism(sides, sideLen, height, center=false) {
bottomMin = 0;
bottomMax = sides - 1;
topMin = sides;
topMax = (2*sides) - 1;
polyhedron(
points=prismPts(sides, sideLen, height, center),
faces=[
range(bottomMin, 1, bottomMax), // bottom
range(topMax, -1, topMin), // top, negative to be clockwise
each for (s=[0:1:sides-1]) [ // sides
let(
bottomLeft = s,
topLeft = s+sides,
tr = topLeft + 1, br = bottomLeft + 1,
topRight = [if (tr <= topMax) tr else (tr % sides) + sides].x,
bottomRight = [if (br <= bottomMax) br else br % sides].x
)
[bottomLeft, topLeft, topRight, bottomRight]
]
]
);
}
/*
Generates points on a torus by generating circles, standing them on on their side,
translating them out to meet the edge of the torus, and rotating them about the
origin.
*/
function torusPts(minorRad, majorRad, minorSegments=undef, majorSegments=undef) = [
let(c=xyToXYZ(circlePts(minorRad, $fn=minorSegments)))
each for(t=angles($fn=majorSegments))
rotZPts(t,
pts=translatePts(x=majorRad,
pts=rotXPts(90,
pts=c
)))
];
/*
Generates faces of a torus by taking each point, and drawing a box to include the
points above it, the point above and to the right, and the point to the immediate
right.
This box is not coplanar, so it's further divided along it's diagonal
into two triangles, as any three points are coplanar.
*/
function torusFaces(minorSegments, majorSegments) =
let(vertexes=(minorSegments*majorSegments))
[ each for (major=iter(majorSegments), minor=iter(minorSegments))
let(
bottomLeft = minor + major*minorSegments,
topLeft = ((minor+1) % minorSegments) + major*minorSegments,
topRight = (topLeft + minorSegments) % vertexes,
bottomRight = (bottomLeft + minorSegments) % vertexes
)
[[bottomLeft, topLeft, topRight], [bottomLeft, topRight, bottomRight]]
// Since 3pts define a plane, these will always be coplanar.
];
module torus(minorRad, majorRad, minorSegments=undef, majorSegments=undef) {
_minorSegments = findFN($fn=minorSegments);
_majorSegments = findFN($fn=majorSegments);
polyhedron(
points = torusPts(minorRad, majorRad, _minorSegments, majorSegments),
faces = torusFaces(_minorSegments, _majorSegments)
);
}