New AMF-to-STL and STL-to-AMF converters

degen-loop-screen
Alessandro Ranellucci 2012-02-19 15:45:27 +01:00
parent 79ebb13bdb
commit 776d985b26
6 changed files with 170 additions and 4 deletions

View File

@ -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

View File

@ -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{<?xml version="1.0" encoding="UTF-8"?>\n};
printf $fh qq{<amf unit="millimeter">\n};
printf $fh qq{ <metadata type="cad">Slic3r %s</metadata>\n}, $Slic3r::VERSION;
printf $fh qq{ <object id="0">\n};
printf $fh qq{ <mesh>\n};
printf $fh qq{ <vertices>\n};
foreach my $vertex (@{$mesh->vertices}) {
printf $fh qq{ <vertex>\n};
printf $fh qq{ <coordinates>\n};
printf $fh qq{ <x>%s</x>\n}, $vertex->[X];
printf $fh qq{ <y>%s</y>\n}, $vertex->[Y];
printf $fh qq{ <z>%s</z>\n}, $vertex->[Z];
printf $fh qq{ </coordinates>\n};
printf $fh qq{ </vertex>\n};
}
printf $fh qq{ </vertices>\n};
printf $fh qq{ <volume>\n};
foreach my $facet (@{$mesh->facets}) {
printf $fh qq{ <triangle>\n};
printf $fh qq{ <v%d>%d</v%d>\n}, $_, $facet->[$_], $_ for 1..3;
printf $fh qq{ </triangle>\n};
}
printf $fh qq{ </volume>\n};
printf $fh qq{ </mesh>\n};
printf $fh qq{ </object>\n};
printf $fh qq{</amf>\n};
close $fh;
}
1;

View File

@ -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) = @_;

View File

@ -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;

50
utils/amf-to-stl.pl Executable file
View File

@ -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__

48
utils/stl-to-amf.pl Executable file
View File

@ -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__