#!/usr/bin/perl -w
#
# usage:
# ./distort-stl OUTPUT DISTORTION [PARAMS...] ...
#
# DISTORTIONs:
#
# project-cylinder RADIUS
# projects the X-Z plane onto the cylinder of
# radius RADIUS with axis [0, 0, t]
# origin becomes [0, -RADIUS, 0]
# other planes of the input are projected onto smaller
# or larger cylinders accordingly
# probably a bad idea if
# object has any Y > RADIUS
# object has any |X| > tau / RADIUS
# technically, treats input as if it were
# polar-rectangular coords:
# Z' = Z; R' = Y + RADIUS; theta' = X / RADIUS
# and then converts back into cartesian
use strict;
use autodie;
use File::Temp;
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);
}
if (@ARGV && $ARGV[0] =~ m/^-/) {
die "no options supported\n";
}
my $itmp = new File::Temp;
my $otmp = new File::Temp;
system "cat >$itmp";
my $admesh_stdout = '--write-ascii-stl /dev/fd/3 3>&1 >/dev/null';
open I, "admesh $admesh_stdout $itmp |";
our @saved_argv = @ARGV;
while () {
@ARGV = @saved_argv;
if (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";
}
print $otmp $_;
}
close I;
if 0; # suppresses Name "main::I" used only once
flush $otmp;
system "admesh --normal-values $admesh_stdout $otmp";