Merge remote-tracking branch 'remotes/origin/master' into lh_adaptive_infill_hooks

This commit is contained in:
Vojtech Bubnik 2020-11-03 15:07:38 +01:00
commit 414fdaefc5
228 changed files with 30930 additions and 13115 deletions

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.13)
project(PrusaSlicer) project(PrusaSlicer)
include("version.inc") include("version.inc")
@ -393,6 +393,7 @@ endif ()
find_package(PNG REQUIRED) find_package(PNG REQUIRED)
set(OpenGL_GL_PREFERENCE "LEGACY")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
# Find glew or use bundled version # Find glew or use bundled version
@ -509,9 +510,15 @@ endif()
if (WIN32) if (WIN32)
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources") install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
elseif (SLIC3R_FHS) elseif (SLIC3R_FHS)
# CMAKE_INSTALL_FULL_DATAROOTDIR: read-only architecture-independent data root (share)
set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/PrusaSlicer") set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/PrusaSlicer")
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}") install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}")
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${SLIC3R_FHS_RESOURCES}/applications)
install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${SLIC3R_FHS_RESOURCES}/applications)
else () else ()
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources") install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
endif () endif ()
configure_file(${LIBDIR}/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/platform/unix/fhs.hpp) configure_file(${LIBDIR}/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/platform/unix/fhs.hpp)

11
deps/CGAL/CGAL.cmake vendored
View file

@ -15,6 +15,17 @@ include(GNUInstallDirs)
# If this file is not present, it will not consider the stored absolute path # If this file is not present, it will not consider the stored absolute path
ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix ExternalProject_Add_Step(dep_CGAL dep_CGAL_relocation_fix
DEPENDEES install DEPENDEES install
COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake COMMAND ${CMAKE_COMMAND} -E remove CGALConfig-installation-dirs.cmake
WORKING_DIRECTORY "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL" WORKING_DIRECTORY "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL"
) )
# Again, for whatever reason, CGAL thinks that its version is not relevant if
# configured as a header only library. Fixing it by placing a cmake version file
# besides the installed config file.
ExternalProject_Add_Step(dep_CGAL dep_CGAL_version_fix
DEPENDEES install
COMMAND ${CMAKE_COMMAND} -E copy cgal/CGALConfigVersion.cmake "${DESTDIR}/usr/local/${CMAKE_INSTALL_LIBDIR}/cmake/CGAL/CGALConfigVersion.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
)

37
deps/CGAL/cgal/CGALConfigVersion.cmake vendored Normal file
View file

@ -0,0 +1,37 @@
# This is a basic version file for the Config-mode of find_package().
# It is used by write_basic_package_version_file() as input file for configure_file()
# to create a version-file which can be installed along a config.cmake file.
#
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
# the requested version string are exactly the same and it sets
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
# The variable CVF_VERSION must be set before calling configure_file().
set(PACKAGE_VERSION "5.0.0")
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
# if the installed project requested no architecture check, don't perform the check
if("FALSE")
return()
endif()
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
return()
endif()
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
math(EXPR installedBits "8 * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

2
deps/PNG/PNG.cmake vendored
View file

@ -1,3 +1,4 @@
prusaslicer_add_cmake_project(PNG prusaslicer_add_cmake_project(PNG
GIT_REPOSITORY https://github.com/glennrp/libpng.git GIT_REPOSITORY https://github.com/glennrp/libpng.git
GIT_TAG v1.6.35 GIT_TAG v1.6.35
@ -5,6 +6,7 @@ prusaslicer_add_cmake_project(PNG
CMAKE_ARGS CMAKE_ARGS
-DPNG_SHARED=OFF -DPNG_SHARED=OFF
-DPNG_STATIC=ON -DPNG_STATIC=ON
-DPNG_PREFIX=prusaslicer_
-DPNG_TESTS=OFF -DPNG_TESTS=OFF
) )

View file

@ -56,6 +56,10 @@ This is done by passing this option to CMake:
Note that PrusaSlicer is tested with wxWidgets 3.0 somewhat sporadically and so there may be bugs in bleeding edge releases. Note that PrusaSlicer is tested with wxWidgets 3.0 somewhat sporadically and so there may be bugs in bleeding edge releases.
When building on ubuntu 20.04 focal fossa, the package libwxgtk3.0-gtk3-dev needs to be installed instead of libwxgtk3.0-dev and you should use:
-DSLIC3R_WX_STABLE=1 -DSLIC3R_GTK=3
### Build variant ### Build variant
By default PrusaSlicer builds the release variant. By default PrusaSlicer builds the release variant.

View file

@ -125,11 +125,11 @@ intermediate files, which are not handled correctly by either `b2.exe` or possib
# Noob guide (step by step) # Noob guide (step by step)
Install Visual Studio Community 2019 from Install Visual Studio Community 2019 from
visualstudio.microsoft.com/vs/ [visualstudio.microsoft.com/vs/](https://visualstudio.microsoft.com/vs/)
Select all workload options for C++ Select all workload options for C++
Install git for Windows from Install git for Windows from
gitforwindows.org [gitforwindows.org](https://gitforwindows.org/)
download and run the exe accepting all defaults download and run the exe accepting all defaults
download PrusaSlicer-master.zip from github download PrusaSlicer-master.zip from github

View file

@ -0,0 +1,12 @@
[Desktop Entry]
Name=PrusaSlicer
GenericName=3D Printing Software
Icon=com.prusa3d.PrusaSlicer
Exec=prusa-slicer %F
Terminal=false
Type=Application
MimeType=model/stl;model/x-wavefront-obj;model/3mf;model/x-geomview-off;application/x-amf;
Categories=Graphics;3DGraphics;Engineering;
Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA
StartupNotify=false
StartupWMClass=prusa-slicer

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>com.prusa3d.PrusaSlicer</id>
<launchable type="desktop-id">com.prusa3d.PrusaSlicer.desktop</launchable>
<provides>
<id>prusa-slicer.desktop</id>
</provides>
<name>PrusaSlicer</name>
<summary>Powerful 3D printing slicer optimized for Prusa printers</summary>
<metadata_license>0BSD</metadata_license>
<project_license>AGPL-3.0-only</project_license>
<description>
<p>
PrusaSlicer takes 3D models (STL, OBJ, AMF) and converts them into G-code
instructions for FFF printers or PNG layers for mSLA 3D printers. It's
compatible with any modern printer based on the RepRap toolchain, including all
those based on the Marlin, Prusa, Sprinter and Repetier firmware. It also works
with Mach3, LinuxCNC and Machinekit controllers.
</p>
<p>
PrusaSlicer is based on Slic3r by Alessandro Ranelucci and the RepRap community.
</p>
<p>
What are some of PrusaSlicer's main features?
</p>
<ul>
<li>multi-platform (Linux/Mac/Win) and packaged as standalone-app with no dependencies required</li>
<li>complete command-line interface to use it with no GUI</li>
<li>multi-material (multiple extruders) object printing</li>
<li>multiple G-code flavors supported (RepRap, Makerbot, Mach3, Machinekit etc.)</li>
<li>ability to plate multiple objects having distinct print settings</li>
<li>multithread processing</li>
<li>STL auto-repair (tolerance for broken models)</li>
<li>wide automated unit testing</li>
</ul>
</description>
<url type="homepage">https://www.prusa3d.com/prusaslicer/</url>
<url type="help">https://help.prusa3d.com</url>
<url type="bugtracker">https://github.com/prusa3d/PrusaSlicer/issues</url>
<screenshots>
<screenshot type="default">
<image>https://user-images.githubusercontent.com/590307/78981854-24d07580-7b21-11ea-9441-77923534a659.png</image>
</screenshot>
<screenshot>
<image>https://user-images.githubusercontent.com/590307/78981860-2863fc80-7b21-11ea-8c2d-8ff79ced2578.png</image>
</screenshot>
<screenshot>
<image>https://user-images.githubusercontent.com/590307/78981862-28fc9300-7b21-11ea-9b0d-d03e16b709d3.png</image>
</screenshot>
</screenshots>
<content_rating type="oars-1.1" />
<releases>
<release version="2.2.0" date="2020-03-21">
<description>
<p>This is final release of PrusaSlicer 2.2.0 introducing SLA hollowing and hole drilling, support for 3rd party printer vendors, 3Dconnexion support,
automatic variable layer height, macOS dark mode support, greatly improved ColorPrint feature and much, much more.
Several bugs found in the previous release candidate are fixed in this final release. See the respective change logs of the previous releases for all the
new features, improvements and bugfixes in the 2.2.0 series.</p>
</description>
</release>
</releases>
</component>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#808080" cx="8" cy="8" r="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#808080" cx="8" cy="8" r="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

13
resources/icons/exit.svg Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="exit" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<path fill="#ED6B21" d="M63.4,45.46l-20-15c-2.51-1.88-6.06-1.37-7.94,1.13c-1.88,2.5-1.37,6.06,1.13,7.94l6.39,4.79H10
c-3.13,0-5.67,2.54-5.67,5.67s2.54,5.67,5.67,5.67h32.99l-6.39,4.8c-2.5,1.88-3.01,5.43-1.13,7.94c1.11,1.49,2.82,2.27,4.54,2.27
c1.18,0,2.38-0.37,3.4-1.13l20-15c1.43-1.07,2.27-2.75,2.27-4.54C65.67,48.22,64.83,46.54,63.4,45.46z"/>
<g>
<path fill="#808080" d="M90,92.83H40c-1.57,0-2.83-1.27-2.83-2.83V80c0-1.57,1.27-2.83,2.83-2.83s2.83,1.27,2.83,2.83v7.17h44.33
V12.83H42.83V20c0,1.57-1.27,2.83-2.83,2.83s-2.83-1.27-2.83-2.83V10c0-1.57,1.27-2.83,2.83-2.83h50c1.57,0,2.83,1.27,2.83,2.83v80
C92.83,91.57,91.57,92.83,90,92.83z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 997 B

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g id="paint_x5F_supports">
<path fill="#ED6B21" d="M88,38.93c-0.83,0-1.5,0.67-1.5,1.5V70.5h-5V45.14c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5V70.5h-5V49.8
c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5v20.7h-5V53.84c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5V70.5h-5V49.8
c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5v20.7h-5V45.14c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5V70.5h-5V40.43
c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5V72v10.99c0,3.59,2.92,6.51,6.51,6.51h2.98c0.67,0.01,6.51,0.24,6.51,6.5v16
c0,3.29,1.99,9.5,9.5,9.5s9.5-6.21,9.5-9.5V96c0-6.26,5.84-6.49,6.5-6.5h3c3.59,0,6.5-2.92,6.5-6.5V72V40.43
C89.5,39.6,88.83,38.93,88,38.93z M86.5,83c0,1.93-1.57,3.5-3.5,3.5h-3c-3.29,0-9.5,1.99-9.5,9.5v15.99
c-0.01,0.67-0.24,6.51-6.5,6.51s-6.49-5.84-6.5-6.5V96c0-7.51-6.21-9.5-9.5-9.5h-2.99c-1.94,0-3.51-1.57-3.51-3.51V73.5h45V83z"/>
<g>
<path fill="#FFFFFF" d="M64,48.03c-0.26,0-0.52-0.07-0.75-0.2l-48-27.69c-0.46-0.27-0.75-0.76-0.75-1.3V8c0-0.83,0.67-1.5,1.5-1.5
s1.5,0.67,1.5,1.5v9.98L64,44.8l46.5-26.83V8c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v10.84c0,0.54-0.29,1.03-0.75,1.3
l-48,27.69C64.52,47.97,64.26,48.03,64,48.03z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="change_x5F_profile_copy" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<rect x="-45" y="5" display="none" fill="#FFFFFF" width="55" height="90"/>
<rect x="90" y="5" transform="matrix(-1 -1.224647e-16 1.224647e-16 -1 235 100)" display="none" fill="#FFFFFF" width="55" height="90"/>
<path fill="#ED6B21" d="M88.52,28.64c-1.25-0.94-3.03-0.69-3.97,0.57l-1.72,2.29V15c0-1.57-1.27-2.83-2.83-2.83H65
c-1.57,0-2.83,1.27-2.83,2.83s1.27,2.83,2.83,2.83h12.17V31.5l-1.72-2.29c-0.94-1.25-2.72-1.5-3.97-0.57
c-1.25,0.94-1.51,2.72-0.57,3.97l6.82,9.09c0.54,0.71,1.38,1.13,2.27,1.13s1.73-0.42,2.27-1.13l6.82-9.09
C90.03,31.36,89.77,29.58,88.52,28.64z"/>
<path fill="#ED6B21" d="M35,82.17H22.83V68.5l1.72,2.29c0.56,0.74,1.41,1.13,2.27,1.13c0.59,0,1.19-0.18,1.7-0.57
c1.25-0.94,1.51-2.72,0.57-3.97l-6.82-9.09c-0.54-0.71-1.38-1.13-2.27-1.13s-1.73,0.42-2.27,1.13l-6.82,9.09
c-0.94,1.25-0.69,3.03,0.57,3.97c1.25,0.94,3.03,0.69,3.97-0.57l1.72-2.29V85c0,1.57,1.27,2.83,2.83,2.83h15
c1.57,0,2.83-1.27,2.83-2.83S36.57,82.17,35,82.17z"/>
<polyline display="none" fill="none" stroke="#ED6B21" stroke-width="11.3386" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
35,65 15,50 35,35 "/>
<g>
<path fill="#808080" d="M50.01,41.11c0-0.75-0.3-1.47-0.83-2l-1.99-1.99H50c1.57,0,2.83-1.27,2.83-2.83v-8.57
c0-1.57-1.27-2.83-2.83-2.83h-2.81l1.99-1.99c0.53-0.53,0.83-1.25,0.83-2s-0.3-1.47-0.83-2l-6.06-6.06c-1.06-1.06-2.95-1.06-4.01,0
l-1.99,1.99V10c0-1.57-1.27-2.83-2.83-2.83h-8.57c-1.57,0-2.83,1.27-2.83,2.83v2.81l-1.99-1.99c-0.53-0.53-1.25-0.83-2-0.83
s-1.47,0.3-2,0.83l-6.06,6.06c-0.53,0.53-0.83,1.25-0.83,2s0.3,1.47,0.83,2l1.99,1.99H10c-1.57,0-2.83,1.27-2.83,2.83v8.57
c0,1.57,1.27,2.83,2.83,2.83h2.81l-1.99,1.99c-0.53,0.53-0.83,1.25-0.83,2s0.3,1.47,0.83,2l6.06,6.06c1.11,1.11,2.9,1.11,4.01,0
l1.99-1.99V50c0,1.57,1.27,2.83,2.83,2.83h8.57c1.57,0,2.83-1.27,2.83-2.83v-2.81l1.99,1.99c1.11,1.11,2.9,1.11,4.01,0l6.06-6.06
C49.71,42.58,50.01,41.86,50.01,41.11z M47.17,31.45h-2.05c-1.27,0-2.38,0.84-2.73,2.06c-0.27,0.96-0.66,1.89-1.14,2.76
c-0.62,1.11-0.43,2.49,0.47,3.39l1.45,1.45l-2.05,2.05l-1.45-1.45c-0.9-0.9-2.28-1.09-3.39-0.47c-0.87,0.49-1.8,0.87-2.76,1.14
c-1.22,0.35-2.06,1.46-2.06,2.73v2.05h-2.9v-2.05c0-1.27-0.84-2.38-2.06-2.73c-0.96-0.27-1.89-0.66-2.76-1.14
c-1.11-0.62-2.49-0.43-3.39,0.47l-1.45,1.45l-2.05-2.05l1.45-1.45c0.9-0.9,1.09-2.28,0.47-3.39c-0.49-0.87-0.87-1.8-1.14-2.76
c-0.35-1.22-1.46-2.06-2.73-2.06h-2.05v-2.9h2.05c1.27,0,2.38-0.84,2.73-2.06c0.27-0.96,0.66-1.89,1.14-2.76
c0.62-1.11,0.43-2.49-0.47-3.39l-1.45-1.45l2.05-2.05l1.45,1.45c0.9,0.9,2.28,1.09,3.39,0.47c0.87-0.49,1.8-0.87,2.76-1.14
c1.22-0.35,2.06-1.46,2.06-2.73v-2.05h2.9v2.05c0,1.27,0.84,2.38,2.06,2.73c0.96,0.27,1.89,0.66,2.76,1.14
c1.11,0.62,2.49,0.43,3.39-0.47l1.45-1.45l2.05,2.05l-1.45,1.45c-0.9,0.9-1.09,2.28-0.47,3.39c0.49,0.87,0.87,1.8,1.14,2.76
c0.35,1.22,1.46,2.06,2.73,2.06h2.05V31.45z"/>
<path fill="#808080" d="M90,62.88h-2.81l1.99-1.99c1.11-1.11,1.11-2.9,0-4.01l-6.06-6.06c-1.11-1.11-2.9-1.11-4.01,0l-1.99,1.99V50
c0-1.57-1.27-2.83-2.83-2.83h-8.57c-1.57,0-2.83,1.27-2.83,2.83v2.81l-1.99-1.99c-1.11-1.11-2.9-1.11-4.01,0l-6.06,6.06
c-1.11,1.11-1.11,2.9,0,4.01l1.99,1.99H50c-1.57,0-2.83,1.27-2.83,2.83v8.57c0,1.57,1.27,2.83,2.83,2.83h2.81l-1.99,1.99
c-1.11,1.11-1.11,2.9,0,4.01l6.06,6.06c1.11,1.11,2.9,1.11,4.01,0l1.99-1.99V90c0,1.57,1.27,2.83,2.83,2.83h8.57
c1.57,0,2.83-1.27,2.83-2.83v-2.81l1.99,1.99c1.11,1.11,2.9,1.11,4.01,0l6.06-6.06c1.11-1.11,1.11-2.9,0-4.01l-1.99-1.99H90
c1.57,0,2.83-1.27,2.83-2.83v-8.57C92.83,64.15,91.57,62.88,90,62.88z M87.17,71.45h-2.05c-1.27,0-2.38,0.84-2.73,2.06
c-0.27,0.96-0.66,1.89-1.14,2.76c-0.62,1.11-0.43,2.49,0.47,3.39l1.45,1.45l-2.05,2.05l-1.45-1.45c-0.9-0.9-2.28-1.09-3.39-0.47
c-0.87,0.49-1.8,0.87-2.76,1.15c-1.22,0.35-2.06,1.46-2.06,2.73v2.05h-2.9v-2.05c0-1.27-0.84-2.38-2.06-2.73
c-0.96-0.27-1.89-0.66-2.76-1.15c-1.11-0.62-2.49-0.43-3.39,0.47l-1.45,1.45l-2.05-2.05l1.45-1.45c0.9-0.9,1.09-2.28,0.47-3.39
c-0.49-0.87-0.87-1.8-1.14-2.76c-0.35-1.22-1.46-2.06-2.73-2.06h-2.05v-2.9h2.05c1.27,0,2.38-0.84,2.73-2.06
c0.27-0.96,0.66-1.89,1.14-2.76c0.62-1.11,0.43-2.49-0.47-3.39l-1.45-1.45l2.05-2.05l1.45,1.45c0.9,0.9,2.28,1.09,3.39,0.47
c0.87-0.49,1.8-0.87,2.76-1.14c1.22-0.35,2.06-1.46,2.06-2.73v-2.05h2.9v2.05c0,1.27,0.84,2.38,2.06,2.73
c0.96,0.27,1.89,0.66,2.76,1.14c1.11,0.62,2.49,0.43,3.39-0.47l1.45-1.45l2.05,2.05l-1.45,1.45c-0.9,0.9-1.09,2.28-0.47,3.39
c0.49,0.87,0.87,1.8,1.14,2.76c0.35,1.22,1.46,2.06,2.73,2.06h2.05V71.45z"/>
<path fill="#808080" d="M30,22.17c-4.32,0-7.83,3.51-7.83,7.83s3.51,7.83,7.83,7.83s7.83-3.51,7.83-7.83S34.32,22.17,30,22.17z
M30,32.17c-1.19,0-2.17-0.97-2.17-2.17s0.97-2.17,2.17-2.17s2.17,0.97,2.17,2.17S31.19,32.17,30,32.17z"/>
<path fill="#808080" d="M70,62.17c-4.32,0-7.83,3.51-7.83,7.83s3.51,7.83,7.83,7.83s7.83-3.51,7.83-7.83S74.32,62.17,70,62.17z
M70,72.17c-1.19,0-2.17-0.97-2.17-2.17s0.97-2.17,2.17-2.17s2.17,0.97,2.17,2.17S71.19,72.17,70,72.17z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g>
<circle fill="#FFFFFF" cx="8" cy="8" r="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 400 B

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="exit" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<path fill="#ED6B21" d="M63.4,45.46l-20-15c-2.51-1.88-6.06-1.37-7.94,1.13c-1.88,2.5-1.37,6.06,1.13,7.94l6.39,4.79H10
c-3.13,0-5.67,2.54-5.67,5.67s2.54,5.67,5.67,5.67h32.99l-6.39,4.8c-2.5,1.88-3.01,5.43-1.13,7.94c1.11,1.49,2.82,2.27,4.54,2.27
c1.18,0,2.38-0.37,3.4-1.13l20-15c1.43-1.07,2.27-2.75,2.27-4.54C65.67,48.22,64.83,46.54,63.4,45.46z"/>
<g>
<path fill="#FFFFFF" d="M90,92.83H40c-1.57,0-2.83-1.27-2.83-2.83V80c0-1.57,1.27-2.83,2.83-2.83s2.83,1.27,2.83,2.83v7.17h44.33
V12.83H42.83V20c0,1.57-1.27,2.83-2.83,2.83s-2.83-1.27-2.83-2.83V10c0-1.57,1.27-2.83,2.83-2.83h50c1.57,0,2.83,1.27,2.83,2.83v80
C92.83,91.57,91.57,92.83,90,92.83z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 997 B

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="change_x5F_profile_copy" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<rect x="-45" y="5" display="none" fill="#FFFFFF" width="55" height="90"/>
<rect x="90" y="5" transform="matrix(-1 -1.224647e-16 1.224647e-16 -1 235 100)" display="none" fill="#FFFFFF" width="55" height="90"/>
<path fill="#ED6B21" d="M88.52,28.64c-1.25-0.94-3.03-0.69-3.97,0.57l-1.72,2.29V15c0-1.57-1.27-2.83-2.83-2.83H65
c-1.57,0-2.83,1.27-2.83,2.83s1.27,2.83,2.83,2.83h12.17V31.5l-1.72-2.29c-0.94-1.25-2.72-1.5-3.97-0.57
c-1.25,0.94-1.51,2.72-0.57,3.97l6.82,9.09c0.54,0.71,1.38,1.13,2.27,1.13s1.73-0.42,2.27-1.13l6.82-9.09
C90.03,31.36,89.77,29.58,88.52,28.64z"/>
<path fill="#ED6B21" d="M35,82.17H22.83V68.5l1.72,2.29c0.56,0.74,1.41,1.13,2.27,1.13c0.59,0,1.19-0.18,1.7-0.57
c1.25-0.94,1.51-2.72,0.57-3.97l-6.82-9.09c-0.54-0.71-1.38-1.13-2.27-1.13s-1.73,0.42-2.27,1.13l-6.82,9.09
c-0.94,1.25-0.69,3.03,0.57,3.97c1.25,0.94,3.03,0.69,3.97-0.57l1.72-2.29V85c0,1.57,1.27,2.83,2.83,2.83h15
c1.57,0,2.83-1.27,2.83-2.83S36.57,82.17,35,82.17z"/>
<polyline display="none" fill="none" stroke="#ED6B21" stroke-width="11.3386" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
35,65 15,50 35,35 "/>
<g>
<path fill="#FFFFFF" d="M50.01,41.11c0-0.75-0.3-1.47-0.83-2l-1.99-1.99H50c1.57,0,2.83-1.27,2.83-2.83v-8.57
c0-1.57-1.27-2.83-2.83-2.83h-2.81l1.99-1.99c0.53-0.53,0.83-1.25,0.83-2s-0.3-1.47-0.83-2l-6.06-6.06c-1.06-1.06-2.95-1.06-4.01,0
l-1.99,1.99V10c0-1.57-1.27-2.83-2.83-2.83h-8.57c-1.57,0-2.83,1.27-2.83,2.83v2.81l-1.99-1.99c-0.53-0.53-1.25-0.83-2-0.83
s-1.47,0.3-2,0.83l-6.06,6.06c-0.53,0.53-0.83,1.25-0.83,2s0.3,1.47,0.83,2l1.99,1.99H10c-1.57,0-2.83,1.27-2.83,2.83v8.57
c0,1.57,1.27,2.83,2.83,2.83h2.81l-1.99,1.99c-0.53,0.53-0.83,1.25-0.83,2s0.3,1.47,0.83,2l6.06,6.06c1.11,1.11,2.9,1.11,4.01,0
l1.99-1.99V50c0,1.57,1.27,2.83,2.83,2.83h8.57c1.57,0,2.83-1.27,2.83-2.83v-2.81l1.99,1.99c1.11,1.11,2.9,1.11,4.01,0l6.06-6.06
C49.71,42.58,50.01,41.86,50.01,41.11z M47.17,31.45h-2.05c-1.27,0-2.38,0.84-2.73,2.06c-0.27,0.96-0.66,1.89-1.14,2.76
c-0.62,1.11-0.43,2.49,0.47,3.39l1.45,1.45l-2.05,2.05l-1.45-1.45c-0.9-0.9-2.28-1.09-3.39-0.47c-0.87,0.49-1.8,0.87-2.76,1.14
c-1.22,0.35-2.06,1.46-2.06,2.73v2.05h-2.9v-2.05c0-1.27-0.84-2.38-2.06-2.73c-0.96-0.27-1.89-0.66-2.76-1.14
c-1.11-0.62-2.49-0.43-3.39,0.47l-1.45,1.45l-2.05-2.05l1.45-1.45c0.9-0.9,1.09-2.28,0.47-3.39c-0.49-0.87-0.87-1.8-1.14-2.76
c-0.35-1.22-1.46-2.06-2.73-2.06h-2.05v-2.9h2.05c1.27,0,2.38-0.84,2.73-2.06c0.27-0.96,0.66-1.89,1.14-2.76
c0.62-1.11,0.43-2.49-0.47-3.39l-1.45-1.45l2.05-2.05l1.45,1.45c0.9,0.9,2.28,1.09,3.39,0.47c0.87-0.49,1.8-0.87,2.76-1.14
c1.22-0.35,2.06-1.46,2.06-2.73v-2.05h2.9v2.05c0,1.27,0.84,2.38,2.06,2.73c0.96,0.27,1.89,0.66,2.76,1.14
c1.11,0.62,2.49,0.43,3.39-0.47l1.45-1.45l2.05,2.05l-1.45,1.45c-0.9,0.9-1.09,2.28-0.47,3.39c0.49,0.87,0.87,1.8,1.14,2.76
c0.35,1.22,1.46,2.06,2.73,2.06h2.05V31.45z"/>
<path fill="#FFFFFF" d="M90,62.88h-2.81l1.99-1.99c1.11-1.11,1.11-2.9,0-4.01l-6.06-6.06c-1.11-1.11-2.9-1.11-4.01,0l-1.99,1.99V50
c0-1.57-1.27-2.83-2.83-2.83h-8.57c-1.57,0-2.83,1.27-2.83,2.83v2.81l-1.99-1.99c-1.11-1.11-2.9-1.11-4.01,0l-6.06,6.06
c-1.11,1.11-1.11,2.9,0,4.01l1.99,1.99H50c-1.57,0-2.83,1.27-2.83,2.83v8.57c0,1.57,1.27,2.83,2.83,2.83h2.81l-1.99,1.99
c-1.11,1.11-1.11,2.9,0,4.01l6.06,6.06c1.11,1.11,2.9,1.11,4.01,0l1.99-1.99V90c0,1.57,1.27,2.83,2.83,2.83h8.57
c1.57,0,2.83-1.27,2.83-2.83v-2.81l1.99,1.99c1.11,1.11,2.9,1.11,4.01,0l6.06-6.06c1.11-1.11,1.11-2.9,0-4.01l-1.99-1.99H90
c1.57,0,2.83-1.27,2.83-2.83v-8.57C92.83,64.15,91.57,62.88,90,62.88z M87.17,71.45h-2.05c-1.27,0-2.38,0.84-2.73,2.06
c-0.27,0.96-0.66,1.89-1.14,2.76c-0.62,1.11-0.43,2.49,0.47,3.39l1.45,1.45l-2.05,2.05l-1.45-1.45c-0.9-0.9-2.28-1.09-3.39-0.47
c-0.87,0.49-1.8,0.87-2.76,1.15c-1.22,0.35-2.06,1.46-2.06,2.73v2.05h-2.9v-2.05c0-1.27-0.84-2.38-2.06-2.73
c-0.96-0.27-1.89-0.66-2.76-1.15c-1.11-0.62-2.49-0.43-3.39,0.47l-1.45,1.45l-2.05-2.05l1.45-1.45c0.9-0.9,1.09-2.28,0.47-3.39
c-0.49-0.87-0.87-1.8-1.14-2.76c-0.35-1.22-1.46-2.06-2.73-2.06h-2.05v-2.9h2.05c1.27,0,2.38-0.84,2.73-2.06
c0.27-0.96,0.66-1.89,1.14-2.76c0.62-1.11,0.43-2.49-0.47-3.39l-1.45-1.45l2.05-2.05l1.45,1.45c0.9,0.9,2.28,1.09,3.39,0.47
c0.87-0.49,1.8-0.87,2.76-1.14c1.22-0.35,2.06-1.46,2.06-2.73v-2.05h2.9v2.05c0,1.27,0.84,2.38,2.06,2.73
c0.96,0.27,1.89,0.66,2.76,1.14c1.11,0.62,2.49,0.43,3.39-0.47l1.45-1.45l2.05,2.05l-1.45,1.45c-0.9,0.9-1.09,2.28-0.47,3.39
c0.49,0.87,0.87,1.8,1.14,2.76c0.35,1.22,1.46,2.06,2.73,2.06h2.05V71.45z"/>
<path fill="#FFFFFF" d="M30,22.17c-4.32,0-7.83,3.51-7.83,7.83s3.51,7.83,7.83,7.83s7.83-3.51,7.83-7.83S34.32,22.17,30,22.17z
M30,32.17c-1.19,0-2.17-0.97-2.17-2.17s0.97-2.17,2.17-2.17s2.17,0.97,2.17,2.17S31.19,32.17,30,32.17z"/>
<path fill="#FFFFFF" d="M70,62.17c-4.32,0-7.83,3.51-7.83,7.83s3.51,7.83,7.83,7.83s7.83-3.51,7.83-7.83S74.32,62.17,70,62.17z
M70,72.17c-1.19,0-2.17-0.97-2.17-2.17s0.97-2.17,2.17-2.17s2.17,0.97,2.17,2.17S71.19,72.17,70,72.17z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,4 @@
src/slic3r/GUI/AboutDialog.cpp src/slic3r/GUI/AboutDialog.cpp
src/slic3r/GUI/AppConfig.cpp
src/slic3r/GUI/BackgroundSlicingProcess.cpp src/slic3r/GUI/BackgroundSlicingProcess.cpp
src/slic3r/GUI/BedShapeDialog.cpp src/slic3r/GUI/BedShapeDialog.cpp
src/slic3r/GUI/BedShapeDialog.hpp src/slic3r/GUI/BedShapeDialog.hpp
@ -9,45 +8,60 @@ src/slic3r/GUI/ConfigManipulation.cpp
src/slic3r/GUI/ConfigSnapshotDialog.cpp src/slic3r/GUI/ConfigSnapshotDialog.cpp
src/slic3r/GUI/ConfigWizard.cpp src/slic3r/GUI/ConfigWizard.cpp
src/slic3r/GUI/DoubleSlider.cpp src/slic3r/GUI/DoubleSlider.cpp
src/slic3r/GUI/ExtraRenderers.cpp
src/slic3r/GUI/ExtruderSequenceDialog.cpp src/slic3r/GUI/ExtruderSequenceDialog.cpp
src/slic3r/GUI/Field.cpp src/slic3r/GUI/Field.cpp
src/slic3r/GUI/FirmwareDialog.cpp src/slic3r/GUI/FirmwareDialog.cpp
src/slic3r/GUI/GCodeViewer.cpp
src/slic3r/GUI/GLCanvas3D.cpp src/slic3r/GUI/GLCanvas3D.cpp
src/slic3r/GUI/GLCanvas3DManager.cpp
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmosManager.cpp src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
src/slic3r/GUI/GUI.cpp src/slic3r/GUI/GUI.cpp
src/slic3r/GUI/GUI_App.cpp src/slic3r/GUI/GUI_App.cpp
src/slic3r/GUI/GUI_Init.cpp
src/slic3r/GUI/GUI_ObjectLayers.cpp src/slic3r/GUI/GUI_ObjectLayers.cpp
src/slic3r/GUI/GUI_ObjectList.cpp src/slic3r/GUI/GUI_ObjectList.cpp
src/slic3r/GUI/GUI_ObjectManipulation.cpp src/slic3r/GUI/GUI_ObjectManipulation.cpp
src/slic3r/GUI/GUI_ObjectSettings.cpp src/slic3r/GUI/GUI_ObjectSettings.cpp
src/slic3r/GUI/GUI_Preview.cpp src/slic3r/GUI/GUI_Preview.cpp
src/slic3r/GUI/Job.hpp src/slic3r/GUI/ImGuiWrapper.cpp
src/slic3r/GUI/Jobs/ArrangeJob.cpp
src/slic3r/GUI/Jobs/Job.cpp
src/slic3r/GUI/Jobs/RotoptimizeJob.cpp
src/slic3r/GUI/Jobs/SLAImportJob.cpp
src/slic3r/GUI/KBShortcutsDialog.cpp src/slic3r/GUI/KBShortcutsDialog.cpp
src/slic3r/GUI/MainFrame.cpp src/slic3r/GUI/MainFrame.cpp
src/slic3r/GUI/Mouse3DController.cpp src/slic3r/GUI/Mouse3DController.cpp
src/slic3r/GUI/MsgDialog.cpp src/slic3r/GUI/MsgDialog.cpp
src/slic3r/GUI/NotificationManager.hpp
src/slic3r/GUI/NotificationManager.cpp
src/slic3r/GUI/ObjectDataViewModel.cpp src/slic3r/GUI/ObjectDataViewModel.cpp
src/slic3r/GUI/OpenGLManager.cpp
src/slic3r/GUI/OptionsGroup.cpp src/slic3r/GUI/OptionsGroup.cpp
src/slic3r/GUI/PhysicalPrinterDialog.cpp
src/slic3r/GUI/Plater.cpp src/slic3r/GUI/Plater.cpp
src/slic3r/GUI/Preferences.cpp src/slic3r/GUI/Preferences.cpp
src/slic3r/GUI/Preset.cpp src/slic3r/GUI/PresetComboBoxes.cpp
src/slic3r/GUI/PresetBundle.cpp
src/slic3r/GUI/PresetHints.cpp src/slic3r/GUI/PresetHints.cpp
src/slic3r/GUI/PrintHostDialogs.cpp src/slic3r/GUI/PrintHostDialogs.cpp
src/slic3r/GUI/ProgressStatusBar.cpp src/slic3r/GUI/ProgressStatusBar.cpp
src/slic3r/GUI/RammingChart.cpp src/slic3r/GUI/RammingChart.cpp
src/slic3r/GUI/SavePresetDialog.cpp
src/slic3r/GUI/Search.cpp
src/slic3r/GUI/Selection.cpp src/slic3r/GUI/Selection.cpp
src/slic3r/GUI/SysInfoDialog.cpp src/slic3r/GUI/SysInfoDialog.cpp
src/slic3r/GUI/Tab.cpp src/slic3r/GUI/Tab.cpp
src/slic3r/GUI/Tab.hpp src/slic3r/GUI/Tab.hpp
src/slic3r/GUI/UnsavedChangesDialog.cpp
src/slic3r/GUI/UpdateDialogs.cpp src/slic3r/GUI/UpdateDialogs.cpp
src/slic3r/GUI/WipeTowerDialog.cpp src/slic3r/GUI/WipeTowerDialog.cpp
src/slic3r/GUI/wxExtensions.cpp src/slic3r/GUI/wxExtensions.cpp
@ -57,18 +71,22 @@ src/slic3r/Utils/FixModelByWin10.cpp
src/slic3r/Utils/FlashAir.cpp src/slic3r/Utils/FlashAir.cpp
src/slic3r/Utils/OctoPrint.cpp src/slic3r/Utils/OctoPrint.cpp
src/slic3r/Utils/PresetUpdater.cpp src/slic3r/Utils/PresetUpdater.cpp
src/libslic3r/SLA/Pad.cpp src/slic3r/Utils/Http.cpp
src/libslic3r/SLA/Hollowing.cpp src/slic3r/Utils/Process.cpp
src/libslic3r/Zipper.cpp
src/libslic3r/GCode.cpp src/libslic3r/GCode.cpp
src/libslic3r/ExtrusionEntity.cpp src/libslic3r/ExtrusionEntity.cpp
src/libslic3r/Flow.cpp src/libslic3r/Flow.cpp
src/libslic3r/Format/3mf.cpp src/libslic3r/Format/3mf.cpp
src/libslic3r/Format/AMF.cpp src/libslic3r/Format/AMF.cpp
src/libslic3r/GCode/PreviewData.cpp
src/libslic3r/miniz_extension.cpp
src/libslic3r/Preset.cpp
src/libslic3r/Print.cpp src/libslic3r/Print.cpp
src/libslic3r/SLA/Pad.cpp
src/libslic3r/SLA/Hollowing.cpp
src/libslic3r/SLAPrint.cpp src/libslic3r/SLAPrint.cpp
src/libslic3r/SLAPrintSteps.cpp src/libslic3r/SLAPrintSteps.cpp
src/libslic3r/PrintBase.cpp src/libslic3r/PrintBase.cpp
src/libslic3r/PrintConfig.cpp src/libslic3r/PrintConfig.cpp
src/libslic3r/Zipper.cpp
src/libslic3r/PrintObject.cpp src/libslic3r/PrintObject.cpp
src/libslic3r/GCode/PreviewData.cpp

View file

@ -1,2 +1,4 @@
min_slic3r_version = 2.3.0-alpha2
0.0.2 Added Anycubic Predator
min_slic3r_version = 2.3.0-alpha0 min_slic3r_version = 2.3.0-alpha0
0.0.1 Initial Version 0.0.1 Initial Version

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,4 +1,5 @@
min_slic3r_version = 2.2.0-alpha3 min_slic3r_version = 2.2.0-alpha3
0.0.2 General print quality improvements
0.0.1 Multiple Print models were unified into a single one. 0.0.1 Multiple Print models were unified into a single one.
0.0.1-beta2 Bed model and textures added. Materials all use the BOBO2 identifier. deretract speed set to 0 to use retract speed. 0.0.1-beta2 Bed model and textures added. Materials all use the BOBO2 identifier. deretract speed set to 0 to use retract speed.
0.0.1-beta1 Added new printer profiles for ditto printing. New retraction settings, new materials. Removed some settings which do not apply. More start gcode improvements. 0.0.1-beta1 Added new printer profiles for ditto printing. New retraction settings, new materials. Removed some settings which do not apply. More start gcode improvements.

View file

@ -5,9 +5,9 @@
name = BIBO name = BIBO
# Configuration version of this file. Config file will only be installed, if the config_version differs. # 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. # This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.1 config_version = 0.0.2
# Where to get the updates from? # Where to get the updates from?
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/BIBO/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/BIBO/
# The printer models will be shown by the Configuration Wizard in this order, # The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install. # also the first model installed & the first nozzle installed will be activated after install.
@ -856,4 +856,4 @@ bed_shape = -33x-93,0x-93,0x93,-33x93
#bed_texture = BIBO2.svg #bed_texture = BIBO2.svg
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nM104 S{temperature[0]} T0 ; set 1st nozzle heater to print temperature\n before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nM104 S{temperature[0]} T0 ; set 1st nozzle heater to print temperature\n
start_gcode = ;Start code PrusaSlicer BIBO 2 printers E2 only (i.e. T1)\nM420 S1 ; Turn on Ditto Printing\nG21 ; set units to metric\nG90 ; absolute positioning\nM107 ; start with the fan off\nM140 S{first_layer_bed_temperature[0] - 5} ; set bed temp\nM105 ; Report Temperatures\nM190 S{first_layer_bed_temperature[0]} ; wait for bed temp\nM104 S{first_layer_temperature[0]} T0 ; set 1st nozzle heater to ditto print temperature\nM104 S{first_layer_temperature[0]} T1 ; set 2nd nozzle heater to first layer temperature\nM105 ; Report Temperatures\nM109 S{first_layer_temperature[0]} T0 ; set 1st nozzle heater to ditto printing temperature\nM109 S{first_layer_temperature[0]} T1 ; Wait for 2nd nozzle heater to first layer temperature\nM105 ; Report Temperatures\nG28 X0 Y0 ; move X/Y to min endstops\nG28 Z0 ; move Z to min endstops\nG1 Z2 F400 ; move the print bed down 2mm\nT0 ; switch to tool position T0\nG90 ; absolute positioning\nG92 E0.0 ; zero the current extruder coordinate\nG28 ; Home all axis\nG1 Y0 F1200 E0 ; move Y to min endstop and reset extruder\nG92 E0.0 ; zero the current extruder coordinate\nT1 ; switch to tool position T1\nG92 E0.0 ; zero the current extruder coordinate\nM117 E2 nozzle wipe... ; Put Nozzle wipe message on screen, Attempt Nozzle Wipe (for ooze free startup)\nG1 X-15.0 Y-92.9 Z0.3 F2400.0 ; move to start-line position\nG1 X15.0 Y-92.9 Z0.3 F1000.0 E2 ; draw 1st line\nG1 X15.0 Y-92.6 Z0.3 F3000.0 ; move to side a little\nG1 X-15.0 Y-92.6 Z0.3 F1000.0 E4 ; draw 2nd line\nG1 X-15.0 Y-92.3 Z0.3 F3000.0 ; move to side a little\nG1 X15.0 Y-92.3 Z0.3 F1000.0 E6 ; draw 3rd line\nG1 X15.0 Y-92 Z0.3 F3000.0 ; move to side a little\nG1 X-15.0 Y-92 Z0.3 F1000.0 E8 ; draw 4th line\nG92 E0.0 ; reset extruder coordinate to zero before printing\nM117 BIBO Now Printing from E2... ; Put now printing message on screen start_gcode = ;Start code PrusaSlicer BIBO 2 printers E2 only (i.e. T1)\nM420 S1 ; Turn on Ditto Printing\nG21 ; set units to metric\nG90 ; absolute positioning\nM107 ; start with the fan off\nM140 S{first_layer_bed_temperature[0] - 5} ; set bed temp\nM105 ; Report Temperatures\nM190 S{first_layer_bed_temperature[0]} ; wait for bed temp\nM104 S{first_layer_temperature[0]} T0 ; set 1st nozzle heater to ditto print temperature\nM104 S{first_layer_temperature[0]} T1 ; set 2nd nozzle heater to first layer temperature\nM105 ; Report Temperatures\nM109 S{first_layer_temperature[0]} T0 ; set 1st nozzle heater to ditto printing temperature\nM109 S{first_layer_temperature[0]} T1 ; Wait for 2nd nozzle heater to first layer temperature\nM105 ; Report Temperatures\nG28 X0 Y0 ; move X/Y to min endstops\nG28 Z0 ; move Z to min endstops\nG1 Z2 F400 ; move the print bed down 2mm\nT0 ; switch to tool position T0\nG90 ; absolute positioning\nG92 E0.0 ; zero the current extruder coordinate\nG28 ; Home all axis\nG1 Y0 F1200 E0 ; move Y to min endstop and reset extruder\nG92 E0.0 ; zero the current extruder coordinate\nT1 ; switch to tool position T1\nG92 E0.0 ; zero the current extruder coordinate\nM117 E2 nozzle wipe... ; Put Nozzle wipe message on screen, Attempt Nozzle Wipe (for ooze free startup)\nG1 X-15.0 Y-92.9 Z0.3 F2400.0 ; move to start-line position\nG1 X15.0 Y-92.9 Z0.3 F1000.0 E2 ; draw 1st line\nG1 X15.0 Y-92.6 Z0.3 F3000.0 ; move to side a little\nG1 X-15.0 Y-92.6 Z0.3 F1000.0 E4 ; draw 2nd line\nG1 X-15.0 Y-92.3 Z0.3 F3000.0 ; move to side a little\nG1 X15.0 Y-92.3 Z0.3 F1000.0 E6 ; draw 3rd line\nG1 X15.0 Y-92 Z0.3 F3000.0 ; move to side a little\nG1 X-15.0 Y-92 Z0.3 F1000.0 E8 ; draw 4th line\nG92 E0.0 ; reset extruder coordinate to zero before printing\nM117 BIBO Now Printing from E2... ; Put now printing message on screen
end_gcode = ;BIBO End GCode\nM107 ; turn fans off\nG91 ; Relative positioning\nG1 Z1 F100\nM140 S0 ; Disable heated bed\nM104 T0 S0 ; extruder T0 heater off\nM104 T1 S0 ; extruder T1 heater off\nG1 Z+0.5 X-20 Y-20 F300 ; move Z down then move print head a bit out of the way\nG28 X0 Y0 ; move X/Y to min endstops, so the head is out of the way\nG90 ; Absolute positioning\nG92 E0.0 ; Reset extruder position\nM84 ; Turn steppers off\nM420 S0 ; Turn off Ditto Printing function\nM117 BIBO Print complete ; Put print complete message on screen end_gcode = ;BIBO End GCode\nM107 ; turn fans off\nG91 ; Relative positioning\nG1 Z1 F100\nM140 S0 ; Disable heated bed\nM104 T0 S0 ; extruder T0 heater off\nM104 T1 S0 ; extruder T1 heater off\nG1 Z+0.5 X-20 Y-20 F300 ; move Z down then move print head a bit out of the way\nG28 X0 Y0 ; move X/Y to min endstops, so the head is out of the way\nG90 ; Absolute positioning\nG92 E0.0 ; Reset extruder position\nM84 ; Turn steppers off\nM420 S0 ; Turn off Ditto Printing function\nM117 BIBO Print complete ; Put print complete message on screen

View file

@ -1,5 +1,8 @@
min_slic3r_version = 2.2.0-alpha3 min_slic3r_version = 2.3.0-alpha2
0.0.4 Added initial CR-10 profile, end g-code improvements.
min_slic3r_version = 2.3.0-alpha0
0.0.3 Added Ender-2, Ender-3 BLTouch, updated Ender-3 bed texture. 0.0.3 Added Ender-2, Ender-3 BLTouch, updated Ender-3 bed texture.
min_slic3r_version = 2.2.0-alpha3
0.0.2 Updated for PrusaSlicer 2.2.0-rc 0.0.2 Updated for PrusaSlicer 2.2.0-rc
0.0.2-beta Update for PrusaSlicer 2.2.0-beta 0.0.2-beta Update for PrusaSlicer 2.2.0-beta
0.0.2-alpha1 Extended list of default filaments to be installed 0.0.2-alpha1 Extended list of default filaments to be installed

View file

@ -5,10 +5,10 @@
name = Creality name = Creality
# Configuration version of this file. Config file will only be installed, if the config_version differs. # 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. # This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.3 config_version = 0.0.4
# Where to get the updates from? # Where to get the updates from?
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
# changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1% # changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
# The printer models will be shown by the Configuration Wizard in this order, # The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install. # also the first model installed & the first nozzle installed will be activated after install.
@ -18,25 +18,145 @@ config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/Prusa
name = Creality Ender-3 name = Creality Ender-3
variants = 0.4 variants = 0.4
technology = FFF technology = FFF
family = ENDER
bed_model = ender3_bed.stl bed_model = ender3_bed.stl
bed_texture = ender3.svg bed_texture = ender3.svg
default_materials = Generic PLA @ENDER3; Generic PETG @ENDER3; Generic ABS @ENDER3; Prusament PLA @ENDER3; Prusament PETG @ENDER3 default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER3BLTOUCH] [printer_model:ENDER3BLTOUCH]
name = Creality Ender-3 BLTouch name = Creality Ender-3 BLTouch
variants = 0.4 variants = 0.4
technology = FFF technology = FFF
family = ENDER
bed_model = ender3_bed.stl bed_model = ender3_bed.stl
bed_texture = ender3.svg bed_texture = ender3.svg
default_materials = Generic PLA @ENDER3; Generic PETG @ENDER3; Generic ABS @ENDER3; Prusament PLA @ENDER3; Prusament PETG @ENDER3 default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER5]
name = Creality Ender-5
variants = 0.4
technology = FFF
family = ENDER
bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER5PLUS]
name = Creality Ender-5 Plus
variants = 0.4
technology = FFF
family = ENDER
bed_model = ender5plus_bed.stl
bed_texture = ender5plus.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER2] [printer_model:ENDER2]
name = Creality Ender-2 name = Creality Ender-2
variants = 0.4 variants = 0.4
technology = FFF technology = FFF
family = ENDER
bed_model = ender2_bed.stl bed_model = ender2_bed.stl
bed_texture = ender2.svg bed_texture = ender2.svg
default_materials = Generic PLA @ENDER3; Generic PETG @ENDER3; Generic ABS @ENDER3; Prusament PLA @ENDER3; Prusament PETG @ENDER3 default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10MINI]
name = Creality CR-10 Mini
variants = 0.4
technology = FFF
family = CR
bed_model = cr10mini_bed.stl
bed_texture = cr10mini.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10]
name = Creality CR-10
variants = 0.4
technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10V2]
name = Creality CR-10 V2
variants = 0.4
technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10V3]
name = Creality CR-10 V3
variants = 0.4
technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10S]
name = Creality CR-10 S
variants = 0.4
technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10SPRO]
name = Creality CR-10 S Pro
variants = 0.4
technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10SPROV2]
name = Creality CR-10 S Pro V2
variants = 0.4
technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10S4]
name = Creality CR-10 S4
variants = 0.4
technology = FFF
family = CR
bed_model = cr10s4_bed.stl
bed_texture = cr10s4.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR10S5]
name = Creality CR-10 S5
variants = 0.4
technology = FFF
family = CR
bed_model = cr10s5_bed.stl
bed_texture = cr10s5.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR20]
name = Creality CR-20
variants = 0.4
technology = FFF
family = CR
bed_model = ender3_bed.stl
bed_texture = cr20.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:CR20PRO]
name = Creality CR-20 Pro
variants = 0.4
technology = FFF
family = CR
bed_model = ender3_bed.stl
bed_texture = cr20.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
# All presets starting with asterisk, for example *common*, are intermediate and they will # All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface. # not make it into the user interface.
@ -57,6 +177,7 @@ ensure_vertical_shell_thickness = 1
external_fill_pattern = rectilinear external_fill_pattern = rectilinear
external_perimeters_first = 0 external_perimeters_first = 0
external_perimeter_extrusion_width = 0.45 external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 25
extra_perimeters = 0 extra_perimeters = 0
extruder_clearance_height = 25 extruder_clearance_height = 25
extruder_clearance_radius = 45 extruder_clearance_radius = 45
@ -75,6 +196,7 @@ infill_extrusion_width = 0.45
infill_first = 0 infill_first = 0
infill_only_where_needed = 0 infill_only_where_needed = 0
infill_overlap = 25% infill_overlap = 25%
infill_speed = 50
interface_shells = 0 interface_shells = 0
max_print_speed = 100 max_print_speed = 100
max_volumetric_extrusion_rate_slope_negative = 0 max_volumetric_extrusion_rate_slope_negative = 0
@ -89,6 +211,7 @@ output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0
perimeters = 2 perimeters = 2
perimeter_extruder = 1 perimeter_extruder = 1
perimeter_extrusion_width = 0.45 perimeter_extrusion_width = 0.45
perimeter_speed = 40
post_process = post_process =
print_settings_id = print_settings_id =
raft_layers = 0 raft_layers = 0
@ -103,11 +226,12 @@ solid_infill_below_area = 0
solid_infill_every_layers = 0 solid_infill_every_layers = 0
solid_infill_extruder = 1 solid_infill_extruder = 1
solid_infill_extrusion_width = 0.45 solid_infill_extrusion_width = 0.45
solid_infill_speed = 40
spiral_vase = 0 spiral_vase = 0
standby_temperature_delta = -5 standby_temperature_delta = -5
support_material = 0 support_material = 0
support_material_extruder = 0 support_material_extruder = 0
support_material_extrusion_width = 0.4 support_material_extrusion_width = 0.38
support_material_interface_extruder = 0 support_material_interface_extruder = 0
support_material_angle = 0 support_material_angle = 0
support_material_buildplate_only = 0 support_material_buildplate_only = 0
@ -125,9 +249,9 @@ support_material_threshold = 45
support_material_with_sheath = 0 support_material_with_sheath = 0
support_material_xy_spacing = 60% support_material_xy_spacing = 60%
thin_walls = 0 thin_walls = 0
top_infill_extrusion_width = 0.45 top_infill_extrusion_width = 0.4
top_solid_infill_speed = 40 top_solid_infill_speed = 30
travel_speed = 100 travel_speed = 150
wipe_tower = 0 wipe_tower = 0
wipe_tower_bridging = 10 wipe_tower_bridging = 10
wipe_tower_rotation_angle = 0 wipe_tower_rotation_angle = 0
@ -136,69 +260,63 @@ wipe_tower_x = 170
wipe_tower_y = 140 wipe_tower_y = 140
xy_size_compensation = 0 xy_size_compensation = 0
[print:*0.10mm*]
inherits = *common*
layer_height = 0.1
perimeters = 3
bottom_solid_layers = 7
top_solid_layers = 9
[print:*0.12mm*] [print:*0.12mm*]
inherits = *common* inherits = *common*
perimeter_speed = 40
external_perimeter_speed = 25
infill_speed = 50
solid_infill_speed = 40
layer_height = 0.12 layer_height = 0.12
perimeters = 3 perimeters = 3
top_infill_extrusion_width = 0.4
bottom_solid_layers = 6 bottom_solid_layers = 6
top_solid_layers = 7 top_solid_layers = 7
[print:*0.15mm*]
inherits = *common*
layer_height = 0.15
bottom_solid_layers = 5
top_solid_layers = 7
[print:*0.20mm*] [print:*0.20mm*]
inherits = *common* inherits = *common*
perimeter_speed = 40
external_perimeter_speed = 25
infill_speed = 50
solid_infill_speed = 40
layer_height = 0.20 layer_height = 0.20
top_infill_extrusion_width = 0.4
bottom_solid_layers = 4 bottom_solid_layers = 4
top_solid_layers = 5 top_solid_layers = 5
[print:*0.24mm*] [print:*0.24mm*]
inherits = *common* inherits = *common*
perimeter_speed = 40
external_perimeter_speed = 25
infill_speed = 50
solid_infill_speed = 40
layer_height = 0.24 layer_height = 0.24
top_infill_extrusion_width = 0.45 top_infill_extrusion_width = 0.45
bottom_solid_layers = 3 bottom_solid_layers = 3
top_solid_layers = 4 top_solid_layers = 4
[print:0.12mm DETAIL @ENDER3] [print:0.10mm HIGHDETAIL @CREALITY]
inherits = *0.10mm*
renamed_from = "0.10mm HIGHDETAIL @ENDER3"
compatible_printers_condition = printer_model=~/(ENDER|CR).*/ and nozzle_diameter[0]==0.4
[print:0.12mm DETAIL @CREALITY]
inherits = *0.12mm* inherits = *0.12mm*
# alias = 0.12mm DETAIL renamed_from = "0.12mm DETAIL @ENDER3"
travel_speed = 150 compatible_printers_condition = printer_model=~/(ENDER|CR).*/ and nozzle_diameter[0]==0.4
infill_speed = 50
solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_extrusion_width = 0.38
compatible_printers_condition = printer_model=~/ENDER.*/ and nozzle_diameter[0]==0.4
[print:0.20mm NORMAL @ENDER3] [print:0.15mm OPTIMAL @CREALITY]
inherits = *0.15mm*
renamed_from = "0.15mm OPTIMAL @ENDER3"
compatible_printers_condition = printer_model=~/(ENDER|CR).*/ and nozzle_diameter[0]==0.4
[print:0.20mm NORMAL @CREALITY]
inherits = *0.20mm* inherits = *0.20mm*
# alias = 0.20mm NORMAL renamed_from = "0.20mm NORMAL @ENDER3"
travel_speed = 150 compatible_printers_condition = printer_model=~/(ENDER|CR).*/ and nozzle_diameter[0]==0.4
infill_speed = 50
solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_extrusion_width = 0.38
compatible_printers_condition = printer_model=~/ENDER.*/ and nozzle_diameter[0]==0.4
[print:0.24mm DRAFT @ENDER3] [print:0.24mm DRAFT @CREALITY]
inherits = *0.24mm* inherits = *0.24mm*
# alias = 0.24mm DRAFT renamed_from = "0.24mm DRAFT @ENDER3"
travel_speed = 150 compatible_printers_condition = printer_model=~/(ENDER|CR).*/ and nozzle_diameter[0]==0.4
infill_speed = 50
solid_infill_speed = 40
top_solid_infill_speed = 30
support_material_extrusion_width = 0.38
compatible_printers_condition = printer_model=~/ENDER.*/ and nozzle_diameter[0]==0.4
# Common filament preset # Common filament preset
[filament:*common*] [filament:*common*]
@ -217,7 +335,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_CREALITY.*/
[filament:*PLA*] [filament:*PLA*]
inherits = *common* inherits = *common*
bed_temperature = 40 bed_temperature = 60
fan_below_layer_time = 100 fan_below_layer_time = 100
filament_colour = #FF3232 filament_colour = #FF3232
filament_max_volumetric_speed = 15 filament_max_volumetric_speed = 15
@ -245,7 +363,7 @@ filament_max_volumetric_speed = 8
filament_type = PETG filament_type = PETG
filament_density = 1.27 filament_density = 1.27
filament_cost = 30 filament_cost = 30
first_layer_bed_temperature =70 first_layer_bed_temperature = 70
first_layer_temperature = 240 first_layer_temperature = 240
fan_always_on = 1 fan_always_on = 1
max_fan_speed = 50 max_fan_speed = 50
@ -273,78 +391,108 @@ bridge_fan_speed = 30
top_fan_speed = 0 top_fan_speed = 0
temperature = 245 temperature = 245
[filament:Generic PLA @ENDER3] [filament:Generic PLA @CREALITY]
inherits = *PLA* inherits = *PLA*
# alias = Generic PLA renamed_from = "Generic PLA @ENDER3"
filament_vendor = Generic filament_vendor = Generic
[filament:Generic PETG @ENDER3] [filament:Generic PETG @CREALITY]
inherits = *PET* inherits = *PET*
renamed_from = "Generic PETG @ENDER3"
filament_vendor = Generic filament_vendor = Generic
[filament:Generic ABS @ENDER3] [filament:Generic ABS @CREALITY]
inherits = *ABS* inherits = *ABS*
# alias = Generic ABS renamed_from = "Generic ABS @ENDER3"
first_layer_bed_temperature = 90 first_layer_bed_temperature = 90
bed_temperature = 90 bed_temperature = 90
filament_vendor = Generic filament_vendor = Generic
[filament:Creality PLA @ENDER3] [filament:Creality PLA @CREALITY]
inherits = *PLA* inherits = *PLA*
# alias = Creality PLA renamed_from = "Creality PLA @ENDER3"
filament_vendor = Creality filament_vendor = Creality
temperature = 205 temperature = 205
bed_temperature = 40 bed_temperature = 40
first_layer_temperature = 210 first_layer_temperature = 210
first_layer_bed_temperature =40 first_layer_bed_temperature = 40
[filament:Creality PETG @ENDER3] [filament:Creality PETG @CREALITY]
inherits = *PET* inherits = *PET*
# alias = Creality PETG renamed_from = "Creality PETG @ENDER3"
filament_vendor = Creality filament_vendor = Creality
temperature = 240 temperature = 240
bed_temperature = 70 bed_temperature = 70
first_layer_temperature = 240 first_layer_temperature = 240
first_layer_bed_temperature =70 first_layer_bed_temperature = 70
max_fan_speed = 40 max_fan_speed = 40
min_fan_speed = 20 min_fan_speed = 20
[filament:Creality ABS @ENDER3] [filament:Creality ABS @CREALITY]
inherits = *ABS* inherits = *ABS*
# alias = Creality ABS renamed_from = "Creality ABS @ENDER3"
filament_vendor = Creality filament_vendor = Creality
temperature = 240 temperature = 240
bed_temperature = 90 bed_temperature = 90
first_layer_temperature = 240 first_layer_temperature = 240
first_layer_bed_temperature =90 first_layer_bed_temperature = 90
[filament:Prusament PLA @ENDER3] [filament:Prusament PLA @CREALITY]
inherits = *PLA* inherits = *PLA*
# alias = Prusament PLA renamed_from = "Prusament PLA @ENDER3"
filament_vendor = Prusa Polymers filament_vendor = Prusa Polymers
temperature = 215 temperature = 215
bed_temperature = 40 bed_temperature = 40
first_layer_temperature = 215 first_layer_temperature = 215
first_layer_bed_temperature =40 first_layer_bed_temperature = 40
filament_cost = 24.99 filament_cost = 24.99
filament_density = 1.24 filament_density = 1.24
[filament:Prusament PETG @ENDER3] [filament:Prusament PETG @CREALITY]
inherits = *PET* inherits = *PET*
# alias = Prusament PETG renamed_from = "Prusament PETG @ENDER3"
filament_vendor = Prusa Polymers filament_vendor = Prusa Polymers
temperature = 245 temperature = 245
bed_temperature = 70 bed_temperature = 70
first_layer_temperature = 245 first_layer_temperature = 245
first_layer_bed_temperature =70 first_layer_bed_temperature = 70
filament_cost = 24.99 filament_cost = 24.99
filament_density = 1.27 filament_density = 1.27
[filament:Devil Design PLA @CREALITY]
inherits = *PLA*
filament_vendor = Devil Design
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 19.00
filament_density = 1.24
[filament:Extrudr PLA NX2 @CREALITY]
inherits = *PLA*
filament_vendor = Extrudr
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 23.63
filament_density = 1.3
[filament:Real Filament PLA @CREALITY]
inherits = *PLA*
filament_vendor = Real Filament
temperature = 195
bed_temperature = 60
first_layer_temperature = 200
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.24
# Common printer preset # Common printer preset
[printer:*common*] [printer:*common*]
printer_technology = FFF printer_technology = FFF
bed_shape = 0x0,200x0,200x200,0x200 before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
between_objects_gcode = between_objects_gcode =
deretract_speed = 0 deretract_speed = 0
extruder_colour = #FFFF00 extruder_colour = #FFFF00
@ -373,8 +521,6 @@ max_layer_height = 0.3
min_layer_height = 0.07 min_layer_height = 0.07
max_print_height = 200 max_print_height = 200
nozzle_diameter = 0.4 nozzle_diameter = 0.4
octoprint_apikey =
octoprint_host =
printer_notes = printer_notes =
printer_settings_id = printer_settings_id =
retract_before_travel = 1 retract_before_travel = 1
@ -388,11 +534,7 @@ retract_lift_below = 0
retract_restart_extra = 0 retract_restart_extra = 0
retract_restart_extra_toolchange = 0 retract_restart_extra_toolchange = 0
retract_speed = 35 retract_speed = 35
serial_port =
serial_speed = 250000
single_extruder_multi_material = 0 single_extruder_multi_material = 0
start_gcode = G90 ; 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 ; home all\nG92 E0.0\nG1 Z0.15 F240\nG1 X60.0 E9.0 F800.0 ; intro line\nG1 X100.0 E12.5 F800 ; intro line\nG92 E0.0
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 F3000 ; home X axis\nM84 ; disable motors
toolchange_gcode = toolchange_gcode =
use_firmware_retraction = 0 use_firmware_retraction = 0
use_relative_e_distances = 1 use_relative_e_distances = 1
@ -404,14 +546,15 @@ printer_model =
default_print_profile = default_print_profile =
default_filament_profile = default_filament_profile =
[printer:Creality ENDER-3] [printer:Creality Ender-3]
inherits = *common* inherits = *common*
renamed_from = "Creality ENDER-3"
printer_model = ENDER3 printer_model = ENDER3
printer_variant = 0.4 printer_variant = 0.4
max_layer_height = 0.25 max_layer_height = 0.25
min_layer_height = 0.1 min_layer_height = 0.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_CREALITY\nPRINTER_MODEL_ENDER3 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_ENDER3\nPRINTER_HAS_BOWDEN
bed_shape = 0x0,220x0,220x220,0x220 bed_shape = 3x3,228x3,228x228,3x228
max_print_height = 250 max_print_height = 250
machine_max_acceleration_e = 5000 machine_max_acceleration_e = 5000
machine_max_acceleration_extruding = 500 machine_max_acceleration_extruding = 500
@ -428,29 +571,134 @@ machine_max_jerk_x = 8
machine_max_jerk_y = 8 machine_max_jerk_y = 8
machine_max_jerk_z = 0.4 machine_max_jerk_z = 0.4
machine_min_extruding_rate = 0 machine_min_extruding_rate = 0
machine_min_travel_rate = 0 machine_min_travel_rate = 0
nozzle_diameter = 0.4 nozzle_diameter = 0.4
retract_before_travel = 2 retract_before_travel = 2
retract_length = 5 retract_length = 5
retract_speed = 60 retract_speed = 60
deretract_speed = 40 deretract_speed = 40
retract_before_wipe = 70% retract_before_wipe = 70%
default_print_profile = 0.20mm NORMAL default_print_profile = 0.15mm OPTIMAL @CREALITY
default_filament_profile = Creality PLA default_filament_profile = Creality PLA @CREALITY
start_gcode = G90 ; 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 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E30 F1200.0 ; intro line\nG92 E0.0 start_gcode = G90 ; 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 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 E0.0
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+10, max_print_height)} F600{endif} ; Move print head up\nG1 X0 Y200 F3000 ; present print\nM84 X Y E ; disable motors end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y170 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+min(layer_z+70, max_print_height-10)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
[printer:*abl*] [printer:*abl*]
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z2 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E30 F1200.0 ; intro line\nG92 E0.0 start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 E0.0
[printer:Creality ENDER-3 BLTouch] [printer:*invertedz*]
inherits = Creality ENDER-3; *abl* end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed down\nM84 X Y E ; disable motors
[printer:Creality Ender-3 BLTouch]
inherits = Creality Ender-3; *abl*
renamed_from = "Creality ENDER-3 BLTouch"
printer_model = ENDER3BLTOUCH printer_model = ENDER3BLTOUCH
[printer:Creality ENDER-2] [printer:Creality Ender-5]
inherits = Creality ENDER-3 inherits = Creality Ender-3; *invertedz*
retract_length = 6
bed_shape = 5x2.5,225x2.5,225x222.5,5x222.5
printer_model = ENDER5
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_ENDER5\nPRINTER_HAS_BOWDEN
max_print_height = 300
[printer:Creality Ender-5 Plus]
inherits = Creality Ender-3; *abl*; *invertedz*
retract_length = 6
bed_shape = 5x5,355x5,355x355,5x355
printer_model = ENDER5PLUS
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_ENDER5PLUS\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality Ender-2]
inherits = Creality Ender-3
renamed_from = "Creality ENDER-2"
bed_shape = 0x0,150x0,150x150,0x150 bed_shape = 0x0,150x0,150x150,0x150
printer_model = ENDER2 printer_model = ENDER2
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_ENDER2\nPRINTER_HAS_BOWDEN
max_print_height = 200 max_print_height = 200
start_gcode = G90 ; 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 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 X15 Y135 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E30 F1200.0 ; intro line\nG92 E0.0 start_gcode = G90 ; 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 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 X15 Y135 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 E0.0
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+10, max_print_height)} F600{endif} ; Move print head up\nG1 X0 Y140 F3000 ; present print\nM84 X Y E ; disable motors end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y140 F3000 ; present print\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
[printer:Creality CR-10 Mini]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 2.5x5,2.5x225,302.5x225,302.5x5
printer_model = CR10MINI
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_CR10MINI\nPRINTER_HAS_BOWDEN
max_print_height = 300
[printer:Creality CR-10]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305
printer_model = CR10
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_CR10\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 V2]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305
printer_model = CR10V2
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_CR10V2\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 V3]
inherits = Creality Ender-3
retract_length = 1
bed_shape = 5x5,305x5,305x305,5x305
printer_model = CR10V3
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_CR10V3
max_print_height = 400
[printer:Creality CR-10 S]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305
printer_model = CR10S
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_CR10S\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 S Pro]
inherits = Creality Ender-3; *abl*
retract_length = 6
bed_shape = 0x0,300x0,300x300,0x300
printer_model = CR10SPRO
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_CR10SPRO\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 S Pro V2]
inherits = Creality Ender-3; *abl*
retract_length = 6
bed_shape = 5x5,305x5,305x305,5x305
printer_model = CR10SPROV2
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_CR10SPROV2\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 S4]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 5x5,405x5,405x405,5x405
printer_model = CR10S4
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_CR10S4\nPRINTER_HAS_BOWDEN
max_print_height = 400
[printer:Creality CR-10 S5]
inherits = Creality Ender-3
retract_length = 6
bed_shape = 5x5,505x5,505x505,5x505
printer_model = CR10S5
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_CR10S5\nPRINTER_HAS_BOWDEN
max_print_height = 500
[printer:Creality CR-20]
inherits = Creality Ender-3
printer_model = CR20
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_CR20\nPRINTER_HAS_BOWDEN
[printer:Creality CR-20 Pro]
inherits = Creality Ender-3; *abl*
retract_length = 4
printer_model = CR20PRO
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_CR20PRO\nPRINTER_HAS_BOWDEN

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="300mm" height="300mm" version="1.1" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="299.5" height="299.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="300mm" height="220mm" version="1.1" viewBox="0 0 300 220" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="299.5" height="219.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="400mm" height="400mm" version="1.1" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="399.5" height="399.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="500mm" height="500mm" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="499.5" height="499.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="225mm" height="225mm" version="1.1" viewBox="0 0 225 225" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="224.5" height="224.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="350mm" height="350mm" version="1.1" viewBox="0 0 350 350" xmlns="http://www.w3.org/2000/svg">
<rect x=".25" y=".25" width="349.5" height="349.5" fill="none" stroke="#fff" stroke-width=".5"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
# Vendor name will be shown by the Config Wizard. # Vendor name will be shown by the Config Wizard.
name = LulzBot name = LulzBot
config_version = 0.0.1 config_version = 0.0.1
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/LulzBot/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/LulzBot/
[printer_model:MINI_AERO] [printer_model:MINI_AERO]
name = Mini Aero name = Mini Aero

View file

@ -1,4 +1,12 @@
min_slic3r_version = 2.2.0-alpha3 min_slic3r_version = 2.2.0-alpha3
1.1.10 Updated firmware version.
1.1.9 Updated K values in filament profiles (linear advance). Added new filament profiles and SLA materials.
1.1.8 Updated start/end g-code scripts for MK3 family printer profiles (reduced extruder motor current for some print profiles). Added new filament and SLA material profiles.
1.1.7 Updated end g-code for MMU2 Single printer profiles. Added/updated filament and SLA material profiles.
1.1.6 Updated firmware version for MK2.5/S and MK3/S.
1.1.5 Updated MMU1 specific retraction settings for Prusament PC Blend
1.1.4 Added Prusament PC Blend filament profile.
1.1.3 Added SLA material and filament profile
1.1.2 Added renamed_from fields for PETG filaments to indicate that they were renamed from PET. 1.1.2 Added renamed_from fields for PETG filaments to indicate that they were renamed from PET.
1.1.1 Added Verbatim and Fiberlogy PETG filament profiles. Updated auto cooling settings for ABS. 1.1.1 Added Verbatim and Fiberlogy PETG filament profiles. Updated auto cooling settings for ABS.
1.1.1-beta Updated for PrusaSlicer 2.2.0-beta 1.1.1-beta Updated for PrusaSlicer 2.2.0-beta
@ -11,6 +19,8 @@ min_slic3r_version = 2.2.0-alpha0
1.1.1-alpha2 Bumped up config version, so our in house customer will get updated profiles. 1.1.1-alpha2 Bumped up config version, so our in house customer will get updated profiles.
1.1.0 Filament aliases, Creality profiles and other goodies for PrusaSlicer 2.2.0-alpha0 1.1.0 Filament aliases, Creality profiles and other goodies for PrusaSlicer 2.2.0-alpha0
min_slic3r_version = 2.1.1-beta0 min_slic3r_version = 2.1.1-beta0
1.0.10 Updated firmware version for MK2.5/S and MK3/S.
1.0.9 Updated firmware version for MK2.5/S and MK3/S.
1.0.8 Various changes in FFF profiles, new filaments/materials added. See changelog. 1.0.8 Various changes in FFF profiles, new filaments/materials added. See changelog.
1.0.7 Updated layer height limits for MINI 1.0.7 Updated layer height limits for MINI
1.0.6 Added Prusa MINI profiles 1.0.6 Added Prusa MINI profiles
@ -27,6 +37,8 @@ min_slic3r_version = 2.1.0-alpha0
1.0.0-alpha1 Added Prusament ASA profile 1.0.0-alpha1 Added Prusament ASA profile
1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX 1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX
min_slic3r_version = 1.42.0-alpha6 min_slic3r_version = 1.42.0-alpha6
0.8.9 Updated firmware version for MK2.5/S and MK3/S.
0.8.8 Updated firmware version for MK2.5/S and MK3/S.
0.8.7 Updated firmware version 0.8.7 Updated firmware version
0.8.6 Updated firmware version for MK2.5/S and MK3/S 0.8.6 Updated firmware version for MK2.5/S and MK3/S
0.8.5 Updated SL1 printer and material settings 0.8.5 Updated SL1 printer and material settings
@ -53,6 +65,8 @@ min_slic3r_version = 1.42.0-alpha
0.4.0-alpha3 Update of SLA profiles 0.4.0-alpha3 Update of SLA profiles
0.4.0-alpha2 First SLA profiles 0.4.0-alpha2 First SLA profiles
min_slic3r_version = 1.41.3-alpha min_slic3r_version = 1.41.3-alpha
0.4.12 Updated firmware version for MK2.5/S and MK3/S.
0.4.11 Updated firmware version for MK2.5/S and MK3/S.
0.4.10 Updated firmware version 0.4.10 Updated firmware version
0.4.9 Updated firmware version for MK2.5/S and MK3/S 0.4.9 Updated firmware version for MK2.5/S and MK3/S
0.4.8 MK2.5/3/S FW update 0.4.8 MK2.5/3/S FW update
@ -65,6 +79,7 @@ min_slic3r_version = 1.41.3-alpha
0.4.1 New MK2.5S and MK3S FW versions 0.4.1 New MK2.5S and MK3S FW versions
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt 0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
min_slic3r_version = 1.41.1 min_slic3r_version = 1.41.1
0.3.11 Updated firmware version for MK2.5/S and MK3/S.
0.3.10 Updated firmware version 0.3.10 Updated firmware version
0.3.9 Updated firmware version for MK2.5/S and MK3/S 0.3.9 Updated firmware version for MK2.5/S and MK3/S
0.3.8 MK2.5/3/S FW update 0.3.8 MK2.5/3/S FW update
@ -123,4 +138,4 @@ min_slic3r_version = 1.40.0-alpha
0.1.3 Fixed an incorrect position of the max_print_height parameter 0.1.3 Fixed an incorrect position of the max_print_height parameter
0.1.2 Wipe tower changes 0.1.2 Wipe tower changes
0.1.1 Minor print speed adjustments 0.1.1 Minor print speed adjustments
0.1.0 Initial 0.1.0 Initial

File diff suppressed because it is too large Load diff

View file

@ -1,2 +1,3 @@
min_slic3r_version = 2.3.0-alpha0 min_slic3r_version = 2.3.0-alpha0
0.0.1 Initial TriLAB bundle 0.0.2 Added 0.15mm print profile
0.0.1 Initial TriLAB bundle

View file

@ -4,13 +4,13 @@
[vendor] [vendor]
# Vendor name will be shown by the Config Wizard. # Vendor name will be shown by the Config Wizard.
name = TRILAB name = TriLAB
# Configuration version of this file. Config file will only be installed, if the config_version differs. # 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. # This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.1 config_version = 0.0.2
# Where to get the updates from? # Where to get the updates from?
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/ config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
# changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1% # changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
# The printer models will be shown by the Configuration Wizard in this order, # The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install. # also the first model installed & the first nozzle installed will be activated after install.
@ -43,10 +43,15 @@ default_materials = DeltiQ PLA; DeltiQ ASA; DeltiQ PET; DeltiQ ABS; DeltiQ CPE
# All presets starting with asterisk, for example *common*, are intermediate and they will # All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface. # not make it into the user interface.
[print:DeltiQ 0.15mm]
inherits = DeltiQ 0.2mm
layer_height = 0.15
bottom_solid_layers = 5
top_solid_layers = 6
[print:DeltiQ 0.2mm] [print:DeltiQ 0.2mm]
avoid_crossing_perimeters = 0 avoid_crossing_perimeters = 0
bottom_solid_layers = 3 bottom_solid_layers = 4
bridge_acceleration = 1000 bridge_acceleration = 1000
bridge_angle = 0 bridge_angle = 0
bridge_flow_ratio = 0.95 bridge_flow_ratio = 0.95
@ -143,7 +148,7 @@ thin_walls = 0
threads = 4 threads = 4
top_infill_extrusion_width = 0.4 top_infill_extrusion_width = 0.4
top_solid_infill_speed = 30 top_solid_infill_speed = 30
top_solid_layers = 4 top_solid_layers = 5
travel_speed = 150 travel_speed = 150
wipe_tower = 0 wipe_tower = 0
wipe_tower_bridging = 10 wipe_tower_bridging = 10
@ -254,7 +259,6 @@ extra_loading_move = -2
extruder_colour = "" extruder_colour = ""
extruder_offset = 0x0 extruder_offset = 0x0
gcode_flavor = repetier gcode_flavor = repetier
host_type = octoprint
layer_gcode = ;AFTER_LAYER_CHANGE\nM117 layer [layer_num] at [layer_z]mm\n;[layer_z]\n layer_gcode = ;AFTER_LAYER_CHANGE\nM117 layer [layer_num] at [layer_z]mm\n;[layer_z]\n
machine_max_acceleration_e = 10000,5000 machine_max_acceleration_e = 10000,5000
machine_max_acceleration_extruding = 1500,1250 machine_max_acceleration_extruding = 1500,1250
@ -277,14 +281,11 @@ max_print_height = 320
min_layer_height = 0.15 min_layer_height = 0.15
nozzle_diameter = 0.4 nozzle_diameter = 0.4
parking_pos_retraction = 92 parking_pos_retraction = 92
print_host =
printer_model = printer_model =
printer_notes = TRILAB printer_notes = TRILAB
printer_settings_id = printer_settings_id =
printer_variant = printer_variant =
printer_vendor = printer_vendor =
printhost_apikey =
printhost_cafile =
remaining_times = 0 remaining_times = 0
retract_before_travel = 2 retract_before_travel = 2
retract_before_wipe = 100% retract_before_wipe = 100%
@ -297,8 +298,6 @@ retract_lift_below = 0
retract_restart_extra = 0 retract_restart_extra = 0
retract_restart_extra_toolchange = 0 retract_restart_extra_toolchange = 0
retract_speed = 33 retract_speed = 33
serial_port =
serial_speed = 250000
silent_mode = 1 silent_mode = 1
single_extruder_multi_material = 0 single_extruder_multi_material = 0
start_gcode = ;START\nM220 S100 ; Set feedmultiply back to 100percent\nG90 ; Absolute positioning\nM83 ; Relative extruder\nM107 ; Layer fan OFF\nM190 S[first_layer_bed_temperature] ; Set bed temperature and wait\nM104 S[first_layer_temperature] ; Set extruder temperature\nG28 ; Home all axes\nG33 ; auto leveling rutine\nG1 X-62 Y-108 Z0.3 F6000 ; Go to purge position start\nG92 E0 ; Zero extruder\nM109 S[first_layer_temperature] ; Set and wait - hotend temperature\nG3 X62 Y-108 I62 J108 E10 F200 ; Go ARC to purge end\nG92 E0 ; Zero extruder start_gcode = ;START\nM220 S100 ; Set feedmultiply back to 100percent\nG90 ; Absolute positioning\nM83 ; Relative extruder\nM107 ; Layer fan OFF\nM190 S[first_layer_bed_temperature] ; Set bed temperature and wait\nM104 S[first_layer_temperature] ; Set extruder temperature\nG28 ; Home all axes\nG33 ; auto leveling rutine\nG1 X-62 Y-108 Z0.3 F6000 ; Go to purge position start\nG92 E0 ; Zero extruder\nM109 S[first_layer_temperature] ; Set and wait - hotend temperature\nG3 X62 Y-108 I62 J108 E10 F200 ; Go ARC to purge end\nG92 E0 ; Zero extruder

View file

@ -9,8 +9,7 @@ const float EPSILON = 0.0001;
struct SlopeDetection struct SlopeDetection
{ {
bool actived; bool actived;
// x = yellow, y = red float normal_z;
vec2 z_range;
mat3 volume_world_normal_matrix; mat3 volume_world_normal_matrix;
}; };
@ -33,8 +32,7 @@ varying vec3 eye_normal;
vec3 slope_color() vec3 slope_color()
{ {
float gradient_range = slope.z_range.x - slope.z_range.y; return (world_normal_z > slope.normal_z - EPSILON) ? GREEN : RED;
return (world_normal_z > slope.z_range.x - EPSILON) ? GREEN : ((gradient_range == 0.0) ? RED : mix(RED, YELLOW, clamp((world_normal_z - slope.z_range.y) / gradient_range, 0.0, 1.0)));
} }
void main() void main()

View file

@ -29,8 +29,7 @@ struct PrintBoxDetection
struct SlopeDetection struct SlopeDetection
{ {
bool actived; bool actived;
// x = yellow, y = red float normal_z;
vec2 z_range;
mat3 volume_world_normal_matrix; mat3 volume_world_normal_matrix;
}; };

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.13)
project(PrusaSlicer-native) project(PrusaSlicer-native)
add_subdirectory(build-utils) add_subdirectory(build-utils)
@ -204,11 +204,11 @@ if (WIN32)
VERBATIM VERBATIM
) )
endif () endif ()
# This has to be a separate target due to the windows command line lenght limits # This has to be a separate target due to the windows command line lenght limits
add_custom_target(PrusaSlicerDllsCopy ALL DEPENDS PrusaSlicer) add_custom_target(PrusaSlicerDllsCopy ALL DEPENDS PrusaSlicer)
prusaslicer_copy_dlls(PrusaSlicerDllsCopy) prusaslicer_copy_dlls(PrusaSlicerDllsCopy)
else () else ()
if (APPLE) if (APPLE)
# On OSX, the name of the binary matches the name of the Application. # On OSX, the name of the binary matches the name of the Application.
@ -247,4 +247,7 @@ if (WIN32)
endif () endif ()
else () else ()
install(TARGETS PrusaSlicer RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") install(TARGETS PrusaSlicer RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
# Install the symlink for gcodeviewer
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink prusa-slicer prusa-gcodeviewer WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})")
endif () endif ()

View file

@ -45,23 +45,21 @@
#include "libslic3r/Format/OBJ.hpp" #include "libslic3r/Format/OBJ.hpp"
#include "libslic3r/Format/SL1.hpp" #include "libslic3r/Format/SL1.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/AppConfig.hpp" #include "libslic3r/Thread.hpp"
#include "PrusaSlicer.hpp" #include "PrusaSlicer.hpp"
#ifdef SLIC3R_GUI #ifdef SLIC3R_GUI
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_Init.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include "slic3r/GUI/InstanceCheck.hpp"
#include "slic3r/GUI/MainFrame.hpp"
#include "slic3r/GUI/Plater.hpp"
#endif /* SLIC3R_GUI */ #endif /* SLIC3R_GUI */
using namespace Slic3r; using namespace Slic3r;
int CLI::run(int argc, char **argv) int CLI::run(int argc, char **argv)
{ {
// Mark the main thread for the debugger and for runtime checks.
set_current_thread_name("slic3r_main");
#ifdef __WXGTK__ #ifdef __WXGTK__
// On Linux, wxGTK has no support for Wayland, and the app crashes on // On Linux, wxGTK has no support for Wayland, and the app crashes on
// startup if gtk3 is used. This env var has to be set explicitly to // startup if gtk3 is used. This env var has to be set explicitly to
@ -154,6 +152,15 @@ int CLI::run(int argc, char **argv)
// Read input file(s) if any. // Read input file(s) if any.
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
for (const std::string& file : m_input_files) {
std::string ext = boost::filesystem::path(file).extension().string();
if (ext == ".gcode" || ext == ".g") {
if (boost::filesystem::exists(file)) {
start_as_gcodeviewer = true;
break;
}
}
}
if (!start_as_gcodeviewer) { if (!start_as_gcodeviewer) {
#endif // ENABLE_GCODE_VIEWER #endif // ENABLE_GCODE_VIEWER
for (const std::string& file : m_input_files) { for (const std::string& file : m_input_files) {
@ -509,9 +516,12 @@ int CLI::run(int argc, char **argv)
outfile_final = sla_print.print_statistics().finalize_output_path(outfile); outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
sla_archive.export_print(outfile_final, sla_print); sla_archive.export_print(outfile_final, sla_print);
} }
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) { if (outfile != outfile_final) {
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl; if (Slic3r::rename_file(outfile, outfile_final)) {
return 1; boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
return 1;
}
outfile = outfile_final;
} }
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl; boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
@ -562,66 +572,20 @@ int CLI::run(int argc, char **argv)
if (start_gui) { if (start_gui) {
#ifdef SLIC3R_GUI #ifdef SLIC3R_GUI
// #ifdef USE_WX Slic3r::GUI::GUI_InitParams params;
#if ENABLE_GCODE_VIEWER params.argc = argc;
GUI::GUI_App* gui = new GUI::GUI_App(start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor); params.argv = argv;
#else params.load_configs = load_configs;
GUI::GUI_App *gui = new GUI::GUI_App(); params.extra_config = std::move(m_extra_config);
#endif // ENABLE_GCODE_VIEWER params.input_files = std::move(m_input_files);
params.start_as_gcodeviewer = start_as_gcodeviewer;
bool gui_single_instance_setting = gui->app_config->get("single_instance") == "1"; return Slic3r::GUI::GUI_Run(params);
if (Slic3r::instance_check(argc, argv, gui_single_instance_setting)) { #else // SLIC3R_GUI
//TODO: do we have delete gui and other stuff?
return -1;
}
// gui->autosave = m_config.opt_string("autosave");
GUI::GUI_App::SetInstance(gui);
#if ENABLE_GCODE_VIEWER
gui->CallAfter([gui, this, &load_configs, start_as_gcodeviewer] {
#else
gui->CallAfter([gui, this, &load_configs] {
#endif // ENABLE_GCODE_VIEWER
if (!gui->initialized()) {
return;
}
#if ENABLE_GCODE_VIEWER
if (start_as_gcodeviewer) {
if (!m_input_files.empty())
gui->plater()->load_gcode(wxString::FromUTF8(m_input_files[0].c_str()));
} else {
#endif // ENABLE_GCODE_VIEWER_AS
#if 0
// Load the cummulative config over the currently active profiles.
//FIXME if multiple configs are loaded, only the last one will have an effect.
// We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
// As of now only the full configs are supported here.
if (!m_print_config.empty())
gui->mainframe->load_config(m_print_config);
#endif
if (!load_configs.empty())
// Load the last config to give it a name at the UI. The name of the preset may be later
// changed by loading an AMF or 3MF.
//FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
gui->mainframe->load_config_file(load_configs.back());
// If loading a 3MF file, the config is loaded from the last one.
if (!m_input_files.empty())
gui->plater()->load_files(m_input_files, true, true);
if (!m_extra_config.empty())
gui->mainframe->load_config(m_extra_config);
#if ENABLE_GCODE_VIEWER
}
#endif // ENABLE_GCODE_VIEWER
});
int result = wxEntry(argc, argv);
return result;
#else /* SLIC3R_GUI */
// No GUI support. Just print out a help. // No GUI support. Just print out a help.
this->print_help(false); this->print_help(false);
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc). // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
return (argc == 0) ? 0 : 1; return (argc == 0) ? 0 : 1;
#endif /* SLIC3R_GUI */ #endif // SLIC3R_GUI
} }
return 0; return 0;
@ -646,7 +610,7 @@ bool CLI::setup(int argc, char **argv)
#ifdef __APPLE__ #ifdef __APPLE__
// The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r'
// The resources are packed to 'Slic3r.app/Contents/Resources' // The resources are packed to 'Slic3r.app/Contents/Resources'
boost::filesystem::path path_resources = path_to_binary.parent_path() / "../Resources"; boost::filesystem::path path_resources = boost::filesystem::canonical(path_to_binary).parent_path() / "../Resources";
#elif defined _WIN32 #elif defined _WIN32
// The application is packed in the .zip archive in the root, // The application is packed in the .zip archive in the root,
// The resources are packed to 'resources' // The resources are packed to 'resources'
@ -660,7 +624,7 @@ bool CLI::setup(int argc, char **argv)
// The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r', // The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r',
// The resources are packed to 'resources' // The resources are packed to 'resources'
// Path from Slic3r binary to resources: // Path from Slic3r binary to resources:
boost::filesystem::path path_resources = path_to_binary.parent_path() / "../resources"; boost::filesystem::path path_resources = boost::filesystem::canonical(path_to_binary).parent_path() / "../resources";
#endif #endif
set_resources_dir(path_resources.string()); set_resources_dir(path_resources.string());

View file

@ -28,7 +28,7 @@
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp> #include <boost/nowide/cstdio.hpp>
#include <boost/detail/endian.hpp> #include <boost/predef/other/endian.h>
#include "stl.h" #include "stl.h"
@ -36,9 +36,9 @@
#error "SEEK_SET not defined" #error "SEEK_SET not defined"
#endif #endif
#ifndef BOOST_LITTLE_ENDIAN #if BOOST_ENDIAN_BIG_BYTE
extern void stl_internal_reverse_quads(char *buf, size_t cnt); extern void stl_internal_reverse_quads(char *buf, size_t cnt);
#endif /* BOOST_LITTLE_ENDIAN */ #endif /* BOOST_ENDIAN_BIG_BYTE */
static FILE* stl_open_count_facets(stl_file *stl, const char *file) static FILE* stl_open_count_facets(stl_file *stl, const char *file)
{ {
@ -89,10 +89,10 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file)
// Read the int following the header. This should contain # of facets. // Read the int following the header. This should contain # of facets.
uint32_t header_num_facets; uint32_t header_num_facets;
bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0; bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0;
#ifndef BOOST_LITTLE_ENDIAN #if BOOST_ENDIAN_BIG_BYTE
// Convert from little endian to big endian. // Convert from little endian to big endian.
stl_internal_reverse_quads((char*)&header_num_facets, 4); stl_internal_reverse_quads((char*)&header_num_facets, 4);
#endif /* BOOST_LITTLE_ENDIAN */ #endif /* BOOST_ENDIAN_BIG_BYTE */
if (! header_num_faces_read || num_facets != header_num_facets) if (! header_num_faces_read || num_facets != header_num_facets)
BOOST_LOG_TRIVIAL(info) << "stl_open_count_facets: Warning: File size doesn't match number of facets in the header: " << file; BOOST_LOG_TRIVIAL(info) << "stl_open_count_facets: Warning: File size doesn't match number of facets in the header: " << file;
} }
@ -158,10 +158,10 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first)
// Read a single facet from a binary .STL file. We assume little-endian architecture! // Read a single facet from a binary .STL file. We assume little-endian architecture!
if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET) if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET)
return false; return false;
#ifndef BOOST_LITTLE_ENDIAN #if BOOST_ENDIAN_BIG_BYTE
// Convert the loaded little endian data to big endian. // Convert the loaded little endian data to big endian.
stl_internal_reverse_quads((char*)&facet, 48); stl_internal_reverse_quads((char*)&facet, 48);
#endif /* BOOST_LITTLE_ENDIAN */ #endif /* BOOST_ENDIAN_BIG_BYTE */
} else { } else {
// Read a single facet from an ASCII .STL file // Read a single facet from an ASCII .STL file
// skip solid/endsolid // skip solid/endsolid

View file

@ -42,10 +42,16 @@
#include <linux/hidraw.h> #include <linux/hidraw.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/input.h> #include <linux/input.h>
#include <libudev.h>
#include "hidapi.h" #include "hidapi.h"
// Declare udev structures needed in this module. They are passed by pointers
// to udev functions and not used directly.
struct udev_device;
struct udev_list_entry;
struct udev_enumerate;
struct udev;
typedef const char* (*hid_wrapper_udev_device_get_devnode_type)(struct udev_device *udev_device); typedef const char* (*hid_wrapper_udev_device_get_devnode_type)(struct udev_device *udev_device);
typedef struct udev_device* (*hid_wrapper_udev_device_get_parent_with_subsystem_devtype_type)(struct udev_device *udev_device, const char *subsystem, const char *devtype); typedef struct udev_device* (*hid_wrapper_udev_device_get_parent_with_subsystem_devtype_type)(struct udev_device *udev_device, const char *subsystem, const char *devtype);
typedef const char* (*hid_wrapper_udev_device_get_sysattr_value_type)(struct udev_device *udev_device, const char *sysattr); typedef const char* (*hid_wrapper_udev_device_get_sysattr_value_type)(struct udev_device *udev_device, const char *sysattr);

View file

@ -2,6 +2,7 @@
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#include "Exception.hpp" #include "Exception.hpp"
#include "Thread.hpp"
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -37,56 +38,89 @@ void AppConfig::reset()
// Override missing or keys with their defaults. // Override missing or keys with their defaults.
void AppConfig::set_defaults() void AppConfig::set_defaults()
{ {
// Reset the empty fields to defaults. #if ENABLE_GCODE_VIEWER
if (get("autocenter").empty()) if (m_mode == EAppMode::Editor) {
set("autocenter", "0"); #endif // ENABLE_GCODE_VIEWER
// Disable background processing by default as it is not stable. // Reset the empty fields to defaults.
if (get("background_processing").empty()) if (get("autocenter").empty())
set("background_processing", "0"); set("autocenter", "0");
// If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. // Disable background processing by default as it is not stable.
// By default, Prusa has the controller hidden. if (get("background_processing").empty())
if (get("no_controller").empty()) set("background_processing", "0");
set("no_controller", "1"); // If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
// If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available. // By default, Prusa has the controller hidden.
if (get("no_defaults").empty()) if (get("no_controller").empty())
set("no_defaults", "1"); set("no_controller", "1");
if (get("show_incompatible_presets").empty()) // If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available.
set("show_incompatible_presets", "0"); if (get("no_defaults").empty())
set("no_defaults", "1");
if (get("show_incompatible_presets").empty())
set("show_incompatible_presets", "0");
if (get("version_check").empty()) if (get("version_check").empty())
set("version_check", "1"); set("version_check", "1");
if (get("preset_update").empty()) if (get("preset_update").empty())
set("preset_update", "1"); set("preset_update", "1");
if (get("export_sources_full_pathnames").empty()) if (get("export_sources_full_pathnames").empty())
set("export_sources_full_pathnames", "0"); set("export_sources_full_pathnames", "0");
// remove old 'use_legacy_opengl' parameter from this config, if present // remove old 'use_legacy_opengl' parameter from this config, if present
if (!get("use_legacy_opengl").empty()) if (!get("use_legacy_opengl").empty())
erase("", "use_legacy_opengl"); erase("", "use_legacy_opengl");
#ifdef __APPLE__ #ifdef __APPLE__
if (get("use_retina_opengl").empty()) if (get("use_retina_opengl").empty())
set("use_retina_opengl", "1"); set("use_retina_opengl", "1");
#endif #endif
if (get("single_instance").empty()) if (get("single_instance").empty())
set("single_instance", "0"); set("single_instance",
#ifdef __APPLE__
"1"
#else // __APPLE__
"0"
#endif // __APPLE__
);
if (get("remember_output_path").empty()) if (get("remember_output_path").empty())
set("remember_output_path", "1"); set("remember_output_path", "1");
if (get("remember_output_path_removable").empty()) if (get("remember_output_path_removable").empty())
set("remember_output_path_removable", "1"); set("remember_output_path_removable", "1");
if (get("use_custom_toolbar_size").empty()) if (get("use_custom_toolbar_size").empty())
set("use_custom_toolbar_size", "0"); set("use_custom_toolbar_size", "0");
if (get("custom_toolbar_size").empty()) if (get("custom_toolbar_size").empty())
set("custom_toolbar_size", "100"); set("custom_toolbar_size", "100");
if (get("auto_toolbar_size").empty()) if (get("auto_toolbar_size").empty())
set("auto_toolbar_size", "100"); set("auto_toolbar_size", "100");
#if !ENABLE_GCODE_VIEWER
if (get("use_perspective_camera").empty())
set("use_perspective_camera", "1");
if (get("use_free_camera").empty())
set("use_free_camera", "0");
if (get("reverse_mouse_wheel_zoom").empty())
set("reverse_mouse_wheel_zoom", "0");
#endif // !ENABLE_GCODE_VIEWER
#if ENABLE_ENVIRONMENT_MAP
if (get("use_environment_map").empty())
set("use_environment_map", "0");
#endif // ENABLE_ENVIRONMENT_MAP
if (get("use_inches").empty())
set("use_inches", "0");
#if ENABLE_GCODE_VIEWER
}
if (get("seq_top_layer_only").empty())
set("seq_top_layer_only", "1");
if (get("use_perspective_camera").empty()) if (get("use_perspective_camera").empty())
set("use_perspective_camera", "1"); set("use_perspective_camera", "1");
@ -94,17 +128,19 @@ void AppConfig::set_defaults()
if (get("use_free_camera").empty()) if (get("use_free_camera").empty())
set("use_free_camera", "0"); set("use_free_camera", "0");
#if ENABLE_ENVIRONMENT_MAP if (get("reverse_mouse_wheel_zoom").empty())
if (get("use_environment_map").empty()) set("reverse_mouse_wheel_zoom", "0");
set("use_environment_map", "0"); #endif // ENABLE_GCODE_VIEWER
#endif // ENABLE_ENVIRONMENT_MAP
if (get("use_inches").empty())
set("use_inches", "0");
if (get("show_splash_screen").empty()) if (get("show_splash_screen").empty())
set("show_splash_screen", "1"); set("show_splash_screen", "1");
if (get("default_action_on_close_application").empty())
set("default_action_on_close_application", "none"); // , "discard" or "save"
if (get("default_action_on_select_preset").empty())
set("default_action_on_select_preset", "none"); // , "transfer", "discard" or "save"
// Remove legacy window positions/sizes // Remove legacy window positions/sizes
erase("", "main_frame_maximized"); erase("", "main_frame_maximized");
erase("", "main_frame_pos"); erase("", "main_frame_pos");
@ -175,6 +211,20 @@ std::string AppConfig::load()
m_legacy_datadir = ini_ver < Semver(1, 40, 0); m_legacy_datadir = ini_ver < Semver(1, 40, 0);
} }
// Legacy conversion
if (m_mode == EAppMode::Editor) {
// Convert [extras] "physical_printer" to [presets] "physical_printer",
// remove the [extras] section if it becomes empty.
if (auto it_section = m_storage.find("extras"); it_section != m_storage.end()) {
if (auto it_physical_printer = it_section->second.find("physical_printer"); it_physical_printer != it_section->second.end()) {
m_storage["presets"]["physical_printer"] = it_physical_printer->second;
it_section->second.erase(it_physical_printer);
}
if (it_section->second.empty())
m_storage.erase(it_section);
}
}
// Override missing or keys with their defaults. // Override missing or keys with their defaults.
this->set_defaults(); this->set_defaults();
m_dirty = false; m_dirty = false;
@ -183,10 +233,12 @@ std::string AppConfig::load()
void AppConfig::save() void AppConfig::save()
{ {
#if ENABLE_GCODE_VIEWER {
if (!m_save_enabled) // Returns "undefined" if the thread naming functionality is not supported by the operating system.
return; std::optional<std::string> current_thread_name = get_current_thread_name();
#endif // ENABLE_GCODE_VIEWER if (current_thread_name && *current_thread_name != "slic3r_main")
throw CriticalException("Calling AppConfig::save() from a worker thread!");
}
// The config is first written to a file with a PID suffix and then moved // The config is first written to a file with a PID suffix and then moved
// to avoid race conditions with multiple instances of Slic3r // to avoid race conditions with multiple instances of Slic3r
@ -195,7 +247,14 @@ void AppConfig::save()
boost::nowide::ofstream c; boost::nowide::ofstream c;
c.open(path_pid, std::ios::out | std::ios::trunc); c.open(path_pid, std::ios::out | std::ios::trunc);
#if ENABLE_GCODE_VIEWER
if (m_mode == EAppMode::Editor)
c << "# " << Slic3r::header_slic3r_generated() << std::endl;
else
c << "# " << Slic3r::header_gcodeviewer_generated() << std::endl;
#else
c << "# " << Slic3r::header_slic3r_generated() << std::endl; c << "# " << Slic3r::header_slic3r_generated() << std::endl;
#endif // ENABLE_GCODE_VIEWER
// Make sure the "no" category is written first. // Make sure the "no" category is written first.
for (const std::pair<std::string, std::string> &kvp : m_storage[""]) for (const std::pair<std::string, std::string> &kvp : m_storage[""])
c << kvp.first << " = " << kvp.second << std::endl; c << kvp.first << " = " << kvp.second << std::endl;
@ -389,13 +448,22 @@ void AppConfig::reset_selections()
it->second.erase("sla_print"); it->second.erase("sla_print");
it->second.erase("sla_material"); it->second.erase("sla_material");
it->second.erase("printer"); it->second.erase("printer");
it->second.erase("physical_printer");
m_dirty = true; m_dirty = true;
} }
} }
std::string AppConfig::config_path() std::string AppConfig::config_path()
{ {
return (boost::filesystem::path(Slic3r::data_dir()) / (SLIC3R_APP_KEY ".ini")).make_preferred().string(); #if ENABLE_GCODE_VIEWER
std::string path = (m_mode == EAppMode::Editor) ?
(boost::filesystem::path(Slic3r::data_dir()) / (SLIC3R_APP_KEY ".ini")).make_preferred().string() :
(boost::filesystem::path(Slic3r::data_dir()) / (GCODEVIEWER_APP_KEY ".ini")).make_preferred().string();
return path;
#else
return (boost::filesystem::path(Slic3r::data_dir()) / (SLIC3R_APP_KEY ".ini")).make_preferred().string();
#endif // ENABLE_GCODE_VIEWER
} }
std::string AppConfig::version_check_url() const std::string AppConfig::version_check_url() const
@ -406,7 +474,11 @@ std::string AppConfig::version_check_url() const
bool AppConfig::exists() bool AppConfig::exists()
{ {
#if ENABLE_GCODE_VIEWER
return boost::filesystem::exists(config_path());
#else
return boost::filesystem::exists(AppConfig::config_path()); return boost::filesystem::exists(AppConfig::config_path());
#endif // ENABLE_GCODE_VIEWER
} }
}; // namespace Slic3r }; // namespace Slic3r

View file

@ -15,11 +15,21 @@ namespace Slic3r {
class AppConfig class AppConfig
{ {
public: public:
#if ENABLE_GCODE_VIEWER
enum class EAppMode : unsigned char
{
Editor,
GCodeViewer
};
explicit AppConfig(EAppMode mode) :
#else
AppConfig() : AppConfig() :
#endif // ENABLE_GCODE_VIEWER
m_dirty(false), m_dirty(false),
m_orig_version(Semver::invalid()), m_orig_version(Semver::invalid()),
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
m_save_enabled(true), m_mode(mode),
#endif // ENABLE_GCODE_VIEWER #endif // ENABLE_GCODE_VIEWER
m_legacy_datadir(false) m_legacy_datadir(false)
{ {
@ -125,22 +135,30 @@ public:
void reset_selections(); void reset_selections();
// Get the default config path from Slic3r::data_dir(). // Get the default config path from Slic3r::data_dir().
#if ENABLE_GCODE_VIEWER
std::string config_path();
#else
static std::string config_path(); static std::string config_path();
#endif // ENABLE_GCODE_VIEWER
// Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating) // Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating)
bool legacy_datadir() const { return m_legacy_datadir; } bool legacy_datadir() const { return m_legacy_datadir; }
void set_legacy_datadir(bool value) { m_legacy_datadir = value; } void set_legacy_datadir(bool value) { m_legacy_datadir = value; }
// Get the Slic3r version check url. // Get the Slic3r version check url.
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file. // This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
std::string version_check_url() const; std::string version_check_url() const;
// Returns the original Slic3r version found in the ini file before it was overwritten // Returns the original Slic3r version found in the ini file before it was overwritten
// by the current version // by the current version
Semver orig_version() const { return m_orig_version; } Semver orig_version() const { return m_orig_version; }
// Does the config file exist? // Does the config file exist?
#if ENABLE_GCODE_VIEWER
bool exists();
#else
static bool exists(); static bool exists();
#endif // ENABLE_GCODE_VIEWER
std::vector<std::string> get_recent_projects() const; std::vector<std::string> get_recent_projects() const;
void set_recent_projects(const std::vector<std::string>& recent_projects); void set_recent_projects(const std::vector<std::string>& recent_projects);
@ -160,10 +178,6 @@ public:
bool get_mouse_device_swap_yz(const std::string& name, bool& swap) const bool get_mouse_device_swap_yz(const std::string& name, bool& swap) const
{ return get_3dmouse_device_numeric_value(name, "swap_yz", swap); } { return get_3dmouse_device_numeric_value(name, "swap_yz", swap); }
#if ENABLE_GCODE_VIEWER
void enable_save(bool enable) { m_save_enabled = enable; }
#endif // ENABLE_GCODE_VIEWER
static const std::string SECTION_FILAMENTS; static const std::string SECTION_FILAMENTS;
static const std::string SECTION_MATERIALS; static const std::string SECTION_MATERIALS;
@ -182,6 +196,10 @@ private:
return true; return true;
} }
#if ENABLE_GCODE_VIEWER
EAppMode m_mode { EAppMode::Editor };
#endif // ENABLE_GCODE_VIEWER
// Map of section, name -> value // Map of section, name -> value
std::map<std::string, std::map<std::string, std::string>> m_storage; std::map<std::string, std::map<std::string, std::string>> m_storage;
// Map of enabled vendors / models / variants // Map of enabled vendors / models / variants
@ -190,10 +208,6 @@ private:
bool m_dirty; bool m_dirty;
// Original version found in the ini file before it was overwritten // Original version found in the ini file before it was overwritten
Semver m_orig_version; Semver m_orig_version;
#if ENABLE_GCODE_VIEWER
// Whether or not calls to save() should take effect
bool m_save_enabled;
#endif // ENABLE_GCODE_VIEWER
// Whether the existing version is before system profiles & configuration updating // Whether the existing version is before system profiles & configuration updating
bool m_legacy_datadir; bool m_legacy_datadir;
}; };

View file

@ -1,5 +1,5 @@
project(libslic3r) project(libslic3r)
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 3.13)
include(PrecompiledHeader) include(PrecompiledHeader)
@ -62,8 +62,6 @@ add_library(libslic3r STATIC
Fill/FillRectilinear.hpp Fill/FillRectilinear.hpp
Fill/FillRectilinear2.cpp Fill/FillRectilinear2.cpp
Fill/FillRectilinear2.hpp Fill/FillRectilinear2.hpp
Fill/FillRectilinear3.cpp
Fill/FillRectilinear3.hpp
Flow.cpp Flow.cpp
Flow.hpp Flow.hpp
format.hpp format.hpp
@ -81,8 +79,6 @@ add_library(libslic3r STATIC
Format/STL.hpp Format/STL.hpp
Format/SL1.hpp Format/SL1.hpp
Format/SL1.cpp Format/SL1.cpp
GCode/Analyzer.cpp
GCode/Analyzer.hpp
GCode/ThumbnailData.cpp GCode/ThumbnailData.cpp
GCode/ThumbnailData.hpp GCode/ThumbnailData.hpp
GCode/CoolingBuffer.cpp GCode/CoolingBuffer.cpp
@ -111,8 +107,6 @@ add_library(libslic3r STATIC
GCodeReader.hpp GCodeReader.hpp
# GCodeSender.cpp # GCodeSender.cpp
# GCodeSender.hpp # GCodeSender.hpp
GCodeTimeEstimator.cpp
GCodeTimeEstimator.hpp
GCodeWriter.cpp GCodeWriter.cpp
GCodeWriter.hpp GCodeWriter.hpp
Geometry.cpp Geometry.cpp
@ -201,6 +195,8 @@ add_library(libslic3r STATIC
Utils.hpp Utils.hpp
Time.cpp Time.cpp
Time.hpp Time.hpp
Thread.cpp
Thread.hpp
TriangleSelector.cpp TriangleSelector.cpp
TriangleSelector.hpp TriangleSelector.hpp
MTUtils.hpp MTUtils.hpp

View file

@ -1414,6 +1414,8 @@ public:
bool multiline = false; bool multiline = false;
// For text input: If true, the GUI text box spans the complete page width. // For text input: If true, the GUI text box spans the complete page width.
bool full_width = false; bool full_width = false;
// For text input: If true, the GUI formats text as code (fixed-width)
bool is_code = false;
// Not editable. Currently only used for the display of the number of threads. // Not editable. Currently only used for the display of the number of threads.
bool readonly = false; bool readonly = false;
// Height of a multiline GUI text box. // Height of a multiline GUI text box.

View file

@ -19,6 +19,7 @@ SLIC3R_DERIVE_EXCEPTION(InvalidArgument, LogicError);
SLIC3R_DERIVE_EXCEPTION(OutOfRange, LogicError); SLIC3R_DERIVE_EXCEPTION(OutOfRange, LogicError);
SLIC3R_DERIVE_EXCEPTION(IOError, CriticalException); SLIC3R_DERIVE_EXCEPTION(IOError, CriticalException);
SLIC3R_DERIVE_EXCEPTION(FileIOError, IOError); SLIC3R_DERIVE_EXCEPTION(FileIOError, IOError);
SLIC3R_DERIVE_EXCEPTION(HostNetworkError, IOError);
// Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications. // Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications.
SLIC3R_DERIVE_EXCEPTION(SlicingError, Exception); SLIC3R_DERIVE_EXCEPTION(SlicingError, Exception);
#undef SLIC3R_DERIVE_EXCEPTION #undef SLIC3R_DERIVE_EXCEPTION

View file

@ -331,7 +331,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
return ""; return "";
} }
ExtrusionRole ExtrusionEntity::string_to_role(const std::string& role) ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role)
{ {
if (role == L("Perimeter")) if (role == L("Perimeter"))
return erPerimeter; return erPerimeter;

View file

@ -6,6 +6,7 @@
#include "Polyline.hpp" #include "Polyline.hpp"
#include <assert.h> #include <assert.h>
#include <string_view>
namespace Slic3r { namespace Slic3r {
@ -106,7 +107,7 @@ public:
virtual double total_volume() const = 0; virtual double total_volume() const = 0;
static std::string role_to_string(ExtrusionRole role); static std::string role_to_string(ExtrusionRole role);
static ExtrusionRole string_to_role(const std::string& role); static ExtrusionRole string_to_role(const std::string_view role);
}; };
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr; typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;

View file

@ -535,7 +535,7 @@ void Layer::make_ironing()
fill_params.density = 1.; fill_params.density = 1.;
// fill_params.dont_connect = true; // fill_params.dont_connect = true;
fill_params.dont_connect = false; fill_params.dont_connect = false;
fill_params.monotonous = true; fill_params.monotonic = true;
for (size_t i = 0; i < by_extruder.size(); ++ i) { for (size_t i = 0; i < by_extruder.size(); ++ i) {
// Find span of regions equivalent to the ironing operation. // Find span of regions equivalent to the ironing operation.
@ -579,7 +579,7 @@ void Layer::make_ironing()
// Save into layer. // Save into layer.
ExtrusionEntityCollection *eec = nullptr; ExtrusionEntityCollection *eec = nullptr;
ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection()); ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection());
// Don't sort the ironing infill lines as they are monotonously ordered. // Don't sort the ironing infill lines as they are monotonicly ordered.
eec->no_sort = true; eec->no_sort = true;
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, std::move(polylines), eec->entities, std::move(polylines),

View file

@ -228,7 +228,7 @@ static const std::array<Vec3d, 8> child_centers {
}; };
// Traversal order of octree children cells for three infill directions, // Traversal order of octree children cells for three infill directions,
// so that a single line will be discretized in a strictly monotonous order. // so that a single line will be discretized in a strictly monotonic order.
static constexpr std::array<std::array<int, 8>, 3> child_traversal_order { static constexpr std::array<std::array<int, 8>, 3> child_traversal_order {
std::array<int, 8>{ 2, 3, 0, 1, 6, 7, 4, 5 }, std::array<int, 8>{ 2, 3, 0, 1, 6, 7, 4, 5 },
std::array<int, 8>{ 4, 0, 6, 2, 5, 1, 7, 3 }, std::array<int, 8>{ 4, 0, 6, 2, 5, 1, 7, 3 },

View file

@ -15,7 +15,6 @@
#include "FillPlanePath.hpp" #include "FillPlanePath.hpp"
#include "FillRectilinear.hpp" #include "FillRectilinear.hpp"
#include "FillRectilinear2.hpp" #include "FillRectilinear2.hpp"
#include "FillRectilinear3.hpp"
#include "FillAdaptive.hpp" #include "FillAdaptive.hpp"
namespace Slic3r { namespace Slic3r {
@ -28,7 +27,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ip3DHoneycomb: return new Fill3DHoneycomb(); case ip3DHoneycomb: return new Fill3DHoneycomb();
case ipGyroid: return new FillGyroid(); case ipGyroid: return new FillGyroid();
case ipRectilinear: return new FillRectilinear2(); case ipRectilinear: return new FillRectilinear2();
case ipMonotonous: return new FillMonotonous(); case ipMonotonic: return new FillMonotonic();
case ipLine: return new FillLine(); case ipLine: return new FillLine();
case ipGrid: return new FillGrid2(); case ipGrid: return new FillGrid2();
case ipTriangles: return new FillTriangles(); case ipTriangles: return new FillTriangles();

View file

@ -43,8 +43,8 @@ struct FillParams
// Don't adjust spacing to fill the space evenly. // Don't adjust spacing to fill the space evenly.
bool dont_adjust { true }; bool dont_adjust { true };
// Monotonous infill - strictly left to right for better surface quality of top infills. // Monotonic infill - strictly left to right for better surface quality of top infills.
bool monotonous { false }; bool monotonic { false };
// For Honeycomb. // For Honeycomb.
// we were requested to complete each loop; // we were requested to complete each loop;

View file

@ -154,7 +154,9 @@ struct SegmentIntersection
// Vertical link, up. // Vertical link, up.
Up, Up,
// Vertical link, down. // Vertical link, down.
Down Down,
// Phony intersection point has no link.
Phony,
}; };
enum class LinkQuality : uint8_t { enum class LinkQuality : uint8_t {
@ -353,6 +355,25 @@ struct SegmentedIntersectionLine
std::vector<SegmentIntersection> intersections; std::vector<SegmentIntersection> intersections;
}; };
static SegmentIntersection phony_outer_intersection(SegmentIntersection::SegmentIntersectionType type, coord_t pos)
{
assert(type == SegmentIntersection::OUTER_LOW || type == SegmentIntersection::OUTER_HIGH);
SegmentIntersection out;
// Invalid contour & segment.
out.iContour = std::numeric_limits<size_t>::max();
out.iSegment = std::numeric_limits<size_t>::max();
out.pos_p = pos;
out.type = type;
// Invalid prev / next.
out.prev_on_contour = -1;
out.next_on_contour = -1;
out.prev_on_contour_type = SegmentIntersection::LinkType::Phony;
out.next_on_contour_type = SegmentIntersection::LinkType::Phony;
out.prev_on_contour_quality = SegmentIntersection::LinkQuality::Invalid;
out.next_on_contour_quality = SegmentIntersection::LinkQuality::Invalid;
return out;
}
// A container maintaining an expolygon with its inner offsetted polygon. // A container maintaining an expolygon with its inner offsetted polygon.
// The purpose of the inner offsetted polygon is to provide segments to connect the infill lines. // The purpose of the inner offsetted polygon is to provide segments to connect the infill lines.
struct ExPolygonWithOffset struct ExPolygonWithOffset
@ -889,6 +910,60 @@ static std::vector<SegmentedIntersectionLine> slice_region_by_vertical_lines(con
return segs; return segs;
} }
#ifndef NDEBUG
bool validate_segment_intersection_connectivity(const std::vector<SegmentedIntersectionLine> &segs)
{
// Validate the connectivity.
for (size_t i_vline = 0; i_vline + 1 < segs.size(); ++ i_vline) {
const SegmentedIntersectionLine &il_left = segs[i_vline];
const SegmentedIntersectionLine &il_right = segs[i_vline + 1];
for (const SegmentIntersection &it : il_left.intersections) {
if (it.has_right_horizontal()) {
const SegmentIntersection &it_right = il_right.intersections[it.right_horizontal()];
// For a right link there is a symmetric left link.
assert(it.iContour == it_right.iContour);
assert(it.type == it_right.type);
assert(it_right.has_left_horizontal());
assert(it_right.left_horizontal() == int(&it - il_left.intersections.data()));
}
}
for (const SegmentIntersection &it : il_right.intersections) {
if (it.has_left_horizontal()) {
const SegmentIntersection &it_left = il_left.intersections[it.left_horizontal()];
// For a right link there is a symmetric left link.
assert(it.iContour == it_left.iContour);
assert(it.type == it_left.type);
assert(it_left.has_right_horizontal());
assert(it_left.right_horizontal() == int(&it - il_right.intersections.data()));
}
}
}
for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) {
const SegmentedIntersectionLine &il = segs[i_vline];
for (const SegmentIntersection &it : il.intersections) {
auto i_it = int(&it - il.intersections.data());
if (it.has_left_vertical_up()) {
assert(il.intersections[it.left_vertical_up()].left_vertical_down() == i_it);
assert(il.intersections[it.left_vertical_up()].prev_on_contour_quality == it.prev_on_contour_quality);
}
if (it.has_left_vertical_down()) {
assert(il.intersections[it.left_vertical_down()].left_vertical_up() == i_it);
assert(il.intersections[it.left_vertical_down()].prev_on_contour_quality == it.prev_on_contour_quality);
}
if (it.has_right_vertical_up()) {
assert(il.intersections[it.right_vertical_up()].right_vertical_down() == i_it);
assert(il.intersections[it.right_vertical_up()].next_on_contour_quality == it.next_on_contour_quality);
}
if (it.has_right_vertical_down()) {
assert(il.intersections[it.right_vertical_down()].right_vertical_up() == i_it);
assert(il.intersections[it.right_vertical_down()].next_on_contour_quality == it.next_on_contour_quality);
}
}
}
return true;
}
#endif /* NDEBUG */
// Connect each contour / vertical line intersection point with another two contour / vertical line intersection points. // Connect each contour / vertical line intersection point with another two contour / vertical line intersection points.
// (fill in SegmentIntersection::{prev_on_contour, prev_on_contour_vertical, next_on_contour, next_on_contour_vertical}. // (fill in SegmentIntersection::{prev_on_contour, prev_on_contour_vertical, next_on_contour, next_on_contour_vertical}.
// These contour points are either on the same vertical line, or on the vertical line left / right to the current one. // These contour points are either on the same vertical line, or on the vertical line left / right to the current one.
@ -1055,55 +1130,104 @@ static void connect_segment_intersections_by_contours(
} }
} }
#ifndef NDEBUG assert(validate_segment_intersection_connectivity(segs));
// Validate the connectivity. }
for (size_t i_vline = 0; i_vline + 1 < segs.size(); ++ i_vline) {
const SegmentedIntersectionLine &il_left = segs[i_vline]; static void pinch_contours_insert_phony_outer_intersections(std::vector<SegmentedIntersectionLine> &segs)
const SegmentedIntersectionLine &il_right = segs[i_vline + 1]; {
for (const SegmentIntersection &it : il_left.intersections) { // Keep the vector outside the loops, so they will not be reallocated.
if (it.has_right_horizontal()) { // Where to insert new outer points.
const SegmentIntersection &it_right = il_right.intersections[it.right_horizontal()]; std::vector<size_t> insert_after;
// For a right link there is a symmetric left link. // Mapping of indices of current intersection line after inserting new outer points.
assert(it.iContour == it_right.iContour); std::vector<int32_t> map;
assert(it.type == it_right.type); std::vector<SegmentIntersection> temp_intersections;
assert(it_right.has_left_horizontal());
assert(it_right.left_horizontal() == int(&it - il_left.intersections.data())); for (size_t i_vline = 1; i_vline < segs.size(); ++ i_vline) {
SegmentedIntersectionLine &il = segs[i_vline];
assert(il.intersections.empty() || il.intersections.size() >= 2);
if (! il.intersections.empty()) {
assert(il.intersections.front().type == SegmentIntersection::OUTER_LOW);
assert(il.intersections.back().type == SegmentIntersection::OUTER_HIGH);
auto end = il.intersections.end() - 1;
insert_after.clear();
for (auto it = il.intersections.begin() + 1; it != end;) {
if (it->type == SegmentIntersection::OUTER_HIGH) {
++ it;
assert(it->type == SegmentIntersection::OUTER_LOW);
++ it;
} else {
auto lo = it;
assert(lo->type == SegmentIntersection::INNER_LOW);
auto hi = ++ it;
assert(hi->type == SegmentIntersection::INNER_HIGH);
auto lo2 = ++ it;
if (lo2->type == SegmentIntersection::INNER_LOW) {
// INNER_HIGH followed by INNER_LOW. The outer contour may have squeezed the inner contour into two separate loops.
// In that case one shall insert a phony OUTER_HIGH / OUTER_LOW pair.
int up = hi->vertical_up();
int dn = lo2->vertical_down();
#ifndef _NDEBUG
assert(up == -1 || up > 0);
assert(dn == -1 || dn >= 0);
assert((up == -1 && dn == -1) || (dn + 1 == up));
#endif // _NDEBUG
bool pinched = dn + 1 != up;
if (pinched) {
// hi is not connected with its inner contour to lo2.
// Insert a phony OUTER_HIGH / OUTER_LOW pair.
#if 0
static int pinch_idx = 0;
printf("Pinched %d\n", pinch_idx++);
#endif
insert_after.emplace_back(hi - il.intersections.begin());
}
}
}
} }
}
for (const SegmentIntersection &it : il_right.intersections) { if (! insert_after.empty()) {
if (it.has_left_horizontal()) { // Insert phony OUTER_HIGH / OUTER_LOW pairs, adjust indices pointing to intersection points on this contour.
const SegmentIntersection &it_left = il_left.intersections[it.left_horizontal()]; map.clear();
// For a right link there is a symmetric left link. {
assert(it.iContour == it_left.iContour); size_t i = 0;
assert(it.type == it_left.type); temp_intersections.clear();
assert(it_left.has_right_horizontal()); for (size_t idx_inset_after : insert_after) {
assert(it_left.right_horizontal() == int(&it - il_right.intersections.data())); for (; i <= idx_inset_after; ++ i) {
map.emplace_back(temp_intersections.size());
temp_intersections.emplace_back(il.intersections[i]);
}
coord_t pos = (temp_intersections.back().pos() + il.intersections[i].pos()) / 2;
temp_intersections.emplace_back(phony_outer_intersection(SegmentIntersection::OUTER_HIGH, pos));
temp_intersections.emplace_back(phony_outer_intersection(SegmentIntersection::OUTER_LOW, pos));
}
for (; i < il.intersections.size(); ++ i) {
map.emplace_back(temp_intersections.size());
temp_intersections.emplace_back(il.intersections[i]);
}
temp_intersections.swap(il.intersections);
}
// Reindex references on current intersection line.
for (SegmentIntersection &ip : il.intersections) {
if (ip.has_left_vertical())
ip.prev_on_contour = map[ip.prev_on_contour];
if (ip.has_right_vertical())
ip.next_on_contour = map[ip.next_on_contour];
}
// Reindex references on previous intersection line.
for (SegmentIntersection &ip : segs[i_vline - 1].intersections)
if (ip.has_right_horizontal())
ip.next_on_contour = map[ip.next_on_contour];
if (i_vline < segs.size()) {
// Reindex references on next intersection line.
for (SegmentIntersection &ip : segs[i_vline + 1].intersections)
if (ip.has_left_horizontal())
ip.prev_on_contour = map[ip.prev_on_contour];
}
} }
} }
} }
for (size_t i_vline = 0; i_vline < segs.size(); ++ i_vline) {
const SegmentedIntersectionLine &il = segs[i_vline]; assert(validate_segment_intersection_connectivity(segs));
for (const SegmentIntersection &it : il.intersections) {
auto i_it = int(&it - il.intersections.data());
if (it.has_left_vertical_up()) {
assert(il.intersections[it.left_vertical_up()].left_vertical_down() == i_it);
assert(il.intersections[it.left_vertical_up()].prev_on_contour_quality == it.prev_on_contour_quality);
}
if (it.has_left_vertical_down()) {
assert(il.intersections[it.left_vertical_down()].left_vertical_up() == i_it);
assert(il.intersections[it.left_vertical_down()].prev_on_contour_quality == it.prev_on_contour_quality);
}
if (it.has_right_vertical_up()) {
assert(il.intersections[it.right_vertical_up()].right_vertical_down() == i_it);
assert(il.intersections[it.right_vertical_up()].next_on_contour_quality == it.next_on_contour_quality);
}
if (it.has_right_vertical_down()) {
assert(il.intersections[it.right_vertical_down()].right_vertical_up() == i_it);
assert(il.intersections[it.right_vertical_down()].next_on_contour_quality == it.next_on_contour_quality);
}
}
}
#endif /* NDEBUG */
} }
// Find the last INNER_HIGH intersection starting with INNER_LOW, that is followed by OUTER_HIGH intersection. // Find the last INNER_HIGH intersection starting with INNER_LOW, that is followed by OUTER_HIGH intersection.
@ -1387,7 +1511,7 @@ static void traverse_graph_generate_polylines(
} }
} }
struct MonotonousRegion struct MonotonicRegion
{ {
struct Boundary { struct Boundary {
int vline; int vline;
@ -1412,13 +1536,13 @@ struct MonotonousRegion
#if NDEBUG #if NDEBUG
// Left regions are used to track whether all regions left to this one have already been printed. // Left regions are used to track whether all regions left to this one have already been printed.
boost::container::small_vector<MonotonousRegion*, 4> left_neighbors; boost::container::small_vector<MonotonicRegion*, 4> left_neighbors;
// Right regions are held to pick a next region to be extruded using the "Ant colony" heuristics. // Right regions are held to pick a next region to be extruded using the "Ant colony" heuristics.
boost::container::small_vector<MonotonousRegion*, 4> right_neighbors; boost::container::small_vector<MonotonicRegion*, 4> right_neighbors;
#else #else
// For debugging, use the normal vector as it is better supported by debug visualizers. // For debugging, use the normal vector as it is better supported by debug visualizers.
std::vector<MonotonousRegion*> left_neighbors; std::vector<MonotonicRegion*> left_neighbors;
std::vector<MonotonousRegion*> right_neighbors; std::vector<MonotonicRegion*> right_neighbors;
#endif #endif
}; };
@ -1429,9 +1553,9 @@ struct AntPath
float pheromone { 0 }; // <0, 1> float pheromone { 0 }; // <0, 1>
}; };
struct MonotonousRegionLink struct MonotonicRegionLink
{ {
MonotonousRegion *region; MonotonicRegion *region;
bool flipped; bool flipped;
// Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region // Distance of right side of this region to left side of the next region, if the "flipped" flag of this region and the next region
// is applied as defined. // is applied as defined.
@ -1447,7 +1571,7 @@ class AntPathMatrix
{ {
public: public:
AntPathMatrix( AntPathMatrix(
const std::vector<MonotonousRegion> &regions, const std::vector<MonotonicRegion> &regions,
const ExPolygonWithOffset &poly_with_offset, const ExPolygonWithOffset &poly_with_offset,
const std::vector<SegmentedIntersectionLine> &segs, const std::vector<SegmentedIntersectionLine> &segs,
const float initial_pheromone) : const float initial_pheromone) :
@ -1463,7 +1587,7 @@ public:
ap.pheromone = initial_pheromone; ap.pheromone = initial_pheromone;
} }
AntPath& operator()(const MonotonousRegion &region_from, bool flipped_from, const MonotonousRegion &region_to, bool flipped_to) AntPath& operator()(const MonotonicRegion &region_from, bool flipped_from, const MonotonicRegion &region_to, bool flipped_to)
{ {
int row = 2 * int(&region_from - m_regions.data()) + flipped_from; int row = 2 * int(&region_from - m_regions.data()) + flipped_from;
int col = 2 * int(&region_to - m_regions.data()) + flipped_to; int col = 2 * int(&region_to - m_regions.data()) + flipped_to;
@ -1490,16 +1614,16 @@ public:
return path; return path;
} }
AntPath& operator()(const MonotonousRegionLink &region_from, const MonotonousRegion &region_to, bool flipped_to) AntPath& operator()(const MonotonicRegionLink &region_from, const MonotonicRegion &region_to, bool flipped_to)
{ return (*this)(*region_from.region, region_from.flipped, region_to, flipped_to); } { return (*this)(*region_from.region, region_from.flipped, region_to, flipped_to); }
AntPath& operator()(const MonotonousRegion &region_from, bool flipped_from, const MonotonousRegionLink &region_to) AntPath& operator()(const MonotonicRegion &region_from, bool flipped_from, const MonotonicRegionLink &region_to)
{ return (*this)(region_from, flipped_from, *region_to.region, region_to.flipped); } { return (*this)(region_from, flipped_from, *region_to.region, region_to.flipped); }
AntPath& operator()(const MonotonousRegionLink &region_from, const MonotonousRegionLink &region_to) AntPath& operator()(const MonotonicRegionLink &region_from, const MonotonicRegionLink &region_to)
{ return (*this)(*region_from.region, region_from.flipped, *region_to.region, region_to.flipped); } { return (*this)(*region_from.region, region_from.flipped, *region_to.region, region_to.flipped); }
private: private:
// Source regions, used for addressing and updating m_matrix. // Source regions, used for addressing and updating m_matrix.
const std::vector<MonotonousRegion> &m_regions; const std::vector<MonotonicRegion> &m_regions;
// To calculate the intersection points and contour lengths. // To calculate the intersection points and contour lengths.
const ExPolygonWithOffset &m_poly_with_offset; const ExPolygonWithOffset &m_poly_with_offset;
const std::vector<SegmentedIntersectionLine> &m_segs; const std::vector<SegmentedIntersectionLine> &m_segs;
@ -1652,9 +1776,9 @@ static std::pair<SegmentIntersection*, SegmentIntersection*> right_overlap(std::
return start_end.first == nullptr ? start_end : right_overlap(*start_end.first, *start_end.second, vline_this, vline_right); return start_end.first == nullptr ? start_end : right_overlap(*start_end.first, *start_end.second, vline_this, vline_right);
} }
static std::vector<MonotonousRegion> generate_montonous_regions(std::vector<SegmentedIntersectionLine> &segs) static std::vector<MonotonicRegion> generate_montonous_regions(std::vector<SegmentedIntersectionLine> &segs)
{ {
std::vector<MonotonousRegion> monotonous_regions; std::vector<MonotonicRegion> monotonic_regions;
#ifndef NDEBUG #ifndef NDEBUG
#define SLIC3R_DEBUG_MONOTONOUS_REGIONS #define SLIC3R_DEBUG_MONOTONOUS_REGIONS
@ -1685,11 +1809,11 @@ static std::vector<MonotonousRegion> generate_montonous_regions(std::vector<Segm
SegmentIntersection *start = &vline_seed.intersections[i_intersection_seed]; SegmentIntersection *start = &vline_seed.intersections[i_intersection_seed];
SegmentIntersection *end = &end_of_vertical_run(vline_seed, *start); SegmentIntersection *end = &end_of_vertical_run(vline_seed, *start);
if (! start->consumed_vertical_up) { if (! start->consumed_vertical_up) {
// Draw a new monotonous region starting with this segment. // Draw a new monotonic region starting with this segment.
// while there is only a single right neighbor // while there is only a single right neighbor
int i_vline = i_vline_seed; int i_vline = i_vline_seed;
std::pair<SegmentIntersection*, SegmentIntersection*> left(start, end); std::pair<SegmentIntersection*, SegmentIntersection*> left(start, end);
MonotonousRegion region; MonotonicRegion region;
region.left.vline = i_vline; region.left.vline = i_vline;
region.left.low = int(left.first - vline_seed.intersections.data()); region.left.low = int(left.first - vline_seed.intersections.data());
region.left.high = int(left.second - vline_seed.intersections.data()); region.left.high = int(left.second - vline_seed.intersections.data());
@ -1722,19 +1846,19 @@ static std::vector<MonotonousRegion> generate_montonous_regions(std::vector<Segm
} }
// Even number of lines makes the infill zig-zag to exit on the other side of the region than where it starts. // Even number of lines makes the infill zig-zag to exit on the other side of the region than where it starts.
region.flips = (num_lines & 1) != 0; region.flips = (num_lines & 1) != 0;
monotonous_regions.emplace_back(region); monotonic_regions.emplace_back(region);
} }
i_intersection_seed = int(end - vline_seed.intersections.data()) + 1; i_intersection_seed = int(end - vline_seed.intersections.data()) + 1;
} }
} }
return monotonous_regions; return monotonic_regions;
} }
// Traverse path, calculate length of the draw for the purpose of optimization. // Traverse path, calculate length of the draw for the purpose of optimization.
// This function is very similar to polylines_from_paths() in the way how it traverses the path, but // This function is very similar to polylines_from_paths() in the way how it traverses the path, but
// polylines_from_paths() emits a path, while this function just calculates the path length. // polylines_from_paths() emits a path, while this function just calculates the path length.
static float montonous_region_path_length(const MonotonousRegion &region, bool dir, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs) static float montonous_region_path_length(const MonotonicRegion &region, bool dir, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs)
{ {
// From the initial point (i_vline, i_intersection), follow a path. // From the initial point (i_vline, i_intersection), follow a path.
int i_intersection = region.left_intersection_point(dir); int i_intersection = region.left_intersection_point(dir);
@ -1822,15 +1946,15 @@ static float montonous_region_path_length(const MonotonousRegion &region, bool d
return unscale<float>(total_length); return unscale<float>(total_length);
} }
static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, const ExPolygonWithOffset &poly_with_offset, std::vector<SegmentedIntersectionLine> &segs) static void connect_monotonic_regions(std::vector<MonotonicRegion> &regions, const ExPolygonWithOffset &poly_with_offset, std::vector<SegmentedIntersectionLine> &segs)
{ {
// Map from low intersection to left / right side of a monotonous region. // Map from low intersection to left / right side of a monotonic region.
using MapType = std::pair<SegmentIntersection*, MonotonousRegion*>; using MapType = std::pair<SegmentIntersection*, MonotonicRegion*>;
std::vector<MapType> map_intersection_to_region_start; std::vector<MapType> map_intersection_to_region_start;
std::vector<MapType> map_intersection_to_region_end; std::vector<MapType> map_intersection_to_region_end;
map_intersection_to_region_start.reserve(regions.size()); map_intersection_to_region_start.reserve(regions.size());
map_intersection_to_region_end.reserve(regions.size()); map_intersection_to_region_end.reserve(regions.size());
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
map_intersection_to_region_start.emplace_back(&segs[region.left.vline].intersections[region.left.low], &region); map_intersection_to_region_start.emplace_back(&segs[region.left.vline].intersections[region.left.low], &region);
map_intersection_to_region_end.emplace_back(&segs[region.right.vline].intersections[region.right.low], &region); map_intersection_to_region_end.emplace_back(&segs[region.right.vline].intersections[region.right.low], &region);
} }
@ -1840,7 +1964,7 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, c
std::sort(map_intersection_to_region_end.begin(), map_intersection_to_region_end.end(), intersections_lower); std::sort(map_intersection_to_region_end.begin(), map_intersection_to_region_end.end(), intersections_lower);
// Scatter links to neighboring regions. // Scatter links to neighboring regions.
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
if (region.left.vline > 0) { if (region.left.vline > 0) {
auto &vline = segs[region.left.vline]; auto &vline = segs[region.left.vline];
auto &vline_left = segs[region.left.vline - 1]; auto &vline_left = segs[region.left.vline - 1];
@ -1884,17 +2008,17 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, c
// Sometimes a segment may indicate that it connects to a segment on the other side while the other does not. // Sometimes a segment may indicate that it connects to a segment on the other side while the other does not.
// This may be a valid case if one side contains runs of OUTER_LOW, INNER_LOW, {INNER_HIGH, INNER_LOW}*, INNER_HIGH, OUTER_HIGH, // This may be a valid case if one side contains runs of OUTER_LOW, INNER_LOW, {INNER_HIGH, INNER_LOW}*, INNER_HIGH, OUTER_HIGH,
// where the part in the middle does not connect to the other side, but it will be extruded through. // where the part in the middle does not connect to the other side, but it will be extruded through.
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
std::sort(region.left_neighbors.begin(), region.left_neighbors.end()); std::sort(region.left_neighbors.begin(), region.left_neighbors.end());
std::sort(region.right_neighbors.begin(), region.right_neighbors.end()); std::sort(region.right_neighbors.begin(), region.right_neighbors.end());
} }
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
for (MonotonousRegion *neighbor : region.left_neighbors) { for (MonotonicRegion *neighbor : region.left_neighbors) {
auto it = std::lower_bound(neighbor->right_neighbors.begin(), neighbor->right_neighbors.end(), &region); auto it = std::lower_bound(neighbor->right_neighbors.begin(), neighbor->right_neighbors.end(), &region);
if (it == neighbor->right_neighbors.end() || *it != &region) if (it == neighbor->right_neighbors.end() || *it != &region)
neighbor->right_neighbors.insert(it, &region); neighbor->right_neighbors.insert(it, &region);
} }
for (MonotonousRegion *neighbor : region.right_neighbors) { for (MonotonicRegion *neighbor : region.right_neighbors) {
auto it = std::lower_bound(neighbor->left_neighbors.begin(), neighbor->left_neighbors.end(), &region); auto it = std::lower_bound(neighbor->left_neighbors.begin(), neighbor->left_neighbors.end(), &region);
if (it == neighbor->left_neighbors.end() || *it != &region) if (it == neighbor->left_neighbors.end() || *it != &region)
neighbor->left_neighbors.insert(it, &region); neighbor->left_neighbors.insert(it, &region);
@ -1903,12 +2027,12 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, c
#ifndef NDEBUG #ifndef NDEBUG
// Verify symmetry of the left_neighbors / right_neighbors. // Verify symmetry of the left_neighbors / right_neighbors.
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
for (MonotonousRegion *neighbor : region.left_neighbors) { for (MonotonicRegion *neighbor : region.left_neighbors) {
assert(std::count(region.left_neighbors.begin(), region.left_neighbors.end(), neighbor) == 1); assert(std::count(region.left_neighbors.begin(), region.left_neighbors.end(), neighbor) == 1);
assert(std::find(neighbor->right_neighbors.begin(), neighbor->right_neighbors.end(), &region) != neighbor->right_neighbors.end()); assert(std::find(neighbor->right_neighbors.begin(), neighbor->right_neighbors.end(), &region) != neighbor->right_neighbors.end());
} }
for (MonotonousRegion *neighbor : region.right_neighbors) { for (MonotonicRegion *neighbor : region.right_neighbors) {
assert(std::count(region.right_neighbors.begin(), region.right_neighbors.end(), neighbor) == 1); assert(std::count(region.right_neighbors.begin(), region.right_neighbors.end(), neighbor) == 1);
assert(std::find(neighbor->left_neighbors.begin(), neighbor->left_neighbors.end(), &region) != neighbor->left_neighbors.end()); assert(std::find(neighbor->left_neighbors.begin(), neighbor->left_neighbors.end(), &region) != neighbor->left_neighbors.end());
} }
@ -1916,7 +2040,7 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, c
#endif /* NDEBUG */ #endif /* NDEBUG */
// Fill in sum length of connecting lines of a region. This length is used for optimizing the infill path for minimum length. // Fill in sum length of connecting lines of a region. This length is used for optimizing the infill path for minimum length.
for (MonotonousRegion &region : regions) { for (MonotonicRegion &region : regions) {
region.len1 = montonous_region_path_length(region, false, poly_with_offset, segs); region.len1 = montonous_region_path_length(region, false, poly_with_offset, segs);
region.len2 = montonous_region_path_length(region, true, poly_with_offset, segs); region.len2 = montonous_region_path_length(region, true, poly_with_offset, segs);
// Subtract the smaller length from the longer one, so we will optimize just with the positive difference of the two. // Subtract the smaller length from the longer one, so we will optimize just with the positive difference of the two.
@ -1934,7 +2058,7 @@ static void connect_monotonous_regions(std::vector<MonotonousRegion> &regions, c
// https://www.chalmers.se/en/departments/math/research/research-groups/optimization/OptimizationMasterTheses/MScThesis-RaadSalman-final.pdf // https://www.chalmers.se/en/departments/math/research/research-groups/optimization/OptimizationMasterTheses/MScThesis-RaadSalman-final.pdf
// Algorithm 6.1 Lexicographic Path Preserving 3-opt // Algorithm 6.1 Lexicographic Path Preserving 3-opt
// Optimize path while maintaining the ordering constraints. // Optimize path while maintaining the ordering constraints.
void monotonous_3_opt(std::vector<MonotonousRegionLink> &path, const std::vector<SegmentedIntersectionLine> &segs) void monotonic_3_opt(std::vector<MonotonicRegionLink> &path, const std::vector<SegmentedIntersectionLine> &segs)
{ {
// When doing the 3-opt path preserving flips, one has to fulfill two constraints: // When doing the 3-opt path preserving flips, one has to fulfill two constraints:
// //
@ -1949,7 +2073,7 @@ void monotonous_3_opt(std::vector<MonotonousRegionLink> &path, const std::vector
// then the precedence constraint verification is amortized inside the O(n^3) loop. Now which is better for our task? // then the precedence constraint verification is amortized inside the O(n^3) loop. Now which is better for our task?
// //
// It is beneficial to also try flipping of the infill zig-zags, for which a prefix sum of both flipped and non-flipped paths over // It is beneficial to also try flipping of the infill zig-zags, for which a prefix sum of both flipped and non-flipped paths over
// MonotonousRegionLinks may be utilized, however updating the prefix sum has a linear complexity, the same complexity as doing the 3-opt // MonotonicRegionLinks may be utilized, however updating the prefix sum has a linear complexity, the same complexity as doing the 3-opt
// exchange by copying the pieces. // exchange by copying the pieces.
} }
@ -1962,17 +2086,17 @@ inline void print_ant(const std::string& fmt, TArgs&&... args) {
#endif #endif
} }
// Find a run through monotonous infill blocks using an 'Ant colony" optimization method. // Find a run through monotonic infill blocks using an 'Ant colony" optimization method.
// http://www.scholarpedia.org/article/Ant_colony_optimization // http://www.scholarpedia.org/article/Ant_colony_optimization
static std::vector<MonotonousRegionLink> chain_monotonous_regions( static std::vector<MonotonicRegionLink> chain_monotonic_regions(
std::vector<MonotonousRegion> &regions, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs, std::mt19937_64 &rng) std::vector<MonotonicRegion> &regions, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs, std::mt19937_64 &rng)
{ {
// Number of left neighbors (regions that this region depends on, this region cannot be printed before the regions left of it are printed) + self. // Number of left neighbors (regions that this region depends on, this region cannot be printed before the regions left of it are printed) + self.
std::vector<int32_t> left_neighbors_unprocessed(regions.size(), 1); std::vector<int32_t> left_neighbors_unprocessed(regions.size(), 1);
// Queue of regions, which have their left neighbors already printed. // Queue of regions, which have their left neighbors already printed.
std::vector<MonotonousRegion*> queue; std::vector<MonotonicRegion*> queue;
queue.reserve(regions.size()); queue.reserve(regions.size());
for (MonotonousRegion &region : regions) for (MonotonicRegion &region : regions)
if (region.left_neighbors.empty()) if (region.left_neighbors.empty())
queue.emplace_back(&region); queue.emplace_back(&region);
else else
@ -1981,13 +2105,13 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
auto left_neighbors_unprocessed_initial = left_neighbors_unprocessed; auto left_neighbors_unprocessed_initial = left_neighbors_unprocessed;
auto queue_initial = queue; auto queue_initial = queue;
std::vector<MonotonousRegionLink> path, best_path; std::vector<MonotonicRegionLink> path, best_path;
path.reserve(regions.size()); path.reserve(regions.size());
best_path.reserve(regions.size()); best_path.reserve(regions.size());
float best_path_length = std::numeric_limits<float>::max(); float best_path_length = std::numeric_limits<float>::max();
struct NextCandidate { struct NextCandidate {
MonotonousRegion *region; MonotonicRegion *region;
AntPath *link; AntPath *link;
AntPath *link_flipped; AntPath *link_flipped;
float probability; float probability;
@ -2002,22 +2126,22 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
[&regions, &left_neighbors_unprocessed, &path, &queue]() { [&regions, &left_neighbors_unprocessed, &path, &queue]() {
std::vector<unsigned char> regions_processed(regions.size(), false); std::vector<unsigned char> regions_processed(regions.size(), false);
std::vector<unsigned char> regions_in_queue(regions.size(), false); std::vector<unsigned char> regions_in_queue(regions.size(), false);
for (const MonotonousRegion *region : queue) { for (const MonotonicRegion *region : queue) {
// This region is not processed yet, his predecessors are processed. // This region is not processed yet, his predecessors are processed.
assert(left_neighbors_unprocessed[region - regions.data()] == 1); assert(left_neighbors_unprocessed[region - regions.data()] == 1);
regions_in_queue[region - regions.data()] = true; regions_in_queue[region - regions.data()] = true;
} }
for (const MonotonousRegionLink &link : path) { for (const MonotonicRegionLink &link : path) {
assert(left_neighbors_unprocessed[link.region - regions.data()] == 0); assert(left_neighbors_unprocessed[link.region - regions.data()] == 0);
regions_processed[link.region - regions.data()] = true; regions_processed[link.region - regions.data()] = true;
} }
for (size_t i = 0; i < regions_processed.size(); ++ i) { for (size_t i = 0; i < regions_processed.size(); ++ i) {
assert(! regions_processed[i] || ! regions_in_queue[i]); assert(! regions_processed[i] || ! regions_in_queue[i]);
const MonotonousRegion &region = regions[i]; const MonotonicRegion &region = regions[i];
if (regions_processed[i] || regions_in_queue[i]) { if (regions_processed[i] || regions_in_queue[i]) {
assert(left_neighbors_unprocessed[i] == (regions_in_queue[i] ? 1 : 0)); assert(left_neighbors_unprocessed[i] == (regions_in_queue[i] ? 1 : 0));
// All left neighbors should be processed already. // All left neighbors should be processed already.
for (const MonotonousRegion *left : region.left_neighbors) { for (const MonotonicRegion *left : region.left_neighbors) {
assert(regions_processed[left - regions.data()]); assert(regions_processed[left - regions.data()]);
assert(left_neighbors_unprocessed[left - regions.data()] == 0); assert(left_neighbors_unprocessed[left - regions.data()] == 0);
} }
@ -2026,7 +2150,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
assert(left_neighbors_unprocessed[i] > 1); assert(left_neighbors_unprocessed[i] > 1);
size_t num_predecessors_unprocessed = 0; size_t num_predecessors_unprocessed = 0;
bool has_left_last_on_path = false; bool has_left_last_on_path = false;
for (const MonotonousRegion* left : region.left_neighbors) { for (const MonotonicRegion* left : region.left_neighbors) {
size_t iprev = left - regions.data(); size_t iprev = left - regions.data();
if (regions_processed[iprev]) { if (regions_processed[iprev]) {
assert(left_neighbors_unprocessed[iprev] == 0); assert(left_neighbors_unprocessed[iprev] == 0);
@ -2058,7 +2182,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
// After how many rounds without an improvement to exit? // After how many rounds without an improvement to exit?
constexpr int num_rounds_no_change_exit = 8; constexpr int num_rounds_no_change_exit = 8;
// With how many ants each of the run will be performed? // With how many ants each of the run will be performed?
const int num_ants = std::min<int>(regions.size(), 10); const int num_ants = std::min(int(regions.size()), 10);
// Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found. // Base (initial) pheromone level. This value will be adjusted based on the length of the first greedy path found.
float pheromone_initial_deposit = 0.5f; float pheromone_initial_deposit = 0.5f;
// Evaporation rate of pheromones. // Evaporation rate of pheromones.
@ -2080,18 +2204,18 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
left_neighbors_unprocessed = left_neighbors_unprocessed_initial; left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
assert(validate_unprocessed()); assert(validate_unprocessed());
// Pick the last of the queue. // Pick the last of the queue.
MonotonousRegionLink path_end { queue.back(), false }; MonotonicRegionLink path_end { queue.back(), false };
queue.pop_back(); queue.pop_back();
-- left_neighbors_unprocessed[path_end.region - regions.data()]; -- left_neighbors_unprocessed[path_end.region - regions.data()];
float total_length = path_end.region->length(false); float total_length = path_end.region->length(false);
while (! queue.empty() || ! path_end.region->right_neighbors.empty()) { while (! queue.empty() || ! path_end.region->right_neighbors.empty()) {
// Chain. // Chain.
MonotonousRegion &region = *path_end.region; MonotonicRegion &region = *path_end.region;
bool dir = path_end.flipped; bool dir = path_end.flipped;
NextCandidate next_candidate; NextCandidate next_candidate;
next_candidate.probability = 0; next_candidate.probability = 0;
for (MonotonousRegion *next : region.right_neighbors) { for (MonotonicRegion *next : region.right_neighbors) {
int &unprocessed = left_neighbors_unprocessed[next - regions.data()]; int &unprocessed = left_neighbors_unprocessed[next - regions.data()];
assert(unprocessed > 1); assert(unprocessed > 1);
if (left_neighbors_unprocessed[next - regions.data()] == 2) { if (left_neighbors_unprocessed[next - regions.data()] == 2) {
@ -2106,7 +2230,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
} }
bool from_queue = next_candidate.probability == 0; bool from_queue = next_candidate.probability == 0;
if (from_queue) { if (from_queue) {
for (MonotonousRegion *next : queue) { for (MonotonicRegion *next : queue) {
AntPath &path1 = path_matrix(region, dir, *next, false); AntPath &path1 = path_matrix(region, dir, *next, false);
AntPath &path2 = path_matrix(region, dir, *next, true); AntPath &path2 = path_matrix(region, dir, *next, true);
if (path1.visibility > next_candidate.probability) if (path1.visibility > next_candidate.probability)
@ -2116,7 +2240,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
} }
} }
// Move the other right neighbors with satisified constraints to the queue. // Move the other right neighbors with satisified constraints to the queue.
for (MonotonousRegion *next : region.right_neighbors) for (MonotonicRegion *next : region.right_neighbors)
if (-- left_neighbors_unprocessed[next - regions.data()] == 1 && next_candidate.region != next) if (-- left_neighbors_unprocessed[next - regions.data()] == 1 && next_candidate.region != next)
queue.emplace_back(next); queue.emplace_back(next);
if (from_queue) { if (from_queue) {
@ -2127,7 +2251,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
queue.pop_back(); queue.pop_back();
} }
// Extend the path. // Extend the path.
MonotonousRegion *next_region = next_candidate.region; MonotonicRegion *next_region = next_candidate.region;
bool next_dir = next_candidate.dir; bool next_dir = next_candidate.dir;
total_length += next_region->length(next_dir) + path_matrix(*path_end.region, path_end.flipped, *next_region, next_dir).length; total_length += next_region->length(next_dir) + path_matrix(*path_end.region, path_end.flipped, *next_region, next_dir).length;
path_end = { next_region, next_dir }; path_end = { next_region, next_dir };
@ -2136,11 +2260,11 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
} }
// Set an initial pheromone value to 10% of the greedy path's value. // Set an initial pheromone value to 10% of the greedy path's value.
pheromone_initial_deposit = 0.1 / total_length; pheromone_initial_deposit = 0.1f / total_length;
path_matrix.update_inital_pheromone(pheromone_initial_deposit); path_matrix.update_inital_pheromone(pheromone_initial_deposit);
} }
// Probability (unnormalized) of traversing a link between two monotonous regions. // Probability (unnormalized) of traversing a link between two monotonic regions.
auto path_probability = [pheromone_alpha, pheromone_beta](AntPath &path) { auto path_probability = [pheromone_alpha, pheromone_beta](AntPath &path) {
return pow(path.pheromone, pheromone_alpha) * pow(path.visibility, pheromone_beta); return pow(path.pheromone, pheromone_alpha) * pow(path.visibility, pheromone_beta);
}; };
@ -2163,10 +2287,10 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
left_neighbors_unprocessed = left_neighbors_unprocessed_initial; left_neighbors_unprocessed = left_neighbors_unprocessed_initial;
assert(validate_unprocessed()); assert(validate_unprocessed());
// Pick randomly the first from the queue at random orientation. // Pick randomly the first from the queue at random orientation.
//FIXME picking the 1st monotonous region should likely be done based on accumulated pheromone level as well, //FIXME picking the 1st monotonic region should likely be done based on accumulated pheromone level as well,
// but the inefficiency caused by the random pick of the 1st monotonous region is likely insignificant. // but the inefficiency caused by the random pick of the 1st monotonic region is likely insignificant.
int first_idx = std::uniform_int_distribution<>(0, int(queue.size()) - 1)(rng); int first_idx = std::uniform_int_distribution<>(0, int(queue.size()) - 1)(rng);
path.emplace_back(MonotonousRegionLink{ queue[first_idx], rng() > rng.max() / 2 }); path.emplace_back(MonotonicRegionLink{ queue[first_idx], rng() > rng.max() / 2 });
*(queue.begin() + first_idx) = std::move(queue.back()); *(queue.begin() + first_idx) = std::move(queue.back());
queue.pop_back(); queue.pop_back();
-- left_neighbors_unprocessed[path.back().region - regions.data()]; -- left_neighbors_unprocessed[path.back().region - regions.data()];
@ -2182,12 +2306,12 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
while (! queue.empty() || ! path.back().region->right_neighbors.empty()) { while (! queue.empty() || ! path.back().region->right_neighbors.empty()) {
// Chain. // Chain.
MonotonousRegion &region = *path.back().region; MonotonicRegion &region = *path.back().region;
bool dir = path.back().flipped; bool dir = path.back().flipped;
// Sort by distance to pt. // Sort by distance to pt.
next_candidates.clear(); next_candidates.clear();
next_candidates.reserve(region.right_neighbors.size() * 2); next_candidates.reserve(region.right_neighbors.size() * 2);
for (MonotonousRegion *next : region.right_neighbors) { for (MonotonicRegion *next : region.right_neighbors) {
int &unprocessed = left_neighbors_unprocessed[next - regions.data()]; int &unprocessed = left_neighbors_unprocessed[next - regions.data()];
assert(unprocessed > 1); assert(unprocessed > 1);
if (-- unprocessed == 1) { if (-- unprocessed == 1) {
@ -2204,7 +2328,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
//FIXME add the queue items to the candidates? These are valid moves as well. //FIXME add the queue items to the candidates? These are valid moves as well.
if (num_direct_neighbors == 0) { if (num_direct_neighbors == 0) {
// Add the queue candidates. // Add the queue candidates.
for (MonotonousRegion *next : queue) { for (MonotonicRegion *next : queue) {
assert(left_neighbors_unprocessed[next - regions.data()] == 1); assert(left_neighbors_unprocessed[next - regions.data()] == 1);
AntPath &path1 = path_matrix(region, dir, *next, false); AntPath &path1 = path_matrix(region, dir, *next, false);
AntPath &path1_flipped = path_matrix(region, ! dir, *next, true); AntPath &path1_flipped = path_matrix(region, ! dir, *next, true);
@ -2247,11 +2371,11 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
queue.pop_back(); queue.pop_back();
} }
// Extend the path. // Extend the path.
MonotonousRegion *next_region = take_path->region; MonotonicRegion *next_region = take_path->region;
bool next_dir = take_path->dir; bool next_dir = take_path->dir;
path.back().next = take_path->link; path.back().next = take_path->link;
path.back().next_flipped = take_path->link_flipped; path.back().next_flipped = take_path->link_flipped;
path.emplace_back(MonotonousRegionLink{ next_region, next_dir }); path.emplace_back(MonotonicRegionLink{ next_region, next_dir });
assert(left_neighbors_unprocessed[next_region - regions.data()] == 1); assert(left_neighbors_unprocessed[next_region - regions.data()] == 1);
left_neighbors_unprocessed[next_region - regions.data()] = 0; left_neighbors_unprocessed[next_region - regions.data()] = 0;
print_ant("\tRegion (%1%:%2%,%3%) (%4%:%5%,%6%) length to prev %7%", print_ant("\tRegion (%1%:%2%,%3%) (%4%:%5%,%6%) length to prev %7%",
@ -2279,14 +2403,14 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
} }
// Perform 3-opt local optimization of the path. // Perform 3-opt local optimization of the path.
monotonous_3_opt(path, segs); monotonic_3_opt(path, segs);
// Measure path length. // Measure path length.
assert(! path.empty()); assert(! path.empty());
float path_length = std::accumulate(path.begin(), path.end() - 1, float path_length = std::accumulate(path.begin(), path.end() - 1,
path.back().region->length(path.back().flipped), path.back().region->length(path.back().flipped),
[&path_matrix](const float l, const MonotonousRegionLink &r) { [&path_matrix](const float l, const MonotonicRegionLink &r) {
const MonotonousRegionLink &next = *(&r + 1); const MonotonicRegionLink &next = *(&r + 1);
return l + r.region->length(r.flipped) + path_matrix(*r.region, r.flipped, *next.region, next.flipped).length; return l + r.region->length(r.flipped) + path_matrix(*r.region, r.flipped, *next.region, next.flipped).length;
}); });
// Save the shortest path. // Save the shortest path.
@ -2309,7 +2433,7 @@ static std::vector<MonotonousRegionLink> chain_monotonous_regions(
// Reinforce the path pheromones with the best path. // Reinforce the path pheromones with the best path.
float total_cost = best_path_length + float(EPSILON); float total_cost = best_path_length + float(EPSILON);
for (size_t i = 0; i + 1 < path.size(); ++ i) { for (size_t i = 0; i + 1 < path.size(); ++ i) {
MonotonousRegionLink &link = path[i]; MonotonicRegionLink &link = path[i];
link.next->pheromone = (1.f - pheromone_evaporation) * link.next->pheromone + pheromone_evaporation / total_cost; link.next->pheromone = (1.f - pheromone_evaporation) * link.next->pheromone + pheromone_evaporation / total_cost;
} }
@ -2324,7 +2448,7 @@ end:
} }
// Traverse path, produce polylines. // Traverse path, produce polylines.
static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs, Polylines &polylines_out) static void polylines_from_paths(const std::vector<MonotonicRegionLink> &path, const ExPolygonWithOffset &poly_with_offset, const std::vector<SegmentedIntersectionLine> &segs, Polylines &polylines_out)
{ {
Polyline *polyline = nullptr; Polyline *polyline = nullptr;
auto finish_polyline = [&polyline, &polylines_out]() { auto finish_polyline = [&polyline, &polylines_out]() {
@ -2334,14 +2458,26 @@ static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path,
// Handle nearly zero length edges. // Handle nearly zero length edges.
if (polyline->points.size() <= 1 || if (polyline->points.size() <= 1 ||
(polyline->points.size() == 2 && (polyline->points.size() == 2 &&
std::abs(polyline->points.front()(0) - polyline->points.back()(0)) < SCALED_EPSILON && std::abs(polyline->points.front().x() - polyline->points.back().x()) < SCALED_EPSILON &&
std::abs(polyline->points.front()(1) - polyline->points.back()(1)) < SCALED_EPSILON)) std::abs(polyline->points.front().y() - polyline->points.back().y()) < SCALED_EPSILON))
polylines_out.pop_back(); polylines_out.pop_back();
else if (polylines_out.size() >= 2) {
assert(polyline->points.size() >= 2);
// Merge the two last polylines. An extrusion may have been split by an introduction of phony outer points on intersection lines
// to cope with pinching of inner offset contours.
Polyline &pl_prev = polylines_out[polylines_out.size() - 2];
if (std::abs(polyline->points.front().x() - pl_prev.points.back().x()) < SCALED_EPSILON &&
std::abs(polyline->points.front().y() - pl_prev.points.back().y()) < SCALED_EPSILON) {
pl_prev.points.back() = (pl_prev.points.back() + polyline->points.front()) / 2;
pl_prev.points.insert(pl_prev.points.end(), polyline->points.begin() + 1, polyline->points.end());
polylines_out.pop_back();
}
}
polyline = nullptr; polyline = nullptr;
}; };
for (const MonotonousRegionLink &path_segment : path) { for (const MonotonicRegionLink &path_segment : path) {
MonotonousRegion &region = *path_segment.region; MonotonicRegion &region = *path_segment.region;
bool dir = path_segment.flipped; bool dir = path_segment.flipped;
// From the initial point (i_vline, i_intersection), follow a path. // From the initial point (i_vline, i_intersection), follow a path.
@ -2350,8 +2486,8 @@ static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path,
if (polyline != nullptr && &path_segment != path.data()) { if (polyline != nullptr && &path_segment != path.data()) {
// Connect previous path segment with the new one. // Connect previous path segment with the new one.
const MonotonousRegionLink &path_segment_prev = *(&path_segment - 1); const MonotonicRegionLink &path_segment_prev = *(&path_segment - 1);
const MonotonousRegion &region_prev = *path_segment_prev.region; const MonotonicRegion &region_prev = *path_segment_prev.region;
bool dir_prev = path_segment_prev.flipped; bool dir_prev = path_segment_prev.flipped;
int i_vline_prev = region_prev.right.vline; int i_vline_prev = region_prev.right.vline;
const SegmentedIntersectionLine &vline_prev = segs[i_vline_prev]; const SegmentedIntersectionLine &vline_prev = segs[i_vline_prev];
@ -2456,7 +2592,7 @@ static void polylines_from_paths(const std::vector<MonotonousRegionLink> &path,
if (polyline != nullptr) { if (polyline != nullptr) {
// Finish the current vertical line, // Finish the current vertical line,
const MonotonousRegion &region = *path.back().region; const MonotonicRegion &region = *path.back().region;
const SegmentedIntersectionLine &vline = segs[region.right.vline]; const SegmentedIntersectionLine &vline = segs[region.right.vline];
const SegmentIntersection *ip = &vline.intersections[region.right_intersection_point(path.back().flipped)]; const SegmentIntersection *ip = &vline.intersections[region.right_intersection_point(path.back().flipped)];
assert(ip->is_inner()); assert(ip->is_inner());
@ -2489,7 +2625,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
surface->expolygon, surface->expolygon,
- rotate_vector.first, - rotate_vector.first,
float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)), float(scale_(this->overlap - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
float(scale_(this->overlap - 0.5 * this->spacing))); float(scale_(this->overlap - 0.5f * this->spacing)));
if (poly_with_offset.n_contours_inner == 0) { if (poly_with_offset.n_contours_inner == 0) {
// Not a single infill line fits. // Not a single infill line fits.
//FIXME maybe one shall trigger the gap fill here? //FIXME maybe one shall trigger the gap fill here?
@ -2558,14 +2694,18 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
svg.Close(); svg.Close();
#endif /* SLIC3R_DEBUG */ #endif /* SLIC3R_DEBUG */
//FIXME this is a hack to get the monotonous infill rolling. We likely want a smarter switch, likely based on user decison. //FIXME this is a hack to get the monotonic infill rolling. We likely want a smarter switch, likely based on user decison.
bool monotonous_infill = params.monotonous; // || params.density > 0.99; bool monotonic_infill = params.monotonic; // || params.density > 0.99;
if (monotonous_infill) { if (monotonic_infill) {
std::vector<MonotonousRegion> regions = generate_montonous_regions(segs); // Sometimes the outer contour pinches the inner contour from both sides along a single vertical line.
connect_monotonous_regions(regions, poly_with_offset, segs); // This situation is not handled correctly by generate_montonous_regions().
// Insert phony OUTER_HIGH / OUTER_LOW pairs at the position where the contour is pinched.
pinch_contours_insert_phony_outer_intersections(segs);
std::vector<MonotonicRegion> regions = generate_montonous_regions(segs);
connect_monotonic_regions(regions, poly_with_offset, segs);
if (! regions.empty()) { if (! regions.empty()) {
std::mt19937_64 rng; std::mt19937_64 rng;
std::vector<MonotonousRegionLink> path = chain_monotonous_regions(regions, poly_with_offset, segs, rng); std::vector<MonotonicRegionLink> path = chain_monotonic_regions(regions, poly_with_offset, segs, rng);
polylines_from_paths(path, poly_with_offset, segs, polylines_out); polylines_from_paths(path, poly_with_offset, segs, polylines_out);
} }
} else } else
@ -2616,13 +2756,13 @@ Polylines FillRectilinear2::fill_surface(const Surface *surface, const FillParam
return polylines_out; return polylines_out;
} }
Polylines FillMonotonous::fill_surface(const Surface *surface, const FillParams &params) Polylines FillMonotonic::fill_surface(const Surface *surface, const FillParams &params)
{ {
FillParams params2 = params; FillParams params2 = params;
params2.monotonous = true; params2.monotonic = true;
Polylines polylines_out; Polylines polylines_out;
if (! fill_surface_by_lines(surface, params2, 0.f, 0.f, polylines_out)) { if (! fill_surface_by_lines(surface, params2, 0.f, 0.f, polylines_out)) {
printf("FillMonotonous::fill_surface() failed to fill a region.\n"); printf("FillMonotonic::fill_surface() failed to fill a region.\n");
} }
return polylines_out; return polylines_out;
} }

View file

@ -20,11 +20,11 @@ protected:
bool fill_surface_by_lines(const Surface *surface, const FillParams &params, float angleBase, float pattern_shift, Polylines &polylines_out); bool fill_surface_by_lines(const Surface *surface, const FillParams &params, float angleBase, float pattern_shift, Polylines &polylines_out);
}; };
class FillMonotonous : public FillRectilinear2 class FillMonotonic : public FillRectilinear2
{ {
public: public:
virtual Fill* clone() const { return new FillMonotonous(*this); }; virtual Fill* clone() const { return new FillMonotonic(*this); };
virtual ~FillMonotonous() = default; virtual ~FillMonotonic() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params); virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual bool no_sort() const { return true; } virtual bool no_sort() const { return true; }
}; };

File diff suppressed because it is too large Load diff

View file

@ -1,83 +0,0 @@
#ifndef slic3r_FillRectilinear3_hpp_
#define slic3r_FillRectilinear3_hpp_
#include "../libslic3r.h"
#include "FillBase.hpp"
namespace Slic3r {
class Surface;
class FillRectilinear3 : public Fill
{
public:
virtual Fill* clone() const { return new FillRectilinear3(*this); };
virtual ~FillRectilinear3() {}
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
struct FillDirParams
{
FillDirParams(coordf_t spacing, double angle, coordf_t pattern_shift = 0.f) :
spacing(spacing), angle(angle), pattern_shift(pattern_shift) {}
coordf_t spacing;
double angle;
coordf_t pattern_shift;
};
protected:
bool fill_surface_by_lines(const Surface *surface, const FillParams &params, std::vector<FillDirParams> &fill_dir_params, Polylines &polylines_out);
};
class FillGrid3 : public FillRectilinear3
{
public:
virtual Fill* clone() const { return new FillGrid3(*this); };
virtual ~FillGrid3() {}
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
};
class FillTriangles3 : public FillRectilinear3
{
public:
virtual Fill* clone() const { return new FillTriangles3(*this); };
virtual ~FillTriangles3() {}
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
};
class FillStars3 : public FillRectilinear3
{
public:
virtual Fill* clone() const { return new FillStars3(*this); };
virtual ~FillStars3() {}
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
};
class FillCubic3 : public FillRectilinear3
{
public:
virtual Fill* clone() const { return new FillCubic3(*this); };
virtual ~FillCubic3() {}
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
protected:
// The grid fill will keep the angle constant between the layers, see the implementation of Slic3r::Fill.
virtual float _layer_angle(size_t /* idx */) const { return 0.f; }
};
}; // namespace Slic3r
#endif // slic3r_FillRectilinear3_hpp_

View file

@ -1899,9 +1899,9 @@ namespace Slic3r {
assert(index < geometry.custom_supports.size()); assert(index < geometry.custom_supports.size());
assert(index < geometry.custom_seam.size()); assert(index < geometry.custom_seam.size());
if (! geometry.custom_supports[index].empty()) if (! geometry.custom_supports[index].empty())
volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]); volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
if (! geometry.custom_seam[index].empty()) if (! geometry.custom_seam[index].empty())
volume->m_seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]); volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
} }
@ -2417,11 +2417,11 @@ namespace Slic3r {
stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" "; stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" ";
} }
std::string custom_supports_data_string = volume->m_supported_facets.get_triangle_as_string(i); std::string custom_supports_data_string = volume->supported_facets.get_triangle_as_string(i);
if (! custom_supports_data_string.empty()) if (! custom_supports_data_string.empty())
stream << CUSTOM_SUPPORTS_ATTR << "=\"" << custom_supports_data_string << "\" "; stream << CUSTOM_SUPPORTS_ATTR << "=\"" << custom_supports_data_string << "\" ";
std::string custom_seam_data_string = volume->m_seam_facets.get_triangle_as_string(i); std::string custom_seam_data_string = volume->seam_facets.get_triangle_as_string(i);
if (! custom_seam_data_string.empty()) if (! custom_seam_data_string.empty())
stream << CUSTOM_SEAM_ATTR << "=\"" << custom_seam_data_string << "\" "; stream << CUSTOM_SEAM_ATTR << "=\"" << custom_seam_data_string << "\" ";

View file

@ -383,6 +383,7 @@ void fill_slicerconf(ConfMap &m, const SLAPrint &print)
static constexpr auto banned_keys = { static constexpr auto banned_keys = {
"compatible_printers"sv, "compatible_printers"sv,
"compatible_prints"sv, "compatible_prints"sv,
//FIXME The print host keys should not be exported to full_print_config anymore. The following keys may likely be removed.
"print_host"sv, "print_host"sv,
"printhost_apikey"sv, "printhost_apikey"sv,
"printhost_cafile"sv "printhost_cafile"sv

View file

@ -158,7 +158,7 @@ namespace Slic3r {
polygons_per_layer[i * 2] = union_(polys); polygons_per_layer[i * 2] = union_(polys);
} }
}); });
for (size_t i = 0; i < cnt / 2; ++i) for (size_t i = 1; i < cnt / 2; ++i)
polygons_per_layer[i] = std::move(polygons_per_layer[i * 2]); polygons_per_layer[i] = std::move(polygons_per_layer[i * 2]);
if (cnt & 1) if (cnt & 1)
polygons_per_layer[cnt / 2] = std::move(polygons_per_layer[cnt - 1]); polygons_per_layer[cnt / 2] = std::move(polygons_per_layer[cnt - 1]);
@ -819,48 +819,54 @@ namespace DoExport {
// this->print_machine_envelope(file, print); // this->print_machine_envelope(file, print);
// shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor. // shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor.
if (config.gcode_flavor.value == gcfMarlin) { if (config.gcode_flavor.value == gcfMarlin) {
normal_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values[0]); if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
normal_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values[0]); normal_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values[0]);
normal_time_estimator.set_minimum_feedrate((float)config.machine_min_extruding_rate.values[0]); normal_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values[0]);
normal_time_estimator.set_minimum_travel_feedrate((float)config.machine_min_travel_rate.values[0]); normal_time_estimator.set_minimum_feedrate((float)config.machine_min_extruding_rate.values[0]);
normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)config.machine_max_acceleration_x.values[0]); normal_time_estimator.set_minimum_travel_feedrate((float)config.machine_min_travel_rate.values[0]);
normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)config.machine_max_acceleration_y.values[0]); normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)config.machine_max_acceleration_x.values[0]);
normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)config.machine_max_acceleration_z.values[0]); normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)config.machine_max_acceleration_y.values[0]);
normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)config.machine_max_acceleration_e.values[0]); normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)config.machine_max_acceleration_z.values[0]);
normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)config.machine_max_feedrate_x.values[0]); normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)config.machine_max_acceleration_e.values[0]);
normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)config.machine_max_feedrate_y.values[0]); normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)config.machine_max_feedrate_x.values[0]);
normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)config.machine_max_feedrate_z.values[0]); normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)config.machine_max_feedrate_y.values[0]);
normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)config.machine_max_feedrate_e.values[0]); normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)config.machine_max_feedrate_z.values[0]);
normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)config.machine_max_jerk_x.values[0]); normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)config.machine_max_feedrate_e.values[0]);
normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)config.machine_max_jerk_y.values[0]); normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)config.machine_max_jerk_x.values[0]);
normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)config.machine_max_jerk_z.values[0]); normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)config.machine_max_jerk_y.values[0]);
normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)config.machine_max_jerk_e.values[0]); normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)config.machine_max_jerk_z.values[0]);
normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)config.machine_max_jerk_e.values[0]);
}
if (silent_time_estimator_enabled) if (silent_time_estimator_enabled)
{ {
silent_time_estimator.reset(); silent_time_estimator.reset();
silent_time_estimator.set_dialect(config.gcode_flavor); silent_time_estimator.set_dialect(config.gcode_flavor);
silent_time_estimator.set_extrusion_axis(config.get_extrusion_axis()[0]); silent_time_estimator.set_extrusion_axis(config.get_extrusion_axis()[0]);
/* "Stealth mode" values can be just a copy of "normal mode" values
* (when they aren't input for a printer preset). if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
* Thus, use back value from values, instead of second one, which could be absent /* "Stealth mode" values can be just a copy of "normal mode" values
*/ * (when they aren't input for a printer preset).
silent_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values.back()); * Thus, use back value from values, instead of second one, which could be absent
silent_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values.back()); */
silent_time_estimator.set_minimum_feedrate((float)config.machine_min_extruding_rate.values.back()); silent_time_estimator.set_max_acceleration((float)config.machine_max_acceleration_extruding.values.back());
silent_time_estimator.set_minimum_travel_feedrate((float)config.machine_min_travel_rate.values.back()); silent_time_estimator.set_retract_acceleration((float)config.machine_max_acceleration_retracting.values.back());
silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)config.machine_max_acceleration_x.values.back()); silent_time_estimator.set_minimum_feedrate((float)config.machine_min_extruding_rate.values.back());
silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)config.machine_max_acceleration_y.values.back()); silent_time_estimator.set_minimum_travel_feedrate((float)config.machine_min_travel_rate.values.back());
silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)config.machine_max_acceleration_z.values.back()); silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)config.machine_max_acceleration_x.values.back());
silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)config.machine_max_acceleration_e.values.back()); silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)config.machine_max_acceleration_y.values.back());
silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)config.machine_max_feedrate_x.values.back()); silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)config.machine_max_acceleration_z.values.back());
silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)config.machine_max_feedrate_y.values.back()); silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)config.machine_max_acceleration_e.values.back());
silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)config.machine_max_feedrate_z.values.back()); silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)config.machine_max_feedrate_x.values.back());
silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)config.machine_max_feedrate_e.values.back()); silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)config.machine_max_feedrate_y.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)config.machine_max_jerk_x.values.back()); silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)config.machine_max_feedrate_z.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)config.machine_max_jerk_y.values.back()); silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)config.machine_max_feedrate_e.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)config.machine_max_jerk_z.values.back()); silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)config.machine_max_jerk_x.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)config.machine_max_jerk_e.values.back()); silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)config.machine_max_jerk_y.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)config.machine_max_jerk_z.values.back());
silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)config.machine_max_jerk_e.values.back());
}
if (config.single_extruder_multi_material) { if (config.single_extruder_multi_material) {
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
// are considered to be active for the single extruder multi-material printers only. // are considered to be active for the single extruder multi-material printers only.
@ -1082,14 +1088,14 @@ namespace DoExport {
++ dst.second; ++ dst.second;
}; };
print_statistics.filament_stats.insert(std::pair<size_t, float>{extruder.id(), (float)used_filament}); print_statistics.filament_stats.insert(std::pair<size_t, float>{extruder.id(), (float)used_filament});
append(out_filament_used_mm, "%.1lf", used_filament); append(out_filament_used_mm, "%.2lf", used_filament);
append(out_filament_used_cm3, "%.1lf", extruded_volume * 0.001); append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
if (filament_weight > 0.) { if (filament_weight > 0.) {
print_statistics.total_weight = print_statistics.total_weight + filament_weight; print_statistics.total_weight = print_statistics.total_weight + filament_weight;
append(out_filament_used_g, "%.1lf", filament_weight); append(out_filament_used_g, "%.2lf", filament_weight);
if (filament_cost > 0.) { if (filament_cost > 0.) {
print_statistics.total_cost = print_statistics.total_cost + filament_cost; print_statistics.total_cost = print_statistics.total_cost + filament_cost;
append(out_filament_cost, "%.1lf", filament_cost); append(out_filament_cost, "%.2lf", filament_cost);
} }
} }
print_statistics.total_used_filament += used_filament; print_statistics.total_used_filament += used_filament;
@ -1598,8 +1604,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
// Modifies // Modifies
print.m_print_statistics)); print.m_print_statistics));
_write(file, "\n"); _write(file, "\n");
_write_format(file, "; total filament used [g] = %.1lf\n", print.m_print_statistics.total_weight); _write_format(file, "; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight);
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost); _write_format(file, "; total filament cost = %.2lf\n", print.m_print_statistics.total_cost);
if (print.m_print_statistics.total_toolchanges > 0) if (print.m_print_statistics.total_toolchanges > 0)
_write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); _write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
@ -1613,7 +1619,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
// Append full config. // Append full config.
_write(file, "\n"); _write(file, "\n");
{ {
std::string full_config = ""; std::string full_config;
append_full_config(print, full_config); append_full_config(print, full_config);
if (!full_config.empty()) if (!full_config.empty())
_write(file, full_config); _write(file, full_config);
@ -1636,9 +1642,9 @@ std::string GCode::placeholder_parser_process(const std::string &name, const std
} }
} }
// Parse the custom G-code, try to find mcode_set_temp_dont_wait and mcode_set_temp_and_wait inside the custom G-code. // Parse the custom G-code, try to find mcode_set_temp_dont_wait and mcode_set_temp_and_wait or optionally G10 with temperature inside the custom G-code.
// Returns true if one of the temp commands are found, and try to parse the target temperature value into temp_out. // Returns true if one of the temp commands are found, and try to parse the target temperature value into temp_out.
static bool custom_gcode_sets_temperature(const std::string &gcode, const int mcode_set_temp_dont_wait, const int mcode_set_temp_and_wait, int &temp_out) static bool custom_gcode_sets_temperature(const std::string &gcode, const int mcode_set_temp_dont_wait, const int mcode_set_temp_and_wait, const bool include_g10, int &temp_out)
{ {
temp_out = -1; temp_out = -1;
if (gcode.empty()) if (gcode.empty())
@ -1649,17 +1655,23 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
while (*ptr != 0) { while (*ptr != 0) {
// Skip whitespaces. // Skip whitespaces.
for (; *ptr == ' ' || *ptr == '\t'; ++ ptr); for (; *ptr == ' ' || *ptr == '\t'; ++ ptr);
if (*ptr == 'M') { if (*ptr == 'M' || // Line starts with 'M'. It is a machine command.
// Line starts with 'M'. It is a machine command. (*ptr == 'G' && include_g10)) { // Only check for G10 if requested
bool is_gcode = *ptr == 'G';
++ ptr; ++ ptr;
// Parse the M code value. // Parse the M or G code value.
char *endptr = nullptr; char *endptr = nullptr;
int mcode = int(strtol(ptr, &endptr, 10)); int mgcode = int(strtol(ptr, &endptr, 10));
if (endptr != nullptr && endptr != ptr && (mcode == mcode_set_temp_dont_wait || mcode == mcode_set_temp_and_wait)) { if (endptr != nullptr && endptr != ptr &&
// M104/M109 or M140/M190 found. is_gcode ?
// G10 found
mgcode == 10 :
// M104/M109 or M140/M190 found.
(mgcode == mcode_set_temp_dont_wait || mgcode == mcode_set_temp_and_wait)) {
ptr = endptr; ptr = endptr;
// Let the caller know that the custom G-code sets the temperature. if (! is_gcode)
temp_set_by_gcode = true; // Let the caller know that the custom M-code sets the temperature.
temp_set_by_gcode = true;
// Now try to parse the temperature value. // Now try to parse the temperature value.
// While not at the end of the line: // While not at the end of the line:
while (strchr(";\r\n\0", *ptr) == nullptr) { while (strchr(";\r\n\0", *ptr) == nullptr) {
@ -1674,6 +1686,10 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
if (endptr > ptr) { if (endptr > ptr) {
ptr = endptr; ptr = endptr;
temp_out = temp_parsed; temp_out = temp_parsed;
// Let the caller know that the custom G-code sets the temperature
// Only do this after successfully parsing temperature since G10
// can be used for other reasons
temp_set_by_gcode = true;
} }
} else { } else {
// Skip this word. // Skip this word.
@ -1694,7 +1710,7 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
// Do not process this piece of G-code by the time estimator, it already knows the values through another sources. // Do not process this piece of G-code by the time estimator, it already knows the values through another sources.
void GCode::print_machine_envelope(FILE *file, Print &print) void GCode::print_machine_envelope(FILE *file, Print &print)
{ {
if (print.config().gcode_flavor.value == gcfMarlin) { if (print.config().gcode_flavor.value == gcfMarlin && print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) {
fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n", fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n",
int(print.config().machine_max_acceleration_x.values.front() + 0.5), int(print.config().machine_max_acceleration_x.values.front() + 0.5),
int(print.config().machine_max_acceleration_y.values.front() + 0.5), int(print.config().machine_max_acceleration_y.values.front() + 0.5),
@ -1730,7 +1746,7 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s
int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id); int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id);
// Is the bed temperature set by the provided custom G-code? // Is the bed temperature set by the provided custom G-code?
int temp_by_gcode = -1; int temp_by_gcode = -1;
bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, temp_by_gcode); bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, false, temp_by_gcode);
if (temp_set_by_gcode && temp_by_gcode >= 0 && temp_by_gcode < 1000) if (temp_set_by_gcode && temp_by_gcode >= 0 && temp_by_gcode < 1000)
temp = temp_by_gcode; temp = temp_by_gcode;
// Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if // Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if
@ -1744,11 +1760,13 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s
// Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature.
// M104 - Set Extruder Temperature // M104 - Set Extruder Temperature
// M109 - Set Extruder Temperature and Wait // M109 - Set Extruder Temperature and Wait
// RepRapFirmware: G10 Sxx
void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait)
{ {
// Is the bed temperature set by the provided custom G-code? // Is the bed temperature set by the provided custom G-code?
int temp_by_gcode = -1; int temp_by_gcode = -1;
if (custom_gcode_sets_temperature(gcode, 104, 109, temp_by_gcode)) { bool include_g10 = print.config().gcode_flavor == gcfRepRapFirmware;
if (custom_gcode_sets_temperature(gcode, 104, 109, include_g10, temp_by_gcode)) {
// Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code. // Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code.
int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id); int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id);
if (temp_by_gcode >= 0 && temp_by_gcode < 1000) if (temp_by_gcode >= 0 && temp_by_gcode < 1000)
@ -2457,6 +2475,7 @@ void GCode::append_full_config(const Print &print, std::string &str)
static constexpr auto banned_keys = { static constexpr auto banned_keys = {
"compatible_printers"sv, "compatible_printers"sv,
"compatible_prints"sv, "compatible_prints"sv,
//FIXME The print host keys should not be exported to full_print_config anymore. The following keys may likely be removed.
"print_host"sv, "print_host"sv,
"printhost_apikey"sv, "printhost_apikey"sv,
"printhost_cafile"sv "printhost_cafile"sv

File diff suppressed because it is too large Load diff

View file

@ -1,309 +0,0 @@
#ifndef slic3r_GCode_Analyzer_hpp_
#define slic3r_GCode_Analyzer_hpp_
#if !ENABLE_GCODE_VIEWER
#include "../libslic3r.h"
#include "../PrintConfig.hpp"
#include "../ExtrusionEntity.hpp"
#include "../Point.hpp"
#include "../GCodeReader.hpp"
namespace Slic3r {
class GCodePreviewData;
class GCodeAnalyzer
{
public:
static const std::string Extrusion_Role_Tag;
static const std::string Mm3_Per_Mm_Tag;
static const std::string Width_Tag;
static const std::string Height_Tag;
static const std::string Color_Change_Tag;
static const std::string Pause_Print_Tag;
static const std::string Custom_Code_Tag;
static const std::string End_Pause_Print_Or_Custom_Code_Tag;
static const float Default_mm3_per_mm;
static const float Default_Width;
static const float Default_Height;
enum EUnits : unsigned char
{
Millimeters,
Inches
};
enum EAxis : unsigned char
{
X,
Y,
Z,
E,
Num_Axis
};
enum EPositioningType : unsigned char
{
Absolute,
Relative
};
struct Metadata
{
ExtrusionRole extrusion_role;
unsigned int extruder_id;
float mm3_per_mm;
float width; // mm
float height; // mm
float feedrate; // mm/s
float fan_speed; // percentage
unsigned int cp_color_id;
Metadata();
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, float fan_speed, unsigned int cp_color_id = 0);
bool operator != (const Metadata& other) const;
};
struct GCodeMove
{
enum EType : unsigned char
{
Noop,
Retract,
Unretract,
Tool_change,
Move,
Extrude,
Num_Types
};
EType type;
Metadata data;
Vec3f start_position;
Vec3f end_position;
float delta_extruder;
GCodeMove(EType type, ExtrusionRole extrusion_role, unsigned int extruder_id, float mm3_per_mm, float width, float height, float feedrate, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder, float fan_speed, unsigned int cp_color_id = 0);
GCodeMove(EType type, const Metadata& data, const Vec3f& start_position, const Vec3f& end_position, float delta_extruder);
};
typedef std::vector<GCodeMove> GCodeMovesList;
typedef std::map<GCodeMove::EType, GCodeMovesList> TypeToMovesMap;
typedef std::map<unsigned int, Vec2d> ExtruderOffsetsMap;
typedef std::map<unsigned int, unsigned int> ExtruderToColorMap;
private:
struct State
{
EUnits units;
EPositioningType global_positioning_type;
EPositioningType e_local_positioning_type;
Metadata data;
Vec3f start_position = Vec3f::Zero();
float cached_position[5];
float start_extrusion;
float position[Num_Axis];
float origin[Num_Axis];
unsigned int cp_color_counter = 0;
};
private:
State m_state;
GCodeReader m_parser;
TypeToMovesMap m_moves_map;
ExtruderOffsetsMap m_extruder_offsets;
unsigned int m_extruders_count;
GCodeFlavor m_gcode_flavor;
ExtruderToColorMap m_extruder_color;
// The output of process_layer()
std::string m_process_output;
public:
GCodeAnalyzer() { reset(); }
void set_extruder_offsets(const ExtruderOffsetsMap& extruder_offsets) { m_extruder_offsets = extruder_offsets; }
void set_extruders_count(unsigned int count);
void set_extrusion_axis(char axis) { m_parser.set_extrusion_axis(axis); }
void set_gcode_flavor(const GCodeFlavor& flavor) { m_gcode_flavor = flavor; }
// Reinitialize the analyzer
void reset();
// Adds the gcode contained in the given string to the analysis and returns it after removing the workcodes
const std::string& process_gcode(const std::string& gcode);
// Calculates all data needed for gcode visualization
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback = std::function<void()>());
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
static bool is_valid_extrusion_role(ExtrusionRole role);
private:
// Processes the given gcode line
void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
// Move
void _processG1(const GCodeReader::GCodeLine& line);
// Retract
void _processG10(const GCodeReader::GCodeLine& line);
// Unretract
void _processG11(const GCodeReader::GCodeLine& line);
// Firmware controlled Retract
void _processG22(const GCodeReader::GCodeLine& line);
// Firmware controlled Unretract
void _processG23(const GCodeReader::GCodeLine& line);
// Set to Absolute Positioning
void _processG90(const GCodeReader::GCodeLine& line);
// Set to Relative Positioning
void _processG91(const GCodeReader::GCodeLine& line);
// Set Position
void _processG92(const GCodeReader::GCodeLine& line);
// Set extruder to absolute mode
void _processM82(const GCodeReader::GCodeLine& line);
// Set extruder to relative mode
void _processM83(const GCodeReader::GCodeLine& line);
// Set fan speed
void _processM106(const GCodeReader::GCodeLine& line);
// Disable fan
void _processM107(const GCodeReader::GCodeLine& line);
// Set tool (MakerWare and Sailfish flavor)
void _processM108orM135(const GCodeReader::GCodeLine& line);
// Recall stored home offsets
void _processM132(const GCodeReader::GCodeLine& line);
// Repetier: Store x, y and z position
void _processM401(const GCodeReader::GCodeLine& line);
// Repetier: Go to stored position
void _processM402(const GCodeReader::GCodeLine& line);
// Processes T line (Select Tool)
void _processT(const std::string& command);
void _processT(const GCodeReader::GCodeLine& line);
// Processes the tags
// Returns true if any tag has been processed
bool _process_tags(const GCodeReader::GCodeLine& line);
// Processes extrusion role tag
void _process_extrusion_role_tag(const std::string& comment, size_t pos);
// Processes mm3_per_mm tag
void _process_mm3_per_mm_tag(const std::string& comment, size_t pos);
// Processes width tag
void _process_width_tag(const std::string& comment, size_t pos);
// Processes height tag
void _process_height_tag(const std::string& comment, size_t pos);
// Processes color change tag
void _process_color_change_tag(unsigned extruder);
// Processes pause print and custom gcode tag
void _process_pause_print_or_custom_code_tag();
// Processes new layer tag
void _process_end_pause_print_or_custom_code_tag();
void _set_units(EUnits units);
EUnits _get_units() const;
void _set_global_positioning_type(EPositioningType type);
EPositioningType _get_global_positioning_type() const;
void _set_e_local_positioning_type(EPositioningType type);
EPositioningType _get_e_local_positioning_type() const;
void _set_extrusion_role(ExtrusionRole extrusion_role);
ExtrusionRole _get_extrusion_role() const;
void _set_extruder_id(unsigned int id);
unsigned int _get_extruder_id() const;
void _set_cp_color_id(unsigned int id);
unsigned int _get_cp_color_id() const;
void _set_mm3_per_mm(float value);
float _get_mm3_per_mm() const;
void _set_width(float width);
float _get_width() const;
void _set_height(float height);
float _get_height() const;
void _set_feedrate(float feedrate_mm_sec);
float _get_feedrate() const;
void _set_fan_speed(float fan_speed_percentage);
float _get_fan_speed() const;
void _set_axis_position(EAxis axis, float position);
float _get_axis_position(EAxis axis) const;
void _set_axis_origin(EAxis axis, float position);
float _get_axis_origin(EAxis axis) const;
// Sets axes position to zero
void _reset_axes_position();
// Sets origin position to zero
void _reset_axes_origin();
void _set_start_position(const Vec3f& position);
const Vec3f& _get_start_position() const;
void _set_cached_position(unsigned char axis, float position);
float _get_cached_position(unsigned char axis) const;
void _reset_cached_position();
void _set_start_extrusion(float extrusion);
float _get_start_extrusion() const;
float _get_delta_extrusion() const;
// Returns current xyz position (from m_state.position[])
Vec3f _get_end_position() const;
// Adds a new move with the given data
void _store_move(GCodeMove::EType type);
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
bool _is_valid_extrusion_role(int value) const;
// All the following methods throw CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
};
} // namespace Slic3r
#endif // !ENABLE_GCODE_VIEWER
#endif /* slic3r_GCode_Analyzer_hpp_ */

View file

@ -10,6 +10,11 @@
#include <float.h> #include <float.h>
#include <assert.h> #include <assert.h>
#if __has_include(<charconv>)
#include <charconv>
#include <utility>
#endif
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
#include <chrono> #include <chrono>
@ -170,7 +175,7 @@ void GCodeProcessor::TimeMachine::reset()
prev.reset(); prev.reset();
gcode_time.reset(); gcode_time.reset();
blocks = std::vector<TimeBlock>(); blocks = std::vector<TimeBlock>();
g1_times_cache = std::vector<float>(); g1_times_cache = std::vector<G1LinesCacheItem>();
std::fill(moves_time.begin(), moves_time.end(), 0.0f); std::fill(moves_time.begin(), moves_time.end(), 0.0f);
std::fill(roles_time.begin(), roles_time.end(), 0.0f); std::fill(roles_time.begin(), roles_time.end(), 0.0f);
layers_time = std::vector<float>(); layers_time = std::vector<float>();
@ -292,7 +297,7 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks)
} }
layers_time[block.layer_id - 1] += block_time; layers_time[block.layer_id - 1] += block_time;
} }
g1_times_cache.push_back(time); g1_times_cache.push_back({ block.g1_line_id, time });
} }
if (keep_last_n_blocks) if (keep_last_n_blocks)
@ -358,7 +363,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
std::string ret; std::string ret;
if (line == First_Line_M73_Placeholder_Tag || line == Last_Line_M73_Placeholder_Tag) { if (export_remaining_time_enabled && (line == First_Line_M73_Placeholder_Tag || line == Last_Line_M73_Placeholder_Tag)) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
if (machine.enabled) { if (machine.enabled) {
@ -371,10 +376,11 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
else if (line == Estimated_Printing_Time_Placeholder_Tag) { else if (line == Estimated_Printing_Time_Placeholder_Tag) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
if (machine.enabled) { PrintEstimatedTimeStatistics::ETimeMode mode = static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i);
if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) {
char buf[128]; char buf[128];
sprintf(buf, "; estimated printing time (%s mode) = %s\n", sprintf(buf, "; estimated printing time (%s mode) = %s\n",
(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent", (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent",
get_time_dhms(machine.time).c_str()); get_time_dhms(machine.time).c_str());
ret += buf; ret += buf;
} }
@ -394,18 +400,30 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
return false; return false;
}; };
// Iterators for the normal and silent cached time estimate entry recently processed, used by process_line_G1.
auto g1_times_cache_it = Slic3r::reserve_vector<std::vector<TimeMachine::G1LinesCacheItem>::const_iterator>(machines.size());
for (const auto& machine : machines)
g1_times_cache_it.emplace_back(machine.g1_times_cache.begin());
// add lines M73 to exported gcode // add lines M73 to exported gcode
auto process_line_G1 = [&]() { auto process_line_G1 = [&]() {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { if (export_remaining_time_enabled) {
const TimeMachine& machine = machines[i]; for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
if (machine.enabled && g1_lines_counter < machine.g1_times_cache.size()) { const TimeMachine& machine = machines[i];
float elapsed_time = machine.g1_times_cache[g1_lines_counter]; if (machine.enabled) {
std::pair<int, int> to_export = { int(::roundf(100.0f * elapsed_time / machine.time)), // Skip all machine.g1_times_cache below g1_lines_counter.
time_in_minutes(machine.time - elapsed_time) }; auto& it = g1_times_cache_it[i];
if (last_exported[i] != to_export) { while (it != machine.g1_times_cache.end() && it->id < g1_lines_counter)
export_line += format_line_M73(machine.line_m73_mask.c_str(), ++it;
to_export.first, to_export.second); if (it != machine.g1_times_cache.end() && it->id == g1_lines_counter) {
last_exported[i] = to_export; float elapsed_time = it->elapsed_time;
std::pair<int, int> to_export = { int(100.0f * elapsed_time / machine.time),
time_in_minutes(machine.time - elapsed_time) };
if (last_exported[i] != to_export) {
export_line += format_line_M73(machine.line_m73_mask.c_str(),
to_export.first, to_export.second);
last_exported[i] = to_export;
}
}
} }
} }
} }
@ -466,6 +484,8 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProcessor::Producers = { const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProcessor::Producers = {
{ EProducer::PrusaSlicer, "PrusaSlicer" }, { EProducer::PrusaSlicer, "PrusaSlicer" },
{ EProducer::Slic3rPE, "Slic3r Prusa Edition" },
{ EProducer::Slic3r, "Slic3r" },
{ EProducer::Cura, "Cura_SteamEngine" }, { EProducer::Cura, "Cura_SteamEngine" },
{ EProducer::Simplify3D, "Simplify3D" }, { EProducer::Simplify3D, "Simplify3D" },
{ EProducer::CraftWare, "CraftWare" }, { EProducer::CraftWare, "CraftWare" },
@ -505,7 +525,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]); m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
} }
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config); if (config.machine_limits_usage.value != MachineLimitsUsage::Ignore)
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
// Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful. // Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
// are considered to be active for the single extruder multi-material printers only. // are considered to be active for the single extruder multi-material printers only.
@ -687,7 +709,7 @@ void GCodeProcessor::reset()
m_global_positioning_type = EPositioningType::Absolute; m_global_positioning_type = EPositioningType::Absolute;
m_e_local_positioning_type = EPositioningType::Absolute; m_e_local_positioning_type = EPositioningType::Absolute;
m_extruder_offsets = std::vector<Vec3f>(Min_Extruder_Count, Vec3f::Zero()); m_extruder_offsets = std::vector<Vec3f>(Min_Extruder_Count, Vec3f::Zero());
m_flavor = gcfRepRap; m_flavor = gcfRepRapSprinter;
m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f }; m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f };
m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f }; m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f };
@ -709,6 +731,7 @@ void GCodeProcessor::reset()
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f); m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
m_extruded_last_z = 0.0f; m_extruded_last_z = 0.0f;
m_g1_line_id = 0;
m_layer_id = 0; m_layer_id = 0;
m_cp_color.reset(); m_cp_color.reset();
@ -739,9 +762,9 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
// parse the gcode file to detect its producer // parse the gcode file to detect its producer
if (m_producers_enabled) { if (m_producers_enabled) {
m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
std::string cmd = line.cmd(); const std::string_view cmd = line.cmd();
if (cmd.length() == 0) { if (cmd.length() == 0) {
std::string comment = line.comment(); const std::string_view comment = line.comment();
if (comment.length() > 1 && detect_producer(comment)) if (comment.length() > 1 && detect_producer(comment))
m_parser.quit_parsing_file(); m_parser.quit_parsing_file();
} }
@ -749,7 +772,7 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
// if the gcode was produced by PrusaSlicer, // if the gcode was produced by PrusaSlicer,
// extract the config from it // extract the config from it
if (m_producer == EProducer::PrusaSlicer) { if (m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
DynamicPrintConfig config; DynamicPrintConfig config;
config.apply(FullPrintConfig::defaults()); config.apply(FullPrintConfig::defaults());
config.load_from_gcode_file(filename); config.load_from_gcode_file(filename);
@ -785,8 +808,7 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
update_estimated_times_stats(); update_estimated_times_stats();
// post-process to add M73 lines into the gcode // post-process to add M73 lines into the gcode
if (m_time_processor.export_remaining_time_enabled) m_time_processor.post_process(filename);
m_time_processor.post_process(filename);
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
std::cout << "\n"; std::cout << "\n";
@ -865,7 +887,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
// update start position // update start position
m_start_position = m_end_position; m_start_position = m_end_position;
std::string cmd = line.cmd(); const std::string_view cmd = line.cmd();
if (cmd.length() > 1) { if (cmd.length() > 1) {
// process command lines // process command lines
switch (::toupper(cmd[0])) switch (::toupper(cmd[0]))
@ -923,122 +945,151 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
} }
} }
else { else {
std::string comment = line.comment(); const std::string &comment = line.raw();
if (comment.length() > 1) if (comment.length() > 2 && comment.front() == ';')
// process tags embedded into comments // Process tags embedded into comments. Tag comments always start at the start of a line
process_tags(comment); // with a comment and continue with a tag without any whitespace separator.
process_tags(comment.substr(1));
} }
} }
void GCodeProcessor::process_tags(const std::string& comment) static inline bool starts_with(const std::string_view comment, const std::string_view tag)
{ {
// producers tags size_t tag_len = tag.size();
if (m_producers_enabled) { return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
if (m_producer != EProducer::Unknown) { }
if (process_producers_tags(comment))
return; #if __has_include(<charconv>)
template <typename T, typename = void>
struct is_from_chars_convertible : std::false_type {};
template <typename T>
struct is_from_chars_convertible<T, std::void_t<decltype(std::from_chars(std::declval<const char*>(), std::declval<const char*>(), std::declval<T&>()))>> : std::true_type {};
#endif
// Returns true if the number was parsed correctly into out and the number spanned the whole input string.
template<typename T>
[[nodiscard]] static inline bool parse_number(const std::string_view sv, T &out)
{
// https://www.bfilipek.com/2019/07/detect-overload-from-chars.html#example-stdfromchars
#if __has_include(<charconv>)
// Visual Studio 19 supports from_chars all right.
// OSX compiler that we use only implements std::from_chars just for ints.
// GCC that we compile on does not provide <charconv> at all.
if constexpr (is_from_chars_convertible<T>::value) {
auto str_end = sv.data() + sv.size();
auto [end_ptr, error_code] = std::from_chars(sv.data(), str_end, out);
return error_code == std::errc() && end_ptr == str_end;
}
else
#endif
{
// Legacy conversion, which is costly due to having to make a copy of the string before conversion.
try {
assert(sv.size() < 1024);
assert(sv.data() != nullptr);
std::string str { sv };
size_t read = 0;
if constexpr (std::is_same_v<T, int>)
out = std::stoi(str, &read);
else if constexpr (std::is_same_v<T, long>)
out = std::stol(str, &read);
else if constexpr (std::is_same_v<T, float>)
out = std::stof(str, &read);
else if constexpr (std::is_same_v<T, double>)
out = std::stod(str, &read);
return str.size() == read;
} catch (...) {
return false;
} }
} }
}
void GCodeProcessor::process_tags(const std::string_view comment)
{
// producers tags
if (m_producers_enabled && process_producers_tags(comment))
return;
// extrusion role tag // extrusion role tag
size_t pos = comment.find(Extrusion_Role_Tag); if (starts_with(comment, Extrusion_Role_Tag)) {
if (pos != comment.npos) { m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(Extrusion_Role_Tag.length()));
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(pos + Extrusion_Role_Tag.length()));
return; return;
} }
if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) { if ((!m_producers_enabled || m_producer == EProducer::PrusaSlicer) &&
starts_with(comment, Height_Tag)) {
// height tag // height tag
pos = comment.find(Height_Tag); if (! parse_number(comment.substr(Height_Tag.size()), m_height))
if (pos != comment.npos) { BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
try { return;
m_height = std::stof(comment.substr(pos + Height_Tag.length()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
}
return;
}
} }
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
// width tag // width tag
pos = comment.find(Width_Tag); if (starts_with(comment, Width_Tag)) {
if (pos != comment.npos) { if (! parse_number(comment.substr(Width_Tag.size()), m_width_compare.last_tag_value))
try {
m_width_compare.last_tag_value = std::stof(comment.substr(pos + Width_Tag.length()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
}
return; return;
} }
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
// color change tag // color change tag
pos = comment.find(Color_Change_Tag); if (starts_with(comment, Color_Change_Tag)) {
if (pos != comment.npos) { unsigned char extruder_id = 0;
pos = comment.find_last_of(",T"); if (starts_with(comment.substr(Color_Change_Tag.size()), ",T")) {
try { int eid;
unsigned char extruder_id = (pos == comment.npos) ? 0 : static_cast<unsigned char>(std::stoi(comment.substr(pos + 1))); if (! parse_number(comment.substr(Color_Change_Tag.size() + 2), eid) || eid < 0 || eid > 255) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview return;
++m_cp_color.counter;
if (m_cp_color.counter == UCHAR_MAX)
m_cp_color.counter = 0;
if (m_extruder_id == extruder_id) {
m_cp_color.current = m_extruder_colors[extruder_id];
store_move_vertex(EMoveType::Color_change);
} }
extruder_id = static_cast<unsigned char>(eid);
}
process_custom_gcode_time(CustomGCode::ColorChange); m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview
} ++m_cp_color.counter;
catch (...) { if (m_cp_color.counter == UCHAR_MAX)
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ")."; m_cp_color.counter = 0;
if (m_extruder_id == extruder_id) {
m_cp_color.current = m_extruder_colors[extruder_id];
store_move_vertex(EMoveType::Color_change);
} }
process_custom_gcode_time(CustomGCode::ColorChange);
return; return;
} }
// pause print tag // pause print tag
pos = comment.find(Pause_Print_Tag); if (comment == Pause_Print_Tag) {
if (pos != comment.npos) {
store_move_vertex(EMoveType::Pause_Print); store_move_vertex(EMoveType::Pause_Print);
process_custom_gcode_time(CustomGCode::PausePrint); process_custom_gcode_time(CustomGCode::PausePrint);
return; return;
} }
// custom code tag // custom code tag
pos = comment.find(Custom_Code_Tag); if (comment == Custom_Code_Tag) {
if (pos != comment.npos) {
store_move_vertex(EMoveType::Custom_GCode); store_move_vertex(EMoveType::Custom_GCode);
return; return;
} }
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
// mm3_per_mm print tag // mm3_per_mm print tag
pos = comment.find(Mm3_Per_Mm_Tag); if (starts_with(comment, Mm3_Per_Mm_Tag)) {
if (pos != comment.npos) { if (! parse_number(comment.substr(Mm3_Per_Mm_Tag.size()), m_mm3_per_mm_compare.last_tag_value))
try {
m_mm3_per_mm_compare.last_tag_value = std::stof(comment.substr(pos + Mm3_Per_Mm_Tag.length()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ").";
}
return; return;
} }
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
// layer change tag // layer change tag
pos = comment.find(Layer_Change_Tag); if (comment == Layer_Change_Tag) {
if (pos != comment.npos) {
++m_layer_id; ++m_layer_id;
return; return;
} }
} }
bool GCodeProcessor::process_producers_tags(const std::string& comment) bool GCodeProcessor::process_producers_tags(const std::string_view comment)
{ {
switch (m_producer) switch (m_producer)
{ {
@ -1051,18 +1102,18 @@ bool GCodeProcessor::process_producers_tags(const std::string& comment)
} }
} }
bool GCodeProcessor::process_prusaslicer_tags(const std::string& comment) bool GCodeProcessor::process_prusaslicer_tags(const std::string_view comment)
{ {
return false; return false;
} }
bool GCodeProcessor::process_cura_tags(const std::string& comment) bool GCodeProcessor::process_cura_tags(const std::string_view comment)
{ {
// TYPE -> extrusion role // TYPE -> extrusion role
std::string tag = "TYPE:"; std::string tag = "TYPE:";
size_t pos = comment.find(tag); size_t pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
std::string type = comment.substr(pos + tag.length()); const std::string_view type = comment.substr(pos + tag.length());
if (type == "SKIRT") if (type == "SKIRT")
m_extrusion_role = erSkirt; m_extrusion_role = erSkirt;
else if (type == "WALL-OUTER") else if (type == "WALL-OUTER")
@ -1091,7 +1142,7 @@ bool GCodeProcessor::process_cura_tags(const std::string& comment)
tag = "FLAVOR:"; tag = "FLAVOR:";
pos = comment.find(tag); pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
std::string flavor = comment.substr(pos + tag.length()); const std::string_view flavor = comment.substr(pos + tag.length());
if (flavor == "BFB") if (flavor == "BFB")
m_flavor = gcfMarlin; // << ??????????????????????? m_flavor = gcfMarlin; // << ???????????????????????
else if (flavor == "Mach3") else if (flavor == "Mach3")
@ -1107,7 +1158,7 @@ bool GCodeProcessor::process_cura_tags(const std::string& comment)
else if (flavor == "Repetier") else if (flavor == "Repetier")
m_flavor = gcfRepetier; m_flavor = gcfRepetier;
else if (flavor == "RepRap") else if (flavor == "RepRap")
m_flavor = gcfRepRap; m_flavor = gcfRepRapFirmware;
else if (flavor == "Marlin") else if (flavor == "Marlin")
m_flavor = gcfMarlin; m_flavor = gcfMarlin;
else else
@ -1119,7 +1170,7 @@ bool GCodeProcessor::process_cura_tags(const std::string& comment)
return false; return false;
} }
bool GCodeProcessor::process_simplify3d_tags(const std::string& comment) bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
{ {
// extrusion roles // extrusion roles
@ -1207,7 +1258,7 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string& comment)
std::string tag = " tool"; std::string tag = " tool";
pos = comment.find(tag); pos = comment.find(tag);
if (pos == 0) { if (pos == 0) {
std::string data = comment.substr(pos + tag.length()); const std::string_view data = comment.substr(pos + tag.length());
std::string h_tag = "H"; std::string h_tag = "H";
size_t h_start = data.find(h_tag); size_t h_start = data.find(h_tag);
size_t h_end = data.find_first_of(' ', h_start); size_t h_end = data.find_first_of(' ', h_start);
@ -1215,20 +1266,12 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string& comment)
size_t w_start = data.find(w_tag); size_t w_start = data.find(w_tag);
size_t w_end = data.find_first_of(' ', w_start); size_t w_end = data.find_first_of(' ', w_start);
if (h_start != data.npos) { if (h_start != data.npos) {
try { if (! parse_number(data.substr(h_start + 1, (h_end != data.npos) ? h_end - h_start - 1 : h_end), m_height_compare.last_tag_value))
m_height_compare.last_tag_value = std::stof(data.substr(h_start + 1, (h_end != data.npos) ? h_end - h_start - 1 : h_end));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
}
} }
if (w_start != data.npos) { if (w_start != data.npos) {
try { if (! parse_number(data.substr(w_start + 1, (w_end != data.npos) ? w_end - w_start - 1 : w_end), m_width_compare.last_tag_value))
m_width_compare.last_tag_value = std::stof(data.substr(w_start + 1, (w_end != data.npos) ? w_end - w_start - 1 : w_end));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
}
} }
return true; return true;
@ -1238,13 +1281,13 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string& comment)
return false; return false;
} }
bool GCodeProcessor::process_craftware_tags(const std::string& comment) bool GCodeProcessor::process_craftware_tags(const std::string_view comment)
{ {
// segType -> extrusion role // segType -> extrusion role
std::string tag = "segType:"; std::string tag = "segType:";
size_t pos = comment.find(tag); size_t pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
std::string type = comment.substr(pos + tag.length()); const std::string_view type = comment.substr(pos + tag.length());
if (type == "Skirt") if (type == "Skirt")
m_extrusion_role = erSkirt; m_extrusion_role = erSkirt;
else if (type == "Perimeter") else if (type == "Perimeter")
@ -1278,13 +1321,13 @@ bool GCodeProcessor::process_craftware_tags(const std::string& comment)
return false; return false;
} }
bool GCodeProcessor::process_ideamaker_tags(const std::string& comment) bool GCodeProcessor::process_ideamaker_tags(const std::string_view comment)
{ {
// TYPE -> extrusion role // TYPE -> extrusion role
std::string tag = "TYPE:"; std::string tag = "TYPE:";
size_t pos = comment.find(tag); size_t pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
std::string type = comment.substr(pos + tag.length()); const std::string_view type = comment.substr(pos + tag.length());
if (type == "RAFT") if (type == "RAFT")
m_extrusion_role = erSkirt; m_extrusion_role = erSkirt;
else if (type == "WALL-OUTER") else if (type == "WALL-OUTER")
@ -1313,12 +1356,8 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string& comment)
tag = "WIDTH:"; tag = "WIDTH:";
pos = comment.find(tag); pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
try { if (! parse_number(comment.substr(pos + tag.length()), m_width_compare.last_tag_value))
m_width_compare.last_tag_value = std::stof(comment.substr(pos + tag.length()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
}
return true; return true;
} }
@ -1326,12 +1365,8 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string& comment)
tag = "HEIGHT:"; tag = "HEIGHT:";
pos = comment.find(tag); pos = comment.find(tag);
if (pos != comment.npos) { if (pos != comment.npos) {
try { if (! parse_number(comment.substr(pos + tag.length()), m_height_compare.last_tag_value))
m_height_compare.last_tag_value = std::stof(comment.substr(pos + tag.length()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ")."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
}
return true; return true;
} }
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -1339,7 +1374,7 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string& comment)
return false; return false;
} }
bool GCodeProcessor::detect_producer(const std::string& comment) bool GCodeProcessor::detect_producer(const std::string_view comment)
{ {
for (const auto& [id, search_string] : Producers) { for (const auto& [id, search_string] : Producers) {
size_t pos = comment.find(search_string); size_t pos = comment.find(search_string);
@ -1391,6 +1426,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
return type; return type;
}; };
++m_g1_line_id;
// enable processing of lines M201/M203/M204/M205 // enable processing of lines M201/M203/M204/M205
m_time_processor.machine_envelope_processing_enabled = true; m_time_processor.machine_envelope_processing_enabled = true;
@ -1454,7 +1491,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast<float>(1.0 - 0.25 * M_PI) * m_height; m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast<float>(1.0 - 0.25 * M_PI) * m_height;
// clamp width to avoid artifacts which may arise from wrong values of m_height // clamp width to avoid artifacts which may arise from wrong values of m_height
m_width = std::min(m_width, 4.0f * m_height); m_width = std::min(m_width, 1.0f);
// m_width = std::min(m_width, 4.0f * m_height);
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_width_compare.update(m_width, m_extrusion_role); m_width_compare.update(m_width, m_extrusion_role);
@ -1495,6 +1533,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
block.move_type = type; block.move_type = type;
block.role = m_extrusion_role; block.role = m_extrusion_role;
block.distance = distance; block.distance = distance;
block.g1_line_id = m_g1_line_id;
block.layer_id = m_layer_id; block.layer_id = m_layer_id;
// calculates block cruise feedrate // calculates block cruise feedrate
@ -1798,7 +1837,7 @@ void GCodeProcessor::process_M201(const GCodeReader::GCodeLine& line)
return; return;
// see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration // see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration
float factor = (m_flavor != gcfRepRap && m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f; float factor = ((m_flavor != gcfRepRapSprinter && m_flavor != gcfRepRapFirmware) && m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
if (line.has_x()) if (line.has_x())
@ -1991,11 +2030,14 @@ void GCodeProcessor::process_T(const GCodeReader::GCodeLine& line)
process_T(line.cmd()); process_T(line.cmd());
} }
void GCodeProcessor::process_T(const std::string& command) void GCodeProcessor::process_T(const std::string_view command)
{ {
if (command.length() > 1) { if (command.length() > 1) {
try { int eid;
unsigned char id = static_cast<unsigned char>(std::stoi(command.substr(1))); if (! parse_number(command.substr(1), eid) || eid < 0 || eid > 255) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
} else {
unsigned char id = static_cast<unsigned char>(eid);
if (m_extruder_id != id) { if (m_extruder_id != id) {
unsigned char extruders_count = static_cast<unsigned char>(m_extruder_offsets.size()); unsigned char extruders_count = static_cast<unsigned char>(m_extruder_offsets.size());
if (id >= extruders_count) if (id >= extruders_count)
@ -2017,9 +2059,6 @@ void GCodeProcessor::process_T(const std::string& command)
store_move_vertex(EMoveType::Tool_change); store_move_vertex(EMoveType::Tool_change);
} }
} }
catch (...) {
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
}
} }
} }

View file

@ -11,6 +11,7 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include <string> #include <string>
#include <string_view>
namespace Slic3r { namespace Slic3r {
@ -145,6 +146,7 @@ namespace Slic3r {
EMoveType move_type{ EMoveType::Noop }; EMoveType move_type{ EMoveType::Noop };
ExtrusionRole role{ erNone }; ExtrusionRole role{ erNone };
unsigned int g1_line_id{ 0 };
unsigned int layer_id{ 0 }; unsigned int layer_id{ 0 };
float distance{ 0.0f }; // mm float distance{ 0.0f }; // mm
float acceleration{ 0.0f }; // mm/s^2 float acceleration{ 0.0f }; // mm/s^2
@ -182,6 +184,12 @@ namespace Slic3r {
void reset(); void reset();
}; };
struct G1LinesCacheItem
{
unsigned int id;
float elapsed_time;
};
bool enabled; bool enabled;
float acceleration; // mm/s^2 float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp. // hard limit for the acceleration, to which the firmware will clamp.
@ -193,7 +201,7 @@ namespace Slic3r {
State prev; State prev;
CustomGCodeTime gcode_time; CustomGCodeTime gcode_time;
std::vector<TimeBlock> blocks; std::vector<TimeBlock> blocks;
std::vector<float> g1_times_cache; std::vector<G1LinesCacheItem> g1_times_cache;
std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time; std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time;
std::array<float, static_cast<size_t>(ExtrusionRole::erCount)> roles_time; std::array<float, static_cast<size_t>(ExtrusionRole::erCount)> roles_time;
std::vector<float> layers_time; std::vector<float> layers_time;
@ -305,10 +313,12 @@ namespace Slic3r {
{} {}
void update(float value, ExtrusionRole role) { void update(float value, ExtrusionRole role) {
++count; if (role != erCustom) {
if (last_tag_value != 0.0f) { ++count;
if (std::abs(value - last_tag_value) / last_tag_value > threshold) if (last_tag_value != 0.0f) {
errors.push_back({ value, last_tag_value, role }); if (std::abs(value - last_tag_value) / last_tag_value > threshold)
errors.push_back({ value, last_tag_value, role });
}
} }
} }
@ -374,6 +384,7 @@ namespace Slic3r {
ExtruderColors m_extruder_colors; ExtruderColors m_extruder_colors;
std::vector<float> m_filament_diameters; std::vector<float> m_filament_diameters;
float m_extruded_last_z; float m_extruded_last_z;
unsigned int m_g1_line_id;
unsigned int m_layer_id; unsigned int m_layer_id;
CpColor m_cp_color; CpColor m_cp_color;
@ -381,6 +392,8 @@ namespace Slic3r {
{ {
Unknown, Unknown,
PrusaSlicer, PrusaSlicer,
Slic3rPE,
Slic3r,
Cura, Cura,
Simplify3D, Simplify3D,
CraftWare, CraftWare,
@ -434,15 +447,15 @@ namespace Slic3r {
void process_gcode_line(const GCodeReader::GCodeLine& line); void process_gcode_line(const GCodeReader::GCodeLine& line);
// Process tags embedded into comments // Process tags embedded into comments
void process_tags(const std::string& comment); void process_tags(const std::string_view comment);
bool process_producers_tags(const std::string& comment); bool process_producers_tags(const std::string_view comment);
bool process_prusaslicer_tags(const std::string& comment); bool process_prusaslicer_tags(const std::string_view comment);
bool process_cura_tags(const std::string& comment); bool process_cura_tags(const std::string_view comment);
bool process_simplify3d_tags(const std::string& comment); bool process_simplify3d_tags(const std::string_view comment);
bool process_craftware_tags(const std::string& comment); bool process_craftware_tags(const std::string_view comment);
bool process_ideamaker_tags(const std::string& comment); bool process_ideamaker_tags(const std::string_view comment);
bool detect_producer(const std::string& comment); bool detect_producer(const std::string_view comment);
// Move // Move
void process_G0(const GCodeReader::GCodeLine& line); void process_G0(const GCodeReader::GCodeLine& line);
@ -528,7 +541,7 @@ namespace Slic3r {
// Processes T line (Select Tool) // Processes T line (Select Tool)
void process_T(const GCodeReader::GCodeLine& line); void process_T(const GCodeReader::GCodeLine& line);
void process_T(const std::string& command); void process_T(const std::string_view command);
void store_move_vertex(EMoveType type); void store_move_vertex(EMoveType type);

View file

@ -165,9 +165,10 @@ static inline float parse_float(const char *&line)
return result; return result;
}; };
#define EXTRUSION_ROLE_TAG ";_EXTRUSION_ROLE:"
bool PressureEqualizer::process_line(const char *line, const size_t len, GCodeLine &buf) bool PressureEqualizer::process_line(const char *line, const size_t len, GCodeLine &buf)
{ {
static constexpr const char *EXTRUSION_ROLE_TAG = ";_EXTRUSION_ROLE:";
if (strncmp(line, EXTRUSION_ROLE_TAG, strlen(EXTRUSION_ROLE_TAG)) == 0) { if (strncmp(line, EXTRUSION_ROLE_TAG, strlen(EXTRUSION_ROLE_TAG)) == 0) {
line += strlen(EXTRUSION_ROLE_TAG); line += strlen(EXTRUSION_ROLE_TAG);
int role = atoi(line); int role = atoi(line);

View file

@ -1,4 +1,3 @@
#include "Analyzer.hpp"
#include "PreviewData.hpp" #include "PreviewData.hpp"
#include <I18N.hpp> #include <I18N.hpp>
#include "Utils.hpp" #include "Utils.hpp"

View file

@ -126,7 +126,7 @@ public:
} }
WipeTowerWriter& disable_linear_advance() { WipeTowerWriter& disable_linear_advance() {
m_gcode += (m_gcode_flavor == gcfRepRap m_gcode += (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware
? (std::string("M572 D") + std::to_string(m_current_tool) + " S0\n") ? (std::string("M572 D") + std::to_string(m_current_tool) + " S0\n")
: std::string("M900 K0\n")); : std::string("M900 K0\n"));
return *this; return *this;
@ -386,7 +386,7 @@ public:
// Set digital trimpot motor // Set digital trimpot motor
WipeTowerWriter& set_extruder_trimpot(int current) WipeTowerWriter& set_extruder_trimpot(int current)
{ {
if (m_gcode_flavor == gcfRepRap) if (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware)
m_gcode += "M906 E"; m_gcode += "M906 E";
else else
m_gcode += "M907 E"; m_gcode += "M907 E";

View file

@ -6,6 +6,7 @@
#include <cstdlib> #include <cstdlib>
#include <functional> #include <functional>
#include <string> #include <string>
#include <string_view>
#include "PrintConfig.hpp" #include "PrintConfig.hpp"
namespace Slic3r { namespace Slic3r {
@ -17,13 +18,13 @@ public:
GCodeLine() { reset(); } GCodeLine() { reset(); }
void reset() { m_mask = 0; memset(m_axis, 0, sizeof(m_axis)); m_raw.clear(); } void reset() { m_mask = 0; memset(m_axis, 0, sizeof(m_axis)); m_raw.clear(); }
const std::string& raw() const { return m_raw; } const std::string& raw() const { return m_raw; }
const std::string cmd() const { const std::string_view cmd() const {
const char *cmd = GCodeReader::skip_whitespaces(m_raw.c_str()); const char *cmd = GCodeReader::skip_whitespaces(m_raw.c_str());
return std::string(cmd, GCodeReader::skip_word(cmd)); return std::string_view(cmd, GCodeReader::skip_word(cmd) - cmd);
} }
const std::string comment() const const std::string_view comment() const
{ size_t pos = m_raw.find(';'); return (pos == std::string::npos) ? "" : m_raw.substr(pos + 1); } { size_t pos = m_raw.find(';'); return (pos == std::string::npos) ? std::string_view() : std::string_view(m_raw).substr(pos + 1); }
bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; } bool has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; }
float value(Axis axis) const { return m_axis[axis]; } float value(Axis axis) const { return m_axis[axis]; }

File diff suppressed because it is too large Load diff

View file

@ -1,488 +0,0 @@
#ifndef slic3r_GCodeTimeEstimator_hpp_
#define slic3r_GCodeTimeEstimator_hpp_
#include "libslic3r.h"
#include "PrintConfig.hpp"
#include "GCodeReader.hpp"
#include "CustomGCode.hpp"
#if !ENABLE_GCODE_VIEWER
#define ENABLE_MOVE_STATS 0
namespace Slic3r {
//
// Some of the algorithms used by class GCodeTimeEstimator were inpired by
// Cura Engine's class TimeEstimateCalculator
// https://github.com/Ultimaker/CuraEngine/blob/master/src/timeEstimate.h
//
class GCodeTimeEstimator
{
public:
static const std::string Normal_First_M73_Output_Placeholder_Tag;
static const std::string Silent_First_M73_Output_Placeholder_Tag;
static const std::string Normal_Last_M73_Output_Placeholder_Tag;
static const std::string Silent_Last_M73_Output_Placeholder_Tag;
static const std::string Color_Change_Tag;
static const std::string Pause_Print_Tag;
enum EMode : unsigned char
{
Normal,
Silent
};
enum EUnits : unsigned char
{
Millimeters,
Inches
};
enum EAxis : unsigned char
{
X,
Y,
Z,
E,
Num_Axis
};
enum EPositioningType : unsigned char
{
Absolute,
Relative
};
private:
struct Axis
{
float position; // mm
float origin; // mm
float max_feedrate; // mm/s
float max_acceleration; // mm/s^2
float max_jerk; // mm/s
};
struct Feedrates
{
float feedrate; // mm/s
float axis_feedrate[Num_Axis]; // mm/s
float abs_axis_feedrate[Num_Axis]; // mm/s
float safe_feedrate; // mm/s
void reset();
};
struct State
{
GCodeFlavor dialect;
EUnits units;
EPositioningType global_positioning_type;
EPositioningType e_local_positioning_type;
Axis axis[Num_Axis];
float feedrate; // mm/s
float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_acceleration; // mm/s^2
float retract_acceleration; // mm/s^2
float minimum_feedrate; // mm/s
float minimum_travel_feedrate; // mm/s
float extrude_factor_override_percentage;
// Additional load / unload times for a filament exchange sequence.
std::vector<float> filament_load_times;
std::vector<float> filament_unload_times;
unsigned int g1_line_id;
// extruder_id is currently used to correctly calculate filament load / unload times
// into the total print time. This is currently only really used by the MK3 MMU2:
// Extruder id (-1) means no filament is loaded yet, all the filaments are parked in the MK3 MMU2 unit.
static const unsigned int extruder_id_unloaded = (unsigned int)-1;
unsigned int extruder_id;
};
public:
struct Block
{
#if ENABLE_MOVE_STATS
enum EMoveType : unsigned char
{
Noop,
Retract,
Unretract,
Tool_change,
Move,
Extrude,
Num_Types
};
#endif // ENABLE_MOVE_STATS
struct FeedrateProfile
{
float entry; // mm/s
float cruise; // mm/s
float exit; // mm/s
};
struct Trapezoid
{
float accelerate_until; // mm
float decelerate_after; // mm
float cruise_feedrate; // mm/sec
float acceleration_time(float entry_feedrate, float acceleration) const;
float cruise_time() const;
float deceleration_time(float distance, float acceleration) const;
float cruise_distance() const;
// This function gives the time needed to accelerate from an initial speed to reach a final distance.
static float acceleration_time_from_distance(float initial_feedrate, float distance, float acceleration);
// This function gives the final speed while accelerating at the given constant acceleration from the given initial speed along the given distance.
static float speed_from_distance(float initial_feedrate, float distance, float acceleration);
};
struct Flags
{
bool recalculate;
bool nominal_length;
};
#if ENABLE_MOVE_STATS
EMoveType move_type;
#endif // ENABLE_MOVE_STATS
Flags flags;
float distance; // mm
float acceleration; // mm/s^2
float max_entry_speed; // mm/s
float safe_feedrate; // mm/s
FeedrateProfile feedrate;
Trapezoid trapezoid;
// Ordnary index of this G1 line in the file.
int g1_line_id { -1 };
// Returns the time spent accelerating toward cruise speed, in seconds
float acceleration_time() const;
// Returns the time spent at cruise speed, in seconds
float cruise_time() const;
// Returns the time spent decelerating from cruise speed, in seconds
float deceleration_time() const;
// Returns the distance covered at cruise speed, in mm
float cruise_distance() const;
// Calculates this block's trapezoid
void calculate_trapezoid();
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// acceleration within the allotted distance.
static float max_allowable_speed(float acceleration, float target_velocity, float distance);
// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the given acceleration:
static float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration);
// This function gives you the point at which you must start braking (at the rate of -acceleration) if
// you started at speed initial_rate and accelerated until this point and want to end at the final_rate after
// a total travel of distance. This can be used to compute the intersection point between acceleration and
// deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed)
static float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance);
};
typedef std::vector<Block> BlocksList;
#if ENABLE_MOVE_STATS
struct MoveStats
{
unsigned int count;
float time;
MoveStats();
};
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
#endif // ENABLE_MOVE_STATS
public:
typedef std::pair<int, float> G1LineIdTime;
typedef std::vector<G1LineIdTime> G1LineIdsTimes;
struct PostProcessData
{
const G1LineIdsTimes& g1_times;
float time;
};
private:
EMode m_mode;
GCodeReader m_parser;
State m_state;
Feedrates m_curr;
Feedrates m_prev;
BlocksList m_blocks;
// Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks.
// Let's be conservative and plan for newer boards with more memory.
static constexpr size_t planner_queue_size = 64;
// The firmware recalculates last planner_queue_size trapezoidal blocks each time a new block is added.
// We are not simulating the firmware exactly, we calculate a sequence of blocks once a reasonable number of blocks accumulate.
static constexpr size_t planner_refresh_if_larger = planner_queue_size * 4;
// Map from g1 line id to its elapsed time from the start of the print.
G1LineIdsTimes m_g1_times;
float m_time; // s
// data to calculate custom code times
bool m_needs_custom_gcode_times;
std::vector<std::pair<CustomGCode::Type, float>> m_custom_gcode_times;
float m_custom_gcode_time_cache;
#if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats;
#endif // ENABLE_MOVE_STATS
public:
explicit GCodeTimeEstimator(EMode mode);
// Adds the given gcode line
void add_gcode_line(const std::string& gcode_line);
void add_gcode_block(const char *ptr);
void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
// Calculates the time estimate from the gcode lines added using add_gcode_line() or add_gcode_block()
// start_from_beginning:
// if set to true all blocks will be used to calculate the time estimate,
// if set to false only the blocks not yet processed will be used and the calculated time will be added to the current calculated time
void calculate_time(bool start_from_beginning);
// Calculates the time estimate from the given gcode in string format
//void calculate_time_from_text(const std::string& gcode);
// Calculates the time estimate from the gcode contained in the file with the given filename
//void calculate_time_from_file(const std::string& file);
// Calculates the time estimate from the gcode contained in given list of gcode lines
//void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
// Process the gcode contained in the file with the given filename,
// replacing placeholders with correspondent new lines M73
// placing new lines M73 (containing the remaining time) where needed (in dependence of the given interval in seconds)
// and removing working tags (as those used for color changes)
// if normal_mode == nullptr no M73 line will be added for normal mode
// if silent_mode == nullptr no M73 line will be added for silent mode
static bool post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode);
// Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position);
// Set current origin on the given axis with the given value
void set_axis_origin(EAxis axis, float position);
void set_axis_max_feedrate(EAxis axis, float feedrate_mm_sec);
void set_axis_max_acceleration(EAxis axis, float acceleration);
void set_axis_max_jerk(EAxis axis, float jerk);
// Returns current position on the given axis
float get_axis_position(EAxis axis) const;
// Returns current origin on the given axis
float get_axis_origin(EAxis axis) const;
float get_axis_max_feedrate(EAxis axis) const;
float get_axis_max_acceleration(EAxis axis) const;
float get_axis_max_jerk(EAxis axis) const;
void set_feedrate(float feedrate_mm_sec);
float get_feedrate() const;
void set_acceleration(float acceleration_mm_sec2);
float get_acceleration() const;
// Maximum acceleration for the machine. The firmware simulator will clamp the M204 Sxxx to this maximum.
void set_max_acceleration(float acceleration_mm_sec2);
float get_max_acceleration() const;
void set_retract_acceleration(float acceleration_mm_sec2);
float get_retract_acceleration() const;
void set_minimum_feedrate(float feedrate_mm_sec);
float get_minimum_feedrate() const;
void set_minimum_travel_feedrate(float feedrate_mm_sec);
float get_minimum_travel_feedrate() const;
void set_filament_load_times(const std::vector<double> &filament_load_times);
void set_filament_unload_times(const std::vector<double> &filament_unload_times);
float get_filament_load_time(unsigned int id_extruder);
float get_filament_unload_time(unsigned int id_extruder);
void set_extrude_factor_override_percentage(float percentage);
float get_extrude_factor_override_percentage() const;
void set_dialect(GCodeFlavor dialect);
GCodeFlavor get_dialect() const;
void set_units(EUnits units);
EUnits get_units() const;
void set_global_positioning_type(EPositioningType type);
EPositioningType get_global_positioning_type() const;
void set_e_local_positioning_type(EPositioningType type);
EPositioningType get_e_local_positioning_type() const;
int get_g1_line_id() const;
void increment_g1_line_id();
void reset_g1_line_id();
void set_extrusion_axis(char axis) { m_parser.set_extrusion_axis(axis); }
void set_extruder_id(unsigned int id);
unsigned int get_extruder_id() const;
void reset_extruder_id();
void set_default();
// Call this method before to start adding lines using add_gcode_line() when reusing an instance of GCodeTimeEstimator
void reset();
// Returns the estimated time, in seconds
float get_time() const;
// Returns the estimated time, in format DDd HHh MMm SSs
std::string get_time_dhms() const;
// Returns the estimated time, in format DDd HHh MMm
std::string get_time_dhm() const;
// Returns the estimated time, in minutes (integer)
std::string get_time_minutes() const;
// Returns the estimated time, in seconds, for each custom gcode
std::vector<std::pair<CustomGCode::Type, float>> get_custom_gcode_times() const;
// Returns the estimated time, in format DDd HHh MMm SSs, for each color
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
std::vector<std::string> get_color_times_dhms(bool include_remaining) const;
// Returns the estimated time, in minutes (integer), for each color
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
// Returns the estimated time, in format DDd HHh MMm, for each custom_gcode
// If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)"
std::vector<std::pair<CustomGCode::Type, std::string>> get_custom_gcode_times_dhm(bool include_remaining) const;
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
PostProcessData get_post_process_data() const { return PostProcessData{ m_g1_times, m_time }; }
private:
void _reset();
void _reset_time();
void _reset_blocks();
// Calculates the time estimate
void _calculate_time(size_t keep_last_n_blocks);
// Processes the given gcode line
void _process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line);
// Move
void _processG1(const GCodeReader::GCodeLine& line);
// Dwell
void _processG4(const GCodeReader::GCodeLine& line);
// Set Units to Inches
void _processG20(const GCodeReader::GCodeLine& line);
// Set Units to Millimeters
void _processG21(const GCodeReader::GCodeLine& line);
// Move to Origin (Home)
void _processG28(const GCodeReader::GCodeLine& line);
// Set to Absolute Positioning
void _processG90(const GCodeReader::GCodeLine& line);
// Set to Relative Positioning
void _processG91(const GCodeReader::GCodeLine& line);
// Set Position
void _processG92(const GCodeReader::GCodeLine& line);
// Sleep or Conditional stop
void _processM1(const GCodeReader::GCodeLine& line);
// Set extruder to absolute mode
void _processM82(const GCodeReader::GCodeLine& line);
// Set extruder to relative mode
void _processM83(const GCodeReader::GCodeLine& line);
// Set Extruder Temperature and Wait
void _processM109(const GCodeReader::GCodeLine& line);
// Set max printing acceleration
void _processM201(const GCodeReader::GCodeLine& line);
// Set maximum feedrate
void _processM203(const GCodeReader::GCodeLine& line);
// Set default acceleration
void _processM204(const GCodeReader::GCodeLine& line);
// Advanced settings
void _processM205(const GCodeReader::GCodeLine& line);
// Set extrude factor override percentage
void _processM221(const GCodeReader::GCodeLine& line);
// Set allowable instantaneous speed change
void _processM566(const GCodeReader::GCodeLine& line);
// Unload the current filament into the MK3 MMU2 unit at the end of print.
void _processM702(const GCodeReader::GCodeLine& line);
// Processes T line (Select Tool)
void _processT(const GCodeReader::GCodeLine& line);
// Processes the tags
// Returns true if any tag has been processed
bool _process_tags(const GCodeReader::GCodeLine& line);
// Processes ColorChangeTag and PausePrintTag
void _process_custom_gcode_tag(CustomGCode::Type code);
// Simulates firmware st_synchronize() call
void _simulate_st_synchronize(float additional_time);
void _forward_pass();
void _reverse_pass();
void _planner_forward_pass_kernel(Block& prev, Block& curr);
void _planner_reverse_pass_kernel(Block& curr, Block& next);
void _recalculate_trapezoids();
// Returns the given time is seconds in format DDd HHh MMm SSs
static std::string _get_time_dhms(float time_in_secs);
// Returns the given time is minutes in format DDd HHh MMm
static std::string _get_time_dhm(float time_in_secs);
// Returns the given, in minutes (integer)
static std::string _get_time_minutes(float time_in_secs);
#if ENABLE_MOVE_STATS
void _log_moves_stats() const;
#endif // ENABLE_MOVE_STATS
};
} /* namespace Slic3r */
#endif // !ENABLE_GCODE_VIEWER
#endif /* slic3r_GCodeTimeEstimator_hpp_ */

View file

@ -20,7 +20,7 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
this->config.apply(print_config, true); this->config.apply(print_config, true);
m_extrusion_axis = this->config.get_extrusion_axis(); m_extrusion_axis = this->config.get_extrusion_axis();
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin) ? m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) ?
print_config.machine_max_acceleration_extruding.values.front() : 0); print_config.machine_max_acceleration_extruding.values.front() : 0);
} }
@ -46,7 +46,13 @@ std::string GCodeWriter::preamble()
gcode << "G21 ; set units to millimeters\n"; gcode << "G21 ; set units to millimeters\n";
gcode << "G90 ; use absolute coordinates\n"; gcode << "G90 ; use absolute coordinates\n";
} }
if (FLAVOR_IS(gcfRepRap) || FLAVOR_IS(gcfMarlin) || FLAVOR_IS(gcfTeacup) || FLAVOR_IS(gcfRepetier) || FLAVOR_IS(gcfSmoothie)) { if (FLAVOR_IS(gcfRepRapSprinter) ||
FLAVOR_IS(gcfRepRapFirmware) ||
FLAVOR_IS(gcfMarlin) ||
FLAVOR_IS(gcfTeacup) ||
FLAVOR_IS(gcfRepetier) ||
FLAVOR_IS(gcfSmoothie))
{
if (this->config.use_relative_e_distances) { if (this->config.use_relative_e_distances) {
gcode << "M83 ; use relative distances for extrusion\n"; gcode << "M83 ; use relative distances for extrusion\n";
} else { } else {
@ -72,11 +78,15 @@ std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, in
return ""; return "";
std::string code, comment; std::string code, comment;
if (wait && FLAVOR_IS_NOT(gcfTeacup)) { if (wait && FLAVOR_IS_NOT(gcfTeacup) && FLAVOR_IS_NOT(gcfRepRapFirmware)) {
code = "M109"; code = "M109";
comment = "set temperature and wait for it to be reached"; comment = "set temperature and wait for it to be reached";
} else { } else {
code = "M104"; if (FLAVOR_IS(gcfRepRapFirmware)) { // M104 is deprecated on RepRapFirmware
code = "G10";
} else {
code = "M104";
}
comment = "set temperature"; comment = "set temperature";
} }
@ -88,14 +98,17 @@ std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, in
gcode << "S"; gcode << "S";
} }
gcode << temperature; gcode << temperature;
if (tool != -1 && bool multiple_tools = this->multiple_extruders && ! m_single_extruder_multi_material;
( (this->multiple_extruders && ! m_single_extruder_multi_material) || if (tool != -1 && (multiple_tools || FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) ) {
FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) ) { if (FLAVOR_IS(gcfRepRapFirmware)) {
gcode << " T" << tool; gcode << " P" << tool;
} else {
gcode << " T" << tool;
}
} }
gcode << " ; " << comment << "\n"; gcode << " ; " << comment << "\n";
if (FLAVOR_IS(gcfTeacup) && wait) if ((FLAVOR_IS(gcfTeacup) || FLAVOR_IS(gcfRepRapFirmware)) && wait)
gcode << "M116 ; wait for temperature to be reached\n"; gcode << "M116 ; wait for temperature to be reached\n";
return gcode.str(); return gcode.str();

View file

@ -12,7 +12,6 @@
#include <CGAL/Exact_integer.h> #include <CGAL/Exact_integer.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h> #include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair.h> #include <CGAL/Polygon_mesh_processing/repair.h>
#include <CGAL/Polygon_mesh_processing/remesh.h> #include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h> #include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>

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