diff options
Diffstat (limited to 'pride-braid.scad')
| -rw-r--r-- | pride-braid.scad | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/pride-braid.scad b/pride-braid.scad new file mode 100644 index 0000000..b25f3e4 --- /dev/null +++ b/pride-braid.scad @@ -0,0 +1,91 @@ +$fa = $preview ? 10 : 10; // 1; +$fs = $preview ? 0.2 : 0.2; // 0.01; + +colors = [ + "#df0000", + "#fb8721", + "#f1e100", + "#158f25", + "#2c3ee5", + "#7706af", + "#333333", + "#88502b", + "#5dccfb", + "#f0a67b", + "#ffffff" +]; +wideR = 65; +braidScale = 5; +braidR = 12; +strands = len(colors); +strandGap = 3; +wideRes = $preview ? 180 : 360; +strandRes = $preview ? 36 : 180; + +braidCircumference = 2 * PI * braidR; +strandR = (braidCircumference / strands - strandGap) / 2; +outermostCircumference = 2 * PI * (wideR + braidR); +strandH = outermostCircumference * wideRes / 360 + 0.1; + +function rodriguesRotation(vector, axis, angle) = + vector * cos(angle) + cross(axis, vector) * sin(angle) + axis * (axis * vector) * (1 - cos(angle)); + +/* +these cross sections were always parallel to the Z axis, +but that’s not really correct + +actual d/dwideT of center of braid is (-wideR sin wideT, wideR cos wideT, 0) +magnitude of that is wideR +absolute d/dwideT of center of strand is +( + -wideR sin wideT - braidR (braidScale cos wideT sin braidT + sin wideT cos braidT), + wideR cos wideT + braidR (-braidScale sin wideT sin braidT + cos wideT cos braidT), + braidR braidScale cos braidT +) +the Maxima CAS says that the magnitude of that is +sqrt(wideR² + 2wideRbraidR cos braidT + braidR²cos²braidT + braidR²braidScale²) +but actually OpenSCAD has a norm() function to get magnitudes anyway oops + +strand plane basis is strand plane normal x braid center normal, +since we know those two vectors are never parallel with braidScale ≠ 0 +*/ + +function point(wideT, strandI, strandT) = + let ( + braidO = [wideR * cos(wideT), wideR * sin(wideT), 0], + braidPlaneNormal = [-wideR * sin(wideT), wideR * cos(wideT), 0], + braidPlaneNormalUnit = braidPlaneNormal / wideR, + braidT = wideT * braidScale - strandI * 360 / strands, + braidPlaneRel = [braidR * cos(braidT), braidR * sin(braidT)], + strandO = [braidO.x + braidPlaneRel.x * cos(wideT), braidO.y + braidPlaneRel.x * sin(wideT), braidPlaneRel.y], + strandPlaneNormal = [braidPlaneNormal.x - braidR * (braidScale * cos(wideT) * sin(braidT) + sin(wideT) * cos(braidT)), braidPlaneNormal.y + braidR * (-braidScale * sin(wideT) * sin(braidT) + cos(wideT) * cos(braidT)), braidR * braidScale * cos(braidT)], + strandPlaneNormalUnit = strandPlaneNormal / norm(strandPlaneNormal), + strandPlaneBasis = cross(strandPlaneNormalUnit, braidPlaneNormalUnit), + strandRelDir = rodriguesRotation(strandPlaneBasis, strandPlaneNormalUnit, strandT), + strandRel = strandRelDir * strandR / norm(strandRelDir) + ) strandO + strandRel; + +pointCount = (wideRes + 1) * (strandRes + 1); + +module theStrand(strandI) { + color(colors[strandI]) + polyhedron( + [ for (wideT = [0 : 360/wideRes : 360.01]) + each [ for (strandT = [0 : 360/strandRes : 360.01]) + point(wideT, strandI, strandT) + ] + ], + [ for (wideTI = [0 : (strandRes + 1) : pointCount - 1]) + each [ for (strandTI = [wideTI : wideTI + strandRes + 1]) + each [ + [(strandTI + 1) % pointCount, strandTI % pointCount, (strandTI + strandRes + 1) % pointCount], + [(strandTI + strandRes + 1) % pointCount, strandTI % pointCount, (strandTI + strandRes) % pointCount], + ] + ] + ] + ); +} + +for (strandI = [0 : strands - 1]) { + theStrand(strandI); +} |