chiark / gitweb /
electron-token: copy of lemon-stand, wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 18 Jun 2017 20:28:06 +0000 (21:28 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 18 Jun 2017 20:28:06 +0000 (21:28 +0100)
electron-token.scad.pl [new file with mode: 0755]

diff --git a/electron-token.scad.pl b/electron-token.scad.pl
new file mode 100755 (executable)
index 0000000..8c1d10f
--- /dev/null
@@ -0,0 +1,164 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Math::Trig;
+use Math::Vector::Real;
+use IO::File;
+use Data::Dumper;
+use constant tau => pi*2;
+
+my $ellipse = 25 / 2;
+my $circle = 7 / 2;
+my $channelh = 3;
+my $channelw = 4;
+my $xscale = 35 / 25;
+my $N = 180; # around ellipse
+my $M = 80; # around each circle
+my @channeldistprops = (0, 1/3, 2/3);
+
+my $NMdiv = $ENV{'LEMONSTAND_COARSE'} || 1;
+
+$M /= $NMdiv;
+$N /= $NMdiv;
+
+print <<END;
+// -*- C -*-
+// *** AUTOGENERATED - DO NOT EDIT ***
+END
+
+print "torusyup = ", ($circle / sqrt(2)), ";\n";
+
+our @ellipse = map {
+    my $theta = tau * $_ / $N;
+    V( cos($theta) * $ellipse * $xscale, sin($theta) * $ellipse, 0 )
+} 0..($N-1);
+
+#print Dumper(\@ellipse);
+
+our @alongs = map {
+    my $i = $_;
+    $ellipse[ ($i+1) % $N ] - $ellipse[ ($i-1) % $N];
+} 0..($N-1);
+
+our @circles = map {
+    my $i = $_;
+    my $centre = $ellipse[$i];
+    my $axis = $alongs[$i]->versor();
+    my $rad0 = $axis x V(0,0,1);
+    my $rad1 = $rad0 x $axis;
+    [ map {
+       my $theta = tau * $_ / $M;
+       $centre + $circle * ($rad0 * cos($theta) + $rad1 * sin($theta));
+    } 0..($M-1) ];
+} 0..($N-1);
+
+sub scadvec ($) {
+    my ($v) = @_;
+    return "[ ".(join ", ", @$v)." ]"
+}
+
+sub torusy () {
+    print "module Torusy(){ polyhedron(points=[";
+    my $ptix = 0;
+    my @cirpt;
+    foreach my $i (0..$N-1) {
+       foreach my $j (0..$M-1) {
+           print "," if $ptix;
+           print "\n";
+           print "    ",(scadvec $circles[$i][$j]);
+           $cirpt[$i][$j] = $ptix++;
+       }
+    }
+    print "\n  ],\n";
+
+    print "  faces=[";
+    foreach my $i (0..$N-1) {
+       my $i2 = ($i+1) % $N;
+       foreach my $j (0..$M-1) {
+           my $j2 = ($j+1) % $M;
+           print "," if $i || $j;
+           print "\n";
+           print "   [ ", (join ", ",
+                           $cirpt[ $i  ][ $j  ],
+                           $cirpt[ $i  ][ $j2 ],
+                           $cirpt[ $i2 ][ $j  ],
+                          ), " ],";
+           print "   [ ", (join ", ",
+                           $cirpt[ $i  ][ $j2 ],
+                           $cirpt[ $i2 ][ $j2 ],
+                           $cirpt[ $i2 ][ $j  ],
+                          ), " ]";
+       }
+    }
+    print "\n  ]);\n}\n";
+}
+
+torusy();
+
+
+our @distances;
+push @distances, 0;
+foreach my $i (1..$N) {
+    my $dist = $distances[ $i-1 ];
+    $dist += abs($ellipse[$i % $N] - $ellipse[$i-1]);
+    $distances[$i] = $dist;
+}
+
+sub infodistprop ($) {
+    my ($distprop) = @_;
+    # returns
+    #   ( $ellipse_centreline_point,
+    #     $along_vector )
+    my $dist = $distprop * $distances[$N];
+    foreach my $i (0..$N-1) {
+       my $prorata =
+           ($dist - $distances[$i]) /
+           ($distances[$i+1] - $distances[$i]);
+       next unless 0 <= $prorata && $prorata <= 1;
+       print "// infodistprop $distprop => #$i=$ellipse[$i] $prorata $ellipse[$i+1]\n";
+       return (
+               (1-$prorata) * $ellipse[$i] + ($prorata) * $ellipse[$i+1],
+               $alongs[$i],
+              );
+    }
+    die "$distprop ?";
+}
+
+sub channels(){
+    print "module Channels(){\n";
+    
+    foreach my $cdp (
+                    (map { 0.5 *  $_    } @channeldistprops),
+                    (map { 0.5 * ($_+1) } @channeldistprops),
+                   ) {
+       my ($ctr, $along) = infodistprop($cdp);
+       my $angle = atan2(-$along->[0], $along->[1]);
+       print "  translate(",scadvec($ctr),")\n";
+       print "  rotate([0,0,$angle*360/",tau,"])\n";
+       print "  rotate([0,90,0])\n";
+       print "  translate([0,0, -2*$circle])\n";
+       print "  scale([1, $channelw/$channelh/2, 1])\n";
+       print "  rotate([0,0,360/8/2])\n";
+       print "  cylinder(r=$channelh, h=4*$circle, \$fn=8);\n";
+    }
+    print "}\n";
+}
+
+channels();
+
+while (<DATA>) { print };
+
+STDOUT->error and die $!;
+STDOUT->flush or die $!;
+
+__DATA__
+module Stand(){
+    difference(){
+       translate([0,0,torusyup])
+           Torusy();
+       Channels();
+       translate([-200,-200,-50])
+           cube([400,400,50]);
+    }
+}
+Stand();