Skip to content

Instantly share code, notes, and snippets.

@wware
Last active August 29, 2015 14:08
Show Gist options
  • Save wware/a3d4c75007e0da49827b to your computer and use it in GitHub Desktop.
Save wware/a3d4c75007e0da49827b to your computer and use it in GitHub Desktop.
Parameterized Sierpinski tetrahedron. It would be sweet if this were suitable for metal casting.
print """$fn = 30;
module bar(v1, v2, r) {
p = v2 - v1;
R = sqrt(p.x * p.x + p.y * p.y);
L = sqrt(R * R + p.z * p.z);
translate(v1)
rotate(atan2(R, p.z), [-p.y, p.x, 0])
cylinder(h=L, r=r);
}
Aa = [1, 0, 0];
Ba = [-1/2, sqrt(3) / 2, 0];
Ca = [-1/2, -sqrt(3) / 2, 0];
Da = [0, 0, sqrt(2)];
center = 0.25 * (Aa + Ba + Ca + Da);
A = Aa - center;
B = Ba - center;
C = Ca - center;
D = Da - center;
module tetrahedron(S, r) {
v1 = S * A;
v2 = S * B;
v3 = S * C;
v4 = S * D;
bar(v1, v2, r);
bar(v1, v3, r);
bar(v1, v4, r);
bar(v2, v3, r);
bar(v2, v4, r);
bar(v3, v4, r);
}
"""
S = 120
r = 0.05 * S
print """
translate({0} * A) sphere(r={1});
translate({0} * B) sphere(r={1});
translate({0} * C) sphere(r={1});
translate({0} * D) sphere(r={1});
""".format(S, r)
def recurse(S, r, depth):
print "tetrahedron({0}, {1});".format(S, r)
if depth > 0:
S, r = 0.5 * S, 0.7 * r
print "translate({0} * A) {{".format(S)
recurse(S, r, depth - 1)
print "}"
print "translate({0} * B) {{".format(S)
recurse(S, r, depth - 1)
print "}"
print "translate({0} * C) {{".format(S)
recurse(S, r, depth - 1)
print "}"
print "translate({0} * D) {{".format(S)
recurse(S, r, depth - 1)
print "}"
recurse(S, r, 3)
$fn = 16;
module bar(v1, v2, diam) {
p = v2 - v1;
R = sqrt(p.x * p.x + p.y * p.y);
L = sqrt(R * R + p.z * p.z);
translate(v1)
rotate(atan2(R, p.z), [-p.y, p.x, 0])
cylinder(h=L, d=diam);
}
Aa = [1, 0, 0];
Ba = [-1/2, sqrt(3) / 2, 0];
Ca = [-1/2, -sqrt(3) / 2, 0];
Da = [0, 0, sqrt(2)];
center = 0.25 * (Aa + Ba + Ca + Da);
A = Aa - center;
B = Ba - center;
C = Ca - center;
D = Da - center;
module tetrahedron(S, dim) {
v1 = S * A;
v2 = S * B;
v3 = S * C;
v4 = S * D;
bar(v1, v2, dim);
bar(v1, v3, dim);
bar(v1, v4, dim);
bar(v2, v3, dim);
bar(v2, v4, dim);
bar(v3, v4, dim);
}
module sierpinski_recurse(S, dim, depth, fn) {
if (depth > 0) {
tetrahedron(S, dim);
translate((S / 2) * A) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1);
}
translate((S / 2) * B) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1);
}
translate((S / 2) * C) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1);
}
translate((S / 2) * D) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1);
}
}
}
module sierpinski(S, depth) {
v1 = S * A;
v2 = S * B;
v3 = S * C;
v4 = S * D;
dim = 0.1 * S;
translate(v1) sphere(d=dim);
translate(v2) sphere(d=dim);
translate(v3) sphere(d=dim);
translate(v4) sphere(d=dim);
sierpinski_recurse(S, dim, depth + 1);
}
sierpinski(40, 5);

OpenSCAD on the Linux box is faster than on the Macbook, I think, but it won't do recursion. Recursion must be done in Python. So the Sierpinski code must be rewritten as a Python script or an exercise in SolidPython that generates OpenSCAD.

The Linux version of OpenSCAD has a few other differences. Cylinders (and possibly spheres) don't support diameter arguments, only radius arguments. Anyway, I'm adding a Python script to perform the recursion and produce a flat *.scad file.

Or instead of all this nonsense resulting from the fact that the OpenSCAD in the Ubuntu repository is old and broken, you could just go to the download page and get a version that works correctly.

module bar(v1, v2, diam) {
p = v2 - v1;
R = sqrt(p.x * p.x + p.y * p.y);
L = sqrt(R * R + p.z * p.z);
translate(v1)
rotate(atan2(R, p.z), [-p.y, p.x, 0])
cylinder(h=L, d=diam, $fn=6);
}
Aa = [1, 0, 0];
Ba = [-1/2, sqrt(3) / 2, 0];
Ca = [-1/2, -sqrt(3) / 2, 0];
Da = [0, 0, sqrt(2)];
center = 0.25 * (Aa + Ba + Ca + Da);
A = Aa - center;
B = Ba - center;
C = Ca - center;
D = Da - center;
module tetrahedron(S, dim, fn) {
v1 = S * A;
v2 = S * B;
v3 = S * C;
v4 = S * D;
translate(v1) sphere(d=dim, $fn=fn);
translate(v2) sphere(d=dim, $fn=fn);
translate(v3) sphere(d=dim, $fn=fn);
translate(v4) sphere(d=dim, $fn=fn);
bar(v1, v2, 0.5 * dim);
bar(v1, v3, 0.5 * dim);
bar(v1, v4, 0.5 * dim);
bar(v2, v3, 0.5 * dim);
bar(v2, v4, 0.5 * dim);
bar(v3, v4, 0.5 * dim);
}
module sierpinski_recurse(S, dim, depth, fn) {
if (depth > 0) {
tetrahedron(S, dim, fn);
translate((S / 2) * A) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1, 6);
}
translate((S / 2) * B) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1, 6);
}
translate((S / 2) * C) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1, 6);
}
translate((S / 2) * D) {
sierpinski_recurse(S / 2, 0.7 * dim, depth - 1, 6);
}
}
}
module sierpinski(S, depth) {
sierpinski_recurse(S, 0.15 * S, depth + 1, 12);
}
sierpinski(120, 4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment