Fixed conflicts after merge with master

This commit is contained in:
enricoturri1966 2022-05-20 12:01:11 +02:00
commit 08732d5d10
278 changed files with 24226 additions and 25094 deletions

View File

@ -22,7 +22,7 @@ body:
label: Project file & How to reproduce
description: "*Please* upload a ZIP archive containing the project file used when the problem arise. Please export it just before the problem occurs. Even if you did nothing and/or there is no object, export it! (it contains your current configuration)."
placeholder: |
`File`->`Export project as...` then zip it & drop it here
`File`->`Save project as...` then zip it & drop it here
Also, if needed include the steps to reproduce the bug:
1. Go to '...'
2. Click on '....'

View File

@ -43,6 +43,14 @@ set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux")
set(IS_CROSS_COMPILE FALSE)
if (SLIC3R_STATIC)
# Prefer config scripts over find modules. This is helpful when building with
# the static dependencies. Many libraries have their own export scripts
# while having a Find<PkgName> module in standard cmake installation.
# (e.g. CURL)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
endif ()
if (APPLE)
set(CMAKE_FIND_FRAMEWORK LAST)
set(CMAKE_FIND_APPBUNDLE LAST)
@ -438,23 +446,6 @@ else()
target_link_libraries(libcurl INTERFACE crypt32)
endif()
if (SLIC3R_STATIC AND NOT SLIC3R_STATIC_EXCLUDE_CURL)
if (NOT APPLE)
# libcurl is always linked dynamically to the system libcurl on OSX.
# On other systems, libcurl is linked statically if SLIC3R_STATIC is set.
target_compile_definitions(libcurl INTERFACE CURL_STATICLIB)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
# As of now, our build system produces a statically linked libcurl,
# which links the OpenSSL library dynamically.
find_package(OpenSSL REQUIRED)
message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}")
message("OpenSSL libraries: ${OPENSSL_LIBRARIES}")
target_include_directories(libcurl INTERFACE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(libcurl INTERFACE ${OPENSSL_LIBRARIES})
endif()
endif()
## OPTIONAL packages
# Find eigen3 or use bundled version
@ -472,6 +463,14 @@ include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR})
find_package(EXPAT REQUIRED)
add_library(libexpat INTERFACE)
if (TARGET EXPAT::EXPAT )
target_link_libraries(libexpat INTERFACE EXPAT::EXPAT)
elseif(TARGET expat::expat)
target_link_libraries(libexpat INTERFACE expat::expat)
endif ()
find_package(PNG REQUIRED)
set(OpenGL_GL_PREFERENCE "LEGACY")

View File

@ -75,7 +75,9 @@ file(TO_NATIVE_PATH ${DESTDIR}/usr/local/ _prefix)
set(_boost_flags "")
if (UNIX)
set(_boost_flags "cflags=-fPIC;cxxflags=-fPIC")
elseif(APPLE)
endif ()
if(APPLE)
set(_boost_flags
"cflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET};"
"cxxflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET};"

9
deps/CMakeLists.txt vendored
View File

@ -179,7 +179,12 @@ include(CGAL/CGAL.cmake)
include(NLopt/NLopt.cmake)
include(OpenSSL/OpenSSL.cmake)
include(CURL/CURL.cmake)
set(CURL_PKG "")
if (NOT CURL_FOUND)
include(CURL/CURL.cmake)
set(CURL_PKG dep_CURL)
endif ()
include(JPEG/JPEG.cmake)
include(TIFF/TIFF.cmake)
@ -188,7 +193,7 @@ include(wxWidgets/wxWidgets.cmake)
set(_dep_list
dep_Boost
dep_TBB
dep_CURL
${CURL_PKG}
dep_wxWidgets
dep_Cereal
dep_NLopt

14
deps/CURL/CURL.cmake vendored
View File

@ -48,11 +48,13 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
)
endif ()
if (BUILD_SHARED_LIBS)
set(_curl_static OFF)
else()
set(_curl_static ON)
endif()
set(_patch_command "")
if (UNIX AND NOT APPLE)
# On non-apple UNIX platforms, finding the location of OpenSSL certificates is necessary at runtime, as there is no standard location usable across platforms.
# The OPENSSL_CERT_OVERRIDE flag is understood by PrusaSlicer and will trigger the search of certificates at initial application launch.
# Then ask the user for consent about the correctness of the found location.
set (_patch_command echo set_target_properties(CURL::libcurl PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_CERT_OVERRIDE) >> CMake/curl-config.cmake.in)
endif ()
prusaslicer_add_cmake_project(CURL
# GIT_REPOSITORY https://github.com/curl/curl.git
@ -62,10 +64,10 @@ prusaslicer_add_cmake_project(CURL
DEPENDS ${ZLIB_PKG}
# PATCH_COMMAND ${GIT_EXECUTABLE} checkout -f -- . && git clean -df &&
# ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/curl-mods.patch
PATCH_COMMAND "${_patch_command}"
CMAKE_ARGS
-DBUILD_TESTING:BOOL=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DCURL_STATICLIB=${_curl_static}
${_curl_platform_flags}
)

View File

@ -6,6 +6,13 @@ else()
set(_build_static ON)
endif()
set (_openvdb_vdbprint ON)
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
# Build fails on raspberry pi due to missing link directive to latomic
# Let's hope it will be fixed soon.
set (_openvdb_vdbprint OFF)
endif ()
prusaslicer_add_cmake_project(OpenVDB
# 8.2 patched
URL https://github.com/tamasmeszaros/openvdb/archive/a68fd58d0e2b85f01adeb8b13d7555183ab10aa5.zip
@ -19,7 +26,7 @@ prusaslicer_add_cmake_project(OpenVDB
-DOPENVDB_CORE_STATIC=${_build_static}
-DOPENVDB_ENABLE_RPATH:BOOL=OFF
-DTBB_STATIC=${_build_static}
-DOPENVDB_BUILD_VDB_PRINT=ON
-DOPENVDB_BUILD_VDB_PRINT=${_openvdb_vdbprint}
-DDISABLE_DEPENDENCY_VERSION_CHECKS=ON # Centos6 has old zlib
)

View File

@ -15,6 +15,11 @@ set(DEP_CMAKE_OPTS
include("deps-unix-common.cmake")
find_package(CURL QUIET)
if (NOT CURL_FOUND)
message(WARNING "No CURL dev package found in system, building static library. Mac SDK should include CURL from at least version 10.12. Check your SDK installation.")
endif ()
# ExternalProject_Add(dep_boost
# EXCLUDE_FROM_ALL 1

View File

@ -9,6 +9,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_wx_toolkit "-DwxBUILD_TOOLKIT=gtk${_gtk_ver}")
endif()
set(_unicode_utf8 OFF)
if (UNIX AND NOT APPLE) # wxWidgets will not use char as the underlying type for wxString unless its forced to.
set (_unicode_utf8 ON)
endif()
prusaslicer_add_cmake_project(wxWidgets
# GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets"
# GIT_TAG tm_cross_compile #${_wx_git_tag}
@ -23,6 +28,7 @@ prusaslicer_add_cmake_project(wxWidgets
-DwxUSE_MEDIACTRL=OFF
-DwxUSE_DETECT_SM=OFF
-DwxUSE_UNICODE=ON
-DwxUSE_UNICODE_UTF8=${_unicode_utf8}
-DwxUSE_OPENGL=ON
-DwxUSE_LIBPNG=sys
-DwxUSE_ZLIB=sys

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -28,11 +28,6 @@ BEGIN {
use FindBin;
# Let the XS module know where the GUI resources reside.
set_resources_dir(decode_path($FindBin::Bin) . (($^O eq 'darwin') ? '/../Resources' : '/resources'));
set_var_dir(resources_dir() . "/icons");
set_local_dir(resources_dir() . "/localization/");
use Moo 1.003001;
use Slic3r::XS; # import all symbols (constants etc.) before they get parsed
@ -40,9 +35,7 @@ use Slic3r::Config;
use Slic3r::ExPolygon;
use Slic3r::ExtrusionLoop;
use Slic3r::ExtrusionPath;
use Slic3r::Flow;
use Slic3r::GCode::Reader;
use Slic3r::Geometry::Clipper;
use Slic3r::Layer;
use Slic3r::Line;
use Slic3r::Model;
@ -61,82 +54,4 @@ use constant SCALING_FACTOR => 0.000001;
$Slic3r::loglevel = (defined($ENV{'SLIC3R_LOGLEVEL'}) && $ENV{'SLIC3R_LOGLEVEL'} =~ /^[1-9]/) ? $ENV{'SLIC3R_LOGLEVEL'} : 0;
set_logging_level($Slic3r::loglevel);
# Let the palceholder parser evaluate one expression to initialize its local static macro_processor
# class instance in a thread safe manner.
Slic3r::GCode::PlaceholderParser->new->evaluate_boolean_expression('1==1');
# Open a file by converting $filename to local file system locales.
sub open {
my ($fh, $mode, $filename) = @_;
return CORE::open $$fh, $mode, encode_path($filename);
}
sub tags {
my ($format) = @_;
$format //= '';
my %tags;
# End of line
$tags{eol} = ($format eq 'html') ? '<br>' : "\n";
# Heading
$tags{h2start} = ($format eq 'html') ? '<b>' : '';
$tags{h2end} = ($format eq 'html') ? '</b>' : '';
# Bold font
$tags{bstart} = ($format eq 'html') ? '<b>' : '';
$tags{bend} = ($format eq 'html') ? '</b>' : '';
# Verbatim
$tags{vstart} = ($format eq 'html') ? '<pre>' : '';
$tags{vend} = ($format eq 'html') ? '</pre>' : '';
return %tags;
}
sub slic3r_info
{
my (%params) = @_;
my %tag = Slic3r::tags($params{format});
my $out = '';
$out .= "$tag{bstart}$Slic3r::FORK_NAME$tag{bend}$tag{eol}";
$out .= "$tag{bstart}Version: $tag{bend}$Slic3r::VERSION$tag{eol}";
$out .= "$tag{bstart}Build: $tag{bend}$Slic3r::BUILD$tag{eol}";
return $out;
}
sub copyright_info
{
my (%params) = @_;
my %tag = Slic3r::tags($params{format});
my $out =
'Copyright &copy; 2016 Vojtech Bubnik, Prusa Research. <br />' .
'Copyright &copy; 2011-2016 Alessandro Ranellucci. <br />' .
'<a href="http://slic3r.org/">Slic3r</a> is licensed under the ' .
'<a href="http://www.gnu.org/licenses/agpl-3.0.html">GNU Affero General Public License, version 3</a>.' .
'<br /><br /><br />' .
'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Petr Ledvina, Y. Sapir, Mike Sheldrake and numerous others. ' .
'Manual by Gary Hodgson. Inspired by the RepRap community. <br />' .
'Slic3r logo designed by Corey Daniels, <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon Set</a> designed by Mark James. ';
return $out;
}
sub system_info
{
my (%params) = @_;
my %tag = Slic3r::tags($params{format});
my $out = '';
$out .= "$tag{bstart}Operating System: $tag{bend}$Config{osname}$tag{eol}";
$out .= "$tag{bstart}System Architecture: $tag{bend}$Config{archname}$tag{eol}";
if ($^O eq 'MSWin32') {
$out .= "$tag{bstart}Windows Version: $tag{bend}" . `ver` . $tag{eol};
} else {
# Hopefully some kind of unix / linux.
$out .= "$tag{bstart}System Version: $tag{bend}" . `uname -a` . $tag{eol};
}
$out .= $tag{vstart} . Config::myconfig . $tag{vend};
$out .= " $tag{bstart}\@INC:$tag{bend}$tag{eol}$tag{vstart}";
foreach my $i (@INC) {
$out .= " $i\n";
}
$out .= "$tag{vend}";
return $out;
}
1;

View File

@ -23,54 +23,10 @@ our $Options = print_config_def();
}
}
# From command line parameters, used by slic3r.pl
sub new_from_cli {
my $class = shift;
my %args = @_;
# Delete hash keys with undefined value.
delete $args{$_} for grep !defined $args{$_}, keys %args;
# Replace the start_gcode, end_gcode ... hash values
# with the content of the files they reference.
for (qw(start end layer toolchange)) {
my $opt_key = "${_}_gcode";
if ($args{$opt_key}) {
if (-e $args{$opt_key}) {
Slic3r::open(\my $fh, "<", $args{$opt_key})
or die "Failed to open $args{$opt_key}\n";
binmode $fh, ':utf8';
$args{$opt_key} = do { local $/; <$fh> };
close $fh;
}
}
}
my $self = $class->new;
foreach my $opt_key (keys %args) {
my $opt_def = $Options->{$opt_key};
# we use set_deserialize() for bool options since GetOpt::Long doesn't handle
# arrays of boolean values
if ($opt_key =~ /^(?:bed_shape|duplicate_grid|extruder_offset)$/ || $opt_def->{type} eq 'bool') {
$self->set_deserialize($opt_key, $args{$opt_key});
} elsif (my $shortcut = $opt_def->{shortcut}) {
$self->set($_, $args{$opt_key}) for @$shortcut;
} else {
$self->set($opt_key, $args{$opt_key});
}
}
return $self;
}
package Slic3r::Config::Static;
use parent 'Slic3r::Config';
sub Slic3r::Config::GCode::new { Slic3r::Config::Static::new_GCodeConfig }
sub Slic3r::Config::Print::new { Slic3r::Config::Static::new_PrintConfig }
sub Slic3r::Config::PrintObject::new { Slic3r::Config::Static::new_PrintObjectConfig }
sub Slic3r::Config::PrintRegion::new { Slic3r::Config::Static::new_PrintRegionConfig }
sub Slic3r::Config::Full::new { Slic3r::Config::Static::new_FullPrintConfig }
1;

View File

@ -4,36 +4,9 @@ use warnings;
# an ExPolygon is a polygon with holes
use List::Util qw(first);
use Slic3r::Geometry::Clipper qw(union_ex diff_pl);
sub offset {
my $self = shift;
return Slic3r::Geometry::Clipper::offset(\@$self, @_);
}
sub offset_ex {
my $self = shift;
return Slic3r::Geometry::Clipper::offset_ex(\@$self, @_);
}
sub noncollapsing_offset_ex {
my $self = shift;
my ($distance, @params) = @_;
return $self->offset_ex($distance + 1, @params);
}
sub bounding_box {
my $self = shift;
return $self->contour->bounding_box;
}
package Slic3r::ExPolygon::Collection;
sub size {
my $self = shift;
return [ Slic3r::Geometry::size_2D([ map @$_, map @$_, @$self ]) ];
}
1;

View File

@ -1,13 +0,0 @@
package Slic3r::Flow;
use strict;
use warnings;
use parent qw(Exporter);
our @EXPORT_OK = qw(FLOW_ROLE_EXTERNAL_PERIMETER FLOW_ROLE_PERIMETER FLOW_ROLE_INFILL
FLOW_ROLE_SOLID_INFILL
FLOW_ROLE_TOP_SOLID_INFILL FLOW_ROLE_SUPPORT_MATERIAL
FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE);
our %EXPORT_TAGS = (roles => \@EXPORT_OK);
1;

View File

@ -9,26 +9,15 @@ our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
PI epsilon
angle3points
collinear
dot
line_intersection
normalize
point_in_segment
polyline_lines
polygon_is_convex
polygon_segment_having_point
scale
unscale
scaled_epsilon
size_2D
X Y Z
convex_hull
chained_path_from
deg2rad
rad2deg
rad2deg_dir
);
use constant PI => 4 * atan2(1, 1);
@ -45,171 +34,6 @@ sub scaled_epsilon () { epsilon / &Slic3r::SCALING_FACTOR }
sub scale ($) { $_[0] / &Slic3r::SCALING_FACTOR }
sub unscale ($) { $_[0] * &Slic3r::SCALING_FACTOR }
# used by geometry.t, polygon_segment_having_point
sub point_in_segment {
my ($point, $line) = @_;
my ($x, $y) = @$point;
my $line_p = $line->pp;
my @line_x = sort { $a <=> $b } $line_p->[A][X], $line_p->[B][X];
my @line_y = sort { $a <=> $b } $line_p->[A][Y], $line_p->[B][Y];
# check whether the point is in the segment bounding box
return 0 unless $x >= ($line_x[0] - epsilon) && $x <= ($line_x[1] + epsilon)
&& $y >= ($line_y[0] - epsilon) && $y <= ($line_y[1] + epsilon);
# if line is vertical, check whether point's X is the same as the line
if ($line_p->[A][X] == $line_p->[B][X]) {
return abs($x - $line_p->[A][X]) < epsilon ? 1 : 0;
}
# calculate the Y in line at X of the point
my $y3 = $line_p->[A][Y] + ($line_p->[B][Y] - $line_p->[A][Y])
* ($x - $line_p->[A][X]) / ($line_p->[B][X] - $line_p->[A][X]);
return abs($y3 - $y) < epsilon ? 1 : 0;
}
# used by geometry.t
sub polyline_lines {
my ($polyline) = @_;
my @points = @$polyline;
return map Slic3r::Line->new(@points[$_, $_+1]), 0 .. $#points-1;
}
# given a $polygon, return the (first) segment having $point
# used by geometry.t
sub polygon_segment_having_point {
my ($polygon, $point) = @_;
foreach my $line (@{ $polygon->lines }) {
return $line if point_in_segment($point, $line);
}
return undef;
}
# polygon must be simple (non complex) and ccw
sub polygon_is_convex {
my ($points) = @_;
for (my $i = 0; $i <= $#$points; $i++) {
my $angle = angle3points($points->[$i-1], $points->[$i-2], $points->[$i]);
return 0 if $angle < PI;
}
return 1;
}
sub normalize {
my ($line) = @_;
my $len = sqrt( ($line->[X]**2) + ($line->[Y]**2) + ($line->[Z]**2) )
or return [0, 0, 0]; # to avoid illegal division by zero
return [ map $_ / $len, @$line ];
}
# 2D dot product
# used by 3DScene.pm
sub dot {
my ($u, $v) = @_;
return $u->[X] * $v->[X] + $u->[Y] * $v->[Y];
}
sub line_intersection {
my ($line1, $line2, $require_crossing) = @_;
$require_crossing ||= 0;
my $intersection = _line_intersection(map @$_, @$line1, @$line2);
return (ref $intersection && $intersection->[1] == $require_crossing)
? $intersection->[0]
: undef;
}
# Used by test cases.
sub collinear {
my ($line1, $line2, $require_overlapping) = @_;
my $intersection = _line_intersection(map @$_, @$line1, @$line2);
return 0 unless !ref($intersection)
&& ($intersection eq 'parallel collinear'
|| ($intersection eq 'parallel vertical' && abs($line1->[A][X] - $line2->[A][X]) < epsilon));
if ($require_overlapping) {
my @box_a = bounding_box([ $line1->[0], $line1->[1] ]);
my @box_b = bounding_box([ $line2->[0], $line2->[1] ]);
return 0 unless bounding_box_intersect( 2, @box_a, @box_b );
}
return 1;
}
sub _line_intersection {
my ( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 ) = @_;
my ($x, $y); # The as-yet-undetermined intersection point.
my $dy10 = $y1 - $y0; # dyPQ, dxPQ are the coordinate differences
my $dx10 = $x1 - $x0; # between the points P and Q.
my $dy32 = $y3 - $y2;
my $dx32 = $x3 - $x2;
my $dy10z = abs( $dy10 ) < epsilon; # Is the difference $dy10 "zero"?
my $dx10z = abs( $dx10 ) < epsilon;
my $dy32z = abs( $dy32 ) < epsilon;
my $dx32z = abs( $dx32 ) < epsilon;
my $dyx10; # The slopes.
my $dyx32;
$dyx10 = $dy10 / $dx10 unless $dx10z;
$dyx32 = $dy32 / $dx32 unless $dx32z;
# Now we know all differences and the slopes;
# we can detect horizontal/vertical special cases.
# E.g., slope = 0 means a horizontal line.
unless ( defined $dyx10 or defined $dyx32 ) {
return "parallel vertical";
}
elsif ( $dy10z and not $dy32z ) { # First line horizontal.
$y = $y0;
$x = $x2 + ( $y - $y2 ) * $dx32 / $dy32;
}
elsif ( not $dy10z and $dy32z ) { # Second line horizontal.
$y = $y2;
$x = $x0 + ( $y - $y0 ) * $dx10 / $dy10;
}
elsif ( $dx10z and not $dx32z ) { # First line vertical.
$x = $x0;
$y = $y2 + $dyx32 * ( $x - $x2 );
}
elsif ( not $dx10z and $dx32z ) { # Second line vertical.
$x = $x2;
$y = $y0 + $dyx10 * ( $x - $x0 );
}
elsif ( abs( $dyx10 - $dyx32 ) < epsilon ) {
# The slopes are suspiciously close to each other.
# Either we have parallel collinear or just parallel lines.
# The bounding box checks have already weeded the cases
# "parallel horizontal" and "parallel vertical" away.
my $ya = $y0 - $dyx10 * $x0;
my $yb = $y2 - $dyx32 * $x2;
return "parallel collinear" if abs( $ya - $yb ) < epsilon;
return "parallel";
}
else {
# None of the special cases matched.
# We have a "honest" line intersection.
$x = ($y2 - $y0 + $dyx10*$x0 - $dyx32*$x2)/($dyx10 - $dyx32);
$y = $y0 + $dyx10 * ($x - $x0);
}
my $h10 = $dx10 ? ($x - $x0) / $dx10 : ($dy10 ? ($y - $y0) / $dy10 : 1);
my $h32 = $dx32 ? ($x - $x2) / $dx32 : ($dy32 ? ($y - $y2) / $dy32 : 1);
return [Slic3r::Point->new($x, $y), $h10 >= 0 && $h10 <= 1 && $h32 >= 0 && $h32 <= 1];
}
# 2D
sub bounding_box {
my ($points) = @_;
@ -227,45 +51,4 @@ sub bounding_box {
return @bb[X1,Y1,X2,Y2];
}
# used by ExPolygon::size
sub size_2D {
my @bounding_box = bounding_box(@_);
return (
($bounding_box[X2] - $bounding_box[X1]),
($bounding_box[Y2] - $bounding_box[Y1]),
);
}
# Used by sub collinear, which is used by test cases.
# bounding_box_intersect($d, @a, @b)
# Return true if the given bounding boxes @a and @b intersect
# in $d dimensions. Used by sub collinear.
sub bounding_box_intersect {
my ( $d, @bb ) = @_; # Number of dimensions and box coordinates.
my @aa = splice( @bb, 0, 2 * $d ); # The first box.
# (@bb is the second one.)
# Must intersect in all dimensions.
for ( my $i_min = 0; $i_min < $d; $i_min++ ) {
my $i_max = $i_min + $d; # The index for the maximum.
return 0 if ( $aa[ $i_max ] + epsilon ) < $bb[ $i_min ];
return 0 if ( $bb[ $i_max ] + epsilon ) < $aa[ $i_min ];
}
return 1;
}
# Used by test cases.
# this assumes a CCW rotation from $p2 to $p3 around $p1
sub angle3points {
my ($p1, $p2, $p3) = @_;
# p1 is the center
my $angle = atan2($p2->[X] - $p1->[X], $p2->[Y] - $p1->[Y])
- atan2($p3->[X] - $p1->[X], $p3->[Y] - $p1->[Y]);
# we only want to return only positive angles
return $angle <= 0 ? $angle + 2*PI() : $angle;
}
1;

View File

@ -1,14 +0,0 @@
package Slic3r::Geometry::Clipper;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
offset
offset_ex offset2_ex
diff_ex diff union_ex intersection_ex
JT_ROUND JT_MITER JT_SQUARE
intersection intersection_pl diff_pl union);
1;

View File

@ -15,23 +15,4 @@ sub config {
return $self->object->config;
}
sub region {
my $self = shift;
my ($region_id) = @_;
while ($self->region_count <= $region_id) {
$self->add_region($self->object->print->get_region($self->region_count));
}
return $self->get_region($region_id);
}
sub regions {
my ($self) = @_;
return [ map $self->get_region($_), 0..($self->region_count-1) ];
}
package Slic3r::Layer::Support;
our @ISA = qw(Slic3r::Layer);
1;

View File

@ -5,15 +5,4 @@ use warnings;
# a line is a two-points line
use parent 'Slic3r::Polyline';
sub intersection {
my $self = shift;
my ($line, $require_crossing) = @_;
return Slic3r::Geometry::line_intersection($self, $line, $require_crossing);
}
sub grow {
my $self = shift;
return Slic3r::Polyline->new(@$self)->grow(@_);
}
1;

View File

@ -133,11 +133,4 @@ sub add_instance {
}
}
sub mesh_stats {
my $self = shift;
# TODO: sum values from all volumes
return $self->volumes->[0]->mesh->stats;
}
1;

View File

@ -5,9 +5,4 @@ use warnings;
# a polygon is a closed polyline.
use parent 'Slic3r::Polyline';
sub grow {
my $self = shift;
return $self->split_at_first_point->grow(@_);
}
1;
1;

View File

@ -4,11 +4,6 @@ use strict;
use warnings;
use List::Util qw(min max sum first);
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(scale epsilon);
use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
offset offset_ex offset2_ex JT_MITER);
use Slic3r::Print::State ':steps';
use Slic3r::Surface ':types';
sub layers {
@ -16,9 +11,4 @@ sub layers {
return [ map $self->get_layer($_), 0..($self->layer_count - 1) ];
}
sub support_layers {
my $self = shift;
return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ];
}
1;

View File

@ -1,12 +0,0 @@
# Wraps C++ enums Slic3r::PrintStep and Slic3r::PrintObjectStep
package Slic3r::Print::State;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(STEP_SLICE STEP_PERIMETERS STEP_PREPARE_INFILL
STEP_INFILL STEP_SUPPORTMATERIAL STEP_SKIRT STEP_BRIM STEP_WIPE_TOWER);
our %EXPORT_TAGS = (steps => \@EXPORT_OK);
1;

View File

@ -8412,7 +8412,7 @@ msgstr "Überlauf"
#: src/slic3r/GUI/GUI_Preview.cpp:241 src/libslic3r/ExtrusionEntity.cpp:320
#: src/libslic3r/ExtrusionEntity.cpp:344
msgid "Overhang perimeter"
msgstr "Überhängende Außenkontur"
msgstr "Überhängende Kontur"
#: src/libslic3r/PrintConfig.cpp:2767
msgid "Overhang threshold"
@ -8731,7 +8731,7 @@ msgstr ""
#: src/slic3r/GUI/GUI_Preview.cpp:239 src/libslic3r/ExtrusionEntity.cpp:318
#: src/libslic3r/ExtrusionEntity.cpp:340
msgid "Perimeter"
msgstr "Außenkontur"
msgstr "Kontur"
#: src/libslic3r/PrintConfig.cpp:1946
msgid "Perimeter extruder"
@ -10848,8 +10848,8 @@ msgstr ""
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
"zuzulassen. Falls auf null belassen, wird PrusaSlicer die Extrusionsbreiten "
"vom Durchmesser der Druckdüse ableiten (siehe die Hilfstexte für die "
"Extrusionsbreite für Außenkonturen, Infill usw.). Falls als Prozentwert (z."
"B. 230%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
"Extrusionsbreite für Konturen, Infill usw.). Falls als Prozentwert (z.B. "
"230%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
#: src/libslic3r/PrintConfig.cpp:729
msgid ""
@ -10859,10 +10859,10 @@ msgid ""
"(for example 200%), it will be computed over layer height."
msgstr ""
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
"für externe Außenkonturen anzugeben. Falls auf null belassen, wird die "
"Standard-Extrusionsbreite verwendet (falls angeben), ansonsten wird der "
"Durchmesser der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. "
"200%) angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
"für Außenkonturen anzugeben. Falls auf null belassen, wird die Standard-"
"Extrusionsbreite verwendet (falls angeben), ansonsten wird der Durchmesser "
"der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. 200%) "
"angegeben, wird dieser ausgehend von der Schichthöhe berechnet."
#: src/libslic3r/PrintConfig.cpp:1196
msgid ""
@ -10931,7 +10931,7 @@ msgid ""
"it will be computed over layer height."
msgstr ""
"Setzen Sie dies auf einen Nicht-Nullwert, um eine manuelle Extrusionsbreite "
"für Außenkonturen anzugeben. Dünnere Extrusionsbreiten sind vorteilhaft, um "
"für Konturen anzugeben. Dünnere Extrusionsbreiten sind vorteilhaft, um "
"genauere Oberflächen zu erhalten. Falls auf null belassen, wird die Standard-"
"Extrusionsbreite verwendet (falls angeben), ansonsten wird der Durchmesser "
"der Druckdüse x 1,125 verwendet. Falls als Prozentwert (z.B. 200%) "
@ -11797,7 +11797,7 @@ msgid ""
"for auto."
msgstr ""
"Druckgeschwindigkeit für die oberen massiven Schichten (betrifft nur die "
"obersten Außenkonturen und nicht deren innenliegende massiven Schichten). "
"obersten Außenschichten und nicht deren innenliegende massiven Schichten). "
"Wir empfehlen, diesen Wert zu reduzieren, um eine schönere Oberfläche zu "
"erhalten. Dies kann als Prozentwert (z.B. 80%) der oben eingegebenen "
"Geschwindigkeit für massives Infill angegeben werden. Für Automatik auf null "
@ -12613,8 +12613,8 @@ msgid ""
msgstr ""
"Der Extruder, der verwendet werden soll, falls keine sonstigen "
"Extrudereinstellungen angegeben wurden. Dies übersteuert die Angaben für die "
"Außenkontur- und Infill-Extruder, aber nicht die Angabe des Extruders für "
"die Stützen."
"Kontur- und Infill-Extruder, aber nicht die Angabe des Extruders für die "
"Stützen."
#: src/libslic3r/PrintConfig.cpp:1448
msgid "The extruder to use when printing infill."
@ -13554,8 +13554,8 @@ msgid ""
"prevent resetting acceleration at all."
msgstr ""
"Dies ist der Beschleunigungswert, auf den Ihr Drucker zurückgesetzt wird, "
"nachdem aufgabenspezifische Beschleunigungswerte (Außenkonturen/Infill) "
"verwendet wurden. Setzen Sie dies auf null, um ein Zurückstellen der "
"nachdem aufgabenspezifische Beschleunigungswerte (Konturen/Infill) verwendet "
"wurden. Setzen Sie dies auf null, um ein Zurückstellen der "
"Beschleunigungswerte zu deaktivieren."
#: src/libslic3r/PrintConfig.cpp:443
@ -13679,11 +13679,11 @@ msgid ""
"surfaces which benefit from a higher number of perimeters if the Extra "
"Perimeters option is enabled."
msgstr ""
"Diese Stellung bestimmt die Anzahl der Außenkonturen, die für jede Schicht "
"Diese Stellung bestimmt die Anzahl der Konturen, die für jede Schicht "
"erzeugt werden. PusaSlicer kann diese Zahl automatisch vergrößern, wenn es "
"schräge Oberflächen erkennt, die sich mit einer höheren Zahl von "
"Außenkonturen besser drucken lassen, wenn die \"Zusätzliche Außenkonturen "
"falls notwendig\" Option aktiviert ist."
"schräge Oberflächen erkennt, die sich mit einer höheren Zahl von Konturen "
"besser drucken lassen, wenn die \"Zusätzliche Konturen falls notwendig\" "
"Option aktiviert ist."
#: src/libslic3r/PrintConfig.cpp:1895
msgid ""
@ -13712,8 +13712,8 @@ msgid ""
"This option will switch the print order of perimeters and infill, making the "
"latter first."
msgstr ""
"Diese Einstellungen kehrt die Druckreihenfolge von Außenkonturen und Infill "
"um, sodass der Infill zuerst gedruckt wird."
"Diese Einstellungen kehrt die Druckreihenfolge von Konturen und Infill um, "
"sodass der Infill zuerst gedruckt wird."
#: src/slic3r/GUI/PhysicalPrinterDialog.cpp:83
msgid "This printer will be shown in the presets list as"
@ -13726,9 +13726,9 @@ msgid ""
"calculated on the perimeters speed setting above. Set to zero for auto."
msgstr ""
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit der äußeren "
"(sichtbaren) Außenkonturen aus. Als Prozentwert eingegeben (z.B. 80%), wird "
"sie ausgehend von der obigen Geschwindigkeitseinstellung für Außenkonturen "
"berechnet. Für die automatische Berechnung auf null setzen."
"(sichtbaren) Konturen aus. Als Prozentwert eingegeben (z.B. 80%), wird sie "
"ausgehend von der obigen Geschwindigkeitseinstellung für Konturen berechnet. "
"Für die automatische Berechnung auf null setzen."
#: src/libslic3r/PrintConfig.cpp:2303
msgid ""
@ -13736,11 +13736,11 @@ msgid ""
"6.5mm (usually holes). If expressed as percentage (for example: 80%) it will "
"be calculated on the perimeters speed setting above. Set to zero for auto."
msgstr ""
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit von "
"Außenkonturen mit einem Radius <= 6,5 mm (üblicherweise Bohrungen) aus. Als "
"Prozentwert eingegeben (z.B. 80%), wird sie ausgehend von der obigen "
"Geschwindigkeitseinstellung für Außenkonturen berechnet. Für eine "
"automatische Berechnung setzen Sie dies auf null."
"Diese separate Einstellung wirkt sich auf die Geschwindigkeit von Konturen "
"mit einem Radius <= 6,5 mm (üblicherweise Bohrungen) aus. Als Prozentwert "
"eingegeben (z.B. 80%), wird sie ausgehend von der obigen "
"Geschwindigkeitseinstellung für Konturen berechnet. Für eine automatische "
"Berechnung setzen Sie dies auf null."
#: src/libslic3r/PrintConfig.cpp:1484
msgid ""
@ -13749,11 +13749,11 @@ msgid ""
"cause gaps. If expressed as percentage (example: 15%) it is calculated over "
"perimeter extrusion width."
msgstr ""
"Diese Einstellung fügt eine zusätzliche Überlappung zwischen Außenkonturen "
"und Infill ein, um die Haftung zu verbessern. Theoretisch sollte dies nicht "
"Diese Einstellung fügt eine zusätzliche Überlappung zwischen Konturen und "
"Infill ein, um die Haftung zu verbessern. Theoretisch sollte dies nicht "
"notwendig sein, doch vorhandenes Getriebespiel könnte Lücken erzeugen. Als "
"Prozentwert eingegeben (z.B. 15%) wird sie ausgehend von der "
"Extrusionsbreite für die Außenkontur ausgerechnet."
"Extrusionsbreite für die Kontur ausgerechnet."
#: src/libslic3r/PrintConfig.cpp:265
msgid ""
@ -15816,7 +15816,7 @@ msgstr "Parametername"
#: src/slic3r/GUI/PresetHints.cpp:171
msgid "perimeters"
msgstr "Außenkonturen"
msgstr "Konturen"
#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:64 src/libslic3r/Preset.cpp:1338
msgid "print"

View File

@ -17,15 +17,20 @@ src/slic3r/GUI/GalleryDialog.cpp
src/slic3r/GUI/GCodeViewer.cpp
src/slic3r/GUI/GLCanvas3D.cpp
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp
src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp
src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -970,10 +970,7 @@ renamed_from = "Creality ENDER-3 BLTouch"
printer_model = ENDER3BLTOUCH
[printer:Creality Ender-3 Pro]
inherits = *common*; *pauseprint*
renamed_from = "Creality Ender-3 Pro"
bed_shape = 5x0,215x0,215x220,5x220
max_print_height = 250
inherits = Creality Ender-3; *pauseprint*
printer_model = ENDER3PRO
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_ENDER3PRO\nPRINTER_HAS_BOWDEN

View File

@ -1,4 +1,5 @@
min_slic3r_version = 2.4.0-rc
1.4.5 Added MMU2/S profiles for 0.25mm nozzle. Updated FW version. Enabled g-code thumbnails for MK3 family printers. Updated end g-code.
1.4.4 Added multiple Fiberlogy filament profiles. Updated Extrudr filament profiles.
1.4.3 Added new filament profiles and SLA materials.
1.4.2 Added SLA material profiles.
@ -24,6 +25,7 @@ min_slic3r_version = 2.4.0-alpha0
1.3.0-alpha1 Added Prusament PCCF. Increased travel acceleration for Prusa MINI. Updated start g-code for Prusa MINI. Added multiple add:north and Extrudr filament profiles. Updated Z travel speed values.
1.3.0-alpha0 Disabled thick bridges, updated support settings.
min_slic3r_version = 2.3.2-alpha0
1.3.7 Updated firmware version.
1.3.6 Updated firmware version.
1.3.5 Added material profiles for Prusament Resins.
1.3.4 Added material profiles for new Prusament Resins. Added profiles for multiple BASF filaments.
@ -32,6 +34,7 @@ min_slic3r_version = 2.3.2-alpha0
1.3.1 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S).
1.3.0 Added SL1S SPEED profiles.
min_slic3r_version = 2.3.0-rc1
1.2.12 Updated firmware version.
1.2.11 Updated firmware version.
1.2.10 Added multiple profiles for Filatech filaments. Updated SLA print settings (pad wall slope angle).
1.2.9 Added material profiles for Prusament Resin.
@ -52,6 +55,7 @@ min_slic3r_version = 2.3.0-alpha4
1.2.0-alpha1 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
1.2.0-alpha0 Added filament spool weights
min_slic3r_version = 2.2.0-alpha3
1.1.16 Updated firmware version.
1.1.15 Updated firmware version.
1.1.14 Updated firmware version.
1.1.13 Updated firmware version. Updated end g-code in MMU2 printer profiles.

View File

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 1.4.4
config_version = 1.4.5
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -288,6 +288,7 @@ output_filename_format = {input_filename_base}_{nozzle_diameter[0]}n_{layer_heig
thick_bridges = 0
bridge_flow_ratio = 1
bridge_speed = 20
wipe_tower_bridging = 6
[print:*0.25nozzleMK3*]
inherits = *0.25nozzle*
@ -308,6 +309,7 @@ max_print_speed = 80
perimeters = 3
fill_pattern = grid
fill_density = 20%
wipe_tower_bridging = 6
[print:*0.25nozzleMINI*]
inherits = *0.25nozzleMK3*
@ -691,6 +693,7 @@ solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_contact_distance = 0.07
raft_contact_distance = 0.07
single_extruder_multi_material_priming = 0
[print:0.15mm OPTIMAL @0.25 nozzle]
inherits = *0.15mm*; *0.25nozzle*
@ -707,6 +710,38 @@ solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_contact_distance = 0.08
raft_contact_distance = 0.07
perimeter_extrusion_width = 0.27
external_perimeter_extrusion_width = 0.27
infill_extrusion_width = 0.27
solid_infill_extrusion_width = 0.27
single_extruder_multi_material_priming = 0
[print:0.15mm SOLUBLE FULL @0.25 nozzle]
inherits = 0.15mm OPTIMAL @0.25 nozzle
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders>1
support_material_contact_distance = 0
raft_contact_distance = 0
wipe_tower_bridging = 5
solid_infill_speed = 40
support_material_extruder = 5
support_material_interface_extruder = 5
support_material_with_sheath = 1
support_material_interface_layers = 4
support_material_threshold = 60
support_material = 1
support_material_synchronize_layers = 1
support_material_xy_spacing = 100%
support_material_style = snug
raft_first_layer_expansion = 2
support_material_interface_spacing = 0.05
single_extruder_multi_material_priming = 0
[print:0.15mm SOLUBLE INTERFACE @0.25 nozzle]
inherits = 0.15mm SOLUBLE FULL @0.25 nozzle
support_material_extruder = 0
support_material_interface_extruder = 5
support_material_with_sheath = 0
support_material_style = grid
## MK2 - 0.6mm nozzle
@ -992,7 +1027,7 @@ raft_contact_distance = 0.07
[print:0.07mm ULTRADETAIL @0.25 nozzle MK3]
inherits = *0.07mm*; *0.25nozzle*; *MK3*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
infill_speed = 30
solid_infill_speed = 30
support_material_speed = 30
@ -1017,6 +1052,36 @@ fill_pattern = grid
fill_density = 20%
support_material_contact_distance = 0.08
raft_contact_distance = 0.07
perimeter_extrusion_width = 0.27
external_perimeter_extrusion_width = 0.27
infill_extrusion_width = 0.27
solid_infill_extrusion_width = 0.27
[print:0.15mm SOLUBLE FULL @0.25 nozzle MK3]
inherits = 0.15mm QUALITY @0.25 nozzle MK3
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders>1
support_material_contact_distance = 0
raft_contact_distance = 0
wipe_tower_bridging = 5
solid_infill_speed = 40
support_material_extruder = 5
support_material_interface_extruder = 5
support_material_with_sheath = 1
support_material_interface_layers = 4
support_material_threshold = 60
support_material = 1
support_material_synchronize_layers = 1
support_material_xy_spacing = 100%
support_material_style = snug
raft_first_layer_expansion = 2
support_material_interface_spacing = 0.05
[print:0.15mm SOLUBLE INTERFACE @0.25 nozzle MK3]
inherits = 0.15mm SOLUBLE FULL @0.25 nozzle MK3
support_material_extruder = 0
support_material_interface_extruder = 5
support_material_with_sheath = 0
support_material_style = grid
## MK3 - 0.6mm nozzle
@ -1315,6 +1380,10 @@ fill_pattern = grid
fill_density = 20%
support_material_contact_distance = 0.08
raft_contact_distance = 0.07
perimeter_extrusion_width = 0.27
external_perimeter_extrusion_width = 0.27
infill_extrusion_width = 0.27
solid_infill_extrusion_width = 0.27
# MINI - 0.6mm nozzle
@ -3331,7 +3400,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MINI
[filament:*ABS MMU2*]
inherits = Prusa ABS
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
filament_cooling_final_speed = 50
filament_cooling_initial_speed = 10
filament_cooling_moves = 5
@ -3346,6 +3415,92 @@ filament_unloading_speed = 20
inherits = *ABS MMU2*
filament_vendor = Generic
[filament:Generic ABS @MMU2 0.25]
inherits = Generic ABS @MMU2
filament_max_volumetric_speed = 1.7
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Generic PLA @MMU2 0.25]
inherits = Generic PLA @MMU2
filament_max_volumetric_speed = 3
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 120 2.70968 2.93548 3.29032 3.80645 4.58065 5.54839 6.54839 7.3871 7.93548 8.19355 8.16129 8.03226| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 7.98716 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusa PLA @MMU2 0.25]
inherits = Generic PLA @MMU2 0.25
[filament:Prusament PLA @MMU2 0.25]
inherits = Prusament PLA @MMU2
filament_max_volumetric_speed = 3
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 120 2.70968 2.93548 3.29032 3.80645 4.58065 5.54839 6.54839 7.3871 7.93548 8.19355 8.16129 8.03226| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 7.98716 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusament PVB @MMU2 0.25]
inherits = Prusament PVB @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 110 1.74194 1.90323 2.16129 2.48387 2.83871 3.25806 3.83871 4.6129 5.41935 5.96774| 0.05 1.69677 0.45 1.96128 0.95 2.63872 1.45 3.46129 1.95 4.99031 2.45 6.12908 2.95 8.30974 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusament ASA @MMU2 0.25]
inherits = Prusament ASA @MMU2
filament_max_volumetric_speed = 1.7
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusament PC Blend @MMU2 0.25]
inherits = Prusament PC Blend @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 120 2.70968 2.93548 3.32258 3.83871 4.58065 5.54839 6.51613 7.35484 7.93548 8.16129| 0.05 2.66451 0.45 3.05805 0.95 4.05807 1.45 5.97742 1.95 7.69999 2.45 8.1936 2.95 11.342 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusa ABS @MMU2 0.25]
inherits = Prusa ABS @MMU2
filament_max_volumetric_speed = 1.7
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 110 3.41935 3.6129 3.93548 4.35484 4.87097 5.51613 6.25806 7.06452 7.80645 8.35484 8.70968 8.83871| 0.05 3.37419 0.45 3.70322 0.95 4.5742 1.45 5.78387 1.95 7.44194 2.45 8.58065 2.95 8.89045 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Generic PETG @MMU2 0.25]
inherits = Generic PETG @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusa PETG @MMU2 0.25]
inherits = Prusa PETG @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Prusament PETG @MMU2 0.25]
inherits = Prusament PETG @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 140 4.70968 4.74194 4.77419 4.80645 4.83871 4.87097 4.90323 5 5.25806 5.67742 6.29032 7.06452 7.83871 8.3871| 0.05 4.72901 0.45 4.73545 0.95 4.83226 1.45 4.88067 1.95 5.05483 2.45 5.93553 2.95 7.53556 3.45 8.6323 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Verbatim BVOH @MMU2 0.25]
inherits = Verbatim BVOH @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 110 1.74194 1.90323 2.16129 2.48387 2.83871 3.25806 3.83871 4.6129 5.41935 5.96774| 0.05 1.69677 0.45 1.96128 0.95 2.63872 1.45 3.46129 1.95 4.99031 2.45 6.12908 2.95 8.30974 3.45 11.4065 3.95 7.6 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:PrimaSelect PVA+ @MMU2 0.25]
inherits = PrimaSelect PVA+ @MMU2
filament_max_volumetric_speed = 2
filament_minimal_purge_on_wipe_tower = 10
filament_ramming_parameters = "200 110 2.32258 2.48387 2.67742 2.87097 3.03226 3.22581 3.48387 3.80645 4.29032 5 5.93548 7 7.90323 8.48387 8.80645 8.90323| 0.05 2.27741 0.45 2.54192 0.95 2.9613 1.45 3.33225 1.95 4.02257 2.45 5.48393 2.95 7.72915 3.45 8.76139 3.95 8.95485 4.45 7.6 4.95 7.6"
compatible_printers_condition = nozzle_diameter[0]==0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
[filament:Generic HIPS @MMU2]
inherits = *ABS MMU2*
filament_vendor = Generic
@ -3585,7 +3740,7 @@ filament_type = PETG
[filament:*PET MMU2*]
inherits = Prusa PETG
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
temperature = 230
first_layer_temperature = 230
filament_cooling_final_speed = 1
@ -4041,7 +4196,7 @@ start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and no
[filament:*PLA MMU2*]
inherits = Prusa PLA
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
temperature = 205
filament_cooling_final_speed = 2
filament_cooling_initial_speed = 3
@ -4290,7 +4445,7 @@ temperature = 210
[filament:Verbatim BVOH @MMU2]
inherits = Verbatim BVOH
filament_vendor = Verbatim
compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
temperature = 195
fan_always_on = 1
first_layer_temperature = 200
@ -4310,7 +4465,7 @@ filament_loading_speed_start = 19
[filament:PrimaSelect PVA+ @MMU2]
inherits = *common*
filament_vendor = PrimaSelect
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
compatible_printers_condition = nozzle_diameter[0]!=0.25 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
bed_temperature = 60
bridge_fan_speed = 100
cooling = 0
@ -8199,7 +8354,7 @@ bed_shape = 0x0,250x0,250x210,0x210
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
between_objects_gcode =
deretract_speed = 0
end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y200 F3600 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM900 K0 ; reset LA\nM84 ; disable motors
extruder_offset = 0x0
gcode_flavor = marlin
silent_mode = 0
@ -8280,7 +8435,7 @@ printer_model = MK2SMM
[printer:*mm-single*]
inherits = *multimaterial*
end_gcode = G1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n\n
end_gcode = G1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+50, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n\n
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.2.3 ; tell printer latest fw version\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0\nM203 E100\nM92 E140\nG1 Z0.25 F7200\nG1 X50 E80 F1000\nG1 X160 E20 F1000\nG1 Z0.2 F7200\nG1 X220 E13 F1000\nG1 X240 E0 F1000\nG92 E0
default_print_profile = 0.15mm OPTIMAL
@ -8288,7 +8443,7 @@ default_print_profile = 0.15mm OPTIMAL
[printer:*mm-multi*]
inherits = *multimaterial*
high_current_on_filament_swap = 1
end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.\nG1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\n{endif}\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.\nG1 E-4 F2100\nG91\nG1 Z1 F7200\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7\nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3\nG1 E-15 F5000\nG1 E-50 F5400\nG1 E-15 F3000\nG1 E-12 F2000\nG1 F1600\nG1 X0 Y1 E3\nG1 X50 Y1 E-5\nG1 F2000\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-5\nG1 F2400\nG1 X0 Y1 E5\nG1 X50 Y1 E-3\nG4 S0\n{endif}\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+50, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors
extruder_colour = #FFAA55;#E37BA0;#4ECDD3;#FB7259
nozzle_diameter = 0.4,0.4,0.4,0.4
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
@ -8364,21 +8519,21 @@ inherits = Original Prusa i3 MK2S
printer_model = MK2.5
remaining_times = 1
machine_max_jerk_e = 4.5
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
inherits = Original Prusa i3 MK2S 0.25 nozzle
printer_model = MK2.5
remaining_times = 1
machine_max_jerk_e = 4.5
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
inherits = Original Prusa i3 MK2S 0.6 nozzle
printer_model = MK2.5
remaining_times = 1
machine_max_jerk_e = 4.5
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
[printer:Original Prusa i3 MK2.5 0.8 nozzle]
inherits = Original Prusa i3 MK2S 0.6 nozzle
@ -8390,7 +8545,7 @@ min_layer_height = 0.2
retract_length = 1
remaining_times = 1
machine_max_jerk_e = 4.5
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0
default_print_profile = 0.40mm QUALITY @0.8 nozzle
default_filament_profile = Prusament PLA @0.8 nozzle
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
@ -8403,8 +8558,8 @@ max_print_height = 200
default_print_profile = 0.15mm OPTIMAL @MK2.5
default_filament_profile = Prusament PLA
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; load to nozzle\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.20 F1000\nG1 X5 E4 F1000\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\n; select extruder\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; load to nozzle\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.20 F1000\nG1 X5 E4 F1000\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
[printer:Original Prusa i3 MK2.5 MMU2 Single 0.8 nozzle]
inherits = Original Prusa i3 MK2.5S MMU2S Single 0.8 nozzle
@ -8427,8 +8582,8 @@ printer_notes = Don't remove the following keywords! These keywords are used in
single_extruder_multi_material = 1
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors\n
[printer:Original Prusa i3 MK2.5S]
inherits = Original Prusa i3 MK2.5
@ -8454,8 +8609,8 @@ max_print_height = 200
default_print_profile = 0.15mm OPTIMAL @MK2.5
default_filament_profile = Prusament PLA
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors
[printer:Original Prusa i3 MK2.5S MMU2S Single 0.8 nozzle]
inherits = Original Prusa i3 MK2.5S MMU2S Single
@ -8465,7 +8620,7 @@ min_layer_height = 0.2
nozzle_diameter = 0.8
printer_variant = 0.8
retract_length = 1
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
default_print_profile = 0.40mm QUALITY @0.8 nozzle
default_filament_profile = Prusament PLA @0.8 nozzle
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
@ -8489,7 +8644,7 @@ nozzle_diameter = 0.25
printer_variant = 0.25
retract_lift = 0.15
default_print_profile = 0.10mm DETAIL 0.25 nozzle
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
[printer:Original Prusa i3 MK2.5S MMU2S]
@ -8501,8 +8656,8 @@ printer_notes = Don't remove the following keywords! These keywords are used in
single_extruder_multi_material = 1
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM900 K0 ; reset LA\nM84 ; disable motors\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\nG92 E0\n
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM900 K0 ; reset LA\nM84 ; disable motors\n
[printer:Original Prusa i3 MK2.5S MMU2S 0.6 nozzle]
inherits = Original Prusa i3 MK2.5S MMU2S
@ -8522,6 +8677,26 @@ printer_variant = 0.6
default_print_profile = 0.20mm NORMAL @0.6 nozzle
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
[printer:Original Prusa i3 MK2.5S MMU2S 0.25 nozzle]
inherits = Original Prusa i3 MK2.5S MMU2S
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
default_print_profile = 0.10mm DETAIL @0.25 nozzle
default_filament_profile = Prusament PLA @MMU2 0.25
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
[printer:Original Prusa i3 MK2.5 MMU2 0.25 nozzle]
inherits = Original Prusa i3 MK2.5 MMU2
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
default_print_profile = 0.10mm DETAIL @0.25 nozzle
default_filament_profile = Prusament PLA @MMU2 0.25
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
## 0.8mm nozzle profiles are only available for MMU2 Single mode at the moment.
## [printer:Original Prusa i3 MK2.5S MMU2S 0.8 nozzle]
@ -8532,7 +8707,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
## printer_variant = 0.8
## retract_length = 1
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
## [printer:Original Prusa i3 MK2.5 MMU2 0.8 nozzle]
## inherits = Original Prusa i3 MK2.5 MMU2
@ -8542,7 +8717,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
## printer_variant = 0.8
## retract_length = 1
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG92 E0.0\n
# XXXXXXXXXXXXXXXXX
# XXX--- MK3 ---XXX
@ -8550,7 +8725,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
[printer:Original Prusa i3 MK3]
inherits = *common*
end_gcode = G4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y200 F3600 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM84 ; disable motors
machine_max_acceleration_e = 5000,5000
machine_max_acceleration_extruding = 1250,1250
machine_max_acceleration_retracting = 1250,1250
@ -8572,9 +8747,10 @@ remaining_times = 1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
retract_lift_below = 209
max_print_height = 210
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
printer_model = MK3
default_print_profile = 0.15mm QUALITY @MK3
thumbnails = 160x120
[printer:Original Prusa i3 MK3 0.25 nozzle]
inherits = Original Prusa i3 MK3
@ -8583,7 +8759,7 @@ max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
retract_lift = 0.15
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E8 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E8 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
@ -8593,7 +8769,7 @@ nozzle_diameter = 0.6
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
@ -8604,7 +8780,7 @@ max_layer_height = 0.6
min_layer_height = 0.2
printer_variant = 0.8
retract_length = 1
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S95
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\nG92 E0\nM221 S95
default_print_profile = 0.40mm QUALITY @0.8 nozzle
default_filament_profile = Prusament PLA @0.8 nozzle
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
@ -8676,8 +8852,8 @@ default_filament_profile = Prusament PLA @MMU2
inherits = *mm2*
single_extruder_multi_material = 0
default_filament_profile = Prusament PLA
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
[printer:Original Prusa i3 MK3 MMU2 Single 0.6 nozzle]
inherits = Original Prusa i3 MK3 MMU2 Single
@ -8686,7 +8862,7 @@ nozzle_diameter = 0.6
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
@ -8698,7 +8874,7 @@ max_layer_height = 0.6
min_layer_height = 0.2
printer_variant = 0.8
retract_length = 1
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.40mm QUALITY @0.8 nozzle
default_filament_profile = Prusament PLA @0.8 nozzle
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
@ -8711,7 +8887,7 @@ max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
retract_lift = 0.15
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F1000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 E8 F1000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
@ -8720,16 +8896,16 @@ inherits = *mm2*
machine_max_acceleration_e = 8000,8000
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM84 ; disable motors\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors\n
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S Single]
inherits = *mm2s*
renamed_from = "Original Prusa i3 MK3S MMU2S Single"
single_extruder_multi_material = 0
default_filament_profile = Prusament PLA
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+10, max_print_height)}{endif} F720 ; Move print head up\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM702 C\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S Single 0.6 nozzle]
inherits = Original Prusa i3 MK3S & MK3S+ MMU2S Single
@ -8739,7 +8915,7 @@ nozzle_diameter = 0.6
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
@ -8751,7 +8927,7 @@ max_layer_height = 0.6
min_layer_height = 0.2
printer_variant = 0.8
retract_length = 1
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.40mm QUALITY @0.8 nozzle
default_filament_profile = Prusament PLA @0.8 nozzle
color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change
@ -8765,7 +8941,7 @@ max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
retract_lift = 0.15
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nTc\n; purge line\nG1 X55 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F1400\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E value below. Excessive value can damage the printer.\n{if print_settings_id=~/.*@0.25 nozzle MK3.*/}M907 E430 ; set extruder motor current{endif}
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
@ -8775,8 +8951,8 @@ renamed_from = "Original Prusa i3 MK3S MMU2S"
machine_max_acceleration_e = 8000,8000
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
extruder_colour = #FF8000;#DB5182;#3EC0FF;#FF4F4F;#FBEB7D
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = ; Lift print head a bit\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; Move print head up\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nG1 X0 Y210 F3000 ; home X axis\nM84 ; disable motors\n
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y210 F7200 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\n{if has_wipe_tower}\nG1 E-15 F3000\n{else}\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15 F5800\nG1 E-20 F5500\nG1 E10 F3000\nG1 E-10 F3100\nG1 E10 F3150\nG1 E-10 F3250\nG1 E10 F3300\n{endif}\n\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|SOLUBLE|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM84 ; disable motors\n
## 0.6mm nozzle MMU2/S printer profiles
@ -8787,7 +8963,7 @@ nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E29 F1073\nG1 X5 E29 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
@ -8797,10 +8973,30 @@ nozzle_diameter = 0.6,0.6,0.6,0.6,0.6
max_layer_height = 0.40
min_layer_height = 0.15
printer_variant = 0.6
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55 E32 F1073\nG1 X5 E32 F1800\nG1 X55 E8 F2000\nG1 Z0.3 F1000\nG92 E0\nG1 X240 E25 F2200\nG1 Y-2 F1000\nG1 X55 E25 F1400\nG1 Z0.2 F1000\nG1 X5 E4 F1000\nG92 E0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0
default_print_profile = 0.30mm QUALITY @0.6 nozzle MK3
color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
[printer:Original Prusa i3 MK3S & MK3S+ MMU2S 0.25 nozzle]
inherits = Original Prusa i3 MK3S & MK3S+ MMU2S 0.6 nozzle
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
default_filament_profile = Prusament PLA @MMU2 0.25
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
[printer:Original Prusa i3 MK3 MMU2 0.25 nozzle]
inherits = Original Prusa i3 MK3 MMU2 0.6 nozzle
nozzle_diameter = 0.25,0.25,0.25,0.25,0.25
max_layer_height = 0.15
min_layer_height = 0.05
printer_variant = 0.25
default_print_profile = 0.10mm DETAIL @0.25 nozzle MK3
default_filament_profile = Prusament PLA @MMU2 0.25
color_change_gcode = M600\nG1 E0.3 F1500 ; prime after color change
## 0.8mm nozzle MMU2/S printer profiles
## For later use. 0.8mm nozzle profiles are only available for MMU2 Single mode at the moment.
@ -8811,7 +9007,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
## max_layer_height = 0.6
## min_layer_height = 0.2
## printer_variant = 0.8
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000\nG1 Z0.4 F1000\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
## [printer:Original Prusa i3 MK3S & MK3S+ MMU2S 0.8 nozzle]
@ -8820,7 +9016,7 @@ color_change_gcode = M600\nG1 E0.5 F1500 ; prime after color change
## max_layer_height = 0.6
## min_layer_height = 0.2
## printer_variant = 0.8
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.10.1 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
## start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.11.0 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG92 E0.0
## default_print_profile = 0.40mm QUALITY @0.8 nozzle
## MINI

View File

@ -1,3 +1,6 @@
min_slic3r_version = 2.4.1-rc1
1.0.1 Fix missing AzteQ Industrial ABS material for 0.6, 0.8 nozzle, enabled elefant foot compensation
1.0.0 Added AzteQ Industrial profiles for 0.8 nozzle, updated spool weight and filament cost, some minor setting improvements
min_slic3r_version = 2.3.2-alpha0
0.0.9 Added AzteQ Industrial materials PC/ABS (Fillamentum), PC-Max (Polymaker), Nylon FX256 (Fillamentum), Added DeltiQ 2 materials Nylon PA12 (Fiberlogy), Nylon CF15 Carbon (Fillamentum), PEBA 90A - FlexFill (Fillamentum), MoldLay (Wax-Alike), disabled retract only when crossing perimeters, some minor setting improvements
0.0.8 Added new AzteQ Industrial printer, added DeltiQ 2 profiles for 0.6mm nozzle, added material ASA 275 (Spectrum), some minor setting improvements

View File

@ -6,7 +6,7 @@
name = TriLAB
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.9
config_version = 1.0.1
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
@ -17,12 +17,12 @@ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/Prus
[printer_model:AQI]
name = AzteQ Industrial
variants = 0.4; 0.6
variants = 0.4; 0.6; 0.8
technology = FFF
family = AzteQ
bed_model = aq_bed.stl
bed_texture = aq_bed_texture.svg
default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle
default_materials = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum);AzteQ Industrial (Door Opened) - PLA - Generic;AzteQ Industrial (PLA Printhead) - PLA - ExtraFill (Fillamentum);AzteQ Industrial - ABS - ExtraFill (Fillamentum);AzteQ Industrial - ABS - Generic;AzteQ Industrial - ASA - ExtraFill (Fillamentum);AzteQ Industrial - ASA - Generic;AzteQ Industrial - ASA - Prusament (Prusa);AzteQ Industrial - PA - Nylon PA12 (Fiberlogy);AzteQ Industrial - PC Blend - Prusament (Prusa);AzteQ Industrial - PC - PolyMax (Polymaker);AzteQ Industrial - PC - PolyMax (Polymaker) @0.6 nozzle;AzteQ Industrial - PC/ABS - (Fillamentum);AzteQ Industrial - PC/ABS - (Fillamentum) @0.6 nozzle;AzteQ Industrial - PA - Nylon FX256 (Fillamentum);AzteQ Industrial - PA - Nylon FX256 (Fillamentum) @0.6 nozzle;AzteQ Industrial - ABS - Generic @0.8 nozzle;AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle;AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle;AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle
[printer_model:DQ2]
name = DeltiQ 2
@ -118,7 +118,7 @@ complete_objects = 0
default_acceleration = 2000
dont_support_bridges = 0
draft_shield = 0
elefant_foot_compensation = 0.0
elefant_foot_compensation = 0.1
ensure_vertical_shell_thickness = 0
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 30
@ -338,6 +338,7 @@ support_material_extrusion_width = 0.55
support_material_interface_spacing = 0.6
support_material_xy_spacing = 0.9
top_infill_extrusion_width = 0.6
elefant_foot_compensation = 0.2
[print:DeltiQ 0.30mm Strong @0.6 nozzle]
inherits = DeltiQ 0.30mm Normal @0.6 nozzle
@ -356,7 +357,7 @@ bottom_solid_min_thickness = 1.2
bridge_flow_ratio = 0.90
bridge_speed = 20
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and nozzle_diameter[0]==0.8
elefant_foot_compensation = 0.0
elefant_foot_compensation = 0.2
external_perimeter_extrusion_width = 0.80
external_perimeter_speed = 30
extrusion_width = 0.80
@ -415,7 +416,7 @@ complete_objects = 0
default_acceleration = 2000
dont_support_bridges = 0
draft_shield = 0
elefant_foot_compensation = 0
elefant_foot_compensation = 0.1
ensure_vertical_shell_thickness = 0
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 30
@ -558,6 +559,7 @@ support_material_extrusion_width = 0.55
support_material_interface_spacing = 0.6
support_material_xy_spacing = 0.9
top_infill_extrusion_width = 0.6
elefant_foot_compensation = 0.2
[print:AzteQ Industrial 0.30mm Strong @0.6 nozzle]
inherits = AzteQ Industrial 0.30mm Normal @0.6 nozzle
@ -569,6 +571,106 @@ inherits = AzteQ Industrial 0.30mm Normal @0.6 nozzle
fill_density = 10%
layer_height = 0.35
[print:AzteQ Industrial 0.40mm Normal @0.8 nozzle]
inherits = AzteQ Industrial 0.20mm Normal
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
avoid_crossing_perimeters = 0
avoid_crossing_perimeters_max_detour = 0
bottom_solid_layers = 4
bottom_solid_min_thickness = 0.7
bridge_flow_ratio = 0.95
bridge_speed = 30
dont_support_bridges = 0
elefant_foot_compensation = 0.2
ensure_vertical_shell_thickness = 0
external_perimeter_extrusion_width = 0.8
external_perimeter_speed = 30
external_perimeters_first = 0
extra_perimeters = 0
extrusion_width = 0.8
fill_angle = 45
fill_density = 20%
fill_pattern = grid
first_layer_extrusion_width = 0.8
first_layer_height = 0.4
first_layer_speed = 20
first_layer_speed_over_raft = 30
gap_fill_enabled = 1
gap_fill_speed = 40
infill_extrusion_width = 0.8
infill_first = 0
infill_overlap = 25%
infill_speed = 60
layer_height = 0.4
max_print_speed = 60
max_volumetric_speed = 0
only_retract_when_crossing_perimeters = 1
overhangs = 1
perimeter_extruder = 1
perimeter_extrusion_width = 0.8
perimeter_speed = 45
perimeters = 2
raft_contact_distance = 0.1
raft_expansion = 1.5
raft_first_layer_density = 90%
raft_first_layer_expansion = 3
raft_layers = 0
skirt_distance = 10
skirt_height = 2
skirts = 1
small_perimeter_speed = 20
solid_infill_below_area = 70
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width = 0.8
solid_infill_speed = 60
support_material = 0
support_material_angle = 30
support_material_auto = 1
support_material_bottom_contact_distance = 0
support_material_bottom_interface_layers = -1
support_material_buildplate_only = 0
support_material_closing_radius = 2
support_material_contact_distance = 0.1
support_material_enforce_layers = 0
support_material_extruder = 0
support_material_extrusion_width = 0.8
support_material_interface_contact_loops = 0
support_material_interface_extruder = 0
support_material_interface_layers = 4
support_material_interface_pattern = auto
support_material_interface_spacing = 0.4
support_material_interface_speed = 100%
support_material_pattern = rectilinear
support_material_spacing = 2
support_material_speed = 50
support_material_style = grid
support_material_synchronize_layers = 0
support_material_threshold = 40
support_material_with_sheath = 0
support_material_xy_spacing = 0.6
thick_bridges = 1
thin_walls = 0
threads = 12
top_fill_pattern = monotonic
top_infill_extrusion_width = 0.8
top_solid_infill_speed = 40
top_solid_layers = 5
top_solid_min_thickness = 0.7
travel_speed = 200
travel_speed_z = 0
[print:AzteQ Industrial 0.40mm Vase @0.8 nozzle]
inherits = AzteQ Industrial 0.40mm Normal @0.8 nozzle
bottom_solid_layers = 4
perimeters = 1
top_solid_layers = 0
fill_density = 0
support_material = 0
spiral_vase = 1
ensure_vertical_shell_thickness = 1
thin_walls = 0
# DeltiQ filaments #
[filament:*DeltiQ common*]
@ -586,6 +688,8 @@ filament_soluble = 0
filament_toolchange_delay = 0
start_filament_gcode = "; FILAMENT_START_GCODE"
end_filament_gcode = "; FILAMENT_END_GCODE"
filament_cost = 0
filament_spool_weight = 250
filament_vendor = Generic
# DeltiQ PLA filaments #
@ -597,7 +701,6 @@ bridge_fan_speed = 100
cooling = 1
fan_always_on = 1
fan_below_layer_time = 100
filament_cost = 750
filament_density = 1.24
filament_max_volumetric_speed = 8
filament_retract_before_travel = 2
@ -618,7 +721,8 @@ temperature = 215
[filament:DeltiQ - PLA - ExtraFill (Fillamentum)]
inherits = DeltiQ - PLA - Generic
filament_cost = 750
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.24
filament_vendor = Fillamentum
@ -652,6 +756,10 @@ filament_retract_speed = 28
[filament:DeltiQ FP - PLA - ExtraFill (Fillamentum)]
inherits = DeltiQ FP - PLA - Generic
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.24
filament_vendor = Fillamentum
[filament:DeltiQ FP2 - PLA - Generic]
inherits = DeltiQ FP - PLA - Generic
@ -661,6 +769,10 @@ filament_retract_speed = 28
[filament:DeltiQ FP2 - PLA - ExtraFill (Fillamentum)]
inherits = DeltiQ FP2 - PLA - Generic
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.24
filament_vendor = Fillamentum
# DeltiQ PETG filaments #
@ -671,7 +783,6 @@ bridge_fan_speed = 50
cooling = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 480
filament_density = 1.27
filament_deretract_speed = 25
filament_max_volumetric_speed = 8
@ -693,7 +804,8 @@ temperature = 245
[filament:DeltiQ - PETG (Devil Design)]
inherits = DeltiQ - PETG - Generic
filament_cost = 480
filament_cost = 16.53
filament_spool_weight = 247
filament_density = 1.27
filament_vendor = DevilDesign
@ -733,6 +845,10 @@ filament_retract_speed = 25
[filament:DeltiQ FP - PETG (Devil Design)]
inherits = DeltiQ FP - PETG - Generic
filament_cost = 16.53
filament_spool_weight = 247
filament_density = 1.27
filament_vendor = DevilDesign
[filament:DeltiQ FP2 - PETG - Generic]
inherits = DeltiQ FP - PETG - Generic
@ -743,6 +859,10 @@ filament_retract_before_wipe = 0%
[filament:DeltiQ FP2 - PETG (Devil Design)]
inherits = DeltiQ FP2 - PETG - Generic
filament_cost = 16.53
filament_spool_weight = 247
filament_density = 1.27
filament_vendor = DevilDesign
# DeltiQ ABS filaments #
@ -753,7 +873,6 @@ bridge_fan_speed = 25
cooling = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 639
filament_density = 1.04
filament_max_volumetric_speed = 8
filament_retract_before_travel = 3
@ -774,7 +893,8 @@ temperature = 255
[filament:DeltiQ - ABS - ExtraFill (Fillamentum)]
inherits = DeltiQ - ABS - Generic
filament_cost = 639
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.04
filament_vendor = Fillamentum
@ -791,6 +911,10 @@ filament_retract_speed = 25
[filament:DeltiQ FP - ABS - ExtraFill (Fillamentum)]
inherits = DeltiQ FP - ABS - Generic
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.04
filament_vendor = Fillamentum
[filament:DeltiQ FP2 - ABS - Generic]
inherits = DeltiQ FP - ABS - Generic
@ -800,12 +924,18 @@ filament_retract_speed = 25
[filament:DeltiQ FP2 - ABS - ExtraFill (Fillamentum)]
inherits = DeltiQ FP2 - ABS - Generic
filament_cost = 24.27
filament_spool_weight = 229
filament_density = 1.04
filament_vendor = Fillamentum
# DeltiQ ASA filaments #
[filament:DeltiQ - ASA - ExtraFill (Fillamentum)]
inherits = DeltiQ - ABS - Generic
filament_cost = 739
filament_cost = 29.53
filament_spool_weight = 229
filament_density = 1.07
filament_type = ASA
filament_vendor = Fillamentum
@ -827,6 +957,7 @@ filament_retract_speed = 25
inherits = DeltiQ FP - ASA - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and printer_notes=~/.*FLEXPRINT2.*/ and nozzle_diameter[0]==0.4
[filament:DeltiQ - ASA - ASA 275 (Spectrum)]
inherits = *DeltiQ common*
bed_temperature = 55
@ -835,7 +966,7 @@ cooling = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_vendor = Spectrum
filament_cost = 587
filament_cost = 29.86
filament_density = 1.07
filament_max_volumetric_speed = 8
filament_retract_before_travel = 3
@ -859,6 +990,7 @@ inherits = DeltiQ - ASA - ASA 275 (Spectrum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_DQ.*/ and !(printer_notes=~/.*FLEXPRINT.*/) and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
# DeltiQ CPE filaments #
[filament:DeltiQ - CPE - HG100 (Fillamentum)]
@ -869,7 +1001,8 @@ cooling = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_vendor = Fillamentum
filament_cost = 1003
filament_cost = 39.07
filament_spool_weight = 229
filament_density = 1.25
filament_deretract_speed = 25
filament_max_volumetric_speed = 8
@ -910,6 +1043,7 @@ filament_retract_speed = 35
filament_deretract_speed = 0
filament_retract_before_wipe = 0%
# DeltiQ FLEX filaments #
[filament:DeltiQ FP - FLEX - Generic]
@ -922,8 +1056,6 @@ disable_fan_first_layers = 1
extrusion_multiplier = 1.07
fan_always_on = 1
fan_below_layer_time = 20
filament_vendor = Generic
filament_cost = 1870
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 3.0
@ -954,8 +1086,6 @@ disable_fan_first_layers = 1
extrusion_multiplier = 1.07
fan_always_on = 1
fan_below_layer_time = 20
filament_vendor = Fillamentum
filament_cost = 1870
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 3.0
@ -986,7 +1116,8 @@ extrusion_multiplier = 1.10
fan_always_on = 1
fan_below_layer_time = 20
filament_vendor = Fillamentum
filament_cost = 1870
filament_cost = 58.33
filament_spool_weight = 229
filament_density = 1.22
filament_deretract_speed = nil
filament_max_volumetric_speed = 3.0
@ -1010,7 +1141,8 @@ temperature = 230
[filament:DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)]
inherits = DeltiQ FP2 - TPU 92A - FlexFill (Fillamentum)
extrusion_multiplier = 1.10
filament_cost = 1870
filament_cost = 58.33
filament_spool_weight = 229
filament_density = 1.23
filament_deretract_speed = nil
filament_max_volumetric_speed = 3.0
@ -1029,7 +1161,8 @@ extrusion_multiplier = 1.00
fan_always_on = 1
fan_below_layer_time = 10
filament_vendor = Smartfil
filament_cost = 1209
filament_cost = 38.21
filament_spool_weight = 250
filament_density = 1.21
filament_deretract_speed = nil
filament_max_volumetric_speed = 2.5
@ -1053,7 +1186,8 @@ temperature = 235
[filament:DeltiQ FP2 - PEBA 90A - FlexFill (Fillamentum)]
inherits = DeltiQ FP2 - TPU 98A - FlexFill (Fillamentum)
extrusion_multiplier = 1.1
filament_cost = 3578
filament_cost = 139.67
filament_spool_weight = 229
filament_density = 1.00
filament_max_volumetric_speed = 2.9
filament_retract_length = 0.0
@ -1070,7 +1204,8 @@ temperature = 245
[filament:DeltiQ - PA - Nylon PA12 (Fiberlogy)]
inherits = DeltiQ - ABS - Generic
bed_temperature = 100
filament_cost = 1213
filament_cost = 45.11
filament_spool_weight = 230
filament_density = 1.02
filament_retract_length = 4.1
filament_type = NYLON
@ -1083,8 +1218,9 @@ temperature = 255
[filament:DeltiQ - PA - Nylon CF15 Carbon (Fillamentum)]
inherits = DeltiQ - ABS - Generic
bed_temperature = 100
filament_cost = 2287
filament_cost = 88.17
filament_density = 1.08
filament_spool_weight = 229
filament_retract_length = 2.0
filament_type = NYLON
first_layer_bed_temperature = 100
@ -1097,7 +1233,8 @@ extrusion_multiplier = 0.95
[filament:DeltiQ - MoldLay (Wax-Alike)]
inherits = DeltiQ - PLA - Generic
bed_temperature = 50
filament_cost = 1951
filament_cost = 79.07
filament_spool_weight = 230
filament_retract_length = 2.0
filament_type = PLA
first_layer_bed_temperature = 50
@ -1107,6 +1244,7 @@ min_fan_speed = 70
temperature = 175
filament_vendor = Wax-Alike
# AzteQ filaments #
[filament:*AzteQ common*]
@ -1124,7 +1262,6 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 750
filament_density = 1.24
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
@ -1161,8 +1298,9 @@ filament_max_volumetric_speed = 15
[filament:AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum)]
inherits = AzteQ Industrial (Door Opened) - PLA - Generic
filament_vendor = Fillamentum
filament_cost = 750
filament_cost = 24.27
filament_density = 1.24
filament_spool_weight = 229
[filament:AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum) @0.6 nozzle]
inherits = AzteQ Industrial (Door Opened) - PLA - ExtraFill (Fillamentum)
@ -1178,8 +1316,9 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 750
filament_cost = 24.27
filament_density = 1.24
filament_spool_weight = 229
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
filament_retract_before_travel = 3
@ -1192,7 +1331,6 @@ filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_toolchange_delay = 0
filament_type = PLA
filament_vendor = Fillamentum
@ -1221,7 +1359,6 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 639
filament_density = 1.04
filament_deretract_speed = nil
filament_load_time = 0
@ -1240,7 +1377,6 @@ filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_type = ABS
filament_vendor = Generic
filament_wipe = 1
first_layer_bed_temperature = 100
first_layer_temperature = 255
@ -1257,22 +1393,41 @@ inherits = AzteQ Industrial - ABS - Generic
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - ABS - Generic @0.8 nozzle]
inherits = AzteQ Industrial - ABS - Generic
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
first_layer_temperature = 255
first_layer_bed_temperature = 100
temperature = 255
bed_temperature = 100
max_fan_speed = 80
min_fan_speed = 50
filament_retract_length = 6.1
filament_max_volumetric_speed = 0
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum)]
inherits = AzteQ Industrial - ABS - Generic
filament_vendor = Fillamentum
filament_cost = 639
filament_cost = 24.27
filament_density = 1.04
filament_spool_weight = 229
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle]
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle]
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
extrusion_multiplier = 0.95
[filament:AzteQ Industrial - PC/ABS - (Fillamentum)]
inherits = AzteQ Industrial - ABS - Generic
filament_vendor = Fillamentum
filament_type = PCABS
filament_cost = 1324
filament_cost = 53.71
filament_spool_weight = 229
filament_density = 1.07
bed_temperature = 100
filament_retract_length = 4.0
@ -1292,7 +1447,8 @@ filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - PC - PolyMax (Polymaker)]
inherits = AzteQ Industrial - ABS - Generic
filament_vendor = Polymaker
filament_cost = 1290
filament_spool_weight = 230
filament_cost = 52.40
filament_density = 1.21
bed_temperature = 100
filament_retract_length = 4.0
@ -1318,7 +1474,6 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 739
filament_density = 1.07
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
@ -1334,7 +1489,6 @@ filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_type = ASA
filament_vendor = Generic
filament_wipe = 1
first_layer_bed_temperature = 100
first_layer_temperature = 265
@ -1358,17 +1512,34 @@ first_layer_temperature = 255
temperature = 255
max_fan_speed = 80
min_fan_speed = 60
filament_spool_weight = 229
filament_cost = 29.53
filament_density = 1.07
[filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.6 nozzle]
inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - ASA - ExtraFill (Fillamentum) @0.8 nozzle]
inherits = AzteQ Industrial - ASA - ExtraFill (Fillamentum)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
first_layer_bed_temperature = 100
bed_temperature = 100
first_layer_temperature = 250
temperature = 250
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S50 ; Set and wait - chamber temperature"
max_fan_speed = 100
min_fan_speed = 80
filament_retract_length = 6.1
filament_max_volumetric_speed = 0
[filament:AzteQ Industrial - ASA - Prusament (Prusa)]
inherits = AzteQ Industrial - ASA - Generic
filament_cost = 680
filament_cost = 29.16
filament_density = 1.07
filament_spool_weight = 0
filament_spool_weight = 201
filament_vendor = Prusa
first_layer_temperature = 260
max_fan_speed = 70
@ -1381,6 +1552,20 @@ inherits = AzteQ Industrial - ASA - Prusament (Prusa)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - ASA - Prusament (Prusa) @0.8 nozzle]
inherits = AzteQ Industrial - ASA - Prusament (Prusa)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
first_layer_bed_temperature = 100
bed_temperature = 100
first_layer_temperature = 250
temperature = 250
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
max_fan_speed = 80
min_fan_speed = 50
filament_retract_length = 4.1
filament_max_volumetric_speed = 0
[filament:AzteQ Industrial - PA - Nylon PA12 (Fiberlogy)]
inherits = *AzteQ common*
bed_temperature = 100
@ -1390,7 +1575,8 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 1212
filament_cost = 45.11
filament_spool_weight = 230
filament_density = 1.02
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
@ -1404,7 +1590,6 @@ filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_toolchange_delay = 0
filament_type = NYLON
filament_unload_time = 0
@ -1436,7 +1621,8 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 1565
filament_cost = 57.32
filament_spool_weight = 229
filament_density = 1.01
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
@ -1450,7 +1636,6 @@ filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_toolchange_delay = 0
filament_type = NYLON
filament_unload_time = 0
@ -1482,8 +1667,9 @@ disable_fan_first_layers = 3
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 20
filament_cost = 1156
filament_cost = 61.98
filament_density = 1.22
filament_spool_weight = 201
filament_deretract_speed = nil
filament_max_volumetric_speed = 8
filament_retract_before_travel = 3
@ -1496,7 +1682,6 @@ filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = 25
filament_soluble = 0
filament_spool_weight = 0
filament_type = PC
filament_vendor = Prusa
filament_wipe = 1
@ -1516,6 +1701,18 @@ inherits = AzteQ Industrial - PC Blend - Prusament (Prusa)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
filament_max_volumetric_speed = 15
[filament:AzteQ Industrial - PC Blend - Prusament (Prusa) @0.8 nozzle]
inherits = AzteQ Industrial - PC Blend - Prusament (Prusa)
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
first_layer_bed_temperature = 100
bed_temperature = 100
first_layer_temperature = 275
temperature = 275
start_filament_gcode = "; FILAMENT_START_GCODE\nM191 S75 ; Set and wait - chamber temperature"
max_fan_speed = 60
min_fan_speed = 60
filament_retract_length = 7.1
filament_max_volumetric_speed = 0
# DeltiQ Printer #
@ -1752,6 +1949,15 @@ nozzle_diameter = 0.6
default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle"
default_print_profile = AzteQ Industrial 0.30mm Normal @0.6 nozzle
[printer:AzteQ Industrial - 0.8 nozzle]
inherits = AzteQ Industrial
printer_variant = 0.8
max_layer_height = 0.6
min_layer_height = 0.2
nozzle_diameter = 0.8
default_filament_profile = "AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle"
default_print_profile = AzteQ Industrial 0.40mm Normal @0.8 nozzle
[presets]
print = DeltiQ 0.20mm Normal
printer = DeltiQ 2

View File

@ -1,2 +1,4 @@
min_slic3r_version = 2.4.2
1.0.1 Added 350mm Voron v1 variant. Updated max print heights. Removed redundant v1 volcano nozzle variants.
min_slic3r_version = 2.4.0-beta0
1.0.0 Initial version

View File

@ -7,7 +7,7 @@
name = Voron
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 1.0.0
config_version = 1.0.1
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Voron/
@ -72,21 +72,30 @@ default_materials = Basic PLA @VORON; Basic PLA VOLCANO @VORON; Basic PET @VORON
[printer_model:Voron_v1_250_afterburner]
name = Voron v1 250mm3
variants = 0.4; 0.25; 0.3; 0.5; 0.6; 0.8; volcano 0.6; volcano 0.8; volcano 1.0; volcano 1.2
variants = 0.4; 0.25; 0.3; 0.5; 0.6; 0.8
technology = FFF
family = Voron v1 Afterburner
bed_model = printbed-v1-250.stl
bed_texture = bedtexture-v1-250.png
default_materials = Basic PLA @VORON; Basic PLA VOLCANO @VORON; Basic PET @VORON; Basic PET VOLCANO @VORON; Basic ABS @VORON; Basic ABS VOLCANO @VORON
default_materials = Basic PLA @VORON; Basic PET @VORON; Basic ABS @VORON
[printer_model:Voron_v1_300_afterburner]
name = Voron v1 300mm3
variants = 0.4; 0.25; 0.3; 0.5; 0.6; 0.8; volcano 0.6; volcano 0.8; volcano 1.0; volcano 1.2
variants = 0.4; 0.25; 0.3; 0.5; 0.6; 0.8
technology = FFF
family = Voron v1 Afterburner
bed_model = printbed-v1-300.stl
bed_texture = bedtexture-v1-300.png
default_materials = Basic PLA @VORON; Basic PLA VOLCANO @VORON; Basic PET @VORON; Basic PET VOLCANO @VORON; Basic ABS @VORON; Basic ABS VOLCANO @VORON
default_materials = Basic PLA @VORON; Basic PET @VORON; Basic ABS @VORON
[printer_model:Voron_v1_350_afterburner]
name = Voron v1 350mm3
variants = 0.4; 0.25; 0.3; 0.5; 0.6; 0.8
technology = FFF
family = Voron v1 Afterburner
bed_model = printbed-v1-350.stl
bed_texture = bedtexture-v2-350.png
default_materials = Basic PLA @VORON; Basic PET @VORON; Basic ABS @VORON
[printer_model:Voron_v0_120]
name = Voron Zero 120mm3
@ -239,21 +248,21 @@ retract_speed = 50
[printer:*Voron_v2_250*]
inherits = *common*
bed_shape = 0x0,250x0,250x250,0x250
max_print_height = 250
max_print_height = 230
printer_model = Voron_v2_250
printer_notes = Unoffical profile.\nPRINTER_HAS_BOWDEN\nE3DV6
[printer:*Voron_v2_300*]
inherits = *common*
bed_shape = 0x0,300x0,300x300,0x300
max_print_height = 300
max_print_height = 280
printer_model = Voron_v2_300
printer_notes = Unoffical profile.\nPRINTER_HAS_BOWDEN\nE3DV6
[printer:*Voron_v2_350*]
inherits = *common*
bed_shape = 0x0,350x0,350x350,0x350
max_print_height = 350
max_print_height = 330
printer_model = Voron_v2_350
printer_notes = Unoffical profile.\nPRINTER_HAS_BOWDEN\nE3DV6
@ -282,10 +291,17 @@ printer_notes = Unoffical profile.\nE3DV6
[printer:*Voron_v1_300_afterburner*]
inherits = *common*; *afterburner*
bed_shape = 0x0,300x0,300x300,0x300
max_print_height = 230
max_print_height = 280
printer_model = Voron_v1_300_afterburner
printer_notes = Unoffical profile.\nE3DV6
[printer:*Voron_v1_350_afterburner*]
inherits = *common*; *afterburner*
bed_shape = 0x0,350x0,350x350,0x350
max_print_height = 330
printer_model = Voron_v1_350_afterburner
printer_notes = Unoffical profile.\nE3DV6
[printer:*Voron_v0_120*]
inherits = *common*
bed_shape = 0x0,120x0,120x120,0x120
@ -455,6 +471,24 @@ inherits = *Voron_v1_300_afterburner*; *0.6nozzle*
[printer:Voron_v1_300_afterburner 0.8 nozzle]
inherits = *Voron_v1_300_afterburner*; *0.8nozzle*
[printer:Voron_v1_350_afterburner 0.25 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.25nozzle*
[printer:Voron_v1_350_afterburner 0.3 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.3nozzle*
[printer:Voron_v1_350_afterburner 0.4 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.4nozzle*
[printer:Voron_v1_350_afterburner 0.5 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.5nozzle*
[printer:Voron_v1_350_afterburner 0.6 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.6nozzle*
[printer:Voron_v1_350_afterburner 0.8 nozzle]
inherits = *Voron_v1_350_afterburner*; *0.8nozzle*
[printer:Voron_v2_250_afterburner 0.25 nozzle]
inherits = *Voron_v2_250_afterburner*; *0.25nozzle*
@ -652,7 +686,7 @@ fill_angle = 45
fill_density = 15%
fill_pattern = gyroid
first_layer_acceleration = 1000
first_layer_height = 75%
first_layer_height = 0.2
first_layer_speed = 30
gap_fill_speed = 40
gcode_comments = 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

View File

@ -92,7 +92,7 @@ if (SLIC3R_GUI)
string(REGEX MATCH "wxexpat" WX_EXPAT_BUILTIN ${wxWidgets_LIBRARIES})
if (EXPAT_FOUND AND NOT WX_EXPAT_BUILTIN)
list(FILTER wxWidgets_LIBRARIES EXCLUDE REGEX expat)
list(APPEND wxWidgets_LIBRARIES EXPAT::EXPAT)
list(APPEND wxWidgets_LIBRARIES libexpat)
endif ()
# This is an issue in the new wxWidgets cmake build, doesn't deal with librt

View File

@ -837,6 +837,9 @@ extern "C" {
"leak:libnvidia-tls.so\n" // For NVidia driver.
"leak:terminator_CreateDevice\n" // For Intel Vulkan drivers.
"leak:swrast_dri.so\n" // For Mesa 3D software driver.
"leak:amdgpu_dri.so\n" // For AMD driver.
"leak:libdrm_amdgpu.so\n" // For AMD driver.
"leak:libdbus-1.so\n" // For D-Bus library. Unsure if it is a leak or not.
;
}
}

View File

@ -9,7 +9,7 @@
bool write_to_pot(boost::filesystem::path path, const std::vector<std::pair<std::string, std::string>>& data)
{
boost::filesystem::ofstream file(std::move(path), std::ios_base::app);
boost::nowide::ofstream file(path.string(), std::ios_base::app);
for (const auto& element : data)
{
//Example of .pot element

View File

@ -446,6 +446,57 @@ namespace detail {
}
}
// Real-time collision detection, Ericson, Chapter 5
template<typename Vector>
static inline Vector closest_point_to_triangle(const Vector &p, const Vector &a, const Vector &b, const Vector &c)
{
using Scalar = typename Vector::Scalar;
// Check if P in vertex region outside A
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
Scalar d1 = ab.dot(ap);
Scalar d2 = ac.dot(ap);
if (d1 <= 0 && d2 <= 0)
return a;
// Check if P in vertex region outside B
Vector bp = p - b;
Scalar d3 = ab.dot(bp);
Scalar d4 = ac.dot(bp);
if (d3 >= 0 && d4 <= d3)
return b;
// Check if P in edge region of AB, if so return projection of P onto AB
Scalar vc = d1*d4 - d3*d2;
if (a != b && vc <= 0 && d1 >= 0 && d3 <= 0) {
Scalar v = d1 / (d1 - d3);
return a + v * ab;
}
// Check if P in vertex region outside C
Vector cp = p - c;
Scalar d5 = ab.dot(cp);
Scalar d6 = ac.dot(cp);
if (d6 >= 0 && d5 <= d6)
return c;
// Check if P in edge region of AC, if so return projection of P onto AC
Scalar vb = d5*d2 - d1*d6;
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
Scalar w = d2 / (d2 - d6);
return a + w * ac;
}
// Check if P in edge region of BC, if so return projection of P onto BC
Scalar va = d3*d6 - d5*d4;
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
return b + w * (c - b);
}
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
Scalar denom = Scalar(1.0) / (va + vb + vc);
Scalar v = vb * denom;
Scalar w = vc * denom;
return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
};
// Nothing to do with COVID-19 social distancing.
template<typename AVertexType, typename AIndexedFaceType, typename ATreeType, typename AVectorType>
struct IndexedTriangleSetDistancer {
@ -453,74 +504,36 @@ namespace detail {
using IndexedFaceType = AIndexedFaceType;
using TreeType = ATreeType;
using VectorType = AVectorType;
using ScalarType = typename VectorType::Scalar;
const std::vector<VertexType> &vertices;
const std::vector<IndexedFaceType> &faces;
const TreeType &tree;
const VectorType origin;
inline VectorType closest_point_to_origin(size_t primitive_index,
ScalarType& squared_distance){
const auto &triangle = this->faces[primitive_index];
VectorType closest_point = closest_point_to_triangle<VectorType>(origin,
this->vertices[triangle(0)].template cast<ScalarType>(),
this->vertices[triangle(1)].template cast<ScalarType>(),
this->vertices[triangle(2)].template cast<ScalarType>());
squared_distance = (origin - closest_point).squaredNorm();
return closest_point;
}
};
// Real-time collision detection, Ericson, Chapter 5
template<typename Vector>
static inline Vector closest_point_to_triangle(const Vector &p, const Vector &a, const Vector &b, const Vector &c)
{
using Scalar = typename Vector::Scalar;
// Check if P in vertex region outside A
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
Scalar d1 = ab.dot(ap);
Scalar d2 = ac.dot(ap);
if (d1 <= 0 && d2 <= 0)
return a;
// Check if P in vertex region outside B
Vector bp = p - b;
Scalar d3 = ab.dot(bp);
Scalar d4 = ac.dot(bp);
if (d3 >= 0 && d4 <= d3)
return b;
// Check if P in edge region of AB, if so return projection of P onto AB
Scalar vc = d1*d4 - d3*d2;
if (a != b && vc <= 0 && d1 >= 0 && d3 <= 0) {
Scalar v = d1 / (d1 - d3);
return a + v * ab;
}
// Check if P in vertex region outside C
Vector cp = p - c;
Scalar d5 = ab.dot(cp);
Scalar d6 = ac.dot(cp);
if (d6 >= 0 && d5 <= d6)
return c;
// Check if P in edge region of AC, if so return projection of P onto AC
Scalar vb = d5*d2 - d1*d6;
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
Scalar w = d2 / (d2 - d6);
return a + w * ac;
}
// Check if P in edge region of BC, if so return projection of P onto BC
Scalar va = d3*d6 - d5*d4;
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
return b + w * (c - b);
}
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
Scalar denom = Scalar(1.0) / (va + vb + vc);
Scalar v = vb * denom;
Scalar w = vc * denom;
return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
};
template<typename IndexedTriangleSetDistancerType, typename Scalar>
static inline Scalar squared_distance_to_indexed_triangle_set_recursive(
IndexedTriangleSetDistancerType &distancer,
template<typename IndexedPrimitivesDistancerType, typename Scalar>
static inline Scalar squared_distance_to_indexed_primitives_recursive(
IndexedPrimitivesDistancerType &distancer,
size_t node_idx,
Scalar low_sqr_d,
Scalar up_sqr_d,
size_t &i,
Eigen::PlainObjectBase<typename IndexedTriangleSetDistancerType::VectorType> &c)
Eigen::PlainObjectBase<typename IndexedPrimitivesDistancerType::VectorType> &c)
{
using Vector = typename IndexedTriangleSetDistancerType::VectorType;
using Vector = typename IndexedPrimitivesDistancerType::VectorType;
if (low_sqr_d > up_sqr_d)
return low_sqr_d;
@ -538,13 +551,9 @@ namespace detail {
assert(node.is_valid());
if (node.is_leaf())
{
const auto &triangle = distancer.faces[node.idx];
Vector c_candidate = closest_point_to_triangle<Vector>(
distancer.origin,
distancer.vertices[triangle(0)].template cast<Scalar>(),
distancer.vertices[triangle(1)].template cast<Scalar>(),
distancer.vertices[triangle(2)].template cast<Scalar>());
set_min((c_candidate - distancer.origin).squaredNorm(), node.idx, c_candidate);
Scalar sqr_dist;
Vector c_candidate = distancer.closest_point_to_origin(node.idx, sqr_dist);
set_min(sqr_dist, node.idx, c_candidate);
}
else
{
@ -561,7 +570,7 @@ namespace detail {
{
size_t i_left;
Vector c_left = c;
Scalar sqr_d_left = squared_distance_to_indexed_triangle_set_recursive(distancer, left_node_idx, low_sqr_d, up_sqr_d, i_left, c_left);
Scalar sqr_d_left = squared_distance_to_indexed_primitives_recursive(distancer, left_node_idx, low_sqr_d, up_sqr_d, i_left, c_left);
set_min(sqr_d_left, i_left, c_left);
looked_left = true;
};
@ -569,13 +578,13 @@ namespace detail {
{
size_t i_right;
Vector c_right = c;
Scalar sqr_d_right = squared_distance_to_indexed_triangle_set_recursive(distancer, right_node_idx, low_sqr_d, up_sqr_d, i_right, c_right);
Scalar sqr_d_right = squared_distance_to_indexed_primitives_recursive(distancer, right_node_idx, low_sqr_d, up_sqr_d, i_right, c_right);
set_min(sqr_d_right, i_right, c_right);
looked_right = true;
};
// must look left or right if in box
using BBoxScalar = typename IndexedTriangleSetDistancerType::TreeType::BoundingBox::Scalar;
using BBoxScalar = typename IndexedPrimitivesDistancerType::TreeType::BoundingBox::Scalar;
if (node_left.bbox.contains(distancer.origin.template cast<BBoxScalar>()))
look_left();
if (node_right.bbox.contains(distancer.origin.template cast<BBoxScalar>()))
@ -709,10 +718,15 @@ inline bool intersect_ray_all_hits(
origin, dir, VectorType(dir.cwiseInverse()),
eps }
};
if (! tree.empty()) {
if (tree.empty()) {
hits.clear();
} else {
// Reusing the output memory if there is some memory already pre-allocated.
ray_intersector.hits = std::move(hits);
ray_intersector.hits.clear();
ray_intersector.hits.reserve(8);
detail::intersect_ray_recursive_all_hits(ray_intersector, 0);
std::swap(hits, ray_intersector.hits);
hits = std::move(ray_intersector.hits);
std::sort(hits.begin(), hits.end(), [](const auto &l, const auto &r) { return l.t < r.t; });
}
return ! hits.empty();
@ -742,7 +756,7 @@ inline typename VectorType::Scalar squared_distance_to_indexed_triangle_set(
auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType>
{ vertices, faces, tree, point };
return tree.empty() ? Scalar(-1) :
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
}
// Decides if exists some triangle in defined radius on a 3D indexed triangle set using a pre-built AABBTreeIndirect::Tree.
@ -759,22 +773,22 @@ inline bool is_any_triangle_in_radius(
const TreeType &tree,
// Point to which the closest point on the indexed triangle set is searched for.
const VectorType &point,
// Maximum distance in which triangle is search for
typename VectorType::Scalar &max_distance)
//Square of maximum distance in which triangle is searched for
typename VectorType::Scalar &max_distance_squared)
{
using Scalar = typename VectorType::Scalar;
auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType>
{ vertices, faces, tree, point };
size_t hit_idx;
VectorType hit_point = VectorType::Ones() * (std::nan(""));
size_t hit_idx;
VectorType hit_point = VectorType::Ones() * (NaN<typename VectorType::Scalar>);
if(tree.empty())
{
return false;
}
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), max_distance, hit_idx, hit_point);
detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), max_distance_squared, hit_idx, hit_point);
return hit_point.allFinite();
}
@ -823,22 +837,22 @@ struct Intersecting<Eigen::AlignedBox<CoordType, NumD>> {
template<class G> auto intersecting(const G &g) { return Intersecting<G>{g}; }
template<class G> struct Containing {};
template<class G> struct Within {};
// Intersection predicate specialization for box-box intersections
template<class CoordType, int NumD>
struct Containing<Eigen::AlignedBox<CoordType, NumD>> {
struct Within<Eigen::AlignedBox<CoordType, NumD>> {
Eigen::AlignedBox<CoordType, NumD> box;
Containing(const Eigen::AlignedBox<CoordType, NumD> &bb): box{bb} {}
Within(const Eigen::AlignedBox<CoordType, NumD> &bb): box{bb} {}
bool operator() (const typename Tree<NumD, CoordType>::Node &node) const
{
return box.contains(node.bbox);
return node.is_leaf() ? box.contains(node.bbox) : box.intersects(node.bbox);
}
};
template<class G> auto containing(const G &g) { return Containing<G>{g}; }
template<class G> auto within(const G &g) { return Within<G>{g}; }
namespace detail {
@ -853,7 +867,7 @@ void traverse_recurse(const Tree<Dims, T> &tree,
if (!pred(tree.node(idx))) return;
if (tree.node(idx).is_leaf()) {
callback(tree.node(idx).idx);
callback(tree.node(idx));
} else {
// call this with left and right node idx:

View File

@ -0,0 +1,112 @@
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
#include "libslic3r/Point.hpp"
#include "libslic3r/EdgeGrid.hpp"
#include "libslic3r/AABBTreeIndirect.hpp"
#include "libslic3r/Line.hpp"
namespace Slic3r {
namespace AABBTreeLines {
namespace detail {
template<typename ALineType, typename ATreeType, typename AVectorType>
struct IndexedLinesDistancer {
using LineType = ALineType;
using TreeType = ATreeType;
using VectorType = AVectorType;
using ScalarType = typename VectorType::Scalar;
const std::vector<LineType> &lines;
const TreeType &tree;
const VectorType origin;
inline VectorType closest_point_to_origin(size_t primitive_index,
ScalarType &squared_distance) {
VectorType nearest_point;
const LineType &line = lines[primitive_index];
squared_distance = line_alg::distance_to_squared(line, origin, &nearest_point);
return nearest_point;
}
};
}
// Build a balanced AABB Tree over a vector of float lines, balancing the tree
// on centroids of the lines.
// Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies
// during tree traversal.
template<typename LineType>
inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(
const std::vector<LineType> &lines,
//FIXME do we want to apply an epsilon?
const float eps = 0)
{
using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>;
// using CoordType = typename TreeType::CoordType;
using VectorType = typename TreeType::VectorType;
using BoundingBox = typename TreeType::BoundingBox;
struct InputType {
size_t idx() const {
return m_idx;
}
const BoundingBox& bbox() const {
return m_bbox;
}
const VectorType& centroid() const {
return m_centroid;
}
size_t m_idx;
BoundingBox m_bbox;
VectorType m_centroid;
};
std::vector<InputType> input;
input.reserve(lines.size());
const VectorType veps(eps, eps);
for (size_t i = 0; i < lines.size(); ++i) {
const LineType &line = lines[i];
InputType n;
n.m_idx = i;
n.m_centroid = (line.a + line.b) * 0.5;
n.m_bbox = BoundingBox(line.a, line.a);
n.m_bbox.extend(line.b);
n.m_bbox.min() -= veps;
n.m_bbox.max() += veps;
input.emplace_back(n);
}
TreeType out;
out.build(std::move(input));
return out;
}
// Finding a closest line, its closest point and squared distance to the closest point
// Returns squared distance to the closest point or -1 if the input is empty.
template<typename LineType, typename TreeType, typename VectorType>
inline typename VectorType::Scalar squared_distance_to_indexed_lines(
const std::vector<LineType> &lines,
const TreeType &tree,
const VectorType &point,
size_t &hit_idx_out,
Eigen::PlainObjectBase<VectorType> &hit_point_out)
{
using Scalar = typename VectorType::Scalar;
auto distancer = detail::IndexedLinesDistancer<LineType, TreeType, VectorType>
{ lines, tree, point };
return tree.empty() ?
Scalar(-1) :
AABBTreeIndirect::detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0),
std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
}
}
}
#endif /* SRC_LIBSLIC3R_AABBTREELINES_HPP_ */

182
src/libslic3r/AStar.hpp Normal file
View File

@ -0,0 +1,182 @@
#ifndef ASTAR_HPP
#define ASTAR_HPP
#include "libslic3r/Point.hpp"
#include "libslic3r/MutablePriorityQueue.hpp"
#include <unordered_map>
namespace Slic3r { namespace astar {
// Input interface for the Astar algorithm. Specialize this struct for a
// particular type and implement all the 4 methods and specify the Node type
// to register the new type for the astar implementation.
template<class T> struct TracerTraits_
{
// The type of a node used by this tracer. Usually a point in space.
using Node = typename T::Node;
// Call fn for every new node reachable from node 'src'. fn should have the
// candidate node as its only argument.
template<class Fn>
static void foreach_reachable(const T &tracer, const Node &src, Fn &&fn)
{
tracer.foreach_reachable(src, fn);
}
// Get the distance from node 'a' to node 'b'. This is sometimes referred
// to as the g value of a node in AStar context.
static float distance(const T &tracer, const Node &a, const Node &b)
{
return tracer.distance(a, b);
}
// Get the estimated distance heuristic from node 'n' to the destination.
// This is referred to as the h value in AStar context.
// If node 'n' is the goal, this function should return a negative value.
static float goal_heuristic(const T &tracer, const Node &n)
{
return tracer.goal_heuristic(n);
}
// Return a unique identifier (hash) for node 'n'.
static size_t unique_id(const T &tracer, const Node &n)
{
return tracer.unique_id(n);
}
};
// Helper definition to get the node type of a tracer
template<class T>
using TracerNodeT = typename TracerTraits_<remove_cvref_t<T>>::Node;
namespace detail {
// Helper functions dispatching calls through the TracerTraits_ interface
template<class T> using TracerTraits = TracerTraits_<remove_cvref_t<T>>;
template<class T, class Fn>
void foreach_reachable(const T &tracer, const TracerNodeT<T> &from, Fn &&fn)
{
TracerTraits<T>::foreach_reachable(tracer, from, fn);
}
template<class T>
float trace_distance(const T &tracer, const TracerNodeT<T> &a, const TracerNodeT<T> &b)
{
return TracerTraits<T>::distance(tracer, a, b);
}
template<class T>
float goal_heuristic(const T &tracer, const TracerNodeT<T> &n)
{
return TracerTraits<T>::goal_heuristic(tracer, n);
}
template<class T>
size_t unique_id(const T &tracer, const TracerNodeT<T> &n)
{
return TracerTraits<T>::unique_id(tracer, n);
}
} // namespace astar_detail
// Run the AStar algorithm on a tracer implementation.
// The 'tracer' argument encapsulates the domain (grid, point cloud, etc...)
// The 'source' argument is the starting node.
// The 'out' argument is the output iterator into which the output nodes are
// written.
// Note that no destination node is given. The tracer's goal_heuristic() method
// should return a negative value if a node is a destination node.
template<class Tracer, class It>
bool search_route(const Tracer &tracer, const TracerNodeT<Tracer> &source, It out)
{
using namespace detail;
using Node = TracerNodeT<Tracer>;
enum class QueueType { Open, Closed, None };
struct QNode // Queue node. Keeps track of scores g, and h
{
Node node; // The actual node itself
QueueType qtype = QueueType::None; // Which queue holds this node
float g = 0.f, h = 0.f;
float f() const { return g + h; }
};
// TODO: apply a linear memory allocator
using QMap = std::unordered_map<size_t, QNode>;
// The traversed nodes are stored here encapsulated in QNodes
QMap cached_nodes;
struct LessPred { // Comparison functor needed by MutablePriorityQueue
QMap &m;
bool operator ()(size_t node_a, size_t node_b) {
auto ait = m.find(node_a);
auto bit = m.find(node_b);
assert (ait != m.end() && bit != m.end());
return ait->second.f() < bit->second.f();
}
};
auto qopen =
make_mutable_priority_queue<size_t, false>([](size_t, size_t){},
LessPred{cached_nodes});
auto qclosed =
make_mutable_priority_queue<size_t, false>([](size_t, size_t){},
LessPred{cached_nodes});
QNode initial{source, QueueType::Open};
cached_nodes.insert({unique_id(tracer, source), initial});
qopen.push(unique_id(tracer, source));
bool goal_reached = false;
while (!goal_reached && !qopen.empty()) {
size_t q_id = qopen.top();
qopen.pop();
QNode q = cached_nodes.at(q_id);
foreach_reachable(tracer, q.node, [&](const Node &nd) {
if (goal_reached) return goal_reached;
float h = goal_heuristic(tracer, nd);
if (h < 0.f) {
goal_reached = true;
} else {
float dst = trace_distance(tracer, q.node, nd);
QNode qnd{nd, QueueType::None, q.g + dst, h};
size_t qnd_id = unique_id(tracer, nd);
auto it = cached_nodes.find(qnd_id);
if (it == cached_nodes.end() ||
(it->second.qtype != QueueType::None && qnd.f() < it->second.f())) {
qnd.qtype = QueueType::Open;
cached_nodes.insert_or_assign(qnd_id, qnd);
qopen.push(qnd_id);
}
}
return goal_reached;
});
q.qtype = QueueType::Closed;
cached_nodes.insert_or_assign(q_id, q);
qclosed.push(q_id);
// write the output
*out = q.node;
++out;
}
return goal_reached;
}
}} // namespace Slic3r::astar
#endif // ASTAR_HPP

View File

@ -15,7 +15,7 @@ class CircleBed {
double radius_;
public:
inline CircleBed(): center_(0, 0), radius_(std::nan("")) {}
inline CircleBed(): center_(0, 0), radius_(NaNd) {}
explicit inline CircleBed(const Point& c, double r): center_(c), radius_(r) {}
inline double radius() const { return radius_; }

View File

@ -17,6 +17,7 @@ endif()
set(SLIC3R_SOURCES
pchheader.cpp
pchheader.hpp
AStar.hpp
BoundingBox.cpp
BoundingBox.hpp
BridgeDetector.cpp
@ -40,8 +41,6 @@ set(SLIC3R_SOURCES
enum_bitmask.hpp
ExPolygon.cpp
ExPolygon.hpp
ExPolygonCollection.cpp
ExPolygonCollection.hpp
Extruder.cpp
Extruder.hpp
ExtrusionEntity.cpp
@ -94,8 +93,12 @@ set(SLIC3R_SOURCES
Format/objparser.hpp
Format/STL.cpp
Format/STL.hpp
Format/SLAArchive.hpp
Format/SLAArchive.cpp
Format/SLAArchiveWriter.hpp
Format/SLAArchiveWriter.cpp
Format/SLAArchiveReader.hpp
Format/SLAArchiveReader.cpp
Format/ZipperArchiveImport.hpp
Format/ZipperArchiveImport.cpp
Format/SL1.hpp
Format/SL1.cpp
Format/SL1_SVG.hpp
@ -138,10 +141,12 @@ set(SLIC3R_SOURCES
GCodeWriter.hpp
Geometry.cpp
Geometry.hpp
Geometry/Bicubic.hpp
Geometry/Circle.cpp
Geometry/Circle.hpp
Geometry/ConvexHull.cpp
Geometry/ConvexHull.hpp
Geometry/Curves.hpp
Geometry/MedialAxis.cpp
Geometry/MedialAxis.hpp
Geometry/Voronoi.hpp
@ -208,6 +213,7 @@ set(SLIC3R_SOURCES
PrintObject.cpp
PrintObjectSlice.cpp
PrintRegion.cpp
PointGrid.hpp
PNGReadWrite.hpp
PNGReadWrite.cpp
QuadricEdgeCollapse.cpp
@ -225,6 +231,8 @@ set(SLIC3R_SOURCES
SlicesToTriangleMesh.cpp
SlicingAdaptive.cpp
SlicingAdaptive.hpp
Subdivide.cpp
Subdivide.hpp
SupportMaterial.cpp
SupportMaterial.hpp
Surface.cpp
@ -364,7 +372,7 @@ target_link_libraries(libslic3r
boost_libs
clipper
nowide
EXPAT::EXPAT
libexpat
glu-libtess
qhull
semver

View File

@ -240,7 +240,7 @@ TResult clipper_union(
// Perform union of input polygons using the positive rule, convert to ExPolygons.
//FIXME is there any benefit of not doing the boolean / using pftEvenOdd?
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union)
inline ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union)
{
return PolyTreeToExPolygons(clipper_union<ClipperLib::PolyTree>(input, do_union ? ClipperLib::pftNonZero : ClipperLib::pftEvenOdd));
}
@ -438,7 +438,7 @@ Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta,
{ return to_polygons(expolygons_offset(surfaces, delta, joinType, miterLimit)); }
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit)
//FIXME one may spare one Clipper Union call.
{ return ClipperPaths_to_Slic3rExPolygons(expolygon_offset(expolygon, delta, joinType, miterLimit)); }
{ return ClipperPaths_to_Slic3rExPolygons(expolygon_offset(expolygon, delta, joinType, miterLimit), /* do union */ false); }
Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit)
{ return PolyTreeToExPolygons(expolygons_offset_pt(expolygons, delta, joinType, miterLimit)); }
Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit)
@ -713,6 +713,8 @@ Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::SinglePathProvider(clip.points)); }
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip)
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::PolygonsProvider(clip)); }
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip)
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::ExPolygonsProvider(clip)); }
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip)
{ return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::PolygonsProvider(clip)); }
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip)

View File

@ -1,17 +1,27 @@
#ifndef slic3r_ClipperUtils_hpp_
#define slic3r_ClipperUtils_hpp_
//#define SLIC3R_USE_CLIPPER2
#include "libslic3r.h"
#include "clipper.hpp"
#include "ExPolygon.hpp"
#include "Polygon.hpp"
#include "Surface.hpp"
#ifdef SLIC3R_USE_CLIPPER2
#include <clipper2.clipper.h>
#else /* SLIC3R_USE_CLIPPER2 */
#include "clipper.hpp"
// import these wherever we're included
using Slic3r::ClipperLib::jtMiter;
using Slic3r::ClipperLib::jtRound;
using Slic3r::ClipperLib::jtSquare;
#endif /* SLIC3R_USE_CLIPPER2 */
namespace Slic3r {
static constexpr const float ClipperSafetyOffset = 10.f;
@ -298,9 +308,6 @@ namespace ClipperUtils {
};
}
// Perform union of input polygons using the non-zero rule, convert to ExPolygons.
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union = false);
// offset Polygons
// Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better.
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit);
@ -429,6 +436,7 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip);
Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip);

View File

@ -4,6 +4,8 @@
#include <array>
#include <algorithm>
#include "Point.hpp"
namespace Slic3r {
class ColorRGB
@ -133,41 +135,57 @@ public:
static const ColorRGBA Z() { return { 0.0f, 0.0f, 0.75f, 1.0f }; }
};
extern ColorRGB operator * (float value, const ColorRGB& other);
extern ColorRGBA operator * (float value, const ColorRGBA& other);
ColorRGB operator * (float value, const ColorRGB& other);
ColorRGBA operator * (float value, const ColorRGBA& other);
extern ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t);
extern ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t);
ColorRGB lerp(const ColorRGB& a, const ColorRGB& b, float t);
ColorRGBA lerp(const ColorRGBA& a, const ColorRGBA& b, float t);
extern ColorRGB complementary(const ColorRGB& color);
extern ColorRGBA complementary(const ColorRGBA& color);
ColorRGB complementary(const ColorRGB& color);
ColorRGBA complementary(const ColorRGBA& color);
extern ColorRGB saturate(const ColorRGB& color, float factor);
extern ColorRGBA saturate(const ColorRGBA& color, float factor);
ColorRGB saturate(const ColorRGB& color, float factor);
ColorRGBA saturate(const ColorRGBA& color, float factor);
extern ColorRGB opposite(const ColorRGB& color);
extern ColorRGB opposite(const ColorRGB& a, const ColorRGB& b);
ColorRGB opposite(const ColorRGB& color);
ColorRGB opposite(const ColorRGB& a, const ColorRGB& b);
extern bool can_decode_color(const std::string& color);
bool can_decode_color(const std::string& color);
extern bool decode_color(const std::string& color_in, ColorRGB& color_out);
extern bool decode_color(const std::string& color_in, ColorRGBA& color_out);
bool decode_color(const std::string& color_in, ColorRGB& color_out);
bool decode_color(const std::string& color_in, ColorRGBA& color_out);
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out);
extern bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out);
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGB>& colors_out);
bool decode_colors(const std::vector<std::string>& colors_in, std::vector<ColorRGBA>& colors_out);
extern std::string encode_color(const ColorRGB& color);
extern std::string encode_color(const ColorRGBA& color);
std::string encode_color(const ColorRGB& color);
std::string encode_color(const ColorRGBA& color);
extern ColorRGB to_rgb(const ColorRGBA& other_rgba);
extern ColorRGBA to_rgba(const ColorRGB& other_rgb);
extern ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha);
ColorRGB to_rgb(const ColorRGBA& other_rgba);
ColorRGBA to_rgba(const ColorRGB& other_rgb);
ColorRGBA to_rgba(const ColorRGB& other_rgb, float alpha);
extern ColorRGBA picking_decode(unsigned int id);
extern unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b);
// Color mapping of a value into RGB false colors.
inline Vec3f value_to_rgbf(float minimum, float maximum, float value)
{
float ratio = 2.0f * (value - minimum) / (maximum - minimum);
float b = std::max(0.0f, (1.0f - ratio));
float r = std::max(0.0f, (ratio - 1.0f));
float g = 1.0f - b - r;
return Vec3f { r, g, b };
}
// Color mapping of a value into RGB false colors.
inline Vec3i value_to_rgbi(float minimum, float maximum, float value)
{
return (value_to_rgbf(minimum, maximum, value) * 255).cast<int>();
}
ColorRGBA picking_decode(unsigned int id);
unsigned int picking_encode(unsigned char r, unsigned char g, unsigned char b);
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
// were not interpolated by alpha blending or multi sampling.
extern unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue);
} // namespace Slic3r

View File

@ -402,6 +402,42 @@ std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, s
return out;
}
std::string ConfigBase::SetDeserializeItem::format(std::initializer_list<int> values)
{
std::string out;
int i = 0;
for (int v : values) {
if (i ++ > 0)
out += ", ";
out += std::to_string(v);
}
return out;
}
std::string ConfigBase::SetDeserializeItem::format(std::initializer_list<float> values)
{
std::string out;
int i = 0;
for (float v : values) {
if (i ++ > 0)
out += ", ";
out += float_to_string_decimal_point(double(v));
}
return out;
}
std::string ConfigBase::SetDeserializeItem::format(std::initializer_list<double> values)
{
std::string out;
int i = 0;
for (float v : values) {
if (i ++ > 0)
out += ", ";
out += float_to_string_decimal_point(v);
}
return out;
}
void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
{
// loop through options and apply them
@ -824,6 +860,7 @@ public:
m_ifs.seekg(m_file_pos, m_ifs.beg);
if (! m_ifs.read(m_block.data(), m_block_len))
return false;
assert(m_block_len == m_ifs.gcount());
}
assert(m_block_len > 0);
@ -866,7 +903,7 @@ private:
ConfigSubstitutions ConfigBase::load_from_gcode_file(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule)
{
// Read a 64k block from the end of the G-code.
boost::nowide::ifstream ifs(file);
boost::nowide::ifstream ifs(file, std::ifstream::binary);
// Look for Slic3r or PrusaSlicer header.
// Look for the header across the whole file as the G-code may have been extended at the start by a post-processing script or the user.
bool has_delimiters = false;

View File

@ -10,6 +10,7 @@
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>
#include "libslic3r.h"
#include "clonable_ptr.hpp"
@ -194,7 +195,8 @@ enum ConfigOptionType {
enum ConfigOptionMode {
comSimple = 0,
comAdvanced,
comExpert
comExpert,
comUndef
};
enum PrinterTechnology : unsigned char
@ -1948,6 +1950,11 @@ public:
throw BadOptionTypeException("Conversion to a wrong type");
return static_cast<TYPE*>(opt);
}
template<class T> T* opt(const t_config_option_key &opt_key, bool create = false)
{ return dynamic_cast<T*>(this->optptr(opt_key, create)); }
template<class T> const T* opt(const t_config_option_key &opt_key) const
{ return dynamic_cast<const T*>(this->optptr(opt_key)); }
// Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
// An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
@ -1988,15 +1995,28 @@ public:
struct SetDeserializeItem {
SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
SetDeserializeItem(const std::string &opt_key, const std::string_view opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
SetDeserializeItem(const char *opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
SetDeserializeItem(const std::string &opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
SetDeserializeItem(const char *opt_key, const int value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const int value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
SetDeserializeItem(const char *opt_key, const std::initializer_list<int> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const std::initializer_list<int> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
SetDeserializeItem(const char *opt_key, const float value, bool append = false) : opt_key(opt_key), opt_value(float_to_string_decimal_point(value)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const float value, bool append = false) : opt_key(opt_key), opt_value(float_to_string_decimal_point(value)), append(append) {}
SetDeserializeItem(const char *opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(float_to_string_decimal_point(value)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(float_to_string_decimal_point(value)), append(append) {}
SetDeserializeItem(const char *opt_key, const std::initializer_list<float> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const std::initializer_list<float> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
SetDeserializeItem(const char *opt_key, const std::initializer_list<double> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
SetDeserializeItem(const std::string &opt_key, const std::initializer_list<double> values, bool append = false) : opt_key(opt_key), opt_value(format(values)), append(append) {}
std::string opt_key; std::string opt_value; bool append = false;
private:
static std::string format(std::initializer_list<int> values);
static std::string format(std::initializer_list<float> values);
static std::string format(std::initializer_list<double> values);
};
// May throw BadOptionTypeException() if the operation fails.
void set_deserialize(std::initializer_list<SetDeserializeItem> items, ConfigSubstitutionContext& substitutions);
@ -2005,7 +2025,31 @@ public:
double get_abs_value(const t_config_option_key &opt_key) const;
double get_abs_value(const t_config_option_key &opt_key, double ratio_over) const;
void setenv_() const;
std::string& opt_string(const t_config_option_key &opt_key, bool create = false) { return this->option<ConfigOptionString>(opt_key, create)->value; }
const std::string& opt_string(const t_config_option_key &opt_key) const { return const_cast<ConfigBase*>(this)->opt_string(opt_key); }
std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionStrings>(opt_key)->get_at(idx); }
const std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) const { return const_cast<ConfigBase*>(this)->opt_string(opt_key, idx); }
double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
// Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
void setenv_() const;
ConfigSubstitutions load(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
ConfigSubstitutions load_from_ini(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
ConfigSubstitutions load_from_ini_string(const std::string &data, ForwardCompatibilitySubstitutionRule compatibility_rule);
@ -2014,10 +2058,10 @@ public:
ConfigSubstitutions load_from_ini_string_commented(std::string &&data, ForwardCompatibilitySubstitutionRule compatibility_rule);
ConfigSubstitutions load_from_gcode_file(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
ConfigSubstitutions load(const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule);
void save(const std::string &file) const;
void save(const std::string &file) const;
// Set all the nullable values to nils.
void null_nullables();
void null_nullables();
static size_t load_from_gcode_string_legacy(ConfigBase& config, const char* str, ConfigSubstitutionContext& substitutions);
@ -2126,10 +2170,6 @@ public:
// Allow DynamicConfig to be instantiated on ints own without a definition.
// If the definition is not defined, the method requiring the definition will throw NoDefinitionException.
const ConfigDef* def() const override { return nullptr; }
template<class T> T* opt(const t_config_option_key &opt_key, bool create = false)
{ return dynamic_cast<T*>(this->option(opt_key, create)); }
template<class T> const T* opt(const t_config_option_key &opt_key) const
{ return dynamic_cast<const T*>(this->option(opt_key)); }
// Overrides ConfigResolver::optptr().
const ConfigOption* optptr(const t_config_option_key &opt_key) const override;
// Overrides ConfigBase::optptr(). Find ando/or create a ConfigOption instance for a given name.
@ -2160,29 +2200,6 @@ public:
// Returns options being equal in the two configs, ignoring options not present in both configs.
t_config_option_keys equal(const DynamicConfig &other) const;
std::string& opt_string(const t_config_option_key &opt_key, bool create = false) { return this->option<ConfigOptionString>(opt_key, create)->value; }
const std::string& opt_string(const t_config_option_key &opt_key) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key); }
std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionStrings>(opt_key)->get_at(idx); }
const std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key, idx); }
double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
// Thus the virtual method getInt() is used to retrieve the enum value.
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return static_cast<ENUM>(this->option(opt_key)->getInt()); }
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
// Command line processing
bool read_cli(int argc, const char* const argv[], t_config_option_keys* extra, t_config_option_keys* keys = nullptr);

View File

@ -136,11 +136,6 @@ void EdgeGrid::Grid::create(const ExPolygons &expolygons, coord_t resolution)
create_from_m_contours(resolution);
}
void EdgeGrid::Grid::create(const ExPolygonCollection &expolygons, coord_t resolution)
{
create(expolygons.expolygons, resolution);
}
// m_contours has been initialized. Now fill in the edge grid.
void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
{

View File

@ -7,7 +7,6 @@
#include "Point.hpp"
#include "BoundingBox.hpp"
#include "ExPolygon.hpp"
#include "ExPolygonCollection.hpp"
namespace Slic3r {
namespace EdgeGrid {
@ -112,7 +111,6 @@ public:
void create(const std::vector<Points> &polygons, coord_t resolution) { this->create(polygons, resolution, false); }
void create(const ExPolygon &expoly, coord_t resolution);
void create(const ExPolygons &expolygons, coord_t resolution);
void create(const ExPolygonCollection &expolygons, coord_t resolution);
const std::vector<Contour>& contours() const { return m_contours; }
@ -123,7 +121,6 @@ public:
bool intersect(const Polygons &polygons) { for (size_t i = 0; i < polygons.size(); ++ i) if (intersect(polygons[i])) return true; return false; }
bool intersect(const ExPolygon &expoly) { if (intersect(expoly.contour)) return true; for (size_t i = 0; i < expoly.holes.size(); ++ i) if (intersect(expoly.holes[i])) return true; return false; }
bool intersect(const ExPolygons &expolygons) { for (size_t i = 0; i < expolygons.size(); ++ i) if (intersect(expolygons[i])) return true; return false; }
bool intersect(const ExPolygonCollection &expolygons) { return intersect(expolygons.expolygons); }
// Test, whether a point is inside a contour.
bool inside(const Point &pt);
@ -391,7 +388,7 @@ protected:
// Referencing the source contours.
// This format allows one to work with any Slic3r fixed point contour format
// (Polygon, ExPolygon, ExPolygonCollection etc).
// (Polygon, ExPolygon, ExPolygons etc).
std::vector<Contour> m_contours;
// Referencing a contour and a line segment of m_contours.

View File

@ -9,7 +9,7 @@
namespace Slic3r {
class ExPolygon;
typedef std::vector<ExPolygon> ExPolygons;
using ExPolygons = std::vector<ExPolygon>;
class ExPolygon
{
@ -67,6 +67,8 @@ public:
void simplify(double tolerance, ExPolygons* expolygons) const;
void medial_axis(double max_width, double min_width, ThickPolylines* polylines) const;
void medial_axis(double max_width, double min_width, Polylines* polylines) const;
Polylines medial_axis(double max_width, double min_width) const
{ Polylines out; this->medial_axis(max_width, min_width, &out); return out; }
Lines lines() const;
// Number of contours (outer contour with holes).

View File

@ -1,136 +0,0 @@
#include "ExPolygonCollection.hpp"
#include "Geometry/ConvexHull.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
ExPolygonCollection::ExPolygonCollection(const ExPolygon &expolygon)
{
this->expolygons.push_back(expolygon);
}
ExPolygonCollection::operator Points() const
{
Points points;
Polygons pp = (Polygons)*this;
for (Polygons::const_iterator poly = pp.begin(); poly != pp.end(); ++poly) {
for (Points::const_iterator point = poly->points.begin(); point != poly->points.end(); ++point)
points.push_back(*point);
}
return points;
}
ExPolygonCollection::operator Polygons() const
{
Polygons polygons;
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) {
polygons.push_back(it->contour);
for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) {
polygons.push_back(*ith);
}
}
return polygons;
}
ExPolygonCollection::operator ExPolygons&()
{
return this->expolygons;
}
void
ExPolygonCollection::scale(double factor)
{
for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) {
(*it).scale(factor);
}
}
void
ExPolygonCollection::translate(double x, double y)
{
for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) {
(*it).translate(x, y);
}
}
void
ExPolygonCollection::rotate(double angle, const Point &center)
{
for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) {
(*it).rotate(angle, center);
}
}
template <class T>
bool ExPolygonCollection::contains(const T &item) const
{
for (const ExPolygon &poly : this->expolygons)
if (poly.contains(item))
return true;
return false;
}
template bool ExPolygonCollection::contains<Point>(const Point &item) const;
template bool ExPolygonCollection::contains<Line>(const Line &item) const;
template bool ExPolygonCollection::contains<Polyline>(const Polyline &item) const;
bool
ExPolygonCollection::contains_b(const Point &point) const
{
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) {
if (it->contains_b(point)) return true;
}
return false;
}
void
ExPolygonCollection::simplify(double tolerance)
{
ExPolygons expp;
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) {
it->simplify(tolerance, &expp);
}
this->expolygons = expp;
}
Polygon
ExPolygonCollection::convex_hull() const
{
Points pp;
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it)
pp.insert(pp.end(), it->contour.points.begin(), it->contour.points.end());
return Slic3r::Geometry::convex_hull(pp);
}
Lines
ExPolygonCollection::lines() const
{
Lines lines;
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) {
Lines ex_lines = it->lines();
lines.insert(lines.end(), ex_lines.begin(), ex_lines.end());
}
return lines;
}
Polygons
ExPolygonCollection::contours() const
{
Polygons contours;
contours.reserve(this->expolygons.size());
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it)
contours.push_back(it->contour);
return contours;
}
void
ExPolygonCollection::append(const ExPolygons &expp)
{
this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end());
}
BoundingBox get_extents(const ExPolygonCollection &expolygon)
{
return get_extents(expolygon.expolygons);
}
}

View File

@ -1,41 +0,0 @@
#ifndef slic3r_ExPolygonCollection_hpp_
#define slic3r_ExPolygonCollection_hpp_
#include "libslic3r.h"
#include "ExPolygon.hpp"
#include "Line.hpp"
#include "Polyline.hpp"
namespace Slic3r {
class ExPolygonCollection;
typedef std::vector<ExPolygonCollection> ExPolygonCollections;
class ExPolygonCollection
{
public:
ExPolygons expolygons;
ExPolygonCollection() {}
explicit ExPolygonCollection(const ExPolygon &expolygon);
explicit ExPolygonCollection(const ExPolygons &expolygons) : expolygons(expolygons) {}
explicit operator Points() const;
explicit operator Polygons() const;
explicit operator ExPolygons&();
void scale(double factor);
void translate(double x, double y);
void rotate(double angle, const Point &center);
template <class T> bool contains(const T &item) const;
bool contains_b(const Point &point) const;
void simplify(double tolerance);
Polygon convex_hull() const;
Lines lines() const;
Polygons contours() const;
void append(const ExPolygons &expolygons);
};
extern BoundingBox get_extents(const ExPolygonCollection &expolygon);
}
#endif

View File

@ -30,8 +30,8 @@ template<class EP> using AsTraits = Traits<remove_cvref_t<EP>>;
// Each execution policy should declare two types of mutexes. A a spin lock and
// a blocking mutex. These types should satisfy the BasicLockable concept.
template<class EP> using SpinningMutex = typename Traits<EP>::SpinningMutex;
template<class EP> using BlockingMutex = typename Traits<EP>::BlockingMutex;
template<class EP> using SpinningMutex = typename AsTraits<EP>::SpinningMutex;
template<class EP> using BlockingMutex = typename AsTraits<EP>::BlockingMutex;
// Query the available threads for concurrency.
template<class EP, class = ExecutionPolicyOnly<EP> >

View File

@ -1,6 +1,6 @@
#include "ExtrusionEntity.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "ExPolygonCollection.hpp"
#include "ExPolygon.hpp"
#include "ClipperUtils.hpp"
#include "Extruder.hpp"
#include "Flow.hpp"
@ -12,14 +12,14 @@
namespace Slic3r {
void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection.expolygons), retval);
this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection), retval);
}
void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
void ExtrusionPath::subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection.expolygons), retval);
this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection), retval);
}
void ExtrusionPath::clip_end(double distance)

View File

@ -11,7 +11,8 @@
namespace Slic3r {
class ExPolygonCollection;
class ExPolygon;
using ExPolygons = std::vector<ExPolygon>;
class ExtrusionEntityCollection;
class Extruder;
@ -84,7 +85,7 @@ public:
virtual ExtrusionEntity* clone() const = 0;
// Create a new object, initialize it with this object using the move semantics.
virtual ExtrusionEntity* clone_move() = 0;
virtual ~ExtrusionEntity() {}
virtual ~ExtrusionEntity() = default;
virtual void reverse() = 0;
virtual const Point& first_point() const = 0;
virtual const Point& last_point() const = 0;
@ -144,12 +145,12 @@ public:
size_t size() const { return this->polyline.size(); }
bool empty() const { return this->polyline.empty(); }
bool is_closed() const { return ! this->empty() && this->polyline.points.front() == this->polyline.points.back(); }
// Produce a list of extrusion paths into retval by clipping this path by ExPolygonCollection.
// Produce a list of extrusion paths into retval by clipping this path by ExPolygons.
// Currently not used.
void intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const;
// Produce a list of extrusion paths into retval by removing parts of this path by ExPolygonCollection.
void intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const;
// Produce a list of extrusion paths into retval by removing parts of this path by ExPolygons.
// Currently not used.
void subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const;
void subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const;
void clip_end(double distance);
void simplify(double tolerance);
double length() const override;
@ -324,10 +325,10 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E
polylines.clear();
}
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, const Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines)
for (const Polyline &polyline : polylines)
if (polyline.is_valid()) {
ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height);
dst.push_back(extrusion_path);

View File

@ -36,9 +36,13 @@ public:
ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort) {}
explicit ExtrusionEntityCollection(const ExtrusionPaths &paths);
ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other);
ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other)
{ this->entities = std::move(other.entities); this->no_sort = other.no_sort; return *this; }
~ExtrusionEntityCollection() { clear(); }
ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other) {
this->clear();
this->entities = std::move(other.entities);
this->no_sort = other.no_sort;
return *this;
}
~ExtrusionEntityCollection() override { clear(); }
explicit operator ExtrusionPaths() const;
bool is_collection() const override { return true; }

View File

@ -21,9 +21,9 @@ void GeneratorDeleter::operator()(Generator *p) {
delete p;
}
GeneratorPtr build_generator(const PrintObject &print_object)
GeneratorPtr build_generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
return GeneratorPtr(new Generator(print_object));
return GeneratorPtr(new Generator(print_object, throw_on_cancel_callback));
}
} // namespace Slic3r::FillAdaptive

View File

@ -14,7 +14,7 @@ class Generator;
struct GeneratorDeleter { void operator()(Generator *p); };
using GeneratorPtr = std::unique_ptr<Generator, GeneratorDeleter>;
GeneratorPtr build_generator(const PrintObject &print_object);
GeneratorPtr build_generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
class Filler : public Slic3r::Fill
{

View File

@ -5,6 +5,8 @@
#include "../FillRectilinear.hpp"
#include "../../ClipperUtils.hpp"
#include <tbb/parallel_for.h>
namespace Slic3r::FillLightning
{
@ -18,33 +20,42 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
// Sample source polygons with a regular grid sampling pattern.
for (const ExPolygon &expoly : union_ex(current_overhang)) {
for (const Point &p : sample_grid_pattern(expoly, m_cell_size)) {
// Find a squared distance to the source expolygon boundary.
double d2 = std::numeric_limits<double>::max();
for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
d2 = std::min(d2, Line::distance_to_squared(p, prev, p2));
prev = p2;
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size);
const size_t unsupported_points_prev_size = m_unsupported_points.size();
m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, sampled_points.size()), [&self = *this, &expoly = std::as_const(expoly), &sampled_points = std::as_const(sampled_points), &unsupported_points_prev_size = std::as_const(unsupported_points_prev_size)](const tbb::blocked_range<size_t> &range) -> void {
for (size_t sp_idx = range.begin(); sp_idx < range.end(); ++sp_idx) {
const Point &sp = sampled_points[sp_idx];
// Find a squared distance to the source expolygon boundary.
double d2 = std::numeric_limits<double>::max();
for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
d2 = std::min(d2, Line::distance_to_squared(sp, prev, p2));
prev = p2;
}
}
}
self.m_unsupported_points[unsupported_points_prev_size + sp_idx] = {sp, coord_t(std::sqrt(d2))};
assert(self.m_unsupported_points_bbox.contains(sp));
}
m_unsupported_points.emplace_back(p, sqrt(d2));
assert(m_unsupported_points_bbox.contains(p));
}
}); // end of parallel_for
}
m_unsupported_points.sort([&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
std::stable_sort(m_unsupported_points.begin(), m_unsupported_points.end(), [&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
constexpr coord_t prime_for_hash = 191;
return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
a.dist_to_boundary < b.dist_to_boundary :
(PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
});
for (auto it = m_unsupported_points.begin(); it != m_unsupported_points.end(); ++it) {
UnsupportedCell& cell = *it;
m_unsupported_points_grid.emplace(this->to_grid_point(cell.loc), it);
}
m_unsupported_points_erased.resize(m_unsupported_points.size());
std::fill(m_unsupported_points_erased.begin(), m_unsupported_points_erased.end(), false);
m_unsupported_points_grid.initialize(m_unsupported_points, [&self = std::as_const(*this)](const Point &p) -> Point { return self.to_grid_point(p); });
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
// in m_unsupported_points_grid contains exactly one point.
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
@ -96,12 +107,11 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
}
// Inside a circle at the end of the new leaf, or inside a rotated rectangle.
// Remove unsupported leafs at this grid location.
if (auto it = m_unsupported_points_grid.find(grid_addr); it != m_unsupported_points_grid.end()) {
std::list<UnsupportedCell>::iterator& list_it = it->second;
UnsupportedCell& cell = *list_it;
if (const size_t cell_idx = m_unsupported_points_grid.find_cell_idx(grid_addr); cell_idx != std::numeric_limits<size_t>::max()) {
const UnsupportedCell &cell = m_unsupported_points[cell_idx];
if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
m_unsupported_points.erase(list_it);
m_unsupported_points_grid.erase(it);
m_unsupported_points_erased[cell_idx] = true;
m_unsupported_points_grid.mark_erased(grid_addr);
}
}
}

View File

@ -38,11 +38,17 @@ public:
* \return ``true`` if successful, or ``false`` if there are no more points
* to consider.
*/
bool tryGetNextPoint(Point* p) const {
if (m_unsupported_points.empty())
return false;
*p = m_unsupported_points.front().loc;
return true;
bool tryGetNextPoint(Point *out_unsupported_location, size_t *out_unsupported_cell_idx, const size_t start_idx = 0) const
{
for (size_t point_idx = start_idx; point_idx < m_unsupported_points.size(); ++point_idx) {
if (!m_unsupported_points_erased[point_idx]) {
*out_unsupported_cell_idx = point_idx;
*out_unsupported_location = m_unsupported_points[point_idx].loc;
return true;
}
}
return false;
}
/*!
@ -77,7 +83,6 @@ protected:
*/
struct UnsupportedCell
{
UnsupportedCell(const Point &loc, coord_t dist_to_boundary) : loc(loc), dist_to_boundary(dist_to_boundary) {}
// The position of the center of this cell.
Point loc;
// How far this cell is removed from the ``current_outline`` polygon, the edge of the infill area.
@ -87,7 +92,8 @@ protected:
/*!
* Cells which still need to be supported at some point.
*/
std::list<UnsupportedCell> m_unsupported_points;
std::vector<UnsupportedCell> m_unsupported_points;
std::vector<bool> m_unsupported_points_erased;
/*!
* BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers.
@ -98,7 +104,84 @@ protected:
* Links the unsupported points to a grid point, so that we can quickly look
* up the cell belonging to a certain position in the grid.
*/
std::unordered_map<Point, std::list<UnsupportedCell>::iterator, PointHash> m_unsupported_points_grid;
class UnsupportedPointsGrid
{
public:
UnsupportedPointsGrid() = default;
void initialize(const std::vector<UnsupportedCell> &unsupported_points, const std::function<Point(const Point &)> &map_cell_to_grid)
{
if (unsupported_points.empty())
return;
BoundingBox unsupported_points_bbox;
for (const UnsupportedCell &cell : unsupported_points)
unsupported_points_bbox.merge(cell.loc);
m_size = unsupported_points.size();
m_grid_range = BoundingBox(map_cell_to_grid(unsupported_points_bbox.min), map_cell_to_grid(unsupported_points_bbox.max));
m_grid_size = m_grid_range.size() + Point::Ones();
m_data.assign(m_grid_size.y() * m_grid_size.x(), std::numeric_limits<size_t>::max());
m_data_erased.assign(m_grid_size.y() * m_grid_size.x(), true);
for (size_t cell_idx = 0; cell_idx < unsupported_points.size(); ++cell_idx) {
const size_t flat_idx = map_to_flat_array(map_cell_to_grid(unsupported_points[cell_idx].loc));
assert(m_data[flat_idx] == std::numeric_limits<size_t>::max());
m_data[flat_idx] = cell_idx;
m_data_erased[flat_idx] = false;
}
}
size_t size() const { return m_size; }
size_t find_cell_idx(const Point &grid_addr)
{
if (!m_grid_range.contains(grid_addr))
return std::numeric_limits<size_t>::max();
if (const size_t flat_idx = map_to_flat_array(grid_addr); !m_data_erased[flat_idx]) {
assert(m_data[flat_idx] != std::numeric_limits<size_t>::max());
return m_data[flat_idx];
}
return std::numeric_limits<size_t>::max();
}
void mark_erased(const Point &grid_addr)
{
assert(m_grid_range.contains(grid_addr));
if (!m_grid_range.contains(grid_addr))
return;
const size_t flat_idx = map_to_flat_array(grid_addr);
assert(!m_data_erased[flat_idx] && m_data[flat_idx] != std::numeric_limits<size_t>::max());
assert(m_size != 0);
m_data_erased[flat_idx] = true;
--m_size;
}
private:
size_t m_size = 0;
BoundingBox m_grid_range;
Point m_grid_size;
std::vector<size_t> m_data;
std::vector<bool> m_data_erased;
inline size_t map_to_flat_array(const Point &loc) const
{
const Point offset_loc = loc - m_grid_range.min;
const size_t flat_idx = m_grid_size.x() * offset_loc.y() + offset_loc.x();
assert(offset_loc.x() >= 0 && offset_loc.y() >= 0);
assert(flat_idx < m_grid_size.y() * m_grid_size.x());
return flat_idx;
}
};
UnsupportedPointsGrid m_unsupported_points_grid;
/*!
* Maps the point to the grid coordinates.

View File

@ -25,7 +25,7 @@
namespace Slic3r::FillLightning {
Generator::Generator(const PrintObject &print_object)
Generator::Generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
const PrintConfig &print_config = print_object.print()->config();
const PrintObjectConfig &object_config = print_object.config();
@ -47,11 +47,11 @@ Generator::Generator(const PrintObject &print_object)
m_prune_length = coord_t(layer_thickness * std::tan(lightning_infill_prune_angle));
m_straightening_max_distance = coord_t(layer_thickness * std::tan(lightning_infill_straightening_angle));
generateInitialInternalOverhangs(print_object);
generateTrees(print_object);
generateInitialInternalOverhangs(print_object, throw_on_cancel_callback);
generateTrees(print_object, throw_on_cancel_callback);
}
void Generator::generateInitialInternalOverhangs(const PrintObject &print_object)
void Generator::generateInitialInternalOverhangs(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
m_overhang_per_layer.resize(print_object.layers().size());
// FIXME: It can be adjusted to improve bonding between infill and perimeters.
@ -59,11 +59,12 @@ void Generator::generateInitialInternalOverhangs(const PrintObject &print_object
Polygons infill_area_above;
//Iterate from top to bottom, to subtract the overhang areas above from the overhang areas on the layer below, to get only overhang in the top layer where it is overhanging.
for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; layer_nr--) {
for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; --layer_nr) {
throw_on_cancel_callback();
Polygons infill_area_here;
for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions())
for (const Surface& surface : layerm->fill_surfaces.surfaces)
if (surface.surface_type == stInternal)
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
append(infill_area_here, infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset));
//Remove the part of the infill area that is already supported by the walls.
@ -80,7 +81,7 @@ const Layer& Generator::getTreesForLayer(const size_t& layer_id) const
return m_lightning_layers[layer_id];
}
void Generator::generateTrees(const PrintObject &print_object)
void Generator::generateTrees(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
m_lightning_layers.resize(print_object.layers().size());
// FIXME: It can be adjusted to improve bonding between infill and perimeters.
@ -89,11 +90,13 @@ void Generator::generateTrees(const PrintObject &print_object)
std::vector<Polygons> infill_outlines(print_object.layers().size(), Polygons());
// For-each layer from top to bottom:
for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--)
for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) {
throw_on_cancel_callback();
for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions())
for (const Surface &surface : layerm->fill_surfaces.surfaces)
if (surface.surface_type == stInternal)
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
append(infill_outlines[layer_id], infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset));
}
// For various operations its beneficial to quickly locate nearby features on the polygon:
const size_t top_layer_id = print_object.layers().size() - 1;
@ -102,6 +105,7 @@ void Generator::generateTrees(const PrintObject &print_object)
// For-each layer from top to bottom:
for (int layer_id = int(top_layer_id); layer_id >= 0; layer_id--) {
throw_on_cancel_callback();
Layer &current_lightning_layer = m_lightning_layers[layer_id];
const Polygons &current_outlines = infill_outlines[layer_id];
const BoundingBox &current_outlines_bbox = get_extents(current_outlines);
@ -109,15 +113,21 @@ void Generator::generateTrees(const PrintObject &print_object)
// register all trees propagated from the previous layer as to-be-reconnected
std::vector<NodeSPtr> to_be_reconnected_tree_roots = current_lightning_layer.tree_roots;
current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius, throw_on_cancel_callback);
current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius);
// Initialize trees for next lower layer from the current one.
if (layer_id == 0)
return;
const Polygons& below_outlines = infill_outlines[layer_id - 1];
outlines_locator.set_bbox(get_extents(below_outlines).inflated(SCALED_EPSILON));
const Polygons &below_outlines = infill_outlines[layer_id - 1];
BoundingBox below_outlines_bbox = get_extents(below_outlines).inflated(SCALED_EPSILON);
if (const BoundingBox &outlines_locator_bbox = outlines_locator.bbox(); outlines_locator_bbox.defined)
below_outlines_bbox.merge(outlines_locator_bbox);
below_outlines_bbox.merge(get_extents(current_lightning_layer.tree_roots).inflated(SCALED_EPSILON));
outlines_locator.set_bbox(below_outlines_bbox);
outlines_locator.create(below_outlines, locator_cell_size);
std::vector<NodeSPtr>& lower_trees = m_lightning_layers[layer_id - 1].tree_roots;

View File

@ -43,9 +43,8 @@ public:
* This generator will pre-compute things in preparation of generating
* Lightning Infill for the infill areas in that mesh. The infill areas must
* already be calculated at this point.
* \param mesh The mesh to generate infill for.
*/
explicit Generator(const PrintObject &print_object);
explicit Generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
/*!
* Get a tree of paths generated for a certain layer of the mesh.
@ -69,12 +68,12 @@ protected:
* only when support is generated. For this pattern, we also need to
* generate overhang areas for the inside of the model.
*/
void generateInitialInternalOverhangs(const PrintObject &print_object);
void generateInitialInternalOverhangs(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
/*!
* Calculate the tree structure of all layers.
*/
void generateTrees(const PrintObject &print_object);
void generateTrees(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
float m_infill_extrusion_width;

View File

@ -6,9 +6,14 @@
#include "DistanceField.hpp"
#include "TreeNode.hpp"
#include "../../ClipperUtils.hpp"
#include "../../Geometry.hpp"
#include "Utils.hpp"
#include <tbb/parallel_for.h>
#include <tbb/blocked_range2d.h>
#include <mutex>
namespace Slic3r::FillLightning {
coord_t Layer::getWeightedDistance(const Point& boundary_loc, const Point& unsupported_location)
@ -43,18 +48,22 @@ void Layer::generateNewTrees
const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outlines_locator,
const coord_t supporting_radius,
const coord_t wall_supporting_radius
const coord_t wall_supporting_radius,
const std::function<void()> &throw_on_cancel_callback
)
{
DistanceField distance_field(supporting_radius, current_outlines, current_outlines_bbox, current_overhang);
throw_on_cancel_callback();
SparseNodeGrid tree_node_locator;
fillLocator(tree_node_locator, current_outlines_bbox);
// Until no more points need to be added to support all:
// Determine next point from tree/outline areas via distance-field
Point unsupported_location;
while (distance_field.tryGetNextPoint(&unsupported_location)) {
size_t unsupported_cell_idx = 0;
Point unsupported_location;
while (distance_field.tryGetNextPoint(&unsupported_location, &unsupported_cell_idx, unsupported_cell_idx)) {
throw_on_cancel_callback();
GroundingLocation grounding_loc = getBestGroundingLocation(
unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
@ -125,9 +134,10 @@ GroundingLocation Layer::getBestGroundingLocation
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
if (double d = Line::distance_to_squared(unsupported_location, prev, p2); d < d2) {
Point closest_point;
if (double d = line_alg::distance_to_squared(Line{prev, p2}, unsupported_location, &closest_point); d < d2) {
d2 = d;
node_location = Geometry::foot_pt({ prev, p2 }, unsupported_location).cast<coord_t>();
node_location = closest_point;
}
prev = p2;
}
@ -136,30 +146,52 @@ GroundingLocation Layer::getBestGroundingLocation
const auto within_dist = coord_t((node_location - unsupported_location).cast<double>().norm());
NodeSPtr sub_tree{ nullptr };
coord_t current_dist = getWeightedDistance(node_location, unsupported_location);
NodeSPtr sub_tree{nullptr};
coord_t current_dist = getWeightedDistance(node_location, unsupported_location);
if (current_dist >= wall_supporting_radius) { // Only reconnect tree roots to other trees if they are not already close to the outlines.
const coord_t search_radius = std::min(current_dist, within_dist);
BoundingBox region(unsupported_location - Point(search_radius, search_radius), unsupported_location + Point(search_radius + locator_cell_size, search_radius + locator_cell_size));
region.min = to_grid_point(region.min, current_outlines_bbox);
region.max = to_grid_point(region.max, current_outlines_bbox);
Point grid_addr;
for (grid_addr.y() = region.min.y(); grid_addr.y() < region.max.y(); ++ grid_addr.y())
for (grid_addr.x() = region.min.x(); grid_addr.x() < region.max.x(); ++ grid_addr.x()) {
auto it_range = tree_node_locator.equal_range(grid_addr);
for (auto it = it_range.first; it != it_range.second; ++ it) {
auto candidate_sub_tree = it->second.lock();
if ((candidate_sub_tree && candidate_sub_tree != exclude_tree) &&
!(exclude_tree && exclude_tree->hasOffspring(candidate_sub_tree)) &&
!polygonCollidesWithLineSegment(unsupported_location, candidate_sub_tree->getLocation(), outline_locator)) {
const coord_t candidate_dist = candidate_sub_tree->getWeightedDistance(unsupported_location, supporting_radius);
if (candidate_dist < current_dist) {
current_dist = candidate_dist;
sub_tree = candidate_sub_tree;
Point current_dist_grid_addr{std::numeric_limits<coord_t>::lowest(), std::numeric_limits<coord_t>::lowest()};
std::mutex current_dist_mutex;
tbb::parallel_for(tbb::blocked_range2d<coord_t>(region.min.y(), region.max.y(), region.min.x(), region.max.x()), [&current_dist, current_dist_copy = current_dist, &current_dist_mutex, &sub_tree, &current_dist_grid_addr, &exclude_tree = std::as_const(exclude_tree), &outline_locator = std::as_const(outline_locator), &supporting_radius = std::as_const(supporting_radius), &tree_node_locator = std::as_const(tree_node_locator), &unsupported_location = std::as_const(unsupported_location)](const tbb::blocked_range2d<coord_t> &range) -> void {
for (coord_t grid_addr_y = range.rows().begin(); grid_addr_y < range.rows().end(); ++grid_addr_y)
for (coord_t grid_addr_x = range.cols().begin(); grid_addr_x < range.cols().end(); ++grid_addr_x) {
const Point local_grid_addr{grid_addr_x, grid_addr_y};
NodeSPtr local_sub_tree{nullptr};
coord_t local_current_dist = current_dist_copy;
const auto it_range = tree_node_locator.equal_range(local_grid_addr);
for (auto it = it_range.first; it != it_range.second; ++it) {
const NodeSPtr candidate_sub_tree = it->second.lock();
if ((candidate_sub_tree && candidate_sub_tree != exclude_tree) &&
!(exclude_tree && exclude_tree->hasOffspring(candidate_sub_tree)) &&
!polygonCollidesWithLineSegment(unsupported_location, candidate_sub_tree->getLocation(), outline_locator)) {
if (const coord_t candidate_dist = candidate_sub_tree->getWeightedDistance(unsupported_location, supporting_radius); candidate_dist < local_current_dist) {
local_current_dist = candidate_dist;
local_sub_tree = candidate_sub_tree;
}
}
}
// To always get the same result in a parallel version as in a non-parallel version,
// we need to preserve that for the same current_dist, we select the same sub_tree
// as in the non-parallel version. For this purpose, inside the variable
// current_dist_grid_addr is stored from with 2D grid position assigned sub_tree comes.
// And when there are two sub_tree with the same current_dist, one which will be found
// the first in the non-parallel version is selected.
{
std::lock_guard<std::mutex> lock(current_dist_mutex);
if (local_current_dist < current_dist ||
(local_current_dist == current_dist && (grid_addr_y < current_dist_grid_addr.y() ||
(grid_addr_y == current_dist_grid_addr.y() && grid_addr_x < current_dist_grid_addr.x())))) {
current_dist = local_current_dist;
sub_tree = local_sub_tree;
current_dist_grid_addr = local_grid_addr;
}
}
}
}
}); // end of parallel_for
}
return ! sub_tree ?
@ -271,6 +303,7 @@ void Layer::reconnectRoots
}
}
#if 0
/*!
* Moves the point \p from onto the nearest polygon or leaves the point as-is, when the comb boundary is not within the root of \p max_dist2 distance.
* Given a \p distance more than zero, the point will end up inside, and conversely outside.
@ -398,6 +431,7 @@ static unsigned int moveInside(const Polygons& polygons, Point& from, int distan
}
return static_cast<unsigned int>(-1);
}
#endif
// Returns 'added someting'.
Polylines Layer::convertToLines(const Polygons& limit_to_outline, const coord_t line_width) const
@ -405,31 +439,11 @@ Polylines Layer::convertToLines(const Polygons& limit_to_outline, const coord_t
if (tree_roots.empty())
return {};
Polygons result_lines;
for (const auto& tree : tree_roots) {
// If even the furthest location in the tree is inside the polygon, the entire tree must be inside of the polygon.
// (Don't take the root as that may be on the edge and cause rounding errors to register as 'outside'.)
constexpr coord_t epsilon = 5;
Point should_be_inside = tree->getLocation();
moveInside(limit_to_outline, should_be_inside, epsilon, epsilon * epsilon);
if (inside(limit_to_outline, should_be_inside))
tree->convertToPolylines(result_lines, line_width);
}
Polylines result_lines;
for (const auto &tree : tree_roots)
tree->convertToPolylines(result_lines, line_width);
// TODO: allow for polylines!
Polylines split_lines;
for (Polygon &line : result_lines) {
if (line.size() <= 1)
continue;
Point last = line[0];
for (size_t point_idx = 1; point_idx < line.size(); point_idx++) {
Point here = line[point_idx];
split_lines.push_back({ last, here });
last = here;
}
}
return split_lines;
return intersection_pl(result_lines, limit_to_outline);
}
} // namespace Slic3r::Lightning

View File

@ -44,7 +44,8 @@ public:
const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
coord_t supporting_radius,
coord_t wall_supporting_radius
coord_t wall_supporting_radius,
const std::function<void()> &throw_on_cancel_callback
);
/*! Determine & connect to connection point in tree/outline.

View File

@ -180,7 +180,11 @@ bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeG
} visitor { outline_locator, a.cast<double>(), b.cast<double>() };
outline_locator.visit_cells_intersecting_line(a, b, visitor);
return visitor.d2min < double(within_max_dist) * double(within_max_dist);
if (visitor.d2min < double(within_max_dist) * double(within_max_dist)) {
result = Point(visitor.intersection_pt);
return true;
}
return false;
}
bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locator, std::vector<NodeSPtr>& rerooted_parts)
@ -343,16 +347,16 @@ coord_t Node::prune(const coord_t& pruning_distance)
return max_distance_pruned;
}
void Node::convertToPolylines(Polygons& output, const coord_t line_width) const
void Node::convertToPolylines(Polylines &output, const coord_t line_width) const
{
Polygons result;
Polylines result;
result.emplace_back();
convertToPolylines(0, result);
removeJunctionOverlap(result, line_width);
append(output, std::move(result));
}
void Node::convertToPolylines(size_t long_line_idx, Polygons& output) const
void Node::convertToPolylines(size_t long_line_idx, Polylines &output) const
{
if (m_children.empty()) {
output[long_line_idx].points.push_back(m_p);
@ -372,11 +376,12 @@ void Node::convertToPolylines(size_t long_line_idx, Polygons& output) const
}
}
void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_width) const
void Node::removeJunctionOverlap(Polylines &result_lines, const coord_t line_width) const
{
const coord_t reduction = line_width / 2; // TODO make configurable?
for (auto poly_it = result_lines.begin(); poly_it != result_lines.end(); ) {
Polygon &polyline = *poly_it;
size_t res_line_idx = 0;
while (res_line_idx < result_lines.size()) {
Polyline &polyline = result_lines[res_line_idx];
if (polyline.size() <= 1) {
polyline = std::move(result_lines.back());
result_lines.pop_back();
@ -386,7 +391,7 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt
coord_t to_be_reduced = reduction;
Point a = polyline.back();
for (int point_idx = int(polyline.size()) - 2; point_idx >= 0; point_idx--) {
const Point b = polyline[point_idx];
const Point b = polyline.points[point_idx];
const Point ab = b - a;
const auto ab_len = coord_t(ab.cast<double>().norm());
if (ab_len >= to_be_reduced) {
@ -403,7 +408,7 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt
polyline = std::move(result_lines.back());
result_lines.pop_back();
} else
++ poly_it;
++ res_line_idx;
}
}

View File

@ -239,7 +239,7 @@ public:
*
* \param output all branches in this tree connected into polylines
*/
void convertToPolylines(Polygons& output, coord_t line_width) const;
void convertToPolylines(Polylines &output, coord_t line_width) const;
/*! If this was ever a direct child of the root, it'll have a previous grounding location.
*
@ -258,9 +258,9 @@ protected:
* \param long_line a reference to a polyline in \p output which to continue building on in the recursion
* \param output all branches in this tree connected into polylines
*/
void convertToPolylines(size_t long_line_idx, Polygons& output) const;
void convertToPolylines(size_t long_line_idx, Polylines &output) const;
void removeJunctionOverlap(Polygons& polylines, coord_t line_width) const;
void removeJunctionOverlap(Polylines &polylines, coord_t line_width) const;
bool m_is_root;
Point m_p;
@ -269,6 +269,9 @@ protected:
std::optional<Point> m_last_grounding_location; //<! The last known grounding location, see 'getLastGroundingLocation()'.
friend BoundingBox get_extents(const NodeSPtr &root_node);
friend BoundingBox get_extents(const std::vector<NodeSPtr> &tree_roots);
#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
friend void export_to_svg(const NodeSPtr &root_node, Slic3r::SVG &svg);
friend void export_to_svg(const std::string &path, const Polygons &contour, const std::vector<NodeSPtr> &root_nodes);
@ -278,6 +281,23 @@ protected:
bool inside(const Polygons &polygons, const Point &p);
bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, coord_t within_max_dist);
inline BoundingBox get_extents(const NodeSPtr &root_node)
{
BoundingBox bbox;
for (const NodeSPtr &children : root_node->m_children)
bbox.merge(get_extents(children));
bbox.merge(root_node->getLocation());
return bbox;
}
inline BoundingBox get_extents(const std::vector<NodeSPtr> &tree_roots)
{
BoundingBox bbox;
for (const NodeSPtr &root_node : tree_roots)
bbox.merge(get_extents(root_node));
return bbox;
}
#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
void export_to_svg(const NodeSPtr &root_node, SVG &svg);
void export_to_svg(const std::string &path, const Polygons &contour, const std::vector<NodeSPtr> &root_nodes);

File diff suppressed because it is too large Load Diff

View File

@ -1,359 +1,37 @@
#include "SL1.hpp"
#include "GCode/ThumbnailData.hpp"
#include "libslic3r/Time.hpp"
#include <boost/log/trivial.hpp>
#include <boost/filesystem.hpp>
#include "libslic3r/Zipper.hpp"
#include "libslic3r/SLAPrint.hpp"
#include <sstream>
#include "libslic3r/Time.hpp"
#include "libslic3r/Zipper.hpp"
#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Exception.hpp"
#include "libslic3r/SlicesToTriangleMesh.hpp"
#include "libslic3r/MarchingSquares.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/MTUtils.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/SLA/RasterBase.hpp"
#include "libslic3r/miniz_extension.hpp"
#include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "SLAArchiveReader.hpp"
#include "ZipperArchiveImport.hpp"
#include "libslic3r/MarchingSquares.hpp"
#include "libslic3r/PNGReadWrite.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/Execution/ExecutionTBB.hpp"
#include "libslic3r/SLA/RasterBase.hpp"
#include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
#include <miniz.h>
namespace marchsq {
template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
using Rst = Slic3r::png::ImageGreyscale;
// The type of pixel cell in the raster
using ValueType = uint8_t;
// Value at a given position
static uint8_t get(const Rst &rst, size_t row, size_t col)
{
return rst.get(row, col);
}
// Number of rows and cols of the raster
static size_t rows(const Rst &rst) { return rst.rows; }
static size_t cols(const Rst &rst) { return rst.cols; }
};
} // namespace marchsq
namespace Slic3r {
namespace {
struct PNGBuffer { std::vector<uint8_t> buf; std::string fname; };
struct ArchiveData {
boost::property_tree::ptree profile, config;
std::vector<PNGBuffer> images;
};
static const constexpr char *CONFIG_FNAME = "config.ini";
static const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
MZ_Archive & zip)
{
std::string buf(size_t(entry.m_uncomp_size), '\0');
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0))
throw Slic3r::FileIOError(zip.get_errorstr());
boost::property_tree::ptree tree;
std::stringstream ss(buf);
boost::property_tree::read_ini(ss, tree);
return tree;
}
PNGBuffer read_png(const mz_zip_archive_file_stat &entry,
MZ_Archive & zip,
const std::string & name)
{
std::vector<uint8_t> buf(entry.m_uncomp_size);
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0))
throw Slic3r::FileIOError(zip.get_errorstr());
return {std::move(buf), (name.empty() ? entry.m_filename : name)};
}
ArchiveData extract_sla_archive(const std::string &zipfname,
const std::string &exclude)
{
ArchiveData arch;
// Little RAII
struct Arch: public MZ_Archive {
Arch(const std::string &fname) {
if (!open_zip_reader(&arch, fname))
throw Slic3r::FileIOError(get_errorstr());
}
~Arch() { close_zip_reader(&arch); }
} zip (zipfname);
mz_uint num_entries = mz_zip_reader_get_num_files(&zip.arch);
for (mz_uint i = 0; i < num_entries; ++i)
{
mz_zip_archive_file_stat entry;
if (mz_zip_reader_file_stat(&zip.arch, i, &entry))
{
std::string name = entry.m_filename;
boost::algorithm::to_lower(name);
if (boost::algorithm::contains(name, exclude)) continue;
if (name == CONFIG_FNAME) arch.config = read_ini(entry, zip);
if (name == PROFILE_FNAME) arch.profile = read_ini(entry, zip);
if (boost::filesystem::path(name).extension().string() == ".png") {
auto it = std::lower_bound(
arch.images.begin(), arch.images.end(), PNGBuffer{{}, name},
[](const PNGBuffer &r1, const PNGBuffer &r2) {
return std::less<std::string>()(r1.fname, r2.fname);
});
arch.images.insert(it, read_png(entry, zip, name));
}
}
}
return arch;
}
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
double px_w, double px_h)
{
auto polys = reserve_vector<ExPolygon>(rings.size());
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
for (const marchsq::Coord &crd : ring)
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
polys.emplace_back(poly);
}
// TODO: Is a union necessary?
return union_ex(polys);
}
template<class Fn> void foreach_vertex(ExPolygon &poly, Fn &&fn)
{
for (auto &p : poly.contour.points) fn(p);
for (auto &h : poly.holes)
for (auto &p : h.points) fn(p);
}
void invert_raster_trafo(ExPolygons & expolys,
const sla::RasterBase::Trafo &trafo,
coord_t width,
coord_t height)
{
if (trafo.flipXY) std::swap(height, width);
for (auto &expoly : expolys) {
if (trafo.mirror_y)
foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); });
if (trafo.mirror_x)
foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); });
expoly.translate(-trafo.center_x, -trafo.center_y);
if (trafo.flipXY)
foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); });
if ((trafo.mirror_x + trafo.mirror_y + trafo.flipXY) % 2) {
expoly.contour.reverse();
for (auto &h : expoly.holes) h.reverse();
}
}
}
struct RasterParams {
sla::RasterBase::Trafo trafo; // Raster transformations
coord_t width, height; // scaled raster dimensions (not resolution)
double px_h, px_w; // pixel dimesions
marchsq::Coord win; // marching squares window size
};
RasterParams get_raster_params(const DynamicPrintConfig &cfg)
{
auto *opt_disp_cols = cfg.option<ConfigOptionInt>("display_pixels_x");
auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("display_orientation");
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
!opt_mirror_x || !opt_mirror_y || !opt_orient)
throw MissingProfileError("Invalid SL1 / SL1S file");
RasterParams rstp;
rstp.px_w = opt_disp_w->value / (opt_disp_cols->value - 1);
rstp.px_h = opt_disp_h->value / (opt_disp_rows->value - 1);
rstp.trafo = sla::RasterBase::Trafo{opt_orient->value == sladoLandscape ?
sla::RasterBase::roLandscape :
sla::RasterBase::roPortrait,
{opt_mirror_x->value, opt_mirror_y->value}};
rstp.height = scaled(opt_disp_h->value);
rstp.width = scaled(opt_disp_w->value);
return rstp;
}
struct SliceParams { double layerh = 0., initial_layerh = 0.; };
SliceParams get_slice_params(const DynamicPrintConfig &cfg)
{
auto *opt_layerh = cfg.option<ConfigOptionFloat>("layer_height");
auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height");
if (!opt_layerh || !opt_init_layerh)
throw MissingProfileError("Invalid SL1 / SL1S file");
return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()};
}
std::vector<ExPolygons> extract_slices_from_sla_archive(
ArchiveData & arch,
const RasterParams & rstp,
std::function<bool(int)> progr)
{
auto jobdir = arch.config.get<std::string>("jobDir");
for (auto &c : jobdir) c = std::tolower(c);
std::vector<ExPolygons> slices(arch.images.size());
struct Status
{
double incr, val, prev;
bool stop = false;
tbb::spin_mutex mutex = {};
} st {100. / slices.size(), 0., 0.};
tbb::parallel_for(size_t(0), arch.images.size(),
[&arch, &slices, &st, &rstp, progr](size_t i) {
// Status indication guarded with the spinlock
{
std::lock_guard<tbb::spin_mutex> lck(st.mutex);
if (st.stop) return;
st.val += st.incr;
double curr = std::round(st.val);
if (curr > st.prev) {
st.prev = curr;
st.stop = !progr(int(curr));
}
}
png::ImageGreyscale img;
png::ReadBuf rb{arch.images[i].buf.data(), arch.images[i].buf.size()};
if (!png::decode_png(rb, img)) return;
uint8_t isoval = 128;
auto rings = marchsq::execute(img, isoval, rstp.win);
ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w, rstp.px_h);
// Invert the raster transformations indicated in the profile metadata
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
slices[i] = std::move(expolys);
});
if (st.stop) slices = {};
return slices;
}
} // namespace
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out)
{
ArchiveData arch = extract_sla_archive(zipfname, "png");
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
}
// If the profile is missing from the archive (older PS versions did not have
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
// function return if the archive did not contain any profile.
ConfigSubstitutions import_sla_archive(
const std::string & zipfname,
Vec2i windowsize,
indexed_triangle_set & out,
DynamicPrintConfig & profile_out,
std::function<bool(int)> progr)
{
// Ensure minimum window size for marching squares
windowsize.x() = std::max(2, windowsize.x());
windowsize.y() = std::max(2, windowsize.y());
std::string exclude_entries{"thumbnail"};
ArchiveData arch = extract_sla_archive(zipfname, exclude_entries);
DynamicPrintConfig profile_in, profile_use;
ConfigSubstitutions config_substitutions =
profile_in.load(arch.profile,
ForwardCompatibilitySubstitutionRule::Enable);
if (profile_in.empty()) { // missing profile... do guess work
// try to recover the layer height from the config.ini which was
// present in all versions of sl1 files.
if (auto lh_opt = arch.config.find("layerHeight");
lh_opt != arch.config.not_found())
{
auto lh_str = lh_opt->second.data();
size_t pos;
double lh = string_to_double_decimal_point(lh_str, &pos);
if (pos) { // TODO: verify that pos is 0 when parsing fails
profile_out.set("layer_height", lh);
profile_out.set("initial_layer_height", lh);
}
}
}
// If the archive contains an empty profile, use the one that was passed as output argument
// then replace it with the readed profile to report that it was empty.
profile_use = profile_in.empty() ? profile_out : profile_in;
profile_out = profile_in;
RasterParams rstp = get_raster_params(profile_use);
rstp.win = {windowsize.y(), windowsize.x()};
SliceParams slicp = get_slice_params(profile_use);
std::vector<ExPolygons> slices =
extract_slices_from_sla_archive(arch, rstp, progr);
if (!slices.empty())
out = slices_to_mesh(slices, 0, slicp.layerh, slicp.initial_layerh);
return config_substitutions;
}
using ConfMap = std::map<std::string, std::string>;
namespace {
@ -558,3 +236,207 @@ void SL1Archive::export_print(const std::string fname,
}
} // namespace Slic3r
// /////////////////////////////////////////////////////////////////////////////
// Reader implementation
// /////////////////////////////////////////////////////////////////////////////
namespace marchsq {
template<> struct _RasterTraits<Slic3r::png::ImageGreyscale> {
using Rst = Slic3r::png::ImageGreyscale;
// The type of pixel cell in the raster
using ValueType = uint8_t;
// Value at a given position
static uint8_t get(const Rst &rst, size_t row, size_t col)
{
return rst.get(row, col);
}
// Number of rows and cols of the raster
static size_t rows(const Rst &rst) { return rst.rows; }
static size_t cols(const Rst &rst) { return rst.cols; }
};
} // namespace marchsq
namespace Slic3r {
template<class Fn> static void foreach_vertex(ExPolygon &poly, Fn &&fn)
{
for (auto &p : poly.contour.points) fn(p);
for (auto &h : poly.holes)
for (auto &p : h.points) fn(p);
}
void invert_raster_trafo(ExPolygons & expolys,
const sla::RasterBase::Trafo &trafo,
coord_t width,
coord_t height)
{
if (trafo.flipXY) std::swap(height, width);
for (auto &expoly : expolys) {
if (trafo.mirror_y)
foreach_vertex(expoly, [height](Point &p) {p.y() = height - p.y(); });
if (trafo.mirror_x)
foreach_vertex(expoly, [width](Point &p) {p.x() = width - p.x(); });
expoly.translate(-trafo.center_x, -trafo.center_y);
if (trafo.flipXY)
foreach_vertex(expoly, [](Point &p) { std::swap(p.x(), p.y()); });
if ((trafo.mirror_x + trafo.mirror_y + trafo.flipXY) % 2) {
expoly.contour.reverse();
for (auto &h : expoly.holes) h.reverse();
}
}
}
RasterParams get_raster_params(const DynamicPrintConfig &cfg)
{
auto *opt_disp_cols = cfg.option<ConfigOptionInt>("display_pixels_x");
auto *opt_disp_rows = cfg.option<ConfigOptionInt>("display_pixels_y");
auto *opt_disp_w = cfg.option<ConfigOptionFloat>("display_width");
auto *opt_disp_h = cfg.option<ConfigOptionFloat>("display_height");
auto *opt_mirror_x = cfg.option<ConfigOptionBool>("display_mirror_x");
auto *opt_mirror_y = cfg.option<ConfigOptionBool>("display_mirror_y");
auto *opt_orient = cfg.option<ConfigOptionEnum<SLADisplayOrientation>>("display_orientation");
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
!opt_mirror_x || !opt_mirror_y || !opt_orient)
throw MissingProfileError("Invalid SL1 / SL1S file");
RasterParams rstp;
rstp.px_w = opt_disp_w->value / (opt_disp_cols->value - 1);
rstp.px_h = opt_disp_h->value / (opt_disp_rows->value - 1);
rstp.trafo = sla::RasterBase::Trafo{opt_orient->value == sladoLandscape ?
sla::RasterBase::roLandscape :
sla::RasterBase::roPortrait,
{opt_mirror_x->value, opt_mirror_y->value}};
rstp.height = scaled(opt_disp_h->value);
rstp.width = scaled(opt_disp_w->value);
return rstp;
}
namespace {
ExPolygons rings_to_expolygons(const std::vector<marchsq::Ring> &rings,
double px_w, double px_h)
{
auto polys = reserve_vector<ExPolygon>(rings.size());
for (const marchsq::Ring &ring : rings) {
Polygon poly; Points &pts = poly.points;
pts.reserve(ring.size());
for (const marchsq::Coord &crd : ring)
pts.emplace_back(scaled(crd.c * px_w), scaled(crd.r * px_h));
polys.emplace_back(poly);
}
// TODO: Is a union necessary?
return union_ex(polys);
}
std::vector<ExPolygons> extract_slices_from_sla_archive(
ZipperArchive &arch,
const RasterParams &rstp,
const marchsq::Coord &win,
std::function<bool(int)> progr)
{
std::vector<ExPolygons> slices(arch.entries.size());
struct Status
{
double incr, val, prev;
bool stop = false;
execution::SpinningMutex<ExecutionTBB> mutex = {};
} st{100. / slices.size(), 0., 0.};
execution::for_each(
ex_tbb, size_t(0), arch.entries.size(),
[&arch, &slices, &st, &rstp, &win, progr](size_t i) {
// Status indication guarded with the spinlock
{
std::lock_guard lck(st.mutex);
if (st.stop) return;
st.val += st.incr;
double curr = std::round(st.val);
if (curr > st.prev) {
st.prev = curr;
st.stop = !progr(int(curr));
}
}
png::ImageGreyscale img;
png::ReadBuf rb{arch.entries[i].buf.data(),
arch.entries[i].buf.size()};
if (!png::decode_png(rb, img)) return;
constexpr uint8_t isoval = 128;
auto rings = marchsq::execute(img, isoval, win);
ExPolygons expolys = rings_to_expolygons(rings, rstp.px_w,
rstp.px_h);
// Invert the raster transformations indicated in the profile metadata
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
slices[i] = std::move(expolys);
},
execution::max_concurrency(ex_tbb));
if (st.stop) slices = {};
return slices;
}
} // namespace
ConfigSubstitutions SL1Reader::read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile_out)
{
Vec2i windowsize;
switch(m_quality)
{
case SLAImportQuality::Fast: windowsize = {8, 8}; break;
case SLAImportQuality::Balanced: windowsize = {4, 4}; break;
default:
case SLAImportQuality::Accurate:
windowsize = {2, 2}; break;
};
// Ensure minimum window size for marching squares
windowsize.x() = std::max(2, windowsize.x());
windowsize.y() = std::max(2, windowsize.y());
std::vector<std::string> includes = { "ini", "png"};
std::vector<std::string> excludes = { "thumbnail" };
ZipperArchive arch = read_zipper_archive(m_fname, includes, excludes);
auto [profile_use, config_substitutions] = extract_profile(arch, profile_out);
RasterParams rstp = get_raster_params(profile_use);
marchsq::Coord win = {windowsize.y(), windowsize.x()};
slices = extract_slices_from_sla_archive(arch, rstp, win, m_progr);
return std::move(config_substitutions);
}
ConfigSubstitutions SL1Reader::read(DynamicPrintConfig &out)
{
ZipperArchive arch = read_zipper_archive(m_fname, {}, {"png"});
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
}
} // namespace Slic3r

View File

@ -3,16 +3,15 @@
#include <string>
#include "SLAArchive.hpp"
#include "SLAArchiveWriter.hpp"
#include "SLAArchiveReader.hpp"
#include "libslic3r/Zipper.hpp"
#include "libslic3r/PrintConfig.hpp"
struct indexed_triangle_set;
namespace Slic3r {
class SL1Archive: public SLAArchive {
class SL1Archive: public SLAArchiveWriter {
SLAPrinterConfig m_cfg;
protected:
@ -38,27 +37,41 @@ public:
const ThumbnailsList &thumbnails,
const std::string &projectname = "") override;
};
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out);
ConfigSubstitutions import_sla_archive(
const std::string & zipfname,
Vec2i windowsize,
indexed_triangle_set & out,
DynamicPrintConfig & profile,
std::function<bool(int)> progr = [](int) { return true; });
class SL1Reader: public SLAArchiveReader {
SLAImportQuality m_quality = SLAImportQuality::Balanced;
std::function<bool(int)> m_progr;
std::string m_fname;
inline ConfigSubstitutions import_sla_archive(
const std::string & zipfname,
Vec2i windowsize,
indexed_triangle_set & out,
std::function<bool(int)> progr = [](int) { return true; })
{
DynamicPrintConfig profile;
return import_sla_archive(zipfname, windowsize, out, profile, progr);
}
public:
// If the profile is missing from the archive (older PS versions did not have
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
// function return if the archive did not contain any profile.
ConfigSubstitutions read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile_out) override;
class MissingProfileError : public RuntimeError { using RuntimeError::RuntimeError; };
ConfigSubstitutions read(DynamicPrintConfig &profile) override;
SL1Reader() = default;
SL1Reader(const std::string &fname,
SLAImportQuality quality,
std::function<bool(int)> progr)
: m_quality(quality), m_progr(progr), m_fname(fname)
{}
};
struct RasterParams {
sla::RasterBase::Trafo trafo; // Raster transformations
coord_t width, height; // scaled raster dimensions (not resolution)
double px_h, px_w; // pixel dimesions
};
RasterParams get_raster_params(const DynamicPrintConfig &cfg);
void invert_raster_trafo(ExPolygons & expolys,
const sla::RasterBase::Trafo &trafo,
coord_t width,
coord_t height);
} // namespace Slic3r::sla

View File

@ -3,6 +3,10 @@
#include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/Format/ZipperArchiveImport.hpp"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#include <limits>
#include <cstdint>
@ -16,6 +20,7 @@ namespace {
size_t constexpr coord_t_bufsize = 40;
// A fast and locale independent implementation of int=>str
char const* decimal_from(coord_t snumber, char* buffer)
{
std::make_unsigned_t<coord_t> number = 0;
@ -50,6 +55,7 @@ inline std::string coord2str(coord_t crd)
return decimal_from(crd, buf);
}
// Apply the sla::RasterBase::Trafo onto an ExPolygon
void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBox &bb)
{
if (tr.flipXY) {
@ -71,12 +77,13 @@ void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBo
}
}
// Append the svg string representation of a Polygon to the input 'buf'
void append_svg(std::string &buf, const Polygon &poly)
{
if (poly.points.empty())
return;
auto c = poly.points.front();
Point c = poly.points.front();
char intbuf[coord_t_bufsize];
@ -84,15 +91,16 @@ void append_svg(std::string &buf, const Polygon &poly)
buf += decimal_from(c.x(), intbuf);
buf += " "sv;
buf += decimal_from(c.y(), intbuf);
buf += " m"sv;
buf += " l "sv;
for (auto &p : poly) {
auto d = p - c;
if (d.squaredNorm() == 0) continue;
for (const Point &p : poly) {
Point d = p - c;
if (d.x() == 0 && d.y() == 0)
continue;
buf += " "sv;
buf += decimal_from(p.x() - c.x(), intbuf);
buf += decimal_from(d.x(), intbuf);
buf += " "sv;
buf += decimal_from(p.y() - c.y(), intbuf);
buf += decimal_from(d.y(), intbuf);
c = p;
}
buf += " z\""sv; // mark path as closed
@ -138,9 +146,6 @@ public:
"<svg height=\"" + hf + "mm" + "\" width=\"" + wf + "mm" + "\" viewBox=\"0 0 " + w + " " + h +
"\" style=\"fill: white; stroke: none; fill-rule: nonzero\" "
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
// Add black background;
m_svg += "<rect fill='black' stroke='none' x='0' y='0' width='" + w + "' height='" + h + "'/>\n";
}
void draw(const ExPolygon& poly) override
@ -170,6 +175,8 @@ public:
Trafo trafo() const override { return m_trafo; }
// The encoder is ignored here, the svg text does not need any further
// encoding.
sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override
{
std::vector<uint8_t> data;
@ -189,13 +196,11 @@ std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
auto w = cfg().display_width.getFloat();
auto h = cfg().display_height.getFloat();
// auto res_x = size_t(cfg().display_pixels_x.getInt());
// auto res_y = size_t(cfg().display_pixels_y.getInt());
float precision_nm = scaled<float>(cfg().sla_output_precision.getFloat());
size_t res_x = std::round(scaled(w) / precision_nm);
size_t res_y = std::round(scaled(h) / precision_nm);
auto res_x = size_t(std::round(scaled(w) / precision_nm));
auto res_y = size_t(std::round(scaled(h) / precision_nm));
std::array<bool, 2> mirror;
std::array<bool, 2> mirror;
mirror[X] = cfg().display_mirror_x.getBool();
mirror[Y] = cfg().display_mirror_y.getBool();
@ -219,6 +224,7 @@ std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
return std::make_unique<SVGRaster>(svgarea, sla::Resolution{res_x, res_y}, tr);
}
// SVG does not need additional binary encoding.
sla::RasterEncoder SL1_SVGArchive::get_encoder() const
{
return nullptr;
@ -229,9 +235,83 @@ void SL1_SVGArchive::export_print(const std::string fname,
const ThumbnailsList &thumbnails,
const std::string &projectname)
{
// Export code is completely identical to SL1, only the compression level
// is elevated, as the SL1 has already compressed PNGs with deflate,
// but the svg is just text.
Zipper zipper{fname, Zipper::TIGHT_COMPRESSION};
SL1Archive::export_print(zipper, print, thumbnails, projectname);
}
struct NanoSVGParser {
NSVGimage *image;
static constexpr const char *Units = "mm"; // Denotes user coordinate system
static constexpr float Dpi = 1.f; // Not needed
explicit NanoSVGParser(char* input): image{nsvgParse(input, Units, Dpi)} {}
~NanoSVGParser() { nsvgDelete(image); }
};
ConfigSubstitutions SL1_SVGReader::read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile_out)
{
std::vector<std::string> includes = { CONFIG_FNAME, PROFILE_FNAME, "svg"};
ZipperArchive arch = read_zipper_archive(m_fname, includes, {});
auto [profile_use, config_substitutions] = extract_profile(arch, profile_out);
RasterParams rstp = get_raster_params(profile_use);
struct Status
{
double incr, val, prev;
bool stop = false;
} st{100. / arch.entries.size(), 0., 0.};
for (const EntryBuffer &entry : arch.entries) {
if (st.stop) break;
st.val += st.incr;
double curr = std::round(st.val);
if (curr > st.prev) {
st.prev = curr;
st.stop = !m_progr(int(curr));
}
// Don't want to use dirty casts for the buffer to be usable in
// the NanoSVGParser until performance is not a bottleneck here.
auto svgtxt = reserve_vector<char>(entry.buf.size() + 1);
std::copy(entry.buf.begin(), entry.buf.end(), std::back_inserter(svgtxt));
svgtxt.emplace_back('\0');
NanoSVGParser svgp(svgtxt.data());
Polygons polys;
for (NSVGshape *shape = svgp.image->shapes; shape != nullptr; shape = shape->next) {
for (NSVGpath *path = shape->paths; path != nullptr; path = path->next) {
Polygon p;
for (int i = 0; i < path->npts; ++i) {
size_t c = 2 * i;
p.points.emplace_back(scaled(Vec2f(path->pts[c], path->pts[c + 1])));
}
polys.emplace_back(p);
}
}
// Create the slice from the read polygons. Here, the fill rule has to
// be the same as stated in the svg file which is `nonzero` when exported
// using SL1_SVGArchive. Would be better to parse it from the svg file,
// but if it's different, the file is probably corrupted anyways.
ExPolygons expolys = union_ex(polys, ClipperLib::pftNonZero);
invert_raster_trafo(expolys, rstp.trafo, rstp.width, rstp.height);
slices.emplace_back(expolys);
}
// Compile error without the move
return std::move(config_substitutions);
}
ConfigSubstitutions SL1_SVGReader::read(DynamicPrintConfig &out)
{
ZipperArchive arch = read_zipper_archive(m_fname, {"prusaslicer.ini"}, {});
return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable);
}
} // namespace Slic3r

View File

@ -22,6 +22,27 @@ public:
using SL1Archive::SL1Archive;
};
class SL1_SVGReader: public SLAArchiveReader {
std::function<bool(int)> m_progr;
std::string m_fname;
public:
// If the profile is missing from the archive (older PS versions did not have
// it), profile_out's initial value will be used as fallback. profile_out will be empty on
// function return if the archive did not contain any profile.
ConfigSubstitutions read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile_out) override;
ConfigSubstitutions read(DynamicPrintConfig &profile) override;
SL1_SVGReader() = default;
SL1_SVGReader(const std::string &fname,
SLAImportQuality /*quality*/,
const ProgrFn & progr)
: m_progr(progr), m_fname(fname)
{}
};
} // namespace Slic3r
#endif // SL1_SVG_HPP

View File

@ -0,0 +1,179 @@
#include "SLAArchiveReader.hpp"
#include "SL1.hpp"
#include "SL1_SVG.hpp"
#include "libslic3r/SlicesToTriangleMesh.hpp"
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
constexpr const char * L(const char * str) { return str; }
#include <array>
#include <map>
namespace Slic3r {
namespace {
// Factory function that returns an implementation of SLAArchiveReader.
using ArchiveFactory = std::function<
std::unique_ptr<SLAArchiveReader>(const std::string &fname,
SLAImportQuality quality,
const ProgrFn & progr)>;
// Entry in the global registry of readable archive formats.
struct ArchiveEntry {
const char *descr;
std::vector<const char *> extensions;
ArchiveFactory factoryfn;
};
// This is where the readable archive formats are registered.
static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
{
"SL1",
{ L("SL1 / SL1S archive files"), {"sl1", "sl1s", "zip"},
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1Reader>(fname, quality, progr); } }
},
{
"SL2",
{ L("SL2 archive files"), {"sl2", "sl1_svg"/*, "zip"*/}, // also a zip but unnecessary hassle to implement single extension for multiple archives
[] (const std::string &fname, SLAImportQuality quality, const ProgrFn &progr) { return std::make_unique<SL1_SVGReader>(fname, quality, progr); }}
},
// TODO: pwmx and future others.
};
} // namespace
std::unique_ptr<SLAArchiveReader> SLAArchiveReader::create(
const std::string &fname,
const std::string &format_id,
SLAImportQuality quality,
const ProgrFn & progr)
{
// Create an instance of SLAArchiveReader using the registered archive
// reader implementations.
// If format_id is specified and valid, that archive format will be
// preferred. When format_id is emtpy, the file extension is compared
// with the advertised extensions of registered readers and the first
// match will be used.
std::string ext = boost::filesystem::path(fname).extension().string();
boost::algorithm::to_lower(ext);
std::unique_ptr<SLAArchiveReader> ret;
auto arch_from = REGISTERED_ARCHIVES.begin();
auto arch_to = REGISTERED_ARCHIVES.end();
auto arch_it = REGISTERED_ARCHIVES.find(format_id);
if (arch_it != REGISTERED_ARCHIVES.end()) {
arch_from = arch_it;
arch_to = arch_it;
}
if (!ext.empty()) {
if (ext.front() == '.')
ext.erase(ext.begin());
auto extcmp = [&ext](const auto &e) { return e == ext; };
for (auto it = arch_from; it != arch_to; ++it) {
const auto &[format_id, entry] = *it;
if (std::any_of(entry.extensions.begin(), entry.extensions.end(), extcmp))
ret = entry.factoryfn(fname, quality, progr);
}
}
return ret;
}
const std::vector<const char *> &SLAArchiveReader::registered_archives()
{
static std::vector<const char*> archnames;
if (archnames.empty()) {
archnames.reserve(REGISTERED_ARCHIVES.size());
for (auto &[name, _] : REGISTERED_ARCHIVES)
archnames.emplace_back(name.c_str());
}
return archnames;
}
std::vector<const char *> SLAArchiveReader::get_extensions(const char *archtype)
{
auto it = REGISTERED_ARCHIVES.find(archtype);
if (it != REGISTERED_ARCHIVES.end())
return it->second.extensions;
return {};
}
const char *SLAArchiveReader::get_description(const char *archtype)
{
auto it = REGISTERED_ARCHIVES.find(archtype);
if (it != REGISTERED_ARCHIVES.end())
return it->second.descr;
return nullptr;
}
struct SliceParams { double layerh = 0., initial_layerh = 0.; };
static SliceParams get_slice_params(const DynamicPrintConfig &cfg)
{
auto *opt_layerh = cfg.option<ConfigOptionFloat>("layer_height");
auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height");
if (!opt_layerh || !opt_init_layerh)
throw MissingProfileError("Invalid SL1 / SL1S file");
return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()};
}
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
const std::string &format_id,
indexed_triangle_set &out,
DynamicPrintConfig &profile,
SLAImportQuality quality,
const ProgrFn & progr)
{
ConfigSubstitutions ret;
if (auto reader = SLAArchiveReader::create(zipfname, format_id, quality, progr)) {
std::vector<ExPolygons> slices;
ret = reader->read(slices, profile);
SliceParams slicp = get_slice_params(profile);
if (!slices.empty())
out = slices_to_mesh(slices, 0, slicp.layerh, slicp.initial_layerh);
} else {
throw ReaderUnimplementedError("Reader unimplemented");
}
return ret;
}
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
const std::string &format_id,
DynamicPrintConfig &out)
{
ConfigSubstitutions ret;
if (auto reader = SLAArchiveReader::create(zipfname, format_id)) {
ret = reader->read(out);
} else {
throw ReaderUnimplementedError("Reader unimplemented");
}
return ret;
}
} // namespace Slic3r

View File

@ -0,0 +1,85 @@
#ifndef SLAARCHIVEREADER_HPP
#define SLAARCHIVEREADER_HPP
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/ExPolygon.hpp"
struct indexed_triangle_set;
namespace Slic3r {
// A generic indicator for the quality of an imported model. Obviously, the
// original cannot be fully reconstructed.
enum class SLAImportQuality { Accurate, Balanced, Fast };
// Raised when the needed metadata cannot be retrieved or guessed from an archive
class MissingProfileError : public RuntimeError
{
using RuntimeError::RuntimeError;
};
// A shortname for status indication function.
// The argument is the status (from <0, 100>)
// Returns false if cancel was requested.
using ProgrFn = std::function<bool(int)>;
// Abstract interface for an archive reader. This needs to be implemented for
// every supported archive format.
class SLAArchiveReader {
public:
virtual ~SLAArchiveReader() = default;
// Read the profile and reconstruct the slices
virtual ConfigSubstitutions read(std::vector<ExPolygons> &slices,
DynamicPrintConfig &profile) = 0;
// Overload for reading only the profile contained in the archive (if present)
virtual ConfigSubstitutions read(DynamicPrintConfig &profile) = 0;
// Creates a reader instance based on the provided file path.
// format_id can be one of the archive type identifiers returned by
// registered_archives(). If left empty, only the file extension will
// be considered. If more archive types have the same extension (like *.zip)
// The first match is used.
static std::unique_ptr<SLAArchiveReader> create(
const std::string &fname,
const std::string &format_id,
SLAImportQuality quality = SLAImportQuality::Balanced,
const ProgrFn &progr = [](int) { return false; });
// Get the names of currently known archive reader implementations
static const std::vector<const char *> & registered_archives();
// Get the understood file extensions belonging to an archive format
static std::vector<const char *> get_extensions(const char *archtype);
// Generic description (usable in GUI) about an archive format
static const char * get_description(const char *archtype);
};
// Raised in import_sla_archive when a nullptr reader is returned by
// SLAArchiveReader::create()
class ReaderUnimplementedError : public RuntimeError
{
using RuntimeError::RuntimeError;
};
// Helper free functions to import an archive using the above interface.
// Can throw ReaderUnimplementedError or MissingProfileError
ConfigSubstitutions import_sla_archive(
const std::string &zipfname,
const std::string &format_id,
indexed_triangle_set &out,
DynamicPrintConfig &profile,
SLAImportQuality quality = SLAImportQuality::Balanced,
const ProgrFn &progr = [](int) { return true; });
// Only reads the profile, doesn't reconstruct the model.
ConfigSubstitutions import_sla_archive(const std::string &zipfname,
const std::string &format_id,
DynamicPrintConfig &out);
} // namespace Slic3r
#endif // SLAARCHIVEREADER_HPP

View File

@ -1,4 +1,4 @@
#include "SLAArchive.hpp"
#include "SLAArchiveWriter.hpp"
#include "SL1.hpp"
#include "SL1_SVG.hpp"
@ -13,7 +13,7 @@
namespace Slic3r {
using ArchiveFactory = std::function<std::unique_ptr<SLAArchive>(const SLAPrinterConfig&)>;
using ArchiveFactory = std::function<std::unique_ptr<SLAArchiveWriter>(const SLAPrinterConfig&)>;
struct ArchiveEntry {
const char *ext;
@ -35,8 +35,8 @@ static const std::map<std::string, ArchiveEntry> REGISTERED_ARCHIVES {
}
};
std::unique_ptr<SLAArchive>
SLAArchive::create(const std::string &archtype, const SLAPrinterConfig &cfg)
std::unique_ptr<SLAArchiveWriter>
SLAArchiveWriter::create(const std::string &archtype, const SLAPrinterConfig &cfg)
{
auto entry = REGISTERED_ARCHIVES.find(archtype);
@ -46,7 +46,7 @@ SLAArchive::create(const std::string &archtype, const SLAPrinterConfig &cfg)
return nullptr;
}
const std::vector<const char*>& SLAArchive::registered_archives()
const std::vector<const char*>& SLAArchiveWriter::registered_archives()
{
static std::vector<const char*> archnames;
@ -60,9 +60,9 @@ const std::vector<const char*>& SLAArchive::registered_archives()
return archnames;
}
const char *SLAArchive::get_extension(const char *archtype)
const char *SLAArchiveWriter::get_extension(const char *archtype)
{
static const char* DEFAULT_EXT = "zip";
constexpr const char* DEFAULT_EXT = "zip";
auto entry = REGISTERED_ARCHIVES.find(archtype);
if (entry != REGISTERED_ARCHIVES.end())

View File

@ -12,7 +12,7 @@ namespace Slic3r {
class SLAPrint;
class SLAPrinterConfig;
class SLAArchive {
class SLAArchiveWriter {
protected:
std::vector<sla::EncodedRaster> m_layers;
@ -20,7 +20,7 @@ protected:
virtual sla::RasterEncoder get_encoder() const = 0;
public:
virtual ~SLAArchive() = default;
virtual ~SLAArchiveWriter() = default;
// Fn have to be thread safe: void(sla::RasterBase& raster, size_t lyrid);
template<class Fn, class CancelFn, class EP = ExecutionTBB>
@ -44,14 +44,15 @@ public:
execution::max_concurrency(ep));
}
// Export the print into an archive using the provided filename.
// Export the print into an archive using the provided filename.
virtual void export_print(const std::string fname,
const SLAPrint &print,
const ThumbnailsList &thumbnails,
const std::string &projectname = "") = 0;
// Factory method to create an archiver instance
static std::unique_ptr<SLAArchive> create(const std::string &archtype, const SLAPrinterConfig&);
static std::unique_ptr<SLAArchiveWriter> create(
const std::string &archtype, const SLAPrinterConfig &);
// Get the names of currently known archiver implementations
static const std::vector<const char *> & registered_archives();

View File

@ -0,0 +1,136 @@
#include "ZipperArchiveImport.hpp"
#include "libslic3r/miniz_extension.hpp"
#include "libslic3r/Exception.hpp"
#include "libslic3r/PrintConfig.hpp"
#include <boost/property_tree/ini_parser.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string.hpp>
namespace Slic3r {
namespace {
// Read an ini file into boost property tree
boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
MZ_Archive &zip)
{
std::string buf(size_t(entry.m_uncomp_size), '\0');
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0))
throw Slic3r::FileIOError(zip.get_errorstr());
boost::property_tree::ptree tree;
std::stringstream ss(buf);
boost::property_tree::read_ini(ss, tree);
return tree;
}
// Read an arbitrary file into EntryBuffer
EntryBuffer read_entry(const mz_zip_archive_file_stat &entry,
MZ_Archive &zip,
const std::string &name)
{
std::vector<uint8_t> buf(entry.m_uncomp_size);
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0))
throw Slic3r::FileIOError(zip.get_errorstr());
return {std::move(buf), (name.empty() ? entry.m_filename : name)};
}
} // namespace
ZipperArchive read_zipper_archive(const std::string &zipfname,
const std::vector<std::string> &includes,
const std::vector<std::string> &excludes)
{
ZipperArchive arch;
// Little RAII
struct Arch : public MZ_Archive
{
Arch(const std::string &fname)
{
if (!open_zip_reader(&arch, fname))
throw Slic3r::FileIOError(get_errorstr());
}
~Arch() { close_zip_reader(&arch); }
} zip(zipfname);
mz_uint num_entries = mz_zip_reader_get_num_files(&zip.arch);
for (mz_uint i = 0; i < num_entries; ++i) {
mz_zip_archive_file_stat entry;
if (mz_zip_reader_file_stat(&zip.arch, i, &entry)) {
std::string name = entry.m_filename;
boost::algorithm::to_lower(name);
if (!std::any_of(includes.begin(), includes.end(),
[&name](const std::string &incl) {
return boost::algorithm::contains(name, incl);
}))
continue;
if (std::any_of(excludes.begin(), excludes.end(),
[&name](const std::string &excl) {
return boost::algorithm::contains(name, excl);
}))
continue;
if (name == CONFIG_FNAME) { arch.config = read_ini(entry, zip); continue; }
if (name == PROFILE_FNAME) { arch.profile = read_ini(entry, zip); continue; }
auto it = std::lower_bound(
arch.entries.begin(), arch.entries.end(),
EntryBuffer{{}, name},
[](const EntryBuffer &r1, const EntryBuffer &r2) {
return std::less<std::string>()(r1.fname, r2.fname);
});
arch.entries.insert(it, read_entry(entry, zip, name));
}
}
return arch;
}
std::pair<DynamicPrintConfig, ConfigSubstitutions> extract_profile(
const ZipperArchive &arch, DynamicPrintConfig &profile_out)
{
DynamicPrintConfig profile_in, profile_use;
ConfigSubstitutions config_substitutions =
profile_in.load(arch.profile,
ForwardCompatibilitySubstitutionRule::Enable);
if (profile_in.empty()) { // missing profile... do guess work
// try to recover the layer height from the config.ini which was
// present in all versions of sl1 files.
if (auto lh_opt = arch.config.find("layerHeight");
lh_opt != arch.config.not_found()) {
auto lh_str = lh_opt->second.data();
size_t pos = 0;
double lh = string_to_double_decimal_point(lh_str, &pos);
if (pos) { // TODO: verify that pos is 0 when parsing fails
profile_out.set("layer_height", lh);
profile_out.set("initial_layer_height", lh);
}
}
}
// If the archive contains an empty profile, use the one that was passed
// as output argument then replace it with the readed profile to report
// that it was empty.
profile_use = profile_in.empty() ? profile_out : profile_in;
profile_out = profile_in;
return {profile_use, std::move(config_substitutions)};
}
} // namespace Slic3r

View File

@ -0,0 +1,54 @@
#ifndef ZIPPERARCHIVEIMPORT_HPP
#define ZIPPERARCHIVEIMPORT_HPP
#include <vector>
#include <string>
#include <cstdint>
#include <boost/property_tree/ptree.hpp>
#include "libslic3r/PrintConfig.hpp"
namespace Slic3r {
// Buffer for arbitraryfiles inside a zipper archive.
struct EntryBuffer
{
std::vector<uint8_t> buf;
std::string fname;
};
// Structure holding the data read from a zipper archive.
struct ZipperArchive
{
boost::property_tree::ptree profile, config;
std::vector<EntryBuffer> entries;
};
// Names of the files containing metadata inside the archive.
const constexpr char *CONFIG_FNAME = "config.ini";
const constexpr char *PROFILE_FNAME = "prusaslicer.ini";
// Read an archive that was written using the Zipper class.
// The includes parameter is a set of file name substrings that the entries
// must contain to be included in ZipperArchive.
// The excludes parameter may contain substrings that filenames must not
// contain.
// Every file in the archive is read into ZipperArchive::entries
// except the files CONFIG_FNAME, and PROFILE_FNAME which are read into
// ZipperArchive::config and ZipperArchive::profile structures.
ZipperArchive read_zipper_archive(const std::string &zipfname,
const std::vector<std::string> &includes,
const std::vector<std::string> &excludes);
// Extract the print profile form the archive into 'out'.
// Returns a profile that has correct parameters to use for model reconstruction
// even if the needed parameters were not fully found in the archive's metadata.
// The inout argument shall be a usable fallback profile if the archive
// has totally corrupted metadata.
std::pair<DynamicPrintConfig, ConfigSubstitutions> extract_profile(
const ZipperArchive &arch, DynamicPrintConfig &inout);
} // namespace Slic3r
#endif // ZIPPERARCHIVEIMPORT_HPP

View File

@ -3,13 +3,13 @@
#include <string>
#include "SLAArchive.hpp"
#include "SLAArchiveWriter.hpp"
#include "libslic3r/PrintConfig.hpp"
namespace Slic3r {
class PwmxArchive: public SLAArchive {
class PwmxArchive: public SLAArchiveWriter {
SLAPrinterConfig m_cfg;
protected:

View File

@ -2312,7 +2312,6 @@ GCode::LayerResult GCode::process_layer(
} // for objects
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
std::vector<std::unique_ptr<EdgeGrid::Grid>> lower_layer_edge_grids(layers.size());
for (unsigned int extruder_id : layer_tools.extruders)
{
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
@ -2337,7 +2336,7 @@ GCode::LayerResult GCode::process_layer(
path.mm3_per_mm = mm3_per_mm;
}
//FIXME using the support_material_speed of the 1st object printed.
gcode += this->extrude_loop(loop, "skirt", m_config.support_material_speed.value);
gcode += this->extrude_loop(loop, "skirt"sv, m_config.support_material_speed.value);
}
m_avoid_crossing_perimeters.use_external_mp(false);
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
@ -2350,7 +2349,7 @@ GCode::LayerResult GCode::process_layer(
this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp();
for (const ExtrusionEntity *ee : print.brim().entities) {
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
gcode += this->extrude_entity(*ee, "brim"sv, m_config.support_material_speed.value);
}
m_brim_done = true;
m_avoid_crossing_perimeters.use_external_mp(false);
@ -2406,9 +2405,9 @@ GCode::LayerResult GCode::process_layer(
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
if (print.config().infill_first) {
gcode += this->extrude_infill(print, by_region_specific, false);
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
gcode += this->extrude_perimeters(print, by_region_specific);
} else {
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
gcode += this->extrude_perimeters(print, by_region_specific);
gcode += this->extrude_infill(print,by_region_specific, false);
}
// ironing
@ -2543,51 +2542,28 @@ std::string GCode::change_layer(coordf_t print_z)
return gcode;
}
static std::unique_ptr<EdgeGrid::Grid> calculate_layer_edge_grid(const Layer& layer)
{
auto out = make_unique<EdgeGrid::Grid>();
// Create the distance field for a layer below.
const coord_t distance_field_resolution = coord_t(scale_(1.) + 0.5);
out->create(layer.lslices, distance_field_resolution);
out->calculate_sdf();
#if 0
{
static int iRun = 0;
BoundingBox bbox = (*lower_layer_edge_grid)->bbox();
bbox.min(0) -= scale_(5.f);
bbox.min(1) -= scale_(5.f);
bbox.max(0) += scale_(5.f);
bbox.max(1) += scale_(5.f);
EdgeGrid::save_png(*(*lower_layer_edge_grid), bbox, scale_(0.1f), debug_out_path("GCode_extrude_loop_edge_grid-%d.png", iRun++));
}
#endif
return out;
static const auto comment_perimeter = "perimeter"sv;
// Comparing string_view pointer & length for speed.
static inline bool comment_is_perimeter(const std::string_view comment) {
return comment.data() == comment_perimeter.data() && comment.size() == comment_perimeter.size();
}
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view description, double speed)
{
// get a copy; don't modify the orientation of the original loop object otherwise
// next copies (if any) would not detect the correct orientation
if (m_layer->lower_layer && lower_layer_edge_grid != nullptr && ! *lower_layer_edge_grid)
*lower_layer_edge_grid = calculate_layer_edge_grid(*m_layer->lower_layer);
// extrude all loops ccw
bool was_clockwise = loop.make_counter_clockwise();
// find the point of the loop that is closest to the current extruder position
// or randomize if requested
Point last_pos = this->last_pos();
if (m_config.spiral_vase) {
if (! m_config.spiral_vase && comment_is_perimeter(description)) {
assert(m_layer != nullptr);
m_seam_placer.place_seam(m_layer, loop, m_config.external_perimeters_first, this->last_pos());
} else
loop.split_at(last_pos, false);
}
else
m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first,
EXTRUDER_CONFIG(nozzle_diameter), lower_layer_edge_grid ? lower_layer_edge_grid->get() : nullptr);
// clip the path to avoid the extruder to get exactly on the first point of the loop;
// if polyline was shorter than the clipping distance we'd get a null polyline, so
@ -2607,11 +2583,9 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path
std::string gcode;
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
// description += ExtrusionLoop::role_to_string(loop.loop_role());
// description += ExtrusionEntity::role_to_string(path->role);
path->simplify(m_scaled_resolution);
gcode += this->_extrude(*path, description, speed);
for (ExtrusionPath &path : paths) {
path.simplify(m_scaled_resolution);
gcode += this->_extrude(path, description, speed);
}
// reset acceleration
@ -2626,18 +2600,19 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// the side depends on the original winding order of the polygon (left for contours, right for holes)
//FIXME improve the algorithm in case the loop is tiny.
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
Point a = paths.front().polyline.points[1]; // second point
Point b = *(paths.back().polyline.points.end()-3); // second to last point
// Angle from the 2nd point to the last point.
double angle_inside = angle(paths.front().polyline.points[1] - paths.front().first_point(),
*(paths.back().polyline.points.end()-3) - paths.front().first_point());
assert(angle_inside >= -M_PI && angle_inside <= M_PI);
// 3rd of this angle will be taken, thus make the angle monotonic before interpolation.
if (was_clockwise) {
// swap points
Point c = a; a = b; b = c;
if (angle_inside > 0)
angle_inside -= 2.0 * M_PI;
} else {
if (angle_inside < 0)
angle_inside += 2.0 * M_PI;
}
double angle = paths.front().first_point().ccw_angle(a, b) / 3;
// turn left if contour, turn right if hole
if (was_clockwise) angle *= -1;
// create the destination point along the first segment and rotate it
// we make sure we don't exceed the segment length because we don't know
// the rotation of the second segment so we might cross the object boundary
@ -2649,7 +2624,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// Shift by no more than a nozzle diameter.
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
Point pt = ((nd * nd >= l2) ? p2 : (p1 + v * (nd / sqrt(l2)))).cast<coord_t>();
pt.rotate(angle, paths.front().polyline.points.front());
// Rotate pt inside around the seam point.
pt.rotate(angle_inside / 3., paths.front().polyline.points.front());
// generate the travel move
gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), "move inwards before travel");
}
@ -2657,13 +2633,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
return gcode;
}
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string description, double speed)
std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::string_view description, double speed)
{
// extrude along the path
std::string gcode;
for (ExtrusionPath path : multipath.paths) {
// description += ExtrusionLoop::role_to_string(loop.loop_role());
// description += ExtrusionEntity::role_to_string(path->role);
path.simplify(m_scaled_resolution);
gcode += this->_extrude(path, description, speed);
}
@ -2676,22 +2650,21 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
return gcode;
}
std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string description, double speed, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed)
{
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity))
return this->extrude_path(*path, description, speed);
else if (const ExtrusionMultiPath* multipath = dynamic_cast<const ExtrusionMultiPath*>(&entity))
return this->extrude_multi_path(*multipath, description, speed);
else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity))
return this->extrude_loop(*loop, description, speed, lower_layer_edge_grid);
return this->extrude_loop(*loop, description, speed);
else
throw Slic3r::InvalidArgument("Invalid argument supplied to extrude()");
return "";
}
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed)
std::string GCode::extrude_path(ExtrusionPath path, std::string_view description, double speed)
{
// description += ExtrusionEntity::role_to_string(path.role());
path.simplify(m_scaled_resolution);
std::string gcode = this->_extrude(path, description, speed);
if (m_wipe.enable) {
@ -2704,24 +2677,15 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
}
// Extrude perimeters: Decide where to put seams (hide or align seams).
std::string GCode::extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid)
std::string GCode::extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region)
{
std::string gcode;
for (const ObjectByExtruder::Island::Region &region : by_region)
if (! region.perimeters.empty()) {
m_config.apply(print.get_print_region(&region - &by_region.front()).config());
// plan_perimeters tries to place seams, it needs to have the lower_layer_edge_grid calculated already.
if (m_layer->lower_layer && ! lower_layer_edge_grid)
lower_layer_edge_grid = calculate_layer_edge_grid(*m_layer->lower_layer);
m_seam_placer.plan_perimeters(std::vector<const ExtrusionEntity*>(region.perimeters.begin(), region.perimeters.end()),
*m_layer, m_config.seam_position, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
(m_layer == NULL ? nullptr : m_layer->object()),
(lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr));
for (const ExtrusionEntity* ee : region.perimeters)
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
gcode += this->extrude_entity(*ee, comment_perimeter, -1.);
}
return gcode;
}
@ -2731,7 +2695,7 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
{
std::string gcode;
ExtrusionEntitiesPtr extrusions;
const char* extrusion_name = ironing ? "ironing" : "infill";
const auto extrusion_name = ironing ? "ironing"sv : "infill"sv;
for (const ObjectByExtruder::Island::Region &region : by_region)
if (! region.infills.empty()) {
extrusions.clear();
@ -2757,8 +2721,8 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills)
{
static constexpr const char *support_label = "support material";
static constexpr const char *support_interface_label = "support material interface";
static constexpr const auto support_label = "support material"sv;
static constexpr const auto support_interface_label = "support material interface"sv;
std::string gcode;
if (! support_fills.entities.empty()) {
@ -2767,7 +2731,7 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
for (const ExtrusionEntity *ee : support_fills.entities) {
ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface);
const char *label = (role == erSupportMaterial) ? support_label : support_interface_label;
const auto label = (role == erSupportMaterial) ? support_label : support_interface_label;
const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed;
const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee);
if (path)
@ -2855,20 +2819,18 @@ void GCode::GCodeOutputStream::write_format(const char* format, ...)
va_end(args);
}
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed)
std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view description, double speed)
{
std::string gcode;
if (is_bridge(path.role()))
description += " (bridge)";
const std::string_view description_bridge = is_bridge(path.role()) ? " (bridge)"sv : ""sv;
// go to first point of extrusion path
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
gcode += this->travel_to(
path.first_point(),
path.role(),
"move to first " + description + " point"
);
std::string comment = "move to first ";
comment += description;
comment += description_bridge;
comment += " point";
gcode += this->travel_to(path.first_point(), path.role(), comment);
}
// compensate retraction
@ -3006,7 +2968,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
gcode += m_writer.set_speed(F, "", comment);
double path_length = 0.;
{
std::string comment = m_config.gcode_comments ? description : "";
std::string comment;
if (m_config.gcode_comments) {
comment = description;
comment += description_bridge;
}
Vec2d prev = this->point_to_gcode_quantized(path.polyline.points.front());
auto it = path.polyline.points.begin();
auto end = path.polyline.points.end();
@ -3097,7 +3063,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role)
if (role == erSupportMaterial) {
const SupportLayer* support_layer = dynamic_cast<const SupportLayer*>(m_layer);
//FIXME support_layer->support_islands.contains should use some search structure!
if (support_layer != NULL && support_layer->support_islands.contains(travel))
if (support_layer != NULL && ! intersection_pl(travel, support_layer->support_islands).empty())
// skip retraction if this is a travel move inside a support material island
//FIXME not retracting over a long path may cause oozing, which in turn may result in missing material
// at the end of the extrusion path!

View File

@ -274,10 +274,10 @@ private:
void set_extruders(const std::vector<unsigned int> &extruder_ids);
std::string preamble();
std::string change_layer(coordf_t print_z);
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid = nullptr);
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
std::string extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed = -1.);
std::string extrude_loop(ExtrusionLoop loop, const std::string_view description, double speed = -1.);
std::string extrude_multi_path(ExtrusionMultiPath multipath, const std::string_view description, double speed = -1.);
std::string extrude_path(ExtrusionPath path, const std::string_view description, double speed = -1.);
// Extruding multiple objects with soluble / non-soluble / combined supports
// on a multi-material printer, trying to minimize tool switches.
@ -342,7 +342,7 @@ private:
// For sequential print, the instance of the object to be printing has to be defined.
const size_t single_object_instance_idx);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
@ -428,7 +428,7 @@ private:
// Processor
GCodeProcessor m_processor;
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
std::string _extrude(const ExtrusionPath &path, const std::string_view description, double speed = -1);
void print_machine_envelope(GCodeOutputStream &file, Print &print);
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);

View File

@ -26,6 +26,8 @@ public:
void reset(const Vec3d &position);
void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
std::string process_layer(const std::string &gcode, size_t layer_id, bool flush)
{ return this->process_layer(std::string(gcode), layer_id, flush); }
private:
CoolingBuffer& operator=(const CoolingBuffer&) = delete;

View File

@ -1991,14 +1991,15 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
if (comment == reserved_tag(ETags::Layer_Change)) {
++m_layer_id;
if (m_spiral_vase_active) {
if (m_result.moves.empty())
m_result.spiral_vase_layers.push_back({ m_first_layer_height, { 0, 0 } });
if (m_result.moves.empty() || m_result.spiral_vase_layers.empty())
// add a placeholder for layer height. the actual value will be set inside process_G1() method
m_result.spiral_vase_layers.push_back({ FLT_MAX, { 0, 0 } });
else {
const size_t move_id = m_result.moves.size() - 1;
if (!m_result.spiral_vase_layers.empty() && m_end_position[Z] == m_result.spiral_vase_layers.back().first)
if (!m_result.spiral_vase_layers.empty())
m_result.spiral_vase_layers.back().second.second = move_id;
else
m_result.spiral_vase_layers.push_back({ static_cast<float>(m_end_position[Z]), { move_id, move_id } });
// add a placeholder for layer height. the actual value will be set inside process_G1() method
m_result.spiral_vase_layers.push_back({ FLT_MAX, { move_id, move_id } });
}
}
return;
@ -2828,8 +2829,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
}
if (m_spiral_vase_active && !m_result.spiral_vase_layers.empty() && !m_result.moves.empty())
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
if (m_spiral_vase_active && !m_result.spiral_vase_layers.empty()) {
if (m_result.spiral_vase_layers.back().first == FLT_MAX && delta_pos[Z] > 0.0)
// replace layer height placeholder with correct value
m_result.spiral_vase_layers.back().first = static_cast<float>(m_end_position[Z]);
if (!m_result.moves.empty())
m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
}
// store move
#if ENABLE_PROCESS_G2_G3_LINES
@ -3661,42 +3667,44 @@ void GCodeProcessor::post_process()
return std::tuple(!ret.empty(), (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1);
};
struct FilamentData
{
double mm{ 0.0 };
double cm3{ 0.0 };
double g{ 0.0 };
double cost{ 0.0 };
};
std::vector<double> filament_mm(m_result.extruders_count, 0.0);
std::vector<double> filament_cm3(m_result.extruders_count, 0.0);
std::vector<double> filament_g(m_result.extruders_count, 0.0);
std::vector<double> filament_cost(m_result.extruders_count, 0.0);
double filament_total_g = 0.0;
double filament_total_cost = 0.0;
FilamentData filament_data;
for (const auto& [role, used] : m_result.print_statistics.used_filaments_per_role) {
filament_data.mm += used.first;
filament_data.g += used.second;
}
for (const auto& [id, volume] : m_result.print_statistics.volumes_per_extruder) {
filament_data.cm3 += volume;
filament_data.cost += volume * double(m_result.filament_densities[id]) * double(m_result.filament_cost[id]) * 0.000001;
filament_mm[id] = volume / (static_cast<double>(M_PI) * sqr(0.5 * m_result.filament_diameters[id]));
filament_cm3[id] = volume * 0.001;
filament_g[id] = filament_cm3[id] * double(m_result.filament_densities[id]);
filament_cost[id] = filament_g[id] * double(m_result.filament_cost[id]) * 0.001;
filament_total_g += filament_g[id];
filament_total_cost += filament_cost[id];
}
auto process_used_filament = [&filament_data](std::string& gcode_line) {
auto process_tag = [](std::string& gcode_line, const std::string& tag, double value) {
auto process_used_filament = [&](std::string& gcode_line) {
auto process_tag = [](std::string& gcode_line, const std::string& tag, const std::vector<double>& values) {
if (boost::algorithm::istarts_with(gcode_line, tag)) {
char buf[128];
sprintf(buf, "%s %.2lf\n", tag.c_str(), value);
gcode_line = buf;
gcode_line = tag;
char buf[1024];
for (size_t i = 0; i < values.size(); ++i) {
sprintf(buf, i == values.size() - 1 ? " %.2lf\n" : " %.2lf,", values[i]);
gcode_line += buf;
}
return true;
}
return false;
};
bool ret = false;
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_data.mm * 1000.0);
ret |= process_tag(gcode_line, "; filament used [g] =", filament_data.g);
ret |= process_tag(gcode_line, "; total filament used [g] =", filament_data.g);
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_data.cm3 / 1000.0);
ret |= process_tag(gcode_line, "; filament cost =", filament_data.cost);
ret |= process_tag(gcode_line, "; total filament cost =", filament_data.cost);
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_mm);
ret |= process_tag(gcode_line, "; filament used [g] =", filament_g);
ret |= process_tag(gcode_line, "; total filament used [g] =", { filament_total_g });
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
return ret;
};

File diff suppressed because it is too large Load Diff

View File

@ -3,12 +3,16 @@
#include <optional>
#include <vector>
#include <memory>
#include <atomic>
#include "libslic3r/libslic3r.h"
#include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/AABBTreeIndirect.hpp"
#include "libslic3r/KDTreeIndirect.hpp"
namespace Slic3r {
@ -16,119 +20,148 @@ class PrintObject;
class ExtrusionLoop;
class Print;
class Layer;
namespace EdgeGrid { class Grid; }
namespace EdgeGrid {
class Grid;
}
class SeamHistory {
public:
SeamHistory() { clear(); }
std::optional<Point> get_last_seam(const PrintObject* po, size_t layer_id, const BoundingBox& island_bb);
void add_seam(const PrintObject* po, const Point& pos, const BoundingBox& island_bb);
void clear();
namespace SeamPlacerImpl {
private:
struct SeamPoint {
Point m_pos;
BoundingBox m_island_bb;
};
struct GlobalModelInfo;
struct SeamComparator;
std::map<const PrintObject*, std::vector<SeamPoint>> m_data_last_layer;
std::map<const PrintObject*, std::vector<SeamPoint>> m_data_this_layer;
size_t m_layer_id;
enum class EnforcedBlockedSeamPoint {
Blocked = 0,
Neutral = 1,
Enforced = 2,
};
// struct representing single perimeter loop
struct Perimeter {
size_t start_index;
size_t end_index; //inclusive!
size_t seam_index;
float flow_width;
// During alignment, a final position may be stored here. In that case, finalized is set to true.
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
// Random position also uses this flexibility to set final seam point position
bool finalized = false;
Vec3f final_seam_position;
};
//Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
// then all the needed attributes are computed and finally, for each perimeter one point is chosen as seam.
// This seam position can be then further aligned
struct SeamCandidate {
SeamCandidate(const Vec3f &pos, Perimeter &perimeter,
float local_ccw_angle,
EnforcedBlockedSeamPoint type) :
position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(
local_ccw_angle), type(type), central_enforcer(false) {
}
const Vec3f position;
// pointer to Perimeter loop of this point. It is shared across all points of the loop
Perimeter &perimeter;
float visibility;
float overhang;
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
// Negative sign means inside the print, comes from EdgeGrid structure
float embedded_distance;
float local_ccw_angle;
EnforcedBlockedSeamPoint type;
bool central_enforcer; //marks this candidate as central point of enforced segment on the perimeter - important for alignment
};
struct FaceVisibilityInfo {
float visibility;
};
struct SeamCandidateCoordinateFunctor {
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) :
seam_candidates(seam_candidates) {
}
const std::vector<SeamCandidate> &seam_candidates;
float operator()(size_t index, size_t dim) const {
return seam_candidates[index].position[dim];
}
};
} // namespace SeamPlacerImpl
struct PrintObjectSeamData
{
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
struct LayerSeams
{
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
std::vector<SeamPlacerImpl::SeamCandidate> points;
std::unique_ptr<SeamCandidatesTree> points_tree;
};
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
std::vector<LayerSeams> layers;
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
// tree of all points of the given layer
void clear()
{
layers.clear();
}
};
class SeamPlacer {
public:
void init(const Print& print);
static constexpr size_t raycasting_decimation_target_triangle_count = 10000;
static constexpr float raycasting_subdivision_target_length = 2.0f;
//square of number of rays per triangle
static constexpr size_t sqr_rays_per_triangle = 7;
// When perimeters are printed, first call this function with the respective
// external perimeter. SeamPlacer will find a location for its seam and remember it.
// Subsequent calls to get_seam will return this position.
// arm length used during angles computation
static constexpr float polygon_local_angles_arm_distance = 0.5f;
// increases angle importance at the cost of deacreasing visibility info importance. must be > 0
static constexpr float additional_angle_importance = 0.6f;
void plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
const Layer& layer, SeamPosition seam_position,
Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
const EdgeGrid::Grid* lower_layer_edge_grid);
// If enforcer or blocker is closer to the seam candidate than this limit, the seam candidate is set to Blocker or Enforcer
static constexpr float enforcer_blocker_distance_tolerance = 0.35f;
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
static constexpr float enforcer_oversampling_distance = 0.2f;
void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
const EdgeGrid::Grid* lower_layer_edge_grid);
// When searching for seam clusters for alignment:
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
static constexpr float seam_align_score_tolerance = 0.5f;
// seam_align_tolerable_dist - if next layer closes point is too far away, break string
static constexpr float seam_align_tolerable_dist = 1.0f;
// if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped.
// this param limits the number of allowed skips
static constexpr size_t seam_align_tolerable_skips = 4;
// minimum number of seams needed in cluster to make alignment happen
static constexpr size_t seam_align_minimum_string_seams = 6;
// points covered by spline; determines number of splines for the given string
static constexpr size_t seam_align_seams_per_segment = 8;
using TreeType = AABBTreeIndirect::Tree<2, coord_t>;
using AlignedBoxType = Eigen::AlignedBox<TreeType::CoordType, TreeType::NumDimensions>;
//The following data structures hold all perimeter points for all PrintObject.
std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object;
void init(const Print &print);
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
private:
// When given an external perimeter (!), returns the seam.
Point calculate_seam(const Layer& layer, const SeamPosition seam_position,
const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po,
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest);
struct CustomTrianglesPerLayer {
Polygons polys;
TreeType tree;
};
// Just a cache to save some lookups.
const Layer* m_last_layer_po = nullptr;
coordf_t m_last_print_z = -1.;
const PrintObject* m_last_po = nullptr;
struct SeamPoint {
Point pt;
bool precalculated = false;
bool external = false;
const Layer* layer = nullptr;
SeamPosition seam_position;
const PrintObject* po = nullptr;
};
std::vector<SeamPoint> m_plan;
size_t m_plan_idx;
std::vector<std::vector<CustomTrianglesPerLayer>> m_enforcers;
std::vector<std::vector<CustomTrianglesPerLayer>> m_blockers;
std::vector<const PrintObject*> m_po_list;
//std::map<const PrintObject*, Point> m_last_seam_position;
SeamHistory m_seam_history;
// Get indices of points inside enforcers and blockers.
void get_enforcers_and_blockers(size_t layer_id,
const Polygon& polygon,
size_t po_id,
std::vector<size_t>& enforcers_idxs,
std::vector<size_t>& blockers_idxs) const;
// Apply penalties to points inside enforcers/blockers.
void apply_custom_seam(const Polygon& polygon, size_t po_id,
std::vector<float>& penalties,
const std::vector<float>& lengths,
int layer_id, SeamPosition seam_position) const;
// Return random point of a polygon. The distribution will be uniform
// along the contour and account for enforcers and blockers.
Point get_random_seam(size_t layer_idx, const Polygon& polygon, size_t po_id,
bool* saw_custom = nullptr) const;
// Is there any enforcer/blocker on this layer?
bool is_custom_seam_on_layer(size_t layer_id, size_t po_idx) const {
return is_custom_enforcer_on_layer(layer_id, po_idx)
|| is_custom_blocker_on_layer(layer_id, po_idx);
}
bool is_custom_enforcer_on_layer(size_t layer_id, size_t po_idx) const {
return (! m_enforcers.at(po_idx).empty() && ! m_enforcers.at(po_idx)[layer_id].polys.empty());
}
bool is_custom_blocker_on_layer(size_t layer_id, size_t po_idx) const {
return (! m_blockers.at(po_idx).empty() && ! m_blockers.at(po_idx)[layer_id].polys.empty());
}
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info,
const SeamPosition configured_seam_preference);
void calculate_candidates_visibility(const PrintObject *po,
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
bool find_next_seam_in_layer(
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
std::pair<size_t, size_t> &last_point_indexes,
const size_t layer_idx, const float slice_z,
const SeamPlacerImpl::SeamComparator &comparator,
std::vector<std::pair<size_t, size_t>> &seam_string) const;
};
}
} // namespace Slic3r
#endif // libslic3r_SeamPlacer_hpp_

View File

@ -153,8 +153,8 @@ public:
float layer_height,
// Maximum number of tool changes on this layer or the layers below.
size_t max_tool_changes,
// Is this the first layer of the print? In that case print the brim first.
bool is_first_layer,
// Is this the first layer of the print? In that case print the brim first. (OBSOLETE)
bool /*is_first_layer*/,
// Is this the last layer of the waste tower?
bool is_last_layer)
{
@ -162,8 +162,14 @@ public:
m_layer_height = layer_height;
m_depth_traversed = 0.f;
m_current_layer_finished = false;
m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
if (is_first_layer) {
// Advance m_layer_info iterator, making sure we got it right
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
++m_layer_info;
m_current_shape = (! this->is_first_layer() && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL;
if (this->is_first_layer()) {
m_num_layer_changes = 0;
m_num_tool_changes = 0;
} else
@ -171,10 +177,6 @@ public:
// Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height:
m_extrusion_flow = extrusion_flow(layer_height);
// Advance m_layer_info iterator, making sure we got it right
while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end())
++m_layer_info;
}
// Return the wipe tower position.

View File

@ -215,9 +215,9 @@ bool GCodeReader::parse_file_raw(const std::string &filename, raw_line_callback_
[](size_t){});
}
bool GCodeReader::GCodeLine::has(char axis) const
const char* GCodeReader::axis_pos(const char *raw_str, char axis)
{
const char *c = m_raw.c_str();
const char *c = raw_str;
// Skip the whitespaces.
c = skip_whitespaces(c);
// Skip the command.
@ -230,40 +230,48 @@ bool GCodeReader::GCodeLine::has(char axis) const
break;
// Check the name of the axis.
if (*c == axis)
return true;
return c;
// Skip the rest of the word.
c = skip_word(c);
}
return false;
return nullptr;
}
bool GCodeReader::GCodeLine::has(char axis) const
{
const char *c = axis_pos(m_raw.c_str(), axis);
return c != nullptr;
}
bool GCodeReader::GCodeLine::has_value(char axis, float &value) const
{
assert(is_decimal_separator_point());
const char *c = m_raw.c_str();
// Skip the whitespaces.
c = skip_whitespaces(c);
// Skip the command.
c = skip_word(c);
// Up to the end of line or comment.
while (! is_end_of_gcode_line(*c)) {
// Skip whitespaces.
c = skip_whitespaces(c);
if (is_end_of_gcode_line(*c))
break;
// Check the name of the axis.
if (*c == axis) {
// Try to parse the numeric value.
char *pend = nullptr;
double v = strtod(++ c, &pend);
if (pend != nullptr && is_end_of_word(*pend)) {
// The axis value has been parsed correctly.
value = float(v);
return true;
}
}
// Skip the rest of the word.
c = skip_word(c);
const char *c = axis_pos(m_raw.c_str(), axis);
if (c == nullptr)
return false;
// Try to parse the numeric value.
char *pend = nullptr;
double v = strtod(++ c, &pend);
if (pend != nullptr && is_end_of_word(*pend)) {
// The axis value has been parsed correctly.
value = float(v);
return true;
}
return false;
}
bool GCodeReader::GCodeLine::has_value(char axis, int &value) const
{
const char *c = axis_pos(m_raw.c_str(), axis);
if (c == nullptr)
return false;
// Try to parse the numeric value.
char *pend = nullptr;
long v = strtol(++ c, &pend, 10);
if (pend != nullptr && is_end_of_word(*pend)) {
// The axis value has been parsed correctly.
value = int(v);
return true;
}
return false;
}

View File

@ -30,11 +30,14 @@ public:
float value(Axis axis) const { return m_axis[axis]; }
bool has(char axis) const;
bool has_value(char axis, float &value) const;
bool has_value(char axis, int &value) const;
float new_X(const GCodeReader &reader) const { return this->has(X) ? this->x() : reader.x(); }
float new_Y(const GCodeReader &reader) const { return this->has(Y) ? this->y() : reader.y(); }
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }
Point new_XY_scaled(const GCodeReader &reader) const
{ return Point::new_scale(this->new_X(reader), this->new_Y(reader)); }
float dist_X(const GCodeReader &reader) const { return this->has(X) ? (this->x() - reader.x()) : 0; }
float dist_Y(const GCodeReader &reader) const { return this->has(Y) ? (this->y() - reader.y()) : 0; }
float dist_Z(const GCodeReader &reader) const { return this->has(Z) ? (this->z() - reader.z()) : 0; }
@ -134,6 +137,8 @@ public:
float e() const { return m_position[E]; }
float& f() { return m_position[F]; }
float f() const { return m_position[F]; }
Point xy_scaled() const { return Point::new_scale(this->x(), this->y()); }
// Returns 0 for gcfNoExtrusion.
char extrusion_axis() const { return m_extrusion_axis; }
@ -162,6 +167,7 @@ private:
; // silence -Wempty-body
return c;
}
static const char* axis_pos(const char *raw_str, char axis);
GCodeConfig m_config;
char m_extrusion_axis;

View File

@ -50,13 +50,6 @@ bool contains(const std::vector<T> &vector, const Point &point)
}
template bool contains(const ExPolygons &vector, const Point &point);
double rad2deg_dir(double angle)
{
angle = (angle < PI) ? (-angle + PI/2.0) : (angle + PI/2.0);
if (angle < 0) angle += PI;
return rad2deg(angle);
}
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
{
Polygons pp;

View File

@ -36,9 +36,9 @@ enum Orientation
static inline Orientation orient(const Point &a, const Point &b, const Point &c)
{
static_assert(sizeof(coord_t) * 2 == sizeof(int64_t), "orient works with 32 bit coordinates");
int64_t u = int64_t(b(0)) * int64_t(c(1)) - int64_t(b(1)) * int64_t(c(0));
int64_t v = int64_t(a(0)) * int64_t(c(1)) - int64_t(a(1)) * int64_t(c(0));
int64_t w = int64_t(a(0)) * int64_t(b(1)) - int64_t(a(1)) * int64_t(b(0));
int64_t u = int64_t(b.x()) * int64_t(c.y()) - int64_t(b.y()) * int64_t(c.x());
int64_t v = int64_t(a.x()) * int64_t(c.y()) - int64_t(a.y()) * int64_t(c.x());
int64_t w = int64_t(a.x()) * int64_t(b.y()) - int64_t(a.y()) * int64_t(b.x());
int64_t d = u - v + w;
return (d > 0) ? ORIENTATION_CCW : ((d == 0) ? ORIENTATION_COLINEAR : ORIENTATION_CW);
}
@ -291,7 +291,6 @@ bool directions_parallel(double angle1, double angle2, double max_diff = 0);
bool directions_perpendicular(double angle1, double angle2, double max_diff = 0);
template<class T> bool contains(const std::vector<T> &vector, const Point &point);
template<typename T> T rad2deg(T angle) { return T(180.0) * angle / T(PI); }
double rad2deg_dir(double angle);
template<typename T> constexpr T deg2rad(const T angle) { return T(PI) * angle / T(180.0); }
template<typename T> T angle_to_0_2PI(T angle)
{

View File

@ -0,0 +1,291 @@
#ifndef BICUBIC_HPP
#define BICUBIC_HPP
#include <algorithm>
#include <vector>
#include <cmath>
#include <Eigen/Dense>
namespace Slic3r {
namespace Geometry {
namespace BicubicInternal {
// Linear kernel, to be able to test cubic methods with hat kernels.
template<typename T>
struct LinearKernel
{
typedef T FloatType;
static T a00() {
return T(0.);
}
static T a01() {
return T(0.);
}
static T a02() {
return T(0.);
}
static T a03() {
return T(0.);
}
static T a10() {
return T(1.);
}
static T a11() {
return T(-1.);
}
static T a12() {
return T(0.);
}
static T a13() {
return T(0.);
}
static T a20() {
return T(0.);
}
static T a21() {
return T(1.);
}
static T a22() {
return T(0.);
}
static T a23() {
return T(0.);
}
static T a30() {
return T(0.);
}
static T a31() {
return T(0.);
}
static T a32() {
return T(0.);
}
static T a33() {
return T(0.);
}
};
// Interpolation kernel aka Catmul-Rom aka Keyes kernel.
template<typename T>
struct CubicCatmulRomKernel
{
typedef T FloatType;
static T a00() {
return 0;
}
static T a01() {
return T( -0.5);
}
static T a02() {
return T( 1.);
}
static T a03() {
return T( -0.5);
}
static T a10() {
return T( 1.);
}
static T a11() {
return 0;
}
static T a12() {
return T( -5. / 2.);
}
static T a13() {
return T( 3. / 2.);
}
static T a20() {
return 0;
}
static T a21() {
return T( 0.5);
}
static T a22() {
return T( 2.);
}
static T a23() {
return T( -3. / 2.);
}
static T a30() {
return 0;
}
static T a31() {
return 0;
}
static T a32() {
return T( -0.5);
}
static T a33() {
return T( 0.5);
}
};
// B-spline kernel
template<typename T>
struct CubicBSplineKernel
{
typedef T FloatType;
static T a00() {
return T( 1. / 6.);
}
static T a01() {
return T( -3. / 6.);
}
static T a02() {
return T( 3. / 6.);
}
static T a03() {
return T( -1. / 6.);
}
static T a10() {
return T( 4. / 6.);
}
static T a11() {
return 0;
}
static T a12() {
return T( -6. / 6.);
}
static T a13() {
return T( 3. / 6.);
}
static T a20() {
return T( 1. / 6.);
}
static T a21() {
return T( 3. / 6.);
}
static T a22() {
return T( 3. / 6.);
}
static T a23() {
return T( -3. / 6.);
}
static T a30() {
return 0;
}
static T a31() {
return 0;
}
static T a32() {
return 0;
}
static T a33() {
return T( 1. / 6.);
}
};
template<class T>
inline T clamp(T a, T lower, T upper)
{
return (a < lower) ? lower :
(a > upper) ? upper : a;
}
}
template<typename Kernel>
struct CubicKernelWrapper
{
typedef typename Kernel::FloatType FloatType;
static constexpr size_t kernel_span = 4;
static FloatType kernel(FloatType x)
{
x = fabs(x);
if (x >= (FloatType) 2.)
return 0.0f;
if (x <= (FloatType) 1.) {
FloatType x2 = x * x;
FloatType x3 = x2 * x;
return Kernel::a10() + Kernel::a11() * x + Kernel::a12() * x2 + Kernel::a13() * x3;
}
assert(x > (FloatType )1. && x < (FloatType )2.);
x -= (FloatType) 1.;
FloatType x2 = x * x;
FloatType x3 = x2 * x;
return Kernel::a00() + Kernel::a01() * x + Kernel::a02() * x2 + Kernel::a03() * x3;
}
static FloatType interpolate(FloatType f0, FloatType f1, FloatType f2, FloatType f3, FloatType x)
{
const FloatType x2 = x * x;
const FloatType x3 = x * x * x;
return f0 * (Kernel::a00() + Kernel::a01() * x + Kernel::a02() * x2 + Kernel::a03() * x3) +
f1 * (Kernel::a10() + Kernel::a11() * x + Kernel::a12() * x2 + Kernel::a13() * x3) +
f2 * (Kernel::a20() + Kernel::a21() * x + Kernel::a22() * x2 + Kernel::a23() * x3) +
f3 * (Kernel::a30() + Kernel::a31() * x + Kernel::a32() * x2 + Kernel::a33() * x3);
}
};
// Linear splines
template<typename NumberType>
using LinearKernel = CubicKernelWrapper<BicubicInternal::LinearKernel<NumberType>>;
// Catmul-Rom splines
template<typename NumberType>
using CubicCatmulRomKernel = CubicKernelWrapper<BicubicInternal::CubicCatmulRomKernel<NumberType>>;
// Cubic B-splines
template<typename NumberType>
using CubicBSplineKernel = CubicKernelWrapper<BicubicInternal::CubicBSplineKernel<NumberType>>;
template<typename KernelWrapper>
static typename KernelWrapper::FloatType cubic_interpolate(const Eigen::ArrayBase<typename KernelWrapper::FloatType> &F,
const typename KernelWrapper::FloatType pt) {
typedef typename KernelWrapper::FloatType T;
const int w = int(F.size());
const int ix = (int) floor(pt);
const T s = pt - T( ix);
if (ix > 1 && ix + 2 < w) {
// Inside the fully interpolated region.
return KernelWrapper::interpolate(F[ix - 1], F[ix], F[ix + 1], F[ix + 2], s);
}
// Transition region. Extend with a constant function.
auto f = [&F, w](T x) {
return F[BicubicInternal::clamp(x, 0, w - 1)];
};
return KernelWrapper::interpolate(f(ix - 1), f(ix), f(ix + 1), f(ix + 2), s);
}
template<typename Kernel, typename Derived>
static float bicubic_interpolate(const Eigen::MatrixBase<Derived> &F,
const Eigen::Matrix<typename Kernel::FloatType, 2, 1, Eigen::DontAlign> &pt) {
typedef typename Kernel::FloatType T;
const int w = F.cols();
const int h = F.rows();
const int ix = (int) floor(pt[0]);
const int iy = (int) floor(pt[1]);
const T s = pt[0] - T( ix);
const T t = pt[1] - T( iy);
if (ix > 1 && ix + 2 < w && iy > 1 && iy + 2 < h) {
// Inside the fully interpolated region.
return Kernel::interpolate(
Kernel::interpolate(F(ix - 1, iy - 1), F(ix, iy - 1), F(ix + 1, iy - 1), F(ix + 2, iy - 1), s),
Kernel::interpolate(F(ix - 1, iy), F(ix, iy), F(ix + 1, iy), F(ix + 2, iy), s),
Kernel::interpolate(F(ix - 1, iy + 1), F(ix, iy + 1), F(ix + 1, iy + 1), F(ix + 2, iy + 1), s),
Kernel::interpolate(F(ix - 1, iy + 2), F(ix, iy + 2), F(ix + 1, iy + 2), F(ix + 2, iy + 2), s), t);
}
// Transition region. Extend with a constant function.
auto f = [&F, w, h](int x, int y) {
return F(BicubicInternal::clamp(x, 0, w - 1), BicubicInternal::clamp(y, 0, h - 1));
};
return Kernel::interpolate(
Kernel::interpolate(f(ix - 1, iy - 1), f(ix, iy - 1), f(ix + 1, iy - 1), f(ix + 2, iy - 1), s),
Kernel::interpolate(f(ix - 1, iy), f(ix, iy), f(ix + 1, iy), f(ix + 2, iy), s),
Kernel::interpolate(f(ix - 1, iy + 1), f(ix, iy + 1), f(ix + 1, iy + 1), f(ix + 2, iy + 1), s),
Kernel::interpolate(f(ix - 1, iy + 2), f(ix, iy + 2), f(ix + 1, iy + 2), f(ix + 2, iy + 2), s), t);
}
} //namespace Geometry
} // namespace Slic3r
#endif /* BICUBIC_HPP */

Some files were not shown because too many files have changed in this diff Show More