mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Ported GCode::extrude_path() to XS (speed boost!)
This commit is contained in:
		
							parent
							
								
									b025efe729
								
							
						
					
					
						commit
						fbd640fdc5
					
				
					 6 changed files with 126 additions and 114 deletions
				
			
		| 
						 | 
				
			
			@ -151,7 +151,7 @@ sub extrude_loop {
 | 
			
		|||
    }
 | 
			
		||||
    
 | 
			
		||||
    # extrude along the path
 | 
			
		||||
    my $gcode = join '', map $self->_extrude_path($_, $description, $speed), @paths;
 | 
			
		||||
    my $gcode = join '', map $self->_extrude_path($_, $description // "", $speed // -1), @paths;
 | 
			
		||||
    
 | 
			
		||||
    # reset acceleration
 | 
			
		||||
    $gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
 | 
			
		||||
| 
						 | 
				
			
			@ -185,115 +185,4 @@ sub extrude_loop {
 | 
			
		|||
    return $gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub extrude_path {
 | 
			
		||||
    my ($self, $path, $description, $speed) = @_;
 | 
			
		||||
    
 | 
			
		||||
    my $gcode = $self->_extrude_path($path, $description, $speed);
 | 
			
		||||
    
 | 
			
		||||
    # reset acceleration
 | 
			
		||||
    $gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
 | 
			
		||||
    
 | 
			
		||||
    return $gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _extrude_path {
 | 
			
		||||
    my ($self, $path, $description, $speed) = @_;
 | 
			
		||||
    
 | 
			
		||||
    $path->simplify(&Slic3r::SCALED_RESOLUTION);
 | 
			
		||||
    
 | 
			
		||||
    # go to first point of extrusion path
 | 
			
		||||
    my $gcode = "";
 | 
			
		||||
    {
 | 
			
		||||
        my $first_point = $path->first_point;
 | 
			
		||||
        $gcode .= $self->travel_to($first_point, $path->role, "move to first $description point")
 | 
			
		||||
            if !$self->last_pos_defined || !$self->last_pos->coincides_with($first_point);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # compensate retraction
 | 
			
		||||
    $gcode .= $self->unretract;
 | 
			
		||||
    
 | 
			
		||||
    # adjust acceleration
 | 
			
		||||
    {
 | 
			
		||||
        my $acceleration;
 | 
			
		||||
        if ($self->config->first_layer_acceleration && $self->first_layer) {
 | 
			
		||||
            $acceleration = $self->config->first_layer_acceleration;
 | 
			
		||||
        } elsif ($self->config->perimeter_acceleration && $path->is_perimeter) {
 | 
			
		||||
            $acceleration = $self->config->perimeter_acceleration;
 | 
			
		||||
        } elsif ($self->config->bridge_acceleration && $path->is_bridge) {
 | 
			
		||||
            $acceleration = $self->config->bridge_acceleration;
 | 
			
		||||
        } elsif ($self->config->infill_acceleration && $path->is_infill) {
 | 
			
		||||
            $acceleration = $self->config->infill_acceleration;
 | 
			
		||||
        } else {
 | 
			
		||||
            $acceleration = $self->config->default_acceleration;
 | 
			
		||||
        }
 | 
			
		||||
        $gcode .= $self->writer->set_acceleration($acceleration);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    # calculate extrusion length per distance unit
 | 
			
		||||
    my $e_per_mm = $self->writer->extruder->e_per_mm3 * $path->mm3_per_mm;
 | 
			
		||||
    $e_per_mm = 0 if !$self->writer->extrusion_axis;
 | 
			
		||||
    
 | 
			
		||||
    # set speed
 | 
			
		||||
    $speed //= -1;
 | 
			
		||||
    if ($speed == -1) {
 | 
			
		||||
        if ($path->role == EXTR_ROLE_PERIMETER) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('perimeter_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_EXTERNAL_PERIMETER) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('external_perimeter_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_OVERHANG_PERIMETER || $path->role == EXTR_ROLE_BRIDGE) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('bridge_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_FILL) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('infill_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_SOLIDFILL) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('solid_infill_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_TOPSOLIDFILL) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('top_solid_infill_speed');
 | 
			
		||||
        } elsif ($path->role == EXTR_ROLE_GAPFILL) {
 | 
			
		||||
            $speed = $self->config->get_abs_value('gap_fill_speed');
 | 
			
		||||
        } else {
 | 
			
		||||
            die "Invalid speed";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ($self->first_layer) {
 | 
			
		||||
        $speed = $self->config->get_abs_value_over('first_layer_speed', $speed);
 | 
			
		||||
    }
 | 
			
		||||
    if ($self->volumetric_speed != 0) {
 | 
			
		||||
        $speed ||= $self->volumetric_speed / $path->mm3_per_mm;
 | 
			
		||||
    }
 | 
			
		||||
    if ($self->config->max_volumetric_speed > 0) {
 | 
			
		||||
        # Cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
 | 
			
		||||
        $speed = min(
 | 
			
		||||
            $speed,
 | 
			
		||||
            $self->config->max_volumetric_speed / $path->mm3_per_mm,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    my $F = $speed * 60;  # convert mm/sec to mm/min
 | 
			
		||||
    
 | 
			
		||||
    # extrude arc or line
 | 
			
		||||
    $gcode .= ";_BRIDGE_FAN_START\n" if $path->is_bridge && $self->enable_cooling_markers;
 | 
			
		||||
    my $path_length = unscale $path->length;
 | 
			
		||||
    {
 | 
			
		||||
        my $extruder_offset = $self->config->get_at('extruder_offset', $self->writer->extruder->id);
 | 
			
		||||
        $gcode .= $path->gcode($self->writer->extruder, $e_per_mm, $F,
 | 
			
		||||
            $self->origin->x - $extruder_offset->x,
 | 
			
		||||
            $self->origin->y - $extruder_offset->y,  #-
 | 
			
		||||
            $self->writer->extrusion_axis,
 | 
			
		||||
            $self->config->gcode_comments ? " ; $description" : "");
 | 
			
		||||
 | 
			
		||||
        if ($self->wipe->enable) {
 | 
			
		||||
            $self->wipe->set_path($path->polyline->clone);
 | 
			
		||||
            $self->wipe->path->reverse;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    $gcode .= ";_BRIDGE_FAN_END\n" if $path->is_bridge && $self->enable_cooling_markers;
 | 
			
		||||
    $self->set_last_pos($path->last_point);
 | 
			
		||||
    
 | 
			
		||||
    if ($self->config->cooling) {
 | 
			
		||||
        my $path_time = $path_length / $F * 60;
 | 
			
		||||
        $self->set_elapsed_time($self->elapsed_time + $path_time);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return $gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ has '_second_layer_things_done'      => (is => 'rw');
 | 
			
		|||
has '_last_obj_copy'                 => (is => 'rw');
 | 
			
		||||
 | 
			
		||||
use List::Util qw(first sum min max);
 | 
			
		||||
use Slic3r::ExtrusionPath ':roles';
 | 
			
		||||
use Slic3r::Flow ':roles';
 | 
			
		||||
use Slic3r::Geometry qw(X Y scale unscale chained_path convex_hull);
 | 
			
		||||
use Slic3r::Geometry::Clipper qw(JT_SQUARE union_ex offset);
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +252,7 @@ sub export {
 | 
			
		|||
                    print $fh $gcodegen->retract;
 | 
			
		||||
                    print $fh $gcodegen->travel_to(
 | 
			
		||||
                        Slic3r::Point->new(0,0),
 | 
			
		||||
                        undef,
 | 
			
		||||
                        EXTR_ROLE_NONE,
 | 
			
		||||
                        'move to origin position for next object',
 | 
			
		||||
                    );
 | 
			
		||||
                    $gcodegen->set_enable_cooling_markers(1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
#include "GCode.hpp"
 | 
			
		||||
#include "ExtrusionEntity.hpp"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
namespace Slic3r {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -267,13 +268,126 @@ GCode::preamble()
 | 
			
		|||
    return gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
GCode::extrude_path(const ExtrusionPath &path, std::string description, double speed)
 | 
			
		||||
{
 | 
			
		||||
    std::string gcode = this->_extrude_path(path, description, speed);
 | 
			
		||||
    
 | 
			
		||||
    // reset acceleration
 | 
			
		||||
    gcode += this->writer.set_acceleration(this->config.default_acceleration.value);
 | 
			
		||||
    
 | 
			
		||||
    return gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
GCode::_extrude_path(ExtrusionPath path, std::string description, double speed)
 | 
			
		||||
{
 | 
			
		||||
    path.simplify(SCALED_RESOLUTION);
 | 
			
		||||
    
 | 
			
		||||
    std::string gcode;
 | 
			
		||||
    
 | 
			
		||||
    // go to first point of extrusion path
 | 
			
		||||
    if (!this->_last_pos_defined || !this->_last_pos.coincides_with(path.first_point())) {
 | 
			
		||||
        gcode += this->travel_to(
 | 
			
		||||
            path.first_point(),
 | 
			
		||||
            path.role,
 | 
			
		||||
            "move to first " + description + " point"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // compensate retraction
 | 
			
		||||
    gcode += this->unretract();
 | 
			
		||||
    
 | 
			
		||||
    // adjust acceleration
 | 
			
		||||
    {
 | 
			
		||||
        double acceleration;
 | 
			
		||||
        if (this->config.first_layer_acceleration.value > 0 && this->first_layer) {
 | 
			
		||||
            acceleration = this->config.first_layer_acceleration.value;
 | 
			
		||||
        } else if (this->config.perimeter_acceleration.value > 0 && path.is_perimeter()) {
 | 
			
		||||
            acceleration = this->config.perimeter_acceleration.value;
 | 
			
		||||
        } else if (this->config.bridge_acceleration.value > 0 && path.is_bridge()) {
 | 
			
		||||
            acceleration = this->config.bridge_acceleration.value;
 | 
			
		||||
        } else if (this->config.infill_acceleration.value > 0 && path.is_infill()) {
 | 
			
		||||
            acceleration = this->config.infill_acceleration.value;
 | 
			
		||||
        } else {
 | 
			
		||||
            acceleration = this->config.default_acceleration.value;
 | 
			
		||||
        }
 | 
			
		||||
        gcode += this->writer.set_acceleration(acceleration);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // calculate extrusion length per distance unit
 | 
			
		||||
    double e_per_mm = this->writer.extruder()->e_per_mm3 * path.mm3_per_mm;
 | 
			
		||||
    if (this->writer.extrusion_axis().empty()) e_per_mm = 0;
 | 
			
		||||
    
 | 
			
		||||
    // set speed
 | 
			
		||||
    if (speed == -1) {
 | 
			
		||||
        if (path.role == erPerimeter) {
 | 
			
		||||
            speed = this->config.get_abs_value("perimeter_speed");
 | 
			
		||||
        } else if (path.role == erExternalPerimeter) {
 | 
			
		||||
            speed = this->config.get_abs_value("external_perimeter_speed");
 | 
			
		||||
        } else if (path.role == erOverhangPerimeter || path.role == erBridgeInfill) {
 | 
			
		||||
            speed = this->config.get_abs_value("bridge_speed");
 | 
			
		||||
        } else if (path.role == erInternalInfill) {
 | 
			
		||||
            speed = this->config.get_abs_value("infill_speed");
 | 
			
		||||
        } else if (path.role == erSolidInfill) {
 | 
			
		||||
            speed = this->config.get_abs_value("solid_infill_speed");
 | 
			
		||||
        } else if (path.role == erTopSolidInfill) {
 | 
			
		||||
            speed = this->config.get_abs_value("top_solid_infill_speed");
 | 
			
		||||
        } else if (path.role == erGapFill) {
 | 
			
		||||
            speed = this->config.get_abs_value("gap_fill_speed");
 | 
			
		||||
        } else {
 | 
			
		||||
            CONFESS("Invalid speed");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (this->first_layer) {
 | 
			
		||||
        speed = this->config.get_abs_value("first_layer_speed", speed);
 | 
			
		||||
    }
 | 
			
		||||
    if (this->volumetric_speed != 0 && speed == 0) {
 | 
			
		||||
        speed = this->volumetric_speed / path.mm3_per_mm;
 | 
			
		||||
    }
 | 
			
		||||
    if (this->config.max_volumetric_speed.value > 0) {
 | 
			
		||||
        // cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
 | 
			
		||||
        speed = std::min(
 | 
			
		||||
            speed,
 | 
			
		||||
            this->config.max_volumetric_speed.value / path.mm3_per_mm
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    double F = speed * 60;  // convert mm/sec to mm/min
 | 
			
		||||
    
 | 
			
		||||
    // extrude arc or line
 | 
			
		||||
    if (path.is_bridge() && this->enable_cooling_markers)
 | 
			
		||||
        gcode += ";_BRIDGE_FAN_START\n";
 | 
			
		||||
    double path_length = unscale(path.length());
 | 
			
		||||
    {
 | 
			
		||||
        Pointf extruder_offset = EXTRUDER_CONFIG(extruder_offset);
 | 
			
		||||
        gcode += path.gcode(this->writer.extruder(), e_per_mm, F,
 | 
			
		||||
            this->origin.x - extruder_offset.x,
 | 
			
		||||
            this->origin.y - extruder_offset.y,
 | 
			
		||||
            this->writer.extrusion_axis(),
 | 
			
		||||
            this->config.gcode_comments ? (" ; " + description) : "");
 | 
			
		||||
 | 
			
		||||
        if (this->wipe.enable) {
 | 
			
		||||
            this->wipe.path = path.polyline;
 | 
			
		||||
            this->wipe.path.reverse();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (path.is_bridge() && this->enable_cooling_markers)
 | 
			
		||||
        gcode += ";_BRIDGE_FAN_END\n";
 | 
			
		||||
    this->set_last_pos(path.last_point());
 | 
			
		||||
    
 | 
			
		||||
    if (this->config.cooling)
 | 
			
		||||
        this->elapsed_time += path_length / F * 60;
 | 
			
		||||
    
 | 
			
		||||
    return gcode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This method accepts &point in print coordinates.
 | 
			
		||||
std::string
 | 
			
		||||
GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment)
 | 
			
		||||
{    
 | 
			
		||||
    /*  Define the travel move as a line between current position and the taget point.
 | 
			
		||||
        This is expressed in print coordinates, so it will need to be translated by
 | 
			
		||||
        $self->origin in order to get G-code coordinates.  */
 | 
			
		||||
        this->origin in order to get G-code coordinates.  */
 | 
			
		||||
    Polyline travel;
 | 
			
		||||
    travel.append(this->last_pos());
 | 
			
		||||
    travel.append(point);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,6 +92,8 @@ class GCode {
 | 
			
		|||
    void apply_print_config(const PrintConfig &print_config);
 | 
			
		||||
    void set_origin(const Pointf &pointf);
 | 
			
		||||
    std::string preamble();
 | 
			
		||||
    std::string extrude_path(const ExtrusionPath &path, std::string description = "", double speed = -1);
 | 
			
		||||
    std::string _extrude_path(ExtrusionPath path, std::string description = "", double speed = -1);
 | 
			
		||||
    std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
 | 
			
		||||
    bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
 | 
			
		||||
    std::string retract(bool toolchange = false);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,8 @@
 | 
			
		|||
 | 
			
		||||
#define EPSILON 1e-4
 | 
			
		||||
#define SCALING_FACTOR 0.000001
 | 
			
		||||
#define RESOLUTION 0.0125
 | 
			
		||||
#define SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR)
 | 
			
		||||
#define PI 3.141592653589793238
 | 
			
		||||
#define scale_(val) (val / SCALING_FACTOR)
 | 
			
		||||
#define unscale(val) (val * SCALING_FACTOR)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,6 +157,10 @@
 | 
			
		|||
    void set_origin(Pointf* pointf)
 | 
			
		||||
        %code{% THIS->set_origin(*pointf); %};
 | 
			
		||||
    std::string preamble();
 | 
			
		||||
    std::string extrude_path(ExtrusionPath* path, std::string description = "", double speed = -1)
 | 
			
		||||
        %code{% RETVAL = THIS->extrude_path(*path, description, speed); %};
 | 
			
		||||
    std::string _extrude_path(ExtrusionPath* path, std::string description = "", double speed = -1)
 | 
			
		||||
        %code{% RETVAL = THIS->_extrude_path(*path, description, speed); %};
 | 
			
		||||
    std::string travel_to(Point* point, ExtrusionRole role, std::string comment)
 | 
			
		||||
        %code{% RETVAL = THIS->travel_to(*point, role, comment); %};
 | 
			
		||||
    bool needs_retraction(Polyline* travel, ExtrusionRole role = erNone)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue