diff --git a/MANIFEST b/MANIFEST index 3adbb0937..f3534a3ca 100644 --- a/MANIFEST +++ b/MANIFEST @@ -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 diff --git a/README.markdown b/README.markdown index 646f262f8..702f91c34 100644 --- a/README.markdown +++ b/README.markdown @@ -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; diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 973537c72..5739b2498 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -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; diff --git a/lib/Slic3r/AMF.pm b/lib/Slic3r/AMF.pm new file mode 100644 index 000000000..4d7fda95e --- /dev/null +++ b/lib/Slic3r/AMF.pm @@ -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; diff --git a/lib/Slic3r/AMF/Parser.pm b/lib/Slic3r/AMF/Parser.pm new file mode 100644 index 000000000..1ad43761a --- /dev/null +++ b/lib/Slic3r/AMF/Parser.pm @@ -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; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 72e37d324..0c9ebf721 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -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); diff --git a/lib/Slic3r/STL.pm b/lib/Slic3r/STL.pm index eec4fb6c0..99825f172 100644 --- a/lib/Slic3r/STL.pm +++ b/lib/Slic3r/STL.pm @@ -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 { diff --git a/lib/Slic3r/Skein.pm b/lib/Slic3r/Skein.pm index 0afd87a86..ee5b61cba 100644 --- a/lib/Slic3r/Skein.pm +++ b/lib/Slic3r/Skein.pm @@ -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