mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	New AMF-to-STL and STL-to-AMF converters
This commit is contained in:
		
							parent
							
								
									79ebb13bdb
								
							
						
					
					
						commit
						776d985b26
					
				
					 6 changed files with 170 additions and 4 deletions
				
			
		
							
								
								
									
										2
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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) = @_; | ||||
|  |  | |||
|  | @ -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
									
								
							
							
						
						
									
										50
									
								
								utils/amf-to-stl.pl
									
										
									
									
									
										Executable 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
									
								
							
							
						
						
									
										48
									
								
								utils/stl-to-amf.pl
									
										
									
									
									
										Executable 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__ | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci