-__DATA__
+#!/usr/bin/perl -w
+
+use strict;
+
+our $shape = <<'END';
xyyZZYYXYxxyzYYZXzzxyXXYXXXZxxxyyXXZyyyzXXzz
zxxYYXXZXzzxyXXYZyyzxZZXZZZYzzzxxZZYxxxyZZyy
yzzXXZZYZyyzxZZXYxxyzYYZYYYXyyyzzYYXzzzxYYxx
+END
+
+sub o { print @_ or die $!; }
+
+o <<'END';
+// -*- autogenerated, do not edit -*-
+
+module Trace() {
+END
+
+my @p = qw(0 0 0);
+
+$"=',';
+
+while ($shape =~ s/^\s*(\w)//) {
+ my $ix = index('xyz', (lc $1));
+ my $sign = $1 =~ /[A-Z]/ ? +1 : -1;
+ my @q = @p;
+ $q[$ix] += $sign;
+ o " TraceEdge([@p],[@q]);\n";
+ @p = @q;
+}
+
+die @p unless "@p" eq '0,0,0';
+
+o "}\n\n";
+
+while (<DATA>) { o $_ }
+
+__DATA__
+
+thick = 7;
+edgeu = 10;
+
+// calculated
+
+octa_long = thick;
+octa_short = octa_long / (1 + sqrt(2));
+
+module OctaThing() {
+ hull(){
+ for (r = [[0,0,0], [90,0,0], [0,90,0]]) {
+ rotate(r)
+ cube([ octa_short,octa_short, octa_long ], center=true);
+ }
+ }
+}
+
+module TraceEdge(p,q) {
+ hull(){
+ for (x=[p,q]) {
+ translate(x * edgeu)
+ OctaThing();
+ }
+ }
+}
+
+Trace();
+
+