From 776d985b26fd707205cc7cc098365d628ca05b2d Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 19 Feb 2012 15:45:27 +0100 Subject: [PATCH] New AMF-to-STL and STL-to-AMF converters --- MANIFEST | 2 ++ lib/Slic3r/AMF.pm | 39 ++++++++++++++++++++++++++++++++ lib/Slic3r/Geometry.pm | 21 +++++++++++++++++- lib/Slic3r/STL.pm | 14 +++++++++--- utils/amf-to-stl.pl | 50 ++++++++++++++++++++++++++++++++++++++++++ utils/stl-to-amf.pl | 48 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 4 deletions(-) create mode 100755 utils/amf-to-stl.pl create mode 100755 utils/stl-to-amf.pl diff --git a/MANIFEST b/MANIFEST index f3534a3ca..67c40fd60 100644 --- a/MANIFEST +++ b/MANIFEST @@ -51,5 +51,7 @@ t/fill.t t/geometry.t t/polyclip.t t/stl.t +utils/amf-to-stl.pl utils/post-processing/z-every-line.pl utils/split_stl.pl +utils/stl-to-amf.pl diff --git a/lib/Slic3r/AMF.pm b/lib/Slic3r/AMF.pm index 4d7fda95e..853b28131 100644 --- a/lib/Slic3r/AMF.pm +++ b/lib/Slic3r/AMF.pm @@ -1,5 +1,7 @@ package Slic3r::AMF; use Moo; + +use Slic3r::Geometry qw(X Y Z); use XXX; sub read_file { @@ -25,4 +27,41 @@ sub read_file { return Slic3r::TriangleMesh->new(vertices => $vertices, facets => $facets); } +sub write_file { + my $self = shift; + my ($file, $mesh) = @_; + + open my $fh, '>', $file; + binmode $fh, ':utf8'; + + printf $fh qq{\n}; + printf $fh qq{\n}; + printf $fh qq{ Slic3r %s\n}, $Slic3r::VERSION; + printf $fh qq{ \n}; + printf $fh qq{ \n}; + printf $fh qq{ \n}; + foreach my $vertex (@{$mesh->vertices}) { + printf $fh qq{ \n}; + printf $fh qq{ \n}; + printf $fh qq{ %s\n}, $vertex->[X]; + printf $fh qq{ %s\n}, $vertex->[Y]; + printf $fh qq{ %s\n}, $vertex->[Z]; + printf $fh qq{ \n}; + printf $fh qq{ \n}; + } + printf $fh qq{ \n}; + printf $fh qq{ \n}; + foreach my $facet (@{$mesh->facets}) { + printf $fh qq{ \n}; + printf $fh qq{ %d\n}, $_, $facet->[$_], $_ for 1..3; + printf $fh qq{ \n}; + } + printf $fh qq{ \n}; + printf $fh qq{ \n}; + printf $fh qq{ \n}; + printf $fh qq{\n}; + + close $fh; +} + 1; diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index 4166fa49c..f919c4a91 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -19,7 +19,7 @@ our @EXPORT_OK = qw( polygon_remove_acute_vertices polygon_remove_parallel_continuous_edges shortest_path collinear scale unscale merge_collinear_lines rad2deg_dir bounding_box_center line_intersects_any - polyline_remove_short_segments + polyline_remove_short_segments normal triangle_normal ); use Slic3r::Geometry::DouglasPeucker qw(Douglas_Peucker); @@ -414,6 +414,25 @@ sub subtract_vectors { return [ $line2->[X] - $line1->[X], $line2->[Y] - $line1->[Y] ]; } +sub normal { + my ($line1, $line2) = @_; + + return [ + ($line1->[Y] * $line2->[Z]) - ($line1->[Z] * $line2->[Y]), + -($line2->[Z] * $line1->[X]) + ($line2->[X] * $line1->[Z]), + ($line1->[X] * $line2->[Y]) - ($line1->[Y] * $line2->[X]), + ]; +} + +sub triangle_normal { + my ($v1, $v2, $v3) = @_; + + my $u = [ map +($v2->[$_] - $v1->[$_]), (X,Y,Z) ]; + my $v = [ map +($v3->[$_] - $v1->[$_]), (X,Y,Z) ]; + + return normal($u, $v); +} + # 2D dot product sub dot { my ($u, $v) = @_; diff --git a/lib/Slic3r/STL.pm b/lib/Slic3r/STL.pm index 99825f172..0c7830c35 100644 --- a/lib/Slic3r/STL.pm +++ b/lib/Slic3r/STL.pm @@ -1,7 +1,7 @@ package Slic3r::STL; use Moo; -use Slic3r::Geometry qw(X Y Z); +use Slic3r::Geometry qw(X Y Z triangle_normal); use XXX; sub read_file { @@ -181,7 +181,10 @@ sub _write_binary { print $fh pack 'x80'; print $fh pack 'L', scalar(@{$mesh->facets}); foreach my $facet (@{$mesh->facets}) { - print $fh pack '(f<3)4S', @{$facet->[0]}, (map @{$mesh->vertices->[$_]}, @$facet[1,2,3]), 0; + print $fh pack '(f<3)4S', + @{_facet_normal($mesh, $facet)}, + (map @{$mesh->vertices->[$_]}, @$facet[1,2,3]), + 0; } } @@ -190,7 +193,7 @@ sub _write_ascii { printf $fh "solid\n"; foreach my $facet (@{$mesh->facets}) { - printf $fh " facet normal %f %f %f\n", @{$facet->[0]}; + printf $fh " facet normal %f %f %f\n", @{_facet_normal($mesh, $facet)}; printf $fh " outer loop\n"; printf $fh " vertex %f %f %f\n", @{$mesh->vertices->[$_]} for @$facet[1,2,3]; printf $fh " endloop\n"; @@ -199,4 +202,9 @@ sub _write_ascii { printf $fh "endsolid\n"; } +sub _facet_normal { + my ($mesh, $facet) = @_; + return triangle_normal(map $mesh->vertices->[$_], @$facet[1,2,3]); +} + 1; diff --git a/utils/amf-to-stl.pl b/utils/amf-to-stl.pl new file mode 100755 index 000000000..ce078f1ae --- /dev/null +++ b/utils/amf-to-stl.pl @@ -0,0 +1,50 @@ +#!/usr/bin/perl +# This script converts an AMF file to STL + +use strict; +use warnings; + +BEGIN { + use FindBin; + use lib "$FindBin::Bin/../lib"; +} + +use File::Basename qw(basename); +use Getopt::Long qw(:config no_auto_abbrev); +use Slic3r; +$|++; + +my %opt = (); +{ + my %options = ( + 'help' => sub { usage() }, + 'ascii' => \$opt{ascii}, + ); + GetOptions(%options) or usage(1); + $ARGV[0] or usage(1); +} + +{ + my $mesh = Slic3r::AMF->read_file($ARGV[0]); + my $output_file = $ARGV[0]; + $output_file =~ s/\.amf(?:\.xml)?$/\.stl/i; + + printf "Writing to %s\n", basename($output_file); + Slic3r::STL->write_file($output_file, $mesh, !$opt{ascii}); +} + + +sub usage { + my ($exit_code) = @_; + + print <<"EOF"; +Usage: amf-to-stl.pl [ OPTIONS ] file.amf + + --help Output this usage screen and exit + --ascii Generate ASCII STL files (default: binary) + +EOF + exit ($exit_code || 0); +} + +__END__ diff --git a/utils/stl-to-amf.pl b/utils/stl-to-amf.pl new file mode 100755 index 000000000..289417231 --- /dev/null +++ b/utils/stl-to-amf.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# This script converts a STL file to AMF + +use strict; +use warnings; + +BEGIN { + use FindBin; + use lib "$FindBin::Bin/../lib"; +} + +use File::Basename qw(basename); +use Getopt::Long qw(:config no_auto_abbrev); +use Slic3r; +$|++; + +my %opt = (); +{ + my %options = ( + 'help' => sub { usage() }, + ); + GetOptions(%options) or usage(1); + $ARGV[0] or usage(1); +} + +{ + my $mesh = Slic3r::STL->read_file($ARGV[0]); + my $output_file = $ARGV[0]; + $output_file =~ s/\.stl$/.amf.xml/i; + + printf "Writing to %s\n", basename($output_file); + Slic3r::AMF->write_file($output_file, $mesh); +} + + +sub usage { + my ($exit_code) = @_; + + print <<"EOF"; +Usage: amf-to-stl.pl [ OPTIONS ] file.stl + + --help Output this usage screen and exit + +EOF + exit ($exit_code || 0); +} + +__END__