Last active
October 25, 2022 17:30
-
-
Save Taneb/69a7a026db53f08b5895032d4de75f2d to your computer and use it in GitHub Desktop.
Duals of polyhedra in OpenSCAD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// the golden ratio | |
phi = (sqrt(5) + 1) / 2; | |
// the points of a regular dodecahedron, oriented "somehow" | |
dodecahedron_points = | |
[ [ 1 , 1 , 1 ] // 0 | |
, [ 1 , 1 , -1 ] | |
, [ 1 , -1 , 1 ] | |
, [ 1 , -1 , -1 ] | |
, [ -1 , 1 , 1 ] // 4 | |
, [ -1 , 1 , -1 ] | |
, [ -1 , -1 , 1 ] | |
, [ -1 , -1 , -1 ] | |
, [ 0 , phi , 1 / phi ] // 8 | |
, [ 0 , phi , -1 / phi ] | |
, [ 0 , -phi , 1 / phi ] | |
, [ 0 , -phi , -1 / phi ] | |
, [ 1 / phi , 0 , phi ] // 12 | |
, [ -1 / phi , 0 , phi ] | |
, [ 1 / phi , 0 , -phi ] | |
, [ -1 / phi , 0 , -phi ] | |
, [ phi , 1 / phi , 0 ] // 16 | |
, [ phi , -1 / phi , 0 ] | |
, [ -phi , 1 / phi , 0 ] | |
, [ -phi , -1 / phi , 0 ] | |
]; | |
for (i = dodecahedron_points) | |
assert(norm(i) == sqrt(3)); | |
// the faces of a dodecahedron | |
dodecahedron_faces = | |
[ [ 0 , 12 , 13 , 4 , 8 ] | |
, [ 0 , 8 , 9 , 1 , 16 ] | |
, [ 0 , 16 , 17 , 2 , 12 ] | |
, [ 10 , 6 , 13 , 12 , 2 ] | |
, [ 10 , 2 , 17 , 3 , 11 ] | |
, [ 10 , 11 , 7 , 19 , 6 ] | |
, [ 15 , 7 , 11 , 3 , 14 ] | |
, [ 15 , 14 , 1 , 9 , 5 ] | |
, [ 15 , 5 , 18 , 19 , 7 ] | |
, [ 16 , 1 , 14 , 3 , 17 ] | |
, [ 13 , 6 , 19 , 18 , 4 ] | |
, [ 4 , 18 , 5 , 9 , 8 ] | |
]; | |
// polyhedron(dodecahedron_points, dodecahedron_faces, 1); | |
function sum(list, i = 0, total = 0) = | |
len(list) == i ? total : sum(list, i+1, total + list[i]); | |
function dual_polyhedron_points(points, faces) = | |
[ for (face = faces) | |
sum([for (i = face) points[i]], total = [0,0,0])/len(face) | |
]; | |
function index_of(needle, haystack, i = 0) = i == len(haystack) ? undef : haystack[i] == needle ? i : index_of(needle, haystack, i + 1); | |
function build_dual_polygon_face(info, end, next) = end == next ? [info[0][0]] : | |
let (i = index_of(next, [ for (t = info) t[2] ])) | |
concat([info[i][0]], build_dual_polygon_face(info, end, info[i][1])); | |
// NOTE it's really important that all the faces are the right way round!!! | |
function dual_polyhedron_faces(points, faces) = | |
[ for (i = [0:len(points) - 1]) | |
let ( | |
// each elem is face index containing vertex, ccw, cw | |
info = [ | |
for (j = [0:len(faces) - 1]) | |
let (face = faces[j], k = index_of(i, face)) | |
if (k != undef) | |
[ j , face[(k + len(face) - 1) % len(face)], face[(k + 1) % len(face)] ] | |
] | |
) | |
build_dual_polygon_face(info, info[0][2], info[0][1]) | |
]; | |
echo(dual_polyhedron_faces(dodecahedron_points, dodecahedron_faces)); | |
function normalize_points(points) = [ for (point = points) point/norm(point) ]; | |
polyhedron(normalize_points(dodecahedron_points), dodecahedron_faces); | |
translate([2,0,0]) | |
polyhedron( | |
normalize_points(dual_polyhedron_points(dodecahedron_points, dodecahedron_faces)), | |
dual_polyhedron_faces(dodecahedron_points, dodecahedron_faces) | |
); | |
translate([4,0,0]) | |
polyhedron( | |
normalize_points( | |
dual_polyhedron_points( | |
dual_polyhedron_points( | |
dodecahedron_points, | |
dodecahedron_faces | |
), | |
dual_polyhedron_faces( | |
dodecahedron_points, | |
dodecahedron_faces | |
) | |
) | |
), | |
dual_polyhedron_faces( | |
dual_polyhedron_points( | |
dodecahedron_points, | |
dodecahedron_faces | |
), | |
dual_polyhedron_faces( | |
dodecahedron_points, | |
dodecahedron_faces | |
) | |
) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment