2015-01-03 12:17:19 +01:00
|
|
|
#!/usr/bin/perl
|
|
|
|
# Generate the mobius segments for a twisting bracelet
|
2015-01-03 20:09:49 +01:00
|
|
|
# (0,0)
|
|
|
|
# (1,0)
|
|
|
|
# (0.5,sqrt(3)/2)
|
|
|
|
# center is (0.5, sqrt(3)/3)
|
2015-01-03 12:17:19 +01:00
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2015-01-03 18:28:24 +01:00
|
|
|
my $sections = 12;
|
2015-01-04 20:59:59 +01:00
|
|
|
my $thickness = 30;
|
2015-01-03 12:17:19 +01:00
|
|
|
my $radius = [40,0,0];
|
2015-01-03 17:43:53 +01:00
|
|
|
my $pi = 2*atan2(1,0);
|
2015-01-03 12:17:19 +01:00
|
|
|
|
2015-01-03 20:09:49 +01:00
|
|
|
my $h = sqrt(3)/2;
|
|
|
|
|
2015-01-03 12:17:19 +01:00
|
|
|
my $pts = [
|
2015-01-03 20:09:49 +01:00
|
|
|
v3scale($thickness, [-0.5, -$h/3, 0]),
|
|
|
|
v3scale($thickness, [ 0.0, +$h*2/3, 0]),
|
|
|
|
v3scale($thickness, [+0.5, -$h/3, 0]),
|
2015-01-03 12:17:19 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
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) = @_;
|
|
|
|
|
2015-01-03 17:43:53 +01:00
|
|
|
my $c = [
|
2015-01-03 12:17:19 +01:00
|
|
|
$u->[1]*$v->[2] - $u->[2]*$v->[1],
|
|
|
|
$u->[2]*$v->[0] - $u->[0]*$v->[2],
|
|
|
|
$u->[0]*$v->[1] - $u->[1]*$v->[0],
|
|
|
|
];
|
2015-01-03 17:43:53 +01:00
|
|
|
|
|
|
|
my $mag = 0
|
|
|
|
+ $c->[0]*$c->[0]
|
|
|
|
+ $c->[1]*$c->[1]
|
|
|
|
+ $c->[2]*$c->[2]
|
|
|
|
;
|
|
|
|
|
|
|
|
return v3scale(1.0/sqrt($mag), $c);
|
2015-01-03 12:17:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub triangle
|
|
|
|
{
|
|
|
|
my ($p0, $p1, $p2) = @_;
|
|
|
|
my $v1 = v3sub($p1, $p0);
|
|
|
|
my $v2 = v3sub($p2, $p0);
|
2015-01-03 17:43:53 +01:00
|
|
|
my $n = v3cross($v2, $v1);
|
2015-01-03 12:17:19 +01:00
|
|
|
|
|
|
|
my $rc = sprintf <<"", $n->[0], $n->[1], $n->[2];
|
2015-01-03 17:43:53 +01:00
|
|
|
facet normal %.4f %.4f %.4f
|
2015-01-03 12:17:19 +01:00
|
|
|
outer loop
|
|
|
|
|
|
|
|
$rc .= sprintf <<"", $p0->[0], $p0->[1], $p0->[2];
|
2015-01-03 17:43:53 +01:00
|
|
|
vertex %.4f %.4f %.4f
|
2015-01-03 12:17:19 +01:00
|
|
|
|
|
|
|
$rc .= sprintf <<"", $p1->[0], $p1->[1], $p1->[2];
|
2015-01-03 17:43:53 +01:00
|
|
|
vertex %.4f %.4f %.4f
|
2015-01-03 12:17:19 +01:00
|
|
|
|
|
|
|
$rc .= sprintf <<"", $p2->[0], $p2->[1], $p2->[2];
|
2015-01-03 17:43:53 +01:00
|
|
|
vertex %.4f %.4f %.4f
|
2015-01-03 12:17:19 +01:00
|
|
|
|
|
|
|
$rc .= <<"";
|
|
|
|
endloop
|
|
|
|
endfacet
|
|
|
|
|
|
|
|
return $rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub module
|
|
|
|
{
|
|
|
|
my $n = shift;
|
|
|
|
|
|
|
|
# Generate the six points for the triangles
|
|
|
|
my $p00 = rotate($pts->[0], $n*120.0/$sections, 2);
|
|
|
|
my $p01 = rotate($pts->[1], $n*120.0/$sections, 2);
|
|
|
|
my $p02 = rotate($pts->[2], $n*120.0/$sections, 2);
|
|
|
|
|
|
|
|
my $p10 = rotate($pts->[0], ($n+1)*120.0/$sections, 2);
|
|
|
|
my $p11 = rotate($pts->[1], ($n+1)*120.0/$sections, 2);
|
|
|
|
my $p12 = rotate($pts->[2], ($n+1)*120.0/$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 ''
|
2015-01-03 17:43:53 +01:00
|
|
|
. triangle($p00, $p01, $p11)
|
|
|
|
. triangle($p01, $p02, $p12)
|
|
|
|
. triangle($p02, $p00, $p10)
|
|
|
|
. triangle($p11, $p10, $p00)
|
|
|
|
. triangle($p12, $p11, $p01)
|
|
|
|
. triangle($p10, $p12, $p02)
|
2015-01-03 12:17:19 +01:00
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
print "solid OpenSCAD_Model\n";
|
|
|
|
|
|
|
|
print module($_) for 1..$sections;
|
|
|
|
#print module(0);
|
|
|
|
#print module(2);
|
|
|
|
|
|
|
|
print "endsolid OpenSCAD_Model\n";
|