chiark / gitweb /
poster-tube-lid-parametric: bugfixes
[reprap-play.git] / poster-tube-lid-parametric.pl
1 #!/usr/bin/perl -w
2 use strict;
3
4 use Math::Vector::Real;
5 use Math::Trig qw(pi);
6 use POSIX;
7 use Data::Dumper;
8
9 sub TAU () { pi*2; }
10
11 my $thick = 4;
12
13 my $small_dia = 20;
14 my $large_dia = 30;
15 my $slope_angle = 45 * TAU/360;
16 my $jcurverad = 5;
17 my $tall = 50;
18
19 my $lin_len = 10;
20 my $lin2_len = 9;
21 my $sine_len = 8;
22 my $sine_height = 6;
23
24 my $ballend_xr = $thick/2;
25
26 my @i_sections = qw(ball0  -6
27                     sine0  -10
28                     -
29                     lin0    2
30                     circle 20
31                     lin1    2
32                     sine1  10
33                     -
34                     lin2   -2
35                     ball2   6
36                     -
37                     );
38
39 my @j_sections = qw(lin0    2
40                     -
41                     curve1 10
42                     -
43                     curveE 20
44                     -
45                     curve2 -10
46                     -
47                     );
48
49 sub point ($$$$) {
50     my ($ip,$it, $jp,$jt) = @_;
51
52     my ($i_offset, $i_outward);
53
54     $i_outward = V( 0,
55                     ($ip =~ m/0$/ ? -1 : +1),
56                     0 );
57
58     my $i_thickscale = 1.0;
59
60     if ($ip =~ m/^lin[01]$/) {
61         $i_offset = V( -$lin_len * $it,
62                        0,
63                        0 );
64     } elsif ($ip =~ m/^circle$/) {
65         $i_offset = V( 0,0,0 );
66         $i_outward = V(  sin($it * TAU/2),
67                          -cos($it * TAU/2),
68                          0 );
69     } elsif ($ip =~ m/^lin2$/) {
70         $i_offset = V( -$lin_len -$sine_len - $it*$lin2_len,
71                        0,
72                        +$sine_height );
73     } elsif ($ip =~ m/^sine[01]$/) {
74         $i_offset = V( -$lin_len -$it*$sine_len,
75                        0,
76                        $sine_height * ( 0.5 - 0.5*cos( $it*TAU/2 ) )
77                      );
78     } elsif ($ip =~ m/^ball[02]$/) {
79         my $angle = $it * TAU/4;
80         $i_offset = V( -$lin_len -$sine_len
81                        -($ip =~ m/2/ ? $lin2_len : 0)
82                        -sin($angle) * $ballend_xr,
83                        0,
84                        +$sine_height
85                      );
86     } else {
87         die "$ip ?";
88     }
89
90     my $j_plus_th = $jp =~ m/2$/ ? $thick : 0;
91
92     my $i_thick = $thick * $i_thickscale;
93     my $j_p_x = $small_dia/2 + $thick;
94     my $j_rs_x = $large_dia/2 + $thick;
95     my $j_dqr_x = (1-cos($slope_angle)) * $jcurverad;
96     my $j_q_x = $j_rs_x - $j_dqr_x;
97     my $j_dpq = ($j_q_x - $j_p_x) / asin($slope_angle);
98     #print STDERR "($j_q_x - $j_p_x) / asin($slope_angle); => $j_dpq\n";
99     my $j_p_y = 0;
100     my $j_q_y = $j_p_y + $j_dpq * cos($slope_angle);
101     my $j_r_y = $j_q_y + sin($slope_angle) * $jcurverad;
102     my $j_s_y = $tall;
103     my $j_qrc_x = $j_rs_x - $jcurverad;
104     my $j_qrc_y = $j_r_y;
105
106     my $j_x;
107     my $j_y;
108
109     if ($jp =~ m/^curveE$/) {
110         my $angle = ($jt + 1) * TAU/2 - $slope_angle;
111         $j_x = $j_p_x + $i_thick/2 * cos($angle);
112         $j_y = $j_p_y + $i_thick/2 * sin($angle);
113     } elsif ($jp =~ m/^curve[12]$/) {
114         my $angle = $slope_angle * $jt;
115         my $outwards = $jp =~ m/1/ ? -1 : +1;
116         $j_x = $j_qrc_x + cos($angle) * ($jcurverad + $outwards * $i_thick/2);
117         $j_y = $j_qrc_y - sin($angle) * ($jcurverad + $outwards * $i_thick/2);
118     } elsif ($jp =~ m/^lin0$/) {
119         $j_x = $j_rs_x + $i_thick * (+0.5 - $jt);
120         $j_y = $j_s_y;
121     } else {
122         die "$jp ?";
123     }
124
125 #    print STDERR "@_ $j_x $j_y $i_offset $i_outward\n";
126     return
127         $i_offset +
128         $j_x * $i_outward +
129         V(0,0,1) * $j_y;
130 }
131
132 sub get_sections_ptvals {
133     my $last_ptval;
134     my @out;
135     while (my $name = shift @_) {
136         if ($name eq '-') {
137             push @out, $last_ptval;
138         } else {
139             my $count = shift @_;
140             my $neg = sub { $_[0] };
141             if ($count < 0) {
142                 $count = -$count;
143                 $neg = sub { 1- $_[0] };
144             }
145             foreach (my $ix = 0; $ix < $count; $ix++) {
146                 push @out, [ $name, $neg->($ix/$count) ];
147             }
148             $last_ptval = [ $name, $neg->(1.0) ];
149         }
150     }
151     return @out;
152 }
153
154 our @points;
155 our %point_indices;
156 our @triangles;
157
158 sub triangle {
159     my @pixs;
160     foreach my $pval (@_) {
161         my $pix = $point_indices{$pval}
162             //= ((push @points, $pval), $#points);
163         return if grep { $pix eq $_ } @pixs;
164         push @pixs, $pix;
165     }
166     push @triangles, \@pixs;
167 }
168
169 sub make_sheet () {
170     my @ipts = get_sections_ptvals(@i_sections);
171     my @jpts = get_sections_ptvals(@j_sections);
172     my @sheet;
173     foreach my $ipt (@ipts) {
174         my @row = ();
175         foreach my $jpt (@jpts) {
176             push @row, &point(@$ipt, @$jpt);
177         }
178         push @sheet, \@row;
179     }
180     foreach (my $qi=0; $qi<$#ipts; $qi++) { # i direction does not wrap
181         my $qi2 = $qi+1;
182         foreach (my $qj=0; $qj<@jpts; $qj++) { # j direction does wrap
183             my $qj2 = ($qj+1) % @jpts;
184             my $p0 = $sheet[$qi][$qj];
185             triangle($p0, $sheet[$qi2][$qj], $sheet[$qi2][$qj2]);
186             triangle($p0, $sheet[$qi2][$qj2], $sheet[$qi][$qj2]);
187         }
188     }
189 }
190
191 sub pv ($) {
192     my $v = shift @_;
193     return "[".(join ',', @$v)."]";
194 }
195
196 sub write_out () {
197     print "polyhedron(points=[\n" or die $!;
198     print pv($_),",\n" or die $! foreach @points;
199     print "],faces=[\n" or die $!;
200     print pv($_),",\n" or die $! foreach @triangles;
201     print "],convexity=10);\n" or die $!;
202 }
203
204 make_sheet();
205 write_out();