X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=distort-stl;h=8167e3540932a14f62954b1790e229528ba624ec;hb=f5e5bb227ce24bc8faa92c700583f7a06bc894d0;hp=39e5a150512c339c38a7a635194194a95b886bce;hpb=c5514926e454f2f2b56d7cf95c09b31b4580d2b1;p=reprap-play.git diff --git a/distort-stl b/distort-stl index 39e5a15..8167e35 100755 --- a/distort-stl +++ b/distort-stl @@ -32,6 +32,14 @@ use Data::Dumper; sub TAU () { M_PI * 2; } +our $debug = $ENV{DISTORT_DEBUG}; + +my $ps = $ENV{DISTORT_PS}; +if ($ps) { + open PS, "> $ps" or die $!; + print PS "%!\n"; +} + our $fa = 10; our $triangles; @@ -44,27 +52,102 @@ sub shift_arg () { #no warnings qw(recursion); -sub subdivide_triangle ($$) { - my ($t, $fn) = @_; +sub sprintf_triangle ($) { + my ($t) = @_; + + return '' unless $debug; + + if ($ps && $t->[3] =~ m/$ENV{DISTORT_PS_RE}/) { + printf PS <<'END', + %20.16g %20.16g %20.16g moveto + %20.16g %20.16g %20.16g lineto + %20.16g %20.16g %20.16g lineto + closepath stroke +END + $t->[0][0], $t->[0][1], $t->[0][2], + $t->[1][0], $t->[1][1], $t->[1][2], + $t->[2][0], $t->[2][1], $t->[2][2], + or die $!; + flush PS or die $!; + } + + sprintf + "%11.6f,%11.6f,%11.6f / ". + "%11.6f,%11.6f,%11.6f / ". + "%11.6f,%11.6f,%11.6f %-40s ", + $t->[0][0], $t->[0][1], $t->[0][2], + $t->[1][0], $t->[1][1], $t->[1][2], + $t->[2][0], $t->[2][1], $t->[2][2], + $t->[3]; +} + +sub maybe_subdivide_triangle ($$$$) { + my ($t, $ok, $changed, $edge_need_subdivide_fn) = @_; - #print STDERR 'SUBDIV', Dumper($t, $fn); + print STDERR sprintf_triangle $t if $debug; + + my (@longest) = qw(-1); - my @mids; foreach my $ix (0..2) { my $jx = ($ix+1) % 3; - my @midp; + next unless $edge_need_subdivide_fn->($t->[$ix], $t->[$jx]); + my $l2 = 0; foreach my $ci (0..2) { - push @midp, 0.5 * ($t->[$ix][$ci] + $t->[$jx][$ci]); + my $d = $t->[$ix][$ci] - $t->[$jx][$ci]; + $l2 += $d*$d; } - push @mids, \@midp; + next unless $l2 > $longest[0]; + @longest = ($l2, $ix, $jx); } - foreach my $ix (0..2) { - #print STDERR 'SUBDIV IX ', $ix, "\n"; - my $kx = ($ix+2) % 3; - $fn->([ $t->[$ix], $mids[$ix], $mids[$kx] ]); + if ($longest[0] < 0) { + push @$ok, $t; + printf STDERR "OK nok=%d nchanged=%d\n", + (scalar @$ok), (scalar @$changed) + if $debug; + return; } - #print STDERR 'SUBDIV MID\n'; - $fn->(\@mids); + my ($dummy,$ix,$jx) = @longest; + my $kx = ($ix+2) % 3; + + printf STDERR + " S i=%d j=%d k=%d ", + $ix, $jx, $kx + if $debug; + my @midp; + foreach my $ci (0..2) { + push @midp, 0.5 * ($t->[$ix][$ci] + $t->[$jx][$ci]); + } + + printf STDERR + " midp %11.6f,%11.6f,%11.6f\n", + @midp + if $debug; + + # triangle i-j-k, splitting edge i-m + # gives i-m-k, k-m-j + my $gensplit = sub { + my ($ixjx, $xwhat) = @_; + my $n = [ @$t ]; + $n->[$ixjx] = \@midp; + $n->[3] = "$t->[3]$xwhat"; + printf STDERR "%s\n", sprintf_triangle $n if $debug; + unshift @$changed, $n; + }; + $gensplit->($ix, "a$ix$jx"); + $gensplit->($jx, "b$ix$jx"); + return; +} + +sub maybe_subdivide ($) { + my ($edge_need_subdivide_fn) = @_; + + my @small_enough = (); + while (my $t = shift @$triangles) { + maybe_subdivide_triangle $t, \@small_enough, $triangles, + $edge_need_subdivide_fn; + } + + $triangles = \@small_enough; } sub append_triangle ($) { @@ -72,23 +155,20 @@ sub append_triangle ($) { push @$output, $t; } +#---------- set-fa ---------- + +sub op__set_fa () { + $fa = shift_arg; +} + #---------- project-cylinder ---------- our $project_cylinder_radius; our $project_cylinder_max_d_theta; -sub project_cylinder_need_subdivide () { - foreach my $t (@$triangles) { - my @thetas = map { $_->[0] / $project_cylinder_radius } @$t; - - foreach my $ix (0..2) { - if (abs($thetas[$ix] - $thetas[($ix+1)%3]) - > $project_cylinder_max_d_theta) { - return 1; - } - } - } - return 0; +sub project_cylinder_edge_need_subdivide ($$) { + my @thetas = map { $_->[0] / $project_cylinder_radius } @_; + return abs($thetas[0] - $thetas[1]) > $project_cylinder_max_d_theta; } sub project_cylinder_tri { @@ -114,14 +194,8 @@ sub op__project_cylinder () { $project_cylinder_radius = shift_arg; $project_cylinder_max_d_theta = $fa * TAU/360; - while (project_cylinder_need_subdivide()) { - $output = []; - foreach my $t (@$triangles) { - subdivide_triangle $t, \&append_triangle; - } - $triangles = $output; - } - + maybe_subdivide \&project_cylinder_edge_need_subdivide; + $output = []; foreach my $t (@$triangles) { project_cylinder_tri $t; @@ -175,6 +249,7 @@ while () { push @$triangle, \@xyz; } elsif (m/^endloop/) { die unless @$triangle == 3; + push @$triangle, $.; push @$triangles, $triangle; undef $triangle; } elsif (m/^(?:solid|facet\s+normal|endfacet|endsolid)\s/) {