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