chiark / gitweb /
ksafe-base: adjustment from first tests
[reprap-play.git] / lemon-stand.scad.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Math::Trig;
5 use Math::Vector::Real;
6 use IO::File;
7 use Data::Dumper;
8 use constant tau => pi*2;
9
10 my $ellipse = 25 / 2;
11 my $circle = 7 / 2;
12 my $channelh = 3;
13 my $channelw = 4;
14 my $xscale = 35 / 25;
15 my $N = 180; # around ellipse
16 my $M = 80; # around each circle
17 my @channeldistprops = (0, 1/3, 2/3);
18
19 my $NMdiv = $ENV{'LEMONSTAND_COARSE'} || 1;
20
21 $M /= $NMdiv;
22 $N /= $NMdiv;
23
24 print <<END;
25 // -*- C -*-
26 // *** AUTOGENERATED - DO NOT EDIT ***
27 END
28
29 print "torusyup = ", ($circle / sqrt(2)), ";\n";
30
31 our @ellipse = map {
32     my $theta = tau * $_ / $N;
33     V( cos($theta) * $ellipse * $xscale, sin($theta) * $ellipse, 0 )
34 } 0..($N-1);
35
36 #print Dumper(\@ellipse);
37
38 our @alongs = map {
39     my $i = $_;
40     $ellipse[ ($i+1) % $N ] - $ellipse[ ($i-1) % $N];
41 } 0..($N-1);
42
43 our @circles = map {
44     my $i = $_;
45     my $centre = $ellipse[$i];
46     my $axis = $alongs[$i]->versor();
47     my $rad0 = $axis x V(0,0,1);
48     my $rad1 = $rad0 x $axis;
49     [ map {
50         my $theta = tau * $_ / $M;
51         $centre + $circle * ($rad0 * cos($theta) + $rad1 * sin($theta));
52     } 0..($M-1) ];
53 } 0..($N-1);
54
55 sub scadvec ($) {
56     my ($v) = @_;
57     return "[ ".(join ", ", @$v)." ]"
58 }
59
60 sub torusy () {
61     print "module Torusy(){ polyhedron(points=[";
62     my $ptix = 0;
63     my @cirpt;
64     foreach my $i (0..$N-1) {
65         foreach my $j (0..$M-1) {
66             print "," if $ptix;
67             print "\n";
68             print "    ",(scadvec $circles[$i][$j]);
69             $cirpt[$i][$j] = $ptix++;
70         }
71     }
72     print "\n  ],\n";
73
74     print "  faces=[";
75     foreach my $i (0..$N-1) {
76         my $i2 = ($i+1) % $N;
77         foreach my $j (0..$M-1) {
78             my $j2 = ($j+1) % $M;
79             print "," if $i || $j;
80             print "\n";
81             print "   [ ", (join ", ",
82                             $cirpt[ $i  ][ $j  ],
83                             $cirpt[ $i  ][ $j2 ],
84                             $cirpt[ $i2 ][ $j  ],
85                            ), " ],";
86             print "   [ ", (join ", ",
87                             $cirpt[ $i  ][ $j2 ],
88                             $cirpt[ $i2 ][ $j2 ],
89                             $cirpt[ $i2 ][ $j  ],
90                            ), " ]";
91         }
92     }
93     print "\n  ]);\n}\n";
94 }
95
96 torusy();
97
98
99 our @distances;
100 push @distances, 0;
101 foreach my $i (1..$N) {
102     my $dist = $distances[ $i-1 ];
103     $dist += abs($ellipse[$i % $N] - $ellipse[$i-1]);
104     $distances[$i] = $dist;
105 }
106
107 sub infodistprop ($) {
108     my ($distprop) = @_;
109     # returns
110     #   ( $ellipse_centreline_point,
111     #     $along_vector )
112     my $dist = $distprop * $distances[$N];
113     foreach my $i (0..$N-1) {
114         my $prorata =
115             ($dist - $distances[$i]) /
116             ($distances[$i+1] - $distances[$i]);
117         next unless 0 <= $prorata && $prorata <= 1;
118         print "// infodistprop $distprop => #$i=$ellipse[$i] $prorata $ellipse[$i+1]\n";
119         return (
120                 (1-$prorata) * $ellipse[$i] + ($prorata) * $ellipse[$i+1],
121                 $alongs[$i],
122                );
123     }
124     die "$distprop ?";
125 }
126
127 sub channels(){
128     print "module Channels(){\n";
129     
130     foreach my $cdp (
131                      (map { 0.5 *  $_    } @channeldistprops),
132                      (map { 0.5 * ($_+1) } @channeldistprops),
133                     ) {
134         my ($ctr, $along) = infodistprop($cdp);
135         my $angle = atan2(-$along->[0], $along->[1]);
136         print "  translate(",scadvec($ctr),")\n";
137         print "  rotate([0,0,$angle*360/",tau,"])\n";
138         print "  rotate([0,90,0])\n";
139         print "  translate([0,0, -2*$circle])\n";
140         print "  scale([1, $channelw/$channelh/2, 1])\n";
141         print "  rotate([0,0,360/8/2])\n";
142         print "  cylinder(r=$channelh, h=4*$circle, \$fn=8);\n";
143     }
144     print "}\n";
145 }
146
147 channels();
148
149 while (<DATA>) { print };
150
151 STDOUT->error and die $!;
152 STDOUT->flush or die $!;
153
154 __DATA__
155 module Stand(){
156     difference(){
157         translate([0,0,torusyup])
158             Torusy();
159         Channels();
160         translate([-200,-200,-50])
161             cube([400,400,50]);
162     }
163 }
164 Stand();