123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- #!/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__
|