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