Merge branch 'master' into fs_CenterSupportForIsland
@ -35,15 +35,27 @@ option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||
|
||||
set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux")
|
||||
|
||||
set(IS_CROSS_COMPILE FALSE)
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_FIND_FRAMEWORK LAST)
|
||||
set(CMAKE_FIND_APPBUNDLE LAST)
|
||||
list(FIND CMAKE_OSX_ARCHITECTURES ${CMAKE_SYSTEM_PROCESSOR} _arch_idx)
|
||||
if (CMAKE_OSX_ARCHITECTURES AND _arch_idx LESS 0)
|
||||
set(IS_CROSS_COMPILE TRUE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Proposal for C++ unit tests and sandboxes
|
||||
option(SLIC3R_BUILD_SANDBOXES "Build development sandboxes" OFF)
|
||||
option(SLIC3R_BUILD_TESTS "Build unit tests" ON)
|
||||
|
||||
if (IS_CROSS_COMPILE)
|
||||
message("Detected cross compilation setup. Tests and encoding checks will be forcedly disabled!")
|
||||
set(SLIC3R_PERL_XS OFF CACHE BOOL "" FORCE)
|
||||
set(SLIC3R_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
endif ()
|
||||
|
||||
# Print out the SLIC3R_* cache options
|
||||
get_cmake_property(_cache_vars CACHE_VARIABLES)
|
||||
list (SORT _cache_vars)
|
||||
@ -80,12 +92,21 @@ if (MSVC)
|
||||
# Disable STL4007: Many result_type typedefs and all argument_type, first_argument_type, and second_argument_type typedefs are deprecated in C++17.
|
||||
#FIXME Remove this line after eigen library adapts to the new C++17 adaptor rules.
|
||||
add_compile_options(-D_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING)
|
||||
# Disable warnings on conversion from unsigned to signed (possible loss of data)
|
||||
# C4244: 'conversion' conversion from 'type1' to 'type2', possible loss of data. An integer type is converted to a smaller integer type.
|
||||
# C4267: The compiler detected a conversion from size_t to a smaller type.
|
||||
add_compile_options(/wd4244 /wd4267)
|
||||
endif ()
|
||||
|
||||
if (MINGW)
|
||||
add_compile_options(-Wa,-mbig-obj)
|
||||
endif ()
|
||||
|
||||
if (NOT MSVC)
|
||||
# ARMs (Raspberry PI) use an unsigned char by default. Let's make it consistent for PrusaSlicer on all platforms.
|
||||
add_compile_options(-fsigned-char)
|
||||
endif ()
|
||||
|
||||
# Display and check CMAKE_PREFIX_PATH
|
||||
message(STATUS "SLIC3R_STATIC: ${SLIC3R_STATIC}")
|
||||
if (NOT "${CMAKE_PREFIX_PATH}" STREQUAL "")
|
||||
@ -190,6 +211,13 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
|
||||
add_compile_options(-Wno-ignored-attributes) # Tamas: Eigen include dirs are marked as SYSTEM
|
||||
endif()
|
||||
|
||||
# Clang reports legacy OpenGL calls as deprecated. Turn off the warning for now
|
||||
# to reduce the clutter, we know about this one. It should be reenabled after
|
||||
# we finally get rid of the deprecated code.
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_compile_options(-Wno-deprecated-declarations)
|
||||
endif()
|
||||
|
||||
#GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
|
||||
@ -223,13 +251,16 @@ include_directories(${LIBDIR})
|
||||
# For generated header files
|
||||
include_directories(${LIBDIR_BIN}/platform)
|
||||
# For libslic3r.h
|
||||
include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition)
|
||||
include_directories(${LIBDIR}/clipper)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
|
||||
if(MSVC)
|
||||
# BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
|
||||
add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 -DBOOST_SYSTEM_USE_UTF8 )
|
||||
# Force the source code encoding to UTF-8. See PrusaSlicer GH pull request #5583
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
endif(MSVC)
|
||||
endif(WIN32)
|
||||
|
||||
@ -266,10 +297,9 @@ if(SLIC3R_STATIC)
|
||||
endif()
|
||||
#set(Boost_DEBUG ON)
|
||||
# set(Boost_COMPILER "-mgw81")
|
||||
if(NOT WIN32)
|
||||
# boost::process was introduced first in version 1.64.0
|
||||
set(MINIMUM_BOOST_VERSION "1.64.0")
|
||||
endif()
|
||||
# boost::process was introduced first in version 1.64.0,
|
||||
# boost::beast::detail::base64 was introduced first in version 1.66.0
|
||||
set(MINIMUM_BOOST_VERSION "1.66.0")
|
||||
set(_boost_components "system;filesystem;thread;log;locale;regex;chrono;atomic;date_time")
|
||||
find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS ${_boost_components})
|
||||
|
||||
|
@ -302,7 +302,7 @@ if(NOT TBB_FOUND)
|
||||
IMPORTED_LOCATION ${TBB_LIBRARIES})
|
||||
if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG)
|
||||
set_target_properties(TBB::tbb PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS};$<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:${TBB_DEFINITIONS_DEBUG}>;$<$<CONFIG:Release>:${TBB_DEFINITIONS_RELEASE}>"
|
||||
INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS};$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:${TBB_DEFINITIONS_RELEASE}>;$<$<CONFIG:Debug>:${TBB_DEFINITIONS_DEBUG}>"
|
||||
IMPORTED_LOCATION_DEBUG ${TBB_LIBRARIES_DEBUG}
|
||||
IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_RELEASE}
|
||||
IMPORTED_LOCATION_RELEASE ${TBB_LIBRARIES_RELEASE}
|
||||
|
@ -157,7 +157,9 @@ function(OPENVDB_ABI_VERSION_FROM_PRINT OPENVDB_PRINT)
|
||||
endif()
|
||||
|
||||
set(_OpenVDB_ABI)
|
||||
string(REGEX REPLACE ".*abi([0-9]*).*" "\\1" _OpenVDB_ABI ${_VDB_PRINT_VERSION_STRING})
|
||||
if (_VDB_PRINT_VERSION_STRING)
|
||||
string(REGEX REPLACE ".*abi([0-9]*).*" "\\1" _OpenVDB_ABI ${_VDB_PRINT_VERSION_STRING})
|
||||
endif ()
|
||||
if(${_OpenVDB_ABI} STREQUAL ${_VDB_PRINT_VERSION_STRING})
|
||||
set(_OpenVDB_ABI "")
|
||||
endif()
|
||||
|
1
deps/deps-linux.cmake
vendored
@ -26,6 +26,7 @@ ExternalProject_Add(dep_boost
|
||||
variant=release
|
||||
threading=multi
|
||||
boost.locale.icu=off
|
||||
--disable-icu
|
||||
cflags=-fPIC
|
||||
cxxflags=-fPIC
|
||||
install
|
||||
|
1
deps/deps-macos.cmake
vendored
@ -33,6 +33,7 @@ ExternalProject_Add(dep_boost
|
||||
variant=release
|
||||
threading=multi
|
||||
boost.locale.icu=off
|
||||
--disable-icu
|
||||
"cflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||
"cxxflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||
"mflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||
|
1
deps/deps-windows.cmake
vendored
@ -76,6 +76,7 @@ ExternalProject_Add(dep_boost
|
||||
variant=release
|
||||
threading=multi
|
||||
boost.locale.icu=off
|
||||
--disable-icu
|
||||
"${DEP_BOOST_DEBUG}" release install
|
||||
INSTALL_COMMAND "" # b2 does that already
|
||||
)
|
||||
|
@ -22,8 +22,6 @@
|
||||
* qhull: libqhull-dev does not contain libqhullcpp => link errors. Until it is fixed, we will use the builtin version. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925540
|
||||
* semver: One module C library, author expects to use clib for installation. No packages.
|
||||
* Shiny: no packages
|
||||
* poly2tree: Obsolete, candidate for removal
|
||||
* polypartition: Obsolete, candidate for removal
|
||||
|
||||
## Header only
|
||||
* igl
|
||||
|
@ -7,7 +7,7 @@ as the versions listed - generally versions available on conservative Linux dist
|
||||
|
||||
Perl is not required any more.
|
||||
|
||||
In a typical situation, one would open a command line, go to the PrusaSlicer sources, create a directory called `build` or similar,
|
||||
In a typical situation, one would open a command line, go to the PrusaSlicer sources (**the root directory of the repository**), create a directory called `build` or similar,
|
||||
`cd` into it and call:
|
||||
|
||||
cmake ..
|
||||
@ -37,7 +37,7 @@ To do this, go to the `deps` directory, create a `build` subdirectory (or the li
|
||||
where the target destdir is a directory of your choosing where the dependencies will be installed.
|
||||
You can also omit the `DESTDIR` option to use the default, in that case the `destdir` will be created inside the `build` directory where `cmake` is run.
|
||||
|
||||
To pass the destdir path to the top-level PrusaSlicer CMake script, use the `CMAKE_PREFIX_PATH` option along with turning on `SLIC3R_STATIC`:
|
||||
Once the dependencies have been built, in order to pass the destdir path to the **top-level** PrusaSlicer `CMakeLists.txt` script, use the `CMAKE_PREFIX_PATH` option along with turning on `SLIC3R_STATIC`:
|
||||
|
||||
cmake .. -DSLIC3R_STATIC=1 -DCMAKE_PREFIX_PATH=<path to destdir>/usr/local
|
||||
|
||||
|
@ -90,8 +90,9 @@ Works on a fresh installation of MacOS Catalina 10.15.6
|
||||
|
||||
- Enter:
|
||||
|
||||
```brew install cmake git gettext
|
||||
```
|
||||
brew update
|
||||
brew install cmake git gettext
|
||||
brew upgrade
|
||||
git clone https://github.com/prusa3d/PrusaSlicer/
|
||||
cd PrusaSlicer/deps
|
||||
@ -105,3 +106,4 @@ cd build
|
||||
cmake .. -DCMAKE_PREFIX_PATH="$PWD/../deps/build/destdir/usr/local"
|
||||
make
|
||||
src/prusa-slicer
|
||||
```
|
||||
|
@ -38,6 +38,8 @@ cd build
|
||||
cmake .. -G "Visual Studio 16 2019" -DCMAKE_PREFIX_PATH="c:\src\PrusaSlicer-deps\usr\local"
|
||||
```
|
||||
|
||||
Note that `CMAKE_PREFIX_PATH` must be absolute path. A relative path like "..\..\PrusaSlicer-deps\usr\local" does not work.
|
||||
|
||||
### Compile PrusaSlicer.
|
||||
|
||||
Double-click c:\src\PrusaSlicer\build\PrusaSlicer.sln to open in Visual Studio 2019.
|
||||
|
30
resources/icons/compare.svg
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, 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 id="compare_1_">
|
||||
<g id="compare">
|
||||
<path fill="#ED6B21" d="M7.87,2.23c-1.54-1.54-4.04-1.54-5.59,0s-1.54,4.04,0,5.59c1.43,1.43,3.69,1.53,5.24,0.31l1.33,1.33
|
||||
c0,0-0.33,0.33,0,0.66c0.33,0.33,3.29,3.29,3.29,3.29s0.33,0.33,0.66,0c0.33-0.33,0.66-0.66,0.66-0.66s0.33-0.33,0-0.66
|
||||
c-0.33-0.33-3.29-3.29-3.29-3.29c-0.33-0.33-0.66,0-0.66,0L8.18,7.47C9.41,5.92,9.3,3.67,7.87,2.23z M7.52,7.47
|
||||
c-1.35,1.35-3.54,1.35-4.89,0s-1.35-3.54,0-4.89s3.54-1.35,4.89,0S8.87,6.12,7.52,7.47z"/>
|
||||
</g>
|
||||
<path fill="#808080" d="M7.49,4.35C7.43,4.16,7.36,3.97,7.26,3.8l0.18-0.54L6.85,2.67L6.31,2.85c-0.17-0.1-0.36-0.17-0.56-0.23
|
||||
L5.5,2.11H4.66L4.41,2.62c-0.2,0.05-0.38,0.13-0.56,0.23L3.31,2.67L2.72,3.26L2.9,3.8C2.8,3.97,2.72,4.16,2.67,4.35L2.16,4.61v0.83
|
||||
L2.67,5.7C2.72,5.9,2.8,6.08,2.9,6.26L2.72,6.8l0.59,0.59l0.54-0.18c0.17,0.1,0.36,0.17,0.56,0.23l0.26,0.51H5.5l0.26-0.51
|
||||
c0.2-0.05,0.38-0.13,0.56-0.23l0.54,0.18L7.44,6.8L7.26,6.26C7.36,6.08,7.43,5.9,7.49,5.7L8,5.45V4.61L7.49,4.35z M5.08,6.33
|
||||
c-0.72,0-1.3-0.58-1.3-1.3c0-0.72,0.58-1.3,1.3-1.3s1.3,0.58,1.3,1.3C6.38,5.75,5.8,6.33,5.08,6.33z"/>
|
||||
<path fill="#808080" d="M14.56,4.45c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51l-0.46,0.15c-0.15-0.08-0.31-0.15-0.48-0.2
|
||||
l-0.22-0.44h-0.71l-0.22,0.44c-0.17,0.05-0.33,0.11-0.48,0.2l-0.46-0.15l-0.51,0.51l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48
|
||||
L10,4.67v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48l-0.15,0.46l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44
|
||||
h0.71l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15l0.51-0.51l-0.15-0.46c0.08-0.15,0.15-0.31,0.2-0.48L15,5.39V4.67
|
||||
L14.56,4.45z M12.5,6.14c-0.62,0-1.11-0.5-1.11-1.11c0-0.62,0.5-1.11,1.11-1.11s1.11,0.5,1.11,1.11
|
||||
C13.61,5.64,13.11,6.14,12.5,6.14z"/>
|
||||
<path fill="#808080" d="M7.14,11.91c-0.05-0.17-0.11-0.33-0.2-0.48l0.15-0.46l-0.51-0.51l-0.46,0.15c-0.15-0.08-0.31-0.15-0.48-0.2
|
||||
L5.44,9.99H4.72L4.5,10.43c-0.17,0.05-0.33,0.11-0.48,0.2l-0.46-0.15l-0.51,0.51l0.15,0.46c-0.08,0.15-0.15,0.31-0.2,0.48
|
||||
l-0.44,0.22v0.71l0.44,0.22c0.05,0.17,0.11,0.33,0.2,0.48L3.06,14l0.51,0.51l0.46-0.15c0.15,0.08,0.31,0.15,0.48,0.2l0.22,0.44
|
||||
h0.71l0.22-0.44c0.17-0.05,0.33-0.11,0.48-0.2l0.46,0.15L7.1,14l-0.15-0.46c0.08-0.15,0.15-0.31,0.2-0.48l0.44-0.22v-0.71
|
||||
L7.14,11.91z M5.08,13.6c-0.62,0-1.11-0.5-1.11-1.11c0-0.62,0.5-1.11,1.11-1.11s1.11,0.5,1.11,1.11C6.19,13.11,5.69,13.6,5.08,13.6
|
||||
z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
15
resources/icons/equal.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="121.805px" height="121.805px" viewBox="0 0 121.805 121.805" style="enable-background:new 0 0 121.805 121.805;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#808080" d="M7.308,85.264h107.188c4.037,0,7.309-3.271,7.309-7.31s-3.271-7.309-7.309-7.309H7.308C3.271,70.646,0,73.916,0,77.954
|
||||
S3.271,85.264,7.308,85.264z"/>
|
||||
<path fill="#808080" d="M7.308,51.158h107.188c4.037,0,7.309-3.272,7.309-7.309c0-4.037-3.271-7.308-7.309-7.308H7.308
|
||||
C3.271,36.541,0,39.812,0,43.849C0,47.886,3.271,51.158,7.308,51.158z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 901 B |
16
resources/icons/not_equal.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="121.807px" height="121.807px" viewBox="0 0 121.807 121.807" style="enable-background:new 0 0 121.807 121.807;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M7.308,75.519C3.271,75.519,0,78.789,0,82.827c0,4.036,3.271,7.31,7.308,7.31h18.897l-3.496,3.495
|
||||
c-2.855,2.854-2.855,7.48,0,10.337c1.428,1.427,3.299,2.141,5.167,2.141c1.869,0,3.74-0.714,5.167-2.139l13.833-13.834h67.621
|
||||
c4.037,0,7.31-3.272,7.31-7.31s-3.271-7.309-7.31-7.309H61.495L80.982,56.03h33.515c4.037,0,7.31-3.272,7.31-7.308
|
||||
c0-4.037-3.271-7.309-7.31-7.309H95.602l13.24-13.24c2.854-2.855,2.854-7.481,0-10.336c-2.855-2.855-7.479-2.853-10.334,0
|
||||
L74.932,41.414H7.308C3.271,41.414,0,44.685,0,48.723c0,4.036,3.271,7.308,7.308,7.308H60.31L40.821,75.519H7.308z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -8,15 +8,15 @@ msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-01-09 15:30+0700\n"
|
||||
"PO-Revision-Date: 2021-01-10 02:38+0700\n"
|
||||
"PO-Revision-Date: 2021-02-03 14:06+0100\n"
|
||||
"Language-Team: Andylg <andylg@yandex.ru>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && "
|
||||
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Poedit 1.8.7\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n"
|
||||
"%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"Last-Translator: Oleksandra Iushchenko <yusanka@gmail.com>\n"
|
||||
"Language: ru_RU\n"
|
||||
|
||||
#: src/slic3r/GUI/AboutDialog.cpp:45 src/slic3r/GUI/AboutDialog.cpp:299
|
||||
@ -394,7 +394,6 @@ msgid "First layer height"
|
||||
msgstr "Высота первого слоя"
|
||||
|
||||
#: src/slic3r/GUI/ConfigManipulation.cpp:81
|
||||
#, c-format
|
||||
msgid ""
|
||||
"The Spiral Vase mode requires:\n"
|
||||
"- one perimeter\n"
|
||||
@ -410,7 +409,7 @@ msgstr ""
|
||||
"- отсутствие верхних сплошных слоёв\n"
|
||||
"- плотность заполнения 0%\n"
|
||||
"- отсутствие поддержки\n"
|
||||
"- отключено \"Обеспечивать вертикальную толщину оболочки\"\n"
|
||||
"- включено \"Обеспечивать вертикальную толщину оболочки\"\n"
|
||||
"- отключено \"Обнаружение тонких стенок\""
|
||||
|
||||
#: src/slic3r/GUI/ConfigManipulation.cpp:89
|
||||
@ -432,7 +431,7 @@ msgstr ""
|
||||
"только в том случае, если она печатается текущим экструдером, без запуска\n"
|
||||
"смены инструмента. (Значения \"Экструдер, печатающий поддержки/подложки/юбки\"\n"
|
||||
"и \"Экструдер, печатающий связующий слой поддержки/подложки\" должны быть\n"
|
||||
"установлены в 0).\""
|
||||
"установлены в 0)."
|
||||
|
||||
#: src/slic3r/GUI/ConfigManipulation.cpp:119
|
||||
msgid "Shall I adjust those settings in order to enable the Wipe Tower?"
|
||||
@ -546,7 +545,7 @@ msgstr "пруток"
|
||||
|
||||
#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:59 src/libslic3r/Preset.cpp:1300
|
||||
msgid "SLA print"
|
||||
msgstr "Профиль SLA печати:"
|
||||
msgstr "Профиль SLA печати"
|
||||
|
||||
#: src/slic3r/GUI/ConfigSnapshotDialog.cpp:60 src/slic3r/GUI/Plater.cpp:696
|
||||
#: src/libslic3r/Preset.cpp:1301
|
||||
@ -1070,7 +1069,7 @@ msgstr ""
|
||||
|
||||
#: src/slic3r/GUI/DoubleSlider.cpp:1241
|
||||
msgid "Edit current color - Right click the colored slider segment"
|
||||
msgstr "Изменить текущий цвет - Правая кнопка мыши по цветному сегменту ползунка ???"
|
||||
msgstr "Изменить текущий цвет - Правая кнопка мыши по цветному сегменту ползунка"
|
||||
|
||||
#: src/slic3r/GUI/DoubleSlider.cpp:1251
|
||||
msgid "Print mode"
|
||||
@ -2238,7 +2237,7 @@ msgstr "Ctrl + Колесо мыши"
|
||||
|
||||
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:233
|
||||
msgid "Autoset custom supports"
|
||||
msgstr "Автоустановка пользовательских поддержек ???"
|
||||
msgstr "Автоустановка пользовательских поддержек"
|
||||
|
||||
#: src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp:235
|
||||
msgid "Threshold:"
|
||||
@ -2344,7 +2343,7 @@ msgstr "Поворот"
|
||||
#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:547
|
||||
#: src/slic3r/GUI/GUI_ObjectManipulation.cpp:563 src/libslic3r/PrintConfig.cpp:3754
|
||||
msgid "Scale"
|
||||
msgstr "Масштаб "
|
||||
msgstr "Масштаб"
|
||||
|
||||
#: src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp:30
|
||||
#: src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp:381
|
||||
@ -2712,7 +2711,7 @@ msgid ""
|
||||
"Note: This name can be changed later from the physical printers settings"
|
||||
msgstr ""
|
||||
"При создании новых принтеров они будут именоваться как \"Принтер N\".\n"
|
||||
"Примечание: это имя можно изменить позже в настройках физических принтеров."
|
||||
"Примечание: это имя можно изменить позже в настройках физических принтеров"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1124 src/slic3r/GUI/PhysicalPrinterDialog.cpp:626
|
||||
msgid "Information"
|
||||
@ -2875,7 +2874,7 @@ msgstr "&Настройки"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1781
|
||||
msgid "The preset(s) modifications are successfully saved"
|
||||
msgstr "Изменения в профиле(-ях) успешно сохранены."
|
||||
msgstr "Изменения в профиле(-ях) успешно сохранены"
|
||||
|
||||
#: src/slic3r/GUI/GUI_App.cpp:1802
|
||||
msgid "The uploads are still ongoing"
|
||||
@ -3459,7 +3458,7 @@ msgstr "Неподдерживаемый выбор"
|
||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:4012
|
||||
#, c-format
|
||||
msgid "You started your selection with %s Item."
|
||||
msgstr "Вы начали свой выбор с сущности %s"
|
||||
msgstr "Вы начали свой выбор с сущности %s."
|
||||
|
||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:4013
|
||||
#, c-format
|
||||
@ -3477,7 +3476,7 @@ msgstr "Информация"
|
||||
|
||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:4137
|
||||
msgid "You can't change a type of the last solid part of the object."
|
||||
msgstr "Вы не можете изменить тип последнего твердотельного элемента модели"
|
||||
msgstr "Вы не можете изменить тип последнего твердотельного элемента модели."
|
||||
|
||||
#: src/slic3r/GUI/GUI_ObjectList.cpp:4142
|
||||
msgid "Modifier"
|
||||
@ -3794,7 +3793,7 @@ msgstr "ОШИБКА: недостаточно ресурсов для выпо
|
||||
|
||||
#: src/slic3r/GUI/Jobs/RotoptimizeJob.cpp:41
|
||||
msgid "Searching for optimal orientation"
|
||||
msgstr "Поиск оптимального положения."
|
||||
msgstr "Поиск оптимального положения"
|
||||
|
||||
#: src/slic3r/GUI/Jobs/RotoptimizeJob.cpp:73
|
||||
msgid "Orientation search canceled."
|
||||
@ -3850,7 +3849,7 @@ msgstr "Импорт завершён."
|
||||
|
||||
#: src/slic3r/GUI/Jobs/SLAImportJob.cpp:208 src/slic3r/GUI/Plater.cpp:2357
|
||||
msgid "You cannot load SLA project with a multi-part object on the bed"
|
||||
msgstr "Вы не можете загрузить SLA проект с составной моделью на столе."
|
||||
msgstr "Вы не можете загрузить SLA проект с составной моделью на столе"
|
||||
|
||||
#: src/slic3r/GUI/Jobs/SLAImportJob.cpp:209 src/slic3r/GUI/Plater.cpp:2358
|
||||
#: src/slic3r/GUI/Tab.cpp:3243
|
||||
@ -5114,7 +5113,7 @@ msgstr ""
|
||||
#: src/slic3r/GUI/NotificationManager.cpp:490
|
||||
#: src/slic3r/GUI/NotificationManager.cpp:500
|
||||
msgid "More"
|
||||
msgstr "Подробнее."
|
||||
msgstr "Подробнее"
|
||||
|
||||
#: src/slic3r/GUI/NotificationManager.cpp:864
|
||||
#: src/slic3r/GUI/NotificationManager.cpp:1141
|
||||
@ -9314,7 +9313,6 @@ msgid "Extra perimeters if needed"
|
||||
msgstr "Дополнительные периметры при необходимости"
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:539
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Add more perimeters when needed for avoiding gaps in sloping walls. Slic3r keeps "
|
||||
"adding perimeters, until more than 70% of the loop immediately above is supported."
|
||||
@ -10365,7 +10363,6 @@ msgid "This setting represents the maximum speed of your fan."
|
||||
msgstr "Этот параметр регулирует максимальную скорость вращения вентилятора."
|
||||
|
||||
#: src/libslic3r/PrintConfig.cpp:1435
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This is the highest printable layer height for this extruder, used to cap the "
|
||||
"variable layer height and support layer height. Maximum recommended layer height is "
|
||||
|
@ -1,8 +1,10 @@
|
||||
min_slic3r_version = 2.3.0-beta2
|
||||
0.0.8 Updated start and end g-code for Anycubic Mega.
|
||||
0.0.7 Updated start g-code for Anycubic Mega.
|
||||
0.0.6 Reduced max print height for Predator. Updated end g-code, before layer change g-code and output filename format for Kossel.
|
||||
0.0.5 Updated end g-code.
|
||||
min_slic3r_version = 2.3.0-alpha2
|
||||
0.0.4 Fixed predator output filaname format, infill overlap.
|
||||
0.0.4 Fixed predator output filename format, infill overlap, start gcode adjustments.
|
||||
0.0.3 Fixed infill_overlap, start_gcode, end_gcode for Anycubic Predator
|
||||
0.0.2 Added Anycubic Predator
|
||||
min_slic3r_version = 2.3.0-alpha0
|
||||
|
@ -5,7 +5,7 @@
|
||||
name = Anycubic
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.0.6
|
||||
config_version = 0.0.8
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -1051,7 +1051,7 @@ before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]
|
||||
default_filament_profile = Generic PLA @MEGA
|
||||
default_print_profile = 0.15mm QUALITY @MEGA
|
||||
deretract_speed = 50
|
||||
end_gcode = G4 ; wait\nG92 E0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-35 F1000 ; move print head up & retract filament\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
end_gcode = G4 ; wait\nG92 E0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} ; move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors
|
||||
extruder_colour = #808080
|
||||
gcode_flavor = marlin
|
||||
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
||||
@ -1063,7 +1063,7 @@ retract_length = 6
|
||||
retract_lift = 0.075
|
||||
retract_lift_below = 204
|
||||
silent_mode = 0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y0 Z1 F100 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0\nG1 E38 F1000; deretract filament\nG92 E0\nG1 X60 Z0 E9 ; intro line\nG1 X100 E12.5 ; intro line\nG92 E0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y0 Z1 F100 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0\nG1 Z0.2 F360\nG1 X60 E9 F700 ; intro line\nG1 X100 E12.5 F700 ; intro line\nG92 E0
|
||||
use_relative_e_distances = 1
|
||||
wipe = 1
|
||||
machine_max_acceleration_e = 5000
|
||||
|
2
resources/profiles/Artillery.idx
Normal file
@ -0,0 +1,2 @@
|
||||
min_slic3r_version = 2.3.0
|
||||
0.0.1 Initial Artillery bundle
|
477
resources/profiles/Artillery.ini
Normal file
@ -0,0 +1,477 @@
|
||||
###############
|
||||
# AUTHOR: Szabolcs Hornyak / design85@gmail.com
|
||||
# https://szabolcs.eu/2020/12/29/prusaslicer-sw-x1-genius/
|
||||
# Tested with PrusaSlicer 2.2, 2.3
|
||||
###############
|
||||
|
||||
# Print profiles for the Artillery printers.
|
||||
|
||||
[vendor]
|
||||
# Vendor name will be shown by the Config Wizard.
|
||||
name = Artillery
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.0.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Artillery/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
|
||||
# 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.
|
||||
# Printer model name will be shown by the installation wizard.
|
||||
|
||||
#############
|
||||
## PRINTER ##
|
||||
#############
|
||||
|
||||
[printer_model:X1]
|
||||
name = Sidewinder X1
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
bed_model = bed-x1.stl
|
||||
bed_texture = bed-x1.png
|
||||
default_materials = Generic PLA @Artillery; Generic ABS @Artillery; Generic PETG @Artillery; Generic TPU @Artillery
|
||||
|
||||
[printer_model:Genius]
|
||||
name = Genius
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
bed_model = bed-genius.stl
|
||||
bed_texture = bed-genius.png
|
||||
default_materials = Generic PLA @Artillery; Generic ABS @Artillery; Generic PETG @Artillery; Generic TPU @Artillery
|
||||
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0
|
||||
between_objects_gcode =
|
||||
cooling_tube_length = 5
|
||||
cooling_tube_retraction = 91.5
|
||||
default_filament_profile = Generic PLA @Artillery
|
||||
default_print_profile = 0.20mm NORMAL @Artillery
|
||||
deretract_speed = 0
|
||||
extruder_colour = #FFFF00
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
||||
machine_max_acceleration_e = 5000,5000
|
||||
machine_max_acceleration_extruding = 1250,1250
|
||||
machine_max_acceleration_retracting = 1250,1250
|
||||
machine_max_acceleration_x = 1000,960
|
||||
machine_max_acceleration_y = 1000,960
|
||||
machine_max_acceleration_z = 1000,1000
|
||||
machine_max_feedrate_e = 120,120
|
||||
machine_max_feedrate_x = 200,100
|
||||
machine_max_feedrate_y = 200,100
|
||||
machine_max_feedrate_z = 12,12
|
||||
machine_max_jerk_e = 1.5,1.5
|
||||
machine_max_jerk_x = 8,8
|
||||
machine_max_jerk_y = 8,8
|
||||
machine_max_jerk_z = 0.4,0.4
|
||||
machine_min_extruding_rate = 0,0
|
||||
machine_min_travel_rate = 0,0
|
||||
max_layer_height = 0.25
|
||||
max_print_height = 250
|
||||
min_layer_height = 0.07
|
||||
nozzle_diameter = 0.4
|
||||
pause_print_gcode =
|
||||
printer_technology = FFF
|
||||
remaining_times = 0
|
||||
retract_before_travel = 1
|
||||
retract_before_wipe = 0%
|
||||
retract_layer_change = 1
|
||||
retract_length = 1.9
|
||||
retract_length_toolchange = 4
|
||||
retract_lift = 0.6
|
||||
retract_lift_above = 0
|
||||
retract_lift_below = 380
|
||||
retract_restart_extra = 0
|
||||
retract_restart_extra_toolchange = 0
|
||||
retract_speed = 35
|
||||
silent_mode = 0
|
||||
single_extruder_multi_material = 0
|
||||
toolchange_gcode =
|
||||
use_firmware_retraction = 0
|
||||
use_relative_e_distances = 1
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 1
|
||||
wipe = 1
|
||||
z_offset = 0
|
||||
end_gcode = G4 ; wait\nG92 E0 ; prepare to retract\nG1 E-0.5 F3000; retract to avoid stringing\n\n; Anti-stringing end wiggle\nG91 ; use relative coordinates\nG1 X1 Y1 F1200\n\n; Raise nozzle and present bed\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+120, max_print_height)}{endif} ; Move print head up\nG90 ; use absolute coordinates\n\n; Reset print setting overrides\nM200 D0 ; disable volumetric e\nM220 S100 ; reset speed factor to 100%\nM221 S100 ; reset extrusion rate to 100%\n\n; Shut down printer\nM106 S0 ; turn-off fan\nM104 S0 ; turn-off hotend\nM140 S0 ; turn-off bed\nM150 P0 ; turn off led\nM85 S0 ; deactivate idle timeout\nM84 ; disable motors\n
|
||||
|
||||
[printer:*common_STOCK_FW*]
|
||||
inherits = *common*
|
||||
start_gcode = ; Initial setups\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM900 W[extrusion_width] H[layer_height] D[filament_diameter]\nM200 D0 ; disable volumetric e\nM220 S100 ; reset speed factor to 100%\nM221 S100 ; reset extrusion rate to 100%\n\n; Set the heating\nM190 S[first_layer_bed_temperature]; wait for bed to heat up\nM104 S[first_layer_temperature]; start nozzle heating but don't wait\n\n; Home\nG1 Z3 F3000 ; move z up little to prevent scratching of surface\nG28 ; home all axes\nG1 X3 Y3 F5000 ; move to corner of the bed to avoid ooze over centre\n\n; Wait for final heating\nM109 S[first_layer_temperature] ; wait for the nozzle to heat up\nM190 S[first_layer_bed_temperature] ; wait for the bed to heat up\n\n; Return to prime position, Prime line routine\nG92 E0 ; Reset Extruder\nG1 Z3 F3000 ; move z up little to prevent scratching of surface\nG1 X10 Y.5 Z0.25 F5000.0 ; Move to start position\nG1 X100 Y.5 Z0.25 F1500.0 E15 ; Draw the first line\nG1 X100 Y.2 Z0.25 F5000.0 ; Move to side a little\nG1 X10 Y.2 Z0.25 F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:*common_UPD_FW*]
|
||||
inherits = *common*
|
||||
start_gcode = ; Initial setups\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM900 K0.12; K factor\nM900 W[extrusion_width] H[layer_height] D[filament_diameter]\nM200 D0 ; disable volumetric e\nM220 S100 ; reset speed factor to 100%\nM221 S100 ; reset extrusion rate to 100%\n\n; Set the heating\nM190 S[first_layer_bed_temperature]; wait for bed to heat up\nM104 S[first_layer_temperature]; start nozzle heating but don't wait\n\n; Home\nG1 Z3 F3000 ; move z up little to prevent scratching of surface\nG28 ; home all axes\nG1 X3 Y3 F5000 ; move to corner of the bed to avoid ooze over centre\n\n; Wait for final heating\nM109 S[first_layer_temperature] ; wait for the nozzle to heat up\nM190 S[first_layer_bed_temperature] ; wait for the bed to heat up\n\n;Auto bed Leveling\n@BEDLEVELVISUALIZER\nG29 ; ABL T\nM420 S1 Z3 ; reload and fade mesh bed leveling until it reach 3mm Z\n\n; Return to prime position, Prime line routine\nG92 E0 ; Reset Extruder\nG1 Z3 F3000 ; move z up little to prevent scratching of surface\nG1 X10 Y.5 Z0.25 F5000.0 ; Move to start position\nG1 X100 Y.5 Z0.25 F1500.0 E15 ; Draw the first line\nG1 X100 Y.2 Z0.25 F5000.0 ; Move to side a little\nG1 X10 Y.2 Z0.25 F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Sidewinder X1]
|
||||
inherits = *common_STOCK_FW*
|
||||
printer_model = X1
|
||||
printer_variant = 0.4
|
||||
bed_shape = 0x0,300x0,300x300,0x300
|
||||
max_print_height = 400
|
||||
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_Artillery\nPRINTER_MODEL_X1
|
||||
|
||||
[printer:Sidewinder X1 BL-TOUCH]
|
||||
inherits = *common_UPD_FW*
|
||||
printer_model = X1
|
||||
printer_variant = 0.4
|
||||
bed_shape = 0x0,300x0,300x300,0x300
|
||||
max_print_height = 400
|
||||
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_Artillery\nPRINTER_MODEL_X1
|
||||
|
||||
[printer:Genius]
|
||||
inherits = *common_STOCK_FW*
|
||||
printer_model = Genius
|
||||
printer_variant = 0.4
|
||||
bed_shape = 0x0,230x0,230x230,0x230
|
||||
max_print_height = 250
|
||||
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_Artillery\nPRINTER_MODEL_Genius
|
||||
|
||||
[printer:Genius BL-TOUCH]
|
||||
inherits = *common_UPD_FW*
|
||||
printer_model = Genius
|
||||
printer_variant = 0.4
|
||||
bed_shape = 0x0,230x0,230x230,0x230
|
||||
max_print_height = 250
|
||||
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_Artillery\nPRINTER_MODEL_Genius
|
||||
|
||||
###########
|
||||
## PRINT ##
|
||||
###########
|
||||
# Common print preset
|
||||
[print:*common*]
|
||||
# V2.2 #
|
||||
#bottom_fill_pattern = rectilinear
|
||||
#top_fill_pattern = rectilinear
|
||||
#fill_pattern = cubic
|
||||
# V2.3 #
|
||||
top_fill_pattern = monotonic
|
||||
bottom_fill_pattern = monotonic
|
||||
fill_pattern = adaptivecubic
|
||||
|
||||
avoid_crossing_perimeters = 0
|
||||
bridge_acceleration = 1000
|
||||
bridge_angle = 0
|
||||
bridge_flow_ratio = 0.78
|
||||
bridge_speed = 20
|
||||
# brim_width = 5
|
||||
bottom_solid_min_thickness = 1.2
|
||||
clip_multipart_objects = 1
|
||||
compatible_printers =
|
||||
complete_objects = 0
|
||||
default_acceleration = 1000
|
||||
dont_support_bridges = 1
|
||||
elefant_foot_compensation = 0
|
||||
ensure_vertical_shell_thickness = 1
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
external_perimeter_speed = 25
|
||||
external_perimeters_first = 0
|
||||
extra_perimeters = 0
|
||||
extruder_clearance_height = 25
|
||||
extruder_clearance_radius = 45
|
||||
extrusion_width = 0.45
|
||||
fill_angle = 45
|
||||
fill_density = 15%
|
||||
first_layer_acceleration = 500
|
||||
first_layer_extrusion_width = 0.42
|
||||
first_layer_height = 150%
|
||||
first_layer_speed = 20
|
||||
gap_fill_speed = 30
|
||||
gcode_comments = 1
|
||||
gcode_label_objects = 1
|
||||
infill_acceleration = 1000
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_extrusion_width = 0.45
|
||||
infill_first = 0
|
||||
infill_only_where_needed = 0
|
||||
infill_overlap = 25%
|
||||
infill_speed = 50
|
||||
interface_shells = 0
|
||||
max_print_speed = 150
|
||||
max_volumetric_extrusion_rate_slope_negative = 0
|
||||
max_volumetric_extrusion_rate_slope_positive = 0
|
||||
max_volumetric_speed = 0
|
||||
min_skirt_length = 4
|
||||
notes =
|
||||
overhangs = 1
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode
|
||||
perimeters = 3
|
||||
perimeter_acceleration = 800
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0
|
||||
perimeter_speed = 45
|
||||
post_process =
|
||||
print_settings_id =
|
||||
raft_layers = 0
|
||||
resolution = 0
|
||||
seam_position = nearest
|
||||
single_extruder_multi_material_priming = 0
|
||||
skirts = 1
|
||||
skirt_distance = 6
|
||||
skirt_height = 1
|
||||
small_perimeter_speed = 25
|
||||
solid_infill_below_area = 0
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_extrusion_width = 0.45
|
||||
solid_infill_speed = 50
|
||||
spiral_vase = 0
|
||||
standby_temperature_delta = -5
|
||||
support_material = 0
|
||||
support_material_extruder = 0
|
||||
support_material_extrusion_width = 0.35
|
||||
support_material_interface_extruder = 0
|
||||
support_material_angle = 0
|
||||
support_material_buildplate_only = 0
|
||||
support_material_enforce_layers = 0
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_interface_spacing = 0.2
|
||||
support_material_interface_speed = 100%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2
|
||||
support_material_speed = 50
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 55
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 50%
|
||||
thin_walls = 1
|
||||
travel_speed = 130
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_infill_speed = 30
|
||||
wipe_tower = 0
|
||||
wipe_tower_bridging = 10
|
||||
wipe_tower_rotation_angle = 0
|
||||
wipe_tower_width = 60
|
||||
wipe_tower_x = 170
|
||||
wipe_tower_y = 125
|
||||
xy_size_compensation = 0
|
||||
|
||||
[print:*0.08mm*]
|
||||
inherits = *common*
|
||||
default_acceleration = 500
|
||||
layer_height = 0.08
|
||||
perimeters = 3
|
||||
bottom_solid_layers = 9
|
||||
top_solid_layers = 11
|
||||
|
||||
[print:*0.10mm*]
|
||||
inherits = *common*
|
||||
default_acceleration = 500
|
||||
layer_height = 0.1
|
||||
perimeters = 3
|
||||
bottom_solid_layers = 7
|
||||
top_solid_layers = 9
|
||||
|
||||
[print:*0.12mm*]
|
||||
inherits = *common*
|
||||
default_acceleration = 500
|
||||
layer_height = 0.12
|
||||
perimeters = 3
|
||||
bottom_solid_layers = 6
|
||||
top_solid_layers = 7
|
||||
|
||||
[print:*0.16mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.16
|
||||
bottom_solid_layers = 5
|
||||
top_solid_layers = 7
|
||||
|
||||
[print:*0.20mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.20
|
||||
bottom_solid_layers = 4
|
||||
top_solid_layers = 5
|
||||
|
||||
[print:*0.24mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.24
|
||||
top_infill_extrusion_width = 0.45
|
||||
bottom_solid_layers = 3
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:*0.28mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.28
|
||||
top_infill_extrusion_width = 0.45
|
||||
first_layer_extrusion_width = 0.75
|
||||
bottom_solid_layers = 3
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:0.08mm SUPERDETAIL @Artillery]
|
||||
inherits = *0.08mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.10mm HIGHDETAIL @Artillery]
|
||||
inherits = *0.10mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.12mm DETAIL @Artillery]
|
||||
inherits = *0.12mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.16mm OPTIMAL @Artillery]
|
||||
inherits = *0.16mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.20mm SLOW @Artillery]
|
||||
inherits = *0.20mm*
|
||||
external_perimeter_speed = 15
|
||||
fill_density = 20%
|
||||
gap_fill_speed = 25
|
||||
infill_speed = 50
|
||||
perimeter_speed = 30
|
||||
perimeters = 3
|
||||
solid_infill_speed = 50
|
||||
top_solid_infill_speed = 25
|
||||
first_layer_speed = 15
|
||||
travel_speed = 100
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.20mm NORMAL @Artillery]
|
||||
inherits = *0.20mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.20mm SPEED @Artillery]
|
||||
inherits = *0.20mm*
|
||||
external_perimeter_speed = 35
|
||||
fill_density = 15%
|
||||
fill_pattern = grid
|
||||
gap_fill_speed = 45
|
||||
infill_speed = 150
|
||||
infill_only_where_needed = 1
|
||||
perimeter_speed = 60
|
||||
perimeters = 2
|
||||
solid_infill_speed = 150
|
||||
top_solid_infill_speed = 50
|
||||
travel_speed = 170
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.24mm DRAFT @Artillery]
|
||||
inherits = *0.24mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.28mm SUPERDRAFT @Artillery]
|
||||
inherits = *0.28mm*
|
||||
compatible_printers_condition = printer_model=~/(X1|Genius).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
###############
|
||||
## FILAMENTS ##
|
||||
###############
|
||||
|
||||
# Common filament preset
|
||||
[filament:*common*]
|
||||
cooling = 1
|
||||
compatible_printers =
|
||||
extrusion_multiplier = 1
|
||||
filament_cost = 0
|
||||
filament_density = 0
|
||||
filament_diameter = 1.75
|
||||
filament_notes = ""
|
||||
filament_settings_id = ""
|
||||
filament_soluble = 0
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 15
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Artillery.*/
|
||||
|
||||
[filament:*PLA*]
|
||||
inherits = *common*
|
||||
bed_temperature = 60
|
||||
bridge_fan_speed = 100
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 1
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #428AF5
|
||||
filament_cost = 20
|
||||
filament_density = 1.24
|
||||
filament_max_volumetric_speed = 15
|
||||
filament_type = PLA
|
||||
first_layer_bed_temperature = 65
|
||||
first_layer_temperature = 210
|
||||
full_fan_speed_layer = 3
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
temperature = 205
|
||||
|
||||
[filament:*PET*]
|
||||
inherits = *common*
|
||||
bed_temperature = 70
|
||||
bridge_fan_speed = 100
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 3
|
||||
fan_always_on = 1
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #42E9F5
|
||||
filament_cost = 30
|
||||
filament_density = 1.27
|
||||
filament_max_volumetric_speed = 8
|
||||
filament_type = PETG
|
||||
first_layer_bed_temperature = 70
|
||||
first_layer_temperature = 235
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 20
|
||||
temperature = 230
|
||||
|
||||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
bed_temperature = 90
|
||||
bridge_fan_speed = 30
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 3
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #6603FC
|
||||
filament_cost = 20
|
||||
filament_density = 1.04
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_type = ABS
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 240
|
||||
max_fan_speed = 0
|
||||
min_fan_speed = 0
|
||||
temperature = 240
|
||||
top_fan_speed = 0
|
||||
|
||||
[filament:*TPU*]
|
||||
inherits = *common*
|
||||
bed_temperature = 55
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 3
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #CFFFFB
|
||||
filament_cost = 30
|
||||
filament_density = 1.2
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_retract_before_travel = 4
|
||||
filament_retract_length = 2.5
|
||||
filament_retract_speed = 30
|
||||
filament_type = TPU
|
||||
first_layer_bed_temperature = 55
|
||||
first_layer_temperature = 210
|
||||
max_fan_speed = 70
|
||||
min_fan_speed = 0
|
||||
|
||||
[filament:Generic PLA @Artillery]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Generic PETG @Artillery]
|
||||
inherits = *PET*
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Generic ABS @Artillery]
|
||||
inherits = *ABS*
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Generic TPU @Artillery]
|
||||
inherits = *TPU*
|
||||
filament_vendor = Generic
|
BIN
resources/profiles/Artillery/bed-genius.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
resources/profiles/Artillery/bed-genius.stl
Normal file
BIN
resources/profiles/Artillery/bed-x1.png
Normal file
After Width: | Height: | Size: 4.3 MiB |
BIN
resources/profiles/Artillery/bed-x1.stl
Normal file
BIN
resources/profiles/Artillery/genius_thumbnail.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
resources/profiles/Artillery/x1_thumbnail.png
Normal file
After Width: | Height: | Size: 36 KiB |
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.3.0-rc2
|
||||
0.0.14 Optimized start g-code. Added filament profile. Various improvements.
|
||||
0.0.13 Optimized start and end g-code. General improvements.
|
||||
0.0.12 Added Ender-3V2 and filament profiles.
|
||||
min_slic3r_version = 2.3.0-beta2
|
||||
|
@ -5,7 +5,7 @@
|
||||
name = Creality
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 0.0.13
|
||||
config_version = 0.0.14
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Creality/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -23,15 +23,6 @@ bed_model = ender3_bed.stl
|
||||
bed_texture = ender3.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:ENDER3V2]
|
||||
name = Creality Ender-3 V2
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
family = ENDER
|
||||
bed_model = ender3_bed.stl
|
||||
bed_texture = ender3.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:ENDER3BLTOUCH]
|
||||
name = Creality Ender-3 BLTouch
|
||||
variants = 0.4
|
||||
@ -41,6 +32,33 @@ bed_model = ender3_bed.stl
|
||||
bed_texture = ender3.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:ENDER3V2]
|
||||
name = Creality Ender-3 V2
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
family = ENDER
|
||||
bed_model = ender3v2_bed.stl
|
||||
bed_texture = ender3v2.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:ENDER3MAX]
|
||||
#name = Creality Ender-3 Max
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = ENDER
|
||||
#bed_model = cr10v2_bed.stl
|
||||
#bed_texture = cr10spro.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:ENDER4]
|
||||
#name = Creality Ender-4
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = ENDER
|
||||
#bed_model = ender3v2_bed.stl
|
||||
#bed_texture = ender3v2.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:ENDER5]
|
||||
name = Creality Ender-5
|
||||
variants = 0.4
|
||||
@ -59,6 +77,15 @@ bed_model = ender5plus_bed.stl
|
||||
bed_texture = ender5plus.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:ENDER6]
|
||||
#name = Creality Ender-6
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = ENDER
|
||||
#bed_model = ender6_bed.stl
|
||||
#bed_texture = ender6.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:ENDER2]
|
||||
name = Creality Ender-2
|
||||
variants = 0.4
|
||||
@ -73,8 +100,17 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR
|
||||
#bed_model = ender3_bed.stl
|
||||
#bed_texture = cr20.svg
|
||||
#bed_model = cr6se_bed.stl
|
||||
#bed_texture = cr6se.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:CR6MAX]
|
||||
#name = Creality CR-6 Max
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR
|
||||
#bed_model = cr10s4_bed.stl
|
||||
#bed_texture = cr10s4.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:CR10MINI]
|
||||
@ -86,6 +122,15 @@ bed_model = cr10mini_bed.stl
|
||||
bed_texture = cr10mini.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:CR10MAX]
|
||||
#name = Creality CR-10 Max
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR
|
||||
#bed_model = cr10max_bed.stl
|
||||
#bed_texture = cr10max.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:CR10]
|
||||
name = Creality CR-10
|
||||
variants = 0.4
|
||||
@ -128,7 +173,7 @@ variants = 0.4
|
||||
technology = FFF
|
||||
family = CR
|
||||
bed_model = cr10v2_bed.stl
|
||||
bed_texture = cr10.svg
|
||||
bed_texture = cr10spro.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
[printer_model:CR10SPROV2]
|
||||
@ -176,6 +221,33 @@ bed_model = ender3_bed.stl
|
||||
bed_texture = cr20.svg
|
||||
default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:CR8]
|
||||
#name = Creality CR-8
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR
|
||||
#bed_model = cr8_bed.stl
|
||||
#bed_texture = cr8.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:CRX]
|
||||
#name = Creality CR-X
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR-X
|
||||
#bed_model = cr10v2_bed.stl
|
||||
#bed_texture = cr10spro.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
#[printer_model:CRXPRO]
|
||||
#name = Creality CR-X Pro
|
||||
#variants = 0.4
|
||||
#technology = FFF
|
||||
#family = CR-X
|
||||
#bed_model = cr10v2_bed.stl
|
||||
#bed_texture = cr10spro.svg
|
||||
#default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Creality PLA @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY; AzureFilm PLA @CREALITY; Devil Design PLA @CREALITY; Devil Design PLA (Galaxy) @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 123-3D Jupiter PLA @CREALITY
|
||||
|
||||
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||
# not make it into the user interface.
|
||||
|
||||
@ -556,6 +628,17 @@ filament_density = 1.3
|
||||
filament_colour = #3C4547
|
||||
filament_spool_weight = 256
|
||||
|
||||
[filament:Extrudr GreenTEC Pro @CREALITY]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Extrudr
|
||||
temperature = 210
|
||||
bed_temperature = 60
|
||||
first_layer_temperature = 215
|
||||
first_layer_bed_temperature = 60
|
||||
filament_cost = 56.24
|
||||
filament_density = 1.35
|
||||
filament_colour = #3C4547
|
||||
|
||||
[filament:Real Filament PLA @CREALITY]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Real Filament
|
||||
@ -610,6 +693,7 @@ first_layer_temperature = 215
|
||||
first_layer_bed_temperature = 60
|
||||
filament_cost = 20.56
|
||||
filament_density = 1.24
|
||||
filament_colour = #C7F935
|
||||
|
||||
[filament:Das Filament PETG @CREALITY]
|
||||
inherits = *PET*
|
||||
@ -620,6 +704,7 @@ first_layer_temperature = 240
|
||||
first_layer_bed_temperature = 70
|
||||
filament_cost = 27.44
|
||||
filament_density = 1.29
|
||||
filament_colour = #C7F935
|
||||
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
@ -628,7 +713,7 @@ before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z]\n\n
|
||||
between_objects_gcode =
|
||||
pause_print_gcode =
|
||||
deretract_speed = 0
|
||||
extruder_colour = #FFFF00
|
||||
extruder_colour = #FCE94F
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
@ -711,138 +796,208 @@ retract_length = 5
|
||||
retract_speed = 60
|
||||
deretract_speed = 40
|
||||
retract_before_wipe = 70%
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG4 S10 ; wait for partial warmup\nG28 ; home all\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\nG1 Y140 E10 F1500 ; intro line\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; intro line\nG92 E0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors
|
||||
|
||||
[printer:Creality Ender-3 V2]
|
||||
inherits = Creality Ender-3
|
||||
renamed_from = "Creality Ender-3V2"
|
||||
printer_model = ENDER3V2
|
||||
bed_shape = 0x0,220x0,220x220,0x220
|
||||
|
||||
# Intended for printers with a smaller bed, like the Ender-3 series
|
||||
[printer:*fastabl*]
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG4 S10 ; wait for partial warmup\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\nG1 Y140 E10 F1500 ; intro line\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; intro line\nG92 E0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nG4 S10 ; allow partial nozzle warmup\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0
|
||||
|
||||
# Intended for printers with a larger bed, like the CR-10 series
|
||||
[printer:*slowabl*]
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set extruder temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; intro line\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; intro line\nG92 E0
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S120 ; set temporary nozzle temp to prevent oozing during homing and auto bed leveling\nM140 S[first_layer_bed_temperature] ; set final bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp to stabilize\nG28 ; home all axis\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set final nozzle temp\nM109 S[first_layer_temperature] ; wait for nozzle temp to stabilize\nG1 Z0.28 F240\nG92 E0\nG1 Y140 E10 F1500 ; prime the nozzle\nG1 X2.3 F5000\nG92 E0\nG1 Y10 E10 F1200 ; prime the nozzle\nG92 E0
|
||||
|
||||
# Intended for printers with vendor official firmware verified to support M25
|
||||
[printer:*pauseprint*]
|
||||
pause_print_gcode = M25 ; pause print
|
||||
|
||||
# Intended for printers where the Z-axis lowers the print bed during printing, like the Ender-5 series
|
||||
[printer:*invertedz*]
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed down further down\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors
|
||||
[printer:*descendingz*]
|
||||
renamed_from = "*invertedz*"
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; move print head out of the way\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed close to the bottom\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors
|
||||
|
||||
# Intended for printers with dual extruders and a single hotend/nozzle, like the CR-X series
|
||||
[printer:*dualextruder*]
|
||||
single_extruder_multi_material = 1
|
||||
cooling_tube_length = 5
|
||||
cooling_tube_retraction = 91.5
|
||||
extra_loading_move = -2
|
||||
parking_pos_retraction = 92
|
||||
deretract_speed = 40,40
|
||||
extruder_colour = #FCE94F;#729FCF
|
||||
extruder_offset = 0x0,0x0
|
||||
max_layer_height = 0.28,0.28
|
||||
min_layer_height = 0.08,0.08
|
||||
nozzle_diameter = 0.4,0.4
|
||||
retract_before_travel = 2,2
|
||||
retract_before_wipe = 70%,70%
|
||||
retract_layer_change = 1,1
|
||||
retract_length = 5,5
|
||||
retract_length_toolchange = 1,1
|
||||
retract_lift = 0,0
|
||||
retract_lift_above = 0,0
|
||||
retract_lift_below = 0,0
|
||||
retract_restart_extra = 0,0
|
||||
retract_restart_extra_toolchange = 0,0
|
||||
retract_speed = 60,60
|
||||
wipe = 1,1
|
||||
|
||||
[printer:Creality Ender-3 BLTouch]
|
||||
inherits = Creality Ender-3; *fastabl*
|
||||
renamed_from = "Creality ENDER-3 BLTouch"
|
||||
printer_model = ENDER3BLTOUCH
|
||||
|
||||
[printer:Creality Ender-3 V2]
|
||||
inherits = Creality Ender-3
|
||||
renamed_from = "Creality Ender-3V2"
|
||||
printer_model = ENDER3V2
|
||||
bed_shape = 5x0,215x0,215x220,5x220
|
||||
|
||||
#[printer:Creality Ender-3 Max]
|
||||
#inherits = Creality Ender-3
|
||||
#retract_length = 6
|
||||
#bed_shape = 5x5,295x5,295x295,5x295
|
||||
#max_print_height = 340
|
||||
#printer_model = ENDER3MAX
|
||||
#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_ENDER3MAX\nPRINTER_HAS_BOWDEN
|
||||
|
||||
#[printer:Creality Ender-4]
|
||||
#inherits = Creality Ender-3; *descendingz*
|
||||
#bed_shape = 5x0,215x0,215x220,5x220
|
||||
#max_print_height = 300
|
||||
#printer_model = ENDER4
|
||||
#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_ENDER4\nPRINTER_HAS_BOWDEN
|
||||
|
||||
[printer:Creality Ender-5]
|
||||
inherits = Creality Ender-3; *invertedz*
|
||||
inherits = Creality Ender-3; *descendingz*
|
||||
retract_length = 6
|
||||
bed_shape = 5x2.5,225x2.5,225x222.5,5x222.5
|
||||
max_print_height = 300
|
||||
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
|
||||
machine_max_acceleration_e = 1000
|
||||
machine_max_feedrate_z = 5
|
||||
|
||||
[printer:Creality Ender-5 Plus]
|
||||
inherits = Creality Ender-3; *slowabl*; *invertedz*
|
||||
inherits = Creality Ender-3; *slowabl*; *descendingz*
|
||||
retract_length = 6
|
||||
bed_shape = 5x5,355x5,355x355,5x355
|
||||
max_print_height = 400
|
||||
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
|
||||
machine_max_acceleration_e = 1000
|
||||
machine_max_feedrate_z = 5
|
||||
machine_max_feedrate_x = 300
|
||||
machine_max_feedrate_y = 300
|
||||
|
||||
#[printer:Creality Ender-6]
|
||||
#inherits = Creality Ender-3; *descendingz*
|
||||
#bed_shape = 5x5,255x5,255x255,5x255
|
||||
#max_print_height = 400
|
||||
#printer_model = ENDER6
|
||||
#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_ENDER6\nPRINTER_HAS_BOWDEN
|
||||
|
||||
[printer:Creality Ender-2]
|
||||
inherits = Creality Ender-3
|
||||
renamed_from = "Creality ENDER-2"
|
||||
bed_shape = 0x0,150x0,150x150,0x150
|
||||
max_print_height = 200
|
||||
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
|
||||
|
||||
#[printer:Creality CR-6 SE]
|
||||
#inherits = Creality Ender-3; *fastabl*
|
||||
#inherits = Creality Ender-3; *fastabl*; *pauseprint*
|
||||
#bed_shape = 5x0,230x0,230x235,5x235
|
||||
#printer_model = CR6SE
|
||||
#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_CR6SE\nPRINTER_HAS_BOWDEN
|
||||
|
||||
#[printer:Creality CR-6 Max]
|
||||
#inherits = Creality Ender-3; *slowabl*
|
||||
#retract_length = 6
|
||||
#bed_shape = 5x5,395x5,395x395,5x395
|
||||
#max_print_height = 400
|
||||
#printer_model = CR6MAX
|
||||
#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_CR6MAX\nPRINTER_HAS_BOWDEN
|
||||
|
||||
[printer:Creality CR-10 Mini]
|
||||
inherits = Creality Ender-3
|
||||
retract_length = 6
|
||||
bed_shape = 2.5x5,2.5x225,302.5x225,302.5x5
|
||||
max_print_height = 300
|
||||
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 Max]
|
||||
#inherits = Creality Ender-3; *slowabl*
|
||||
#retract_length = 6
|
||||
#bed_shape = 5x5,445x5,445x445,5x445
|
||||
#max_print_height = 470
|
||||
#printer_model = CR10MAX
|
||||
#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_CR10MAX\nPRINTER_HAS_BOWDEN
|
||||
|
||||
[printer:Creality CR-10]
|
||||
inherits = Creality Ender-3
|
||||
retract_length = 6
|
||||
bed_shape = 5x5,305x5,305x305,5x305
|
||||
max_print_height = 400
|
||||
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
|
||||
max_print_height = 400
|
||||
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
|
||||
max_print_height = 400
|
||||
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
|
||||
max_print_height = 400
|
||||
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; *slowabl*
|
||||
retract_length = 6
|
||||
bed_shape = 0x0,300x0,300x300,0x300
|
||||
bed_shape = 5x5,295x5,295x295,5x295
|
||||
max_print_height = 400
|
||||
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; *slowabl*
|
||||
retract_length = 6
|
||||
bed_shape = 5x5,305x5,305x305,5x305
|
||||
max_print_height = 400
|
||||
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
|
||||
bed_shape = 5x5,395x5,395x395,5x395
|
||||
max_print_height = 400
|
||||
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
|
||||
max_print_height = 500
|
||||
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
|
||||
@ -854,3 +1009,26 @@ inherits = Creality Ender-3; *fastabl*
|
||||
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
|
||||
|
||||
#[printer:Creality CR-8]
|
||||
#inherits = Creality Ender-3
|
||||
#bed_shape = 5x5,215x5,215x215,5x215
|
||||
#max_print_height = 210
|
||||
#printer_model = CR8
|
||||
#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_CR8\nPRINTER_HAS_BOWDEN
|
||||
|
||||
#[printer:Creality CR-X]
|
||||
#inherits = Creality Ender-3; *dualextruder*
|
||||
#retract_length = 6,6
|
||||
#bed_shape = 5x5,295x5,295x295,5x295
|
||||
#max_print_height = 400
|
||||
#printer_model = CRX
|
||||
#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_CRX\nPRINTER_HAS_BOWDEN
|
||||
|
||||
#[printer:Creality CR-X Pro]
|
||||
#inherits = Creality Ender-3; *dualextruder*; *slowabl*
|
||||
#retract_length = 6,6
|
||||
#bed_shape = 5x5,295x5,295x295,5x295
|
||||
#max_print_height = 400
|
||||
#printer_model = CRXPRO
|
||||
#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_CRXPRO\nPRINTER_HAS_BOWDEN
|
||||
|
BIN
resources/profiles/Creality/CR10MAX_thumbnail.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
resources/profiles/Creality/CR6MAX_thumbnail.png
Normal file
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 45 KiB |
BIN
resources/profiles/Creality/CR8_thumbnail.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
resources/profiles/Creality/CRXPRO_thumbnail.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
resources/profiles/Creality/CRX_thumbnail.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
resources/profiles/Creality/ENDER3MAX_thumbnail.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
resources/profiles/Creality/ENDER4_thumbnail.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
resources/profiles/Creality/ENDER6_thumbnail.png
Normal file
After Width: | Height: | Size: 45 KiB |
4
resources/profiles/Creality/cr10max.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="440mm" height="440mm" version="1.1" viewBox="0 0 440 440" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="439.5" height="439.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
2774
resources/profiles/Creality/cr10max_bed.stl
Normal file
@ -1,4 +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 width="390mm" height="390mm" version="1.1" viewBox="0 0 390 390" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="389.5" height="389.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 251 B After Width: | Height: | Size: 251 B |
4
resources/profiles/Creality/cr10spro.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="290mm" height="290mm" version="1.1" viewBox="0 0 290 290" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="289.5" height="289.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
4
resources/profiles/Creality/cr6se.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="225mm" height="235mm" version="1.1" viewBox="0 0 225 235" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="224.5" height="234.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
2774
resources/profiles/Creality/cr6se_bed.stl
Normal file
4
resources/profiles/Creality/cr8.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="210mm" height="210mm" version="1.1" viewBox="0 0 210 210" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="209.5" height="209.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
2774
resources/profiles/Creality/cr8_bed.stl
Normal file
4
resources/profiles/Creality/ender3v2.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="210mm" height="220mm" version="1.1" viewBox="0 0 210 220" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="209.5" height="219.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
2774
resources/profiles/Creality/ender3v2_bed.stl
Normal file
4
resources/profiles/Creality/ender6.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="250mm" height="250mm" version="1.1" viewBox="0 0 250 250" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x=".25" y=".25" width="249.5" height="249.5" fill="none" stroke="#fff" stroke-width=".5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 251 B |
2774
resources/profiles/Creality/ender6_bed.stl
Normal file
2
resources/profiles/INAT.idx
Normal file
@ -0,0 +1,2 @@
|
||||
min_slic3r_version = 2.3.0
|
||||
0.0.1 Initial version
|
467
resources/profiles/INAT.ini
Normal file
@ -0,0 +1,467 @@
|
||||
# generated by PrusaSlicer 2.1.1+win64 on 2020-02-25 at 01:51:21 UTC
|
||||
|
||||
[vendor]
|
||||
# Vendor name will be shown by the Config Wizard.
|
||||
name = INAT s.r.o.
|
||||
config_version = 0.0.1
|
||||
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/
|
||||
|
||||
###
|
||||
### PRINTER LIST
|
||||
###
|
||||
|
||||
[printer_model:PROTON_X_RAIL]
|
||||
name = INAT Proton X Rail
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
family = Proton
|
||||
|
||||
[printer_model:PROTON_X_ROD]
|
||||
name = INAT Proton X Rod
|
||||
variants = 0.4
|
||||
technology = FFF
|
||||
family = Proton
|
||||
|
||||
|
||||
###
|
||||
### QUALITY DEFINITIONS
|
||||
###
|
||||
|
||||
[print:*common*]
|
||||
#layers
|
||||
layer_height = 0.2
|
||||
first_layer_height = 0.2
|
||||
perimeters = 3
|
||||
spiral_vase = 0
|
||||
top_solid_layers = 4
|
||||
bottom_solid_layers = 3
|
||||
top_solid_min_thickness = 0.8
|
||||
bottom_solid_min_thickness = 0.6
|
||||
extra_perimeters = 1
|
||||
ensure_vertical_shell_thickness = 1
|
||||
avoid_crossing_perimeters = 0
|
||||
thin_walls = 0
|
||||
overhangs = 1
|
||||
seam_position = aligned
|
||||
external_perimeters_first = 0
|
||||
#infill
|
||||
fill_density = 30%
|
||||
fill_pattern = cubic
|
||||
infill_anchor = 600%
|
||||
infill_anchor_max = 30
|
||||
top_fill_pattern = monotonic
|
||||
bottom_fill_patter = monotonic
|
||||
ironing = 0
|
||||
ironing_type = top
|
||||
infill_every_layers = 1
|
||||
infill_only_where_needed = 0
|
||||
solid_infill_every_layers = 0
|
||||
fill_angle = 45
|
||||
solid_infill_below_area = 20
|
||||
bridge_angle = 0
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
infill_first = 0
|
||||
#skirt brim
|
||||
skirts = 5
|
||||
skirt_distance = 15
|
||||
skirt_height = 1
|
||||
draft_shield = 0
|
||||
min_skirt_length = 5
|
||||
brim_width = 0
|
||||
#support
|
||||
support_material = 0
|
||||
support_material_auto = 1
|
||||
support_material_threshold = 0
|
||||
support_material_enforce_layers = 0
|
||||
raft_layers = 0
|
||||
support_material_contact_distance = 0.2
|
||||
support_material_pattern = rectilinear
|
||||
support_material_with_sheath = 0
|
||||
support_material_spacing = 5
|
||||
support_material_angle = 45
|
||||
support_material_interface_layers = 3
|
||||
support_material_interface_spacing = 0
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_buildplate_only = 0
|
||||
support_material_xy_spacing = 1
|
||||
dont_support_bridges = 1
|
||||
#speed
|
||||
perimeter_speed = 60
|
||||
small_perimeter_speed = 75%
|
||||
external_perimeter_speed = 50%
|
||||
infill_speed = 80
|
||||
solid_infill_speed = 100%
|
||||
top_solid_infill_speed = 30
|
||||
support_material_speed = 80
|
||||
support_material_interface_speed = 100%
|
||||
bridge_speed = 60
|
||||
gap_fill_speed = 40
|
||||
ironing_speed = 30
|
||||
travel_speed = 150
|
||||
first_layer_speed = 30
|
||||
default_acceleration = 0
|
||||
max_print_speed = 80
|
||||
max_volumetric_speed = 12
|
||||
#multiple extruders
|
||||
perimeter_extruder = 1
|
||||
infill_extruder = 1
|
||||
solid_infill_extruder = 1
|
||||
support_material_extruder = 1
|
||||
support_material_interface_extruder = 1
|
||||
ooze_prevention = 0
|
||||
wipe_tower = 0
|
||||
interface_shells = 0
|
||||
#advanced
|
||||
extrusion_width = 0
|
||||
first_layer_extrusion_width = 0
|
||||
perimeter_extrusion_width = 0
|
||||
external_perimeter_extrusion_width = 0
|
||||
infill_extrusion_width = 0
|
||||
solid_infill_extrusion_width = 0
|
||||
top_infill_extrusion_width = 0
|
||||
support_material_extrusion_width = 0
|
||||
infill_overlap = 25%
|
||||
bridge_flow_ratio = 1
|
||||
slice_closing_radius = 0.049
|
||||
resolution = 0
|
||||
xy_size_compensation = 0
|
||||
elefant_foot_compensation = 0.3
|
||||
clip_multipart_objects = 0
|
||||
#output
|
||||
complete_objects = 0
|
||||
extruder_clearance_radius = 85
|
||||
extruder_clearance_height = 34
|
||||
gcode_comments = 0
|
||||
gcode_label_objects = 0
|
||||
output_filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode
|
||||
|
||||
|
||||
[print:0.2mm Standard @PROTON_X]
|
||||
inherits = *common*
|
||||
|
||||
[print:0.2mm Strong @PROTON_X]
|
||||
inherits = *common*
|
||||
fill_density = 50%
|
||||
perimeters = 6
|
||||
|
||||
[print:0.2mm Advanced Material @PROTON_X]
|
||||
inherits = *common*
|
||||
bottom_solid_layers = 5
|
||||
top_solid_layers = 6
|
||||
skirts = 0
|
||||
brim_width = 30
|
||||
infill_speed = 60
|
||||
support_material_speed = 60
|
||||
travel_speed = 100
|
||||
first_layer_speed = 20
|
||||
elefant_foot_compensation = 0
|
||||
|
||||
[print:0.12mm Fine @PROTON_X]
|
||||
inherits = *common*
|
||||
bottom_solid_layers = 7
|
||||
top_solid_layers = 7
|
||||
infill_every_layers = 2
|
||||
perimeter_speed = 50
|
||||
infill_speed = 50
|
||||
|
||||
[print:0.32mm Draft @PROTON_X]
|
||||
inherits = *common*
|
||||
perimeter_speed = 80
|
||||
external_perimeter_speed = 75%
|
||||
infill_speed = 100
|
||||
top_solid_infill_speed = 60
|
||||
fill_density = 15%
|
||||
|
||||
###
|
||||
### PRINTER DEFINITIONS
|
||||
###
|
||||
|
||||
[printer:*common*]
|
||||
printer_vendor = INAT s.r.o.
|
||||
default_filament_profile = "PLA @PROTON_X"
|
||||
#general
|
||||
printer_technology = FFF
|
||||
bed_shape = 0x0,304x0,304x304,0x304
|
||||
max_print_height = 650
|
||||
z_offset = 0
|
||||
extruders_count = 1
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
remaining_times = 1
|
||||
use_relative_e_distances = 0
|
||||
use_firmware_retraction = 0
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 1
|
||||
#gcodes
|
||||
start_gcode = G28 ;Home\nG0 Z0.3 F200 ;Move nozzle down\nM192 S50 ; Wait for probe temperature to settle\nG29\nG0 X0 Y0 Z30 F6000\nM84 E\nM0\nG1 Z15.0 F6000 ;Move the platform down 15mm\n;Prime the extruder\nG92 E0\nG1 F200 E3\nG92 E0\n
|
||||
end_gcode = M400\nM104 S0\nM140 S0\nM107\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X R5\nG0 Y300 F2000\nM84\n
|
||||
color_change_gcode = M600
|
||||
#limits
|
||||
machine_limits_usage = emit_to_gcode
|
||||
machine_max_feedrate_x = 200,200
|
||||
machine_max_feedrate_y = 200,200
|
||||
machine_max_feedrate_z = 10,10
|
||||
machine_max_feedrate_e = 100,100
|
||||
machine_max_acceleration_x = 500,500
|
||||
machine_max_acceleration_y = 500,500
|
||||
machine_max_acceleration_z = 100,100
|
||||
machine_max_acceleration_e = 2000,2000
|
||||
machine_max_acceleration_extruding = 1000,1000
|
||||
machine_max_acceleration_retracting = 1500,1500
|
||||
machine_max_jerk_x = 8,8
|
||||
machine_max_jerk_y = 8,8
|
||||
machine_max_jerk_z = 1,1
|
||||
machine_max_jerk_e = 2.5,2.5
|
||||
machine_min_extruding_rate = 5
|
||||
#extruder 1
|
||||
nozzle_diameter = 0.4
|
||||
min_layer_height = 0.05
|
||||
max_layer_height = 0.33
|
||||
extruder_offset = 0x0
|
||||
retract_length = 1.5
|
||||
retract_lift = 0.6
|
||||
retract_lift_above = 0
|
||||
retract_lift_below = 0
|
||||
retract_speed = 45
|
||||
deretract_speed = 0
|
||||
retract_restart_extra = 0
|
||||
retract_before_travel = 2
|
||||
retract_layer_change = 0
|
||||
wipe = 1
|
||||
retract_before_wipe = 100%
|
||||
|
||||
|
||||
[printer:Proton X Rail]
|
||||
inherits = *common*
|
||||
printer_model = PROTON_X_RAIL
|
||||
printer_variant = 0.4
|
||||
default_print_profile = 0.2mm Standard @PROTON_X
|
||||
gcode_flavor = marlin
|
||||
machine_max_acceleration_y = 800,800
|
||||
|
||||
[printer:Proton X Rod]
|
||||
inherits = *common*
|
||||
printer_model = PROTON_X_ROD
|
||||
printer_variant = 0.4
|
||||
default_print_profile = 0.2mm Standard @PROTON_X
|
||||
gcode_flavor = marlin
|
||||
|
||||
|
||||
###
|
||||
### MATERIAL DEFINITIONS
|
||||
###
|
||||
|
||||
[filament:*common*]
|
||||
#filament
|
||||
filament_colour = #29B2B2
|
||||
filament_diameter = 1.75
|
||||
extrusion_multiplier = 1
|
||||
filament_vendor = Generic
|
||||
#cooling
|
||||
fan_always_on = 0
|
||||
cooling = 1
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 3
|
||||
full_fan_speed_layer = 0
|
||||
fan_below_layer_time = 10
|
||||
slowdown_below_layer_time = 5
|
||||
min_print_speed = 10
|
||||
#advanced
|
||||
filament_soluble = 0
|
||||
|
||||
|
||||
[filament:PLA @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 210
|
||||
bed_temperature = 60
|
||||
first_layer_temperature = 210
|
||||
first_layer_bed_temperature = 60
|
||||
filament_type = PLA
|
||||
filament_cost = 20
|
||||
filament_density = 1.25
|
||||
min_fan_speed = 50
|
||||
max_fan_speed = 100
|
||||
|
||||
|
||||
[filament:PETG @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 240
|
||||
bed_temperature = 80
|
||||
first_layer_temperature = 240
|
||||
first_layer_bed_temperature = 80
|
||||
filament_type = PETG
|
||||
filament_cost = 25
|
||||
filament_density = 1.27
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 50
|
||||
|
||||
[filament:ABS @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 235
|
||||
bed_temperature = 100
|
||||
first_layer_temperature = 235
|
||||
first_layer_bed_temperature = 100
|
||||
filament_type = ABS
|
||||
filament_cost = 20
|
||||
filament_density = 1.01
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:ASA @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 240
|
||||
bed_temperature = 110
|
||||
first_layer_temperature = 240
|
||||
first_layer_bed_temperature = 110
|
||||
filament_type = ASA
|
||||
filament_cost = 22
|
||||
filament_density = 1.07
|
||||
cooling = 0
|
||||
|
||||
[filament:TPE @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 220
|
||||
bed_temperature = 40
|
||||
first_layer_temperature = 220
|
||||
first_layer_bed_temperature = 40
|
||||
filament_type = TPE
|
||||
filament_cost = 32
|
||||
filament_density = 0.9
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 50
|
||||
filament_retract_length = 0.8
|
||||
filament_retract_speed = 25
|
||||
|
||||
[filament:HIPS @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 245
|
||||
bed_temperature = 100
|
||||
first_layer_temperature = 245
|
||||
first_layer_bed_temperature = 100
|
||||
filament_type = HIPS
|
||||
filament_cost = 15
|
||||
filament_density = 1.04
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 50
|
||||
filament_soluble = 1
|
||||
|
||||
[filament:Nylon @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 235
|
||||
bed_temperature = 130
|
||||
first_layer_temperature = 235
|
||||
first_layer_bed_temperature = 130
|
||||
filament_type = Nylon
|
||||
filament_cost = 70
|
||||
filament_density = 1.01
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:PC @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 270
|
||||
bed_temperature = 130
|
||||
first_layer_temperature = 270
|
||||
first_layer_bed_temperature = 130
|
||||
filament_type = PC
|
||||
filament_cost = 65
|
||||
filament_density = 1.19
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:CPE @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 280
|
||||
bed_temperature = 90
|
||||
first_layer_temperature = 280
|
||||
first_layer_bed_temperature = 90
|
||||
filament_type = PEI
|
||||
filament_cost = 380
|
||||
filament_density = 1.27
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:PEEK @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 440
|
||||
bed_temperature = 150
|
||||
first_layer_temperature = 440
|
||||
first_layer_bed_temperature = 150
|
||||
filament_type = PEEK
|
||||
filament_cost = 500
|
||||
filament_density = 1.3
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:PEI @PROTON_X]
|
||||
inherits = *common*
|
||||
temperature = 400
|
||||
bed_temperature = 150
|
||||
first_layer_temperature = 400
|
||||
first_layer_bed_temperature = 150
|
||||
filament_type = PEI
|
||||
filament_cost = 380
|
||||
filament_density = 1.27
|
||||
cooling = 0
|
||||
bridge_fan_speed = 0
|
||||
|
||||
[filament:Polymaker PolyMide CoPA @PROTON_X]
|
||||
inherits = *common*
|
||||
filament_vendor = Polymaker
|
||||
temperature = 265
|
||||
bed_temperature = 50
|
||||
first_layer_temperature = 265
|
||||
first_layer_bed_temperature = 50
|
||||
filament_type = Nylon
|
||||
filament_cost = 93
|
||||
filament_density = 1.12
|
||||
cooling = 0
|
||||
|
||||
[filament:Polymaker PolyMide PA6-CF @PROTON_X]
|
||||
inherits = *common*
|
||||
filament_vendor = Polymaker
|
||||
temperature = 300
|
||||
bed_temperature = 40
|
||||
first_layer_temperature = 300
|
||||
first_layer_bed_temperature = 40
|
||||
filament_type = Nylon
|
||||
filament_cost = 95
|
||||
filament_density = 1.17
|
||||
cooling = 0
|
||||
|
||||
[filament:Polymaker PolyMide PA6-GF @PROTON_X]
|
||||
inherits = *common*
|
||||
filament_vendor = Polymaker
|
||||
temperature = 300
|
||||
bed_temperature = 40
|
||||
first_layer_temperature = 300
|
||||
first_layer_bed_temperature = 40
|
||||
filament_type = Nylon
|
||||
filament_cost = 95
|
||||
filament_density = 1.2
|
||||
cooling = 0
|
||||
|
||||
[filament:Devil Design PETG @PROTON_X]
|
||||
inherits = *common*
|
||||
filament_vendor = Devil Design
|
||||
temperature = 250
|
||||
bed_temperature = 80
|
||||
first_layer_temperature = 250
|
||||
first_layer_bed_temperature = 80
|
||||
filament_type = PETG
|
||||
filament_cost = 22
|
||||
filament_density = 1.23
|
||||
min_fan_speed = 0
|
||||
max_fan_speed = 50
|
||||
|
||||
[filament:Filament PM PETG FRJet @PROTON_X]
|
||||
inherits = *common*
|
||||
filament_vendor = Filament PM
|
||||
temperature = 250
|
||||
bed_temperature = 90
|
||||
first_layer_temperature = 250
|
||||
first_layer_bed_temperature = 90
|
||||
filament_type = PETG
|
||||
filament_cost = 45.5
|
||||
filament_density = 1.27
|
||||
cooling = 0
|
BIN
resources/profiles/INAT/PROTON_X_RAIL_thumbnail.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
resources/profiles/INAT/PROTON_X_ROD_thumbnail.png
Normal file
After Width: | Height: | Size: 64 KiB |
@ -1,4 +1,6 @@
|
||||
min_slic3r_version = 2.3.0-rc1
|
||||
1.2.4 Updated cost/density values in filament settings. Various changes in print settings.
|
||||
1.2.3 Updated firmware version. Updated end g-code in MMU2 printer profiles.
|
||||
1.2.2 Added Prusament PVB filament profile. Added 0.8mm nozzle profiles.
|
||||
1.2.1 Updated FW version for MK2.5 family printers.
|
||||
1.2.0 Added full_fan_speed_layer value for PETG. Increased support interface spacing for 0.6mm nozzle profiles. Updated firmware version.
|
||||
@ -10,6 +12,7 @@ min_slic3r_version = 2.3.0-alpha4
|
||||
1.2.0-alpha1 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
||||
1.2.0-alpha0 Added filament spool weights
|
||||
min_slic3r_version = 2.2.0-alpha3
|
||||
1.1.13 Updated firmware version. Updated end g-code in MMU2 printer profiles.
|
||||
1.1.12 Added Prusament PVB filament profile. Added 0.8mm nozzle profiles.
|
||||
1.1.11 Renamed MK3S and MINI printer profiles. Updated end g-code (MINI). Added new SLA materials and filament profiles.
|
||||
1.1.10 Updated firmware version.
|
||||
@ -32,6 +35,7 @@ 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.0 Filament aliases, Creality profiles and other goodies for PrusaSlicer 2.2.0-alpha0
|
||||
min_slic3r_version = 2.1.1-beta0
|
||||
1.0.11 Updated firmware version.
|
||||
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.
|
||||
@ -50,6 +54,7 @@ min_slic3r_version = 2.1.0-alpha0
|
||||
1.0.0-alpha1 Added Prusament ASA profile
|
||||
1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX
|
||||
min_slic3r_version = 1.42.0-alpha6
|
||||
0.8.10 Updated firmware version.
|
||||
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
|
||||
|
@ -32,22 +32,22 @@ varying vec3 delta_box_max;
|
||||
varying float world_normal_z;
|
||||
varying vec3 eye_normal;
|
||||
|
||||
vec3 slope_color()
|
||||
{
|
||||
return (world_normal_z > slope.normal_z - EPSILON) ? GREEN : RED;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||
discard;
|
||||
vec3 color = slope.actived ? slope_color() : uniform_color.rgb;
|
||||
vec3 color = uniform_color.rgb;
|
||||
float alpha = uniform_color.a;
|
||||
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
||||
color = vec3(0.7, 0.7, 1.0);
|
||||
alpha = 1.0;
|
||||
}
|
||||
// if the fragment is outside the print volume -> use darker color
|
||||
color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||
if (use_environment_tex)
|
||||
gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, uniform_color.a);
|
||||
gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
|
||||
else
|
||||
#endif
|
||||
gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, uniform_color.a);
|
||||
gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ add_subdirectory(boost)
|
||||
add_subdirectory(clipper)
|
||||
add_subdirectory(miniz)
|
||||
add_subdirectory(glu-libtess)
|
||||
add_subdirectory(polypartition)
|
||||
add_subdirectory(poly2tri)
|
||||
add_subdirectory(qhull)
|
||||
add_subdirectory(Shiny)
|
||||
add_subdirectory(semver)
|
||||
|
@ -402,7 +402,8 @@ int CLI::run(int argc, char **argv)
|
||||
for (Model &model : m_models) {
|
||||
size_t num_objects = model.objects.size();
|
||||
for (size_t i = 0; i < num_objects; ++ i) {
|
||||
model.objects.front()->split(nullptr);
|
||||
ModelObjectPtrs new_objects;
|
||||
model.objects.front()->split(&new_objects);
|
||||
model.delete_object(size_t(0));
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ void stl_remove_unconnected_facets(stl_file *stl)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (facet_number < -- stl->stats.number_of_facets) {
|
||||
if (facet_number < int(-- stl->stats.number_of_facets)) {
|
||||
// Removing a face, which was not the last one.
|
||||
// Copy the face and neighborship from the last face to facet_number.
|
||||
stl->facet_start[facet_number] = stl->facet_start[stl->stats.number_of_facets];
|
||||
|
@ -133,16 +133,16 @@ void stl_fix_normal_directions(stl_file *stl)
|
||||
// Initialize list that keeps track of already fixed facets.
|
||||
std::vector<char> norm_sw(stl->stats.number_of_facets, 0);
|
||||
// Initialize list that keeps track of reversed facets.
|
||||
std::vector<int> reversed_ids(stl->stats.number_of_facets, 0);
|
||||
std::vector<int> reversed_ids;
|
||||
reversed_ids.reserve(stl->stats.number_of_facets);
|
||||
|
||||
int facet_num = 0;
|
||||
int reversed_count = 0;
|
||||
// If normal vector is not within tolerance and backwards:
|
||||
// Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
||||
// of it being wrong randomly are low if most of the triangles are right:
|
||||
if (check_normal_vector(stl, 0, 0)) {
|
||||
reverse_facet(stl, 0);
|
||||
reversed_ids[reversed_count ++] = 0;
|
||||
reversed_ids.emplace_back(0);
|
||||
}
|
||||
|
||||
// Say that we've fixed this facet:
|
||||
@ -159,13 +159,13 @@ void stl_fix_normal_directions(stl_file *stl)
|
||||
if (stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) {
|
||||
// trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206)
|
||||
for (int id = reversed_count - 1; id >= 0; -- id)
|
||||
for (int id = int(reversed_ids.size()) - 1; id >= 0; -- id)
|
||||
reverse_facet(stl, reversed_ids[id]);
|
||||
force_exit = true;
|
||||
break;
|
||||
}
|
||||
reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
||||
reversed_ids[reversed_count ++] = stl->neighbors_start[facet_num].neighbor[j];
|
||||
reversed_ids.emplace_back(stl->neighbors_start[facet_num].neighbor[j]);
|
||||
}
|
||||
}
|
||||
// If this edge of the facet is connected:
|
||||
@ -188,6 +188,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
||||
// Get next facet to fix from top of list.
|
||||
if (head->next != tail) {
|
||||
facet_num = head->next->facet_num;
|
||||
assert(facet_num < stl->stats.number_of_facets);
|
||||
if (norm_sw[facet_num] != 1) { // If facet is in list mutiple times
|
||||
norm_sw[facet_num] = 1; // Record this one as being fixed.
|
||||
++ checked;
|
||||
@ -197,7 +198,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
||||
// pool.destroy(temp);
|
||||
} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
|
||||
++ stl->stats.number_of_parts;
|
||||
if (checked >= stl->stats.number_of_facets)
|
||||
if (checked >= int(stl->stats.number_of_facets))
|
||||
// All of the facets have been checked. Bail out.
|
||||
break;
|
||||
// There is another part here. Find it and continue.
|
||||
@ -207,7 +208,7 @@ void stl_fix_normal_directions(stl_file *stl)
|
||||
facet_num = i;
|
||||
if (check_normal_vector(stl, i, 0)) {
|
||||
reverse_facet(stl, i);
|
||||
reversed_ids[reversed_count++] = i;
|
||||
reversed_ids.emplace_back(i);
|
||||
}
|
||||
norm_sw[facet_num] = 1;
|
||||
++ checked;
|
||||
|
@ -70,7 +70,7 @@ void stl_translate(stl_file *stl, float x, float y, float z)
|
||||
{
|
||||
stl_vertex new_min(x, y, z);
|
||||
stl_vertex shift = new_min - stl->stats.min;
|
||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
stl->facet_start[i].vertex[j] += shift;
|
||||
stl->stats.min = new_min;
|
||||
@ -81,7 +81,7 @@ void stl_translate(stl_file *stl, float x, float y, float z)
|
||||
void stl_translate_relative(stl_file *stl, float x, float y, float z)
|
||||
{
|
||||
stl_vertex shift(x, y, z);
|
||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
stl->facet_start[i].vertex[j] += shift;
|
||||
stl->stats.min += shift;
|
||||
@ -100,7 +100,7 @@ void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
||||
if (stl->stats.volume > 0.0)
|
||||
stl->stats.volume *= versor(0) * versor(1) * versor(2);
|
||||
// Scale the mesh.
|
||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
stl->facet_start[i].vertex[j].array() *= s;
|
||||
}
|
||||
@ -330,10 +330,10 @@ void stl_repair(
|
||||
increment = stl->stats.bounding_diameter / 10000.0;
|
||||
}
|
||||
|
||||
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||
if (stl->stats.connected_facets_3_edge < int(stl->stats.number_of_facets)) {
|
||||
int last_edges_fixed = 0;
|
||||
for (int i = 0; i < iterations; ++ i) {
|
||||
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||
if (stl->stats.connected_facets_3_edge < int(stl->stats.number_of_facets)) {
|
||||
if (verbose_flag)
|
||||
printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
|
||||
stl_check_facets_nearby(stl, tolerance);
|
||||
@ -351,7 +351,7 @@ void stl_repair(
|
||||
printf("All facets connected. No nearby check necessary.\n");
|
||||
|
||||
if (remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
||||
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||
if (stl->stats.connected_facets_3_edge < int(stl->stats.number_of_facets)) {
|
||||
if (verbose_flag)
|
||||
printf("Removing unconnected facets...\n");
|
||||
stl_remove_unconnected_facets(stl);
|
||||
@ -360,7 +360,7 @@ void stl_repair(
|
||||
}
|
||||
|
||||
if (fill_holes_flag || fixall_flag) {
|
||||
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||
if (stl->stats.connected_facets_3_edge < int(stl->stats.number_of_facets)) {
|
||||
if (verbose_flag)
|
||||
printf("Filling holes...\n");
|
||||
stl_fill_holes(stl);
|
||||
|
@ -1,6 +1,11 @@
|
||||
|
||||
option(SLIC3R_ENC_CHECK "Verify encoding of source files" 1)
|
||||
|
||||
if (IS_CROSS_COMPILE)
|
||||
# Force disable due to cross compilation. This fact is already printed on cli for users
|
||||
set(SLIC3R_ENC_CHECK OFF CACHE BOOL "" FORCE)
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_ENC_CHECK)
|
||||
add_executable(encoding-check encoding-check.cpp)
|
||||
|
||||
|
@ -3895,10 +3895,10 @@ double DistanceFromLineSqrd(
|
||||
const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
|
||||
{
|
||||
//The equation of a line in general form (Ax + By + C = 0)
|
||||
//given 2 points (x¹,y¹) & (x²,y²) is ...
|
||||
//(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
|
||||
//A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
|
||||
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
|
||||
//given 2 points (x¹,y¹) & (x²,y²) is ...
|
||||
//(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
|
||||
//A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
|
||||
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
|
||||
//see http://en.wikipedia.org/wiki/Perpendicular_distance
|
||||
double A = double(ln1.Y - ln2.Y);
|
||||
double B = double(ln2.X - ln1.X);
|
||||
|
@ -836,7 +836,7 @@ public:
|
||||
inline ItemIteratorOnly<It, size_t> execute(It from, It to)
|
||||
{
|
||||
auto infl = static_cast<Coord>(std::ceil(min_obj_distance_/2.0));
|
||||
if(infl > 0) std::for_each(from, to, [this, infl](Item& item) {
|
||||
if(infl > 0) std::for_each(from, to, [infl](Item& item) {
|
||||
item.inflate(infl);
|
||||
});
|
||||
|
||||
|
@ -653,8 +653,8 @@ inline bool intersect_ray_all_hits(
|
||||
std::vector<igl::Hit> &hits)
|
||||
{
|
||||
auto ray_intersector = detail::RayIntersectorHits<VertexType, IndexedFaceType, TreeType, VectorType> {
|
||||
vertices, faces, tree,
|
||||
origin, dir, VectorType(dir.cwiseInverse())
|
||||
{ vertices, faces, {tree},
|
||||
origin, dir, VectorType(dir.cwiseInverse()) }
|
||||
};
|
||||
if (! tree.empty()) {
|
||||
ray_intersector.hits.reserve(8);
|
||||
|
@ -123,6 +123,9 @@ void AppConfig::set_defaults()
|
||||
|
||||
if (get("default_action_on_select_preset").empty())
|
||||
set("default_action_on_select_preset", "none"); // , "transfer", "discard" or "save"
|
||||
|
||||
if (get("color_mapinulation_panel").empty())
|
||||
set("color_mapinulation_panel", "0");
|
||||
}
|
||||
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
|
||||
else {
|
||||
@ -136,6 +139,11 @@ void AppConfig::set_defaults()
|
||||
if (get("seq_top_layer_only").empty())
|
||||
set("seq_top_layer_only", "1");
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
if (get("seq_top_gcode_indices").empty())
|
||||
set("seq_top_gcode_indices", "1");
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
if (get("use_perspective_camera").empty())
|
||||
set("use_perspective_camera", "1");
|
||||
|
||||
@ -266,14 +274,14 @@ void AppConfig::save()
|
||||
else
|
||||
c << "# " << Slic3r::header_gcodeviewer_generated() << std::endl;
|
||||
// Make sure the "no" category is written first.
|
||||
for (const std::pair<std::string, std::string> &kvp : m_storage[""])
|
||||
for (const auto& kvp : m_storage[""])
|
||||
c << kvp.first << " = " << kvp.second << std::endl;
|
||||
// Write the other categories.
|
||||
for (const auto category : m_storage) {
|
||||
for (const auto& category : m_storage) {
|
||||
if (category.first.empty())
|
||||
continue;
|
||||
c << std::endl << "[" << category.first << "]" << std::endl;
|
||||
for (const std::pair<std::string, std::string> &kvp : category.second)
|
||||
for (const auto& kvp : category.second)
|
||||
c << kvp.first << " = " << kvp.second << std::endl;
|
||||
}
|
||||
// Write vendor sections
|
||||
@ -395,7 +403,7 @@ std::vector<std::string> AppConfig::get_mouse_device_names() const
|
||||
static constexpr const char *prefix = "mouse_device:";
|
||||
static const size_t prefix_len = strlen(prefix);
|
||||
std::vector<std::string> out;
|
||||
for (const std::pair<std::string, std::map<std::string, std::string>>& key_value_pair : m_storage)
|
||||
for (const auto& key_value_pair : m_storage)
|
||||
if (boost::starts_with(key_value_pair.first, prefix) && key_value_pair.first.size() > prefix_len)
|
||||
out.emplace_back(key_value_pair.first.substr(prefix_len));
|
||||
return out;
|
||||
|
@ -207,6 +207,62 @@ std::vector<double> BridgeDetector::bridge_direction_candidates() const
|
||||
return angles;
|
||||
}
|
||||
|
||||
/*
|
||||
static void get_trapezoids(const ExPolygon &expoly, Polygons* polygons) const
|
||||
{
|
||||
ExPolygons expp;
|
||||
expp.push_back(expoly);
|
||||
boost::polygon::get_trapezoids(*polygons, expp);
|
||||
}
|
||||
|
||||
void ExPolygon::get_trapezoids(ExPolygon clone, Polygons* polygons, double angle) const
|
||||
{
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
clone.get_trapezoids(polygons);
|
||||
for (Polygons::iterator polygon = polygons->begin(); polygon != polygons->end(); ++polygon)
|
||||
polygon->rotate(-(PI/2 - angle), Point(0,0));
|
||||
}
|
||||
*/
|
||||
|
||||
// This algorithm may return more trapezoids than necessary
|
||||
// (i.e. it may break a single trapezoid in several because
|
||||
// other parts of the object have x coordinates in the middle)
|
||||
static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons)
|
||||
{
|
||||
Polygons src_polygons = to_polygons(expoly);
|
||||
// get all points of this ExPolygon
|
||||
const Points pp = to_points(src_polygons);
|
||||
|
||||
// build our bounding box
|
||||
BoundingBox bb(pp);
|
||||
|
||||
// get all x coordinates
|
||||
std::vector<coord_t> xx;
|
||||
xx.reserve(pp.size());
|
||||
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
|
||||
xx.push_back(p->x());
|
||||
std::sort(xx.begin(), xx.end());
|
||||
|
||||
// find trapezoids by looping from first to next-to-last coordinate
|
||||
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end()-1; ++x) {
|
||||
coord_t next_x = *(x + 1);
|
||||
if (*x != next_x)
|
||||
// intersect with rectangle
|
||||
// append results to return value
|
||||
polygons_append(*polygons, intersection({ { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } } }, src_polygons));
|
||||
}
|
||||
}
|
||||
|
||||
static void get_trapezoids2(const ExPolygon &expoly, Polygons* polygons, double angle)
|
||||
{
|
||||
ExPolygon clone = expoly;
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
get_trapezoids2(clone, polygons);
|
||||
for (Polygon &polygon : *polygons)
|
||||
polygon.rotate(-(PI/2 - angle), Point(0,0));
|
||||
}
|
||||
|
||||
// Coverage is currently only used by the unit tests. It is extremely slow and unreliable!
|
||||
Polygons BridgeDetector::coverage(double angle) const
|
||||
{
|
||||
if (angle == -1)
|
||||
@ -228,7 +284,7 @@ Polygons BridgeDetector::coverage(double angle) const
|
||||
for (ExPolygon &expoly : offset_ex(expolygon, 0.5f * float(this->spacing))) {
|
||||
// Compute trapezoids according to a vertical orientation
|
||||
Polygons trapezoids;
|
||||
expoly.get_trapezoids2(&trapezoids, PI/2.0);
|
||||
get_trapezoids2(expoly, &trapezoids, PI/2.0);
|
||||
for (const Polygon &trapezoid : trapezoids) {
|
||||
// not nice, we need a more robust non-numeric check
|
||||
size_t n_supported = 0;
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
BridgeDetector(const ExPolygons &_expolygons, const ExPolygons &_lower_slices, coord_t _extrusion_width);
|
||||
// If bridge_direction_override != 0, then the angle is used instead of auto-detect.
|
||||
bool detect_angle(double bridge_direction_override = 0.);
|
||||
// Coverage is currently only used by the unit tests. It is extremely slow and unreliable!
|
||||
Polygons coverage(double angle = -1) const;
|
||||
void unsupported_edges(double angle, Polylines* unsupported) const;
|
||||
Polylines unsupported_edges(double angle = -1) const;
|
||||
|
532
src/libslic3r/Brim.cpp
Normal file
@ -0,0 +1,532 @@
|
||||
#include "clipper/clipper_z.hpp"
|
||||
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "Layer.hpp"
|
||||
#include "Print.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "libslic3r.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
// #define BRIM_DEBUG_TO_SVG
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static void append_and_translate(ExPolygons &dst, const ExPolygons &src, const PrintInstance &instance) {
|
||||
size_t dst_idx = dst.size();
|
||||
expolygons_append(dst, src);
|
||||
for (; dst_idx < dst.size(); ++dst_idx)
|
||||
dst[dst_idx].translate(instance.shift.x(), instance.shift.y());
|
||||
}
|
||||
|
||||
static void append_and_translate(Polygons &dst, const Polygons &src, const PrintInstance &instance) {
|
||||
size_t dst_idx = dst.size();
|
||||
polygons_append(dst, src);
|
||||
for (; dst_idx < dst.size(); ++dst_idx)
|
||||
dst[dst_idx].translate(instance.shift.x(), instance.shift.y());
|
||||
}
|
||||
|
||||
static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects)
|
||||
{
|
||||
assert(!objects.empty());
|
||||
return float(std::accumulate(objects.begin(), objects.end(), 0.,
|
||||
[](double partial_result, const PrintObject *object) {
|
||||
return std::max(partial_result, object->config().brim_type == btNoBrim ? 0. : object->config().brim_width.value);
|
||||
}));
|
||||
}
|
||||
|
||||
static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
|
||||
{
|
||||
Polygons islands;
|
||||
ConstPrintObjectPtrs island_to_object;
|
||||
for (const PrintObject *object : print.objects()) {
|
||||
Polygons islands_object;
|
||||
islands_object.reserve(object->layers().front()->lslices.size());
|
||||
for (const ExPolygon &ex_poly : object->layers().front()->lslices)
|
||||
islands_object.emplace_back(ex_poly.contour);
|
||||
|
||||
islands.reserve(islands.size() + object->instances().size() * islands_object.size());
|
||||
for (const PrintInstance &instance : object->instances())
|
||||
for (Polygon &poly : islands_object) {
|
||||
islands.emplace_back(poly);
|
||||
islands.back().translate(instance.shift);
|
||||
island_to_object.emplace_back(object);
|
||||
}
|
||||
}
|
||||
assert(islands.size() == island_to_object.size());
|
||||
|
||||
ClipperLib_Z::Paths islands_clip;
|
||||
islands_clip.reserve(islands.size());
|
||||
for (const Polygon &poly : islands) {
|
||||
islands_clip.emplace_back();
|
||||
ClipperLib_Z::Path &island_clip = islands_clip.back();
|
||||
island_clip.reserve(poly.points.size());
|
||||
int island_idx = int(&poly - &islands.front());
|
||||
// The Z coordinate carries index of the island used to get the pointer to the object.
|
||||
for (const Point &pt : poly.points)
|
||||
island_clip.emplace_back(pt.x(), pt.y(), island_idx + 1);
|
||||
}
|
||||
|
||||
// Init Clipper
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
// Assign the maximum Z from four points. This values is valid index of the island
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot,
|
||||
const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
|
||||
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
|
||||
});
|
||||
// Add islands
|
||||
clipper.AddPaths(islands_clip, ClipperLib_Z::ptSubject, true);
|
||||
// Execute union operation to construct polytree
|
||||
ClipperLib_Z::PolyTree islands_polytree;
|
||||
clipper.Execute(ClipperLib_Z::ctUnion, islands_polytree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
|
||||
std::unordered_set<size_t> processed_objects_idx;
|
||||
ConstPrintObjectPtrs top_level_objects_with_brim;
|
||||
for (int i = 0; i < islands_polytree.ChildCount(); ++i) {
|
||||
for (const ClipperLib_Z::IntPoint &point : islands_polytree.Childs[i]->Contour) {
|
||||
if (point.Z != 0 && processed_objects_idx.find(island_to_object[point.Z - 1]->id().id) == processed_objects_idx.end()) {
|
||||
top_level_objects_with_brim.emplace_back(island_to_object[point.Z - 1]);
|
||||
processed_objects_idx.insert(island_to_object[point.Z - 1]->id().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return top_level_objects_with_brim;
|
||||
}
|
||||
|
||||
static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_level_objects_with_brim)
|
||||
{
|
||||
Polygons islands;
|
||||
for (const PrintObject *object : top_level_objects_with_brim) {
|
||||
//FIXME how about the brim type?
|
||||
float brim_offset = float(scale_(object->config().brim_offset.value));
|
||||
Polygons islands_object;
|
||||
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
|
||||
Polygons contour_offset = offset(ex_poly.contour, brim_offset);
|
||||
for (Polygon &poly : contour_offset)
|
||||
poly.douglas_peucker(SCALED_RESOLUTION);
|
||||
|
||||
polygons_append(islands_object, std::move(contour_offset));
|
||||
}
|
||||
|
||||
for (const PrintInstance &instance : object->instances())
|
||||
append_and_translate(islands, islands_object, instance);
|
||||
}
|
||||
return islands;
|
||||
}
|
||||
|
||||
static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
|
||||
{
|
||||
std::unordered_set<size_t> top_level_objects_idx;
|
||||
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
|
||||
for (const PrintObject *object : top_level_objects_with_brim)
|
||||
top_level_objects_idx.insert(object->id().id);
|
||||
|
||||
ExPolygons brim_area;
|
||||
Polygons no_brim_area;
|
||||
for (const PrintObject *object : print.objects()) {
|
||||
const BrimType brim_type = object->config().brim_type.value;
|
||||
const float brim_offset = scale_(object->config().brim_offset.value);
|
||||
const float brim_width = scale_(object->config().brim_width.value);
|
||||
const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
|
||||
|
||||
ExPolygons brim_area_object;
|
||||
Polygons no_brim_area_object;
|
||||
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
|
||||
if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim)
|
||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
|
||||
|
||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
||||
append(no_brim_area_object, offset(ex_poly.holes, -no_brim_offset));
|
||||
|
||||
if (brim_type != BrimType::btNoBrim)
|
||||
append(no_brim_area_object, offset(ex_poly.contour, brim_offset));
|
||||
|
||||
no_brim_area_object.emplace_back(ex_poly.contour);
|
||||
}
|
||||
|
||||
for (const PrintInstance &instance : object->instances()) {
|
||||
append_and_translate(brim_area, brim_area_object, instance);
|
||||
append_and_translate(no_brim_area, no_brim_area_object, instance);
|
||||
}
|
||||
}
|
||||
|
||||
return diff_ex(to_polygons(std::move(brim_area)), no_brim_area);
|
||||
}
|
||||
|
||||
static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
|
||||
{
|
||||
std::unordered_set<size_t> top_level_objects_idx;
|
||||
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
|
||||
for (const PrintObject *object : top_level_objects_with_brim)
|
||||
top_level_objects_idx.insert(object->id().id);
|
||||
|
||||
ExPolygons brim_area;
|
||||
ExPolygons no_brim_area;
|
||||
Polygons holes;
|
||||
for (const PrintObject *object : print.objects()) {
|
||||
const BrimType brim_type = object->config().brim_type.value;
|
||||
const float brim_offset = scale_(object->config().brim_offset.value);
|
||||
const float brim_width = scale_(object->config().brim_width.value);
|
||||
const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
|
||||
|
||||
ExPolygons brim_area_object;
|
||||
ExPolygons no_brim_area_object;
|
||||
Polygons holes_object;
|
||||
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
|
||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) {
|
||||
if (top_outer_brim)
|
||||
no_brim_area_object.emplace_back(ex_poly);
|
||||
else
|
||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.contour, brim_width + brim_offset), offset_ex(ex_poly.contour, brim_offset)));
|
||||
}
|
||||
|
||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner)
|
||||
append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset)));
|
||||
|
||||
if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim)
|
||||
append(no_brim_area_object, offset_ex(ex_poly.contour, no_brim_offset));
|
||||
|
||||
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim)
|
||||
append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset));
|
||||
|
||||
append(holes_object, ex_poly.holes);
|
||||
}
|
||||
append(no_brim_area_object, offset_ex(object->layers().front()->lslices, brim_offset));
|
||||
|
||||
for (const PrintInstance &instance : object->instances()) {
|
||||
append_and_translate(brim_area, brim_area_object, instance);
|
||||
append_and_translate(no_brim_area, no_brim_area_object, instance);
|
||||
append_and_translate(holes, holes_object, instance);
|
||||
}
|
||||
}
|
||||
|
||||
return diff_ex(intersection_ex(to_polygons(std::move(brim_area)), holes), no_brim_area);
|
||||
}
|
||||
|
||||
// Flip orientation of open polylines to minimize travel distance.
|
||||
static void optimize_polylines_by_reversing(Polylines *polylines)
|
||||
{
|
||||
for (size_t poly_idx = 1; poly_idx < polylines->size(); ++poly_idx) {
|
||||
const Polyline &prev = (*polylines)[poly_idx - 1];
|
||||
Polyline & next = (*polylines)[poly_idx];
|
||||
|
||||
if (!next.is_closed()) {
|
||||
double dist_to_start = (next.first_point() - prev.last_point()).cast<double>().norm();
|
||||
double dist_to_end = (next.last_point() - prev.last_point()).cast<double>().norm();
|
||||
|
||||
if (dist_to_end < dist_to_start)
|
||||
next.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_area, float max_connection_length)
|
||||
{
|
||||
if (polylines.empty())
|
||||
return Polylines();
|
||||
|
||||
BoundingBox bbox = get_extents(polylines);
|
||||
bbox.merge(get_extents(brim_area));
|
||||
|
||||
EdgeGrid::Grid grid(bbox.inflated(SCALED_EPSILON));
|
||||
grid.create(brim_area, polylines, coord_t(scale_(10.)));
|
||||
|
||||
struct Visitor
|
||||
{
|
||||
explicit Visitor(const EdgeGrid::Grid &grid) : grid(grid) {}
|
||||
|
||||
bool operator()(coord_t iy, coord_t ix)
|
||||
{
|
||||
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||
auto cell_data_range = grid.cell_data_range(iy, ix);
|
||||
this->intersect = false;
|
||||
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++it_contour_and_segment) {
|
||||
// End points of the line segment and their vector.
|
||||
auto segment = grid.segment(*it_contour_and_segment);
|
||||
if (Geometry::segments_intersect(segment.first, segment.second, brim_line.a, brim_line.b)) {
|
||||
this->intersect = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Continue traversing the grid along the edge.
|
||||
return true;
|
||||
}
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
Line brim_line;
|
||||
bool intersect;
|
||||
|
||||
} visitor(grid);
|
||||
|
||||
// Connect successive polylines if they are open, their ends are closer than max_connection_length.
|
||||
// Remove empty polylines.
|
||||
{
|
||||
// Skip initial empty lines.
|
||||
size_t poly_idx = 0;
|
||||
for (; poly_idx < polylines.size() && polylines[poly_idx].empty(); ++ poly_idx) ;
|
||||
size_t end = ++ poly_idx;
|
||||
double max_connection_length2 = Slic3r::sqr(max_connection_length);
|
||||
for (; poly_idx < polylines.size(); ++poly_idx) {
|
||||
Polyline &next = polylines[poly_idx];
|
||||
if (! next.empty()) {
|
||||
Polyline &prev = polylines[end - 1];
|
||||
bool connect = false;
|
||||
if (! prev.is_closed() && ! next.is_closed()) {
|
||||
double dist2 = (prev.last_point() - next.first_point()).cast<double>().squaredNorm();
|
||||
if (dist2 <= max_connection_length2) {
|
||||
visitor.brim_line.a = prev.last_point();
|
||||
visitor.brim_line.b = next.first_point();
|
||||
// Shrink the connection line to avoid collisions with the brim centerlines.
|
||||
visitor.brim_line.extend(-SCALED_EPSILON);
|
||||
grid.visit_cells_intersecting_line(visitor.brim_line.a, visitor.brim_line.b, visitor);
|
||||
connect = ! visitor.intersect;
|
||||
}
|
||||
}
|
||||
if (connect) {
|
||||
append(prev.points, std::move(next.points));
|
||||
} else {
|
||||
if (end < poly_idx)
|
||||
polylines[end] = std::move(next);
|
||||
++ end;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end < polylines.size())
|
||||
polylines.erase(polylines.begin() + end, polylines.end());
|
||||
}
|
||||
|
||||
return std::move(polylines);
|
||||
}
|
||||
|
||||
static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, ExtrusionEntityCollection &brim)
|
||||
{
|
||||
Flow flow = print.brim_flow();
|
||||
ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, flow.scaled_spacing());
|
||||
Polygons loops;
|
||||
islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), jtSquare);
|
||||
for (size_t i = 0; !islands_ex.empty(); ++i) {
|
||||
for (ExPolygon &poly_ex : islands_ex)
|
||||
poly_ex.douglas_peucker(SCALED_RESOLUTION);
|
||||
polygons_append(loops, to_polygons(islands_ex));
|
||||
islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare);
|
||||
}
|
||||
|
||||
loops = union_pt_chained_outside_in(loops, false);
|
||||
std::reverse(loops.begin(), loops.end());
|
||||
extrusion_entities_append_loops(brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()),
|
||||
float(flow.width), float(print.skirt_first_layer_height()));
|
||||
}
|
||||
|
||||
// Produce brim lines around those objects, that have the brim enabled.
|
||||
// Collect islands_area to be merged into the final 1st layer convex hull.
|
||||
ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area)
|
||||
{
|
||||
Flow flow = print.brim_flow();
|
||||
ConstPrintObjectPtrs top_level_objects_with_brim = get_top_level_objects_with_brim(print);
|
||||
Polygons islands = top_level_outer_brim_islands(top_level_objects_with_brim);
|
||||
ExPolygons islands_area_ex = top_level_outer_brim_area(print, top_level_objects_with_brim, flow.scaled_spacing());
|
||||
islands_area = to_polygons(islands_area_ex);
|
||||
|
||||
Polygons loops;
|
||||
size_t num_loops = size_t(floor(max_brim_width(print.objects()) / flow.spacing()));
|
||||
for (size_t i = 0; i < num_loops; ++i) {
|
||||
try_cancel();
|
||||
islands = offset(islands, float(flow.scaled_spacing()), jtSquare);
|
||||
for (Polygon &poly : islands)
|
||||
poly.douglas_peucker(SCALED_RESOLUTION);
|
||||
polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing())));
|
||||
}
|
||||
loops = union_pt_chained_outside_in(loops, false);
|
||||
|
||||
std::vector<Polylines> loops_pl_by_levels;
|
||||
{
|
||||
Polylines loops_pl = to_polylines(loops);
|
||||
loops_pl_by_levels.assign(loops_pl.size(), Polylines());
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, loops_pl.size()),
|
||||
[&loops_pl_by_levels, &loops_pl, &islands_area](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||
loops_pl_by_levels[i] = chain_polylines(intersection_pl({ std::move(loops_pl[i]) }, islands_area));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// output
|
||||
ExtrusionEntityCollection brim;
|
||||
|
||||
// Reduce down to the ordered list of polylines.
|
||||
Polylines all_loops;
|
||||
for (Polylines &polylines : loops_pl_by_levels)
|
||||
append(all_loops, std::move(polylines));
|
||||
loops_pl_by_levels.clear();
|
||||
|
||||
// Flip orientation of open polylines to minimize travel distance.
|
||||
optimize_polylines_by_reversing(&all_loops);
|
||||
|
||||
#ifdef BRIM_DEBUG_TO_SVG
|
||||
static int irun = 0;
|
||||
++ irun;
|
||||
|
||||
{
|
||||
SVG svg(debug_out_path("brim-%d.svg", irun).c_str(), get_extents(all_loops));
|
||||
svg.draw(union_ex(islands), "blue");
|
||||
svg.draw(islands_area_ex, "green");
|
||||
svg.draw(all_loops, "black", coord_t(scale_(0.1)));
|
||||
}
|
||||
#endif // BRIM_DEBUG_TO_SVG
|
||||
|
||||
all_loops = connect_brim_lines(std::move(all_loops), offset(islands_area_ex, float(SCALED_EPSILON)), flow.scaled_spacing() * 2.f);
|
||||
|
||||
#ifdef BRIM_DEBUG_TO_SVG
|
||||
{
|
||||
SVG svg(debug_out_path("brim-connected-%d.svg", irun).c_str(), get_extents(all_loops));
|
||||
svg.draw(union_ex(islands), "blue");
|
||||
svg.draw(islands_area_ex, "green");
|
||||
svg.draw(all_loops, "black", coord_t(scale_(0.1)));
|
||||
}
|
||||
#endif // BRIM_DEBUG_TO_SVG
|
||||
|
||||
const bool could_brim_intersects_skirt = std::any_of(print.objects().begin(), print.objects().end(), [&print](PrintObject *object) {
|
||||
const BrimType &bt = object->config().brim_type;
|
||||
return (bt == btOuterOnly || bt == btOuterAndInner) && print.config().skirt_distance.value < object->config().brim_width;
|
||||
});
|
||||
// If there is a possibility that brim intersects skirt, go through loops and split those extrusions
|
||||
// The result is either the original Polygon or a list of Polylines
|
||||
if (! print.skirt().empty() && could_brim_intersects_skirt)
|
||||
{
|
||||
// Find the bounding polygons of the skirt
|
||||
const Polygons skirt_inners = offset(dynamic_cast<ExtrusionLoop*>(print.skirt().entities.back())->polygon(),
|
||||
-float(scale_(print.skirt_flow().spacing()))/2.f,
|
||||
ClipperLib::jtRound,
|
||||
float(scale_(0.1)));
|
||||
const Polygons skirt_outers = offset(dynamic_cast<ExtrusionLoop*>(print.skirt().entities.front())->polygon(),
|
||||
float(scale_(print.skirt_flow().spacing()))/2.f,
|
||||
ClipperLib::jtRound,
|
||||
float(scale_(0.1)));
|
||||
|
||||
// First calculate the trimming region.
|
||||
ClipperLib_Z::Paths trimming;
|
||||
{
|
||||
ClipperLib_Z::Paths input_subject;
|
||||
ClipperLib_Z::Paths input_clip;
|
||||
for (const Polygon &poly : skirt_outers) {
|
||||
input_subject.emplace_back();
|
||||
ClipperLib_Z::Path &out = input_subject.back();
|
||||
out.reserve(poly.points.size());
|
||||
for (const Point &pt : poly.points)
|
||||
out.emplace_back(pt.x(), pt.y(), 0);
|
||||
}
|
||||
for (const Polygon &poly : skirt_inners) {
|
||||
input_clip.emplace_back();
|
||||
ClipperLib_Z::Path &out = input_clip.back();
|
||||
out.reserve(poly.points.size());
|
||||
for (const Point &pt : poly.points)
|
||||
out.emplace_back(pt.x(), pt.y(), 0);
|
||||
}
|
||||
// init Clipper
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
// add polygons
|
||||
clipper.AddPaths(input_subject, ClipperLib_Z::ptSubject, true);
|
||||
clipper.AddPaths(input_clip, ClipperLib_Z::ptClip, true);
|
||||
// perform operation
|
||||
clipper.Execute(ClipperLib_Z::ctDifference, trimming, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
}
|
||||
|
||||
// Second, trim the extrusion loops with the trimming regions.
|
||||
ClipperLib_Z::Paths loops_trimmed;
|
||||
{
|
||||
// Produce ClipperLib_Z::Paths from polylines (not necessarily closed).
|
||||
ClipperLib_Z::Paths input_clip;
|
||||
for (const Polyline &loop_pl : all_loops) {
|
||||
input_clip.emplace_back();
|
||||
ClipperLib_Z::Path& out = input_clip.back();
|
||||
out.reserve(loop_pl.points.size());
|
||||
int64_t loop_idx = &loop_pl - &all_loops.front();
|
||||
for (const Point& pt : loop_pl.points)
|
||||
// The Z coordinate carries index of the source loop.
|
||||
out.emplace_back(pt.x(), pt.y(), loop_idx + 1);
|
||||
}
|
||||
// init Clipper
|
||||
ClipperLib_Z::Clipper clipper;
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
|
||||
// Assign a valid input loop identifier. Such an identifier is strictly positive, the next line is safe even in case one side of a segment
|
||||
// hat the Z coordinate not set to the contour coordinate.
|
||||
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
|
||||
});
|
||||
// add polygons
|
||||
clipper.AddPaths(input_clip, ClipperLib_Z::ptSubject, false);
|
||||
clipper.AddPaths(trimming, ClipperLib_Z::ptClip, true);
|
||||
// perform operation
|
||||
ClipperLib_Z::PolyTree loops_trimmed_tree;
|
||||
clipper.Execute(ClipperLib_Z::ctDifference, loops_trimmed_tree, ClipperLib_Z::pftEvenOdd, ClipperLib_Z::pftEvenOdd);
|
||||
ClipperLib_Z::PolyTreeToPaths(loops_trimmed_tree, loops_trimmed);
|
||||
}
|
||||
|
||||
// Third, produce the extrusions, sorted by the source loop indices.
|
||||
{
|
||||
std::vector<std::pair<const ClipperLib_Z::Path*, size_t>> loops_trimmed_order;
|
||||
loops_trimmed_order.reserve(loops_trimmed.size());
|
||||
for (const ClipperLib_Z::Path &path : loops_trimmed) {
|
||||
size_t input_idx = 0;
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
if (pt.Z > 0) {
|
||||
input_idx = (size_t)pt.Z;
|
||||
break;
|
||||
}
|
||||
assert(input_idx != 0);
|
||||
loops_trimmed_order.emplace_back(&path, input_idx);
|
||||
}
|
||||
std::stable_sort(loops_trimmed_order.begin(), loops_trimmed_order.end(),
|
||||
[](const std::pair<const ClipperLib_Z::Path*, size_t> &l, const std::pair<const ClipperLib_Z::Path*, size_t> &r) {
|
||||
return l.second < r.second;
|
||||
});
|
||||
|
||||
Point last_pt(0, 0);
|
||||
for (size_t i = 0; i < loops_trimmed_order.size();) {
|
||||
// Find all pieces that the initial loop was split into.
|
||||
size_t j = i + 1;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
|
||||
auto *loop = new ExtrusionLoop();
|
||||
brim.entities.emplace_back(loop);
|
||||
loop->paths.emplace_back(erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(print.skirt_first_layer_height()));
|
||||
Points &points = loop->paths.front().polyline.points;
|
||||
points.reserve(first_path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : first_path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
i = j;
|
||||
} else {
|
||||
//FIXME The path chaining here may not be optimal.
|
||||
ExtrusionEntityCollection this_loop_trimmed;
|
||||
this_loop_trimmed.entities.reserve(j - i);
|
||||
for (; i < j; ++ i) {
|
||||
this_loop_trimmed.entities.emplace_back(new ExtrusionPath(erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(print.skirt_first_layer_height())));
|
||||
const ClipperLib_Z::Path &path = *loops_trimmed_order[i].first;
|
||||
Points &points = static_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points;
|
||||
points.reserve(path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
}
|
||||
chain_and_reorder_extrusion_entities(this_loop_trimmed.entities, &last_pt);
|
||||
brim.entities.reserve(brim.entities.size() + this_loop_trimmed.entities.size());
|
||||
append(brim.entities, std::move(this_loop_trimmed.entities));
|
||||
this_loop_trimmed.entities.clear();
|
||||
}
|
||||
last_pt = brim.last_point();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(print.skirt_first_layer_height()));
|
||||
}
|
||||
|
||||
make_inner_brim(print, top_level_objects_with_brim, brim);
|
||||
return brim;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
14
src/libslic3r/Brim.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef slic3r_Brim_hpp_
|
||||
#define slic3r_Brim_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Print;
|
||||
|
||||
// Produce brim lines around those objects, that have the brim enabled.
|
||||
// Collect islands_area to be merged into the final 1st layer convex hull.
|
||||
ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area);
|
||||
|
||||
} // Slic3r
|
||||
|
||||
#endif // slic3r_Brim_hpp_
|
@ -21,6 +21,8 @@ add_library(libslic3r STATIC
|
||||
BoundingBox.hpp
|
||||
BridgeDetector.cpp
|
||||
BridgeDetector.hpp
|
||||
Brim.cpp
|
||||
Brim.hpp
|
||||
ClipperUtils.cpp
|
||||
ClipperUtils.hpp
|
||||
Config.cpp
|
||||
@ -307,8 +309,6 @@ target_link_libraries(libslic3r
|
||||
nowide
|
||||
${EXPAT_LIBRARIES}
|
||||
glu-libtess
|
||||
polypartition
|
||||
poly2tri
|
||||
qhull
|
||||
semver
|
||||
TBB::tbb
|
||||
|
@ -616,11 +616,11 @@ void ConfigBase::load(const boost::property_tree::ptree &tree)
|
||||
}
|
||||
|
||||
// Load the config keys from the tail of a G-code file.
|
||||
void ConfigBase::load_from_gcode_file(const std::string &file)
|
||||
void ConfigBase::load_from_gcode_file(const std::string& file, bool check_header)
|
||||
{
|
||||
// Read a 64k block from the end of the G-code.
|
||||
boost::nowide::ifstream ifs(file);
|
||||
{
|
||||
if (check_header) {
|
||||
const char slic3r_gcode_header[] = "; generated by Slic3r ";
|
||||
const char prusaslicer_gcode_header[] = "; generated by PrusaSlicer ";
|
||||
std::string firstline;
|
||||
|
@ -1344,7 +1344,7 @@ public:
|
||||
|
||||
static bool has(T value)
|
||||
{
|
||||
for (const std::pair<std::string, int> &kvp : ConfigOptionEnum<T>::get_enum_values())
|
||||
for (const auto &kvp : ConfigOptionEnum<T>::get_enum_values())
|
||||
if (kvp.second == value)
|
||||
return true;
|
||||
return false;
|
||||
@ -1358,11 +1358,11 @@ public:
|
||||
// Initialize the map.
|
||||
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
|
||||
int cnt = 0;
|
||||
for (const std::pair<std::string, int> &kvp : enum_keys_map)
|
||||
for (const auto& kvp : enum_keys_map)
|
||||
cnt = std::max(cnt, kvp.second);
|
||||
cnt += 1;
|
||||
names.assign(cnt, "");
|
||||
for (const std::pair<std::string, int> &kvp : enum_keys_map)
|
||||
for (const auto& kvp : enum_keys_map)
|
||||
names[kvp.second] = kvp.first;
|
||||
}
|
||||
return names;
|
||||
@ -1695,6 +1695,7 @@ public:
|
||||
// Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
virtual const ConfigDef* def() const = 0;
|
||||
// Find ando/or create a ConfigOption instance for a given name.
|
||||
using ConfigOptionResolver::optptr;
|
||||
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0;
|
||||
// Collect names of all configuration values maintained by this configuration store.
|
||||
virtual t_config_option_keys keys() const = 0;
|
||||
@ -1790,7 +1791,7 @@ public:
|
||||
void setenv_() const;
|
||||
void load(const std::string &file);
|
||||
void load_from_ini(const std::string &file);
|
||||
void load_from_gcode_file(const std::string &file);
|
||||
void load_from_gcode_file(const std::string& file, bool check_header = true);
|
||||
// Returns number of key/value pairs extracted.
|
||||
size_t load_from_gcode_string(const char* str);
|
||||
void load(const boost::property_tree::ptree &tree);
|
||||
@ -1946,8 +1947,9 @@ public:
|
||||
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
|
||||
int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
|
||||
|
||||
// In ConfigManipulation::toggle_print_fff_options, it is called on option with type ConfigOptionEnumGeneric* and also ConfigOptionEnum*.
|
||||
template<typename ENUM>
|
||||
ENUM opt_enum(const t_config_option_key &opt_key) const { return (ENUM)dynamic_cast<const ConfigOptionEnumGeneric*>(this->option(opt_key))->value; }
|
||||
ENUM opt_enum(const t_config_option_key &opt_key) const { return this->option<ConfigOptionEnum<ENUM>>(opt_key)->value; }
|
||||
|
||||
bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
|
||||
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
|
||||
|
@ -25,90 +25,89 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
EdgeGrid::Grid::Grid() :
|
||||
m_rows(0), m_cols(0)
|
||||
{
|
||||
}
|
||||
|
||||
EdgeGrid::Grid::~Grid()
|
||||
{
|
||||
m_contours.clear();
|
||||
m_cell_data.clear();
|
||||
m_cells.clear();
|
||||
}
|
||||
|
||||
void EdgeGrid::Grid::create(const Polygons &polygons, coord_t resolution)
|
||||
{
|
||||
// Count the contours.
|
||||
size_t ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j].points.empty())
|
||||
++ ncontours;
|
||||
|
||||
// Collect the contours.
|
||||
m_contours.assign(ncontours, nullptr);
|
||||
ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j].points.empty())
|
||||
m_contours[ncontours ++] = &polygons[j].points;
|
||||
m_contours.clear();
|
||||
m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return ! p.empty(); }));
|
||||
for (const Polygon &polygon : polygons)
|
||||
if (! polygon.empty())
|
||||
m_contours.emplace_back(polygon.points, false);
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
}
|
||||
|
||||
void EdgeGrid::Grid::create(const std::vector<const Polygon*> &polygons, coord_t resolution)
|
||||
{
|
||||
// Count the contours.
|
||||
size_t ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j]->points.empty())
|
||||
++ ncontours;
|
||||
|
||||
// Collect the contours.
|
||||
m_contours.assign(ncontours, nullptr);
|
||||
ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j]->points.empty())
|
||||
m_contours[ncontours ++] = &polygons[j]->points;
|
||||
m_contours.clear();
|
||||
m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Polygon *p) { return ! p->empty(); }));
|
||||
for (const Polygon *polygon : polygons)
|
||||
if (! polygon->empty())
|
||||
m_contours.emplace_back(polygon->points, false);
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
}
|
||||
|
||||
void EdgeGrid::Grid::create(const std::vector<Points> &polygons, coord_t resolution)
|
||||
void EdgeGrid::Grid::create(const std::vector<Points> &polygons, coord_t resolution, bool open_polylines)
|
||||
{
|
||||
// Count the contours.
|
||||
size_t ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j].empty())
|
||||
++ ncontours;
|
||||
|
||||
// Collect the contours.
|
||||
m_contours.assign(ncontours, nullptr);
|
||||
ncontours = 0;
|
||||
for (size_t j = 0; j < polygons.size(); ++ j)
|
||||
if (! polygons[j].empty())
|
||||
m_contours[ncontours ++] = &polygons[j];
|
||||
m_contours.clear();
|
||||
m_contours.reserve(std::count_if(polygons.begin(), polygons.end(), [](const Points &p) { return p.size() > 1; }));
|
||||
for (const Points &points : polygons)
|
||||
if (points.size() > 1) {
|
||||
const Point *begin = points.data();
|
||||
const Point *end = points.data() + points.size();
|
||||
bool open = open_polylines;
|
||||
if (open_polylines) {
|
||||
if (*begin == end[-1]) {
|
||||
open = false;
|
||||
-- end;
|
||||
}
|
||||
} else
|
||||
assert(*begin != end[-1]);
|
||||
m_contours.emplace_back(begin, end, open);
|
||||
}
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
}
|
||||
|
||||
void EdgeGrid::Grid::create(const Polygons &polygons, const Polylines &polylines, coord_t resolution)
|
||||
{
|
||||
// Collect the contours.
|
||||
m_contours.clear();
|
||||
m_contours.reserve(
|
||||
std::count_if(polygons.begin(), polygons.end(), [](const Polygon &p) { return p.size() > 1; }) +
|
||||
std::count_if(polylines.begin(), polylines.end(), [](const Polyline &p) { return p.size() > 1; }));
|
||||
|
||||
for (const Polyline &polyline : polylines)
|
||||
if (polyline.size() > 1) {
|
||||
const Point *begin = polyline.points.data();
|
||||
const Point *end = polyline.points.data() + polyline.size();
|
||||
bool open = true;
|
||||
if (*begin == end[-1]) {
|
||||
open = false;
|
||||
-- end;
|
||||
}
|
||||
m_contours.emplace_back(begin, end, open);
|
||||
}
|
||||
|
||||
for (const Polygon &polygon : polygons)
|
||||
if (polygon.size() > 1)
|
||||
m_contours.emplace_back(polygon.points, false);
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
}
|
||||
|
||||
void EdgeGrid::Grid::create(const ExPolygon &expoly, coord_t resolution)
|
||||
{
|
||||
// Count the contours.
|
||||
size_t ncontours = 0;
|
||||
if (! expoly.contour.points.empty())
|
||||
++ ncontours;
|
||||
for (size_t j = 0; j < expoly.holes.size(); ++ j)
|
||||
if (! expoly.holes[j].points.empty())
|
||||
++ ncontours;
|
||||
|
||||
// Collect the contours.
|
||||
m_contours.assign(ncontours, nullptr);
|
||||
ncontours = 0;
|
||||
if (! expoly.contour.points.empty())
|
||||
m_contours[ncontours++] = &expoly.contour.points;
|
||||
for (size_t j = 0; j < expoly.holes.size(); ++ j)
|
||||
if (! expoly.holes[j].points.empty())
|
||||
m_contours[ncontours++] = &expoly.holes[j].points;
|
||||
m_contours.clear();
|
||||
m_contours.reserve((expoly.contour.empty() ? 0 : 1) + std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); }));
|
||||
if (! expoly.contour.empty())
|
||||
m_contours.emplace_back(expoly.contour.points, false);
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
if (! hole.empty())
|
||||
m_contours.emplace_back(hole.points, false);
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
}
|
||||
@ -117,25 +116,21 @@ void EdgeGrid::Grid::create(const ExPolygons &expolygons, coord_t resolution)
|
||||
{
|
||||
// Count the contours.
|
||||
size_t ncontours = 0;
|
||||
for (size_t i = 0; i < expolygons.size(); ++ i) {
|
||||
const ExPolygon &expoly = expolygons[i];
|
||||
if (! expoly.contour.points.empty())
|
||||
for (const ExPolygon &expoly : expolygons) {
|
||||
if (! expoly.contour.empty())
|
||||
++ ncontours;
|
||||
for (size_t j = 0; j < expoly.holes.size(); ++ j)
|
||||
if (! expoly.holes[j].points.empty())
|
||||
++ ncontours;
|
||||
ncontours += std::count_if(expoly.holes.begin(), expoly.holes.end(), [](const Polygon &p) { return ! p.empty(); });
|
||||
}
|
||||
|
||||
// Collect the contours.
|
||||
m_contours.assign(ncontours, nullptr);
|
||||
ncontours = 0;
|
||||
for (size_t i = 0; i < expolygons.size(); ++ i) {
|
||||
const ExPolygon &expoly = expolygons[i];
|
||||
if (! expoly.contour.points.empty())
|
||||
m_contours[ncontours++] = &expoly.contour.points;
|
||||
for (size_t j = 0; j < expoly.holes.size(); ++ j)
|
||||
if (! expoly.holes[j].points.empty())
|
||||
m_contours[ncontours++] = &expoly.holes[j].points;
|
||||
m_contours.clear();
|
||||
m_contours.reserve(ncontours);
|
||||
for (const ExPolygon &expoly : expolygons) {
|
||||
if (! expoly.contour.empty())
|
||||
m_contours.emplace_back(expoly.contour.points, false);
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
if (! hole.empty())
|
||||
m_contours.emplace_back(hole.points, false);
|
||||
}
|
||||
|
||||
create_from_m_contours(resolution);
|
||||
@ -151,11 +146,13 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||
{
|
||||
assert(resolution > 0);
|
||||
// 1) Measure the bounding box.
|
||||
for (size_t i = 0; i < m_contours.size(); ++ i) {
|
||||
const Slic3r::Points &pts = *m_contours[i];
|
||||
for (size_t j = 0; j < pts.size(); ++ j)
|
||||
m_bbox.merge(pts[j]);
|
||||
for (const Contour &contour : m_contours) {
|
||||
assert(contour.num_segments() > 0);
|
||||
assert(*contour.begin() != contour.end()[-1]);
|
||||
for (const Slic3r::Point &pt : contour)
|
||||
m_bbox.merge(pt);
|
||||
}
|
||||
|
||||
coord_t eps = 16;
|
||||
m_bbox.min(0) -= eps;
|
||||
m_bbox.min(1) -= eps;
|
||||
@ -170,11 +167,11 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||
|
||||
// 3) First round of contour rasterization, count the edges per grid cell.
|
||||
for (size_t i = 0; i < m_contours.size(); ++ i) {
|
||||
const Slic3r::Points &pts = *m_contours[i];
|
||||
for (size_t j = 0; j < pts.size(); ++ j) {
|
||||
const Contour &contour = m_contours[i];
|
||||
for (size_t j = 0; j < contour.num_segments(); ++ j) {
|
||||
// End points of the line segment.
|
||||
Slic3r::Point p1(pts[j]);
|
||||
Slic3r::Point p2 = pts[(j + 1 == pts.size()) ? 0 : j + 1];
|
||||
Slic3r::Point p1(contour.segment_start(j));
|
||||
Slic3r::Point p2(contour.segment_end(j));
|
||||
p1(0) -= m_bbox.min(0);
|
||||
p1(1) -= m_bbox.min(1);
|
||||
p2(0) -= m_bbox.min(0);
|
||||
@ -333,9 +330,9 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||
|
||||
assert(visitor.i == 0);
|
||||
for (; visitor.i < m_contours.size(); ++ visitor.i) {
|
||||
const Slic3r::Points &pts = *m_contours[visitor.i];
|
||||
for (visitor.j = 0; visitor.j < pts.size(); ++ visitor.j)
|
||||
this->visit_cells_intersecting_line(pts[visitor.j], pts[(visitor.j + 1 == pts.size()) ? 0 : visitor.j + 1], visitor);
|
||||
const Contour &contour = m_contours[visitor.i];
|
||||
for (visitor.j = 0; visitor.j < contour.num_segments(); ++ visitor.j)
|
||||
this->visit_cells_intersecting_line(contour.segment_start(visitor.j), contour.segment_end(visitor.j), visitor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -701,11 +698,12 @@ void EdgeGrid::Grid::calculate_sdf()
|
||||
const Cell &cell = m_cells[r * m_cols + c];
|
||||
// For each segment in the cell:
|
||||
for (size_t i = cell.begin; i != cell.end; ++ i) {
|
||||
const Slic3r::Points &pts = *m_contours[m_cell_data[i].first];
|
||||
const Contour &contour = m_contours[m_cell_data[i].first];
|
||||
assert(contour.closed());
|
||||
size_t ipt = m_cell_data[i].second;
|
||||
// End points of the line segment.
|
||||
const Slic3r::Point &p1 = pts[ipt];
|
||||
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
|
||||
const Slic3r::Point &p1 = contour.segment_start(ipt);
|
||||
const Slic3r::Point &p2 = contour.segment_end(ipt);
|
||||
// Segment vector
|
||||
const Slic3r::Point v_seg = p2 - p1;
|
||||
// l2 of v_seg
|
||||
@ -729,7 +727,7 @@ void EdgeGrid::Grid::calculate_sdf()
|
||||
double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
|
||||
if (dabs < d_min) {
|
||||
// Previous point.
|
||||
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
|
||||
const Slic3r::Point &p0 = contour.segment_prev(ipt);
|
||||
Slic3r::Point v_seg_prev = p1 - p0;
|
||||
int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
|
||||
if (t2_pt > 0) {
|
||||
@ -1049,7 +1047,7 @@ float EdgeGrid::Grid::signed_distance_bilinear(const Point &pt) const
|
||||
return f;
|
||||
}
|
||||
|
||||
EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt, coord_t search_radius) const
|
||||
EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point_signed_distance(const Point &pt, coord_t search_radius) const
|
||||
{
|
||||
BoundingBox bbox;
|
||||
bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
|
||||
@ -1088,12 +1086,13 @@ EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt
|
||||
for (int c = bbox.min(0); c <= bbox.max(0); ++ c) {
|
||||
const Cell &cell = m_cells[r * m_cols + c];
|
||||
for (size_t i = cell.begin; i < cell.end; ++ i) {
|
||||
const size_t contour_idx = m_cell_data[i].first;
|
||||
const Slic3r::Points &pts = *m_contours[contour_idx];
|
||||
const size_t contour_idx = m_cell_data[i].first;
|
||||
const Contour &contour = m_contours[contour_idx];
|
||||
assert(contour.closed());
|
||||
size_t ipt = m_cell_data[i].second;
|
||||
// End points of the line segment.
|
||||
const Slic3r::Point &p1 = pts[ipt];
|
||||
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
|
||||
const Slic3r::Point &p1 = contour.segment_start(ipt);
|
||||
const Slic3r::Point &p2 = contour.segment_end(ipt);
|
||||
const Slic3r::Point v_seg = p2 - p1;
|
||||
const Slic3r::Point v_pt = pt - p1;
|
||||
// dot(p2-p1, pt-p1)
|
||||
@ -1105,7 +1104,7 @@ EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt
|
||||
double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
|
||||
if (dabs < d_min) {
|
||||
// Previous point.
|
||||
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
|
||||
const Slic3r::Point &p0 = contour.segment_prev(ipt);
|
||||
Slic3r::Point v_seg_prev = p1 - p0;
|
||||
int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
|
||||
if (t2_pt > 0) {
|
||||
@ -1161,9 +1160,9 @@ EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt
|
||||
assert(result.t >= 0. && result.t <= 1.);
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
const Slic3r::Points &pts = *m_contours[result.contour_idx];
|
||||
const Slic3r::Point &p1 = pts[result.start_point_idx];
|
||||
const Slic3r::Point &p2 = pts[(result.start_point_idx + 1 == pts.size()) ? 0 : result.start_point_idx + 1];
|
||||
const Contour &contour = m_contours[result.contour_idx];
|
||||
const Slic3r::Point &p1 = contour.segment_start(result.start_point_idx);
|
||||
const Slic3r::Point &p2 = contour.segment_end(result.start_point_idx);
|
||||
Vec2d vfoot;
|
||||
if (result.t == 0)
|
||||
vfoot = p1.cast<double>() - pt.cast<double>();
|
||||
@ -1217,11 +1216,12 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu
|
||||
for (int c = bbox.min(0); c <= bbox.max(0); ++ c) {
|
||||
const Cell &cell = m_cells[r * m_cols + c];
|
||||
for (size_t i = cell.begin; i < cell.end; ++ i) {
|
||||
const Slic3r::Points &pts = *m_contours[m_cell_data[i].first];
|
||||
const Contour &contour = m_contours[m_cell_data[i].first];
|
||||
assert(contour.closed());
|
||||
size_t ipt = m_cell_data[i].second;
|
||||
// End points of the line segment.
|
||||
const Slic3r::Point &p1 = pts[ipt];
|
||||
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
|
||||
const Slic3r::Point &p1 = contour.segment_start(ipt);
|
||||
const Slic3r::Point &p2 = contour.segment_end(ipt);
|
||||
Slic3r::Point v_seg = p2 - p1;
|
||||
Slic3r::Point v_pt = pt - p1;
|
||||
// dot(p2-p1, pt-p1)
|
||||
@ -1233,7 +1233,7 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu
|
||||
double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
|
||||
if (dabs < d_min) {
|
||||
// Previous point.
|
||||
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
|
||||
const Slic3r::Point &p0 = contour.segment_prev(ipt);
|
||||
Slic3r::Point v_seg_prev = p1 - p0;
|
||||
int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
|
||||
if (t2_pt > 0) {
|
||||
@ -1423,26 +1423,26 @@ std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>>
|
||||
const Cell &cell = m_cells[r * m_cols + c];
|
||||
// For each pair of segments in the cell:
|
||||
for (size_t i = cell.begin; i != cell.end; ++ i) {
|
||||
const Slic3r::Points &ipts = *m_contours[m_cell_data[i].first];
|
||||
const Contour &icontour = m_contours[m_cell_data[i].first];
|
||||
size_t ipt = m_cell_data[i].second;
|
||||
// End points of the line segment and their vector.
|
||||
const Slic3r::Point &ip1 = ipts[ipt];
|
||||
const Slic3r::Point &ip2 = ipts[(ipt + 1 == ipts.size()) ? 0 : ipt + 1];
|
||||
const Slic3r::Point &ip1 = icontour.segment_start(ipt);
|
||||
const Slic3r::Point &ip2 = icontour.segment_end(ipt);
|
||||
for (size_t j = i + 1; j != cell.end; ++ j) {
|
||||
const Slic3r::Points &jpts = *m_contours[m_cell_data[j].first];
|
||||
size_t jpt = m_cell_data[j].second;
|
||||
const Contour &jcontour = m_contours[m_cell_data[j].first];
|
||||
size_t jpt = m_cell_data[j].second;
|
||||
// End points of the line segment and their vector.
|
||||
const Slic3r::Point &jp1 = jpts[jpt];
|
||||
const Slic3r::Point &jp2 = jpts[(jpt + 1 == jpts.size()) ? 0 : jpt + 1];
|
||||
if (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2))
|
||||
const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
|
||||
const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
|
||||
if (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2))
|
||||
// Segments of the same contour share a common vertex.
|
||||
continue;
|
||||
if (Geometry::segments_intersect(ip1, ip2, jp1, jp2)) {
|
||||
// The two segments intersect. Add them to the output.
|
||||
int jfirst = (&jpts < &ipts) || (&jpts == &ipts && jpt < ipt);
|
||||
int jfirst = (&jcontour < &icontour) || (&jcontour == &icontour && jpt < ipt);
|
||||
out.emplace_back(jfirst ?
|
||||
std::make_pair(std::make_pair(&ipts, ipt), std::make_pair(&jpts, jpt)) :
|
||||
std::make_pair(std::make_pair(&ipts, ipt), std::make_pair(&jpts, jpt)));
|
||||
std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)) :
|
||||
std::make_pair(std::make_pair(&icontour, ipt), std::make_pair(&jcontour, jpt)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1460,18 +1460,18 @@ bool EdgeGrid::Grid::has_intersecting_edges() const
|
||||
const Cell &cell = m_cells[r * m_cols + c];
|
||||
// For each pair of segments in the cell:
|
||||
for (size_t i = cell.begin; i != cell.end; ++ i) {
|
||||
const Slic3r::Points &ipts = *m_contours[m_cell_data[i].first];
|
||||
const Contour &icontour = m_contours[m_cell_data[i].first];
|
||||
size_t ipt = m_cell_data[i].second;
|
||||
// End points of the line segment and their vector.
|
||||
const Slic3r::Point &ip1 = ipts[ipt];
|
||||
const Slic3r::Point &ip2 = ipts[(ipt + 1 == ipts.size()) ? 0 : ipt + 1];
|
||||
const Slic3r::Point &ip1 = icontour.segment_start(ipt);
|
||||
const Slic3r::Point &ip2 = icontour.segment_end(ipt);
|
||||
for (size_t j = i + 1; j != cell.end; ++ j) {
|
||||
const Slic3r::Points &jpts = *m_contours[m_cell_data[j].first];
|
||||
const Contour &jcontour = m_contours[m_cell_data[j].first];
|
||||
size_t jpt = m_cell_data[j].second;
|
||||
// End points of the line segment and their vector.
|
||||
const Slic3r::Point &jp1 = jpts[jpt];
|
||||
const Slic3r::Point &jp2 = jpts[(jpt + 1 == jpts.size()) ? 0 : jpt + 1];
|
||||
if (! (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2)) &&
|
||||
const Slic3r::Point &jp1 = jcontour.segment_start(jpt);
|
||||
const Slic3r::Point &jp2 = jcontour.segment_end(jpt);
|
||||
if (! (&icontour == &jcontour && (&ip1 == &jp2 || &jp1 == &ip2)) &&
|
||||
Geometry::segments_intersect(ip1, ip2, jp1, jp2))
|
||||
return true;
|
||||
}
|
||||
@ -1606,22 +1606,27 @@ void export_intersections_to_svg(const std::string &filename, const Polygons &po
|
||||
SVG svg(filename.c_str(), bbox);
|
||||
svg.draw(union_ex(polygons), "gray", 0.25f);
|
||||
svg.draw_outline(polygons, "black");
|
||||
std::set<const Points*> intersecting_contours;
|
||||
std::set<const EdgeGrid::Contour*> intersecting_contours;
|
||||
for (const std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge> &ie : intersections) {
|
||||
intersecting_contours.insert(ie.first.first);
|
||||
intersecting_contours.insert(ie.second.first);
|
||||
}
|
||||
// Highlight the contours with intersections.
|
||||
coord_t line_width = coord_t(scale_(0.01));
|
||||
for (const Points *ic : intersecting_contours) {
|
||||
svg.draw_outline(Polygon(*ic), "green");
|
||||
svg.draw_outline(Polygon(*ic), "black", line_width);
|
||||
for (const EdgeGrid::Contour *ic : intersecting_contours) {
|
||||
if (ic->open())
|
||||
svg.draw(Polyline(Points(ic->begin(), ic->end())), "green");
|
||||
else {
|
||||
Polygon polygon(Points(ic->begin(), ic->end()));
|
||||
svg.draw_outline(polygon, "green");
|
||||
svg.draw_outline(polygon, "black", line_width);
|
||||
}
|
||||
}
|
||||
// Paint the intersections.
|
||||
for (const std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge> &intersecting_edges : intersections) {
|
||||
auto edge = [](const EdgeGrid::Grid::ContourEdge &e) {
|
||||
return Line(e.first->at(e.second),
|
||||
e.first->at((e.second + 1 == e.first->size()) ? 0 : e.second + 1));
|
||||
return Line(e.first->segment_start(e.second),
|
||||
e.first->segment_end(e.second));
|
||||
};
|
||||
svg.draw(edge(intersecting_edges.first), "red", line_width);
|
||||
svg.draw(edge(intersecting_edges.second), "red", line_width);
|
||||
|
@ -12,22 +12,89 @@
|
||||
namespace Slic3r {
|
||||
namespace EdgeGrid {
|
||||
|
||||
|
||||
class Contour {
|
||||
public:
|
||||
Contour() = default;
|
||||
Contour(const Slic3r::Point *begin, const Slic3r::Point *end, bool open) : m_begin(begin), m_end(end), m_open(open) {}
|
||||
Contour(const Slic3r::Point *data, size_t size, bool open) : Contour(data, data + size, open) {}
|
||||
Contour(const std::vector<Slic3r::Point> &pts, bool open) : Contour(pts.data(), pts.size(), open) {}
|
||||
|
||||
const Slic3r::Point *begin() const { return m_begin; }
|
||||
const Slic3r::Point *end() const { return m_end; }
|
||||
bool open() const { return m_open; }
|
||||
bool closed() const { return ! m_open; }
|
||||
|
||||
// Start point of a segment idx.
|
||||
const Slic3r::Point& segment_start(size_t idx) const {
|
||||
assert(idx < this->num_segments());
|
||||
return m_begin[idx];
|
||||
}
|
||||
|
||||
// End point of a segment idx.
|
||||
const Slic3r::Point& segment_end(size_t idx) const {
|
||||
assert(idx < this->num_segments());
|
||||
const Slic3r::Point *ptr = m_begin + idx + 1;
|
||||
return ptr == m_end ? *m_begin : *ptr;
|
||||
}
|
||||
|
||||
// Start point of a segment preceding idx.
|
||||
const Slic3r::Point& segment_prev(size_t idx) const {
|
||||
assert(idx < this->num_segments());
|
||||
assert(idx > 0 || ! m_open);
|
||||
return idx == 0 ? m_end[-1] : m_begin[idx - 1];
|
||||
}
|
||||
|
||||
// Index of a segment preceding idx.
|
||||
const size_t segment_idx_prev(size_t idx) const {
|
||||
assert(idx < this->num_segments());
|
||||
assert(idx > 0 || ! m_open);
|
||||
return (idx == 0 ? this->size() : idx) - 1;
|
||||
}
|
||||
|
||||
// Index of a segment preceding idx.
|
||||
const size_t segment_idx_next(size_t idx) const {
|
||||
assert(idx < this->num_segments());
|
||||
++ idx;
|
||||
return m_begin + idx == m_end ? 0 : idx;
|
||||
}
|
||||
|
||||
size_t num_segments() const { return this->size() - (m_open ? 1 : 0); }
|
||||
|
||||
private:
|
||||
size_t size() const { return m_end - m_begin; }
|
||||
|
||||
const Slic3r::Point *m_begin { nullptr };
|
||||
const Slic3r::Point *m_end { nullptr };
|
||||
bool m_open { false };
|
||||
};
|
||||
|
||||
class Grid
|
||||
{
|
||||
public:
|
||||
Grid();
|
||||
~Grid();
|
||||
Grid() = default;
|
||||
Grid(const BoundingBox &bbox) : m_bbox(bbox) {}
|
||||
|
||||
void set_bbox(const BoundingBox &bbox) { m_bbox = bbox; }
|
||||
|
||||
// Fill in the grid with open polylines or closed contours.
|
||||
// If open flag is indicated, then polylines_or_polygons are considered to be open by default.
|
||||
// Only if the first point of a polyline is equal to the last point of a polyline,
|
||||
// then the polyline is considered to be closed and the last repeated point is removed when
|
||||
// inserted into the EdgeGrid.
|
||||
// Most of the Grid functions expect all the contours to be closed, you have been warned!
|
||||
void create(const std::vector<Points> &polylines_or_polygons, coord_t resolution, bool open);
|
||||
void create(const Polygons &polygons, const Polylines &polylines, coord_t resolution);
|
||||
|
||||
// Fill in the grid with closed contours.
|
||||
void create(const Polygons &polygons, coord_t resolution);
|
||||
void create(const std::vector<const Polygon*> &polygons, coord_t resolution);
|
||||
void create(const std::vector<Points> &polygons, coord_t resolution);
|
||||
void create(const std::vector<Points> &polygons, coord_t resolution) { this->create(polygons, resolution, false); }
|
||||
void create(const ExPolygon &expoly, coord_t resolution);
|
||||
void create(const ExPolygons &expolygons, coord_t resolution);
|
||||
void create(const ExPolygonCollection &expolygons, coord_t resolution);
|
||||
|
||||
const std::vector<const Slic3r::Points*>& contours() const { return m_contours; }
|
||||
const std::vector<Contour>& contours() const { return m_contours; }
|
||||
|
||||
#if 0
|
||||
// Test, whether the edges inside the grid intersect with the polygons provided.
|
||||
@ -44,12 +111,14 @@ public:
|
||||
|
||||
// Fill in a rough m_signed_distance_field from the edge grid.
|
||||
// The rough SDF is used by signed_distance() for distances outside of the search_radius.
|
||||
// Only call this function for closed contours!
|
||||
void calculate_sdf();
|
||||
|
||||
// Return an estimate of the signed distance based on m_signed_distance_field grid.
|
||||
float signed_distance_bilinear(const Point &pt) const;
|
||||
|
||||
// Calculate a signed distance to the contours in search_radius from the point.
|
||||
// Only call this function for closed contours!
|
||||
struct ClosestPointResult {
|
||||
size_t contour_idx = size_t(-1);
|
||||
size_t start_point_idx = size_t(-1);
|
||||
@ -60,12 +129,14 @@ public:
|
||||
|
||||
bool valid() const { return contour_idx != size_t(-1); }
|
||||
};
|
||||
ClosestPointResult closest_point(const Point &pt, coord_t search_radius) const;
|
||||
ClosestPointResult closest_point_signed_distance(const Point &pt, coord_t search_radius) const;
|
||||
|
||||
// Only call this function for closed contours!
|
||||
bool signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment = nullptr) const;
|
||||
|
||||
// Calculate a signed distance to the contours in search_radius from the point. If no edge is found in search_radius,
|
||||
// return an interpolated value from m_signed_distance_field, if it exists.
|
||||
// Only call this function for closed contours!
|
||||
bool signed_distance(const Point &pt, coord_t search_radius, coordf_t &result_min_dist) const;
|
||||
|
||||
const BoundingBox& bbox() const { return m_bbox; }
|
||||
@ -76,8 +147,8 @@ public:
|
||||
// For supports: Contours enclosing the rasterized edges.
|
||||
Polygons contours_simplified(coord_t offset, bool fill_holes) const;
|
||||
|
||||
typedef std::pair<const Slic3r::Points*, size_t> ContourPoint;
|
||||
typedef std::pair<const Slic3r::Points*, size_t> ContourEdge;
|
||||
typedef std::pair<const Contour*, size_t> ContourPoint;
|
||||
typedef std::pair<const Contour*, size_t> ContourEdge;
|
||||
std::vector<std::pair<ContourEdge, ContourEdge>> intersecting_edges() const;
|
||||
bool has_intersecting_edges() const;
|
||||
|
||||
@ -255,16 +326,16 @@ public:
|
||||
|
||||
std::pair<const Slic3r::Point&, const Slic3r::Point&> segment(const std::pair<size_t, size_t> &contour_and_segment_idx) const
|
||||
{
|
||||
const Slic3r::Points &ipts = *m_contours[contour_and_segment_idx.first];
|
||||
size_t ipt = contour_and_segment_idx.second;
|
||||
return std::pair<const Slic3r::Point&, const Slic3r::Point&>(ipts[ipt], ipts[ipt + 1 == ipts.size() ? 0 : ipt + 1]);
|
||||
const Contour &contour = m_contours[contour_and_segment_idx.first];
|
||||
size_t iseg = contour_and_segment_idx.second;
|
||||
return std::pair<const Slic3r::Point&, const Slic3r::Point&>(contour.segment_start(iseg), contour.segment_end(iseg));
|
||||
}
|
||||
|
||||
Line line(const std::pair<size_t, size_t> &contour_and_segment_idx) const
|
||||
{
|
||||
const Slic3r::Points &ipts = *m_contours[contour_and_segment_idx.first];
|
||||
size_t ipt = contour_and_segment_idx.second;
|
||||
return Line(ipts[ipt], ipts[ipt + 1 == ipts.size() ? 0 : ipt + 1]);
|
||||
const Contour &contour = m_contours[contour_and_segment_idx.first];
|
||||
size_t iseg = contour_and_segment_idx.second;
|
||||
return Line(contour.segment_start(iseg), contour.segment_end(iseg));
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -295,13 +366,13 @@ protected:
|
||||
BoundingBox m_bbox;
|
||||
// Grid dimensions.
|
||||
coord_t m_resolution;
|
||||
size_t m_rows;
|
||||
size_t m_cols;
|
||||
size_t m_rows = 0;
|
||||
size_t m_cols = 0;
|
||||
|
||||
// Referencing the source contours.
|
||||
// This format allows one to work with any Slic3r fixed point contour format
|
||||
// (Polygon, ExPolygon, ExPolygonCollection etc).
|
||||
std::vector<const Slic3r::Points*> m_contours;
|
||||
std::vector<Contour> m_contours;
|
||||
|
||||
// Referencing a contour and a line segment of m_contours.
|
||||
std::vector<std::pair<size_t, size_t> > m_cell_data;
|
||||
|
@ -104,7 +104,7 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx
|
||||
double param_hi;
|
||||
double param_end = resampled_point_parameters.back().curve_parameter;
|
||||
{
|
||||
const Slic3r::Points &ipts = *grid.contours()[it_contour_and_segment->first];
|
||||
const EdgeGrid::Contour &contour = grid.contours()[it_contour_and_segment->first];
|
||||
size_t ipt = it_contour_and_segment->second;
|
||||
ResampledPoint key(ipt, false, 0.);
|
||||
auto lower = [](const ResampledPoint& l, const ResampledPoint r) { return l.idx_src < r.idx_src || (l.idx_src == r.idx_src && int(l.interpolated) > int(r.interpolated)); };
|
||||
@ -112,7 +112,7 @@ std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx
|
||||
assert(it != resampled_point_parameters.end() && it->idx_src == ipt && ! it->interpolated);
|
||||
double t2 = cross2(dir, vptpt2) / denom;
|
||||
assert(t2 > - EPSILON && t2 < 1. + EPSILON);
|
||||
if (++ ipt == ipts.size())
|
||||
if (contour.begin() + (++ ipt) == contour.end())
|
||||
param_hi = t2 * dir2.norm();
|
||||
else
|
||||
param_hi = it->curve_parameter + t2 * dir2.norm();
|
||||
@ -251,7 +251,7 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
|
||||
#endif
|
||||
struct Visitor {
|
||||
Visitor(const EdgeGrid::Grid &grid, const size_t idx_contour, const std::vector<ResampledPoint> &resampled_point_parameters, double dist_same_contour_accept, double dist_same_contour_reject) :
|
||||
grid(grid), idx_contour(idx_contour), contour(*grid.contours()[idx_contour]), resampled_point_parameters(resampled_point_parameters), dist_same_contour_accept(dist_same_contour_accept), dist_same_contour_reject(dist_same_contour_reject) {}
|
||||
grid(grid), idx_contour(idx_contour), contour(grid.contours()[idx_contour]), resampled_point_parameters(resampled_point_parameters), dist_same_contour_accept(dist_same_contour_accept), dist_same_contour_reject(dist_same_contour_reject) {}
|
||||
|
||||
void init(const Points &contour, const Point &apoint) {
|
||||
this->idx_point = &apoint - contour.data();
|
||||
@ -283,15 +283,15 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
|
||||
double param_lo = resampled_point_parameters[this->idx_point].curve_parameter;
|
||||
double param_hi;
|
||||
double param_end = resampled_point_parameters.back().curve_parameter;
|
||||
const Slic3r::Points &ipts = *grid.contours()[it_contour_and_segment->first];
|
||||
const size_t ipt = it_contour_and_segment->second;
|
||||
const EdgeGrid::Contour &contour = grid.contours()[it_contour_and_segment->first];
|
||||
const size_t ipt = it_contour_and_segment->second;
|
||||
{
|
||||
ResampledPoint key(ipt, false, 0.);
|
||||
auto lower = [](const ResampledPoint& l, const ResampledPoint r) { return l.idx_src < r.idx_src || (l.idx_src == r.idx_src && int(l.interpolated) > int(r.interpolated)); };
|
||||
auto it = std::lower_bound(resampled_point_parameters.begin(), resampled_point_parameters.end(), key, lower);
|
||||
assert(it != resampled_point_parameters.end() && it->idx_src == ipt && ! it->interpolated);
|
||||
param_hi = t * sqrt(l2);
|
||||
if (ipt + 1 < ipts.size())
|
||||
if (contour.begin() + ipt + 1 < contour.end())
|
||||
param_hi += it->curve_parameter;
|
||||
}
|
||||
if (param_lo > param_hi)
|
||||
@ -307,9 +307,9 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
|
||||
// Bulge is estimated by 0.6 of the circle circumference drawn around the bisector.
|
||||
// Test whether the contour is convex or concave.
|
||||
bool inside =
|
||||
(t == 0.) ? this->inside_corner(ipts, ipt, this->point) :
|
||||
(t == 1.) ? this->inside_corner(ipts, ipt + 1 == ipts.size() ? 0 : ipt + 1, this->point) :
|
||||
this->left_of_segment(ipts, ipt, this->point);
|
||||
(t == 0.) ? this->inside_corner(contour, ipt, this->point) :
|
||||
(t == 1.) ? this->inside_corner(contour, contour.segment_idx_next(ipt), this->point) :
|
||||
this->left_of_segment(contour, ipt, this->point);
|
||||
accept = inside && dist_along_contour > 0.6 * M_PI * dist;
|
||||
}
|
||||
}
|
||||
@ -329,7 +329,7 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
const size_t idx_contour;
|
||||
const Points &contour;
|
||||
const EdgeGrid::Contour &contour;
|
||||
const std::vector<ResampledPoint> &resampled_point_parameters;
|
||||
const double dist_same_contour_accept;
|
||||
const double dist_same_contour_reject;
|
||||
@ -358,24 +358,28 @@ std::vector<float> contour_distance2(const EdgeGrid::Grid &grid, const size_t id
|
||||
return Vec2d(- v.y(), v.x());
|
||||
}
|
||||
|
||||
static bool inside_corner(const Slic3r::Points &contour, size_t i, const Point &pt_oposite) {
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
size_t iprev = prev_idx_modulo(i, contour);
|
||||
size_t inext = next_idx_modulo(i, contour);
|
||||
Vec2d v1 = (contour[i] - contour[iprev]).cast<double>();
|
||||
Vec2d v2 = (contour[inext] - contour[i]).cast<double>();
|
||||
bool left_of_v1 = cross2(v1, pt - contour[iprev].cast<double>()) > 0.;
|
||||
bool left_of_v2 = cross2(v2, pt - contour[i ].cast<double>()) > 0.;
|
||||
return cross2(v1, v2) > 0 ?
|
||||
left_of_v1 && left_of_v2 : // convex corner
|
||||
left_of_v1 || left_of_v2; // concave corner
|
||||
}
|
||||
static bool left_of_segment(const Slic3r::Points &contour, size_t i, const Point &pt_oposite) {
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
size_t inext = next_idx_modulo(i, contour);
|
||||
Vec2d v = (contour[inext] - contour[i]).cast<double>();
|
||||
return cross2(v, pt - contour[i].cast<double>()) > 0.;
|
||||
}
|
||||
static bool inside_corner(const EdgeGrid::Contour &contour, size_t i, const Point &pt_oposite)
|
||||
{
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
const Point &pt_prev = contour.segment_prev(i);
|
||||
const Point &pt_this = contour.segment_start(i);
|
||||
const Point &pt_next = contour.segment_end(i);
|
||||
Vec2d v1 = (pt_this - pt_prev).cast<double>();
|
||||
Vec2d v2 = (pt_next - pt_this).cast<double>();
|
||||
bool left_of_v1 = cross2(v1, pt - pt_prev.cast<double>()) > 0.;
|
||||
bool left_of_v2 = cross2(v2, pt - pt_this.cast<double>()) > 0.;
|
||||
return cross2(v1, v2) > 0 ? left_of_v1 && left_of_v2 : // convex corner
|
||||
left_of_v1 || left_of_v2; // concave corner
|
||||
}
|
||||
|
||||
static bool left_of_segment(const EdgeGrid::Contour &contour, size_t i, const Point &pt_oposite)
|
||||
{
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
const Point &pt_this = contour.segment_start(i);
|
||||
const Point &pt_next = contour.segment_end(i);
|
||||
Vec2d v = (pt_next - pt_this).cast<double>();
|
||||
return cross2(v, pt - pt_this.cast<double>()) > 0.;
|
||||
}
|
||||
} visitor(grid, idx_contour, resampled_point_parameters, 0.5 * compensation * M_PI, search_radius);
|
||||
|
||||
out.reserve(contour.size());
|
||||
@ -441,6 +445,7 @@ Points resample_polygon(const Points &contour, double dist, std::vector<Resample
|
||||
return out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline void smooth_compensation(std::vector<float> &compensation, float strength, size_t num_iterations)
|
||||
{
|
||||
std::vector<float> out(compensation);
|
||||
@ -455,6 +460,7 @@ static inline void smooth_compensation(std::vector<float> &compensation, float s
|
||||
out.swap(compensation);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void smooth_compensation_banded(const Points &contour, float band, std::vector<float> &compensation, float strength, size_t num_iterations)
|
||||
{
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include "Line.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "polypartition.h"
|
||||
#include "poly2tri/poly2tri.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
@ -80,6 +78,13 @@ bool ExPolygon::is_valid() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExPolygon::douglas_peucker(double tolerance)
|
||||
{
|
||||
this->contour.douglas_peucker(tolerance);
|
||||
for (Polygon &poly : this->holes)
|
||||
poly.douglas_peucker(tolerance);
|
||||
}
|
||||
|
||||
bool ExPolygon::contains(const Line &line) const
|
||||
{
|
||||
return this->contains(Polyline(line.a, line.b));
|
||||
@ -311,284 +316,6 @@ ExPolygon::medial_axis(double max_width, double min_width, Polylines* polylines)
|
||||
polylines->insert(polylines->end(), tp.begin(), tp.end());
|
||||
}
|
||||
|
||||
/*
|
||||
void ExPolygon::get_trapezoids(Polygons* polygons) const
|
||||
{
|
||||
ExPolygons expp;
|
||||
expp.push_back(*this);
|
||||
boost::polygon::get_trapezoids(*polygons, expp);
|
||||
}
|
||||
|
||||
void ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
|
||||
{
|
||||
ExPolygon clone = *this;
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
clone.get_trapezoids(polygons);
|
||||
for (Polygons::iterator polygon = polygons->begin(); polygon != polygons->end(); ++polygon)
|
||||
polygon->rotate(-(PI/2 - angle), Point(0,0));
|
||||
}
|
||||
*/
|
||||
|
||||
// This algorithm may return more trapezoids than necessary
|
||||
// (i.e. it may break a single trapezoid in several because
|
||||
// other parts of the object have x coordinates in the middle)
|
||||
void ExPolygon::get_trapezoids2(Polygons* polygons) const
|
||||
{
|
||||
// get all points of this ExPolygon
|
||||
Points pp = *this;
|
||||
|
||||
// build our bounding box
|
||||
BoundingBox bb(pp);
|
||||
|
||||
// get all x coordinates
|
||||
std::vector<coord_t> xx;
|
||||
xx.reserve(pp.size());
|
||||
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p)
|
||||
xx.push_back(p->x());
|
||||
std::sort(xx.begin(), xx.end());
|
||||
|
||||
// find trapezoids by looping from first to next-to-last coordinate
|
||||
for (std::vector<coord_t>::const_iterator x = xx.begin(); x != xx.end()-1; ++x) {
|
||||
coord_t next_x = *(x + 1);
|
||||
if (*x != next_x)
|
||||
// intersect with rectangle
|
||||
// append results to return value
|
||||
polygons_append(*polygons, intersection({ { { *x, bb.min.y() }, { next_x, bb.min.y() }, { next_x, bb.max.y() }, { *x, bb.max.y() } } }, to_polygons(*this)));
|
||||
}
|
||||
}
|
||||
|
||||
void ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
|
||||
{
|
||||
ExPolygon clone = *this;
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
clone.get_trapezoids2(polygons);
|
||||
for (Polygons::iterator polygon = polygons->begin(); polygon != polygons->end(); ++polygon)
|
||||
polygon->rotate(-(PI/2 - angle), Point(0,0));
|
||||
}
|
||||
|
||||
// While this triangulates successfully, it's NOT a constrained triangulation
|
||||
// as it will create more vertices on the boundaries than the ones supplied.
|
||||
void ExPolygon::triangulate(Polygons* polygons) const
|
||||
{
|
||||
// first make trapezoids
|
||||
Polygons trapezoids;
|
||||
this->get_trapezoids2(&trapezoids);
|
||||
|
||||
// then triangulate each trapezoid
|
||||
for (Polygons::iterator polygon = trapezoids.begin(); polygon != trapezoids.end(); ++polygon)
|
||||
polygon->triangulate_convex(polygons);
|
||||
}
|
||||
|
||||
/*
|
||||
void ExPolygon::triangulate_pp(Polygons* polygons) const
|
||||
{
|
||||
// convert polygons
|
||||
std::list<TPPLPoly> input;
|
||||
|
||||
ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true));
|
||||
|
||||
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||
// contour
|
||||
{
|
||||
TPPLPoly p;
|
||||
p.Init(int(ex->contour.points.size()));
|
||||
//printf("%zu\n0\n", ex->contour.points.size());
|
||||
for (const Point &point : ex->contour.points) {
|
||||
size_t i = &point - &ex->contour.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
//printf("%ld %ld\n", point->x(), point->y());
|
||||
}
|
||||
p.SetHole(false);
|
||||
input.push_back(p);
|
||||
}
|
||||
|
||||
// holes
|
||||
for (Polygons::const_iterator hole = ex->holes.begin(); hole != ex->holes.end(); ++hole) {
|
||||
TPPLPoly p;
|
||||
p.Init(hole->points.size());
|
||||
//printf("%zu\n1\n", hole->points.size());
|
||||
for (const Point &point : hole->points) {
|
||||
size_t i = &point - &hole->points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
//printf("%ld %ld\n", point->x(), point->y());
|
||||
}
|
||||
p.SetHole(true);
|
||||
input.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
// perform triangulation
|
||||
std::list<TPPLPoly> output;
|
||||
int res = TPPLPartition().Triangulate_MONO(&input, &output);
|
||||
if (res != 1)
|
||||
throw Slic3r::RuntimeError("Triangulation failed");
|
||||
|
||||
// convert output polygons
|
||||
for (std::list<TPPLPoly>::iterator poly = output.begin(); poly != output.end(); ++poly) {
|
||||
long num_points = poly->GetNumPoints();
|
||||
Polygon p;
|
||||
p.points.resize(num_points);
|
||||
for (long i = 0; i < num_points; ++i) {
|
||||
p.points[i](0) = coord_t((*poly)[i].x);
|
||||
p.points[i](1) = coord_t((*poly)[i].y);
|
||||
}
|
||||
polygons->push_back(p);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex)
|
||||
{
|
||||
std::list<TPPLPoly> input;
|
||||
// contour
|
||||
{
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(int(ex.contour.points.size()));
|
||||
for (const Point &point : ex.contour.points) {
|
||||
size_t i = &point - &ex.contour.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(false);
|
||||
}
|
||||
// holes
|
||||
for (const Polygon &hole : ex.holes) {
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(hole.points.size());
|
||||
for (const Point &point : hole.points) {
|
||||
size_t i = &point - &hole.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(true);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expps)
|
||||
{
|
||||
std::list<TPPLPoly> input;
|
||||
for (const ExPolygon &ex : expps) {
|
||||
// contour
|
||||
{
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(int(ex.contour.points.size()));
|
||||
for (const Point &point : ex.contour.points) {
|
||||
size_t i = &point - &ex.contour.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(false);
|
||||
}
|
||||
// holes
|
||||
for (const Polygon &hole : ex.holes) {
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(hole.points.size());
|
||||
for (const Point &point : hole.points) {
|
||||
size_t i = &point - &hole.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(true);
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output)
|
||||
{
|
||||
size_t num_triangles = 0;
|
||||
for (const TPPLPoly &poly : output)
|
||||
if (poly.GetNumPoints() >= 3)
|
||||
num_triangles += (size_t)poly.GetNumPoints() - 2;
|
||||
std::vector<Point> triangles;
|
||||
triangles.reserve(triangles.size() + num_triangles * 3);
|
||||
for (const TPPLPoly &poly : output) {
|
||||
long num_points = poly.GetNumPoints();
|
||||
if (num_points >= 3) {
|
||||
const TPPLPoint *pt0 = &poly[0];
|
||||
const TPPLPoint *pt1 = nullptr;
|
||||
const TPPLPoint *pt2 = &poly[1];
|
||||
for (long i = 2; i < num_points; ++ i) {
|
||||
pt1 = pt2;
|
||||
pt2 = &poly[i];
|
||||
triangles.emplace_back(coord_t(pt0->x), coord_t(pt0->y));
|
||||
triangles.emplace_back(coord_t(pt1->x), coord_t(pt1->y));
|
||||
triangles.emplace_back(coord_t(pt2->x), coord_t(pt2->y));
|
||||
}
|
||||
}
|
||||
}
|
||||
return triangles;
|
||||
}
|
||||
|
||||
void ExPolygon::triangulate_pp(Points *triangles) const
|
||||
{
|
||||
ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true));
|
||||
std::list<TPPLPoly> input = expoly_to_polypartition_input(expp);
|
||||
// perform triangulation
|
||||
std::list<TPPLPoly> output;
|
||||
int res = TPPLPartition().Triangulate_MONO(&input, &output);
|
||||
// int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
|
||||
if (res != 1)
|
||||
throw Slic3r::RuntimeError("Triangulation failed");
|
||||
*triangles = polypartition_output_to_triangles(output);
|
||||
}
|
||||
|
||||
// Uses the Poly2tri library maintained by Jan Niklas Hasse @jhasse // https://github.com/jhasse/poly2tri
|
||||
// See https://github.com/jhasse/poly2tri/blob/master/README.md for the limitations of the library!
|
||||
// No duplicate points are allowed, no very close points, holes must not touch outer contour etc.
|
||||
void ExPolygon::triangulate_p2t(Polygons* polygons) const
|
||||
{
|
||||
ExPolygons expp = simplify_polygons_ex(*this, true);
|
||||
|
||||
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||
// TODO: prevent duplicate points
|
||||
|
||||
// contour
|
||||
std::vector<p2t::Point*> ContourPoints;
|
||||
for (const Point &pt : ex->contour.points)
|
||||
// We should delete each p2t::Point object
|
||||
ContourPoints.push_back(new p2t::Point(pt(0), pt(1)));
|
||||
p2t::CDT cdt(ContourPoints);
|
||||
|
||||
// holes
|
||||
for (Polygons::const_iterator hole = ex->holes.begin(); hole != ex->holes.end(); ++hole) {
|
||||
std::vector<p2t::Point*> points;
|
||||
for (const Point &pt : hole->points)
|
||||
// will be destructed in SweepContext::~SweepContext
|
||||
points.push_back(new p2t::Point(pt(0), pt(1)));
|
||||
cdt.AddHole(points);
|
||||
}
|
||||
|
||||
// perform triangulation
|
||||
try {
|
||||
cdt.Triangulate();
|
||||
std::vector<p2t::Triangle*> triangles = cdt.GetTriangles();
|
||||
|
||||
for (std::vector<p2t::Triangle*>::const_iterator triangle = triangles.begin(); triangle != triangles.end(); ++triangle) {
|
||||
Polygon p;
|
||||
for (int i = 0; i <= 2; ++i) {
|
||||
p2t::Point* point = (*triangle)->GetPoint(i);
|
||||
p.points.push_back(Point(point->x, point->y));
|
||||
}
|
||||
polygons->push_back(p);
|
||||
}
|
||||
} catch (const Slic3r::RuntimeError & /* err */) {
|
||||
assert(false);
|
||||
// just ignore, don't triangulate
|
||||
}
|
||||
|
||||
for (p2t::Point *ptr : ContourPoints)
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
|
||||
Lines ExPolygon::lines() const
|
||||
{
|
||||
Lines lines = this->contour.lines();
|
||||
|
@ -6,9 +6,6 @@
|
||||
#include "Polyline.hpp"
|
||||
#include <vector>
|
||||
|
||||
// polygon class of the polypartition library
|
||||
class TPPLPoly;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ExPolygon;
|
||||
@ -49,6 +46,7 @@ public:
|
||||
double area() const;
|
||||
bool empty() const { return contour.points.empty(); }
|
||||
bool is_valid() const;
|
||||
void douglas_peucker(double tolerance);
|
||||
|
||||
// Contains the line / polyline / polylines etc COMPLETELY.
|
||||
bool contains(const Line &line) const;
|
||||
@ -69,14 +67,6 @@ public:
|
||||
void simplify(double tolerance, ExPolygons* expolygons) const;
|
||||
void medial_axis(double max_width, double min_width, ThickPolylines* polylines) const;
|
||||
void medial_axis(double max_width, double min_width, Polylines* polylines) const;
|
||||
// void get_trapezoids(Polygons* polygons) const;
|
||||
// void get_trapezoids(Polygons* polygons, double angle) const;
|
||||
void get_trapezoids2(Polygons* polygons) const;
|
||||
void get_trapezoids2(Polygons* polygons, double angle) const;
|
||||
void triangulate(Polygons* polygons) const;
|
||||
// Triangulate into triples of points.
|
||||
void triangulate_pp(Points *triangles) const;
|
||||
void triangulate_p2t(Polygons* polygons) const;
|
||||
Lines lines() const;
|
||||
|
||||
// Number of contours (outer contour with holes).
|
||||
@ -249,6 +239,24 @@ inline Polygons to_polygons(ExPolygons &&src)
|
||||
return polygons;
|
||||
}
|
||||
|
||||
inline ExPolygons to_expolygons(const Polygons &polys)
|
||||
{
|
||||
ExPolygons ex_polys;
|
||||
ex_polys.assign(polys.size(), ExPolygon());
|
||||
for (size_t idx = 0; idx < polys.size(); ++idx)
|
||||
ex_polys[idx].contour = polys[idx];
|
||||
return ex_polys;
|
||||
}
|
||||
|
||||
inline ExPolygons to_expolygons(Polygons &&polys)
|
||||
{
|
||||
ExPolygons ex_polys;
|
||||
ex_polys.assign(polys.size(), ExPolygon());
|
||||
for (size_t idx = 0; idx < polys.size(); ++idx)
|
||||
ex_polys[idx].contour = std::move(polys[idx]);
|
||||
return ex_polys;
|
||||
}
|
||||
|
||||
inline void polygons_append(Polygons &dst, const ExPolygon &src)
|
||||
{
|
||||
dst.reserve(dst.size() + src.holes.size() + 1);
|
||||
@ -330,10 +338,6 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
|
||||
extern bool remove_sticks(ExPolygon &poly);
|
||||
extern void keep_largest_contour_only(ExPolygons &polygons);
|
||||
|
||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expp);
|
||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex);
|
||||
extern std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output);
|
||||
|
||||
inline double area(const ExPolygons &polys)
|
||||
{
|
||||
double s = 0.;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string_view>
|
||||
#include <numeric>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -102,6 +103,7 @@ public:
|
||||
virtual double min_mm3_per_mm() const = 0;
|
||||
virtual Polyline as_polyline() const = 0;
|
||||
virtual void collect_polylines(Polylines &dst) const = 0;
|
||||
virtual void collect_points(Points &dst) const = 0;
|
||||
virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; }
|
||||
virtual double length() const = 0;
|
||||
virtual double total_volume() const = 0;
|
||||
@ -167,6 +169,7 @@ public:
|
||||
double min_mm3_per_mm() const override { return this->mm3_per_mm; }
|
||||
Polyline as_polyline() const override { return this->polyline; }
|
||||
void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline); }
|
||||
void collect_points(Points &dst) const override { append(dst, this->polyline.points); }
|
||||
double total_volume() const override { return mm3_per_mm * unscale<double>(length()); }
|
||||
|
||||
private:
|
||||
@ -217,6 +220,12 @@ public:
|
||||
double min_mm3_per_mm() const override;
|
||||
Polyline as_polyline() const override;
|
||||
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
|
||||
void collect_points(Points &dst) const override {
|
||||
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
|
||||
dst.reserve(dst.size() + n);
|
||||
for (const ExtrusionPath &p : this->paths)
|
||||
append(dst, p.polyline.points);
|
||||
}
|
||||
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
|
||||
};
|
||||
|
||||
@ -268,6 +277,12 @@ public:
|
||||
double min_mm3_per_mm() const override;
|
||||
Polyline as_polyline() const override { return this->polygon().split_at_first_point(); }
|
||||
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
|
||||
void collect_points(Points &dst) const override {
|
||||
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
|
||||
dst.reserve(dst.size() + n);
|
||||
for (const ExtrusionPath &p : this->paths)
|
||||
append(dst, p.polyline.points);
|
||||
}
|
||||
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
|
||||
|
||||
//static inline std::string role_to_string(ExtrusionLoopRole role);
|
||||
@ -343,6 +358,25 @@ inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons
|
||||
loops.clear();
|
||||
}
|
||||
|
||||
inline void extrusion_entities_append_loops_and_paths(ExtrusionEntitiesPtr &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
|
||||
{
|
||||
dst.reserve(dst.size() + polylines.size());
|
||||
for (Polyline &polyline : polylines) {
|
||||
if (polyline.is_valid()) {
|
||||
if (polyline.is_closed()) {
|
||||
ExtrusionPath extrusion_path(role, mm3_per_mm, width, height);
|
||||
extrusion_path.polyline = std::move(polyline);
|
||||
dst.emplace_back(new ExtrusionLoop(std::move(extrusion_path)));
|
||||
} else {
|
||||
ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height);
|
||||
extrusion_path->polyline = std::move(polyline);
|
||||
dst.emplace_back(extrusion_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
polylines.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -117,6 +117,11 @@ public:
|
||||
extrusion_entity->collect_polylines(dst);
|
||||
}
|
||||
|
||||
void collect_points(Points &dst) const override {
|
||||
for (ExtrusionEntity* extrusion_entity : this->entities)
|
||||
extrusion_entity->collect_points(dst);
|
||||
}
|
||||
|
||||
double length() const override {
|
||||
throw Slic3r::RuntimeError("Calling length() on a ExtrusionEntityCollection");
|
||||
return 0.;
|
||||
|
@ -25,7 +25,7 @@ struct SurfaceFillParams
|
||||
// in unscaled coordinates
|
||||
coordf_t spacing = 0.;
|
||||
// infill / perimeter overlap, in unscaled coordinates
|
||||
coordf_t overlap = 0.;
|
||||
// coordf_t overlap = 0.;
|
||||
// Angle as provided by the region config, in radians.
|
||||
float angle = 0.f;
|
||||
// Non-negative for a bridge.
|
||||
@ -34,7 +34,7 @@ struct SurfaceFillParams
|
||||
// FillParams
|
||||
float density = 0.f;
|
||||
// Don't adjust spacing to fill the space evenly.
|
||||
bool dont_adjust = false;
|
||||
// bool dont_adjust = false;
|
||||
// Length of the infill anchor along the perimeter line.
|
||||
// 1000mm is roughly the maximum length line that fits into a 32bit coord_t.
|
||||
float anchor_length = 1000.f;
|
||||
@ -64,10 +64,10 @@ struct SurfaceFillParams
|
||||
RETURN_COMPARE_NON_EQUAL(extruder);
|
||||
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, pattern);
|
||||
RETURN_COMPARE_NON_EQUAL(spacing);
|
||||
RETURN_COMPARE_NON_EQUAL(overlap);
|
||||
// RETURN_COMPARE_NON_EQUAL(overlap);
|
||||
RETURN_COMPARE_NON_EQUAL(angle);
|
||||
RETURN_COMPARE_NON_EQUAL(density);
|
||||
RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
||||
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
|
||||
RETURN_COMPARE_NON_EQUAL(anchor_length);
|
||||
RETURN_COMPARE_NON_EQUAL(anchor_length_max);
|
||||
RETURN_COMPARE_NON_EQUAL(flow.width);
|
||||
@ -83,10 +83,10 @@ struct SurfaceFillParams
|
||||
this->pattern == rhs.pattern &&
|
||||
this->pattern == rhs.pattern &&
|
||||
this->spacing == rhs.spacing &&
|
||||
this->overlap == rhs.overlap &&
|
||||
// this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->density == rhs.density &&
|
||||
this->dont_adjust == rhs.dont_adjust &&
|
||||
// this->dont_adjust == rhs.dont_adjust &&
|
||||
this->anchor_length == rhs.anchor_length &&
|
||||
this->anchor_length_max == rhs.anchor_length_max &&
|
||||
this->flow == rhs.flow &&
|
||||
@ -130,7 +130,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
params.density = 100.f;
|
||||
params.pattern = (surface.is_external() && ! is_bridge) ?
|
||||
(surface.is_top() ? region_config.top_fill_pattern.value : region_config.bottom_fill_pattern.value) :
|
||||
ipRectilinear;
|
||||
region_config.top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
|
||||
} else if (params.density <= 0)
|
||||
continue;
|
||||
|
||||
@ -158,6 +158,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
params.spacing = params.flow.spacing();
|
||||
// Don't limit anchor length for solid or bridging infill.
|
||||
params.anchor_length = 1000.f;
|
||||
params.anchor_length_max = 1000.f;
|
||||
} else {
|
||||
// it's internal infill, so we can calculate a generic flow spacing
|
||||
// for all layers, for avoiding the ugly effect of
|
||||
@ -173,13 +174,13 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
).spacing();
|
||||
// Anchor a sparse infill to inner perimeters with the following anchor length:
|
||||
params.anchor_length = float(region_config.infill_anchor);
|
||||
if (region_config.infill_anchor.percent)
|
||||
params.anchor_length = float(params.anchor_length * 0.01 * params.spacing);
|
||||
params.anchor_length_max = float(region_config.infill_anchor_max);
|
||||
if (region_config.infill_anchor_max.percent)
|
||||
params.anchor_length_max = float(params.anchor_length_max * 0.01 * params.spacing);
|
||||
}
|
||||
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
|
||||
if (region_config.infill_anchor.percent)
|
||||
params.anchor_length = float(params.anchor_length * 0.01 * params.spacing);
|
||||
params.anchor_length_max = float(region_config.infill_anchor_max);
|
||||
if (region_config.infill_anchor_max.percent)
|
||||
params.anchor_length_max = float(params.anchor_length_max * 0.01 * params.spacing);
|
||||
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
|
||||
}
|
||||
|
||||
auto it_params = set_surface_params.find(params);
|
||||
if (it_params == set_surface_params.end())
|
||||
@ -284,7 +285,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
if (internal_solid_fill == nullptr) {
|
||||
// Produce another solid fill.
|
||||
params.extruder = layerm.region()->extruder(frSolidInfill);
|
||||
params.pattern = ipRectilinear;
|
||||
params.pattern = layerm.region()->config().top_fill_pattern == ipMonotonic ? ipMonotonic : ipRectilinear;
|
||||
params.density = 100.f;
|
||||
params.extrusion_role = erInternalInfill;
|
||||
params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
||||
@ -384,7 +385,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
// apply half spacing using this flow's own spacing and generate infill
|
||||
FillParams params;
|
||||
params.density = float(0.01 * surface_fill.params.density);
|
||||
params.dont_adjust = surface_fill.params.dont_adjust; // false
|
||||
params.dont_adjust = false; // surface_fill.params.dont_adjust;
|
||||
params.anchor_length = surface_fill.params.anchor_length;
|
||||
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
||||
|
||||
@ -532,6 +533,7 @@ void Layer::make_ironing()
|
||||
}
|
||||
}
|
||||
if (ironing_params.extruder != -1) {
|
||||
//TODO just_infill is currently not used.
|
||||
ironing_params.just_infill = false;
|
||||
ironing_params.line_spacing = config.ironing_spacing;
|
||||
ironing_params.height = default_layer_height * 0.01 * config.ironing_flowrate;
|
||||
@ -562,17 +564,54 @@ void Layer::make_ironing()
|
||||
ExPolygons ironing_areas;
|
||||
double nozzle_dmr = this->object()->print()->config().nozzle_diameter.values[ironing_params.extruder - 1];
|
||||
if (ironing_params.just_infill) {
|
||||
//TODO just_infill is currently not used.
|
||||
// Just infill.
|
||||
} else {
|
||||
// Infill and perimeter.
|
||||
// Merge top surfaces with the same ironing parameters.
|
||||
Polygons polys;
|
||||
for (size_t k = i; k < j; ++ k)
|
||||
for (const Surface &surface : by_extruder[k].layerm->slices.surfaces)
|
||||
if (surface.surface_type == stTop)
|
||||
Polygons infills;
|
||||
for (size_t k = i; k < j; ++ k) {
|
||||
const IroningParams &ironing_params = by_extruder[k];
|
||||
const PrintRegionConfig ®ion_config = ironing_params.layerm->region()->config();
|
||||
bool iron_everything = region_config.ironing_type == IroningType::AllSolid;
|
||||
bool iron_completely = iron_everything;
|
||||
if (iron_everything) {
|
||||
// Check whether there is any non-solid hole in the regions.
|
||||
bool internal_infill_solid = region_config.fill_density.value > 95.;
|
||||
for (const Surface &surface : ironing_params.layerm->fill_surfaces.surfaces)
|
||||
if ((! internal_infill_solid && surface.surface_type == stInternal) || surface.surface_type == stInternalBridge || surface.surface_type == stInternalVoid) {
|
||||
// Some fill region is not quite solid. Don't iron over the whole surface.
|
||||
iron_completely = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iron_completely) {
|
||||
// Iron everything. This is likely only good for solid transparent objects.
|
||||
for (const Surface &surface : ironing_params.layerm->slices.surfaces)
|
||||
polygons_append(polys, surface.expolygon);
|
||||
} else {
|
||||
for (const Surface &surface : ironing_params.layerm->slices.surfaces)
|
||||
if (surface.surface_type == stTop || (iron_everything && surface.surface_type == stBottom))
|
||||
// stBottomBridge is not being ironed on purpose, as it would likely destroy the bridges.
|
||||
polygons_append(polys, surface.expolygon);
|
||||
}
|
||||
if (iron_everything && ! iron_completely) {
|
||||
// Add solid fill surfaces. This may not be ideal, as one will not iron perimeters touching these
|
||||
// solid fill surfaces, but it is likely better than nothing.
|
||||
for (const Surface &surface : ironing_params.layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternalSolid)
|
||||
polygons_append(infills, surface.expolygon);
|
||||
}
|
||||
}
|
||||
// Trim the top surfaces with half the nozzle diameter.
|
||||
ironing_areas = intersection_ex(polys, offset(this->lslices, - float(scale_(0.5 * nozzle_dmr))));
|
||||
if (! infills.empty()) {
|
||||
// For IroningType::AllSolid only:
|
||||
// Add solid infill areas for layers, that contain some non-ironable infil (sparse infill, bridge infill).
|
||||
append(infills, to_polygons(std::move(ironing_areas)));
|
||||
ironing_areas = union_ex(infills, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the filler object.
|
||||
|
@ -678,6 +678,7 @@ static inline bool line_rounded_thick_segment_collision(
|
||||
return intersects;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static inline bool inside_interval(double low, double high, double p)
|
||||
{
|
||||
return p >= low && p <= high;
|
||||
@ -702,6 +703,7 @@ static inline bool cyclic_interval_inside_interval(double outer_low, double oute
|
||||
}
|
||||
return interval_inside_interval(outer_low, outer_high, inner_low, inner_high, double(SCALED_EPSILON));
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
// #define INFILL_DEBUG_OUTPUT
|
||||
|
||||
@ -1129,7 +1131,7 @@ void Fill::connect_infill(Polylines &&infill_ordered, const std::vector<const Po
|
||||
intersection_points.reserve(infill_ordered.size() * 2);
|
||||
for (const Polyline &pl : infill_ordered)
|
||||
for (const Point *pt : { &pl.points.front(), &pl.points.back() }) {
|
||||
EdgeGrid::Grid::ClosestPointResult cp = grid.closest_point(*pt, coord_t(SCALED_EPSILON));
|
||||
EdgeGrid::Grid::ClosestPointResult cp = grid.closest_point_signed_distance(*pt, coord_t(SCALED_EPSILON));
|
||||
if (cp.valid()) {
|
||||
// The infill end point shall lie on the contour.
|
||||
assert(cp.distance <= 3.);
|
||||
|
@ -2245,22 +2245,22 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
|
||||
#endif /* NDEBUG */
|
||||
|
||||
// How many times to repeat the ant simulation (number of ant generations).
|
||||
constexpr int num_rounds = 25;
|
||||
constexpr int const num_rounds = 25;
|
||||
// After how many rounds without an improvement to exit?
|
||||
constexpr int num_rounds_no_change_exit = 8;
|
||||
constexpr int const num_rounds_no_change_exit = 8;
|
||||
// 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.
|
||||
float pheromone_initial_deposit = 0.5f;
|
||||
float pheromone_initial_deposit = 0.5f;
|
||||
// Evaporation rate of pheromones.
|
||||
constexpr float pheromone_evaporation = 0.1f;
|
||||
constexpr float const pheromone_evaporation = 0.1f;
|
||||
// Evaporation rate to diversify paths taken by individual ants.
|
||||
constexpr float pheromone_diversification = 0.1f;
|
||||
constexpr float const pheromone_diversification = 0.1f;
|
||||
// Probability at which to take the next best path. Otherwise take the the path based on the cost distribution.
|
||||
constexpr float probability_take_best = 0.9f;
|
||||
constexpr float const probability_take_best = 0.9f;
|
||||
// Exponents of the cost function.
|
||||
constexpr float pheromone_alpha = 1.f; // pheromone exponent
|
||||
constexpr float pheromone_beta = 2.f; // attractiveness weighted towards edge length
|
||||
constexpr float const pheromone_alpha = 1.f; // pheromone exponent
|
||||
constexpr float const pheromone_beta = 2.f; // attractiveness weighted towards edge length
|
||||
|
||||
AntPathMatrix path_matrix(regions, poly_with_offset, segs, pheromone_initial_deposit);
|
||||
|
||||
@ -2332,7 +2332,12 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
|
||||
}
|
||||
|
||||
// Probability (unnormalized) of traversing a link between two monotonic regions.
|
||||
auto path_probability = [pheromone_alpha, pheromone_beta](AntPath &path) {
|
||||
auto path_probability = [
|
||||
#ifndef __APPLE__
|
||||
// clang complains when capturing constexpr constants.
|
||||
pheromone_alpha, pheromone_beta
|
||||
#endif // __APPLE__
|
||||
](AntPath &path) {
|
||||
return pow(path.pheromone, pheromone_alpha) * pow(path.visibility, pheromone_beta);
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,7 @@ class Surface;
|
||||
class FillRectilinear : public Fill
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillRectilinear(*this); };
|
||||
Fill* clone() const override { return new FillRectilinear(*this); }
|
||||
~FillRectilinear() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
@ -32,18 +32,18 @@ protected:
|
||||
class FillAlignedRectilinear : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillAlignedRectilinear(*this); };
|
||||
Fill* clone() const override { return new FillAlignedRectilinear(*this); }
|
||||
~FillAlignedRectilinear() override = default;
|
||||
|
||||
protected:
|
||||
// Always generate infill at the same angle.
|
||||
virtual float _layer_angle(size_t idx) const { return 0.f; }
|
||||
virtual float _layer_angle(size_t idx) const override { return 0.f; }
|
||||
};
|
||||
|
||||
class FillMonotonic : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillMonotonic(*this); };
|
||||
Fill* clone() const override { return new FillMonotonic(*this); }
|
||||
~FillMonotonic() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
bool no_sort() const override { return true; }
|
||||
@ -52,7 +52,7 @@ public:
|
||||
class FillGrid : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillGrid(*this); };
|
||||
Fill* clone() const override { return new FillGrid(*this); }
|
||||
~FillGrid() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
@ -64,7 +64,7 @@ protected:
|
||||
class FillTriangles : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillTriangles(*this); };
|
||||
Fill* clone() const override { return new FillTriangles(*this); }
|
||||
~FillTriangles() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
@ -76,7 +76,7 @@ protected:
|
||||
class FillStars : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillStars(*this); };
|
||||
Fill* clone() const override { return new FillStars(*this); }
|
||||
~FillStars() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
@ -88,7 +88,7 @@ protected:
|
||||
class FillCubic : public FillRectilinear
|
||||
{
|
||||
public:
|
||||
Fill* clone() const override { return new FillCubic(*this); };
|
||||
Fill* clone() const override { return new FillCubic(*this); }
|
||||
~FillCubic() override = default;
|
||||
Polylines fill_surface(const Surface *surface, const FillParams ¶ms) override;
|
||||
|
||||
@ -98,6 +98,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
}; // namespace Slic3r
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_FillRectilinear_hpp_
|
||||
|
@ -19,9 +19,8 @@
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
@ -116,6 +115,7 @@ static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
|
||||
static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
|
||||
static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
||||
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
|
||||
static constexpr const char* SOURCE_IN_METERS = "source_in_meters";
|
||||
|
||||
const unsigned int VALID_OBJECT_TYPES_COUNT = 1;
|
||||
const char* VALID_OBJECT_TYPES[] =
|
||||
@ -123,7 +123,6 @@ const char* VALID_OBJECT_TYPES[] =
|
||||
"model"
|
||||
};
|
||||
|
||||
const unsigned int INVALID_OBJECT_TYPES_COUNT = 4;
|
||||
const char* INVALID_OBJECT_TYPES[] =
|
||||
{
|
||||
"solidsupport",
|
||||
@ -257,9 +256,8 @@ namespace Slic3r {
|
||||
public:
|
||||
void log_errors()
|
||||
{
|
||||
for (const std::string& error : m_errors) {
|
||||
printf("%s\n", error.c_str());
|
||||
}
|
||||
for (const std::string& error : m_errors)
|
||||
BOOST_LOG_TRIVIAL(error) << error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -392,6 +390,10 @@ namespace Slic3r {
|
||||
bool m_check_version;
|
||||
|
||||
XML_Parser m_xml_parser;
|
||||
// Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state
|
||||
// after returning from XML_Parse() function, thus we keep the error state here.
|
||||
bool m_parse_error { false };
|
||||
std::string m_parse_error_message;
|
||||
Model* m_model;
|
||||
float m_unit_factor;
|
||||
CurrentObject m_curr_object;
|
||||
@ -417,7 +419,16 @@ namespace Slic3r {
|
||||
|
||||
private:
|
||||
void _destroy_xml_parser();
|
||||
void _stop_xml_parser();
|
||||
void _stop_xml_parser(const std::string& msg = std::string());
|
||||
|
||||
bool parse_error() const { return m_parse_error; }
|
||||
const char* parse_error_message() const {
|
||||
return m_parse_error ?
|
||||
// The error was signalled by the user code, not the expat parser.
|
||||
(m_parse_error_message.empty() ? "Invalid 3MF format" : m_parse_error_message.c_str()) :
|
||||
// The error was signalled by the expat parser.
|
||||
XML_ErrorString(XML_GetErrorCode(m_xml_parser));
|
||||
}
|
||||
|
||||
bool _load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config);
|
||||
bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
@ -556,10 +567,14 @@ namespace Slic3r {
|
||||
}
|
||||
}
|
||||
|
||||
void _3MF_Importer::_stop_xml_parser()
|
||||
void _3MF_Importer::_stop_xml_parser(const std::string &msg)
|
||||
{
|
||||
if (m_xml_parser != nullptr)
|
||||
XML_StopParser(m_xml_parser, false);
|
||||
assert(! m_parse_error);
|
||||
assert(m_parse_error_message.empty());
|
||||
assert(m_xml_parser != nullptr);
|
||||
m_parse_error = true;
|
||||
m_parse_error_message = msg;
|
||||
XML_StopParser(m_xml_parser, false);
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config)
|
||||
@ -659,7 +674,7 @@ namespace Slic3r {
|
||||
// select the geometry associated with the original model object
|
||||
const Geometry* geometry = nullptr;
|
||||
for (const IdToModelObjectMap::value_type& object : m_objects) {
|
||||
if (static_cast<int>(object.second) == i) {
|
||||
if (object.second == int(i)) {
|
||||
IdToGeometryMap::const_iterator obj_geometry = m_geometries.find(object.first);
|
||||
if (obj_geometry == m_geometries.end()) {
|
||||
add_error("Unable to find object geometry");
|
||||
@ -695,6 +710,10 @@ namespace Slic3r {
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_FOR_3MF
|
||||
|
||||
for (const IdToModelObjectMap::value_type& object : m_objects) {
|
||||
if (object.second >= int(m_model->objects.size())) {
|
||||
add_error("Unable to find object");
|
||||
return false;
|
||||
}
|
||||
ModelObject* model_object = m_model->objects[object.second];
|
||||
IdToGeometryMap::const_iterator obj_geometry = m_geometries.find(object.first);
|
||||
if (obj_geometry == m_geometries.end()) {
|
||||
@ -802,12 +821,13 @@ namespace Slic3r {
|
||||
struct CallbackData
|
||||
{
|
||||
XML_Parser& parser;
|
||||
_3MF_Importer& importer;
|
||||
const mz_zip_archive_file_stat& stat;
|
||||
|
||||
CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {}
|
||||
CallbackData(XML_Parser& parser, _3MF_Importer& importer, const mz_zip_archive_file_stat& stat) : parser(parser), importer(importer), stat(stat) {}
|
||||
};
|
||||
|
||||
CallbackData data(m_xml_parser, stat);
|
||||
CallbackData data(m_xml_parser, *this, stat);
|
||||
|
||||
mz_bool res = 0;
|
||||
|
||||
@ -815,9 +835,9 @@ namespace Slic3r {
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0)) {
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->importer.parse_error()) {
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", data->importer.parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw Slic3r::FileIOError(error_buf);
|
||||
}
|
||||
|
||||
@ -1221,7 +1241,8 @@ namespace Slic3r {
|
||||
|
||||
CustomGCode::Type type;
|
||||
std::string extra;
|
||||
if (tree.find("type") == tree.not_found()) {
|
||||
pt::ptree attr_tree = tree.find("<xmlattr>")->second;
|
||||
if (attr_tree.find("type") == attr_tree.not_found()) {
|
||||
// It means that data was saved in old version (2.2.0 and older) of PrusaSlicer
|
||||
// read old data ...
|
||||
std::string gcode = tree.get<std::string> ("<xmlattr>.gcode");
|
||||
@ -1374,6 +1395,10 @@ namespace Slic3r {
|
||||
{
|
||||
// deletes all non-built or non-instanced objects
|
||||
for (const IdToModelObjectMap::value_type& object : m_objects) {
|
||||
if (object.second >= int(m_model->objects.size())) {
|
||||
add_error("Unable to find object");
|
||||
return false;
|
||||
}
|
||||
ModelObject *model_object = m_model->objects[object.second];
|
||||
if (model_object != nullptr && model_object->instances.size() == 0)
|
||||
m_model->delete_object(model_object);
|
||||
@ -1834,6 +1859,10 @@ namespace Slic3r {
|
||||
stl_facet& facet = stl.facet_start[i];
|
||||
for (unsigned int v = 0; v < 3; ++v) {
|
||||
unsigned int tri_id = geometry.triangles[src_start_id + ii + v] * 3;
|
||||
if (tri_id + 2 >= geometry.vertices.size()) {
|
||||
add_error("Malformed triangle mesh");
|
||||
return false;
|
||||
}
|
||||
facet.vertex[v] = Vec3f(geometry.vertices[tri_id + 0], geometry.vertices[tri_id + 1], geometry.vertices[tri_id + 2]);
|
||||
}
|
||||
}
|
||||
@ -1850,10 +1879,6 @@ namespace Slic3r {
|
||||
triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix());
|
||||
object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
|
||||
}
|
||||
else {
|
||||
std::cout << "non-single instance !!!\n";
|
||||
int a = 0;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_FOR_3MF
|
||||
|
||||
@ -1897,6 +1922,8 @@ namespace Slic3r {
|
||||
volume->source.mesh_offset(2) = ::atof(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_IN_INCHES)
|
||||
volume->source.is_converted_from_inches = metadata.value == "1";
|
||||
else if (metadata.key == SOURCE_IN_METERS)
|
||||
volume->source.is_converted_from_meters = metadata.value == "1";
|
||||
else
|
||||
volume->config.set_deserialize(metadata.key, metadata.value);
|
||||
}
|
||||
@ -2414,7 +2441,7 @@ namespace Slic3r {
|
||||
if (!volume->mesh().has_shared_vertices())
|
||||
throw Slic3r::FileIOError("store_3mf() requires shared vertices");
|
||||
|
||||
volumes_offsets.insert({ volume, Offsets(vertices_count) }).first;
|
||||
volumes_offsets.insert({ volume, Offsets(vertices_count) });
|
||||
|
||||
const indexed_triangle_set &its = volume->mesh().its;
|
||||
if (its.vertices.empty()) {
|
||||
@ -2806,6 +2833,8 @@ namespace Slic3r {
|
||||
}
|
||||
if (volume->source.is_converted_from_inches)
|
||||
stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
if (volume->source.is_converted_from_meters)
|
||||
stream << prefix << SOURCE_IN_METERS << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
}
|
||||
|
||||
// stores volume's config data
|
||||
|
@ -24,6 +24,7 @@ namespace pt = boost::property_tree;
|
||||
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
@ -63,23 +64,31 @@ namespace Slic3r
|
||||
struct AMFParserContext
|
||||
{
|
||||
AMFParserContext(XML_Parser parser, DynamicPrintConfig* config, Model* model) :
|
||||
m_version(0),
|
||||
m_parser(parser),
|
||||
m_model(*model),
|
||||
m_object(nullptr),
|
||||
m_volume(nullptr),
|
||||
m_material(nullptr),
|
||||
m_instance(nullptr),
|
||||
m_config(config)
|
||||
{
|
||||
m_path.reserve(12);
|
||||
}
|
||||
|
||||
void stop()
|
||||
void stop(const std::string &msg = std::string())
|
||||
{
|
||||
assert(! m_error);
|
||||
assert(m_error_message.empty());
|
||||
m_error = true;
|
||||
m_error_message = msg;
|
||||
XML_StopParser(m_parser, 0);
|
||||
}
|
||||
|
||||
bool error() const { return m_error; }
|
||||
const char* error_message() const {
|
||||
return m_error ?
|
||||
// The error was signalled by the user code, not the expat parser.
|
||||
(m_error_message.empty() ? "Invalid AMF format" : m_error_message.c_str()) :
|
||||
// The error was signalled by the expat parser.
|
||||
XML_ErrorString(XML_GetErrorCode(m_parser));
|
||||
}
|
||||
|
||||
void startElement(const char *name, const char **atts);
|
||||
void endElement(const char *name);
|
||||
void endDocument();
|
||||
@ -217,33 +226,37 @@ struct AMFParserContext
|
||||
};
|
||||
|
||||
// Version of the amf file
|
||||
unsigned int m_version;
|
||||
unsigned int m_version { 0 };
|
||||
// Current Expat XML parser instance.
|
||||
XML_Parser m_parser;
|
||||
// Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state
|
||||
// after returning from XML_Parse() function, thus we keep the error state here.
|
||||
bool m_error { false };
|
||||
std::string m_error_message;
|
||||
// Model to receive objects extracted from an AMF file.
|
||||
Model &m_model;
|
||||
// Current parsing path in the XML file.
|
||||
std::vector<AMFNodeType> m_path;
|
||||
// Current object allocated for an amf/object XML subtree.
|
||||
ModelObject *m_object;
|
||||
ModelObject *m_object { nullptr };
|
||||
// Map from obect name to object idx & instances.
|
||||
std::map<std::string, Object> m_object_instances_map;
|
||||
// Vertices parsed for the current m_object.
|
||||
std::vector<float> m_object_vertices;
|
||||
// Current volume allocated for an amf/object/mesh/volume subtree.
|
||||
ModelVolume *m_volume;
|
||||
ModelVolume *m_volume { nullptr };
|
||||
// Faces collected for the current m_volume.
|
||||
std::vector<int> m_volume_facets;
|
||||
// Transformation matrix of a volume mesh from its coordinate system to Object's coordinate system.
|
||||
Transform3d m_volume_transform;
|
||||
// Current material allocated for an amf/metadata subtree.
|
||||
ModelMaterial *m_material;
|
||||
ModelMaterial *m_material { nullptr };
|
||||
// Current instance allocated for an amf/constellation/instance subtree.
|
||||
Instance *m_instance;
|
||||
Instance *m_instance { nullptr };
|
||||
// Generic string buffer for vertices, face indices, metadata etc.
|
||||
std::string m_value[5];
|
||||
// Pointer to config to update if config data are stored inside the amf file
|
||||
DynamicPrintConfig *m_config;
|
||||
DynamicPrintConfig *m_config { nullptr };
|
||||
|
||||
private:
|
||||
AMFParserContext& operator=(AMFParserContext&);
|
||||
@ -591,9 +604,9 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
// Faces of the current volume:
|
||||
case NODE_TYPE_TRIANGLE:
|
||||
assert(m_object && m_volume);
|
||||
m_volume_facets.push_back(atoi(m_value[0].c_str()));
|
||||
m_volume_facets.push_back(atoi(m_value[1].c_str()));
|
||||
m_volume_facets.push_back(atoi(m_value[2].c_str()));
|
||||
m_volume_facets.emplace_back(atoi(m_value[0].c_str()));
|
||||
m_volume_facets.emplace_back(atoi(m_value[1].c_str()));
|
||||
m_volume_facets.emplace_back(atoi(m_value[2].c_str()));
|
||||
m_value[0].clear();
|
||||
m_value[1].clear();
|
||||
m_value[2].clear();
|
||||
@ -616,6 +629,10 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
for (unsigned int v = 0; v < 3; ++v)
|
||||
{
|
||||
unsigned int tri_id = m_volume_facets[i++] * 3;
|
||||
if (tri_id < 0 || tri_id + 2 >= m_object_vertices.size()) {
|
||||
this->stop("Malformed triangle mesh");
|
||||
return;
|
||||
}
|
||||
facet.vertex[v] = Vec3f(m_object_vertices[tri_id + 0], m_object_vertices[tri_id + 1], m_object_vertices[tri_id + 2]);
|
||||
}
|
||||
}
|
||||
@ -781,6 +798,9 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
else if (strcmp(opt_key, "source_in_inches") == 0) {
|
||||
m_volume->source.is_converted_from_inches = m_value[1] == "1";
|
||||
}
|
||||
else if (strcmp(opt_key, "source_in_meters") == 0) {
|
||||
m_volume->source.is_converted_from_meters = m_value[1] == "1";
|
||||
}
|
||||
}
|
||||
} else if (m_path.size() == 3) {
|
||||
if (m_path[1] == NODE_TYPE_MATERIAL) {
|
||||
@ -811,7 +831,7 @@ void AMFParserContext::endDocument()
|
||||
{
|
||||
for (const auto &object : m_object_instances_map) {
|
||||
if (object.second.idx == -1) {
|
||||
printf("Undefined object %s referenced in constellation\n", object.first.c_str());
|
||||
BOOST_LOG_TRIVIAL(error) << "Undefined object " << object.first.c_str() << " referenced in constellation";
|
||||
continue;
|
||||
}
|
||||
for (const Instance &instance : object.second.instances)
|
||||
@ -834,13 +854,13 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(nullptr); // encoding
|
||||
if (!parser) {
|
||||
printf("Couldn't allocate memory for parser\n");
|
||||
BOOST_LOG_TRIVIAL(error) << "Couldn't allocate memory for parser";
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *pFile = boost::nowide::fopen(path, "rt");
|
||||
if (pFile == nullptr) {
|
||||
printf("Cannot open file %s\n", path);
|
||||
BOOST_LOG_TRIVIAL(error) << "Cannot open file " << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -854,14 +874,12 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, Model *model)
|
||||
for (;;) {
|
||||
int len = (int)fread(buff, 1, 8192, pFile);
|
||||
if (ferror(pFile)) {
|
||||
printf("AMF parser: Read error\n");
|
||||
BOOST_LOG_TRIVIAL(error) << "AMF parser: Read error";
|
||||
break;
|
||||
}
|
||||
int done = feof(pFile);
|
||||
if (XML_Parse(parser, buff, len, done) == XML_STATUS_ERROR) {
|
||||
printf("AMF parser: Parse error at line %d:\n%s\n",
|
||||
(int)XML_GetCurrentLineNumber(parser),
|
||||
XML_ErrorString(XML_GetErrorCode(parser)));
|
||||
if (XML_Parse(parser, buff, len, done) == XML_STATUS_ERROR || ctx.error()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "AMF parser: Parse error at line " << int(XML_GetCurrentLineNumber(parser)) << ": " << ctx.error_message();
|
||||
break;
|
||||
}
|
||||
if (done) {
|
||||
@ -892,14 +910,14 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
{
|
||||
if (stat.m_uncomp_size == 0)
|
||||
{
|
||||
printf("Found invalid size\n");
|
||||
BOOST_LOG_TRIVIAL(error) << "Found invalid size";
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(nullptr); // encoding
|
||||
if (!parser) {
|
||||
printf("Couldn't allocate memory for parser\n");
|
||||
BOOST_LOG_TRIVIAL(error) << "Couldn't allocate memory for parser";
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
@ -912,12 +930,13 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
struct CallbackData
|
||||
{
|
||||
XML_Parser& parser;
|
||||
AMFParserContext& ctx;
|
||||
const mz_zip_archive_file_stat& stat;
|
||||
|
||||
CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {}
|
||||
CallbackData(XML_Parser& parser, AMFParserContext& ctx, const mz_zip_archive_file_stat& stat) : parser(parser), ctx(ctx), stat(stat) {}
|
||||
};
|
||||
|
||||
CallbackData data(parser, stat);
|
||||
CallbackData data(parser, ctx, stat);
|
||||
|
||||
mz_bool res = 0;
|
||||
|
||||
@ -925,10 +944,10 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0))
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->ctx.error())
|
||||
{
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", data->ctx.error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw Slic3r::FileIOError(error_buf);
|
||||
}
|
||||
|
||||
@ -937,14 +956,14 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
printf("%s\n", e.what());
|
||||
BOOST_LOG_TRIVIAL(error) << "Error reading AMF file: " << e.what();
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Error while extracting model data from zip archive");
|
||||
BOOST_LOG_TRIVIAL(error) << "Error while extracting model data from zip archive";
|
||||
close_zip_reader(&archive);
|
||||
return false;
|
||||
}
|
||||
@ -973,7 +992,7 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, Model* model
|
||||
|
||||
if (!open_zip_reader(&archive, path))
|
||||
{
|
||||
printf("Unable to init zip reader\n");
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to init zip reader";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -992,7 +1011,7 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, Model* model
|
||||
if (!extract_model_from_archive(archive, stat, config, model, check_version))
|
||||
{
|
||||
close_zip_reader(&archive);
|
||||
printf("Archive does not contain a valid model");
|
||||
BOOST_LOG_TRIVIAL(error) << "Archive does not contain a valid model";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1216,6 +1235,8 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
|
||||
}
|
||||
if (volume->source.is_converted_from_inches)
|
||||
stream << " <metadata type=\"slic3r.source_in_inches\">1</metadata>\n";
|
||||
if (volume->source.is_converted_from_meters)
|
||||
stream << " <metadata type=\"slic3r.source_in_meters\">1</metadata>\n";
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
const indexed_triangle_set &its = volume->mesh().its;
|
||||
for (size_t i = 0; i < its.indices.size(); ++i) {
|
||||
@ -1231,7 +1252,7 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
|
||||
if (!object->instances.empty()) {
|
||||
for (ModelInstance *instance : object->instances) {
|
||||
char buf[512];
|
||||
sprintf(buf,
|
||||
::sprintf(buf,
|
||||
" <instance objectid=\"%zu\">\n"
|
||||
" <deltax>%lf</deltax>\n"
|
||||
" <deltay>%lf</deltay>\n"
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include <exception>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
|
@ -170,7 +170,11 @@ namespace Slic3r {
|
||||
// subdivide the retraction in segments
|
||||
if (!wipe_path.empty()) {
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Wipe_Start_Tag + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
for (const Line& line : wipe_path.lines()) {
|
||||
double segment_length = line.length();
|
||||
/* Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
@ -186,7 +190,11 @@ namespace Slic3r {
|
||||
);
|
||||
}
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Wipe_End_Tag + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcodegen.set_last_pos(wipe_path.points.back());
|
||||
}
|
||||
|
||||
@ -478,7 +486,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||
//FIXME should we use the printing extruders instead?
|
||||
double gap_over_supports = object.config().support_material_contact_distance;
|
||||
// FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports.
|
||||
assert(!object.config().support_material || gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
||||
assert(!object.has_support() || gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
||||
if (gap_over_supports != 0.) {
|
||||
gap_over_supports = std::max(0., gap_over_supports);
|
||||
// Not a soluble support,
|
||||
@ -610,6 +618,59 @@ namespace DoExport {
|
||||
print_statistics.estimated_silent_print_time = processor.is_stealth_time_estimator_enabled() ?
|
||||
get_time_dhms(result.time_statistics.modes[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].time) : "N/A";
|
||||
}
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// if any reserved keyword is found, returns a std::vector containing the first MAX_COUNT keywords found
|
||||
// into pairs containing:
|
||||
// first: source
|
||||
// second: keyword
|
||||
// to be shown in the warning notification
|
||||
// The returned vector is empty if no keyword has been found
|
||||
static std::vector<std::pair<std::string, std::string>> validate_custom_gcode(const Print& print) {
|
||||
static const unsigned int MAX_TAGS_COUNT = 5;
|
||||
std::vector<std::pair<std::string, std::string>> ret;
|
||||
|
||||
auto check = [&ret](const std::string& source, const std::string& gcode) {
|
||||
std::vector<std::string> tags;
|
||||
if (GCodeProcessor::contains_reserved_tags(gcode, MAX_TAGS_COUNT, tags)) {
|
||||
if (!tags.empty()) {
|
||||
size_t i = 0;
|
||||
while (ret.size() < MAX_TAGS_COUNT && i < tags.size()) {
|
||||
ret.push_back({ source, tags[i] });
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const GCodeConfig& config = print.config();
|
||||
check(_(L("Start G-code")), config.start_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("End G-code")), config.end_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Before layer change G-code")), config.before_layer_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("After layer change G-code")), config.layer_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Tool change G-code")), config.toolchange_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Between objects G-code (for sequential printing)")), config.between_objects_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), config.color_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Pause Print G-code")), config.pause_print_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Template Custom G-code")), config.template_custom_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) {
|
||||
for (const std::string& value : config.start_filament_gcode.values) {
|
||||
check(_(L("Filament Start G-code")), value);
|
||||
if (ret.size() == MAX_TAGS_COUNT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret.size() < MAX_TAGS_COUNT) {
|
||||
for (const std::string& value : config.end_filament_gcode.values) {
|
||||
check(_(L("Filament End G-code")), value);
|
||||
if (ret.size() == MAX_TAGS_COUNT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
} // namespace DoExport
|
||||
|
||||
void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
@ -622,6 +683,22 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
|
||||
|
||||
print->set_started(psGCodeExport);
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// check if any custom gcode contains keywords used by the gcode processor to
|
||||
// produce time estimation and gcode toolpaths
|
||||
std::vector<std::pair<std::string, std::string>> validation_res = DoExport::validate_custom_gcode(*print);
|
||||
if (!validation_res.empty()) {
|
||||
std::string reports;
|
||||
for (const auto& [source, keyword] : validation_res) {
|
||||
reports += source + ": \"" + keyword + "\"\n";
|
||||
}
|
||||
print->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL,
|
||||
_(L("Found reserved keyword(s) into custom g-code:")) + "\n" +
|
||||
reports +
|
||||
_(L("This may cause problems in g-code visualization and printing time estimation.")));
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Exporting G-code..." << log_memory_info();
|
||||
|
||||
// Remove the old g-code if it exists.
|
||||
@ -851,7 +928,7 @@ namespace DoExport {
|
||||
double extruded_volume = extruder.extruded_volume() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] * 2.4052f : 0.f); // assumes 1.75mm filament diameter
|
||||
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
|
||||
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
|
||||
auto append = [&extruder, &extruders](std::pair<std::string, unsigned int> &dst, const char *tmpl, double value) {
|
||||
auto append = [&extruder](std::pair<std::string, unsigned int> &dst, const char *tmpl, double value) {
|
||||
while (dst.second < extruder.id()) {
|
||||
// Fill in the non-printing extruders with zeros.
|
||||
dst.first += (dst.second > 0) ? ", 0" : "0";
|
||||
@ -891,6 +968,7 @@ namespace DoExport {
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Sort the PrintObjects by their increasing Z, likely useful for avoiding colisions on Deltas during sequential prints.
|
||||
static inline std::vector<const PrintInstance*> sort_object_instances_by_max_z(const Print &print)
|
||||
{
|
||||
@ -903,6 +981,7 @@ static inline std::vector<const PrintInstance*> sort_object_instances_by_max_z(c
|
||||
instances.emplace_back(&object->instances()[i]);
|
||||
return instances;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Produce a vector of PrintObjects in the order of their respective ModelObjects in print.model().
|
||||
std::vector<const PrintInstance*> sort_object_instances_by_model_order(const Print& print)
|
||||
@ -937,14 +1016,9 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
m_last_height = 0.f;
|
||||
m_last_layer_z = 0.f;
|
||||
m_max_layer_z = 0.f;
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_last_width = 0.f;
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_last_mm3_per_mm = 0.;
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_last_width = 0.f;
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
// How many times will be change_layer() called?
|
||||
@ -1037,7 +1111,11 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
|
||||
// adds tags for time estimators
|
||||
if (print.config().remaining_times.value)
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
_write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
|
||||
#else
|
||||
_writeln(file, GCodeProcessor::First_Line_M73_Placeholder_Tag);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||
m_placeholder_parser = print.placeholder_parser();
|
||||
@ -1143,7 +1221,11 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false);
|
||||
|
||||
// adds tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
_write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
#else
|
||||
_write_format(file, ";%s%s\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
// Write the custom start G-code
|
||||
_writeln(file, start_gcode);
|
||||
@ -1222,7 +1304,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
for (const LayerToPrint <p : layers_to_print) {
|
||||
std::vector<LayerToPrint> lrs;
|
||||
lrs.emplace_back(std::move(ltp));
|
||||
this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), nullptr, *print_object_instance_sequential_active - object.instances().data());
|
||||
this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), <p == &layers_to_print.back(),
|
||||
nullptr, *print_object_instance_sequential_active - object.instances().data());
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
@ -1286,7 +1369,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
const LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first);
|
||||
if (m_wipe_tower && layer_tools.has_wipe_tower)
|
||||
m_wipe_tower->next_layer();
|
||||
this->process_layer(file, print, layer.second, layer_tools, &print_object_instances_ordering, size_t(-1));
|
||||
this->process_layer(file, print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1));
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
@ -1303,7 +1386,11 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
_write(file, m_writer.set_fan(false));
|
||||
|
||||
// adds tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
_write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
#else
|
||||
_write_format(file, ";%s%s\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
// Process filament-specific gcode in extruder order.
|
||||
{
|
||||
@ -1330,7 +1417,11 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
|
||||
// adds tags for time estimators
|
||||
if (print.config().remaining_times.value)
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
_write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str());
|
||||
#else
|
||||
_writeln(file, GCodeProcessor::Last_Line_M73_Placeholder_Tag);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
print.throw_if_canceled();
|
||||
|
||||
@ -1346,7 +1437,11 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
_write_format(file, "; total filament cost = %.2lf\n", print.m_print_statistics.total_cost);
|
||||
if (print.m_print_statistics.total_toolchanges > 0)
|
||||
_write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
_write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
|
||||
#else
|
||||
_writeln(file, GCodeProcessor::Estimated_Printing_Time_Placeholder_Tag);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
// Append full config.
|
||||
_write(file, "\n");
|
||||
@ -1633,7 +1728,11 @@ namespace ProcessLayer
|
||||
assert(m600_extruder_before_layer >= 0);
|
||||
// Color Change or Tool Change as Color Change.
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Color_Change) + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
|
||||
// && !MMU1
|
||||
@ -1648,21 +1747,27 @@ namespace ProcessLayer
|
||||
gcode += "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (gcode_type == CustomGCode::PausePrint) // Pause print
|
||||
{
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Pause_Print_Tag + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
//! FIXME_in_fw show message during print pause
|
||||
if (!pause_print_msg.empty())
|
||||
gcode += "M117 " + pause_print_msg + "\n";
|
||||
gcode += config.pause_print_gcode;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Custom_Code) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Custom_Code_Tag + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
if (gcode_type == CustomGCode::Template) // Template Cistom Gcode
|
||||
gcode += config.template_custom_gcode;
|
||||
else // custom Gcode
|
||||
@ -1755,6 +1860,7 @@ void GCode::process_layer(
|
||||
// Set of object & print layers of the same PrintObject and with the same print_z.
|
||||
const std::vector<LayerToPrint> &layers,
|
||||
const LayerTools &layer_tools,
|
||||
const bool last_layer,
|
||||
// Pairs of PrintObject index and its instance index.
|
||||
const std::vector<const PrintInstance*> *ordering,
|
||||
// If set to size_t(-1), then print all copies of all objects.
|
||||
@ -1790,7 +1896,7 @@ void GCode::process_layer(
|
||||
// Just a reminder: A spiral vase mode is allowed for a single object, single material print only.
|
||||
m_enable_loop_clipping = true;
|
||||
if (m_spiral_vase && layers.size() == 1 && support_layer == nullptr) {
|
||||
bool enable = (layer.id() > 0 || print.config().brim_width.value == 0.) && (layer.id() >= (size_t)print.config().skirt_height.value && ! print.has_infinite_skirt());
|
||||
bool enable = (layer.id() > 0 || !print.has_brim()) && (layer.id() >= (size_t)print.config().skirt_height.value && ! print.has_infinite_skirt());
|
||||
if (enable) {
|
||||
for (const LayerRegion *layer_region : layer.regions())
|
||||
if (size_t(layer_region->region()->config().bottom_solid_layers.value) > layer.id() ||
|
||||
@ -1808,14 +1914,22 @@ void GCode::process_layer(
|
||||
std::string gcode;
|
||||
|
||||
// add tag for processor
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change) + "\n";
|
||||
#else
|
||||
gcode += ";" + GCodeProcessor::Layer_Change_Tag + "\n";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// export layer z
|
||||
char buf[64];
|
||||
sprintf(buf, ";Z:%g\n", print_z);
|
||||
gcode += buf;
|
||||
// export layer height
|
||||
float height = first_layer ? static_cast<float>(print_z) : static_cast<float>(print_z) - m_last_layer_z;
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), height);
|
||||
#else
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::Height_Tag.c_str(), height);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += buf;
|
||||
// update caches
|
||||
m_last_layer_z = static_cast<float>(print_z);
|
||||
@ -2138,11 +2252,13 @@ void GCode::process_layer(
|
||||
// we apply spiral vase at this stage because it requires a full layer.
|
||||
// Just a reminder: A spiral vase mode is allowed for a single object per layer, single material print only.
|
||||
if (m_spiral_vase)
|
||||
gcode = m_spiral_vase->process_layer(gcode);
|
||||
gcode = m_spiral_vase->process_layer(std::move(gcode));
|
||||
|
||||
// Apply cooling logic; this may alter speeds.
|
||||
if (m_cooling_buffer)
|
||||
gcode = m_cooling_buffer->process_layer(gcode, layer.id());
|
||||
gcode = m_cooling_buffer->process_layer(std::move(gcode), layer.id(),
|
||||
// Flush the cooling buffer at each object layer or possibly at the last layer, even if it contains just supports (This should not happen).
|
||||
object_layer || last_layer);
|
||||
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
// Apply pressure equalization if enabled;
|
||||
@ -2154,7 +2270,7 @@ void GCode::process_layer(
|
||||
|
||||
_write(file, gcode);
|
||||
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
|
||||
log_memory_info();
|
||||
log_memory_info();
|
||||
}
|
||||
|
||||
void GCode::apply_print_config(const PrintConfig &print_config)
|
||||
@ -2457,10 +2573,11 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||
|
||||
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills)
|
||||
{
|
||||
static constexpr const char *support_label = "support material";
|
||||
static constexpr const char *support_interface_label = "support material interface";
|
||||
|
||||
std::string gcode;
|
||||
if (! support_fills.entities.empty()) {
|
||||
const char *support_label = "support material";
|
||||
const char *support_interface_label = "support material interface";
|
||||
const double support_speed = m_config.support_material_speed.value;
|
||||
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
|
||||
for (const ExtrusionEntity *ee : support_fills.entities) {
|
||||
@ -2473,9 +2590,14 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
||||
gcode += this->extrude_path(*path, label, speed);
|
||||
else {
|
||||
const ExtrusionMultiPath *multipath = dynamic_cast<const ExtrusionMultiPath*>(ee);
|
||||
assert(multipath != nullptr);
|
||||
if (multipath)
|
||||
gcode += this->extrude_multi_path(*multipath, label, speed);
|
||||
else {
|
||||
const ExtrusionEntityCollection *eec = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||
assert(eec);
|
||||
if (eec)
|
||||
gcode += this->extrude_support(*eec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2634,17 +2756,23 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
|
||||
if (path.role() != m_last_processor_extrusion_role) {
|
||||
m_last_processor_extrusion_role = path.role();
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(m_last_processor_extrusion_role).c_str());
|
||||
#else
|
||||
sprintf(buf, ";%s%s\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), ExtrusionEntity::role_to_string(m_last_processor_extrusion_role).c_str());
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
if (last_was_wipe_tower || m_last_width != path.width) {
|
||||
m_last_width = path.width;
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width).c_str(), m_last_width);
|
||||
#else
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::Width_Tag.c_str(), m_last_width);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += buf;
|
||||
}
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
if (last_was_wipe_tower || (m_last_mm3_per_mm != path.mm3_per_mm)) {
|
||||
@ -2652,19 +2780,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
if (last_was_wipe_tower || m_last_width != path.width) {
|
||||
m_last_width = path.width;
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::Width_Tag.c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
}
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
if (last_was_wipe_tower || std::abs(m_last_height - path.height) > EPSILON) {
|
||||
m_last_height = path.height;
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), m_last_height);
|
||||
#else
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::Height_Tag.c_str(), m_last_height);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
@ -2735,10 +2859,10 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
|
||||
Point last_post_before_retract = this->last_pos();
|
||||
gcode += this->retract();
|
||||
// When "Wipe while retracting" is enabled, then extruder moves to another position, and travel from this position can cross perimeters.
|
||||
// Because of it, it is necessary to call avoid crossing perimeters for the path between previous last_post and last_post after calling retraction()
|
||||
// Because of it, it is necessary to call avoid crossing perimeters again with new starting point after calling retraction()
|
||||
// FIXME Lukas H.: Try to predict if this second calling of avoid crossing perimeters will be needed or not. It could save computations.
|
||||
if (last_post_before_retract != this->last_pos() && m_config.avoid_crossing_perimeters) {
|
||||
Polyline retract_travel = m_avoid_crossing_perimeters.travel_to(*this, last_post_before_retract);
|
||||
append(retract_travel.points, travel.points);
|
||||
Polyline retract_travel = m_avoid_crossing_perimeters.travel_to(*this, point);
|
||||
travel = std::move(retract_travel);
|
||||
}
|
||||
} else
|
||||
|
@ -33,7 +33,7 @@ class GCode;
|
||||
|
||||
namespace { struct Item; }
|
||||
struct PrintInstance;
|
||||
using PrintObjectPtrs = std::vector<PrintObject*>;
|
||||
class ConstPrintObjectPtrsAdaptor;
|
||||
|
||||
class OozePrevention {
|
||||
public:
|
||||
@ -131,14 +131,9 @@ public:
|
||||
m_volumetric_speed(0),
|
||||
m_last_pos_defined(false),
|
||||
m_last_extrusion_role(erNone),
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_last_width(0.0f),
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_last_mm3_per_mm(0.0),
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_last_width(0.0f),
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_brim_done(false),
|
||||
m_second_layer_things_done(false),
|
||||
@ -201,6 +196,7 @@ private:
|
||||
// Set of object & print layers of the same PrintObject and with the same print_z.
|
||||
const std::vector<LayerToPrint> &layers,
|
||||
const LayerTools &layer_tools,
|
||||
const bool last_layer,
|
||||
// Pairs of PrintObject index and its instance index.
|
||||
const std::vector<const PrintInstance*> *ordering,
|
||||
// If set to size_t(-1), then print all copies of all objects.
|
||||
@ -332,14 +328,9 @@ private:
|
||||
float m_last_height{ 0.0f };
|
||||
float m_last_layer_z{ 0.0f };
|
||||
float m_max_layer_z{ 0.0f };
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
float m_last_width{ 0.0f };
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
double m_last_mm3_per_mm;
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
float m_last_width{ 0.0f };
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
Point m_last_pos;
|
||||
|
@ -283,8 +283,10 @@ static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &bo
|
||||
AllIntersectionsVisitor visitor(edge_grid, intersections, Line(start, end));
|
||||
edge_grid.visit_cells_intersecting_line(start, end, visitor);
|
||||
Vec2d dir = (end - start).cast<double>();
|
||||
for (Intersection &intersection : intersections)
|
||||
intersection.distance = boundary.boundaries_params[intersection.border_idx][intersection.line_idx];
|
||||
for (Intersection &intersection : intersections) {
|
||||
float dist_from_line_begin = (intersection.point - boundary.boundaries[intersection.border_idx][intersection.line_idx]).cast<float>().norm();
|
||||
intersection.distance = boundary.boundaries_params[intersection.border_idx][intersection.line_idx] + dist_from_line_begin;
|
||||
}
|
||||
std::sort(intersections.begin(), intersections.end(), [dir](const auto &l, const auto &r) { return (r.point - l.point).template cast<double>().dot(dir) > 0.; });
|
||||
}
|
||||
|
||||
@ -568,7 +570,7 @@ static void precompute_polygon_distances(const Polygon &polygon, std::vector<flo
|
||||
polygon_distances_out.assign(polygon.size() + 1, 0.f);
|
||||
for (size_t point_idx = 1; point_idx < polygon.size(); ++point_idx)
|
||||
polygon_distances_out[point_idx] = polygon_distances_out[point_idx - 1] + (polygon[point_idx].cast<float>() - polygon[point_idx - 1].cast<float>()).norm();
|
||||
polygon_distances_out.back() = polygon_distances_out[polygon.size() - 1] + (polygon.last_point().cast<float>() - polygon.first_point().cast<float>()).norm();
|
||||
polygon_distances_out.back() = polygon_distances_out[polygon.size() - 1] + (polygon.points.back().cast<float>() - polygon.points.front().cast<float>()).norm();
|
||||
}
|
||||
|
||||
static void precompute_expolygon_distances(const ExPolygon &ex_polygon, std::vector<std::vector<float>> &expolygon_distances_out)
|
||||
@ -596,7 +598,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
{
|
||||
struct Visitor {
|
||||
Visitor(const EdgeGrid::Grid &grid, const size_t contour_idx, const std::vector<float> &polygon_distances, double dist_same_contour_accept, double dist_same_contour_reject) :
|
||||
grid(grid), idx_contour(contour_idx), contour(*grid.contours()[contour_idx]), boundary_parameters(polygon_distances), dist_same_contour_accept(dist_same_contour_accept), dist_same_contour_reject(dist_same_contour_reject) {}
|
||||
grid(grid), idx_contour(contour_idx), contour(grid.contours()[contour_idx]), boundary_parameters(polygon_distances), dist_same_contour_accept(dist_same_contour_accept), dist_same_contour_reject(dist_same_contour_reject) {}
|
||||
|
||||
void init(const Points &contour, const Point &apoint)
|
||||
{
|
||||
@ -630,12 +632,12 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
// Complex case: The closest segment originates from the same contour as the starting point.
|
||||
// Reject the closest point if its distance along the contour is reasonable compared to the current contour bisector
|
||||
// (this->pt, foot).
|
||||
const Slic3r::Points &ipts = *grid.contours()[it_contour_and_segment->first];
|
||||
double param_lo = boundary_parameters[this->idx_point];
|
||||
double param_hi = t * sqrt(l2);
|
||||
double param_end = boundary_parameters.back();
|
||||
const EdgeGrid::Contour &contour = grid.contours()[it_contour_and_segment->first];
|
||||
double param_lo = boundary_parameters[this->idx_point];
|
||||
double param_hi = t * sqrt(l2);
|
||||
double param_end = boundary_parameters.back();
|
||||
const size_t ipt = it_contour_and_segment->second;
|
||||
if (ipt + 1 < ipts.size())
|
||||
if (contour.begin() + ipt + 1 < contour.end())
|
||||
param_hi += boundary_parameters[ipt > 0 ? ipt - 1 : 0];
|
||||
if (param_lo > param_hi)
|
||||
std::swap(param_lo, param_hi);
|
||||
@ -649,9 +651,9 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
// longer than the bisector. That is, the path shall not bulge away from the bisector too much.
|
||||
// Bulge is estimated by 0.6 of the circle circumference drawn around the bisector.
|
||||
// Test whether the contour is convex or concave.
|
||||
bool inside = (t == 0.) ? this->inside_corner(ipts, ipt, this->point) :
|
||||
(t == 1.) ? this->inside_corner(ipts, ipt + 1 == ipts.size() ? 0 : ipt + 1, this->point) :
|
||||
this->left_of_segment(ipts, ipt, this->point);
|
||||
bool inside = (t == 0.) ? this->inside_corner(contour, ipt, this->point) :
|
||||
(t == 1.) ? this->inside_corner(contour, contour.segment_idx_next(ipt), this->point) :
|
||||
this->left_of_segment(contour, ipt, this->point);
|
||||
accept = inside && dist_along_contour > 0.6 * M_PI * dist;
|
||||
}
|
||||
}
|
||||
@ -668,7 +670,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
|
||||
const EdgeGrid::Grid &grid;
|
||||
const size_t idx_contour;
|
||||
const Points &contour;
|
||||
const EdgeGrid::Contour &contour;
|
||||
|
||||
const std::vector<float> &boundary_parameters;
|
||||
const double dist_same_contour_accept;
|
||||
@ -691,25 +693,27 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
return Vec2d(-v1.y() - v2.y(), v1.x() + v2.x());
|
||||
}
|
||||
|
||||
static bool inside_corner(const Slic3r::Points &contour, size_t i, const Point &pt_oposite)
|
||||
static bool inside_corner(const EdgeGrid::Contour &contour, size_t i, const Point &pt_oposite)
|
||||
{
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
size_t iprev = prev_idx_modulo(i, contour);
|
||||
size_t inext = next_idx_modulo(i, contour);
|
||||
Vec2d v1 = (contour[i] - contour[iprev]).cast<double>();
|
||||
Vec2d v2 = (contour[inext] - contour[i]).cast<double>();
|
||||
bool left_of_v1 = cross2(v1, pt - contour[iprev].cast<double>()) > 0.;
|
||||
bool left_of_v2 = cross2(v2, pt - contour[i].cast<double>()) > 0.;
|
||||
const Point &pt_prev = contour.segment_prev(i);
|
||||
const Point &pt_this = contour.segment_start(i);
|
||||
const Point &pt_next = contour.segment_end(i);
|
||||
Vec2d v1 = (pt_this - pt_prev).cast<double>();
|
||||
Vec2d v2 = (pt_next - pt_this).cast<double>();
|
||||
bool left_of_v1 = cross2(v1, pt - pt_prev.cast<double>()) > 0.;
|
||||
bool left_of_v2 = cross2(v2, pt - pt_this.cast<double>()) > 0.;
|
||||
return cross2(v1, v2) > 0 ? left_of_v1 && left_of_v2 : // convex corner
|
||||
left_of_v1 || left_of_v2; // concave corner
|
||||
}
|
||||
|
||||
static bool left_of_segment(const Slic3r::Points &contour, size_t i, const Point &pt_oposite)
|
||||
static bool left_of_segment(const EdgeGrid::Contour &contour, size_t i, const Point &pt_oposite)
|
||||
{
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
size_t inext = next_idx_modulo(i, contour);
|
||||
Vec2d v = (contour[inext] - contour[i]).cast<double>();
|
||||
return cross2(v, pt - contour[i].cast<double>()) > 0.;
|
||||
const Vec2d pt = pt_oposite.cast<double>();
|
||||
const Point &pt_this = contour.segment_start(i);
|
||||
const Point &pt_next = contour.segment_end(i);
|
||||
Vec2d v = (pt_next - pt_this).cast<double>();
|
||||
return cross2(v, pt - pt_this.cast<double>()) > 0.;
|
||||
}
|
||||
} visitor(grid, contour_idx, poly_distances, 0.5 * compensation * M_PI, search_radius);
|
||||
|
||||
@ -727,10 +731,11 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
|
||||
|
||||
// Polygon offset which ensures that if a polygon breaks up into several separate parts, the original polygon will be used in these places.
|
||||
// ExPolygons are handled one by one so returned ExPolygons could intersect.
|
||||
static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset, double min_contour_width = scale_(0.001))
|
||||
static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
|
||||
{
|
||||
double search_radius = 2. * (offset + min_contour_width);
|
||||
ExPolygons ex_poly_result = ex_polygons;
|
||||
double min_contour_width = 2. * offset + SCALED_EPSILON;
|
||||
double search_radius = 2. * (offset + min_contour_width);
|
||||
ExPolygons ex_poly_result = ex_polygons;
|
||||
resample_expolygons(ex_poly_result, offset / 2);
|
||||
|
||||
for (ExPolygon &ex_poly : ex_poly_result) {
|
||||
|
@ -279,11 +279,24 @@ finished:
|
||||
return new_feedrate;
|
||||
}
|
||||
|
||||
std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_id)
|
||||
std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, bool flush)
|
||||
{
|
||||
std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(gcode, m_current_pos);
|
||||
float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
|
||||
return this->apply_layer_cooldown(gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
|
||||
// Cache the input G-code.
|
||||
if (m_gcode.empty())
|
||||
m_gcode = std::move(gcode);
|
||||
else
|
||||
m_gcode += gcode;
|
||||
|
||||
std::string out;
|
||||
if (flush) {
|
||||
// This is either an object layer or the very last print layer. Calculate cool down over the collected support layers
|
||||
// and one object layer.
|
||||
std::vector<PerExtruderAdjustments> per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos);
|
||||
float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments);
|
||||
out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments);
|
||||
m_gcode.clear();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Parse the layer G-code for the moves, which could be adjusted.
|
||||
@ -683,6 +696,13 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
|
||||
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
|
||||
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
|
||||
// Is the fan speed ramp enabled?
|
||||
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
|
||||
if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) {
|
||||
// When ramping up fan speed from disable_fan_first_layers to full_fan_speed_layer, force disable_fan_first_layers above zero,
|
||||
// so there will be a zero fan speed at least at the 1st layer.
|
||||
disable_fan_first_layers = 1;
|
||||
}
|
||||
if (int(layer_id) >= disable_fan_first_layers) {
|
||||
int max_fan_speed = EXTRUDER_CONFIG(max_fan_speed);
|
||||
float slowdown_below_layer_time = float(EXTRUDER_CONFIG(slowdown_below_layer_time));
|
||||
@ -699,11 +719,6 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
}
|
||||
}
|
||||
bridge_fan_speed = EXTRUDER_CONFIG(bridge_fan_speed);
|
||||
// Is the fan speed ramp enabled?
|
||||
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
|
||||
// When ramping up fan speed from disable_fan_first_layers to full_fan_speed_layer, force disable_fan_first_layers above zero,
|
||||
// so there will be a zero fan speed at least at the 1st layer.
|
||||
disable_fan_first_layers = std::max(disable_fan_first_layers, 1);
|
||||
if (int(layer_id) >= disable_fan_first_layers && int(layer_id) + 1 < full_fan_speed_layer) {
|
||||
// Ramp up the fan speed from disable_fan_first_layers to full_fan_speed_layer.
|
||||
float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers);
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
CoolingBuffer(GCode &gcodegen);
|
||||
void reset();
|
||||
void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
|
||||
std::string process_layer(const std::string &gcode, size_t layer_id);
|
||||
std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
|
||||
GCode* gcodegen() { return &m_gcodegen; }
|
||||
|
||||
private:
|
||||
@ -37,6 +37,7 @@ private:
|
||||
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
|
||||
|
||||
GCode& m_gcodegen;
|
||||
// G-code snippet cached for the support layers preceding an object layer.
|
||||
std::string m_gcode;
|
||||
// Internal data.
|
||||
// X,Y,Z,E,F
|
||||
|
@ -19,15 +19,31 @@
|
||||
|
||||
static const float INCHES_TO_MM = 25.4f;
|
||||
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
|
||||
|
||||
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
||||
"TYPE:",
|
||||
"WIPE_START",
|
||||
"WIPE_END",
|
||||
"HEIGHT:",
|
||||
"WIDTH:",
|
||||
"LAYER_CHANGE",
|
||||
"COLOR_CHANGE",
|
||||
"PAUSE_PRINT",
|
||||
"CUSTOM_GCODE",
|
||||
"_GP_FIRST_LINE_M73_PLACEHOLDER",
|
||||
"_GP_LAST_LINE_M73_PLACEHOLDER",
|
||||
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER"
|
||||
};
|
||||
#else
|
||||
const std::string GCodeProcessor::Extrusion_Role_Tag = "TYPE:";
|
||||
const std::string GCodeProcessor::Wipe_Start_Tag = "WIPE_START";
|
||||
const std::string GCodeProcessor::Wipe_End_Tag = "WIPE_END";
|
||||
const std::string GCodeProcessor::Height_Tag = "HEIGHT:";
|
||||
const std::string GCodeProcessor::Width_Tag = "WIDTH:";
|
||||
const std::string GCodeProcessor::Layer_Change_Tag = "LAYER_CHANGE";
|
||||
const std::string GCodeProcessor::Color_Change_Tag = "COLOR_CHANGE";
|
||||
const std::string GCodeProcessor::Pause_Print_Tag = "PAUSE_PRINT";
|
||||
@ -36,17 +52,12 @@ const std::string GCodeProcessor::Custom_Code_Tag = "CUSTOM_GCODE";
|
||||
const std::string GCodeProcessor::First_Line_M73_Placeholder_Tag = "; _GP_FIRST_LINE_M73_PLACEHOLDER";
|
||||
const std::string GCodeProcessor::Last_Line_M73_Placeholder_Tag = "; _GP_LAST_LINE_M73_PLACEHOLDER";
|
||||
const std::string GCodeProcessor::Estimated_Printing_Time_Placeholder_Tag = "; _GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER";
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
const float GCodeProcessor::Wipe_Width = 0.05f;
|
||||
const float GCodeProcessor::Wipe_Height = 0.05f;
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
const std::string GCodeProcessor::Width_Tag = "WIDTH:";
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
const std::string GCodeProcessor::Width_Tag = "WIDTH:";
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
const std::string GCodeProcessor::Mm3_Per_Mm_Tag = "MM3_PER_MM:";
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
@ -324,7 +335,11 @@ void GCodeProcessor::TimeProcessor::reset()
|
||||
machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].enabled = true;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector<MoveVertex>& moves)
|
||||
#else
|
||||
void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
{
|
||||
boost::nowide::ifstream in(filename);
|
||||
if (!in.good())
|
||||
@ -362,11 +377,33 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
|
||||
// replace placeholder lines with the proper final value
|
||||
auto process_placeholders = [&](const std::string& gcode_line) {
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
unsigned int extra_lines_count = 0;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
// remove trailing '\n'
|
||||
std::string line = gcode_line.substr(0, gcode_line.length() - 1);
|
||||
|
||||
std::string ret;
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
if (line.length() > 1) {
|
||||
line = line.substr(1);
|
||||
if (export_remaining_time_enabled &&
|
||||
(line == reserved_tag(ETags::First_Line_M73_Placeholder) || line == reserved_tag(ETags::Last_Line_M73_Placeholder))) {
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
if (machine.enabled) {
|
||||
ret += format_line_M73(machine.line_m73_mask.c_str(),
|
||||
(line == reserved_tag(ETags::First_Line_M73_Placeholder)) ? 0 : 100,
|
||||
(line == reserved_tag(ETags::First_Line_M73_Placeholder)) ? time_in_minutes(machine.time) : 0);
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
++extra_lines_count;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (line == reserved_tag(ETags::Estimated_Printing_Time_Placeholder)) {
|
||||
#else
|
||||
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) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
@ -378,20 +415,28 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
}
|
||||
}
|
||||
else if (line == Estimated_Printing_Time_Placeholder_Tag) {
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
PrintEstimatedTimeStatistics::ETimeMode mode = static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "; estimated printing time (%s mode) = %s\n",
|
||||
(mode == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
get_time_dhms(machine.time).c_str());
|
||||
ret += buf;
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
PrintEstimatedTimeStatistics::ETimeMode mode = static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "; estimated printing time (%s mode) = %s\n",
|
||||
(mode == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
get_time_dhms(machine.time).c_str());
|
||||
ret += buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
return std::tuple(!ret.empty(), ret.empty() ? gcode_line : ret, (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1);
|
||||
#else
|
||||
return std::make_pair(!ret.empty(), ret.empty() ? gcode_line : ret);
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
};
|
||||
|
||||
// check for temporary lines
|
||||
@ -412,8 +457,12 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
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
|
||||
auto process_line_G1 = [&]() {
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
unsigned int exported_lines_count = 0;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
if (export_remaining_time_enabled) {
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
@ -430,11 +479,17 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
export_line += format_line_M73(machine.line_m73_mask.c_str(),
|
||||
to_export.first, to_export.second);
|
||||
last_exported[i] = to_export;
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
++exported_lines_count;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
return exported_lines_count;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
};
|
||||
|
||||
// helper function to write to disk
|
||||
@ -449,15 +504,30 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
export_line.clear();
|
||||
};
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
unsigned int line_id = 0;
|
||||
std::vector<std::pair<unsigned int, unsigned int>> offsets;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
while (std::getline(in, gcode_line)) {
|
||||
if (!in.good()) {
|
||||
fclose(out);
|
||||
throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n"));
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
++line_id;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
gcode_line += "\n";
|
||||
// replace placeholder lines
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
auto [processed, result, lines_added_count] = process_placeholders(gcode_line);
|
||||
if (processed && lines_added_count > 0)
|
||||
offsets.push_back({ line_id, lines_added_count });
|
||||
#else
|
||||
auto [processed, result] = process_placeholders(gcode_line);
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
gcode_line = result;
|
||||
if (!processed) {
|
||||
// remove temporary lines
|
||||
@ -468,8 +538,15 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
parser.parse_line(gcode_line,
|
||||
[&](GCodeReader& reader, const GCodeReader::GCodeLine& line) {
|
||||
if (line.cmd_is("G1")) {
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
unsigned int extra_lines_count = process_line_G1();
|
||||
++g1_lines_counter;
|
||||
if (extra_lines_count > 0)
|
||||
offsets.push_back({ line_id, extra_lines_count });
|
||||
#else
|
||||
process_line_G1();
|
||||
++g1_lines_counter;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -485,6 +562,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
fclose(out);
|
||||
in.close();
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
// updates moves' gcode ids which have been modified by the insertion of the M73 lines
|
||||
unsigned int curr_offset_id = 0;
|
||||
unsigned int total_offset = 0;
|
||||
for (MoveVertex& move : moves) {
|
||||
while (curr_offset_id < static_cast<unsigned int>(offsets.size()) && offsets[curr_offset_id].first <= move.gcode_id) {
|
||||
total_offset += offsets[curr_offset_id].second;
|
||||
++curr_offset_id;
|
||||
}
|
||||
move.gcode_id += total_offset;
|
||||
}
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
if (rename_file(out_path, filename))
|
||||
throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + filename + '\n' +
|
||||
"Is " + out_path + " locked?" + '\n');
|
||||
@ -503,6 +593,64 @@ const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProces
|
||||
|
||||
unsigned int GCodeProcessor::s_result_id = 0;
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
|
||||
{
|
||||
size_t tag_len = tag.size();
|
||||
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
|
||||
}
|
||||
|
||||
bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string& found_tag)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
GCodeReader parser;
|
||||
parser.parse_buffer(gcode, [&ret, &found_tag](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
|
||||
std::string comment = line.raw();
|
||||
if (comment.length() > 2 && comment.front() == ';') {
|
||||
comment = comment.substr(1);
|
||||
for (const std::string& s : Reserved_Tags) {
|
||||
if (starts_with(comment, s)) {
|
||||
ret = true;
|
||||
found_tag = comment;
|
||||
parser.quit_parsing();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector<std::string>& found_tag)
|
||||
{
|
||||
max_count = std::max(max_count, 1U);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
GCodeReader parser;
|
||||
parser.parse_buffer(gcode, [&ret, &found_tag, max_count](GCodeReader& parser, const GCodeReader::GCodeLine& line) {
|
||||
std::string comment = line.raw();
|
||||
if (comment.length() > 2 && comment.front() == ';') {
|
||||
comment = comment.substr(1);
|
||||
for (const std::string& s : Reserved_Tags) {
|
||||
if (starts_with(comment, s)) {
|
||||
ret = true;
|
||||
found_tag.push_back(comment);
|
||||
if (found_tag.size() == max_count) {
|
||||
parser.quit_parsing();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
GCodeProcessor::GCodeProcessor()
|
||||
{
|
||||
reset();
|
||||
@ -750,13 +898,14 @@ void GCodeProcessor::reset()
|
||||
m_cached_position.reset();
|
||||
m_wiping = false;
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
m_line_id = 0;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
m_feedrate = 0.0f;
|
||||
m_width = 0.0f;
|
||||
m_height = 0.0f;
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_forced_width = 0.0f;
|
||||
m_forced_height = 0.0f;
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
m_mm3_per_mm = 0.0f;
|
||||
m_fan_speed = 0.0f;
|
||||
|
||||
@ -808,7 +957,11 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||
if (cmd.length() == 0) {
|
||||
const std::string_view comment = line.comment();
|
||||
if (comment.length() > 1 && detect_producer(comment))
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
m_parser.quit_parsing();
|
||||
#else
|
||||
m_parser.quit_parsing_file();
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
}
|
||||
});
|
||||
|
||||
@ -817,7 +970,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||
if (m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) {
|
||||
DynamicPrintConfig config;
|
||||
config.apply(FullPrintConfig::defaults());
|
||||
config.load_from_gcode_file(filename);
|
||||
config.load_from_gcode_file(filename, false);
|
||||
apply_config(config);
|
||||
}
|
||||
}
|
||||
@ -859,7 +1012,11 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
|
||||
|
||||
// post-process to add M73 lines into the gcode
|
||||
if (apply_postprocess)
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
m_time_processor.post_process(filename, m_result.moves);
|
||||
#else
|
||||
m_time_processor.post_process(filename);
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
std::cout << "\n";
|
||||
@ -935,6 +1092,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
/* std::cout << line.raw() << std::endl; */
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
++m_line_id;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
// update start position
|
||||
m_start_position = m_end_position;
|
||||
|
||||
@ -1004,11 +1165,13 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
||||
}
|
||||
}
|
||||
|
||||
#if !ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
|
||||
{
|
||||
size_t tag_len = tag.size();
|
||||
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
|
||||
}
|
||||
#endif // !ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
#if __has_include(<charconv>)
|
||||
template <typename T, typename = void>
|
||||
@ -1061,6 +1224,25 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
if (m_producers_enabled && process_producers_tags(comment))
|
||||
return;
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// extrusion role tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Role))) {
|
||||
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe start tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
|
||||
m_wiping = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe end tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Wipe_End))) {
|
||||
m_wiping = false;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// extrusion role tag
|
||||
if (starts_with(comment, Extrusion_Role_Tag)) {
|
||||
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(Extrusion_Role_Tag.length()));
|
||||
@ -1078,9 +1260,23 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
m_wiping = false;
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) {
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// height tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Height))) {
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
// width tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Width))) {
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Width).size()), m_forced_width))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// height tag
|
||||
if (starts_with(comment, Height_Tag)) {
|
||||
if (!parse_number(comment.substr(Height_Tag.size()), m_forced_height))
|
||||
@ -1093,26 +1289,56 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
}
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// color change tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Color_Change))) {
|
||||
unsigned char extruder_id = 0;
|
||||
if (starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) {
|
||||
int eid;
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Color_Change).size() + 2), eid) || eid < 0 || eid > 255) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
extruder_id = static_cast<unsigned char>(eid);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
process_custom_gcode_time(CustomGCode::ColorChange);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// pause print tag
|
||||
if (comment == reserved_tag(ETags::Pause_Print)) {
|
||||
store_move_vertex(EMoveType::Pause_Print);
|
||||
process_custom_gcode_time(CustomGCode::PausePrint);
|
||||
return;
|
||||
}
|
||||
|
||||
// custom code tag
|
||||
if (comment == reserved_tag(ETags::Custom_Code)) {
|
||||
store_move_vertex(EMoveType::Custom_GCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// layer change tag
|
||||
if (comment == reserved_tag(ETags::Layer_Change)) {
|
||||
++m_layer_id;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if ((!m_producers_enabled || m_producer == EProducer::PrusaSlicer) &&
|
||||
starts_with(comment, Height_Tag)) {
|
||||
// height tag
|
||||
if (!parse_number(comment.substr(Height_Tag.size()), m_height))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
// width tag
|
||||
if (starts_with(comment, Width_Tag)) {
|
||||
if (! parse_number(comment.substr(Width_Tag.size()), m_width_compare.last_tag_value))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
// color change tag
|
||||
if (starts_with(comment, Color_Change_Tag)) {
|
||||
unsigned char extruder_id = 0;
|
||||
@ -1153,6 +1379,13 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
return;
|
||||
}
|
||||
|
||||
// layer change tag
|
||||
if (comment == Layer_Change_Tag) {
|
||||
++m_layer_id;
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
// mm3_per_mm print tag
|
||||
if (starts_with(comment, Mm3_Per_Mm_Tag)) {
|
||||
@ -1161,12 +1394,6 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
return;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
// layer change tag
|
||||
if (comment == Layer_Change_Tag) {
|
||||
++m_layer_id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool GCodeProcessor::process_producers_tags(const std::string_view comment)
|
||||
@ -1343,7 +1570,6 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
|
||||
}
|
||||
|
||||
// geometry
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
// ; tool
|
||||
std::string tag = " tool";
|
||||
pos = comment.find(tag);
|
||||
@ -1369,35 +1595,6 @@ bool GCodeProcessor::process_simplify3d_tags(const std::string_view comment)
|
||||
|
||||
// ; layer
|
||||
tag = " layer";
|
||||
#else
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
// ; tool
|
||||
std::string tag = " tool";
|
||||
pos = comment.find(tag);
|
||||
if (pos == 0) {
|
||||
const std::string_view data = comment.substr(pos + tag.length());
|
||||
std::string h_tag = "H";
|
||||
size_t h_start = data.find(h_tag);
|
||||
size_t h_end = data.find_first_of(' ', h_start);
|
||||
std::string w_tag = "W";
|
||||
size_t w_start = data.find(w_tag);
|
||||
size_t w_end = data.find_first_of(' ', w_start);
|
||||
if (h_start != data.npos) {
|
||||
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))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
}
|
||||
if (w_start != data.npos) {
|
||||
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))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
// ; layer
|
||||
std::string tag = " layer";
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
pos = comment.find(tag);
|
||||
if (pos == 0) {
|
||||
// skip lines "; layer end"
|
||||
@ -1488,7 +1685,6 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string_view comment)
|
||||
}
|
||||
|
||||
// geometry
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
// width
|
||||
tag = "WIDTH:";
|
||||
pos = comment.find(tag);
|
||||
@ -1506,27 +1702,6 @@ bool GCodeProcessor::process_ideamaker_tags(const std::string_view comment)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
// width
|
||||
tag = "WIDTH:";
|
||||
pos = comment.find(tag);
|
||||
if (pos != comment.npos) {
|
||||
if (! parse_number(comment.substr(pos + tag.length()), m_width_compare.last_tag_value))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return true;
|
||||
}
|
||||
|
||||
// height
|
||||
tag = "HEIGHT:";
|
||||
pos = comment.find(tag);
|
||||
if (pos != comment.npos) {
|
||||
if (! parse_number(comment.substr(pos + tag.length()), m_height_compare.last_tag_value))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
// layer
|
||||
pos = comment.find("LAYER:");
|
||||
@ -1755,7 +1930,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
if (m_forced_height > 0.0f)
|
||||
m_height = m_forced_height;
|
||||
else {
|
||||
@ -1768,25 +1942,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_height_compare.update(m_height, m_extrusion_role);
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#else
|
||||
if ((m_producers_enabled && m_producer != EProducer::PrusaSlicer) || m_height == 0.0f) {
|
||||
if (m_end_position[Z] > m_extruded_last_z + EPSILON) {
|
||||
m_height = m_end_position[Z] - m_extruded_last_z;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_height_compare.update(m_height, m_extrusion_role);
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_extruded_last_z = m_end_position[Z];
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
if (m_forced_width > 0.0f)
|
||||
m_width = m_forced_width;
|
||||
else if (m_extrusion_role == erExternalPerimeter)
|
||||
#else
|
||||
if (m_extrusion_role == erExternalPerimeter)
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
// cross section: rectangle
|
||||
m_width = delta_pos[E] * static_cast<float>(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height);
|
||||
else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone)
|
||||
@ -2340,6 +2499,10 @@ void GCodeProcessor::process_T(const std::string_view command)
|
||||
if (command.length() > 1) {
|
||||
int eid = 0;
|
||||
if (! parse_number(command.substr(1), eid) || eid < 0 || eid > 255) {
|
||||
// Specific to the MMU2 V2 (see https://www.help.prusa3d.com/en/article/prusa-specific-g-codes_112173):
|
||||
if (m_flavor == gcfMarlin && (command == "Tx" || command == "Tc" || command == "T?"))
|
||||
return;
|
||||
|
||||
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
||||
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
||||
@ -2372,6 +2535,9 @@ void GCodeProcessor::process_T(const std::string_view command)
|
||||
void GCodeProcessor::store_move_vertex(EMoveType type)
|
||||
{
|
||||
MoveVertex vertex = {
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
m_line_id,
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
type,
|
||||
m_extrusion_role,
|
||||
m_extruder_id,
|
||||
|
@ -69,7 +69,34 @@ namespace Slic3r {
|
||||
|
||||
class GCodeProcessor
|
||||
{
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
static const std::vector<std::string> Reserved_Tags;
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
public:
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
enum class ETags : unsigned char
|
||||
{
|
||||
Role,
|
||||
Wipe_Start,
|
||||
Wipe_End,
|
||||
Height,
|
||||
Width,
|
||||
Layer_Change,
|
||||
Color_Change,
|
||||
Pause_Print,
|
||||
Custom_Code,
|
||||
First_Line_M73_Placeholder,
|
||||
Last_Line_M73_Placeholder,
|
||||
Estimated_Printing_Time_Placeholder
|
||||
};
|
||||
|
||||
static const std::string& reserved_tag(ETags tag) { return Reserved_Tags[static_cast<unsigned char>(tag)]; }
|
||||
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
|
||||
static bool contains_reserved_tag(const std::string& gcode, std::string& found_tag);
|
||||
// checks the given gcode for reserved tags and returns true when finding any
|
||||
// (the first max_count found tags are returned into found_tag)
|
||||
static bool contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector<std::string>& found_tag);
|
||||
#else
|
||||
static const std::string Extrusion_Role_Tag;
|
||||
static const std::string Wipe_Start_Tag;
|
||||
static const std::string Wipe_End_Tag;
|
||||
@ -81,17 +108,13 @@ namespace Slic3r {
|
||||
static const std::string First_Line_M73_Placeholder_Tag;
|
||||
static const std::string Last_Line_M73_Placeholder_Tag;
|
||||
static const std::string Estimated_Printing_Time_Placeholder_Tag;
|
||||
static const std::string Width_Tag;
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
static const float Wipe_Width;
|
||||
static const float Wipe_Height;
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
static const std::string Width_Tag;
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
static const std::string Width_Tag;
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
static const std::string Mm3_Per_Mm_Tag;
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
@ -173,6 +196,27 @@ namespace Slic3r {
|
||||
float time() const;
|
||||
};
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
struct MoveVertex
|
||||
{
|
||||
unsigned int gcode_id{ 0 };
|
||||
EMoveType type{ EMoveType::Noop };
|
||||
ExtrusionRole extrusion_role{ erNone };
|
||||
unsigned char extruder_id{ 0 };
|
||||
unsigned char cp_color_id{ 0 };
|
||||
Vec3f position{ Vec3f::Zero() }; // mm
|
||||
float delta_extruder{ 0.0f }; // mm
|
||||
float feedrate{ 0.0f }; // mm/s
|
||||
float width{ 0.0f }; // mm
|
||||
float height{ 0.0f }; // mm
|
||||
float mm3_per_mm{ 0.0f };
|
||||
float fan_speed{ 0.0f }; // percentage
|
||||
float time{ 0.0f }; // s
|
||||
|
||||
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
||||
};
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
private:
|
||||
struct TimeMachine
|
||||
{
|
||||
@ -253,10 +297,16 @@ namespace Slic3r {
|
||||
void reset();
|
||||
|
||||
// post process the file with the given filename to add remaining time lines M73
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
// and updates moves' gcode ids accordingly
|
||||
void post_process(const std::string& filename, std::vector<MoveVertex>& moves);
|
||||
#else
|
||||
void post_process(const std::string& filename);
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
};
|
||||
|
||||
public:
|
||||
#if !ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
struct MoveVertex
|
||||
{
|
||||
EMoveType type{ EMoveType::Noop };
|
||||
@ -274,6 +324,7 @@ namespace Slic3r {
|
||||
|
||||
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
||||
};
|
||||
#endif // !ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
|
||||
struct Result
|
||||
{
|
||||
@ -404,13 +455,14 @@ namespace Slic3r {
|
||||
CachedPosition m_cached_position;
|
||||
bool m_wiping;
|
||||
|
||||
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
unsigned int m_line_id;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
float m_feedrate; // mm/s
|
||||
float m_width; // mm
|
||||
float m_height; // mm
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
float m_forced_width; // mm
|
||||
float m_forced_height; // mm
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
float m_mm3_per_mm;
|
||||
float m_fan_speed; // percentage
|
||||
ExtrusionRole m_extrusion_role;
|
||||
|
@ -15,7 +15,7 @@ static constexpr float ENFORCER_BLOCKER_PENALTY = 100;
|
||||
|
||||
// In case there are custom enforcers/blockers, the loop polygon shall always have
|
||||
// sides smaller than this (so it isn't limited to original resolution).
|
||||
static constexpr float MINIMAL_POLYGON_SIDE = scale_(0.2f);
|
||||
static constexpr float MINIMAL_POLYGON_SIDE = scaled<float>(0.2f);
|
||||
|
||||
// When spAligned is active and there is a support enforcer,
|
||||
// add this penalty to its center.
|
||||
@ -664,7 +664,7 @@ static std::vector<size_t> find_enforcer_centers(const Polygon& polygon,
|
||||
if (polygon.size() < 2 || enforcers_idxs.empty())
|
||||
return out;
|
||||
|
||||
auto get_center_idx = [&polygon, &lengths](size_t start_idx, size_t end_idx) -> size_t {
|
||||
auto get_center_idx = [&lengths](size_t start_idx, size_t end_idx) -> size_t {
|
||||
assert(end_idx >= start_idx);
|
||||
if (start_idx == end_idx)
|
||||
return start_idx;
|
||||
@ -750,35 +750,36 @@ void SeamPlacer::apply_custom_seam(const Polygon& polygon, size_t po_idx,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// std::ostringstream os;
|
||||
// os << std::setw(3) << std::setfill('0') << layer_id;
|
||||
// int a = scale_(30.);
|
||||
// SVG svg("custom_seam" + os.str() + ".svg", BoundingBox(Point(-a, -a), Point(a, a)));
|
||||
// //if (! m_enforcers[po_idx].empty())
|
||||
// // svg.draw(m_enforcers[po_idx][layer_id].polys, "blue");
|
||||
// //if (! m_blockers[po_idx].empty())
|
||||
// // svg.draw(m_blockers[po_idx][layer_id].polys, "red");
|
||||
#if 0
|
||||
std::ostringstream os;
|
||||
os << std::setw(3) << std::setfill('0') << layer_id;
|
||||
int a = scale_(30.);
|
||||
SVG svg("custom_seam" + os.str() + ".svg", BoundingBox(Point(-a, -a), Point(a, a)));
|
||||
if (! m_enforcers[po_idx].empty())
|
||||
svg.draw(m_enforcers[po_idx][layer_id].polys, "blue");
|
||||
if (! m_blockers[po_idx].empty())
|
||||
svg.draw(m_blockers[po_idx][layer_id].polys, "red");
|
||||
|
||||
if (! blockers_idxs.empty()) {
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
size_t min_idx = std::min_element(penalties.begin(), penalties.end()) - penalties.begin();
|
||||
|
||||
// size_t min_idx = std::min_element(penalties.begin(), penalties.end()) - penalties.begin();
|
||||
|
||||
// //svg.draw(polygon.points[idx_min], "red", 6e5);
|
||||
// for (size_t i=0; i<polygon.points.size(); ++i) {
|
||||
// std::string fill;
|
||||
// coord_t size = 0;
|
||||
// if (min_idx == i) {
|
||||
// fill = "yellow";
|
||||
// size = 5e5;
|
||||
// } else
|
||||
// fill = (std::find(enforcers_idxs.begin(), enforcers_idxs.end(), i) != enforcers_idxs.end() ? "green" : "black");
|
||||
// if (i != 0)
|
||||
// svg.draw(polygon.points[i], fill, size);
|
||||
// else
|
||||
// svg.draw(polygon.points[i], "red", 5e5);
|
||||
// }
|
||||
//////////////////////
|
||||
for (size_t i=0; i<polygon.points.size(); ++i) {
|
||||
std::string fill;
|
||||
coord_t size = 5e5;
|
||||
if (min_idx == i)
|
||||
fill = "yellow";
|
||||
else
|
||||
fill = (std::find(blockers_idxs.begin(), blockers_idxs.end(), i) != blockers_idxs.end() ? "green" : "black");
|
||||
if (i != 0)
|
||||
svg.draw(polygon.points[i], fill, size);
|
||||
else
|
||||
svg.draw(polygon.points[i], "red", 5e5);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -786,16 +787,16 @@ void SeamPlacer::apply_custom_seam(const Polygon& polygon, size_t po_idx,
|
||||
|
||||
std::optional<Point> SeamHistory::get_last_seam(const PrintObject* po, size_t layer_id, const BoundingBox& island_bb)
|
||||
{
|
||||
assert(layer_id >= m_layer_id);
|
||||
if (layer_id > m_layer_id) {
|
||||
assert(layer_id >= m_layer_id || layer_id == 0);
|
||||
if (layer_id != m_layer_id) {
|
||||
// Get seam was called for different layer than last time.
|
||||
if (layer_id == 0) // seq printing
|
||||
m_data_this_layer.clear();
|
||||
m_data_last_layer = m_data_this_layer;
|
||||
m_data_this_layer.clear();
|
||||
m_layer_id = layer_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::optional<Point> out;
|
||||
|
||||
auto seams_it = m_data_last_layer.find(po);
|
||||
|
@ -600,7 +600,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
return std::max(0.f, volume_to_wipe); // Soluble filament cannot be wiped in a random infill, neither the filament after it
|
||||
|
||||
// we will sort objects so that dedicated for wiping are at the beginning:
|
||||
PrintObjectPtrs object_list = print.objects();
|
||||
ConstPrintObjectPtrs object_list = print.objects().vector();
|
||||
std::sort(object_list.begin(), object_list.end(), [](const PrintObject* a, const PrintObject* b) { return a->config().wipe_into_objects; });
|
||||
|
||||
// We will now iterate through
|
||||
|
@ -42,36 +42,32 @@ public:
|
||||
{
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
|
||||
m_gcode += buf;
|
||||
sprintf(buf, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erWipeTower).c_str());
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
|
||||
m_gcode += buf;
|
||||
sprintf(buf, ";%s%s\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), ExtrusionEntity::role_to_string(erWipeTower).c_str());
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
m_gcode += buf;
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
change_analyzer_line_width(line_width);
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
WipeTowerWriter& change_analyzer_line_width(float line_width) {
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width).c_str(), line_width);
|
||||
#else
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), line_width);
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
m_gcode += buf;
|
||||
return *this;
|
||||
}
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
#if !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
WipeTowerWriter& change_analyzer_line_width(float line_width) {
|
||||
// adds tag for analyzer:
|
||||
char buf[64];
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), line_width);
|
||||
m_gcode += buf;
|
||||
return *this;
|
||||
}
|
||||
#endif // !ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE
|
||||
|
||||
WipeTowerWriter& change_analyzer_mm3_per_mm(float len, float e) {
|
||||
static const float area = float(M_PI) * 1.75f * 1.75f / 4.f;
|
||||
float mm3_per_mm = (len == 0.f ? 0.f : area * e / len);
|
||||
@ -405,7 +401,7 @@ public:
|
||||
|
||||
WipeTowerWriter& append(const std::string& text) { m_gcode += text; return *this; }
|
||||
|
||||
std::vector<Vec2f> wipe_path() const
|
||||
const std::vector<Vec2f>& wipe_path() const
|
||||
{
|
||||
return m_wipe_path;
|
||||
}
|
||||
@ -874,12 +870,8 @@ void WipeTower::toolchange_Unload(
|
||||
const float line_width = m_perimeter_width * m_filpar[m_current_tool].ramming_line_width_multiplicator; // desired ramming line thickness
|
||||
const float y_step = line_width * m_filpar[m_current_tool].ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm
|
||||
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
writer.append("; CP TOOLCHANGE UNLOAD\n")
|
||||
.change_analyzer_line_width(line_width);
|
||||
#else
|
||||
writer.append("; CP TOOLCHANGE UNLOAD\n");
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
unsigned i = 0; // iterates through ramming_speed
|
||||
m_left_to_right = true; // current direction of ramming
|
||||
@ -942,9 +934,7 @@ void WipeTower::toolchange_Unload(
|
||||
}
|
||||
}
|
||||
Vec2f end_of_ramming(writer.x(),writer.y());
|
||||
#if ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
writer.change_analyzer_line_width(m_perimeter_width); // so the next lines are not affected by ramming_line_width_multiplier
|
||||
#endif // ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE || ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
// Retraction:
|
||||
float old_x = writer.x();
|
||||
|
@ -116,8 +116,13 @@ void GCodeReader::parse_file(const std::string &file, callback_t callback)
|
||||
{
|
||||
boost::nowide::ifstream f(file);
|
||||
std::string line;
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
m_parsing = true;
|
||||
while (m_parsing && std::getline(f, line))
|
||||
#else
|
||||
m_parsing_file = true;
|
||||
while (m_parsing_file && std::getline(f, line))
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
this->parse_line(line, callback);
|
||||
}
|
||||
|
||||
|