Parse AMF

This commit is contained in:
Alessandro Ranellucci 2012-02-19 15:14:54 +01:00
parent dba6197935
commit 79ebb13bdb
8 changed files with 105 additions and 11 deletions

View file

@ -32,6 +32,8 @@ lib/Slic3r/Polygon.pm
lib/Slic3r/Polyline.pm
lib/Slic3r/Print.pm
lib/Slic3r/Skein.pm
lib/Slic3r/AMF.pm
lib/Slic3r/AMF/Parser.pm
lib/Slic3r/STL.pm
lib/Slic3r/Surface.pm
lib/Slic3r/SVG.pm

View file

@ -23,7 +23,7 @@ Slic3r current key features are:
* multi-platform (Linux/Mac/Win) and packaged as standalone-app with no dependencies required;
* easy configuration/calibration;
* read binary and ASCII STL files;
* read binary and ASCII STL files as well as AMF;
* powerful command line interface;
* easy GUI;
* multithreaded;

View file

@ -31,6 +31,7 @@ use Slic3r::Polygon;
use Slic3r::Polyline;
use Slic3r::Print;
use Slic3r::Skein;
use Slic3r::AMF;
use Slic3r::STL;
use Slic3r::Surface;
use Slic3r::TriangleMesh;

28
lib/Slic3r/AMF.pm Normal file
View file

@ -0,0 +1,28 @@
package Slic3r::AMF;
use Moo;
use XXX;
sub read_file {
my $self = shift;
my ($file) = @_;
eval "require Slic3r::AMF::Parser; 1"
or die "AMF parsing requires XML::SAX::ExpatXS\n";
open my $fh, '<', $file or die "Failed to open $file\n";
my $vertices = [];
my $facets = [];
XML::SAX::ExpatXS
->new(Handler => Slic3r::AMF::Parser->new(
_vertices => $vertices,
_facets => $facets,
))
->parse_file($fh);
close $fh;
return Slic3r::TriangleMesh->new(vertices => $vertices, facets => $facets);
}
1;

64
lib/Slic3r/AMF/Parser.pm Normal file
View file

@ -0,0 +1,64 @@
package Slic3r::AMF::Parser;
use strict;
use warnings;
use XML::SAX::ExpatXS;
use base 'XML::SAX::Base';
my %xyz_index = (x => 0, y => 1, z => 2); #=
sub new {
my $self = shift->SUPER::new(@_);
$self->{_tree} = [];
$self;
}
sub start_element {
my $self = shift;
my $data = shift;
if ($data->{LocalName} eq 'vertex') {
$self->{_vertex} = ["", "", ""];
} elsif ($self->{_vertex} && $data->{LocalName} =~ /^[xyz]$/ && $self->{_tree}[-1] eq 'coordinates') {
$self->{_coordinate} = $data->{LocalName};
} elsif ($data->{LocalName} eq 'triangle') {
$self->{_triangle} = [[], "", "", ""]; # empty normal
} elsif ($self->{_triangle} && $data->{LocalName} =~ /^v([123])$/ && $self->{_tree}[-1] eq 'triangle') {
$self->{_vertex_idx} = $1;
}
push @{$self->{_tree}}, $data->{LocalName};
}
sub characters {
my $self = shift;
my $data = shift;
if ($self->{_vertex} && $self->{_coordinate}) {
$self->{_vertex}[ $xyz_index{$self->{_coordinate}} ] .= $data->{Data};
} elsif ($self->{_triangle} && defined $self->{_vertex_idx}) {
$self->{_triangle}[ $self->{_vertex_idx} ] .= $data->{Data};
}
}
sub end_element {
my $self = shift;
my $data = shift;
pop @{$self->{_tree}};
if ($data->{LocalName} eq 'vertex') {
push @{$self->{_vertices}}, $self->{_vertex};
$self->{_vertex} = undef;
} elsif ($self->{_coordinate} && $data->{LocalName} =~ /^[xyz]$/) {
$self->{_coordinate} = undef;
} elsif ($data->{LocalName} eq 'triangle') {
push @{$self->{_facets}}, $self->{_triangle};
$self->{_triangle} = undef;
} elsif ($self->{_vertex_idx} && $data->{LocalName} =~ /^v[123]$/) {
$self->{_vertex_idx} = undef;
}
}
1;

View file

@ -146,7 +146,7 @@ sub new {
return $self;
}
my $stl_wildcard = "STL files *.stl|*.stl;*.STL";
my $model_wildcard = "STL files (*.stl)|*.stl;*.STL|AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML";
my $ini_wildcard = "INI files *.ini|*.ini;*.INI";
my $gcode_wildcard = "GCODE files *.gcode|*.gcode;*.GCODE";
@ -169,7 +169,7 @@ sub do_slice {
# select input file
my $dir = $last_skein_dir || $last_config_dir || "";
my $dialog = Wx::FileDialog->new($self, 'Choose a STL file to slice:', $dir, "", $stl_wildcard, wxFD_OPEN);
my $dialog = Wx::FileDialog->new($self, 'Choose a STL or AMF file to slice:', $dir, "", $model_wildcard, wxFD_OPEN);
return unless $dialog->ShowModal == wxID_OK;
my ($input_file) = $dialog->GetPaths;
my $input_file_basename = basename($input_file);

View file

@ -1,8 +1,7 @@
package Slic3r::STL;
use Moo;
use Math::Clipper qw(integerize_coordinate_sets is_counter_clockwise);
use Slic3r::Geometry qw(X Y Z three_points_aligned longest_segment);
use Slic3r::Geometry qw(X Y Z);
use XXX;
sub read_file {

View file

@ -19,10 +19,6 @@ has 'processing_time' => (is => 'rw', required => 0);
sub go {
my $self = shift;
die "Input file must have .stl extension\n"
if $self->input_file !~ /\.stl$/i;
my $t0 = [gettimeofday];
# skein the STL into layers
@ -30,7 +26,11 @@ sub go {
$self->status_cb->(10, "Processing triangulated mesh...");
my $print;
{
my $mesh = Slic3r::STL->read_file($self->input_file);
my $mesh = $self->input_file =~ /\.stl$/i
? Slic3r::STL->read_file($self->input_file)
: $self->input_file =~ /\.amf(\.xml)?$/i
? Slic3r::AMF->read_file($self->input_file)
: die "Input file must have .stl or .amf(.xml) extension\n";
$mesh->check_manifoldness;
$print = Slic3r::Print->new_from_mesh($mesh);
}
@ -152,7 +152,7 @@ sub expanded_output_filepath {
my $input_basename = basename($self->input_file);
$path =~ s/\[input_filename\]/$input_basename/g;
$input_basename =~ s/\.stl$//i;
$input_basename =~ s/\.(?:stl|amf(?:\.xml)?)$//i;
$path =~ s/\[input_filename_base\]/$input_basename/g;
# build a regexp to match the available options