From 0b7257ca44cddaf016c96b1998fe34b99d1701b6 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 7 Jan 2018 21:44:52 +0000 Subject: [PATCH] distort-stl: new approach --- distort-stl | 122 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 103 insertions(+), 19 deletions(-) diff --git a/distort-stl b/distort-stl index 4820e03..eb3a7a1 100755 --- a/distort-stl +++ b/distort-stl @@ -18,27 +18,87 @@ # polar-rectangular coords: # Z' = Z; R' = Y + RADIUS; theta' = X / RADIUS # and then converts back into cartesian +# honours fa but not fs or fn +# +# set-fa $FA use strict; use autodie; use File::Temp; +use List::Util; + +our $fa = 10; + +our @triangles; sub shift_arg () { die unless @ARGV; scalar shift @ARGV; } -sub pointmap_project_cylinder { - my ($x,$y,$z) = @_; - my $radius = shift_arg; - my $r = $radius - $y; - my $theta = $x / $radius; - return ($r * sin($theta), - -$r * cos($theta), - $z); +sub subdivide_triangle ($$) { + my ($it, $fn) = @_; + my @mids; + foreach my $ix (0..2) { + my $jx = ($ix+1) % 3; + my @midp; + foreach my $ci (0..2) { + push @midp, 0.5 * ($it->[$ix][$ci] + $it->[$jx][$ci]); + } + push @mids, @midp; + } + foreach my $ix (0..2) { + my $kx = ($ix+2) % 3; + $fn->([ $it->[$ix], $mids[$ix], $it->[$kx] ]); + } + $fn->(\@mids); +} + +#---------- project-cylinder ---------- + +our $project_cylinder_radius; +our $project_cylinder_max_d_theta; + +sub project_cylinder_tri { + my ($it) = @_; + + my $radius = project_cylinder_radius; + + my @thetas = map { $_->[0] / $radius } @$it; + + foreach my $ix (0..2) { + if (abs($thetas[$ix] - $thetas[($ix+1)%3]) + > $project_cylinder_max_d_theta) { + subdivide_triangle $it, \&project_cylinder_tri; + return; + } + } + + my @ot; + foreach my $p (@it) { + my ($x,$y,$z) = @$p; + my $r = $radius - $y; + my $theta = $x / $radius; + push @ot, [ $r * sin($theta), + -$r * cos($theta), + $z ]; + } + push @triangles, \@ot; +} + +sub op__project_cylinder () { + $project_cylinder_radius = shift_arg; + $project_cylinder_max_d_theta = $fa * TAU/360; + + my @input = (@triangles); + @triangles = (); + + project_cylinder_tri $_ foreach @input; } +#---------- main program ---------- + if (@ARGV && $ARGV[0] =~ m/^-/) { die "no options supported\n"; } @@ -52,28 +112,52 @@ my $admesh_stdout = '--write-ascii-stl /dev/fd/3 3>&1 >/dev/null'; open I, "admesh $admesh_stdout $itmp |"; -our @saved_argv = @ARGV; +my $triangle; while () { - @ARGV = @saved_argv; - if (s/^\s+vertex\s+//) { + if (m/^\s+outer\s+loop/) { + die if $triangle; + $triangle = []; + } elsif (s/^\s+vertex\s+//) { my $lhs = $&; s/\s+$//; my @xyz = split /\s+/, $_; - while (@ARGV) { - my $op = shift_arg; - $op =~ y/-/_/; - @xyz = &{ ${*::}{"pointmap_$op"} }( @xyz ); - } - @xyz = map { sprintf "%.18g", $_ } @xyz; - $_ = "$lhs@xyz\n"; + die unless $triangle; + push @$triangle, \@xya; + } elsif (m/^\s+endloop/) { + die unless @$triangle == 3; + push @triangles, $triangle; + } elsif (m/^\s+(?:solid|facet\s+normal|endfacet|endsolid)\s/) { + } else { + die "$_ ?"; } - print $otmp $_; } close I; if 0; # suppresses Name "main::I" used only once +while (@ARGV) { + my $op = shift_arg; + $op =~ y/-/_/; + &{ ${*::}{"op__$op"} }; +} + +select $otmp; + +print "solid distort-stl\n"; + +foreach my $t (@triangles) { + print " facet normal 0 0 0\n"; + print " outer loop\n"; + print " vertex"; + printf " %.18g", $_ foreach @$t; + print "\n"; + print " endloop\n"; + print " endfacet\n"; +} + +print "endsolid distort-stl\n"; + flush $otmp; system "admesh --normal-values $admesh_stdout $otmp"; -- 2.30.2