aboutsummaryrefslogtreecommitdiff
path: root/pride-braid.scad
diff options
context:
space:
mode:
Diffstat (limited to 'pride-braid.scad')
-rw-r--r--pride-braid.scad91
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);
+}