mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| #!/usr/bin/perl
 | ||
| # This script exports experimental G-code for wireframe printing
 | ||
| # (inspired by the brilliant WirePrint concept)
 | ||
| 
 | ||
| use strict;
 | ||
| use warnings;
 | ||
| 
 | ||
| BEGIN {
 | ||
|     use FindBin;
 | ||
|     use lib "$FindBin::Bin/../lib";
 | ||
|     use local::lib "$FindBin::Bin/../local-lib";
 | ||
| }
 | ||
| 
 | ||
| use Getopt::Long qw(:config no_auto_abbrev);
 | ||
| use Slic3r;
 | ||
| use Slic3r::ExtrusionPath ':roles';
 | ||
| use Slic3r::Geometry qw(scale unscale X Y PI);
 | ||
| 
 | ||
| my %opt = (
 | ||
|     step_height         => 5,
 | ||
|     nozzle_angle        => 30,
 | ||
|     nozzle_width        => 10,
 | ||
|     first_layer_height  => 0.3,
 | ||
| );
 | ||
| {
 | ||
|     my %options = (
 | ||
|         'help'                  => sub { usage() },
 | ||
|         'output|o=s'            => \$opt{output_file},
 | ||
|         'step-height|h=f'       => \$opt{step_height},
 | ||
|         'nozzle-angle|a=f'      => \$opt{nozzle_angle},
 | ||
|         'nozzle-width|w=f'      => \$opt{nozzle_width},
 | ||
|         'first-layer-height=f'  => \$opt{first_layer_height},
 | ||
|     );
 | ||
|     GetOptions(%options) or usage(1);
 | ||
|     $opt{output_file} or usage(1);
 | ||
|     $ARGV[0] or usage(1);
 | ||
| }
 | ||
| 
 | ||
| {
 | ||
|     # load model
 | ||
|     my $model = Slic3r::Model->read_from_file($ARGV[0]);
 | ||
|     $model->center_instances_around_point(Slic3r::Pointf->new(100,100));
 | ||
|     my $mesh = $model->mesh;
 | ||
|     $mesh->translate(0, 0, -$mesh->bounding_box->z_min);
 | ||
|     
 | ||
|     # get slices
 | ||
|     my @z = ();
 | ||
|     my $z_max = $mesh->bounding_box->z_max;
 | ||
|     for (my $z = $opt{first_layer_height}; $z <= $z_max; $z += $opt{step_height}) {
 | ||
|         push @z, $z;
 | ||
|     }
 | ||
|     my @slices = @{$mesh->slice(\@z)};
 | ||
|     
 | ||
|     my $flow = Slic3r::Flow->new(
 | ||
|         width           => 0.35,
 | ||
|         height          => 0.35,
 | ||
|         nozzle_diameter => 0.35,
 | ||
|         bridge          => 1,
 | ||
|     );
 | ||
|     
 | ||
|     my $config = Slic3r::Config::Print->new;
 | ||
|     $config->set('gcode_comments', 1);
 | ||
|     
 | ||
|     open my $fh, '>', $opt{output_file};
 | ||
|     my $gcodegen = Slic3r::GCode->new(
 | ||
|         enable_loop_clipping => 0,  # better bonding
 | ||
|     );
 | ||
|     $gcodegen->apply_print_config($config);
 | ||
|     $gcodegen->set_extruders([0]);
 | ||
|     print $fh $gcodegen->set_extruder(0);
 | ||
|     print $fh $gcodegen->writer->preamble;
 | ||
|     
 | ||
|     my $e = $gcodegen->writer->extruder->e_per_mm3 * $flow->mm3_per_mm;
 | ||
|     
 | ||
|     foreach my $layer_id (0..$#z) {
 | ||
|         my $z = $z[$layer_id];
 | ||
|         
 | ||
|         foreach my $island (@{$slices[$layer_id]}) {
 | ||
|             foreach my $polygon (@$island) {
 | ||
|                 if ($layer_id > 0) {
 | ||
|                     # find the lower polygon that we want to connect to this one
 | ||
|                     my $lower = $slices[$layer_id-1]->[0]->contour;  # 't was easy, wasn't it?
 | ||
|                     my $lower_z = $z[$layer_id-1];
 | ||
|                     
 | ||
|                     {
 | ||
|                         my @points = ();
 | ||
|                         
 | ||
|                         # keep all points with strong angles
 | ||
|                         {
 | ||
|                             my @pp = @$polygon;
 | ||
|                             foreach my $i (0..$#pp) {
 | ||
|                                 push @points, $pp[$i-1] if abs($pp[$i-1]->ccw_angle($pp[$i-2], $pp[$i]) - PI) > PI/3;
 | ||
|                             }
 | ||
|                         }
 | ||
|                         
 | ||
|                         $polygon = Slic3r::Polygon->new(@points);
 | ||
|                     }
 | ||
|                     #$polygon = Slic3r::Polygon->new(@{$polygon->split_at_first_point->equally_spaced_points(scale $opt{nozzle_width})});
 | ||
|                     
 | ||
|                     # find vertical lines
 | ||
|                     my @vertical = ();
 | ||
|                     foreach my $point (@{$polygon}) {
 | ||
|                         push @vertical, Slic3r::Line->new($point->projection_onto_polygon($lower), $point);
 | ||
|                     }
 | ||
|                     
 | ||
|                     next if !@vertical;
 | ||
|                 
 | ||
|                     my @points = ();
 | ||
|                     foreach my $line (@vertical) {
 | ||
|                         push @points, Slic3r::Pointf3->new(
 | ||
|                             unscale($line->a->x),
 | ||
|                             unscale($line->a->y),  #))
 | ||
|                             $lower_z,
 | ||
|                         );
 | ||
|                         push @points, Slic3r::Pointf3->new(
 | ||
|                             unscale($line->b->x),
 | ||
|                             unscale($line->b->y),  #))
 | ||
|                             $z,
 | ||
|                         );
 | ||
|                     }
 | ||
|                 
 | ||
|                     # reappend first point as destination of the last diagonal segment
 | ||
|                     push @points, Slic3r::Pointf3->new(
 | ||
|                         unscale($vertical[0]->a->x),
 | ||
|                         unscale($vertical[0]->a->y),  #))
 | ||
|                         $lower_z,
 | ||
|                     );
 | ||
|                 
 | ||
|                     # move to the position of the first vertical line
 | ||
|                     print $fh $gcodegen->writer->travel_to_xyz(shift @points);
 | ||
|                 
 | ||
|                     # extrude segments
 | ||
|                     foreach my $point (@points) {
 | ||
|                         print $fh $gcodegen->writer->extrude_to_xyz($point, $e * $gcodegen->writer->get_position->distance_to($point));
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|             
 | ||
|         print $fh $gcodegen->writer->travel_to_z($z);
 | ||
|             foreach my $polygon (@$island) {
 | ||
|                 #my $polyline = $polygon->split_at_vertex(Slic3r::Point->new_scale(@{$gcodegen->writer->get_position}[0,1]));
 | ||
|                 my $polyline = $polygon->split_at_first_point;
 | ||
|                 print $fh $gcodegen->writer->travel_to_xy(Slic3r::Pointf->new_unscale(@{ $polyline->first_point }), "move to first contour point");
 | ||
|                 
 | ||
|                 foreach my $line (@{$polyline->lines}) {
 | ||
|                     my $point = Slic3r::Pointf->new_unscale(@{ $line->b });
 | ||
|                     print $fh $gcodegen->writer->extrude_to_xy($point, $e * unscale($line->length));
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     close $fh;
 | ||
| }
 | ||
| 
 | ||
| sub usage {
 | ||
|     my ($exit_code) = @_;
 | ||
|     
 | ||
|     print <<"EOF";
 | ||
| Usage: wireframe.pl [ OPTIONS ] file.stl
 | ||
| 
 | ||
|     --help              Output this usage screen and exit
 | ||
|     --output, -o        Write to the specified file
 | ||
|     --step-height, -h   Use the specified step height
 | ||
|     --nozzle-angle, -a  Max nozzle angle
 | ||
|     --nozzle-width, -w  External nozzle diameter
 | ||
|     
 | ||
| EOF
 | ||
|     exit ($exit_code || 0);
 | ||
| }
 | ||
| 
 | ||
| __END__
 | 
