#!/usr/bin/perl # Generate the mobius segments for a twisting bracelet # (0,0) # (1,0) # (0.5,sqrt(3)/2) # center is (0.5, sqrt(3)/3) use warnings; use strict; my $sections = 9; my $thickness = 150; my $twist = 120.0; my $radius = [200,0,0]; my $pi = 2*atan2(1,0); my $h = sqrt(3)/2; my $pts = [ v3scale($thickness, [-0.5, -$h/3, 0]), v3scale($thickness, [ 0.0, +$h*2/3, 0]), v3scale($thickness, [+0.5, -$h/3, 0]), ]; sub rotate2 { my $x = shift; my $y = shift; my $angle_deg = shift; my $angle = $angle_deg * $pi / 180; my $s = sin($angle); my $c = cos($angle); return ( $x*$c - $y*$s, $x*$s + $y*$c, ); } sub rotate { my $p = shift; my $angle_deg = shift; my $axis = shift; my ($x,$y,$z) = @$p; if ($axis == 2) { ($x,$y) = rotate2($x, $y, $angle_deg); } elsif ($axis == 1) { ($x,$z) = rotate2($x, $z, $angle_deg); } elsif ($axis == 0) { ($y,$z) = rotate2($y, $z, $angle_deg); } return [$x,$y,$z]; } sub v3scale { my $s = shift; my $p1 = shift; return [ $p1->[0]*$s, $p1->[1]*$s, $p1->[2]*$s, ]; } sub v3add { my $p1 = shift; my $p2 = shift; return [ $p1->[0] + $p2->[0], $p1->[1] + $p2->[1], $p1->[2] + $p2->[2], ]; } sub v3sub { my ($v0, $v1) = @_; return [ $v0->[0] - $v1->[0], $v0->[1] - $v1->[1], $v0->[2] - $v1->[2], ]; } sub v3cross { my ($u,$v) = @_; my $c = [ $u->[1]*$v->[2] - $u->[2]*$v->[1], $u->[2]*$v->[0] - $u->[0]*$v->[2], $u->[0]*$v->[1] - $u->[1]*$v->[0], ]; my $mag = 0 + $c->[0]*$c->[0] + $c->[1]*$c->[1] + $c->[2]*$c->[2] ; return v3scale(1.0/sqrt($mag), $c); } sub triangle { my ($p0, $p1, $p2) = @_; my $v1 = v3sub($p1, $p0); my $v2 = v3sub($p2, $p0); my $n = v3cross($v2, $v1); my $rc = sprintf <<"", $n->[0], $n->[1], $n->[2]; facet normal %.4f %.4f %.4f outer loop $rc .= sprintf <<"", $p0->[0], $p0->[1], $p0->[2]; vertex %.4f %.4f %.4f $rc .= sprintf <<"", $p1->[0], $p1->[1], $p1->[2]; vertex %.4f %.4f %.4f $rc .= sprintf <<"", $p2->[0], $p2->[1], $p2->[2]; vertex %.4f %.4f %.4f $rc .= <<""; endloop endfacet return $rc; } sub module { my $n = shift; # Generate the six points for the triangles my $p00 = rotate($pts->[0], $n*$twist/$sections, 2); my $p01 = rotate($pts->[1], $n*$twist/$sections, 2); my $p02 = rotate($pts->[2], $n*$twist/$sections, 2); my $p10 = rotate($pts->[0], ($n+1)*$twist/$sections, 2); my $p11 = rotate($pts->[1], ($n+1)*$twist/$sections, 2); my $p12 = rotate($pts->[2], ($n+1)*$twist/$sections, 2); # Now offset them by the radius, after flipping $p00 = v3add($radius, rotate($p00, 90, 0)); $p01 = v3add($radius, rotate($p01, 90, 0)); $p02 = v3add($radius, rotate($p02, 90, 0)); $p10 = v3add($radius, rotate($p10, 90, 0)); $p11 = v3add($radius, rotate($p11, 90, 0)); $p12 = v3add($radius, rotate($p12, 90, 0)); # rotate them to line up with the radials $p00 = rotate($p00, $n*360.0/$sections, 2); $p01 = rotate($p01, $n*360.0/$sections, 2); $p02 = rotate($p02, $n*360.0/$sections, 2); $p10 = rotate($p10, ($n+1)*360.0/$sections, 2); $p11 = rotate($p11, ($n+1)*360.0/$sections, 2); $p12 = rotate($p12, ($n+1)*360.0/$sections, 2); # And now generate the triangles return '' . triangle($p00, $p01, $p11) . triangle($p01, $p02, $p12) . triangle($p02, $p00, $p10) . triangle($p11, $p10, $p00) . triangle($p12, $p11, $p01) . triangle($p10, $p12, $p02) ; } print "solid OpenSCAD_Model\n"; print module($_) for 1..$sections; #print module(0); #print module(2); print "endsolid OpenSCAD_Model\n";