Merge remote-tracking branch 'origin/ys_wx317_master' into ys_cut

This commit is contained in:
YuSanka 2022-06-29 11:44:11 +02:00
commit 89a7f6bdb1
167 changed files with 26900 additions and 24434 deletions

2
.gitignore vendored
View File

@ -18,4 +18,4 @@ local-lib
build-linux/*
deps/build-linux/*
**/.DS_Store
/.idea/
**/.idea/

View File

@ -458,9 +458,8 @@ if (NOT EIGEN3_FOUND)
endif ()
include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR})
# Find expat or use bundled version
# Always use the system libexpat on Linux.
# Find expat. We have our overriden FindEXPAT which exports libexpat target
# no matter what.
find_package(EXPAT REQUIRED)
add_library(libexpat INTERFACE)

View File

@ -30,82 +30,101 @@
# ``CURL_VERSION_STRING``
# The version of curl found.
# Look for the header file.
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
mark_as_advanced(CURL_INCLUDE_DIR)
# First, prefer config scripts
set(_q "")
if(CURL_FIND_QUIETLY)
set(_q QUIET)
endif()
find_package(CURL ${CURL_FIND_VERSION} CONFIG ${_q})
if(NOT CURL_LIBRARY)
# Look for the library (sorted from most current/relevant entry to least).
find_library(CURL_LIBRARY_RELEASE NAMES
curl
# Windows MSVC prebuilts:
curllib
libcurl_imp
curllib_static
# Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
libcurl
# Static library on Windows
libcurl_a
)
mark_as_advanced(CURL_LIBRARY_RELEASE)
find_library(CURL_LIBRARY_DEBUG NAMES
# Windows MSVC CMake builds in debug configuration on vcpkg:
libcurl-d_imp
libcurl-d
# Static library on Windows, compiled in debug mode
libcurl_a_debug
)
mark_as_advanced(CURL_LIBRARY_DEBUG)
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations_SLIC3R.cmake)
select_library_configurations_SLIC3R(CURL)
if(NOT CURL_FIND_QUIETLY)
if (NOT CURL_FOUND)
message(STATUS "Falling back to MODULE search for CURL...")
else()
message(STATUS "CURL found in ${CURL_DIR}")
endif()
endif()
if(CURL_INCLUDE_DIR)
foreach(_curl_version_header curlver.h curl.h)
if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
if (NOT CURL_FOUND)
string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}")
unset(curl_version_str)
break()
endif()
endforeach()
endif()
# Look for the header file.
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
mark_as_advanced(CURL_INCLUDE_DIR)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs_SLIC3R.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS_SLIC3R(CURL
REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
VERSION_VAR CURL_VERSION_STRING)
if(NOT CURL_LIBRARY)
# Look for the library (sorted from most current/relevant entry to least).
find_library(CURL_LIBRARY_RELEASE NAMES
curl
# Windows MSVC prebuilts:
curllib
libcurl_imp
curllib_static
# Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
libcurl
# Static library on Windows
libcurl_a
)
mark_as_advanced(CURL_LIBRARY_RELEASE)
if(CURL_FOUND)
set(CURL_LIBRARIES ${CURL_LIBRARY})
set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
find_library(CURL_LIBRARY_DEBUG NAMES
# Windows MSVC CMake builds in debug configuration on vcpkg:
libcurl-d_imp
libcurl-d
# Static library on Windows, compiled in debug mode
libcurl_a_debug
)
mark_as_advanced(CURL_LIBRARY_DEBUG)
if(NOT TARGET CURL::libcurl)
add_library(CURL::libcurl UNKNOWN IMPORTED)
set_target_properties(CURL::libcurl PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations_SLIC3R.cmake)
select_library_configurations_SLIC3R(CURL)
endif()
if(EXISTS "${CURL_LIBRARY}")
if(CURL_INCLUDE_DIR)
foreach(_curl_version_header curlver.h curl.h)
if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}")
file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"")
string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}")
unset(curl_version_str)
break()
endif()
endforeach()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs_SLIC3R.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS_SLIC3R(CURL
REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR
VERSION_VAR CURL_VERSION_STRING)
if(CURL_FOUND)
set(CURL_LIBRARIES ${CURL_LIBRARY})
set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
if(NOT TARGET CURL::libcurl)
add_library(CURL::libcurl UNKNOWN IMPORTED)
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${CURL_LIBRARY}")
endif()
if(CURL_LIBRARY_RELEASE)
set_property(TARGET CURL::libcurl APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}")
endif()
if(CURL_LIBRARY_DEBUG)
set_property(TARGET CURL::libcurl APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}")
INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
if(EXISTS "${CURL_LIBRARY}")
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${CURL_LIBRARY}")
endif()
if(CURL_LIBRARY_RELEASE)
set_property(TARGET CURL::libcurl APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}")
endif()
if(CURL_LIBRARY_DEBUG)
set_property(TARGET CURL::libcurl APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(CURL::libcurl PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}")
endif()
endif()
endif()
endif()
endif (NOT CURL_FOUND)

View File

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

1
deps/CMakeLists.txt vendored
View File

@ -188,6 +188,7 @@ endif ()
include(JPEG/JPEG.cmake)
include(TIFF/TIFF.cmake)
include(NanoSVG/NanoSVG.cmake)
include(wxWidgets/wxWidgets.cmake)
set(_dep_list

View File

@ -4,8 +4,8 @@ find_package(OpenGL QUIET REQUIRED)
prusaslicer_add_cmake_project(
GLEW
URL https://sourceforge.net/projects/glew/files/glew/2.1.0/glew-2.1.0.zip
URL_HASH SHA256=2700383d4de2455f06114fbaf872684f15529d4bdc5cdea69b5fb0e9aa7763f1
URL https://sourceforge.net/projects/glew/files/glew/2.2.0/glew-2.2.0.zip
URL_HASH SHA256=a9046a913774395a095edcc0b0ac2d81c3aacca61787b39839b941e9be14e0d4
SOURCE_SUBDIR build/cmake
CMAKE_ARGS
-DBUILD_UTILS=OFF

4
deps/NanoSVG/NanoSVG.cmake vendored Normal file
View File

@ -0,0 +1,4 @@
prusaslicer_add_cmake_project(NanoSVG
URL https://github.com/memononen/nanosvg/archive/4c8f0139b62c6e7faa3b67ce1fbe6e63590ed148.zip
URL_HASH SHA256=584e084af1a75bf633f79753ce2f6f6ec8686002ca27f35f1037c25675fecfb6
)

View File

@ -1,5 +1,3 @@
set(_wx_git_tag v3.1.4-patched)
set(_wx_toolkit "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(_gtk_ver 2)
@ -15,11 +13,9 @@ if (UNIX AND NOT APPLE) # wxWidgets will not use char as the underlying type for
endif()
prusaslicer_add_cmake_project(wxWidgets
# GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets"
# GIT_TAG tm_cross_compile #${_wx_git_tag}
URL https://github.com/prusa3d/wxWidgets/archive/489f6118256853cf5b299d595868641938566cdb.zip
URL_HASH SHA256=5b22d465377cedd8044bba69bea958b248953fd3628c1de4913a84d4e6f6175b
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} dep_TIFF dep_JPEG
URL https://github.com/prusa3d/wxWidgets/archive/e616df45b3a8aedc31beb5540df793dd1f0f3914.zip
URL_HASH SHA256=30bc6cad64dce5cdc755e3a4119cfeb24c12d43279e1e062d8ac350d3880f315
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} dep_TIFF dep_JPEG dep_NanoSVG
CMAKE_ARGS
-DwxBUILD_PRECOMP=ON
${_wx_toolkit}
@ -32,13 +28,16 @@ prusaslicer_add_cmake_project(wxWidgets
-DwxUSE_OPENGL=ON
-DwxUSE_LIBPNG=sys
-DwxUSE_ZLIB=sys
-DwxUSE_REGEX=builtin
-DwxUSE_NANOSVG=sys
-DwxUSE_NANOSVG_EXTERNAL=ON
-DwxUSE_REGEX=OFF
-DwxUSE_LIBXPM=builtin
-DwxUSE_LIBJPEG=sys
-DwxUSE_LIBTIFF=sys
-DwxUSE_EXPAT=sys
-DwxUSE_LIBSDL=OFF
-DwxUSE_XTEST=OFF
-DwxUSE_GLCANVAS_EGL=OFF
)
if (MSVC)

View File

@ -1,3 +1,5 @@
min_slic3r_version = 2.5.0-alpha0
0.1.5 Added Ender-3 S1 Pro
min_slic3r_version = 2.4.1
0.1.4 Added Ender-3 Pro. Added M25 support for some printers.
min_slic3r_version = 2.4.0-rc

View File

@ -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.1.4
config_version = 0.1.5
# 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%
@ -21,7 +21,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3BLTOUCH]
name = Creality Ender-3 BLTouch
@ -30,7 +30,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3PRO]
name = Creality Ender-3 Pro
@ -39,7 +39,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3V2]
name = Creality Ender-3 V2
@ -48,7 +48,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3S1]
name = Creality Ender-3 S1
@ -57,7 +57,16 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3S1PRO]
name = Creality Ender-3 S1 Pro
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER3MAX]
name = Creality Ender-3 Max
@ -66,7 +75,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER4]
name = Creality Ender-4
@ -75,7 +84,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER5]
name = Creality Ender-5
@ -84,7 +93,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER5PLUS]
name = Creality Ender-5 Plus
@ -93,7 +102,7 @@ technology = FFF
family = ENDER
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER6]
name = Creality Ender-6
@ -102,7 +111,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER7]
name = Creality Ender-7
@ -111,7 +120,7 @@ technology = FFF
family = ENDER
bed_model = ender7_bed.stl
bed_texture = ender7.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER2]
name = Creality Ender-2
@ -120,7 +129,7 @@ technology = FFF
family = ENDER
bed_model = ender2_bed.stl
bed_texture = ender2.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:ENDER2PRO]
name = Creality Ender-2 Pro
@ -129,7 +138,7 @@ technology = FFF
family = ENDER
bed_model = ender2pro_bed.stl
bed_texture = ender2pro.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR5PRO]
name = Creality CR-5 Pro
@ -138,7 +147,7 @@ technology = FFF
family = CR
bed_model = cr5pro_bed.stl
bed_texture = cr5pro.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR5PROH]
name = Creality CR-5 Pro H
@ -147,7 +156,7 @@ technology = FFF
family = CR
bed_model = cr5pro_bed.stl
bed_texture = cr5pro.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR6SE]
name = Creality CR-6 SE
@ -156,7 +165,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR6MAX]
name = Creality CR-6 Max
@ -165,7 +174,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10SMART]
name = Creality CR-10 SMART
@ -174,7 +183,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10MINI]
name = Creality CR-10 Mini
@ -183,7 +192,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10MAX]
name = Creality CR-10 Max
@ -192,7 +201,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10]
name = Creality CR-10
@ -201,7 +210,7 @@ technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10V2]
name = Creality CR-10 V2
@ -210,7 +219,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10V3]
name = Creality CR-10 V3
@ -219,7 +228,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10S]
name = Creality CR-10 S
@ -228,7 +237,7 @@ technology = FFF
family = CR
bed_model = cr10_bed.stl
bed_texture = cr10.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10SPRO]
name = Creality CR-10 S Pro
@ -237,7 +246,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10SPROV2]
name = Creality CR-10 S Pro V2
@ -246,7 +255,7 @@ technology = FFF
family = CR
bed_model = cr10v2_bed.stl
bed_texture = cr10.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10S4]
name = Creality CR-10 S4
@ -255,7 +264,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR10S5]
name = Creality CR-10 S5
@ -264,7 +273,7 @@ technology = FFF
family = CR
bed_model = cr10s5_bed.stl
bed_texture = cr10s5.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR20]
name = Creality CR-20
@ -273,7 +282,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR20PRO]
name = Creality CR-20 Pro
@ -282,7 +291,7 @@ technology = FFF
family = CR
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR200B]
name = Creality CR-200B
@ -291,7 +300,7 @@ technology = FFF
family = CR
bed_model = cr200b_bed.stl
bed_texture = cr200b.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:CR8]
name = Creality CR-8
@ -300,7 +309,7 @@ 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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
#[printer_model:CRX]
#name = Creality CR-X
@ -309,7 +318,7 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
#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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
#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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
#[printer_model:CRXPRO]
#name = Creality CR-X Pro
@ -318,7 +327,7 @@ default_materials = Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @
#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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
#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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
[printer_model:SERMOOND1]
name = Creality Sermoon-D1
@ -327,7 +336,7 @@ technology = FFF
family = SERMOON
bed_model = sermoond1_bed.stl
bed_texture = sermoond1.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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY
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 Matt @CREALITY; Devil Design PLA Galaxy @CREALITY; Extrudr PLA NX2 @CREALITY; Real Filament PLA @CREALITY; Velleman PLA @CREALITY; 3DJAKE ecoPLA @CREALITY; 3DJAKE ecoPLA Matt @CREALITY; 3DJAKE ecoPLA Tough @CREALITY; 123-3D Jupiter PLA @CREALITY; Verbatim PLA @CREALITY
# All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface.
@ -842,6 +851,17 @@ filament_cost = 27.44
filament_density = 1.29
filament_colour = #C7F935
[filament:Verbatim PLA @CREALITY]
inherits = *PLA*
filament_vendor = Verbatim
temperature = 205
bed_temperature = 60
first_layer_temperature = 210
first_layer_bed_temperature = 60
filament_cost = 22.99
filament_density = 1.24
filament_colour = #001ca8
# Common printer preset
[printer:*common*]
printer_technology = FFF
@ -970,10 +990,7 @@ renamed_from = "Creality ENDER-3 BLTouch"
printer_model = ENDER3BLTOUCH
[printer:Creality Ender-3 Pro]
inherits = *common*; *pauseprint*
renamed_from = "Creality Ender-3 Pro"
bed_shape = 5x0,215x0,215x220,5x220
max_print_height = 250
inherits = Creality Ender-3; *pauseprint*
printer_model = ENDER3PRO
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_ENDER3PRO\nPRINTER_HAS_BOWDEN
@ -992,6 +1009,13 @@ max_print_height = 270
printer_model = ENDER3S1
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_ENDER3S1
[printer:Creality Ender-3 S1 Pro]
inherits = *common*; *pauseprint*; *spriteextruder*
bed_shape = 5x0,215x0,215x220,5x220
max_print_height = 270
printer_model = ENDER3S1PRO
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_ENDER3S1PRO
[printer:Creality Ender-3 Max]
inherits = *common*; *pauseprint*
retract_length = 6

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -1,4 +1,6 @@
min_slic3r_version = 2.3.1-beta
min_slic3r_version = 2.5.0-alpha0
0.0.4 Improve Proton X profiles, Add Proton XE-750 printer
min_slic3r_version = 2.4.1
0.0.3 Set default filament profile.
0.0.2 Improved start gcode, changed filename format
0.0.1 Initial version

View File

@ -3,7 +3,7 @@
[vendor]
# Vendor name will be shown by the Config Wizard.
name = INAT
config_version = 0.0.3
config_version = 0.0.4
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/INAT/
###
@ -24,9 +24,16 @@ technology = FFF
family = Proton
default_materials = PLA @PROTON_X
[printer_model:PROTON_XE750]
name = INAT Proton XE-750
variants = 0.4
technology = FFF
family = Proton
default_materials = PLA @PROTON_XE750
###
### QUALITY DEFINITIONS
### COMMON QUALITY DEFINITIONS
###
[print:*common*]
@ -35,14 +42,15 @@ layer_height = 0.2
first_layer_height = 0.2
perimeters = 3
spiral_vase = 0
top_solid_layers = 4
top_solid_layers = 5
bottom_solid_layers = 3
top_solid_min_thickness = 0.8
top_solid_min_thickness = 1
bottom_solid_min_thickness = 0.6
extra_perimeters = 1
ensure_vertical_shell_thickness = 1
avoid_crossing_perimeters = 0
thin_walls = 0
thick_bridges = 0
overhangs = 1
seam_position = aligned
external_perimeters_first = 0
@ -76,7 +84,9 @@ support_material_auto = 1
support_material_threshold = 0
support_material_enforce_layers = 0
raft_layers = 0
support_material_contact_distance = 0.2
support_material_style = grid
support_material_contact_distance = 0.25
support_material_bottom_contact_distance = 0.3
support_material_pattern = rectilinear
support_material_with_sheath = 0
support_material_spacing = 5
@ -92,8 +102,8 @@ perimeter_speed = 60
small_perimeter_speed = 75%
external_perimeter_speed = 50%
infill_speed = 80
solid_infill_speed = 100%
top_solid_infill_speed = 30
solid_infill_speed = 80%
top_solid_infill_speed = 20
support_material_speed = 80
support_material_interface_speed = 100%
bridge_speed = 60
@ -126,7 +136,7 @@ infill_overlap = 25%
bridge_flow_ratio = 1
slice_closing_radius = 0.049
resolution = 0
xy_size_compensation = 0
xy_size_compensation = -0.05
elefant_foot_compensation = 0.3
clip_multipart_objects = 0
#output
@ -138,47 +148,50 @@ gcode_label_objects = 0
output_filename_format = {input_filename_base}_{filament_type[0]}.gcode
[print:0.2mm Standard @PROTON_X]
[print:*common 0.2mm Standard @INAT*]
inherits = *common*
[print:0.2mm Strong @PROTON_X]
[print:*common 0.2mm Strong @INAT*]
inherits = *common*
fill_density = 50%
perimeters = 6
[print:0.2mm Advanced Material @PROTON_X]
[print:*common 0.2mm Advanced Material @INAT*]
inherits = *common*
bottom_solid_layers = 5
top_solid_layers = 6
skirts = 0
brim_width = 30
brim_width = 20
infill_speed = 60
support_material_speed = 60
travel_speed = 100
first_layer_speed = 20
elefant_foot_compensation = 0
[print:0.12mm Fine @PROTON_X]
[print:*common 0.12mm Fine @INAT*]
inherits = *common*
layer_height = 0.12
bottom_solid_layers = 7
top_solid_layers = 7
infill_every_layers = 2
perimeter_speed = 50
infill_speed = 50
[print:0.32mm Draft @PROTON_X]
[print:*common 0.32mm Draft @INAT*]
inherits = *common*
layer_height = 0.32
perimeter_speed = 80
external_perimeter_speed = 75%
infill_speed = 100
top_solid_infill_speed = 60
fill_density = 15%
support_material_style = snug
###
### PRINTER DEFINITIONS
### COMMON PRINTER DEFINITIONS
###
[printer:*common*]
[printer:*proton_x_common*]
printer_vendor = INAT s.r.o.
default_filament_profile = "PLA @PROTON_X"
#general
@ -206,14 +219,14 @@ 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_z = 200,200
machine_max_acceleration_e = 8000,8000
machine_max_acceleration_extruding = 1000,1000
machine_max_acceleration_retracting = 1500,1500
machine_max_acceleration_retracting = 8000,8000
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_max_jerk_z = 3,3
machine_max_jerk_e = 10,10
machine_min_extruding_rate = 5
#extruder 1
nozzle_diameter = 0.4
@ -233,24 +246,65 @@ 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
[printer:*proton_xe750_common*]
printer_vendor = INAT s.r.o.
default_filament_profile = "PLA @PROTON_XE750"
#general
printer_technology = FFF
bed_shape = 0x0,600x0,600x500,0x500
max_print_height = 750
z_offset = 0
extruders_count = 2
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 Z10 F1000\nG29\nG0 X0 Y0 Z30 F6000\nM84 E\nM0\nG1 Z15.0 F6000 ;Move the platform down 15mm\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\nG4 S180\nM81 S30\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 = 1500,1500
machine_max_acceleration_y = 1500,1500
machine_max_acceleration_z = 500,500
machine_max_acceleration_e = 20000,20000
machine_max_acceleration_extruding = 2000,2000
machine_max_acceleration_retracting = 8000,8000
machine_max_jerk_x = 12,12
machine_max_jerk_y = 12,12
machine_max_jerk_z = 3,3
machine_max_jerk_e = 20,20
machine_min_extruding_rate = 5
#extruder 1
nozzle_diameter = 0.4,0.4
min_layer_height = 0.05,0.05
max_layer_height = 0.33,0.33
extruder_offset = 0x0,0x0
retract_length = 1.5,1.5
retract_lift = 0.6,0.6
retract_lift_above = 0,0
retract_lift_below = 0,0
retract_speed = 45,45
deretract_speed = 0,0
retract_restart_extra = 0,0
retract_before_travel = 2,2
retract_layer_change = 0,0
wipe = 1,1
retract_before_wipe = 100%,100%
retract_length_toolchange = 37,37
extruder_colour = #33CC33;#3399FF
###
### MATERIAL DEFINITIONS
### COMMON MATERIAL DEFINITIONS
###
[filament:*common*]
@ -272,7 +326,7 @@ min_print_speed = 10
filament_soluble = 0
[filament:PLA @PROTON_X]
[filament:*common PLA @INAT*]
inherits = *common*
temperature = 210
bed_temperature = 60
@ -281,11 +335,12 @@ first_layer_bed_temperature = 60
filament_type = PLA
filament_cost = 20
filament_density = 1.25
fan_always_on = 1
min_fan_speed = 50
max_fan_speed = 100
[filament:PETG @PROTON_X]
[filament:*common PETG @INAT*]
inherits = *common*
temperature = 240
bed_temperature = 80
@ -294,10 +349,11 @@ first_layer_bed_temperature = 80
filament_type = PETG
filament_cost = 25
filament_density = 1.27
min_fan_speed = 0
fan_always_on = 1
min_fan_speed = 25
max_fan_speed = 50
[filament:ABS @PROTON_X]
[filament:*common ABS @INAT*]
inherits = *common*
temperature = 235
bed_temperature = 100
@ -309,7 +365,7 @@ filament_density = 1.01
cooling = 0
bridge_fan_speed = 0
[filament:ASA @PROTON_X]
[filament:*common ASA @INAT*]
inherits = *common*
temperature = 240
bed_temperature = 110
@ -320,7 +376,7 @@ filament_cost = 22
filament_density = 1.07
cooling = 0
[filament:TPE @PROTON_X]
[filament:*common TPE @INAT*]
inherits = *common*
temperature = 220
bed_temperature = 40
@ -334,7 +390,7 @@ max_fan_speed = 50
filament_retract_length = 0.8
filament_retract_speed = 25
[filament:HIPS @PROTON_X]
[filament:*common HIPS @INAT*]
inherits = *common*
temperature = 245
bed_temperature = 100
@ -347,7 +403,7 @@ min_fan_speed = 0
max_fan_speed = 50
filament_soluble = 1
[filament:Nylon @PROTON_X]
[filament:*common Nylon @INAT*]
inherits = *common*
temperature = 235
bed_temperature = 130
@ -359,19 +415,19 @@ filament_density = 1.01
cooling = 0
bridge_fan_speed = 0
[filament:PC @PROTON_X]
[filament:*common PC @INAT*]
inherits = *common*
temperature = 270
bed_temperature = 130
bed_temperature = 115
first_layer_temperature = 270
first_layer_bed_temperature = 130
first_layer_bed_temperature = 115
filament_type = PC
filament_cost = 65
filament_density = 1.19
cooling = 0
bridge_fan_speed = 0
[filament:CPE @PROTON_X]
[filament:*common CPE @INAT*]
inherits = *common*
temperature = 280
bed_temperature = 90
@ -383,7 +439,7 @@ filament_density = 1.27
cooling = 0
bridge_fan_speed = 0
[filament:PEEK @PROTON_X]
[filament:*common PEEK @INAT*]
inherits = *common*
temperature = 440
bed_temperature = 150
@ -395,7 +451,7 @@ filament_density = 1.3
cooling = 0
bridge_fan_speed = 0
[filament:PEI @PROTON_X]
[filament:*common PEI @INAT*]
inherits = *common*
temperature = 400
bed_temperature = 150
@ -407,7 +463,7 @@ filament_density = 1.27
cooling = 0
bridge_fan_speed = 0
[filament:Polymaker PolyMide CoPA @PROTON_X]
[filament:*common Polymaker PolyMide CoPA @INAT*]
inherits = *common*
filament_vendor = Polymaker
temperature = 265
@ -419,7 +475,7 @@ filament_cost = 93
filament_density = 1.12
cooling = 0
[filament:Polymaker PolyMide PA6-CF @PROTON_X]
[filament:*common Polymaker PolyMide PA6-CF @INAT*]
inherits = *common*
filament_vendor = Polymaker
temperature = 300
@ -431,7 +487,7 @@ filament_cost = 95
filament_density = 1.17
cooling = 0
[filament:Polymaker PolyMide PA6-GF @PROTON_X]
[filament:*common Polymaker PolyMide PA6-GF @INAT*]
inherits = *common*
filament_vendor = Polymaker
temperature = 300
@ -443,20 +499,21 @@ filament_cost = 95
filament_density = 1.2
cooling = 0
[filament:Devil Design PETG @PROTON_X]
[filament:*common Devil Design PETG @INAT*]
inherits = *common*
filament_vendor = Devil Design
temperature = 250
temperature = 245
bed_temperature = 80
first_layer_temperature = 250
first_layer_temperature = 245
first_layer_bed_temperature = 80
filament_type = PETG
filament_cost = 22
filament_density = 1.23
min_fan_speed = 0
fan_always_on = 1
min_fan_speed = 25
max_fan_speed = 50
[filament:Filament PM PETG FRJet @PROTON_X]
[filament:*common Filament PM PETG FRJet @INAT*]
inherits = *common*
filament_vendor = Filament PM
temperature = 250
@ -467,3 +524,207 @@ filament_type = PETG
filament_cost = 45.5
filament_density = 1.27
cooling = 0
######
###### PROTON X PRINTERS
######
[printer:Proton X Rail]
inherits = *proton_x_common*
printer_model = PROTON_X_RAIL
printer_variant = 0.4
default_print_profile = 0.2mm Standard @PROTON_X
gcode_flavor = marlin
machine_max_acceleration_x = 800,800
machine_max_acceleration_y = 800,800
machine_max_jerk_x = 10,10
machine_max_jerk_y = 10,10
[printer:Proton X Rod]
inherits = *proton_x_common*
printer_model = PROTON_X_ROD
printer_variant = 0.4
default_print_profile = 0.2mm Standard @PROTON_X
gcode_flavor = marlin
[print:0.2mm Standard @PROTON_X]
inherits = *common 0.2mm Standard @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[print:0.2mm Strong @PROTON_X]
inherits = *common 0.2mm Strong @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[print:0.2mm Advanced Material @PROTON_X]
inherits = *common 0.2mm Advanced Material @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[print:0.12mm Fine @PROTON_X]
inherits = *common 0.12mm Fine @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[print:0.32mm Draft @PROTON_X]
inherits = *common 0.32mm Draft @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:PLA @PROTON_X]
inherits =*common PLA @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:PETG @PROTON_X]
inherits =*common PETG @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:ABS @PROTON_X]
inherits =*common ABS @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:ASA @PROTON_X]
inherits =*common ASA @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:TPE @PROTON_X]
inherits =*common TPE @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:HIPS @PROTON_X]
inherits =*common HIPS @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Nylon @PROTON_X]
inherits =*common Nylon @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:PC @PROTON_X]
inherits =*common PC @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:CPE @PROTON_X]
inherits =*common CPE @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:PEEK @PROTON_X]
inherits =*common PEEK @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:PEI @PROTON_X]
inherits =*common PEI @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Polymaker PolyMide CoPA @PROTON_X]
inherits =*common Polymaker PolyMide CoPA @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Polymaker PolyMide PA6-CF @PROTON_X]
inherits =*common Polymaker PolyMide PA6-CF @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Polymaker PolyMide PA6-GF @PROTON_X]
inherits =*common Polymaker PolyMide PA6-GF @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Devil Design PETG @PROTON_X]
inherits =*common Devil Design PETG @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
[filament:Filament PM PETG FRJet @PROTON_X]
inherits =*common Filament PM PETG FRJet @INAT*
compatible_printers = "Proton X Rail";"Proton X Rod"
######### #########
######### Proton XE 750 #########
######### #########
[printer:Proton XE-750]
inherits = *proton_xe750_common*
printer_model = PROTON_XE750
printer_variant = 0.4
default_print_profile = 0.2mm Standard @PROTON_XE750
gcode_flavor = marlin
[print:0.2mm Standard @PROTON_XE750]
inherits = *common 0.2mm Standard @INAT*
compatible_printers = "Proton XE-750"
[print:0.2mm Strong @PROTON_XE750]
inherits = *common 0.2mm Strong @INAT*
compatible_printers = "Proton XE-750"
[print:0.2mm Advanced Material @PROTON_XE750]
inherits = *common 0.2mm Advanced Material @INAT*
compatible_printers = "Proton XE-750"
[print:0.12mm Fine @PROTON_XE750]
inherits = *common 0.12mm Fine @INAT*
compatible_printers = "Proton XE-750"
[print:0.32mm Draft @PROTON_XE750]
inherits = *common 0.32mm Draft @INAT*
compatible_printers = "Proton XE-750"
[filament:*start_end_gcode @PROTON_XE750*]
start_filament_gcode = "; Filament start gcode BEGIN\nM104 S[temperature[current_extruder]]\nG4 S20\n; Filament start gcode END\n"
end_filament_gcode = "; Filament end gcode BEGIN\nG0 X-5 Y250 F10000\nM104 S{temperature[current_extruder] - 50}\n; Filament end gcode END\n"
compatible_printers = "Proton XE-750"
[filament:PLA @PROTON_XE750]
inherits =*common PLA @INAT*; *start_end_gcode @PROTON_XE750*
[filament:PETG @PROTON_XE750]
inherits =*common PETG @INAT*; *start_end_gcode @PROTON_XE750*
[filament:ABS @PROTON_XE750]
inherits =*common ABS @INAT*; *start_end_gcode @PROTON_XE750*
[filament:ASA @PROTON_XE750]
inherits =*common ASA @INAT*; *start_end_gcode @PROTON_XE750*
[filament:TPE @PROTON_XE750]
inherits =*common TPE @INAT*; *start_end_gcode @PROTON_XE750*
[filament:HIPS @PROTON_XE750]
inherits =*common HIPS @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Nylon @PROTON_XE750]
inherits =*common Nylon @INAT*; *start_end_gcode @PROTON_XE750*
[filament:PC @PROTON_XE750]
inherits =*common PC @INAT*; *start_end_gcode @PROTON_XE750*
[filament:CPE @PROTON_XE750]
inherits =*common CPE @INAT*; *start_end_gcode @PROTON_XE750*
[filament:PEEK @PROTON_XE750]
inherits =*common PEEK @INAT*; *start_end_gcode @PROTON_XE750*
[filament:PEI @PROTON_XE750]
inherits =*common PEI @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Polymaker PolyMide CoPA @PROTON_XE750]
inherits =*common Polymaker PolyMide CoPA @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Polymaker PolyMide PA6-CF @PROTON_XE750]
inherits =*common Polymaker PolyMide PA6-CF @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Polymaker PolyMide PA6-GF @PROTON_XE750]
inherits =*common Polymaker PolyMide PA6-GF @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Devil Design PETG @PROTON_XE750]
inherits =*common Devil Design PETG @INAT*; *start_end_gcode @PROTON_XE750*
[filament:Filament PM PETG FRJet @PROTON_XE750]
inherits =*common Filament PM PETG FRJet @INAT*; *start_end_gcode @PROTON_XE750*

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,2 @@
min_slic3r_version = 2.5.0-alpha0
1.0.0 Initial Infinity3D bundle

View File

@ -0,0 +1,812 @@
# Infinity3D profiles
[vendor]
# Vendor name will be shown by the Config Wizard.
name = Infinity3D
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the Slic3r configuration to be downgraded.
config_version = 1.0.0
# Where to get the updates from?
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Infinity3D/
# The printer models will be shown by the Configuration Wizard in this order,
[printer_model:DEV-200]
name = Infinity3D DEV-200
variants = 0.4
technology = FFF
bed_model = DEV_200_bed.stl
bed_texture = DEV_200_texture.svg
default_materials = Generic PLA @Infinity3D; Generic PETG @Infinity3D
[printer_model:DEV-350]
name = Infinity3D DEV-350
variants = 0.4
technology = FFF
bed_model = DEV_350_bed.stl
bed_texture = DEV_350_texture.svg
default_materials = Generic PLA @Infinity3D; Generic PETG @Infinity3D
[print:*common*]
avoid_crossing_perimeters = 1
avoid_crossing_perimeters_max_detour = 0
bottom_fill_pattern = monotonic
bottom_solid_layers = 4
bottom_solid_min_thickness = 0
bridge_acceleration = 0
bridge_angle = 0
bridge_flow_ratio = 1
bridge_speed = 60
brim_separation = 0
brim_type = outer_only
brim_width = 0
clip_multipart_objects = 1
complete_objects = 0
default_acceleration = 0
dont_support_bridges = 1
draft_shield = disabled
elefant_foot_compensation = 0.1
ensure_vertical_shell_thickness = 1
external_perimeter_extrusion_width = 0.45
external_perimeter_speed = 80%
external_perimeters_first = 0
extra_perimeters = 0
extruder_clearance_height = 25
extruder_clearance_radius = 75
extrusion_width = 0.45
fill_angle = 45
fill_density = 20%
fill_pattern = gyroid
first_layer_acceleration = 0
first_layer_acceleration_over_raft = 0
first_layer_extrusion_width = 0.45
first_layer_height = 0.2
first_layer_speed = 45
first_layer_speed_over_raft = 45
fuzzy_skin = none
fuzzy_skin_point_dist = 0.8
fuzzy_skin_thickness = 0.3
gap_fill_enabled = 1
gap_fill_speed = 20
gcode_comments = 0
gcode_label_objects = 0
gcode_resolution = 0.0125
gcode_substitutions =
infill_acceleration = 0
infill_anchor = 600%
infill_anchor_max = 50
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 = 60
inherits =
interface_shells = 0
ironing = 0
ironing_flowrate = 15%
ironing_spacing = 0.25
ironing_speed = 30
ironing_type = top
layer_height = 0.2
max_print_speed = 100
max_volumetric_speed = 0
min_skirt_length = 4
mmu_segmented_region_max_width = 0
notes =
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
overhangs = 0
perimeter_acceleration = 0
perimeter_extruder = 1
perimeter_extrusion_width = 0.45
perimeter_speed = 60
perimeters = 2
post_process =
print_settings_id =
raft_contact_distance = 0.1
raft_expansion = 1.5
raft_first_layer_density = 90%
raft_first_layer_expansion = 3
raft_layers = 0
resolution = 0
seam_position = nearest
single_extruder_multi_material_priming = 1
skirt_distance = 5
skirt_height = 1
skirts = 3
slice_closing_radius = 0.049
slicing_mode = regular
small_perimeter_speed = 70%
solid_infill_below_area = 0
solid_infill_every_layers = 0
solid_infill_extruder = 1
solid_infill_extrusion_width= 0.45
solid_infill_speed = 80%
spiral_vase = 0
standby_temperature_delta = -5
support_material = 0
support_material_angle = 0
support_material_auto = 1
support_material_bottom_contact_distance = 0
support_material_bottom_interface_layers = -1
support_material_buildplate_only = 0
support_material_closing_radius = 2
support_material_contact_distance = 0.15
support_material_enforce_layers = 0
support_material_extruder = 0
support_material_extrusion_width = 0.38
support_material_interface_contact_loops = 0
support_material_interface_extruder = 0
support_material_interface_layers = 2
support_material_interface_pattern = rectilinear
support_material_interface_spacing = 0.2
support_material_interface_speed = 100%
support_material_pattern = rectilinear
support_material_spacing = 2
support_material_speed = 60
support_material_style = grid
support_material_synchronize_layers = 0
support_material_threshold = 45
support_material_with_sheath = 0
support_material_xy_spacing = 60%
thick_bridges = 1
thin_walls = 0
threads = 8
top_fill_pattern = monotonic
top_infill_extrusion_width = 0.45
top_solid_infill_speed = 60%
top_solid_layers = 4
top_solid_min_thickness = 0
travel_speed = 70
travel_speed_z = 0
wipe_tower = 0
wipe_tower_bridging = 10
wipe_tower_brim_width = 2
wipe_tower_no_sparse_layers = 0
wipe_tower_rotation_angle = 0
wipe_tower_width = 60
wipe_tower_x = 170
wipe_tower_y = 140
xy_size_compensation = 0
compatible_printers_condition = nozzle_diameter[0]==0.4
[print:0.06mm SUPERFINE @Infinity3D_DEV_200]
inherits = *common*
layer_height = 0.06
bottom_solid_layers = 12
top_solid_layers = 12
top_solid_min_thickness = 0.72
bottom_solid_min_thickness = 0.72
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-200"
[print:0.10mm Fine @Infinity3D_DEV_200]
inherits = *common*
layer_height = 0.10
top_solid_layers = 8
bottom_solid_layers = 8
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-200"
[print:0.20mm GOOD @Infinity3D_DEV_200]
inherits = *common*
layer_height = 0.20
top_solid_layers = 5
bottom_solid_layers = 5
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-200"
[print:0.30mm RAPID @Infinity3D_DEV_200]
inherits = *common*
layer_height = 0.30
top_solid_layers = 3
bottom_solid_layers = 3
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-200"
[print:0.40mm FAST @Infinity3D_DEV_200]
inherits = *common*
layer_height = 0.40
top_solid_layers = 3
bottom_solid_layers = 3
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
support_material_extrusion_width = 0.45
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-200"
[print:0.06mm SUPERFINE @Infinity3D_DEV_350]
inherits = *common*
layer_height = 0.06
bottom_solid_layers = 12
top_solid_layers = 12
top_solid_min_thickness = 0.72
bottom_solid_min_thickness = 0.72
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-350"
[print:0.10mm Fine @Infinity3D_DEV_350]
inherits = *common*
layer_height = 0.10
top_solid_layers = 8
bottom_solid_layers = 8
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-350"
[print:0.20mm GOOD @Infinity3D_DEV_350]
inherits = *common*
layer_height = 0.20
top_solid_layers = 5
bottom_solid_layers = 5
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
first_layer_extrusion_width = 0.45
perimeter_extrusion_width = 0.4
external_perimeter_extrusion_width = 0.4
infill_extrusion_width = 0.4
solid_infill_extrusion_width = 0.4
top_infill_extrusion_width = 0.4
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-350"
[print:0.30mm RAPID @Infinity3D_DEV_350]
inherits = *common*
layer_height = 0.30
top_solid_layers = 3
bottom_solid_layers = 3
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-350"
[print:0.40mm FAST @Infinity3D_DEV_350]
inherits = *common*
layer_height = 0.40
top_solid_layers = 3
bottom_solid_layers = 3
bridge_speed = 45
infill_speed = 60
perimeter_speed = 50
support_material_speed = 50
max_print_speed = 60
skirt_distance = 10
first_layer_speed = 80%
support_material_extrusion_width = 0.45
compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="DEV-350"
[filament:*common*]
bed_temperature = 60
bridge_fan_speed = 100
compatible_printers =
compatible_printers_condition =
compatible_prints =
compatible_prints_condition =
cooling = 1
disable_fan_first_layers = 2
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
extrusion_multiplier = 1
fan_always_on = 1
fan_below_layer_time = 60
filament_colour = #29B2B2
filament_cooling_final_speed = 3.4
filament_cooling_initial_speed = 2.2
filament_cooling_moves = 4
filament_cost = 0
filament_density = 0
filament_deretract_speed = nil
filament_diameter = 1.75
filament_load_time = 0
filament_loading_speed = 28
filament_loading_speed_start = 3
filament_max_volumetric_speed = 0
filament_minimal_purge_on_wipe_tower = 15
filament_notes = ""
filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
filament_retract_before_travel = nil
filament_retract_before_wipe = nil
filament_retract_layer_change = nil
filament_retract_length = nil
filament_retract_lift = nil
filament_retract_lift_above = nil
filament_retract_lift_below = nil
filament_retract_restart_extra = nil
filament_retract_speed = nil
filament_settings_id = ""
filament_soluble = 0
filament_spool_weight = 0
filament_toolchange_delay = 0
filament_type = PLA
filament_unload_time = 0
filament_unloading_speed = 90
filament_unloading_speed_start = 100
filament_wipe = nil
first_layer_bed_temperature = 60
first_layer_temperature = 210
full_fan_speed_layer = 0
inherits =
max_fan_speed = 100
min_fan_speed = 35
min_print_speed = 10
slowdown_below_layer_time = 5
start_filament_gcode = "; Filament gcode\n"
temperature = 210
[filament:*PLA*]
inherits = *common*
bed_temperature = 60
fan_below_layer_time = 100
filament_colour = #DDDDDD
filament_max_volumetric_speed = 15
filament_type = PLA
filament_density = 1.24
filament_cost = 20
first_layer_bed_temperature = 60
first_layer_temperature = 210
fan_always_on = 1
cooling = 1
max_fan_speed = 100
min_fan_speed = 100
bridge_fan_speed = 100
disable_fan_first_layers = 1
temperature = 205
[filament:*PET*]
inherits = *common*
bed_temperature = 70
cooling = 1
disable_fan_first_layers = 3
fan_below_layer_time = 20
filament_colour = #DDDDDD
filament_max_volumetric_speed = 8
filament_type = PETG
filament_density = 1.27
filament_cost = 30
first_layer_bed_temperature = 70
first_layer_temperature = 240
fan_always_on = 1
max_fan_speed = 50
min_fan_speed = 20
bridge_fan_speed = 100
temperature = 240
[filament:*ABS*]
inherits = *common*
bed_temperature = 100
cooling = 0
disable_fan_first_layers = 3
fan_below_layer_time = 20
filament_colour = #DDDDDD
filament_max_volumetric_speed = 11
filament_type = ABS
filament_density = 1.04
filament_cost = 20
first_layer_bed_temperature = 100
first_layer_temperature = 245
fan_always_on = 0
max_fan_speed = 0
min_fan_speed = 0
bridge_fan_speed = 30
top_fan_speed = 0
temperature = 245
[filament:Generic PLA @Infinity3D]
inherits = *PLA*
renamed_from = "Generic PLA @Infinity3D"
filament_vendor = Generic
[filament:Generic PETG @Infinity3D]
inherits = *PET*
renamed_from = "Generic PETG @Infinity3D"
filament_vendor = Generic
[filament:Generic ABS @Infinity3D]
inherits = *ABS*
renamed_from = "Generic ABS @Infinity3D"
first_layer_bed_temperature = 90
bed_temperature = 90
filament_vendor = Generic
[filament:Infinity3D PLA @Infinity3D]
inherits = *PLA*
renamed_from = "Infinity3D PLA @Infinity3D"
filament_vendor = Infinity3D
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_colour = #42BDD8
[filament:Infinity3D PETG @Infinity3D]
inherits = *PET*
renamed_from = "Infinity3D PETG @Infinity3D"
filament_vendor = Infinity3D
temperature = 240
bed_temperature = 70
first_layer_temperature = 240
first_layer_bed_temperature = 70
max_fan_speed = 40
min_fan_speed = 20
filament_colour = #42BDD8
[filament:Infinity3D ABS @Infinity3D]
inherits = *ABS*
renamed_from = "Infinity3D ABS @Infinity3D"
filament_vendor = Infinity3D
temperature = 240
bed_temperature = 90
first_layer_temperature = 240
first_layer_bed_temperature = 90
filament_colour = #42BDD8
[filament:Prusament PLA @Infinity3D]
inherits = *PLA*
renamed_from = "Prusament PLA @Infinity3D"
filament_vendor = Prusa Polymers
temperature = 210
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.24
filament_colour = #F94D0C
[filament:Prusament PETG @Infinity3D]
inherits = *PET*
renamed_from = "Prusament PETG @Infinity3D"
filament_vendor = Prusa Polymers
temperature = 245
bed_temperature = 70
first_layer_temperature = 245
first_layer_bed_temperature = 70
filament_cost = 24.99
filament_density = 1.27
filament_colour = #F94D0C
[filament:AzureFilm PLA @Infinity3D]
inherits = *PLA*
filament_vendor = AzureFilm
temperature = 210
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 19.97
filament_density = 1.24
filament_colour = #006AA6
[filament:Devil Design PLA @Infinity3D]
inherits = *PLA*
filament_vendor = Devil Design
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 19.00
filament_density = 1.24
filament_colour = #FF0000
filament_spool_weight = 256
[filament:Devil Design PLA Matt @Infinity3D]
inherits = *PLA*
filament_vendor = Devil Design
temperature = 205
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 20.00
filament_density = 1.38
filament_colour = #FF0000
filament_spool_weight = 256
[filament:Devil Design PLA Galaxy @Infinity3D]
inherits = *PLA*
renamed_from = "Devil Design PLA (Galaxy) @Infinity3D"
filament_vendor = Devil Design
temperature = 225
bed_temperature = 65
first_layer_temperature = 225
first_layer_bed_temperature = 65
filament_cost = 19.00
filament_density = 1.24
filament_colour = #FF0000
filament_spool_weight = 256
[filament:Extrudr PLA NX2 @Infinity3D]
inherits = *PLA*
filament_vendor = Extrudr
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 23.63
filament_density = 1.3
filament_colour = #3C4547
filament_spool_weight = 256
[filament:Extrudr GreenTEC Pro @Infinity3D]
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 @Infinity3D]
inherits = *PLA*
filament_vendor = Real Filament
temperature = 195
bed_temperature = 60
first_layer_temperature = 200
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.24
filament_colour = #007ABF
[filament:Velleman PLA @Infinity3D]
inherits = *PLA*
filament_vendor = Velleman
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 27.99
filament_density = 1.24
filament_colour = #7EA60D
[filament:3DJAKE ecoPLA @Infinity3D]
inherits = *PLA*
filament_vendor = 3DJAKE
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 21.99
filament_density = 1.24
filament_colour = #125467
filament_spool_weight = 238
[filament:3DJAKE ecoPLA Matt @Infinity3D]
inherits = *PLA*
filament_vendor = 3DJAKE
temperature = 195
bed_temperature = 60
first_layer_temperature = 195
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.38
filament_colour = #125467
filament_spool_weight = 238
[filament:3DJAKE ecoPLA Tough @Infinity3D]
inherits = *PLA*
filament_vendor = 3DJAKE
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 29.99
filament_density = 1.21
filament_colour = #125467
[filament:FormFutura Tough PLA @Infinity3D]
inherits = *PLA*
filament_vendor = FormFutura
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 46.65
filament_density = 1.21
filament_colour = #ed000e
[filament:123-3D Jupiter PLA @Infinity3D]
inherits = *PLA*
filament_vendor = 123-3D
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 19.50
filament_density = 1.24
filament_colour = #FFE200
[filament:Das Filament PLA @Infinity3D]
inherits = *PLA*
filament_vendor = Das Filament
temperature = 210
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 20.56
filament_density = 1.24
filament_colour = #C7F935
[filament:Das Filament PETG @Infinity3D]
inherits = *PET*
filament_vendor = Das Filament
temperature = 240
bed_temperature = 70
first_layer_temperature = 240
first_layer_bed_temperature = 70
filament_cost = 27.44
filament_density = 1.29
filament_colour = #C7F935
[filament:Verbatim PLA @Infinity3D]
inherits = *PLA*
filament_vendor = Verbatim
temperature = 205
bed_temperature = 60
first_layer_temperature = 210
first_layer_bed_temperature = 60
filament_cost = 22.99
filament_density = 1.24
filament_colour = #001ca8
# Common printer preset
[printer:*common*]
bed_shape = 0x0,350x0,350x350,0x350
color_change_gcode = M600
cooling_tube_length = 5
cooling_tube_retraction = 91.5
default_filament_profile = ""
default_print_profile =
end_gcode = ;End GCode begin\nM140 S0 ;Heated bed heater off\nM104 S0 ;Extruder heater off\nG90 ;absolute positioning\nG92 E0 ;Retract the filament\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z350 E-1 F3000 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y350 F3000 ;so the head is out of the way and Plate is moved forward\nM84 ;stepper off\nM107 ; fan off\nM82 ; absolute extrusion\n;End GCode end
extra_loading_move = -2
extruder_colour = ""
extruder_offset = 0x0
gcode_flavor = marlin
high_current_on_filament_swap = 0
machine_limits_usage = time_estimate_only
machine_max_acceleration_e = 10000
machine_max_acceleration_extruding = 1000
machine_max_acceleration_retracting = 1000
machine_max_acceleration_travel = 1500
machine_max_acceleration_x = 3000
machine_max_acceleration_y = 3000
machine_max_acceleration_z = 100
machine_max_feedrate_e = 25
machine_max_feedrate_x = 150
machine_max_feedrate_y = 150
machine_max_feedrate_z = 50
machine_max_jerk_e = 2.5
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.2
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
max_layer_height = 0.4
max_print_height = 350
min_layer_height = 0.08
nozzle_diameter = 0.4
parking_pos_retraction = 92
pause_print_gcode =
printer_technology = FFF
remaining_times = 0
retract_before_travel = 2
retract_before_wipe = 0%
retract_layer_change = 1
retract_length = 2
retract_length_toolchange = 10
retract_lift = 0
retract_lift_above = 0
retract_lift_below = 328
retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 60
deretract_speed = 40
silent_mode = 0
single_extruder_multi_material = 0
start_gcode = Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start Warming Bed\nM104 S[first_layer_temperature] ;Preheat\nG28 ;home\nG29 ;Auto Bed-level\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000 ;Move to corner\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0 ;Zero set extruder position\nG1 E3 F200 ;Feed filament to clear nozzle\nG92 E0 ;Zero set extruder position
thumbnails = 16x16,220x124
use_firmware_retraction = 0
use_relative_e_distances = 0
use_volumetric_e = 0
variable_layer_height = 1
wipe = 0
z_offset = 0
[printer:Infinity3D DEV-350]
inherits = *common*
printer_model = DEV-350
printer_variant = 0.4
default_filament_profile = Generic PLA @Infinity3D
default_print_profile = 0.20mm GOOD @Infinity3D_DEV_350
[printer:Infinity3D DEV-200]
inherits = *common*
printer_model = DEV-200
printer_variant = 0.4
bed_shape = 0x0,200x0,200x200,0x200
thumbnails =
variable_layer_height = 0
retract_lift_below = 0
max_print_height = 235
start_gcode = Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start Warming Bed\nM104 S[first_layer_temperature] ;Preheat\nG28 ;home\nG29 ;Auto Bed-level\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000 ;Move to corner\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0 ;Zero set extruder position\nG1 E3 F200 ;Feed filament to clear nozzle\nG92 E0 ;Zero set extruder position
end_gcode = ;End GCode begin\nM140 S0 ;Heated bed heater off\nM104 S0 ;Extruder heater off\nG90 ;absolute positioning\nG92 E0 ;Retract the filament\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z240 E-1 F3000 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y200 F3000 ;so the head is out of the way and Plate is moved forward\nM84 ;stepper off\nM107 ; fan off\nM82 ; absolute extrusion\n;End GCode end
default_filament_profile = Generic PLA @Infinity3D
default_print_profile = 0.20mm GOOD @Infinity3D_DEV_200

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

View File

@ -0,0 +1,487 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="2717.000000pt" height="2953.000000pt" viewBox="0 0 2717.000000 2953.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,2953.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1160 28950 l0 -580 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580
-20 l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -570 0 -570 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-509 0 -580 -2 -580 -15 0 -13 71 -15 580 -15
l580 0 0 -575 0 -575 -580 0 c-573 0 -580 0 -580 -20 0 -20 7 -20 580 -20
l580 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20 580 l0 580 575 0 575 0 0
-580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0
-509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -509 2
-580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -509 2 -580 15
-580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -573 0 -580 20 -580 20
0 20 7 20 580 l0 580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20
580 l0 580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20 580 l0
580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20 580 l0 580 575 0
575 0 0 -580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0
-580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0
-509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -509 2
-580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -573 0 -580 20
-580 20 0 20 7 20 580 l0 580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0
20 7 20 580 l0 580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20
580 l0 580 570 0 570 0 0 -580 c0 -573 0 -580 20 -580 20 0 20 7 20 580 l0
580 575 0 575 0 0 -580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575
0 575 0 0 -580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0
0 -580 c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580
c0 -509 2 -580 15 -580 13 0 15 71 15 580 l0 580 575 0 575 0 0 -580 c0 -573
0 -580 20 -580 20 0 20 7 20 580 l0 580 580 0 c573 0 580 0 580 20 0 20 -7 20
-580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580 20 0 20 -7 20 -580 20
l-580 0 0 575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0
575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575
580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0
c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0 c573 0
580 0 580 20 0 20 -7 20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580
20 0 20 -7 20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580 20 0 20 -7
20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580 20 0 20 -7 20 -580 20
l-580 0 0 575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0
575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575
580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0
c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0 c573 0
580 0 580 20 0 20 -7 20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580
20 0 20 -7 20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580 20 0 20 -7
20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580 20 0 20 -7 20 -580 20
l-580 0 0 575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0
575 0 575 580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575
580 0 c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0
c509 0 580 2 580 15 0 13 -71 15 -580 15 l-580 0 0 575 0 575 580 0 c573 0
580 0 580 20 0 20 -7 20 -580 20 l-580 0 0 570 0 570 580 0 c573 0 580 0 580
20 0 20 -7 20 -580 20 l-580 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20
-580 l0 -580 -575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15
-580 l0 -580 -575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15
-580 l0 -580 -575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15
-580 l0 -580 -575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15
-580 l0 -580 -575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15
-580 l0 -580 -575 0 -575 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580
l0 -580 -570 0 -570 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0
-580 -570 0 -570 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0 -580
-575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580
-575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580
-575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580
-575 0 -575 0 0 580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580
-575 0 -575 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0 -580 -570
0 -570 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0 -580 -570 0
-570 0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0 -580 -570 0 -570
0 0 580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580 l0 -580 -575 0 -575 0 0
580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580 -575 0 -575 0 0
580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580 -575 0 -575 0 0
580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580 -575 0 -575 0 0
580 c0 509 -2 580 -15 580 -13 0 -15 -71 -15 -580 l0 -580 -575 0 -575 0 0
580 c0 573 0 580 -20 580 -20 0 -20 -7 -20 -580z m1190 -1190 l0 -570 -575 0
-575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570
0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0
575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z
m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0
-570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0
-570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570
0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0
575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z
m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0
-570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0
-575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570
0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0
570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z
m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0
-570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0
-575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570
0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0
575 0 0 -570z m-23620 -1185 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1185 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570
575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570
0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570
0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m-23620 -1180 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0
0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180
0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570
570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0
-570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1190 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m-23620 -1180 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570
575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570
0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570
0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m-23620 -1185 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1185 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570
575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570
0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570
0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m-23620 -1180 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0
0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180
0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570
570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0
-570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1190 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m-23620 -1180 l0 -570
-575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0
0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570
575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -570 0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570
0 -570 0 0 570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0
570 0 570 570 0 570 0 0 -570z m1180 0 l0 -570 -570 0 -570 0 0 570 0 570 570
0 570 0 0 -570z m1190 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0
-570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0
l0 -570 -575 0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575
0 -575 0 0 570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0
570 0 570 575 0 575 0 0 -570z m1180 0 l0 -570 -575 0 -575 0 0 570 0 570 575
0 575 0 0 -570z m-23620 -1185 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m-23620 -1180 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575
575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570
0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0
575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570
0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0
-575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575
0 575 0 0 -575z m-23620 -1180 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0
0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180
0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575
-575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0
0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575
570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0
-575z m1180 0 l0 -575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1190 0
l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575
0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0
575 0 575 575 0 575 0 0 -575z m11810 -590 l0 -1165 -4705 0 c-4176 0 -4705 2
-4705 15 0 8 -9 15 -20 15 -11 0 -20 -7 -20 -15 0 -13 -71 -15 -575 -15 -504
0 -575 2 -575 15 0 8 -7 15 -15 15 -8 0 -15 -7 -15 -15 0 -13 -71 -15 -575
-15 l-575 0 0 575 c0 377 3 575 10 575 6 0 10 7 10 15 0 8 -4 15 -10 15 -7 0
-10 198 -10 575 l0 575 5890 0 5890 0 0 -1165z m-23620 -590 l0 -575 -575 0
-575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575
0 575 575 0 575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0
575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z
m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z m1180 0 l0
-575 -570 0 -570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0
-570 0 0 575 0 575 570 0 570 0 0 -575z m1180 0 l0 -575 -570 0 -570 0 0 575
0 575 570 0 570 0 0 -575z m1190 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0
575 0 0 -575z m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z
m1180 0 l0 -575 -575 0 -575 0 0 575 0 575 575 0 575 0 0 -575z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

View File

@ -0,0 +1,589 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="3780.000000pt" height="4134.000000pt" viewBox="0 0 3780.000000 4134.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,4134.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1618 40273 l-3 -808 -807 -3 c-799 -2 -808 -2 -808 -22 0 -20 9 -20
808 -22 l807 -3 0 -795 0 -795 -808 -3 -807 -2 0 -25 0 -25 810 0 810 0 -2
-797 -3 -798 -805 -2 c-800 -2 -805 -3 -808 -23 -3 -20 -1 -20 807 -20 l811 0
-2 -797 -3 -798 -807 -3 c-800 -2 -808 -2 -808 -22 0 -20 7 -20 810 -20 l810
0 0 -800 0 -800 -810 0 -810 0 0 -25 0 -25 810 0 810 0 0 -795 0 -795 -810 0
-810 0 0 -25 0 -25 810 0 810 0 -2 -797 -3 -798 -808 -3 c-798 -2 -807 -2
-807 -22 0 -20 9 -20 807 -22 l808 -3 0 -795 0 -795 -808 -3 c-805 -2 -808 -2
-805 -22 3 -20 9 -21 808 -23 l805 -2 3 -797 2 -798 -810 0 -810 0 0 -25 0
-25 810 0 810 0 -2 -797 -3 -798 -807 -3 c-799 -2 -808 -2 -808 -22 0 -20 9
-20 808 -22 l807 -3 3 -797 2 -798 -810 0 -810 0 0 -25 0 -25 810 0 810 0 0
-795 0 -795 -810 0 -810 0 0 -25 0 -25 810 0 810 0 0 -800 0 -800 -810 0
c-803 0 -810 0 -810 -20 0 -20 8 -20 808 -22 l807 -3 3 -797 2 -798 -810 0
c-803 0 -810 0 -810 -20 0 -20 8 -20 807 -22 l808 -3 3 -797 2 -798 -810 0
-810 0 0 -25 0 -25 808 -2 807 -3 0 -795 0 -795 -808 -3 c-798 -2 -807 -2
-807 -22 0 -20 9 -20 808 -22 l807 -3 3 -797 2 -798 -810 0 -810 0 0 -25 0
-25 810 0 810 0 0 -795 0 -795 -810 0 -810 0 0 -25 0 -25 810 0 810 0 0 -800
0 -800 -810 0 c-803 0 -810 0 -810 -20 0 -20 8 -20 808 -22 l807 -3 3 -797 2
-798 -810 0 -810 0 0 -25 0 -25 810 0 810 0 -2 -797 -3 -798 -808 -3 c-799 -2
-807 -2 -807 -22 0 -20 7 -20 810 -20 l810 0 -2 -797 -3 -798 -807 -3 c-799
-2 -808 -2 -808 -22 0 -20 9 -20 807 -22 l808 -3 0 -800 0 -800 -807 -3 c-709
-2 -808 -4 -808 -17 0 -13 98 -15 810 -15 l810 0 0 -800 0 -800 -810 0 -810 0
0 -25 0 -25 810 0 810 0 0 -810 0 -810 25 0 25 0 0 808 0 807 795 0 795 0 0
-807 0 -808 25 0 25 0 0 810 0 810 798 -2 797 -3 3 -807 c2 -800 2 -808 22
-808 20 0 20 7 20 810 l0 810 800 0 800 0 0 -810 0 -810 25 0 25 0 0 808 0
807 795 3 795 2 0 -810 0 -810 25 0 25 0 0 810 0 810 798 -2 797 -3 3 -807 c2
-799 2 -808 22 -808 20 0 20 9 22 808 l3 807 798 3 797 2 0 -811 c0 -808 0
-810 20 -807 20 3 21 8 23 808 l2 805 798 3 797 2 0 -810 0 -810 25 0 25 0 0
810 0 810 798 -2 797 -3 3 -807 c2 -799 2 -808 22 -808 20 0 20 9 22 807 l3
808 798 3 797 2 0 -810 0 -810 25 0 25 0 0 810 0 810 795 0 795 0 0 -810 0
-810 25 0 25 0 0 810 0 810 800 0 800 0 0 -810 c0 -803 0 -810 20 -810 20 0
20 8 22 808 l3 807 798 3 797 2 0 -810 c0 -803 0 -810 20 -810 20 0 20 8 22
807 l3 808 798 3 797 2 0 -810 0 -810 25 0 25 0 0 810 0 810 798 -2 797 -3 2
-805 c2 -799 3 -805 23 -808 20 -3 20 0 22 805 l3 808 798 3 797 2 0 -810 0
-810 25 0 25 0 0 810 0 810 795 0 795 0 0 -810 0 -810 25 0 25 0 0 810 0 810
800 0 800 0 0 -810 c0 -803 0 -810 20 -810 20 0 20 8 22 808 l3 807 798 3 797
2 0 -810 0 -810 25 0 25 0 0 810 0 810 798 -2 797 -3 3 -807 c2 -800 2 -808
22 -808 20 0 20 7 20 810 l0 810 798 -2 797 -3 3 -807 c2 -800 2 -808 22 -808
20 0 20 7 20 810 l0 810 800 0 800 0 0 -810 0 -810 25 0 25 0 0 810 0 810 811
0 810 0 -3 22 -3 23 -807 3 -808 2 0 795 0 795 808 2 807 3 3 23 3 22 -810 0
-811 0 0 800 0 800 810 0 c803 0 810 0 810 20 0 20 -7 20 -810 20 l-810 0 0
800 0 800 811 0 c808 0 810 0 807 20 -3 20 -8 21 -808 23 l-805 2 -3 797 -2
798 807 2 808 3 3 23 3 22 -810 0 -811 0 2 798 3 797 808 3 c799 2 807 2 807
22 0 20 -7 20 -810 20 l-810 0 0 800 0 800 811 0 810 0 -3 23 -3 22 -807 3
-808 2 0 795 0 795 811 0 810 0 -3 23 -3 22 -807 3 -808 2 0 800 0 800 810 0
c803 0 810 0 810 20 0 20 -8 20 -807 22 l-808 3 -3 798 -2 797 811 0 810 0 -3
23 -3 22 -808 3 -807 2 2 798 3 797 805 2 c800 2 805 3 808 23 3 20 1 20 -807
20 l-811 0 0 800 0 800 810 0 c803 0 810 0 810 20 0 20 -7 20 -810 20 l-810 0
0 800 0 800 811 0 810 0 -3 23 -3 22 -807 3 -808 2 0 795 0 795 808 2 c799 3
807 3 807 23 0 20 -8 20 -807 23 l-808 2 0 800 0 800 810 0 c803 0 810 0 810
20 0 20 -8 20 -807 22 l-808 3 -3 798 -2 797 811 0 810 0 -3 23 -3 22 -805 2
-805 3 0 797 0 798 805 2 c800 2 805 3 808 23 3 20 1 20 -807 20 l-811 0 2
798 3 797 808 3 c799 2 807 2 807 22 0 20 -7 20 -810 20 l-810 0 0 800 0 800
808 2 807 3 3 23 3 22 -810 0 -811 0 2 795 3 795 805 3 805 2 3 23 3 22 -810
0 -811 0 0 800 0 800 810 0 c803 0 810 0 810 20 0 20 -7 20 -810 20 l-810 0 0
800 0 800 811 0 c808 0 810 0 807 20 -3 20 -8 21 -808 23 l-805 2 0 798 0 797
805 3 805 2 3 23 3 22 -810 0 -811 0 2 798 3 797 808 3 c799 2 807 2 807 22 0
20 -7 20 -810 20 l-810 0 0 810 0 810 -25 0 -25 0 0 -810 0 -810 -797 2 -798
3 -3 808 c-2 798 -2 807 -22 807 -20 0 -20 -9 -22 -807 l-3 -808 -797 -3 -798
-2 0 810 c0 803 0 810 -20 810 -20 0 -20 -8 -22 -807 l-3 -808 -797 -3 -798
-2 0 810 0 810 -25 0 -25 0 0 -810 0 -810 -797 2 -798 3 -3 808 c-2 798 -2
807 -22 807 -20 0 -20 -9 -22 -807 l-3 -808 -797 -3 -798 -2 0 810 c0 803 0
810 -20 810 -20 0 -20 -8 -22 -807 l-3 -808 -800 0 -800 0 -3 808 c-2 798 -2
807 -22 807 -20 0 -20 -9 -22 -807 l-3 -808 -795 0 -795 0 -3 808 c-2 798 -2
807 -22 807 -20 0 -20 -9 -22 -807 l-3 -808 -795 0 -795 0 -3 808 -2 807 -25
0 -25 0 0 -810 0 -810 -797 2 -798 3 -3 808 c-2 799 -2 807 -22 807 -20 0 -20
-7 -20 -810 l0 -810 -797 2 -798 3 -3 808 c-2 798 -2 807 -22 807 -20 0 -20
-9 -22 -807 l-3 -808 -797 -3 -798 -2 0 810 0 810 -25 0 -25 0 0 -810 0 -810
-795 0 -795 0 0 810 0 810 -25 0 -25 0 0 -810 0 -810 -797 2 -798 3 -3 808
c-2 798 -2 807 -22 807 -20 0 -20 -9 -22 -807 l-3 -808 -795 0 -795 0 -3 808
-2 807 -25 0 -25 0 0 -810 0 -810 -797 2 -798 3 0 808 0 807 -22 0 -23 0 -2
-807 -3 -808 -795 0 -795 0 -3 808 c-2 798 -2 807 -22 807 -20 0 -20 -9 -22
-807 l-3 -808 -797 -3 -798 -2 0 810 0 810 -25 0 -25 0 0 -810 0 -810 -795 0
c-629 0 -795 3 -795 13 0 6 0 371 0 810 l0 797 -25 0 -25 0 0 -810 0 -810
-800 0 -800 0 0 810 c0 803 0 810 -20 810 -20 0 -20 -8 -22 -807 l-3 -808
-797 -3 -798 -2 0 810 0 810 -25 0 -25 0 0 -797 c0 -439 0 -804 0 -810 0 -10
-166 -13 -795 -13 -629 0 -795 3 -795 13 0 6 0 371 0 810 l0 797 -25 0 -25 0
-2 -807z m1642 -1648 c0 -434 0 -793 0 -797 0 -5 -358 -8 -795 -8 -437 0 -795
3 -795 8 0 22 0 1578 0 1585 0 4 358 6 795 5 l795 -3 0 -790z m1645 -5 l0
-795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800
0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1640 0 l0
-800 -795 0 c-523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0 3
358 5 795 5 l795 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798
-2 797 -3 0 -795z m1640 0 l0 -795 -795 0 -795 0 -3 785 c-1 432 0 791 3 798
3 10 168 12 797 10 l793 -3 0 -795z m1645 0 l0 -800 -797 2 -798 3 -3 785 c-1
432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1645 0 l0 -795 -797 -3
-798 -2 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 0 -795z m1645 0 l0
-800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0
-800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1648
-2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1640 -1 l2 -797
-797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 10 168 12 797 10 l793 -3 3 -798z
m1642 3 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12
l795 0 0 -800z m1648 -3 l2 -797 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3
10 168 12 797 10 l793 -3 3 -798z m1640 0 l2 -797 -797 2 -798 3 -3 785 c-1
432 0 791 3 798 3 10 168 12 797 10 l793 -3 3 -798z m1647 3 l0 -795 -800 0
-800 0 -3 785 c-1 432 0 791 3 798 3 10 169 12 802 10 l798 -3 0 -795z m1643
-2 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3
-797z m1642 2 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12
800 12 l795 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2
797 -3 0 -795z m1643 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3
-797z m1640 -1 l2 -797 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 10 168 12
797 10 l793 -3 3 -798z m-31218 -1642 l0 -795 -22 -5 c-13 -3 -372 -4 -798 -3
l-775 3 -3 790 c-1 435 0 795 2 800 2 7 276 9 800 7 l796 -2 0 -795z m1635 -2
l0 -798 -795 0 -795 0 -3 790 c-1 435 0 795 2 800 2 7 275 9 797 8 l794 -3 0
-797z m1645 -4 l0 -799 -789 0 c-473 0 -792 4 -796 9 -3 5 -5 364 -5 798 l0
788 787 5 c434 3 791 4 796 2 4 -2 7 -363 7 -803z m1648 0 l-3 -794 -795 0
-795 0 -3 797 -2 798 792 2 c436 2 796 0 801 -3 4 -3 6 -363 5 -800z m1637 4
l0 -798 -775 -3 c-426 -1 -785 0 -797 3 l-23 5 0 794 c0 521 3 795 10 798 5 2
364 2 797 1 l788 -3 0 -797z m1640 0 l0 -798 -784 -3 c-571 -1 -787 1 -797 9
-12 10 -14 147 -14 799 0 517 3 789 10 792 5 2 364 2 797 1 l788 -3 0 -797z
m1648 797 c4 0 7 -358 7 -795 l0 -795 -22 -5 c-13 -3 -372 -4 -798 -3 l-775 3
-3 790 c-1 435 0 795 2 800 3 8 901 11 1589 5z m1645 -798 l-3 -797 -795 0
-795 0 -3 790 c-1 435 0 795 2 800 2 7 276 9 800 7 l796 -2 -2 -798z m1640 0
l-3 -797 -792 -3 -793 -2 0 802 0 803 795 -3 795 -2 -2 -798z m1647 1 l0 -798
-797 -3 -798 -2 0 798 c0 439 2 801 4 803 2 2 361 3 798 2 l793 -3 0 -797z
m1643 -4 l-3 -794 -775 -3 c-426 -1 -785 0 -797 3 l-23 5 0 795 0 795 793 2
c435 2 795 0 800 -3 4 -3 6 -363 5 -800z m1640 0 l-3 -794 -775 -3 c-426 -1
-785 0 -797 3 l-23 5 0 795 0 795 793 2 c435 2 795 0 800 -3 4 -3 6 -363 5
-800z m3290 0 l-3 -794 -795 0 -795 0 -3 797 -2 798 792 2 c436 2 796 0 801
-3 4 -3 6 -363 5 -800z m1652 7 c0 -715 -2 -794 -16 -800 -20 -8 -1558 -8
-1578 0 -14 6 -16 85 -16 799 0 520 3 794 10 797 5 2 368 2 805 0 l795 -2 0
-794z m1640 -1 l0 -795 -22 -5 c-13 -3 -372 -4 -798 -3 l-775 3 -3 790 c-1
435 0 795 2 800 2 7 276 9 800 7 l796 -2 0 -795z m1640 -3 l0 -802 -797 2
-798 3 -3 790 c-1 435 0 795 2 800 2 7 278 10 800 10 l796 0 0 -803z m1648 21
c1 -428 0 -788 -3 -800 l-5 -23 -795 0 -795 0 0 803 0 802 797 -2 798 -3 3
-777z m1637 -20 l0 -798 -797 -3 -798 -2 0 802 0 803 797 -2 798 -3 0 -797z
m1643 -4 l-3 -794 -775 -3 c-426 -1 -785 0 -797 3 l-23 5 0 795 0 795 793 2
c435 2 795 0 800 -3 4 -3 6 -363 5 -800z m-32865 10 c-2 -435 -5 -795 -9 -800
-6 -11 -1584 -13 -1584 -1 0 4 -1 364 -3 800 l-2 792 800 0 800 0 -2 -791z
m21365 -6 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m-21368
-1635 c0 -434 0 -792 0 -798 0 -7 -272 -10 -795 -10 -523 0 -795 3 -795 10 0
6 0 363 0 795 0 432 0 787 0 790 0 3 358 4 795 3 l795 -3 0 -787z m1648 -5
l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0 -800
-797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -795 0
c-523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0 3 358 5 795 5
l795 0 0 -800z m1648 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2
-797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z
m1643 793 c2 -2 3 -362 1 -800 l-2 -796 -794 0 c-715 0 -794 2 -800 16 -8 21
-8 1569 1 1577 7 7 1587 10 1594 3z m1647 -793 l-3 -798 -795 0 -795 0 -3 798
-2 797 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797
800 0 800 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0
-800z m1648 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z
m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0
-800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1648 3 l-3 -798 -795
0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0
-3 798 -2 797 800 0 800 0 -2 -797z m1650 0 l-3 -798 -800 0 -800 0 -3 798 -2
797 805 0 805 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0
800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0
-800z m1648 20 c1 -426 0 -785 -3 -797 l-5 -23 -795 0 -795 0 0 800 0 800 798
-2 797 -3 3 -775z m1640 -17 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800
0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z
m-32870 -1640 l0 -795 -795 0 -795 0 0 793 c0 435 0 794 0 797 0 3 358 4 795
3 l795 -3 0 -795z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3
3 -797z m1642 2 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640
0 l0 -800 -795 2 -795 3 0 793 c0 435 0 794 0 797 0 3 358 5 795 5 l795 0 0
-800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z
m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793
0 0 -800z m1641 796 c2 -2 3 -362 1 -800 l-2 -796 -798 2 -797 3 -3 785 c-1
432 0 791 3 798 3 9 172 12 798 12 437 0 796 -2 798 -4z m1647 -798 l2 -798
-800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800
0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800
795 0 795 0 0 -800z m1650 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m1640 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0
l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0
-800z m1650 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0
l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1650 0 l0 -800 -805
0 -805 0 0 793 c0 437 3 797 7 800 3 4 366 7 805 7 l798 0 0 -800z m1640 0 l0
-800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -800 0
-800 0 0 800 0 800 800 0 800 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0
800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 800 0 800
800 0 800 0 0 -800z m1640 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m-31220 -1645 l0 -795 -800 0 -800 0 0 793 c0 437 2 796 4 798 2 2 362
3 800 1 l796 -2 0 -795z m1638 0 l2 -795 -800 0 -800 0 0 793 c0 437 2 796 4
798 2 2 361 3 798 2 l793 -3 3 -795z m3292 -1 l0 -794 -800 0 -800 0 0 795 0
795 793 2 c435 2 795 2 800 0 4 -2 7 -361 7 -798z m1640 0 l0 -794 -800 0
-800 0 0 795 0 795 793 2 c435 2 795 2 800 0 4 -2 7 -361 7 -798z m1638 1 l2
-795 -800 0 -800 0 0 788 c0 484 4 792 9 798 6 5 310 8 798 7 l788 -3 3 -795z
m1645 795 c4 0 7 -358 7 -795 l0 -795 -800 0 -800 0 0 793 c0 437 2 796 4 798
3 3 1205 2 1589 -1z m1647 -795 l0 -795 -800 0 -800 0 0 793 c0 437 2 796 4
798 2 2 362 3 800 1 l796 -2 0 -795z m1640 0 l0 -795 -795 0 -795 0 0 798 0
797 795 -3 795 -2 0 -795z m1650 -1 l0 -794 -800 0 -800 0 0 795 0 795 793 2
c435 2 795 2 800 0 4 -2 7 -361 7 -798z m1640 0 l0 -794 -800 0 -800 0 0 795
0 795 793 2 c435 2 795 2 800 0 4 -2 7 -361 7 -798z m4930 0 l0 -794 -800 0
-800 0 0 795 0 795 793 2 c435 2 795 2 800 0 4 -2 7 -361 7 -798z m3290 1 l0
-795 -800 0 -800 0 0 793 c0 437 2 796 4 798 2 2 362 3 800 1 l796 -2 0 -795z
m1640 3 l0 -798 -800 0 -800 0 0 793 c0 437 2 796 4 798 2 2 362 4 800 4 l796
0 0 -797z m1642 787 c4 -5 8 -364 8 -797 l0 -788 -800 0 -800 0 0 798 0 797
792 0 c517 0 796 -3 800 -10z m1646 -790 l2 -795 -800 0 -800 0 0 798 0 797
797 -2 798 -3 3 -795z m1642 -1 l0 -794 -800 0 -800 0 0 795 0 795 793 2 c435
2 795 2 800 0 4 -2 7 -361 7 -798z m-32867 -2 l2 -792 -800 0 -800 0 2 792 c2
436 3 794 3 796 0 1 358 1 795 0 l795 -3 3 -793z m4927 3 l0 -795 -801 0
c-726 0 -801 1 -795 16 3 9 6 366 6 795 l0 779 795 0 795 0 0 -795z m14790 0
l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1650 0 l0 -795 -800
0 -800 0 0 795 0 795 800 0 800 0 0 -795z m3290 0 l0 -795 -805 0 -805 0 0
795 0 795 805 0 805 0 0 -795z m-24660 -855 c0 -5 0 -364 0 -797 l0 -788 -795
0 -795 0 0 788 c0 433 0 792 0 797 0 7 272 10 795 10 523 0 795 -3 795 -10z
m1648 -787 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642
-3 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800
-793 0 c-437 0 -796 2 -798 4 -2 2 -3 362 -1 800 l2 796 795 0 795 0 0 -800z
m1648 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1640 0
l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1642 7 c0 -434 0
-793 0 -797 0 -5 -359 -8 -797 -8 l-798 0 -3 785 c-1 432 0 791 3 798 3 9 173
12 800 12 l795 0 0 -790z m1645 -10 l0 -795 -795 0 -795 0 -3 798 -2 797 797
-2 798 -3 0 -795z m1645 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0
-800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1648 3
l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0 -800
-797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798
3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1648 3 l-3
-798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1640 0 l-3 -798 -795
0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1650 0 l-3 -798 -800 0 -800 0
-3 798 -2 797 805 0 805 0 -2 -797z m1640 0 l-3 -798 -797 -3 -798 -2 0 800 0
800 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0
800 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0
-795z m1643 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z
m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m-32870
-850 c0 -5 0 -364 0 -797 l0 -788 -795 0 -795 0 0 788 c0 433 0 792 0 797 0 7
272 10 795 10 523 0 795 -3 795 -10z m1645 -790 l0 -795 -797 -3 -798 -2 0
800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 793 c0 437
3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 0
788 c0 433 0 792 0 797 0 7 272 10 795 10 l795 0 0 -800z m1645 0 l0 -795
-797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1640 0 l0 -795 -795 0
-795 0 -3 785 c-1 432 0 791 3 798 3 10 168 12 797 10 l793 -3 0 -795z m1645
10 c0 -434 0 -793 0 -797 0 -5 -359 -8 -797 -8 l-798 0 -3 775 c-1 426 0 785
3 798 l5 22 795 0 795 0 0 -790z m1645 -10 l0 -795 -797 -3 -798 -2 0 793 c0
437 3 797 7 800 3 4 362 6 797 5 l791 -3 0 -795z m1645 0 l0 -800 -797 2 -798
3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1640 0 l0
-800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1648 -2 l2 -798 -800 0
-800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -797 2 -798 3 -3
785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1640 0 l0 -800
-797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z
m1648 -2 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5
l791 -3 3 -797z m1640 -1 l2 -797 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3
10 168 12 797 10 l793 -3 3 -798z m1647 3 l0 -795 -800 0 -800 0 -3 785 c-1
432 0 791 3 798 3 10 169 12 802 10 l798 -3 0 -795z m1643 -2 l2 -798 -800 0
-800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1642 2 l0
-800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z
m1645 778 c3 -13 4 -372 3 -798 l-3 -775 -797 -3 -798 -2 0 800 0 800 795 0
795 0 5 -22z m1643 -780 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3
-797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800
7 l793 0 0 -800z m-32875 -849 c3 -5 5 -364 5 -798 l0 -788 -795 0 -795 0 0
788 c0 433 0 792 0 797 0 13 1576 14 1585 1z m1639 3 c14 -6 16 -85 16 -800
l0 -794 -796 -2 c-438 -2 -798 -1 -800 1 -7 7 -4 1587 3 1594 8 9 1556 9 1577
1z m1651 -797 l0 -797 -795 0 -795 0 -3 787 c-1 434 0 794 3 801 3 10 168 12
797 10 l793 -3 0 -798z m1645 3 l0 -800 -795 2 -795 3 0 788 c0 434 2 793 5
798 4 5 323 9 796 9 l789 0 0 -800z m1645 -2 c0 -439 -3 -798 -7 -798 -5 0
-363 0 -798 0 l-790 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 0
-797z m1640 0 c0 -439 -3 -798 -7 -798 -5 0 -363 0 -798 0 l-790 0 0 794 c0
626 3 795 13 799 6 3 365 5 797 4 l785 -2 0 -797z m1640 -1 l0 -797 -788 0
c-434 0 -793 2 -798 5 -15 10 -12 1568 3 1583 9 9 195 12 798 10 l785 -3 0
-798z m1643 791 c15 -15 18 -1573 3 -1583 -5 -3 -364 -5 -798 -5 l-788 0 -3
787 c-1 434 0 794 3 801 6 17 1565 18 1583 0z m1650 -790 l2 -798 -796 -2
c-438 -2 -798 -1 -800 1 -7 7 -4 1587 3 1594 3 4 362 6 797 5 l791 -3 3 -797z
m1640 0 l2 -798 -795 -2 -795 -3 0 803 0 802 793 -2 792 -3 3 -797z m1647 -1
l0 -797 -795 0 -795 0 -3 800 -2 800 797 -2 798 -3 0 -798z m1640 1 c0 -439
-3 -798 -7 -798 -5 0 -363 0 -798 0 l-790 0 0 794 c0 626 3 795 13 799 6 3
365 5 797 4 l785 -2 0 -797z m1640 -1 l0 -797 -789 0 c-433 0 -792 3 -797 6
-5 3 -9 347 -9 794 0 621 3 789 13 793 6 3 365 5 797 4 l785 -2 0 -798z m1653
1 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3
-797z m1637 0 c0 -439 -3 -798 -7 -798 -5 0 -363 0 -798 0 l-790 0 0 793 c0
437 3 797 7 800 3 4 362 6 797 5 l791 -3 0 -797z m1639 796 c14 -6 16 -85 16
-800 l0 -794 -795 -2 c-437 -2 -800 -1 -805 0 -16 6 -14 1589 3 1595 18 8
1562 8 1581 1z m1640 0 c14 -6 16 -85 16 -800 l0 -794 -796 -2 c-438 -2 -798
-1 -800 1 -7 7 -4 1587 3 1594 8 9 1556 9 1577 1z m1656 -796 l0 -803 -797 2
-798 3 -3 787 c-1 434 0 794 3 801 3 9 173 12 800 12 l795 0 0 -802z m1644
786 c9 -23 7 -1567 -2 -1579 -4 -7 -283 -10 -800 -10 l-792 0 0 803 0 802 794
0 c715 0 794 -2 800 -16z m1641 -787 l0 -797 -798 -3 -797 -2 0 803 0 802 798
-2 797 -3 0 -798z m1640 1 c0 -439 -3 -798 -7 -798 -5 0 -363 0 -798 0 l-790
0 0 794 c0 626 3 795 13 799 6 3 365 5 797 4 l785 -2 0 -797z m-32865 -1640
c0 -434 0 -792 0 -798 0 -7 -272 -10 -795 -10 -523 0 -795 3 -795 10 0 6 0
363 0 795 0 432 0 787 0 790 0 3 358 4 795 3 l795 -3 0 -787z m1645 -8 l0
-795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -797
2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -795 0 c-523 0
-795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0 3 358 5 795 5 l795 0 0
-800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z
m1643 3 l-3 -798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12
l795 0 -2 -797z m1642 3 c0 -433 -3 -792 -6 -797 -3 -5 -347 -9 -794 -9 -709
0 -788 2 -794 16 -8 22 -8 1569 1 1577 3 4 364 6 800 5 l793 -3 0 -789z m1645
-6 l0 -795 -795 0 -795 0 -3 798 -2 797 797 -2 798 -3 0 -795z m1643 3 l-3
-798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 -2
-797z m1642 -3 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1648
3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1640 0 l-3
-798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 -2
-797z m1642 -3 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12
800 12 l795 0 0 -800z m1648 3 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0
800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3
9 173 12 800 12 l795 0 -2 -797z m1647 -3 l0 -795 -800 0 -800 0 -3 785 c-1
432 0 791 3 798 3 10 169 12 802 10 l798 -3 0 -795z m1643 3 l-3 -798 -795 0
-795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3
798 -2 797 800 0 800 0 0 -800z m1648 20 c1 -426 0 -785 -3 -797 l-5 -23 -795
0 -795 0 0 800 0 800 798 -2 797 -3 3 -775z m1640 -17 l-3 -798 -797 -3 -798
-2 0 800 0 800 800 0 800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 798
-2 797 800 0 800 0 -2 -797z m-32868 -1635 c0 -434 0 -792 0 -798 0 -7 -272
-10 -795 -10 -523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0 3
358 4 795 3 l795 -3 0 -787z m1648 -10 l2 -798 -800 0 -800 0 0 800 0 800 798
-2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m1640 0 l0 -800 -795 0 -795 0 -2 796 c-2 438 -1 798 1 800 2 2 361 4
798 4 l793 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797
-3 3 -797z m1640 0 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6
797 5 l791 -3 3 -797z m1643 798 c2 -2 3 -362 1 -800 l-2 -796 -798 2 -797 3
-3 785 c-1 432 0 791 3 798 3 9 172 12 798 12 437 0 796 -2 798 -4z m1644
-796 l0 -795 -797 -3 -798 -2 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791
-3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7
800 7 l793 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0
0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z
m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793
0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173
12 800 12 l795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 793 c0 437 3 797
7 800 3 4 362 6 797 5 l791 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 793
c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1648 -2 l2 -798 -805 0
-805 0 0 793 c0 437 3 797 7 800 3 4 365 6 802 5 l796 -3 3 -797z m1640 0 l2
-798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0
-800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1645 0 l0
-795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1643 -2 l2 -798
-800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800
0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m-32867 -1642 l-3
-793 -795 0 -795 0 -3 793 -2 792 800 0 800 0 -2 -792z m1647 -3 l0 -795 -800
0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0
795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -795 0 -795 0 0 779 c0 429 -3
786 -6 795 -6 15 69 16 795 16 l801 0 0 -795z m1650 0 l0 -795 -800 0 -800 0
0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795
800 0 800 0 0 -795z m1640 0 l0 -795 -797 2 -798 3 -3 793 -2 792 800 0 800 0
0 -795z m1650 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640
0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795
-795 0 -795 0 0 795 0 795 795 0 795 0 0 -795z m1650 0 l0 -795 -800 0 -800 0
0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795
800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0
-795z m1650 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0
l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1650 0 l0 -795 -805
0 -805 0 0 795 0 795 805 0 805 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0
795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795 800
0 800 0 0 -795z m1648 3 l-3 -793 -797 -3 -798 -2 0 795 0 795 800 0 800 0 -2
-792z m1642 -3 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640
0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m-32870 -1645 l0
-795 -795 0 -795 0 0 793 c0 435 0 794 0 797 0 3 358 4 795 3 l795 -3 0 -795z
m1648 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3
l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -795
2 -795 3 0 793 c0 435 0 794 0 797 0 3 358 5 795 5 l795 0 0 -800z m1648 3
l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0 -800
-797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 10 c0 -434 0 -793 0
-797 0 -5 -359 -8 -797 -8 l-798 0 -3 798 -2 797 800 0 800 0 0 -790z m1648
-7 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0
-800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -795 0
-795 0 0 800 0 800 795 0 795 0 0 -800z m1650 0 l0 -800 -800 0 -800 0 0 800
0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0
800 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0
-800z m1650 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0
l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1650 0 l0 -800
-802 2 -803 3 -3 798 -2 797 805 0 805 0 0 -800z m1640 0 l0 -800 -800 0 -800
0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -800 0 -800 0 0 800 0 800
800 0 800 0 0 -800z m1648 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800
0 -2 -797z m1642 -3 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z
m1640 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m-32870 -850
c0 -5 0 -364 0 -797 l0 -788 -795 0 -795 0 0 788 c0 433 0 792 0 797 0 7 272
10 795 10 523 0 795 -3 795 -10z m1648 -792 l2 -798 -800 0 -800 0 0 800 0
800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 800 0 800 800 0
800 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 0 788 c0 433 0 792 0 797 0 7
272 10 795 10 l795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798
-2 797 -3 3 -797z m1640 0 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3
4 362 6 797 5 l791 -3 3 -797z m1642 12 c0 -434 0 -793 0 -797 0 -5 -359 -8
-797 -8 l-798 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -790z
m1645 -10 l0 -795 -797 -3 -798 -2 0 793 c0 437 3 797 7 800 3 4 362 6 797 5
l791 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4
363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0
795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3
-797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800
7 l793 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3
9 173 12 800 12 l795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 793 c0 437
3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0
793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1648 -2 l2 -798 -805
0 -805 0 0 793 c0 437 3 797 7 800 3 4 365 6 802 5 l796 -3 3 -797z m1640 0
l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800
-800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1645
0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1643 -2 l2
-798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0
-800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m-32870 -850
c0 -5 0 -364 0 -797 l0 -788 -795 0 -795 0 0 788 c0 433 0 792 0 797 0 7 272
10 795 10 523 0 795 -3 795 -10z m1648 -792 l2 -798 -800 0 -800 0 0 800 0
800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797
7 800 3 4 363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 0 788 c0
434 2 793 5 798 4 5 323 9 796 9 l789 0 0 -800z m1648 -2 l2 -798 -800 0 -800
0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1640 0 l2 -798
-800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z
m1640 0 l2 -798 -800 0 -800 0 0 788 c0 602 3 791 12 800 9 9 195 12 798 10
l785 -3 3 -797z m1636 796 c14 -6 16 -85 16 -800 l0 -794 -800 0 -800 0 0 793
c0 437 3 797 7 800 8 9 1556 9 1577 1z m1654 -796 l2 -798 -800 0 -800 0 0
793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1640 0 l2 -798 -795
0 -795 0 0 800 0 800 793 -2 792 -3 3 -797z m1647 0 c0 -439 -3 -798 -7 -798
-5 0 -363 0 -798 0 l-790 0 0 800 0 800 798 -2 797 -3 0 -797z m1643 0 l2
-798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z
m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793
0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6
797 5 l791 -3 3 -797z m1640 0 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7
800 3 4 362 6 797 5 l791 -3 3 -797z m1650 0 l2 -798 -805 0 -805 0 0 793 c0
437 3 797 7 800 3 4 365 6 802 5 l796 -3 3 -797z m1640 0 l2 -798 -800 0 -800
0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1642 2 l0 -800
-800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1645
778 c8 -35 1 -1578 -7 -1578 -5 0 -363 0 -798 0 l-790 0 0 800 0 800 795 0
795 0 5 -22z m1643 -780 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3
-797z m1640 0 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797
5 l791 -3 3 -797z m-32868 -1648 l0 -795 -795 0 -795 0 0 793 c0 435 0 794 0
797 0 3 358 4 795 3 l795 -3 0 -795z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0
800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0
800 0 0 -800z m1640 0 l0 -800 -793 0 c-437 0 -796 2 -798 4 -2 2 -3 362 -1
800 l2 796 795 0 795 0 0 -800z m1645 0 l0 -795 -795 0 -795 0 -3 798 -2 797
797 -2 798 -3 0 -795z m1640 0 l0 -795 -795 0 -795 0 -3 785 c-1 432 0 791 3
798 3 10 168 12 797 10 l793 -3 0 -795z m1643 3 l-3 -798 -775 -3 c-426 -1
-785 0 -797 3 l-23 5 0 789 c0 433 3 791 7 794 3 4 363 7 800 7 l793 0 -2
-797z m1647 -3 l0 -795 -795 0 -795 0 -3 798 -2 797 797 -2 798 -3 0 -795z
m1643 3 l-3 -798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12
l795 0 -2 -797z m1640 0 l-3 -798 -792 -3 -793 -2 0 800 0 800 795 0 795 0 -2
-797z m1650 0 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z
m1640 0 l-3 -798 -795 0 -795 0 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12
l795 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3
9 173 12 800 12 l795 0 0 -800z m1648 3 l-3 -798 -795 0 -795 0 -3 798 -2 797
800 0 800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 785 c-1 432 0 791 3
798 3 9 173 12 800 12 l795 0 -2 -797z m1647 -3 l0 -795 -800 0 -800 0 -3 785
c-1 432 0 791 3 798 3 10 169 12 802 10 l798 -3 0 -795z m1643 3 l-3 -798
-795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2
-798 3 -3 798 -2 797 800 0 800 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0
800 0 800 798 -2 797 -3 0 -795z m1643 3 l-3 -798 -797 -3 -798 -2 0 800 0
800 800 0 800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0
800 0 -2 -797z m-32868 -853 c0 -5 0 -364 0 -797 l0 -788 -795 0 -795 0 0 788
c0 433 0 792 0 797 0 7 272 10 795 10 523 0 795 -3 795 -10z m1645 -790 l0
-795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800
0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 0
788 c0 433 0 792 0 797 0 7 272 10 795 10 l795 0 0 -800z m1645 0 l0 -795
-797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1643 -3 l2 -797 -797 2
-798 3 -3 785 c-1 432 0 791 3 798 3 10 168 12 797 10 l793 -3 3 -798z m1642
3 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0
0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 793 c0 437 3 797 7 800 3 4 362 6
797 5 l791 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7
800 3 4 363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0
800 795 0 795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2
797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4
363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 785 c-1 432 0
791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0
793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1642 2 l0 -800 -800
0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1648 -3
l2 -797 -802 2 -803 3 -3 785 c-1 432 0 791 3 798 3 10 169 12 802 10 l798 -3
3 -798z m1640 1 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z
m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793
0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z
m1643 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z m1642 2 l0
-800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z
m-32870 -1645 l0 -790 -795 0 -795 0 0 788 c0 433 0 789 0 792 0 3 358 4 795
3 l795 -3 0 -790z m1650 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0
-795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0
l0 -795 -795 2 -795 3 0 788 c0 433 0 789 0 792 0 3 358 5 795 5 l795 0 0
-795z m1650 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0
l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1641 791 c2 -2 3
-360 1 -795 l-2 -791 -798 2 -797 3 -3 780 c-1 429 0 786 3 793 3 9 172 12
798 12 437 0 796 -2 798 -4z m1644 -791 l0 -790 -797 -3 -798 -2 0 795 0 795
798 -2 797 -3 0 -790z m1645 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0
0 -795z m1640 0 l0 -795 -795 0 -795 0 0 795 0 795 795 0 795 0 0 -795z m1650
0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795
-800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -797 2 -798 3
-3 780 c-1 429 0 786 3 793 3 9 173 12 800 12 l795 0 0 -795z m1650 0 l0 -795
-800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0
0 795 0 795 800 0 800 0 0 -795z m1650 0 l0 -795 -802 2 -803 3 -3 793 -2 792
805 0 805 0 0 -795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0
-795z m1640 0 l0 -795 -800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1645 0
l0 -790 -797 -3 -798 -2 0 795 0 795 798 -2 797 -3 0 -790z m1645 0 l0 -795
-800 0 -800 0 0 795 0 795 800 0 800 0 0 -795z m1640 0 l0 -795 -800 0 -800 0
0 795 0 795 800 0 800 0 0 -795z m-32870 -1637 c0 -434 0 -792 0 -798 0 -7
-272 -10 -795 -10 -523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0
3 358 4 795 3 l795 -3 0 -787z m1645 -8 l0 -795 -797 -3 -798 -2 0 800 0 800
798 -2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0
0 -800z m1640 0 l0 -800 -795 0 c-523 0 -795 3 -795 10 0 6 0 363 0 795 0 432
0 787 0 790 0 3 358 5 795 5 l795 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2
0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -797 2 -798 3 -3 785 c-1
432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1641 796 c2 -2 3 -362 1
-800 l-2 -796 -798 2 -797 3 -3 785 c-1 432 0 791 3 798 3 9 172 12 798 12
437 0 796 -2 798 -4z m1644 -796 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2
797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z
m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1650 0 l0
-800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2
-798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3
785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1650 0 l0 -800
-800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798 3
-3 798 -2 797 800 0 800 0 0 -800z m1650 0 l0 -800 -802 2 -803 3 -3 785 c-1
432 0 791 3 798 3 9 174 12 805 12 l800 0 0 -800z m1640 0 l0 -800 -800 0
-800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -800 0 -800 0 0 800
0 800 800 0 800 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798
-2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m1640 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m-32870
-1632 c0 -434 0 -792 0 -798 0 -7 -272 -10 -795 -10 -523 0 -795 3 -795 10 0
6 0 363 0 795 0 432 0 787 0 790 0 3 358 4 795 3 l795 -3 0 -787z m1645 -8 l0
-795 -797 -3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800
0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800 7 l793 0 0 -800z m1640 0 l0
-800 -795 0 c-523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 787 0 790 0 3
358 5 795 5 l795 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798
-2 797 -3 0 -795z m1643 -2 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3
4 362 6 797 5 l791 -3 3 -797z m1643 798 c2 -2 3 -362 1 -800 l-2 -796 -798 2
-797 3 -3 785 c-1 432 0 791 3 798 3 9 172 12 798 12 437 0 796 -2 798 -4z
m1644 -796 l0 -795 -797 -3 -798 -2 0 793 c0 437 3 797 7 800 3 4 362 6 797 5
l791 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4
363 7 800 7 l793 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0
795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3
-797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7 800
7 l793 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 785 c-1 432 0 791 3 798 3
9 173 12 800 12 l795 0 0 -800z m1648 -2 l2 -798 -800 0 -800 0 0 793 c0 437
3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1640 0 l2 -798 -800 0 -800 0 0
793 c0 437 3 797 7 800 3 4 362 6 797 5 l791 -3 3 -797z m1650 -1 l2 -797
-802 2 -803 3 -3 785 c-1 432 0 791 3 798 3 10 169 12 802 10 l798 -3 3 -798z
m1640 1 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791
-3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 363 7
800 7 l793 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0 800 0 800 798 -2 797
-3 0 -795z m1643 -2 l2 -798 -800 0 -800 0 0 800 0 800 798 -2 797 -3 3 -797z
m1640 0 l2 -798 -800 0 -800 0 0 793 c0 437 3 797 7 800 3 4 362 6 797 5 l791
-3 3 -797z m-16430 -1649 l-3 -794 -797 -3 -798 -2 0 800 0 800 793 2 c435 2
795 0 800 -3 4 -3 6 -363 5 -800z m13150 0 l-3 -794 -797 -3 -798 -2 0 800 0
800 793 2 c435 2 795 0 800 -3 4 -3 6 -363 5 -800z m-29585 4 l-3 -798 -795 0
-795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1645 0 l-3 -798 -797 -3 -798 -2
0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2
797 800 0 800 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 -3 798 -2 797 798 0
797 0 0 -800z m1648 3 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2
-797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z
m1647 5 c0 -517 -3 -796 -10 -800 -12 -9 -1556 -11 -1579 -2 -14 6 -16 85 -16
800 l0 794 803 0 802 0 0 -792z m1643 -5 l-3 -798 -795 0 -795 0 -3 798 -2
797 800 0 800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0
800 0 -2 -797z m1640 0 l-3 -798 -792 -3 -793 -2 0 800 0 800 795 0 795 0 -2
-797z m3290 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z
m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1648 3
l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1640 0 l-3 -798
-795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1650 0 l-3 -798 -800 0
-800 0 -3 798 -2 797 805 0 805 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3
798 -2 797 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797 2 -798 3 -3 798 -2
797 800 0 800 0 0 -800z m3288 3 l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0
800 0 -2 -797z m1640 0 l-3 -798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2
-797z m-32868 -853 c0 -5 0 -364 0 -797 l0 -788 -795 0 -795 0 0 788 c0 433 0
792 0 797 0 7 272 10 795 10 523 0 795 -3 795 -10z m1645 -790 l0 -795 -797
-3 -798 -2 0 800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0
0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -795 2 -795 3 0 788 c0 433
0 792 0 797 0 7 272 10 795 10 l795 0 0 -800z m1645 0 l0 -795 -797 -3 -798
-2 0 800 0 800 798 -2 797 -3 0 -795z m1643 3 l-3 -798 -795 0 -795 0 -3 785
c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 -2 -797z m1642 7 c0 -434 0
-793 0 -797 0 -5 -359 -8 -797 -8 l-798 0 -3 785 c-1 432 0 791 3 798 3 9 173
12 800 12 l795 0 0 -790z m1645 -10 l0 -795 -797 -3 -798 -2 0 800 0 800 798
-2 797 -3 0 -795z m1645 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0 0
-800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z m1648 3
l-3 -798 -797 -3 -798 -2 0 800 0 800 800 0 800 0 -2 -797z m1642 -3 l0 -800
-797 2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798
3 -3 785 c-1 432 0 791 3 798 3 9 173 12 800 12 l795 0 0 -800z m1648 3 l-3
-798 -795 0 -795 0 -3 798 -2 797 800 0 800 0 -2 -797z m1642 -3 l0 -800 -797
2 -798 3 -3 798 -2 797 800 0 800 0 0 -800z m1648 3 l-3 -798 -800 0 -800 0
-3 785 c-1 432 0 791 3 798 3 9 174 12 805 12 l800 0 -2 -797z m1642 -3 l0
-800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1640 0 l0 -800 -797 2
-798 3 -3 798 -2 797 800 0 800 0 0 -800z m1645 0 l0 -795 -797 -3 -798 -2 0
800 0 800 798 -2 797 -3 0 -795z m1645 0 l0 -800 -800 0 -800 0 0 800 0 800
800 0 800 0 0 -800z m1640 0 l0 -800 -797 2 -798 3 -3 798 -2 797 800 0 800 0
0 -800z m-32870 -850 c0 -5 0 -363 0 -795 0 -432 0 -789 0 -795 0 -7 -272 -10
-795 -10 -523 0 -795 3 -795 10 0 6 0 363 0 795 0 432 0 790 0 795 0 7 272 10
795 10 523 0 795 -3 795 -10z m1645 -795 l0 -800 -795 0 -795 0 -3 803 -2 802
797 -2 798 -3 0 -800z m1645 0 l0 -805 -797 2 -798 3 -3 803 -2 802 800 0 800
0 0 -805z m1640 0 l0 -805 -795 0 c-523 0 -795 3 -795 10 0 6 0 363 0 795 0
432 0 790 0 795 0 7 272 10 795 10 l795 0 0 -805z m1645 0 l0 -800 -795 0
-795 0 -3 803 -2 802 797 -2 798 -3 0 -800z m1640 0 l0 -800 -795 0 -795 0 -3
790 c-1 435 0 796 3 803 3 10 168 12 797 10 l793 -3 0 -800z m1643 3 l-3 -803
-784 -3 c-571 -1 -787 1 -797 9 -12 10 -14 147 -14 799 0 432 3 790 7 793 3 4
363 7 800 7 l793 0 -2 -802z m1650 0 l2 -798 -22 -5 c-13 -3 -372 -4 -798 -3
l-775 3 -3 803 -2 802 797 -2 798 -3 3 -797z m1640 0 l-3 -803 -795 0 -795 0
-3 790 c-1 435 0 796 3 803 3 9 173 12 800 12 l795 0 -2 -802z m1640 0 l-3
-803 -792 -3 -793 -2 0 805 0 805 795 0 795 0 -2 -802z m1650 0 l-3 -803 -797
-3 -798 -2 0 805 0 805 800 0 800 0 -2 -802z m16432 -818 l0 -1620 -6550 0
c-6543 0 -6550 0 -6550 20 0 15 -7 20 -25 20 -18 0 -25 -5 -25 -20 0 -20 -7
-20 -800 -20 -793 0 -800 0 -800 20 0 13 -7 20 -20 20 -13 0 -20 -7 -20 -20 0
-20 -7 -20 -800 -20 l-800 0 0 800 c0 704 2 800 15 800 8 0 15 7 15 15 0 9 -7
18 -15 21 -13 5 -15 103 -15 798 0 436 3 796 7 799 3 4 3691 7 8195 7 l8188 0
0 -1620z m-32870 -820 l0 -795 -795 0 -795 0 0 793 c0 435 0 794 0 797 0 3
358 4 795 3 l795 -3 0 -795z m1648 -2 l2 -798 -800 0 -800 0 0 800 0 800 798
-2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m1640 0 l0 -800 -795 2 -795 3 0 793 c0 435 0 794 0 797 0 3 358 5 795
5 l795 0 0 -800z m1650 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0
-800z m1640 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z m1641
796 c2 -2 3 -362 1 -800 l-2 -796 -798 2 -797 3 -3 785 c-1 432 0 791 3 798 3
9 172 12 798 12 437 0 796 -2 798 -4z m1647 -798 l2 -798 -800 0 -800 0 0 800
0 800 798 -2 797 -3 3 -797z m1642 2 l0 -800 -800 0 -800 0 0 800 0 800 800 0
800 0 0 -800z m1640 0 l0 -800 -795 0 -795 0 0 800 0 800 795 0 795 0 0 -800z
m1650 0 l0 -800 -800 0 -800 0 0 800 0 800 800 0 800 0 0 -800z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -105,7 +105,10 @@ if (SLIC3R_GUI)
# wrong libs for opengl in the link line and it does not link to it by himself.
# libslic3r_gui will link to opengl anyway, so lets override wx
list(FILTER wxWidgets_LIBRARIES EXCLUDE REGEX OpenGL)
if (UNIX AND NOT APPLE)
list(APPEND wxWidgets_LIBRARIES X11 wayland-client wayland-egl EGL)
endif ()
# list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc)
message(STATUS "wx libs: ${wxWidgets_LIBRARIES}")

View File

@ -66,16 +66,25 @@ public:
return this->success;
}
void unload_opengl_dll()
bool unload_opengl_dll()
{
if (this->hOpenGL) {
BOOL released = FreeLibrary(this->hOpenGL);
if (released)
printf("System OpenGL library released\n");
if (this->hOpenGL != nullptr) {
if (::FreeLibrary(this->hOpenGL) != FALSE) {
if (::GetModuleHandle(L"opengl32.dll") == nullptr) {
printf("System OpenGL library successfully released\n");
this->hOpenGL = nullptr;
return true;
}
else
printf("System OpenGL library released but not removed\n");
}
else
printf("System OpenGL library NOT released\n");
this->hOpenGL = nullptr;
return false;
}
return true;
}
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
@ -270,20 +279,26 @@ int wmain(int argc, wchar_t **argv)
// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
if (load_mesa) {
opengl_version_check.unload_opengl_dll();
wchar_t path_to_mesa[MAX_PATH + 1] = { 0 };
wcscpy(path_to_mesa, path_to_exe);
wcscat(path_to_mesa, L"mesa\\opengl32.dll");
printf("Loading MESA OpenGL library: %S\n", path_to_mesa);
HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0);
if (hInstance_OpenGL == nullptr) {
printf("MESA OpenGL library was not loaded\n");
} else
printf("MESA OpenGL library was loaded sucessfully\n");
bool res = opengl_version_check.unload_opengl_dll();
if (!res) {
MessageBox(nullptr, L"PrusaSlicer was unable to automatically switch to MESA OpenGL library\nPlease, try to run the application using the '--sw-renderer' option.\n",
L"PrusaSlicer Warning", MB_OK);
return -1;
}
else {
wchar_t path_to_mesa[MAX_PATH + 1] = { 0 };
wcscpy(path_to_mesa, path_to_exe);
wcscat(path_to_mesa, L"mesa\\opengl32.dll");
printf("Loading MESA OpenGL library: %S\n", path_to_mesa);
HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0);
if (hInstance_OpenGL == nullptr)
printf("MESA OpenGL library was not loaded\n");
else
printf("MESA OpenGL library was loaded sucessfully\n");
}
}
#endif /* SLIC3R_GUI */
wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 };
wcscpy(path_to_slic3r, path_to_exe);
wcscat(path_to_slic3r, L"PrusaSlicer.dll");

View File

@ -2290,6 +2290,12 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times
{
#ifdef CLIPPERLIB_USE_XYZ
if (dir == dLeftToRight)
SetZ(e->Curr, *horzEdge, *e);
else
SetZ(e->Curr, *e, *horzEdge);
#endif
op1 = AddOutPt(horzEdge, e->Curr);
TEdge* eNextHorz = m_SortedEdges;
while (eNextHorz)
@ -2614,6 +2620,9 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
{
e->Curr.x() = TopX( *e, topY );
e->Curr.y() = topY;
#ifdef CLIPPERLIB_USE_XYZ
e->Curr.z() = topY == e->Top.y() ? e->Top.z() : (topY == e->Bot.y() ? e->Bot.z() : 0);
#endif
}
//When StrictlySimple and 'e' is being touched by another edge, then

View File

@ -446,6 +446,57 @@ namespace detail {
}
}
// Real-time collision detection, Ericson, Chapter 5
template<typename Vector>
static inline Vector closest_point_to_triangle(const Vector &p, const Vector &a, const Vector &b, const Vector &c)
{
using Scalar = typename Vector::Scalar;
// Check if P in vertex region outside A
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
Scalar d1 = ab.dot(ap);
Scalar d2 = ac.dot(ap);
if (d1 <= 0 && d2 <= 0)
return a;
// Check if P in vertex region outside B
Vector bp = p - b;
Scalar d3 = ab.dot(bp);
Scalar d4 = ac.dot(bp);
if (d3 >= 0 && d4 <= d3)
return b;
// Check if P in edge region of AB, if so return projection of P onto AB
Scalar vc = d1*d4 - d3*d2;
if (a != b && vc <= 0 && d1 >= 0 && d3 <= 0) {
Scalar v = d1 / (d1 - d3);
return a + v * ab;
}
// Check if P in vertex region outside C
Vector cp = p - c;
Scalar d5 = ab.dot(cp);
Scalar d6 = ac.dot(cp);
if (d6 >= 0 && d5 <= d6)
return c;
// Check if P in edge region of AC, if so return projection of P onto AC
Scalar vb = d5*d2 - d1*d6;
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
Scalar w = d2 / (d2 - d6);
return a + w * ac;
}
// Check if P in edge region of BC, if so return projection of P onto BC
Scalar va = d3*d6 - d5*d4;
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
return b + w * (c - b);
}
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
Scalar denom = Scalar(1.0) / (va + vb + vc);
Scalar v = vb * denom;
Scalar w = vc * denom;
return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
};
// Nothing to do with COVID-19 social distancing.
template<typename AVertexType, typename AIndexedFaceType, typename ATreeType, typename AVectorType>
struct IndexedTriangleSetDistancer {
@ -453,74 +504,36 @@ namespace detail {
using IndexedFaceType = AIndexedFaceType;
using TreeType = ATreeType;
using VectorType = AVectorType;
using ScalarType = typename VectorType::Scalar;
const std::vector<VertexType> &vertices;
const std::vector<IndexedFaceType> &faces;
const TreeType &tree;
const VectorType origin;
inline VectorType closest_point_to_origin(size_t primitive_index,
ScalarType& squared_distance){
const auto &triangle = this->faces[primitive_index];
VectorType closest_point = closest_point_to_triangle<VectorType>(origin,
this->vertices[triangle(0)].template cast<ScalarType>(),
this->vertices[triangle(1)].template cast<ScalarType>(),
this->vertices[triangle(2)].template cast<ScalarType>());
squared_distance = (origin - closest_point).squaredNorm();
return closest_point;
}
};
// Real-time collision detection, Ericson, Chapter 5
template<typename Vector>
static inline Vector closest_point_to_triangle(const Vector &p, const Vector &a, const Vector &b, const Vector &c)
{
using Scalar = typename Vector::Scalar;
// Check if P in vertex region outside A
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
Scalar d1 = ab.dot(ap);
Scalar d2 = ac.dot(ap);
if (d1 <= 0 && d2 <= 0)
return a;
// Check if P in vertex region outside B
Vector bp = p - b;
Scalar d3 = ab.dot(bp);
Scalar d4 = ac.dot(bp);
if (d3 >= 0 && d4 <= d3)
return b;
// Check if P in edge region of AB, if so return projection of P onto AB
Scalar vc = d1*d4 - d3*d2;
if (a != b && vc <= 0 && d1 >= 0 && d3 <= 0) {
Scalar v = d1 / (d1 - d3);
return a + v * ab;
}
// Check if P in vertex region outside C
Vector cp = p - c;
Scalar d5 = ab.dot(cp);
Scalar d6 = ac.dot(cp);
if (d6 >= 0 && d5 <= d6)
return c;
// Check if P in edge region of AC, if so return projection of P onto AC
Scalar vb = d5*d2 - d1*d6;
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
Scalar w = d2 / (d2 - d6);
return a + w * ac;
}
// Check if P in edge region of BC, if so return projection of P onto BC
Scalar va = d3*d6 - d5*d4;
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
return b + w * (c - b);
}
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
Scalar denom = Scalar(1.0) / (va + vb + vc);
Scalar v = vb * denom;
Scalar w = vc * denom;
return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
};
template<typename IndexedTriangleSetDistancerType, typename Scalar>
static inline Scalar squared_distance_to_indexed_triangle_set_recursive(
IndexedTriangleSetDistancerType &distancer,
template<typename IndexedPrimitivesDistancerType, typename Scalar>
static inline Scalar squared_distance_to_indexed_primitives_recursive(
IndexedPrimitivesDistancerType &distancer,
size_t node_idx,
Scalar low_sqr_d,
Scalar up_sqr_d,
size_t &i,
Eigen::PlainObjectBase<typename IndexedTriangleSetDistancerType::VectorType> &c)
Eigen::PlainObjectBase<typename IndexedPrimitivesDistancerType::VectorType> &c)
{
using Vector = typename IndexedTriangleSetDistancerType::VectorType;
using Vector = typename IndexedPrimitivesDistancerType::VectorType;
if (low_sqr_d > up_sqr_d)
return low_sqr_d;
@ -538,13 +551,9 @@ namespace detail {
assert(node.is_valid());
if (node.is_leaf())
{
const auto &triangle = distancer.faces[node.idx];
Vector c_candidate = closest_point_to_triangle<Vector>(
distancer.origin,
distancer.vertices[triangle(0)].template cast<Scalar>(),
distancer.vertices[triangle(1)].template cast<Scalar>(),
distancer.vertices[triangle(2)].template cast<Scalar>());
set_min((c_candidate - distancer.origin).squaredNorm(), node.idx, c_candidate);
Scalar sqr_dist;
Vector c_candidate = distancer.closest_point_to_origin(node.idx, sqr_dist);
set_min(sqr_dist, node.idx, c_candidate);
}
else
{
@ -561,7 +570,7 @@ namespace detail {
{
size_t i_left;
Vector c_left = c;
Scalar sqr_d_left = squared_distance_to_indexed_triangle_set_recursive(distancer, left_node_idx, low_sqr_d, up_sqr_d, i_left, c_left);
Scalar sqr_d_left = squared_distance_to_indexed_primitives_recursive(distancer, left_node_idx, low_sqr_d, up_sqr_d, i_left, c_left);
set_min(sqr_d_left, i_left, c_left);
looked_left = true;
};
@ -569,13 +578,13 @@ namespace detail {
{
size_t i_right;
Vector c_right = c;
Scalar sqr_d_right = squared_distance_to_indexed_triangle_set_recursive(distancer, right_node_idx, low_sqr_d, up_sqr_d, i_right, c_right);
Scalar sqr_d_right = squared_distance_to_indexed_primitives_recursive(distancer, right_node_idx, low_sqr_d, up_sqr_d, i_right, c_right);
set_min(sqr_d_right, i_right, c_right);
looked_right = true;
};
// must look left or right if in box
using BBoxScalar = typename IndexedTriangleSetDistancerType::TreeType::BoundingBox::Scalar;
using BBoxScalar = typename IndexedPrimitivesDistancerType::TreeType::BoundingBox::Scalar;
if (node_left.bbox.contains(distancer.origin.template cast<BBoxScalar>()))
look_left();
if (node_right.bbox.contains(distancer.origin.template cast<BBoxScalar>()))
@ -747,7 +756,7 @@ inline typename VectorType::Scalar squared_distance_to_indexed_triangle_set(
auto distancer = detail::IndexedTriangleSetDistancer<VertexType, IndexedFaceType, TreeType, VectorType>
{ vertices, faces, tree, point };
return tree.empty() ? Scalar(-1) :
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
}
// Decides if exists some triangle in defined radius on a 3D indexed triangle set using a pre-built AABBTreeIndirect::Tree.
@ -779,7 +788,7 @@ inline bool is_any_triangle_in_radius(
return false;
}
detail::squared_distance_to_indexed_triangle_set_recursive(distancer, size_t(0), Scalar(0), max_distance_squared, hit_idx, hit_point);
detail::squared_distance_to_indexed_primitives_recursive(distancer, size_t(0), Scalar(0), max_distance_squared, hit_idx, hit_point);
return hit_point.allFinite();
}

View File

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

View File

@ -1,11 +1,12 @@
#ifndef ASTAR_HPP
#define ASTAR_HPP
#include <cmath> // std::isinf() is here
#include <unordered_map>
#include "libslic3r/Point.hpp"
#include "libslic3r/MutablePriorityQueue.hpp"
#include <unordered_map>
namespace Slic3r { namespace astar {
// Input interface for the Astar algorithm. Specialize this struct for a
@ -34,6 +35,8 @@ template<class T> struct TracerTraits_
// Get the estimated distance heuristic from node 'n' to the destination.
// This is referred to as the h value in AStar context.
// If node 'n' is the goal, this function should return a negative value.
// Note that this heuristic should be admissible (never bigger than the real
// cost) in order for Astar to work.
static float goal_heuristic(const T &tracer, const Node &n)
{
return tracer.goal_heuristic(n);
@ -50,131 +53,136 @@ template<class T> struct TracerTraits_
template<class T>
using TracerNodeT = typename TracerTraits_<remove_cvref_t<T>>::Node;
namespace detail {
// Helper functions dispatching calls through the TracerTraits_ interface
constexpr auto Unassigned = std::numeric_limits<size_t>::max();
template<class T> using TracerTraits = TracerTraits_<remove_cvref_t<T>>;
template<class T, class Fn>
void foreach_reachable(const T &tracer, const TracerNodeT<T> &from, Fn &&fn)
template<class Tracer>
struct QNode // Queue node. Keeps track of scores g, and h
{
TracerTraits<T>::foreach_reachable(tracer, from, fn);
}
TracerNodeT<Tracer> node; // The actual node itself
size_t queue_id; // Position in the open queue or Unassigned if closed
size_t parent; // unique id of the parent or Unassigned
template<class T>
float trace_distance(const T &tracer, const TracerNodeT<T> &a, const TracerNodeT<T> &b)
{
return TracerTraits<T>::distance(tracer, a, b);
}
float g, h;
float f() const { return g + h; }
template<class T>
float goal_heuristic(const T &tracer, const TracerNodeT<T> &n)
{
return TracerTraits<T>::goal_heuristic(tracer, n);
}
template<class T>
size_t unique_id(const T &tracer, const TracerNodeT<T> &n)
{
return TracerTraits<T>::unique_id(tracer, n);
}
} // namespace astar_detail
QNode(TracerNodeT<Tracer> n = {},
size_t p = Unassigned,
float gval = std::numeric_limits<float>::infinity(),
float hval = 0.f)
: node{std::move(n)}
, parent{p}
, queue_id{InvalidQueueID}
, g{gval}
, h{hval}
{}
};
// Run the AStar algorithm on a tracer implementation.
// The 'tracer' argument encapsulates the domain (grid, point cloud, etc...)
// The 'source' argument is the starting node.
// The 'out' argument is the output iterator into which the output nodes are
// written.
// Note that no destination node is given. The tracer's goal_heuristic() method
// should return a negative value if a node is a destination node.
template<class Tracer, class It>
bool search_route(const Tracer &tracer, const TracerNodeT<Tracer> &source, It out)
// written. For performance reasons, the order is reverse, from the destination
// to the source -- (destination included, source is not).
// The 'cached_nodes' argument is an optional associative container to hold a
// QNode entry for each visited node. Any compatible container can be used
// (like std::map or maps with different allocators, even a sufficiently large
// std::vector).
//
// Note that no destination node is given in the signature. The tracer's
// goal_heuristic() method should return a negative value if a node is a
// destination node.
template<class Tracer,
class It,
class NodeMap = std::unordered_map<size_t, QNode<Tracer>>>
bool search_route(const Tracer &tracer,
const TracerNodeT<Tracer> &source,
It out,
NodeMap &&cached_nodes = {})
{
using namespace detail;
using Node = TracerNodeT<Tracer>;
using QNode = QNode<Tracer>;
using TracerTraits = TracerTraits_<remove_cvref_t<Tracer>>;
using Node = TracerNodeT<Tracer>;
enum class QueueType { Open, Closed, None };
struct QNode // Queue node. Keeps track of scores g, and h
{
Node node; // The actual node itself
QueueType qtype = QueueType::None; // Which queue holds this node
float g = 0.f, h = 0.f;
float f() const { return g + h; }
};
// TODO: apply a linear memory allocator
using QMap = std::unordered_map<size_t, QNode>;
// The traversed nodes are stored here encapsulated in QNodes
QMap cached_nodes;
struct LessPred { // Comparison functor needed by MutablePriorityQueue
QMap &m;
struct LessPred { // Comparison functor needed by the priority queue
NodeMap &m;
bool operator ()(size_t node_a, size_t node_b) {
auto ait = m.find(node_a);
auto bit = m.find(node_b);
assert (ait != m.end() && bit != m.end());
return ait->second.f() < bit->second.f();
return m[node_a].f() < m[node_b].f();
}
};
auto qopen =
make_mutable_priority_queue<size_t, false>([](size_t, size_t){},
LessPred{cached_nodes});
auto qopen = make_mutable_priority_queue<size_t, true>(
[&cached_nodes](size_t el, size_t qidx) {
cached_nodes[el].queue_id = qidx;
},
LessPred{cached_nodes});
auto qclosed =
make_mutable_priority_queue<size_t, false>([](size_t, size_t){},
LessPred{cached_nodes});
QNode initial{source, /*parent = */ Unassigned, /*g = */0.f};
size_t source_id = TracerTraits::unique_id(tracer, source);
cached_nodes[source_id] = initial;
qopen.push(source_id);
QNode initial{source, QueueType::Open};
cached_nodes.insert({unique_id(tracer, source), initial});
qopen.push(unique_id(tracer, source));
size_t goal_id = TracerTraits::goal_heuristic(tracer, source) < 0.f ?
source_id :
Unassigned;
bool goal_reached = false;
while (!goal_reached && !qopen.empty()) {
while (goal_id == Unassigned && !qopen.empty()) {
size_t q_id = qopen.top();
qopen.pop();
QNode q = cached_nodes.at(q_id);
QNode &q = cached_nodes[q_id];
foreach_reachable(tracer, q.node, [&](const Node &nd) {
if (goal_reached) return goal_reached;
// This should absolutely be initialized in the cache already
assert(!std::isinf(q.g));
TracerTraits::foreach_reachable(tracer, q.node, [&](const Node &succ_nd) {
if (goal_id != Unassigned)
return true;
float h = TracerTraits::goal_heuristic(tracer, succ_nd);
float dst = TracerTraits::distance(tracer, q.node, succ_nd);
size_t succ_id = TracerTraits::unique_id(tracer, succ_nd);
QNode qsucc_nd{succ_nd, q_id, q.g + dst, h};
float h = goal_heuristic(tracer, nd);
if (h < 0.f) {
goal_reached = true;
goal_id = succ_id;
cached_nodes[succ_id] = qsucc_nd;
} else {
float dst = trace_distance(tracer, q.node, nd);
QNode qnd{nd, QueueType::None, q.g + dst, h};
size_t qnd_id = unique_id(tracer, nd);
// If succ_id is not in cache, it gets created with g = infinity
QNode &prev_nd = cached_nodes[succ_id];
auto it = cached_nodes.find(qnd_id);
if (qsucc_nd.g < prev_nd.g) {
// new route is better, apply it:
if (it == cached_nodes.end() ||
(it->second.qtype != QueueType::None && qnd.f() < it->second.f())) {
qnd.qtype = QueueType::Open;
cached_nodes.insert_or_assign(qnd_id, qnd);
qopen.push(qnd_id);
// Save the old queue id, it would be lost after the next line
size_t queue_id = prev_nd.queue_id;
// The cache needs to be updated either way
prev_nd = qsucc_nd;
if (queue_id == InvalidQueueID)
// was in closed or unqueued, rescheduling
qopen.push(succ_id);
else // was in open, updating
qopen.update(queue_id);
}
}
return goal_reached;
return goal_id != Unassigned;
});
q.qtype = QueueType::Closed;
cached_nodes.insert_or_assign(q_id, q);
qclosed.push(q_id);
// write the output
*out = q.node;
++out;
}
return goal_reached;
// Write the output, do not reverse. Clients can do so if they need to.
if (goal_id != Unassigned) {
const QNode *q = &cached_nodes[goal_id];
while (q->parent != Unassigned) {
assert(!std::isinf(q->g)); // Uninitialized nodes are NOT allowed
*out = q->node;
++out;
q = &cached_nodes[q->parent];
}
}
return goal_id != Unassigned;
}
}} // namespace Slic3r::astar

View File

@ -230,8 +230,13 @@ static std::string appconfig_md5_hash_line(const std::string_view data)
return "# MD5 checksum " + md5_digest_str + "\n";
};
struct ConfigFileInfo {
bool correct_checksum {false};
bool contains_null {false};
};
// Assume that the last line with the comment inside the config file contains a checksum and that the user didn't modify the config file.
static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
static ConfigFileInfo check_config_file_and_verify_checksum(boost::nowide::ifstream &ifs)
{
auto read_whole_config_file = [&ifs]() -> std::string {
std::stringstream ss;
@ -240,7 +245,8 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
};
ifs.seekg(0, boost::nowide::ifstream::beg);
std::string whole_config = read_whole_config_file();
const std::string whole_config = read_whole_config_file();
const bool contains_null = whole_config.find_first_of('\0') != std::string::npos;
// The checksum should be on the last line in the config file.
if (size_t last_comment_pos = whole_config.find_last_of('#'); last_comment_pos != std::string::npos) {
@ -249,9 +255,9 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
// When the checksum isn't found, the checksum was not saved correctly, it was removed or it is an older config file without the checksum.
// If the checksum is incorrect, then the file was either not saved correctly or modified.
if (std::string_view(whole_config.c_str() + last_comment_pos, whole_config.size() - last_comment_pos) == appconfig_md5_hash_line({ whole_config.data(), last_comment_pos }))
return true;
return {true, contains_null};
}
return false;
return {false, contains_null};
}
#endif
@ -269,14 +275,25 @@ std::string AppConfig::load(const std::string &path)
ifs.open(path);
#ifdef WIN32
// Verify the checksum of the config file without taking just for debugging purpose.
if (!verify_config_file_checksum(ifs))
BOOST_LOG_TRIVIAL(info) << "The configuration file " << path <<
" has a wrong MD5 checksum or the checksum is missing. This may indicate a file corruption or a harmless user edit.";
const ConfigFileInfo config_file_info = check_config_file_and_verify_checksum(ifs);
if (!config_file_info.correct_checksum)
BOOST_LOG_TRIVIAL(info)
<< "The configuration file " << path
<< " has a wrong MD5 checksum or the checksum is missing. This may indicate a file corruption or a harmless user edit.";
if (!config_file_info.correct_checksum && config_file_info.contains_null) {
BOOST_LOG_TRIVIAL(info) << "The configuration file " + path + " is corrupted, because it is contains null characters.";
throw Slic3r::CriticalException("The configuration file contains null characters.");
}
ifs.seekg(0, boost::nowide::ifstream::beg);
#endif
pt::read_ini(ifs, tree);
} catch (pt::ptree_error& ex) {
try {
pt::read_ini(ifs, tree);
} catch (pt::ptree_error &ex) {
throw Slic3r::CriticalException(ex.what());
}
} catch (Slic3r::CriticalException &ex) {
#ifdef WIN32
// The configuration file is corrupted, try replacing it with the backup configuration.
ifs.close();
@ -284,29 +301,29 @@ std::string AppConfig::load(const std::string &path)
if (boost::filesystem::exists(backup_path)) {
// Compute checksum of the configuration backup file and try to load configuration from it when the checksum is correct.
boost::nowide::ifstream backup_ifs(backup_path);
if (!verify_config_file_checksum(backup_ifs)) {
BOOST_LOG_TRIVIAL(error) << format("Both \"%1%\" and \"%2%\" are corrupted. It isn't possible to restore configuration from the backup.", path, backup_path);
if (const ConfigFileInfo config_file_info = check_config_file_and_verify_checksum(backup_ifs); !config_file_info.correct_checksum || config_file_info.contains_null) {
BOOST_LOG_TRIVIAL(error) << format(R"(Both "%1%" and "%2%" are corrupted. It isn't possible to restore configuration from the backup.)", path, backup_path);
backup_ifs.close();
boost::filesystem::remove(backup_path);
} else if (std::string error_message; copy_file(backup_path, path, error_message, false) != SUCCESS) {
BOOST_LOG_TRIVIAL(error) << format("Configuration file \"%1%\" is corrupted. Failed to restore from backup \"%2%\": %3%", path, backup_path, error_message);
BOOST_LOG_TRIVIAL(error) << format(R"(Configuration file "%1%" is corrupted. Failed to restore from backup "%2%": %3%)", path, backup_path, error_message);
backup_ifs.close();
boost::filesystem::remove(backup_path);
} else {
BOOST_LOG_TRIVIAL(info) << format("Configuration file \"%1%\" was corrupted. It has been succesfully restored from the backup \"%2%\".", path, backup_path);
BOOST_LOG_TRIVIAL(info) << format(R"(Configuration file "%1%" was corrupted. It has been successfully restored from the backup "%2%".)", path, backup_path);
// Try parse configuration file after restore from backup.
try {
ifs.open(path);
pt::read_ini(ifs, tree);
recovered = true;
} catch (pt::ptree_error& ex) {
BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\" after it has been restored from backup: %2%", path, ex.what());
BOOST_LOG_TRIVIAL(info) << format(R"(Failed to parse configuration file "%1%" after it has been restored from backup: %2%)", path, ex.what());
}
}
} else
#endif // WIN32
BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\": %2%", path, ex.what());
if (! recovered) {
BOOST_LOG_TRIVIAL(info) << format(R"(Failed to parse configuration file "%1%": %2%)", path, ex.what());
if (!recovered) {
// Report the initial error of parsing PrusaSlicer.ini.
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
// ! But to avoid the use of _utf8 (related to use of wxWidgets)

View File

@ -238,7 +238,7 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
const stl_vertex p2 = trafo * its.vertices[tri(iedge)];
assert(sign(p1) == s[iprev]);
assert(sign(p2) == s[iedge]);
assert(p1.z() * p2.z() < 0);
assert((p1.z() - world_min_z) * (p2.z() - world_min_z) < 0);
// Edge crosses the z plane. Calculate intersection point with the plane.
const float t = (world_min_z - p1.z()) / (p2.z() - p1.z());
(is_inside(Vec3f(p1.x() + (p2.x() - p1.x()) * t, p1.y() + (p2.y() - p1.y()) * t, world_min_z)) ? inside : outside) = true;

View File

@ -1,29 +1,34 @@
#include "../Print.hpp"
#include "../ShortestPath.hpp"
#include "FillLightning.hpp"
#include "Lightning/Generator.hpp"
#include "../Surface.hpp"
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <numeric>
namespace Slic3r::FillLightning {
Polylines Filler::fill_surface(const Surface *surface, const FillParams &params)
void Filler::_fill_surface_single(
const FillParams &params,
unsigned int thickness_layers,
const std::pair<float, Point> &direction,
ExPolygon expolygon,
Polylines &polylines_out)
{
const Layer &layer = generator->getTreesForLayer(this->layer_id);
return layer.convertToLines(to_polygons(surface->expolygon), generator->infilll_extrusion_width());
const Layer &layer = generator->getTreesForLayer(this->layer_id);
Polylines fill_lines = layer.convertToLines(to_polygons(expolygon), scaled<coord_t>(0.5 * this->spacing - this->overlap));
if (params.dont_connect() || fill_lines.size() <= 1) {
append(polylines_out, chain_polylines(std::move(fill_lines)));
} else
connect_infill(std::move(fill_lines), expolygon, polylines_out, this->spacing, params);
}
void GeneratorDeleter::operator()(Generator *p) {
delete p;
}
GeneratorPtr build_generator(const PrintObject &print_object)
GeneratorPtr build_generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
return GeneratorPtr(new Generator(print_object));
return GeneratorPtr(new Generator(print_object, throw_on_cancel_callback));
}
} // namespace Slic3r::FillAdaptive

View File

@ -14,7 +14,7 @@ class Generator;
struct GeneratorDeleter { void operator()(Generator *p); };
using GeneratorPtr = std::unique_ptr<Generator, GeneratorDeleter>;
GeneratorPtr build_generator(const PrintObject &print_object);
GeneratorPtr build_generator(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback);
class Filler : public Slic3r::Fill
{
@ -24,8 +24,13 @@ public:
Generator *generator { nullptr };
protected:
Fill* clone() const override { return new Filler(*this); }
// Perform the fill.
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
void _fill_surface_single(const FillParams &params,
unsigned int thickness_layers,
const std::pair<float, Point> &direction,
ExPolygon expolygon,
Polylines &polylines_out) override;
// Let the G-code export reoder the infill lines.
bool no_sort() const override { return false; }
};

View File

@ -3043,14 +3043,18 @@ Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams
return polylines_out;
}
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing)
// Lightning infill assumes that the distance between any two sampled points is always
// at least equal to the value of spacing. To meet this assumption, we need to use
// BoundingBox for whole layers instead of bounding box just around processing ExPolygon.
// Using just BoundingBox around processing ExPolygon could produce two points closer
// than spacing (in cases where two ExPolygon are closer than spacing).
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box)
{
ExPolygonWithOffset poly_with_offset(expolygon, 0, 0, 0);
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
std::vector<SegmentedIntersectionLine> segs = slice_region_by_vertical_lines(
poly_with_offset,
(bounding_box.max.x() - bounding_box.min.x() + spacing - 1) / spacing,
bounding_box.min.x(),
(global_bounding_box.max.x() - global_bounding_box.min.x() + spacing - 1) / spacing,
global_bounding_box.min.x(),
spacing);
Points out;
@ -3066,17 +3070,17 @@ Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing)
return out;
}
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing)
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box)
{
Points out;
for (const ExPolygon &expoly : expolygons)
append(out, sample_grid_pattern(expoly, spacing));
append(out, sample_grid_pattern(expoly, spacing, global_bounding_box));
return out;
}
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing)
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box)
{
return sample_grid_pattern(union_ex(polygons), spacing);
return sample_grid_pattern(union_ex(polygons), spacing, global_bounding_box);
}
} // namespace Slic3r

View File

@ -109,9 +109,9 @@ protected:
float _layer_angle(size_t idx) const override { return 0.f; }
};
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing);
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing);
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing);
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box);
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box);
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box);
} // namespace Slic3r

View File

@ -5,11 +5,36 @@
#include "../FillRectilinear.hpp"
#include "../../ClipperUtils.hpp"
#include <tbb/parallel_for.h>
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
#include "../../SVG.hpp"
#endif
namespace Slic3r::FillLightning
{
constexpr coord_t radius_per_cell_size = 6; // The cell-size should be small compared to the radius, but not so small as to be inefficient.
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
void export_distance_field_to_svg(const std::string &path, const Polygons &outline, const Polygons &overhang, const std::list<DistanceField::UnsupportedCell> &unsupported_points, const Points &points = {})
{
coordf_t stroke_width = scaled<coordf_t>(0.01);
BoundingBox bbox = get_extents(outline);
bbox.offset(SCALED_EPSILON);
SVG svg(path, bbox);
svg.draw_outline(outline, "green", stroke_width);
svg.draw_outline(overhang, "blue", stroke_width);
for (const DistanceField::UnsupportedCell &cell : unsupported_points)
svg.draw(cell.loc, "cyan", coord_t(stroke_width));
for (const Point &pt : points)
svg.draw(pt, "red", coord_t(stroke_width));
}
#endif
DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang) :
m_cell_size(radius / radius_per_cell_size),
m_supporting_radius(radius),
@ -17,37 +42,54 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
{
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
// Sample source polygons with a regular grid sampling pattern.
const BoundingBox overhang_bbox = get_extents(current_overhang);
for (const ExPolygon &expoly : union_ex(current_overhang)) {
for (const Point &p : sample_grid_pattern(expoly, m_cell_size)) {
// Find a squared distance to the source expolygon boundary.
double d2 = std::numeric_limits<double>::max();
for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
d2 = std::min(d2, Line::distance_to_squared(p, prev, p2));
prev = p2;
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
const size_t unsupported_points_prev_size = m_unsupported_points.size();
m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
tbb::parallel_for(tbb::blocked_range<size_t>(0, sampled_points.size()), [&self = *this, &expoly = std::as_const(expoly), &sampled_points = std::as_const(sampled_points), &unsupported_points_prev_size = std::as_const(unsupported_points_prev_size)](const tbb::blocked_range<size_t> &range) -> void {
for (size_t sp_idx = range.begin(); sp_idx < range.end(); ++sp_idx) {
const Point &sp = sampled_points[sp_idx];
// Find a squared distance to the source expolygon boundary.
double d2 = std::numeric_limits<double>::max();
for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) {
const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1];
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
d2 = std::min(d2, Line::distance_to_squared(sp, prev, p2));
prev = p2;
}
}
}
self.m_unsupported_points[unsupported_points_prev_size + sp_idx] = {sp, coord_t(std::sqrt(d2))};
assert(self.m_unsupported_points_bbox.contains(sp));
}
m_unsupported_points.emplace_back(p, sqrt(d2));
assert(m_unsupported_points_bbox.contains(p));
}
}); // end of parallel_for
}
m_unsupported_points.sort([&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
std::stable_sort(m_unsupported_points.begin(), m_unsupported_points.end(), [&radius](const UnsupportedCell &a, const UnsupportedCell &b) {
constexpr coord_t prime_for_hash = 191;
return std::abs(b.dist_to_boundary - a.dist_to_boundary) > radius ?
a.dist_to_boundary < b.dist_to_boundary :
(PointHash{}(a.loc) % prime_for_hash) < (PointHash{}(b.loc) % prime_for_hash);
});
for (auto it = m_unsupported_points.begin(); it != m_unsupported_points.end(); ++it) {
UnsupportedCell& cell = *it;
m_unsupported_points_grid.emplace(this->to_grid_point(cell.loc), it);
}
m_unsupported_points_erased.resize(m_unsupported_points.size());
std::fill(m_unsupported_points_erased.begin(), m_unsupported_points_erased.end(), false);
m_unsupported_points_grid.initialize(m_unsupported_points, [&self = std::as_const(*this)](const Point &p) -> Point { return self.to_grid_point(p); });
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
// in m_unsupported_points_grid contains exactly one point.
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
{
static int iRun = 0;
export_distance_field_to_svg(debug_out_path("FillLightning-DistanceField-%d.svg", iRun++), current_outline, current_overhang, m_unsupported_points);
}
#endif
}
void DistanceField::update(const Point& to_node, const Point& added_leaf)
@ -96,12 +138,11 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf)
}
// Inside a circle at the end of the new leaf, or inside a rotated rectangle.
// Remove unsupported leafs at this grid location.
if (auto it = m_unsupported_points_grid.find(grid_addr); it != m_unsupported_points_grid.end()) {
std::list<UnsupportedCell>::iterator& list_it = it->second;
UnsupportedCell& cell = *list_it;
if (const size_t cell_idx = m_unsupported_points_grid.find_cell_idx(grid_addr); cell_idx != std::numeric_limits<size_t>::max()) {
const UnsupportedCell &cell = m_unsupported_points[cell_idx];
if ((cell.loc - added_leaf).cast<int64_t>().squaredNorm() <= m_supporting_radius2) {
m_unsupported_points.erase(list_it);
m_unsupported_points_grid.erase(it);
m_unsupported_points_erased[cell_idx] = true;
m_unsupported_points_grid.mark_erased(grid_addr);
}
}
}

View File

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

View File

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

View File

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

View File

@ -10,6 +10,10 @@
#include "../../Geometry.hpp"
#include "Utils.hpp"
#include <tbb/parallel_for.h>
#include <tbb/blocked_range2d.h>
#include <mutex>
namespace Slic3r::FillLightning {
coord_t Layer::getWeightedDistance(const Point& boundary_loc, const Point& unsupported_location)
@ -44,18 +48,22 @@ void Layer::generateNewTrees
const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outlines_locator,
const coord_t supporting_radius,
const coord_t wall_supporting_radius
const coord_t wall_supporting_radius,
const std::function<void()> &throw_on_cancel_callback
)
{
DistanceField distance_field(supporting_radius, current_outlines, current_outlines_bbox, current_overhang);
throw_on_cancel_callback();
SparseNodeGrid tree_node_locator;
fillLocator(tree_node_locator, current_outlines_bbox);
// Until no more points need to be added to support all:
// Determine next point from tree/outline areas via distance-field
Point unsupported_location;
while (distance_field.tryGetNextPoint(&unsupported_location)) {
size_t unsupported_cell_idx = 0;
Point unsupported_location;
while (distance_field.tryGetNextPoint(&unsupported_location, &unsupported_cell_idx, unsupported_cell_idx)) {
throw_on_cancel_callback();
GroundingLocation grounding_loc = getBestGroundingLocation(
unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator);
@ -126,9 +134,10 @@ GroundingLocation Layer::getBestGroundingLocation
if (contour.size() > 2) {
Point prev = contour.points.back();
for (const Point &p2 : contour.points) {
if (double d = Line::distance_to_squared(unsupported_location, prev, p2); d < d2) {
Point closest_point;
if (double d = line_alg::distance_to_squared(Line{prev, p2}, unsupported_location, &closest_point); d < d2) {
d2 = d;
node_location = Geometry::foot_pt({ prev, p2 }, unsupported_location).cast<coord_t>();
node_location = closest_point;
}
prev = p2;
}
@ -137,30 +146,52 @@ GroundingLocation Layer::getBestGroundingLocation
const auto within_dist = coord_t((node_location - unsupported_location).cast<double>().norm());
NodeSPtr sub_tree{ nullptr };
coord_t current_dist = getWeightedDistance(node_location, unsupported_location);
NodeSPtr sub_tree{nullptr};
coord_t current_dist = getWeightedDistance(node_location, unsupported_location);
if (current_dist >= wall_supporting_radius) { // Only reconnect tree roots to other trees if they are not already close to the outlines.
const coord_t search_radius = std::min(current_dist, within_dist);
BoundingBox region(unsupported_location - Point(search_radius, search_radius), unsupported_location + Point(search_radius + locator_cell_size, search_radius + locator_cell_size));
region.min = to_grid_point(region.min, current_outlines_bbox);
region.max = to_grid_point(region.max, current_outlines_bbox);
Point grid_addr;
for (grid_addr.y() = region.min.y(); grid_addr.y() < region.max.y(); ++ grid_addr.y())
for (grid_addr.x() = region.min.x(); grid_addr.x() < region.max.x(); ++ grid_addr.x()) {
auto it_range = tree_node_locator.equal_range(grid_addr);
for (auto it = it_range.first; it != it_range.second; ++ it) {
auto candidate_sub_tree = it->second.lock();
if ((candidate_sub_tree && candidate_sub_tree != exclude_tree) &&
!(exclude_tree && exclude_tree->hasOffspring(candidate_sub_tree)) &&
!polygonCollidesWithLineSegment(unsupported_location, candidate_sub_tree->getLocation(), outline_locator)) {
const coord_t candidate_dist = candidate_sub_tree->getWeightedDistance(unsupported_location, supporting_radius);
if (candidate_dist < current_dist) {
current_dist = candidate_dist;
sub_tree = candidate_sub_tree;
Point current_dist_grid_addr{std::numeric_limits<coord_t>::lowest(), std::numeric_limits<coord_t>::lowest()};
std::mutex current_dist_mutex;
tbb::parallel_for(tbb::blocked_range2d<coord_t>(region.min.y(), region.max.y(), region.min.x(), region.max.x()), [&current_dist, current_dist_copy = current_dist, &current_dist_mutex, &sub_tree, &current_dist_grid_addr, &exclude_tree = std::as_const(exclude_tree), &outline_locator = std::as_const(outline_locator), &supporting_radius = std::as_const(supporting_radius), &tree_node_locator = std::as_const(tree_node_locator), &unsupported_location = std::as_const(unsupported_location)](const tbb::blocked_range2d<coord_t> &range) -> void {
for (coord_t grid_addr_y = range.rows().begin(); grid_addr_y < range.rows().end(); ++grid_addr_y)
for (coord_t grid_addr_x = range.cols().begin(); grid_addr_x < range.cols().end(); ++grid_addr_x) {
const Point local_grid_addr{grid_addr_x, grid_addr_y};
NodeSPtr local_sub_tree{nullptr};
coord_t local_current_dist = current_dist_copy;
const auto it_range = tree_node_locator.equal_range(local_grid_addr);
for (auto it = it_range.first; it != it_range.second; ++it) {
const NodeSPtr candidate_sub_tree = it->second.lock();
if ((candidate_sub_tree && candidate_sub_tree != exclude_tree) &&
!(exclude_tree && exclude_tree->hasOffspring(candidate_sub_tree)) &&
!polygonCollidesWithLineSegment(unsupported_location, candidate_sub_tree->getLocation(), outline_locator)) {
if (const coord_t candidate_dist = candidate_sub_tree->getWeightedDistance(unsupported_location, supporting_radius); candidate_dist < local_current_dist) {
local_current_dist = candidate_dist;
local_sub_tree = candidate_sub_tree;
}
}
}
// To always get the same result in a parallel version as in a non-parallel version,
// we need to preserve that for the same current_dist, we select the same sub_tree
// as in the non-parallel version. For this purpose, inside the variable
// current_dist_grid_addr is stored from with 2D grid position assigned sub_tree comes.
// And when there are two sub_tree with the same current_dist, one which will be found
// the first in the non-parallel version is selected.
{
std::lock_guard<std::mutex> lock(current_dist_mutex);
if (local_current_dist < current_dist ||
(local_current_dist == current_dist && (grid_addr_y < current_dist_grid_addr.y() ||
(grid_addr_y == current_dist_grid_addr.y() && grid_addr_x < current_dist_grid_addr.x())))) {
current_dist = local_current_dist;
sub_tree = local_sub_tree;
current_dist_grid_addr = local_grid_addr;
}
}
}
}
}); // end of parallel_for
}
return ! sub_tree ?
@ -402,15 +433,14 @@ static unsigned int moveInside(const Polygons& polygons, Point& from, int distan
}
#endif
// Returns 'added someting'.
Polylines Layer::convertToLines(const Polygons& limit_to_outline, const coord_t line_width) const
Polylines Layer::convertToLines(const Polygons& limit_to_outline, const coord_t line_overlap) const
{
if (tree_roots.empty())
return {};
Polylines result_lines;
for (const auto &tree : tree_roots)
tree->convertToPolylines(result_lines, line_width);
tree->convertToPolylines(result_lines, line_overlap);
return intersection_pl(result_lines, limit_to_outline);
}

View File

@ -44,7 +44,8 @@ public:
const BoundingBox& current_outlines_bbox,
const EdgeGrid::Grid& outline_locator,
coord_t supporting_radius,
coord_t wall_supporting_radius
coord_t wall_supporting_radius,
const std::function<void()> &throw_on_cancel_callback
);
/*! Determine & connect to connection point in tree/outline.
@ -79,7 +80,7 @@ public:
coord_t wall_supporting_radius
);
Polylines convertToLines(const Polygons& limit_to_outline, coord_t line_width) const;
Polylines convertToLines(const Polygons& limit_to_outline, coord_t line_overlap) const;
coord_t getWeightedDistance(const Point& boundary_loc, const Point& unsupported_location);

View File

@ -180,7 +180,11 @@ bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeG
} visitor { outline_locator, a.cast<double>(), b.cast<double>() };
outline_locator.visit_cells_intersecting_line(a, b, visitor);
return visitor.d2min < double(within_max_dist) * double(within_max_dist);
if (visitor.d2min < double(within_max_dist) * double(within_max_dist)) {
result = Point(visitor.intersection_pt);
return true;
}
return false;
}
bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locator, std::vector<NodeSPtr>& rerooted_parts)
@ -343,12 +347,12 @@ coord_t Node::prune(const coord_t& pruning_distance)
return max_distance_pruned;
}
void Node::convertToPolylines(Polylines &output, const coord_t line_width) const
void Node::convertToPolylines(Polylines &output, const coord_t line_overlap) const
{
Polylines result;
result.emplace_back();
convertToPolylines(0, result);
removeJunctionOverlap(result, line_width);
removeJunctionOverlap(result, line_overlap);
append(output, std::move(result));
}
@ -372,10 +376,10 @@ void Node::convertToPolylines(size_t long_line_idx, Polylines &output) const
}
}
void Node::removeJunctionOverlap(Polylines &result_lines, const coord_t line_width) const
void Node::removeJunctionOverlap(Polylines &result_lines, const coord_t line_overlap) const
{
const coord_t reduction = line_width / 2; // TODO make configurable?
size_t res_line_idx = 0;
const coord_t reduction = line_overlap;
size_t res_line_idx = 0;
while (res_line_idx < result_lines.size()) {
Polyline &polyline = result_lines[res_line_idx];
if (polyline.size() <= 1) {

View File

@ -46,7 +46,7 @@ public:
{
struct EnableMakeShared : public Node
{
EnableMakeShared(Arg&&...arg) : Node(std::forward<Arg>(arg)...) {}
explicit EnableMakeShared(Arg&&...arg) : Node(std::forward<Arg>(arg)...) {}
};
return std::make_shared<EnableMakeShared>(std::forward<Arg>(arg)...);
}
@ -179,16 +179,16 @@ public:
*/
bool hasOffspring(const NodeSPtr& to_be_checked) const;
protected:
Node() = delete; // Don't allow empty contruction
protected:
/*!
* Construct a new node, either for insertion in a tree or as root.
* \param p The physical location in the 2D layer that this node represents.
* Connecting other nodes to this node indicates that a line segment should
* be drawn between those two physical positions.
*/
Node(const Point& p, const std::optional<Point>& last_grounding_location = std::nullopt);
explicit Node(const Point& p, const std::optional<Point>& last_grounding_location = std::nullopt);
/*!
* Copy this node and its entire sub-tree.
@ -239,7 +239,7 @@ public:
*
* \param output all branches in this tree connected into polylines
*/
void convertToPolylines(Polylines &output, coord_t line_width) const;
void convertToPolylines(Polylines &output, coord_t line_overlap) const;
/*! If this was ever a direct child of the root, it'll have a previous grounding location.
*
@ -260,7 +260,7 @@ protected:
*/
void convertToPolylines(size_t long_line_idx, Polylines &output) const;
void removeJunctionOverlap(Polylines &polylines, coord_t line_width) const;
void removeJunctionOverlap(Polylines &polylines, coord_t line_overlap) const;
bool m_is_root;
Point m_p;
@ -269,6 +269,9 @@ protected:
std::optional<Point> m_last_grounding_location; //<! The last known grounding location, see 'getLastGroundingLocation()'.
friend BoundingBox get_extents(const NodeSPtr &root_node);
friend BoundingBox get_extents(const std::vector<NodeSPtr> &tree_roots);
#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
friend void export_to_svg(const NodeSPtr &root_node, Slic3r::SVG &svg);
friend void export_to_svg(const std::string &path, const Polygons &contour, const std::vector<NodeSPtr> &root_nodes);
@ -278,6 +281,23 @@ protected:
bool inside(const Polygons &polygons, const Point &p);
bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, coord_t within_max_dist);
inline BoundingBox get_extents(const NodeSPtr &root_node)
{
BoundingBox bbox;
for (const NodeSPtr &children : root_node->m_children)
bbox.merge(get_extents(children));
bbox.merge(root_node->getLocation());
return bbox;
}
inline BoundingBox get_extents(const std::vector<NodeSPtr> &tree_roots)
{
BoundingBox bbox;
for (const NodeSPtr &root_node : tree_roots)
bbox.merge(get_extents(root_node));
return bbox;
}
#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT
void export_to_svg(const NodeSPtr &root_node, SVG &svg);
void export_to_svg(const std::string &path, const Polygons &contour, const std::vector<NodeSPtr> &root_nodes);

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,8 @@
#include "SVG.hpp"
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_observer.h>
#include <tbb/enumerable_thread_specific.h>
// Intel redesigned some TBB interface considerably when merging TBB with their oneAPI set of libraries, see GH #7332.
// We are using quite an old TBB 2017 U7. Before we update our build servers, let's use the old API, which is deprecated in up to date TBB.
@ -1488,6 +1490,32 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
print.throw_if_canceled();
}
// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread
// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned.
// So in this class method on_scheduler_entry is called for every thread before it starts participating
// in tbb::parallel_pipeline to ensure that locales are set correctly
// For tbb::parallel_pipeline, it seems that on_scheduler_entry is called for every layer and every filter.
// We ensure using thread-local storage that locales will be set to "C" just once for any participating thread.
class TBBLocalesSetter : public tbb::task_scheduler_observer
{
public:
TBBLocalesSetter() { this->observe(true); }
~TBBLocalesSetter() override { this->observe(false); };
void on_scheduler_entry(bool is_worker) override
{
if (bool &is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) {
// Set locales of the worker thread to "C".
set_c_locales();
is_locales_sets = true;
}
}
private:
tbb::enumerable_thread_specific<bool, tbb::cache_aligned_allocator<bool>, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{false};
};
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.
@ -1531,6 +1559,10 @@ void GCode::process_layers(
[&output_stream](std::string s) { output_stream.write(s); }
);
// It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline.
// Handler is unregistered when the destructor is called.
TBBLocalesSetter locales_setter;
// The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress();
if (m_spiral_vase && m_find_replace)
@ -1584,6 +1616,10 @@ void GCode::process_layers(
[&output_stream](std::string s) { output_stream.write(s); }
);
// It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline.
// Handler is unregistered when the destructor is called.
TBBLocalesSetter locales_setter;
// The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress();
if (m_spiral_vase && m_find_replace)

View File

@ -313,9 +313,60 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
return transform;
}
void assemble_transform(Transform3d& transform, const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror)
{
transform = translation * rotation * scale * mirror;
}
Transform3d assemble_transform(const Transform3d& translation, const Transform3d& rotation, const Transform3d& scale, const Transform3d& mirror)
{
Transform3d transform;
assemble_transform(transform, translation, rotation, scale, mirror);
return transform;
}
void translation_transform(Transform3d& transform, const Vec3d& translation)
{
transform = Transform3d::Identity();
transform.translate(translation);
}
Transform3d translation_transform(const Vec3d& translation)
{
Transform3d transform;
translation_transform(transform, translation);
return transform;
}
void rotation_transform(Transform3d& transform, const Vec3d& rotation)
{
transform = Transform3d::Identity();
transform.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()) * Eigen::AngleAxisd(rotation.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(rotation.x(), Vec3d::UnitX()));
}
Transform3d rotation_transform(const Vec3d& rotation)
{
Transform3d transform;
rotation_transform(transform, rotation);
return transform;
}
void scale_transform(Transform3d& transform, const Vec3d& scale)
{
transform = Transform3d::Identity();
transform.scale(scale);
}
Transform3d scale_transform(const Vec3d& scale)
{
Transform3d transform;
scale_transform(transform, scale);
return transform;
}
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
{
// reference: http://www.gregslabaugh.net/publications/euler.pdf
// reference: http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf
Vec3d angles1 = Vec3d::Zero();
Vec3d angles2 = Vec3d::Zero();
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5) {
@ -363,6 +414,54 @@ Vec3d extract_euler_angles(const Transform3d& transform)
return extract_euler_angles(m);
}
#if ENABLE_WORLD_COORDINATE
Transform3d Transformation::get_offset_matrix() const
{
return assemble_transform(get_offset());
}
static Transform3d extract_rotation(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return Transform3d(rotation);
}
static Transform3d extract_scale(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return Transform3d(scale);
}
static std::pair<Transform3d, Transform3d> extract_rotation_scale(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return { Transform3d(rotation), Transform3d(scale) };
}
static bool contains_skew(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return !scale.isDiagonal();
}
Vec3d Transformation::get_rotation() const
{
return extract_euler_angles(extract_rotation(m_matrix));
}
Transform3d Transformation::get_rotation_matrix() const
{
return extract_rotation(m_matrix);
}
#else
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
{
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror);
@ -400,12 +499,19 @@ void Transformation::set_offset(Axis axis, double offset)
m_dirty = true;
}
}
#endif // ENABLE_WORLD_COORDINATE
void Transformation::set_rotation(const Vec3d& rotation)
{
#if ENABLE_WORLD_COORDINATE
const Vec3d offset = get_offset();
m_matrix = rotation_transform(rotation) * extract_scale(m_matrix);
m_matrix.translation() = offset;
#else
set_rotation(X, rotation.x());
set_rotation(Y, rotation.y());
set_rotation(Z, rotation.z());
#endif // ENABLE_WORLD_COORDINATE
}
void Transformation::set_rotation(Axis axis, double rotation)
@ -414,32 +520,106 @@ void Transformation::set_rotation(Axis axis, double rotation)
if (is_approx(std::abs(rotation), 2.0 * double(PI)))
rotation = 0.0;
#if ENABLE_WORLD_COORDINATE
auto [curr_rotation, scale] = extract_rotation_scale(m_matrix);
Vec3d angles = extract_euler_angles(curr_rotation);
angles[axis] = rotation;
const Vec3d offset = get_offset();
m_matrix = rotation_transform(angles) * scale;
m_matrix.translation() = offset;
#else
if (m_rotation(axis) != rotation) {
m_rotation(axis) = rotation;
m_dirty = true;
}
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
Vec3d Transformation::get_scaling_factor() const
{
const Transform3d scale = extract_scale(m_matrix);
return { scale(0, 0), scale(1, 1), scale(2, 2) };
}
Transform3d Transformation::get_scaling_factor_matrix() const
{
return extract_scale(m_matrix);
}
#endif // ENABLE_WORLD_COORDINATE
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
{
#if ENABLE_WORLD_COORDINATE
assert(scaling_factor.x() > 0.0 && scaling_factor.y() > 0.0 && scaling_factor.z() > 0.0);
const Vec3d offset = get_offset();
m_matrix = extract_rotation(m_matrix) * scale_transform(scaling_factor);
m_matrix.translation() = offset;
#else
set_scaling_factor(X, scaling_factor.x());
set_scaling_factor(Y, scaling_factor.y());
set_scaling_factor(Z, scaling_factor.z());
#endif // ENABLE_WORLD_COORDINATE
}
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
{
#if ENABLE_WORLD_COORDINATE
assert(scaling_factor > 0.0);
auto [rotation, scale] = extract_rotation_scale(m_matrix);
scale(axis, axis) = scaling_factor;
const Vec3d offset = get_offset();
m_matrix = rotation * scale;
m_matrix.translation() = offset;
#else
if (m_scaling_factor(axis) != std::abs(scaling_factor)) {
m_scaling_factor(axis) = std::abs(scaling_factor);
m_dirty = true;
}
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
Vec3d Transformation::get_mirror() const
{
const Transform3d scale = extract_scale(m_matrix);
return { scale(0, 0) / std::abs(scale(0, 0)), scale(1, 1) / std::abs(scale(1, 1)), scale(2, 2) / std::abs(scale(2, 2)) };
}
Transform3d Transformation::get_mirror_matrix() const
{
const Vec3d scale = get_scaling_factor();
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
}
#endif // ENABLE_WORLD_COORDINATE
void Transformation::set_mirror(const Vec3d& mirror)
{
#if ENABLE_WORLD_COORDINATE
Vec3d copy(mirror);
const Vec3d abs_mirror = copy.cwiseAbs();
for (int i = 0; i < 3; ++i) {
if (abs_mirror(i) == 0.0)
copy(i) = 1.0;
else if (abs_mirror(i) != 1.0)
copy(i) /= abs_mirror(i);
}
const Vec3d curr_scale = get_scaling_factor();
const Vec3d signs = curr_scale.cwiseProduct(copy);
set_scaling_factor({
signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(),
signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(),
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
});
#else
set_mirror(X, mirror.x());
set_mirror(Y, mirror.y());
set_mirror(Z, mirror.z());
#endif // ENABLE_WORLD_COORDINATE
}
void Transformation::set_mirror(Axis axis, double mirror)
@ -450,12 +630,24 @@ void Transformation::set_mirror(Axis axis, double mirror)
else if (abs_mirror != 1.0)
mirror /= abs_mirror;
#if ENABLE_WORLD_COORDINATE
const double curr_scale = get_scaling_factor(axis);
const double sign = curr_scale * mirror;
set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale);
#else
if (m_mirror(axis) != mirror) {
m_mirror(axis) = mirror;
m_dirty = true;
}
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
bool Transformation::has_skew() const
{
return contains_skew(m_matrix);
}
#else
void Transformation::set_from_transform(const Transform3d& transform)
{
// offset
@ -493,17 +685,62 @@ void Transformation::set_from_transform(const Transform3d& transform)
// if (!m_matrix.isApprox(transform))
// std::cout << "something went wrong in extracting data from matrix" << std::endl;
}
#endif // ENABLE_WORLD_COORDINATE
void Transformation::reset()
{
#if !ENABLE_WORLD_COORDINATE
m_offset = Vec3d::Zero();
m_rotation = Vec3d::Zero();
m_scaling_factor = Vec3d::Ones();
m_mirror = Vec3d::Ones();
#endif // !ENABLE_WORLD_COORDINATE
m_matrix = Transform3d::Identity();
#if !ENABLE_WORLD_COORDINATE
m_dirty = false;
#endif // !ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
void Transformation::reset_skew()
{
Matrix3d rotation;
Matrix3d scale;
m_matrix.computeRotationScaling(&rotation, &scale);
const double average_scale = std::cbrt(scale(0, 0) * scale(1, 1) * scale(2, 2));
scale(0, 0) = average_scale;
scale(1, 1) = average_scale;
scale(2, 2) = average_scale;
scale(0, 1) = 0.0;
scale(0, 2) = 0.0;
scale(1, 0) = 0.0;
scale(1, 2) = 0.0;
scale(2, 0) = 0.0;
scale(2, 1) = 0.0;
const Vec3d offset = get_offset();
m_matrix = rotation * scale;
m_matrix.translation() = offset;
}
Transform3d Transformation::get_matrix_no_offset() const
{
Transformation copy(*this);
copy.reset_offset();
return copy.get_matrix();
}
Transform3d Transformation::get_matrix_no_scaling_factor() const
{
Transformation copy(*this);
copy.reset_scaling_factor();
copy.reset_mirror();
return copy.get_matrix();
}
#else
const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
{
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) {
@ -520,12 +757,14 @@ const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rot
return m_matrix;
}
#endif // ENABLE_WORLD_COORDINATE
Transformation Transformation::operator * (const Transformation& other) const
{
return Transformation(get_matrix() * other.get_matrix());
}
#if !ENABLE_WORLD_COORDINATE
Transformation Transformation::volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox)
{
Transformation out;
@ -571,8 +810,7 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
out.set_scaling_factor(Vec3d(std::abs(scale.x()), std::abs(scale.y()), std::abs(scale.z())));
out.set_mirror(Vec3d(scale.x() > 0 ? 1. : -1, scale.y() > 0 ? 1. : -1, scale.z() > 0 ? 1. : -1));
}
else
{
else {
// General anisotropic scaling, general rotation.
// Keep the modifier mesh in the instance coordinate system, so the modifier mesh will not be aligned with the world.
// Scale it to get the required size.
@ -581,6 +819,7 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
return out;
}
#endif // !ENABLE_WORLD_COORDINATE
// For parsing a transformation matrix from 3MF / AMF.
Transform3d transform3d_from_string(const std::string& transform_str)
@ -619,7 +858,7 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
const Vec3d axis = angle_axis.axis();
const Vec3d& axis = angle_axis.axis();
const double angle = angle_axis.angle();
#ifndef NDEBUG
if (std::abs(angle) > 1e-8) {

View File

@ -323,7 +323,8 @@ bool arrange(
// 4) rotate Y
// 5) rotate Z
// 6) translate
void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(),
const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
// Returns the transform obtained by assembling the given transformations in the following order:
// 1) mirror
@ -332,7 +333,43 @@ void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d
// 4) rotate Y
// 5) rotate Z
// 6) translate
Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(),
const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones());
// Sets the given transform by multiplying the given transformations in the following order:
// T = translation * rotation * scale * mirror
void assemble_transform(Transform3d& transform, const Transform3d& translation = Transform3d::Identity(),
const Transform3d& rotation = Transform3d::Identity(), const Transform3d& scale = Transform3d::Identity(),
const Transform3d& mirror = Transform3d::Identity());
// Returns the transform obtained by multiplying the given transformations in the following order:
// T = translation * rotation * scale * mirror
Transform3d assemble_transform(const Transform3d& translation = Transform3d::Identity(), const Transform3d& rotation = Transform3d::Identity(),
const Transform3d& scale = Transform3d::Identity(), const Transform3d& mirror = Transform3d::Identity());
// Sets the given transform by assembling the given translation
void translation_transform(Transform3d& transform, const Vec3d& translation);
// Returns the transform obtained by assembling the given translation
Transform3d translation_transform(const Vec3d& translation);
// Sets the given transform by assembling the given rotations in the following order:
// 1) rotate X
// 2) rotate Y
// 3) rotate Z
void rotation_transform(Transform3d& transform, const Vec3d& rotation);
// Returns the transform obtained by assembling the given rotations in the following order:
// 1) rotate X
// 2) rotate Y
// 3) rotate Z
Transform3d rotation_transform(const Vec3d& rotation);
// Sets the given transform by assembling the given scale factors
void scale_transform(Transform3d& transform, const Vec3d& scale);
// Returns the transform obtained by assembling the given scale factors
Transform3d scale_transform(const Vec3d& scale);
// Returns the euler angles extracted from the given rotation matrix
// Warning -> The matrix should not contain any scale or shear !!!
@ -344,6 +381,9 @@ Vec3d extract_euler_angles(const Transform3d& transform);
class Transformation
{
#if ENABLE_WORLD_COORDINATE
Transform3d m_matrix{ Transform3d::Identity() };
#else
struct Flags
{
bool dont_translate{ true };
@ -363,8 +403,26 @@ class Transformation
mutable Transform3d m_matrix{ Transform3d::Identity() };
mutable Flags m_flags;
mutable bool m_dirty{ false };
#endif // ENABLE_WORLD_COORDINATE
public:
#if ENABLE_WORLD_COORDINATE
Transformation() = default;
explicit Transformation(const Transform3d& transform) : m_matrix(transform) {}
Vec3d get_offset() const { return m_matrix.translation(); }
double get_offset(Axis axis) const { return get_offset()[axis]; }
Transform3d get_offset_matrix() const;
void set_offset(const Vec3d& offset) { m_matrix.translation() = offset; }
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
Vec3d get_rotation() const;
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
Transform3d get_rotation_matrix() const;
#else
Transformation();
explicit Transformation(const Transform3d& transform);
@ -376,47 +434,103 @@ public:
const Vec3d& get_rotation() const { return m_rotation; }
double get_rotation(Axis axis) const { return m_rotation(axis); }
#endif // ENABLE_WORLD_COORDINATE
void set_rotation(const Vec3d& rotation);
void set_rotation(Axis axis, double rotation);
#if ENABLE_WORLD_COORDINATE
Vec3d get_scaling_factor() const;
double get_scaling_factor(Axis axis) const { return get_scaling_factor()[axis]; }
Transform3d get_scaling_factor_matrix() const;
bool is_scaling_uniform() const {
const Vec3d scale = get_scaling_factor();
return std::abs(scale.x() - scale.y()) < 1e-8 && std::abs(scale.x() - scale.z()) < 1e-8;
}
#else
const Vec3d& get_scaling_factor() const { return m_scaling_factor; }
double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); }
#endif // ENABLE_WORLD_COORDINATE
void set_scaling_factor(const Vec3d& scaling_factor);
void set_scaling_factor(Axis axis, double scaling_factor);
#if ENABLE_WORLD_COORDINATE
Vec3d get_mirror() const;
double get_mirror(Axis axis) const { return get_mirror()[axis]; }
Transform3d get_mirror_matrix() const;
bool is_left_handed() const {
const Vec3d mirror = get_mirror();
return mirror.x() * mirror.y() * mirror.z() < 0.0;
}
#else
bool is_scaling_uniform() const { return std::abs(m_scaling_factor.x() - m_scaling_factor.y()) < 1e-8 && std::abs(m_scaling_factor.x() - m_scaling_factor.z()) < 1e-8; }
const Vec3d& get_mirror() const { return m_mirror; }
double get_mirror(Axis axis) const { return m_mirror(axis); }
bool is_left_handed() const { return m_mirror.x() * m_mirror.y() * m_mirror.z() < 0.; }
#endif // ENABLE_WORLD_COORDINATE
void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror);
#if ENABLE_WORLD_COORDINATE
bool has_skew() const;
#else
void set_from_transform(const Transform3d& transform);
#endif // ENABLE_WORLD_COORDINATE
void reset();
#if ENABLE_WORLD_COORDINATE
void reset_offset() { set_offset(Vec3d::Zero()); }
void reset_rotation() { set_rotation(Vec3d::Zero()); }
void reset_scaling_factor() { set_scaling_factor(Vec3d::Ones()); }
void reset_mirror() { set_mirror(Vec3d::Ones()); }
void reset_skew();
const Transform3d& get_matrix() const { return m_matrix; }
Transform3d get_matrix_no_offset() const;
Transform3d get_matrix_no_scaling_factor() const;
void set_matrix(const Transform3d& transform) { m_matrix = transform; }
#else
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
#endif // ENABLE_WORLD_COORDINATE
Transformation operator * (const Transformation& other) const;
#if !ENABLE_WORLD_COORDINATE
// Find volume transformation, so that the chained (instance_trafo * volume_trafo) will be as close to identity
// as possible in least squares norm in regard to the 8 corners of bbox.
// Bounding box is expected to be centered around zero in all axes.
static Transformation volume_to_bed_transformation(const Transformation& instance_transformation, const BoundingBoxf3& bbox);
#endif // !ENABLE_WORLD_COORDINATE
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) { ar(m_offset, m_rotation, m_scaling_factor, m_mirror); }
explicit Transformation(int) : m_dirty(true) {}
template <class Archive> static void load_and_construct(Archive &ar, cereal::construct<Transformation> &construct)
{
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
construct(1);
ar(construct.ptr()->m_offset, construct.ptr()->m_rotation, construct.ptr()->m_scaling_factor, construct.ptr()->m_mirror);
}
friend class cereal::access;
#if ENABLE_WORLD_COORDINATE
template<class Archive> void serialize(Archive& ar) { ar(m_matrix); }
explicit Transformation(int) {}
template <class Archive> static void load_and_construct(Archive& ar, cereal::construct<Transformation>& construct)
{
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
construct(1);
ar(construct.ptr()->m_matrix);
}
#else
template<class Archive> void serialize(Archive& ar) { ar(m_offset, m_rotation, m_scaling_factor, m_mirror); }
explicit Transformation(int) : m_dirty(true) {}
template <class Archive> static void load_and_construct(Archive& ar, cereal::construct<Transformation>& construct)
{
// Calling a private constructor with special "int" parameter to indicate that no construction is necessary.
construct(1);
ar(construct.ptr()->m_offset, construct.ptr()->m_rotation, construct.ptr()->m_scaling_factor, construct.ptr()->m_mirror);
}
#endif // ENABLE_WORLD_COORDINATE
};
// For parsing a transformation matrix from 3MF / AMF.

View File

@ -43,6 +43,25 @@ std::string float_to_string_decimal_point(double value, int precision = -1);
//std::string float_to_string_decimal_point(float value, int precision = -1);
double string_to_double_decimal_point(const std::string_view str, size_t* pos = nullptr);
// Set locales to "C".
inline void set_c_locales()
{
#ifdef _WIN32
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
std::setlocale(LC_ALL, "C");
#else
// We are leaking some memory here, because the newlocale() produced memory will never be released.
// This is not a problem though, as there will be a maximum one worker thread created per physical thread.
uselocale(newlocale(
#ifdef __APPLE__
LC_ALL_MASK
#else // some Unix / Linux / BSD
LC_ALL
#endif
, "C", nullptr));
#endif
}
} // namespace Slic3r
#endif // slic3r_LocalesUtils_hpp_

View File

@ -947,7 +947,11 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
if (this->instances.empty())
throw Slic3r::InvalidArgument("Can't call raw_bounding_box() with no instances");
#if ENABLE_WORLD_COORDINATE
const Transform3d inst_matrix = this->instances.front()->get_transformation().get_matrix_no_offset();
#else
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
#endif // ENABLE_WORLD_COORDINATE
for (const ModelVolume *v : this->volumes)
if (v->is_model_part())
m_raw_bounding_box.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
@ -959,9 +963,15 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
{
BoundingBoxf3 bb;
#if ENABLE_WORLD_COORDINATE
const Transform3d inst_matrix = dont_translate ?
this->instances[instance_idx]->get_transformation().get_matrix_no_offset() :
this->instances[instance_idx]->get_transformation().get_matrix();
#else
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
for (ModelVolume *v : this->volumes)
{
#endif // ENABLE_WORLD_COORDINATE
for (ModelVolume *v : this->volumes) {
if (v->is_model_part())
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
}
@ -1730,9 +1740,12 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
new_object->add_instance(*model_instance);
ModelVolume* new_vol = new_object->add_volume(*volume, std::move(mesh));
for (ModelInstance* model_instance : new_object->instances)
{
for (ModelInstance* model_instance : new_object->instances) {
#if ENABLE_WORLD_COORDINATE
Vec3d shift = model_instance->get_transformation().get_matrix_no_offset() * new_vol->get_offset();
#else
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
#endif // ENABLE_WORLD_COORDINATE
model_instance->set_offset(model_instance->get_offset() + shift);
}
@ -1774,9 +1787,11 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
assert(instance_idx < this->instances.size());
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
#if !ENABLE_WORLD_COORDINATE
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
return;
#endif // !ENABLE_WORLD_COORDINATE
bool left_handed = reference_trafo.is_left_handed();
bool has_mirrorring = ! reference_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.));
@ -1794,8 +1809,18 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
// Adjust the meshes.
// Transformation to be applied to the meshes.
#if ENABLE_WORLD_COORDINATE
Geometry::Transformation reference_trafo_mod = reference_trafo;
reference_trafo_mod.reset_offset();
if (uniform_scaling)
reference_trafo_mod.reset_scaling_factor();
if (!has_mirrorring)
reference_trafo_mod.reset_mirror();
Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo_mod.get_matrix().matrix().block<3, 3>(0, 0);
#else
Eigen::Matrix3d mesh_trafo_3x3 = reference_trafo.get_matrix(true, false, uniform_scaling, ! has_mirrorring).matrix().block<3, 3>(0, 0);
Transform3d volume_offset_correction = this->instances[instance_idx]->get_transformation().get_matrix().inverse() * reference_trafo.get_matrix();
#endif // ENABLE_WORLD_COORDINATE
Transform3d volume_offset_correction = this->instances[instance_idx]->get_transformation().get_matrix().inverse() * reference_trafo.get_matrix();
for (ModelVolume *model_volume : this->volumes) {
const Geometry::Transformation volume_trafo = model_volume->get_transformation();
bool volume_left_handed = volume_trafo.is_left_handed();
@ -1804,7 +1829,17 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
std::abs(volume_trafo.get_scaling_factor().x() - volume_trafo.get_scaling_factor().z()) < EPSILON;
double volume_new_scaling_factor = volume_uniform_scaling ? volume_trafo.get_scaling_factor().x() : 1.;
// Transform the mesh.
Matrix3d volume_trafo_3x3 = volume_trafo.get_matrix(true, false, volume_uniform_scaling, !volume_has_mirrorring).matrix().block<3, 3>(0, 0);
#if ENABLE_WORLD_COORDINATE
Geometry::Transformation volume_trafo_mod = volume_trafo;
volume_trafo_mod.reset_offset();
if (volume_uniform_scaling)
volume_trafo_mod.reset_scaling_factor();
if (!volume_has_mirrorring)
volume_trafo_mod.reset_mirror();
Eigen::Matrix3d volume_trafo_3x3 = volume_trafo_mod.get_matrix().matrix().block<3, 3>(0, 0);
#else
Matrix3d volume_trafo_3x3 = volume_trafo.get_matrix(true, false, volume_uniform_scaling, !volume_has_mirrorring).matrix().block<3, 3>(0, 0);
#endif // ENABLE_WORLD_COORDINATE
// Following method creates a new shared_ptr<TriangleMesh>
model_volume->transform_this_mesh(mesh_trafo_3x3 * volume_trafo_3x3, left_handed != volume_left_handed);
// Reset the rotation, scaling and mirroring.
@ -1851,7 +1886,11 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
double min_z = DBL_MAX;
const ModelInstance* inst = instances[instance_idx];
#if ENABLE_WORLD_COORDINATE
const Transform3d mi = inst->get_matrix_no_offset();
#else
const Transform3d& mi = inst->get_matrix(true);
#endif // ENABLE_WORLD_COORDINATE
for (const ModelVolume* v : volumes) {
if (!v->is_model_part())
@ -1872,7 +1911,11 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
double max_z = -DBL_MAX;
const ModelInstance* inst = instances[instance_idx];
#if ENABLE_WORLD_COORDINATE
const Transform3d mi = inst->get_matrix_no_offset();
#else
const Transform3d& mi = inst->get_matrix(true);
#endif // ENABLE_WORLD_COORDINATE
for (const ModelVolume* v : volumes) {
if (!v->is_model_part())
@ -2298,14 +2341,22 @@ void ModelVolume::convert_from_meters()
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
{
#if ENABLE_WORLD_COORDINATE
mesh->transform(dont_translate ? get_matrix_no_offset() : get_matrix());
#else
mesh->transform(get_matrix(dont_translate));
#endif // ENABLE_WORLD_COORDINATE
}
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate) const
{
// Rotate around mesh origin.
TriangleMesh copy(mesh);
#if ENABLE_WORLD_COORDINATE
copy.transform(get_transformation().get_rotation_matrix());
#else
copy.transform(get_matrix(true, false, true, true));
#endif // ENABLE_WORLD_COORDINATE
BoundingBoxf3 bbox = copy.bounding_box();
if (!empty(bbox)) {
@ -2330,12 +2381,20 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh& mes
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
{
#if ENABLE_WORLD_COORDINATE
return bbox.transformed(dont_translate ? get_matrix_no_offset() : get_matrix());
#else
return bbox.transformed(get_matrix(dont_translate));
#endif // ENABLE_WORLD_COORDINATE
}
Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const
{
#if ENABLE_WORLD_COORDINATE
return dont_translate ? get_matrix_no_offset() * v : get_matrix() * v;
#else
return get_matrix(dont_translate) * v;
#endif // ENABLE_WORLD_COORDINATE
}
void ModelInstance::transform_polygon(Polygon* polygon) const

View File

@ -781,15 +781,26 @@ public:
const Geometry::Transformation& get_transformation() const { return m_transformation; }
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
#if ENABLE_WORLD_COORDINATE
void set_transformation(const Transform3d& trafo) { m_transformation.set_matrix(trafo); }
Vec3d get_offset() const { return m_transformation.get_offset(); }
#else
void set_transformation(const Transform3d &trafo) { m_transformation.set_from_transform(trafo); }
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
#endif // ENABLE_WORLD_COORDINATE
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
#if ENABLE_WORLD_COORDINATE
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
#else
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
#endif // ENABLE_WORLD_COORDINATE
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
@ -801,7 +812,11 @@ public:
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
#if ENABLE_WORLD_COORDINATE
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
#else
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
#endif // ENABLE_WORLD_COORDINATE
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
bool is_left_handed() const { return m_transformation.is_left_handed(); }
@ -810,7 +825,12 @@ public:
void convert_from_imperial_units();
void convert_from_meters();
#if ENABLE_WORLD_COORDINATE
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
#else
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
#endif // ENABLE_WORLD_COORDINATE
void set_new_unique_id() {
ObjectBase::set_new_unique_id();
@ -1013,25 +1033,41 @@ public:
const Geometry::Transformation& get_transformation() const { return m_transformation; }
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
#if ENABLE_WORLD_COORDINATE
Vec3d get_offset() const { return m_transformation.get_offset(); }
#else
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
#endif // ENABLE_WORLD_COORDINATE
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
#if ENABLE_WORLD_COORDINATE
Vec3d get_rotation() const { return m_transformation.get_rotation(); }
#else
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
#endif // ENABLE_WORLD_COORDINATE
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); }
#if ENABLE_WORLD_COORDINATE
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
#else
const Vec3d& get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
#endif // ENABLE_WORLD_COORDINATE
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
#if ENABLE_WORLD_COORDINATE
Vec3d get_mirror() const { return m_transformation.get_mirror(); }
#else
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
#endif // ENABLE_WORLD_COORDINATE
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
bool is_left_handed() const { return m_transformation.is_left_handed(); }
@ -1049,7 +1085,12 @@ public:
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
void transform_polygon(Polygon* polygon) const;
#if ENABLE_WORLD_COORDINATE
const Transform3d& get_matrix() const { return m_transformation.get_matrix(); }
Transform3d get_matrix_no_offset() const { return m_transformation.get_matrix_no_offset(); }
#else
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
#endif // ENABLE_WORLD_COORDINATE
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }

View File

@ -3,6 +3,13 @@
#include <assert.h>
#include <type_traits>
#include <vector>
#include <limits>
#include <cstdlib> // adds size_t (without std::)
namespace Slic3r {
constexpr auto InvalidQueueID = std::numeric_limits<size_t>::max();
template<typename T, typename IndexSetter, typename LessPredicate, const bool ResetIndexWhenRemoved = false>
class MutablePriorityQueue
@ -21,7 +28,7 @@ public:
MutablePriorityQueue& operator=(MutablePriorityQueue &&) = default;
// This class modifies the outside data through the m_index_setter
// and thus it should not be copied. The semantics are similar to std::unique_ptr
// and thus it should not be copied. The semantics is similar to std::unique_ptr
MutablePriorityQueue(const MutablePriorityQueue &) = delete;
MutablePriorityQueue& operator=(const MutablePriorityQueue &) = delete;
@ -38,6 +45,7 @@ public:
bool empty() const { return m_heap.empty(); }
T& operator[](std::size_t idx) noexcept { return m_heap[idx]; }
const T& operator[](std::size_t idx) const noexcept { return m_heap[idx]; }
static constexpr size_t invalid_id() { return InvalidQueueID; }
using iterator = typename std::vector<T>::iterator;
using const_iterator = typename std::vector<T>::const_iterator;
@ -66,14 +74,10 @@ MutablePriorityQueue<T, IndexSetter, LessPredicate, ResetIndexWhenRemoved> make_
template<class T, class LessPredicate, class IndexSetter, const bool ResetIndexWhenRemoved>
inline void MutablePriorityQueue<T, LessPredicate, IndexSetter, ResetIndexWhenRemoved>::clear()
{
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
for (size_t idx = 0; idx < m_heap.size(); ++ idx)
// Mark as removed from the queue.
m_index_setter(m_heap[idx], std::numeric_limits<size_t>::max());
m_index_setter(m_heap[idx], this->invalid_id());
}
m_heap.clear();
}
@ -100,13 +104,9 @@ template<class T, class LessPredicate, class IndexSetter, const bool ResetIndexW
inline void MutablePriorityQueue<T, LessPredicate, IndexSetter, ResetIndexWhenRemoved>::pop()
{
assert(! m_heap.empty());
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
// Mark as removed from the queue.
m_index_setter(m_heap.front(), std::numeric_limits<size_t>::max());
m_index_setter(m_heap.front(), this->invalid_id());
}
if (m_heap.size() > 1) {
m_heap.front() = m_heap.back();
@ -121,13 +121,10 @@ template<class T, class LessPredicate, class IndexSetter, const bool ResetIndexW
inline void MutablePriorityQueue<T, LessPredicate, IndexSetter, ResetIndexWhenRemoved>::remove(size_t idx)
{
assert(idx < m_heap.size());
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
// Mark as removed from the queue.
m_index_setter(m_heap[idx], std::numeric_limits<size_t>::max());
m_index_setter(m_heap[idx], this->invalid_id());
}
if (idx + 1 == m_heap.size()) {
m_heap.pop_back();
@ -274,6 +271,14 @@ public:
{}
~MutableSkipHeapPriorityQueue() { clear(); }
MutableSkipHeapPriorityQueue(MutableSkipHeapPriorityQueue &&) = default;
MutableSkipHeapPriorityQueue &operator=(MutableSkipHeapPriorityQueue &&) = default;
// This class modifies the outside data through the m_index_setter
// and thus it should not be copied. The semantics is similar to std::unique_ptr
MutableSkipHeapPriorityQueue(const MutableSkipHeapPriorityQueue &) = delete;
MutableSkipHeapPriorityQueue &operator=(const MutableSkipHeapPriorityQueue &) = delete;
void clear();
// Reserve one unused element per miniheap.
void reserve(size_t cnt) { m_heap.reserve(cnt + ((cnt + (address::block_size - 1)) / (address::block_size - 1))); }
@ -285,9 +290,12 @@ public:
void update(size_t idx) { assert(! address::is_padding(idx)); T item = m_heap[idx]; remove(idx); push(item); }
// There is one padding element storead at each miniheap, thus lower the number of elements by the number of miniheaps.
size_t size() const noexcept { return m_heap.size() - (m_heap.size() + address::block_size - 1) / address::block_size; }
// Number of heap elements including padding. heap_size() >= size().
size_t heap_size() const noexcept { return m_heap.size(); }
bool empty() const { return m_heap.empty(); }
T& operator[](std::size_t idx) noexcept { assert(! address::is_padding(idx)); return m_heap[idx]; }
const T& operator[](std::size_t idx) const noexcept { assert(! address::is_padding(idx)); return m_heap[idx]; }
static constexpr size_t invalid_id() { return InvalidQueueID; }
protected:
void update_heap_up(size_t top, size_t bottom);
@ -317,15 +325,11 @@ MutableSkipHeapPriorityQueue<T, IndexSetter, LessPredicate, BlockSize, ResetInde
template<class T, class LessPredicate, class IndexSetter, std::size_t blocking, const bool ResetIndexWhenRemoved>
inline void MutableSkipHeapPriorityQueue<T, LessPredicate, IndexSetter, blocking, ResetIndexWhenRemoved>::clear()
{
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
for (size_t idx = 0; idx < m_heap.size(); ++ idx)
// Mark as removed from the queue.
if (! address::is_padding(idx))
m_index_setter(m_heap[idx], std::numeric_limits<size_t>::max());
m_index_setter(m_heap[idx], this->invalid_id());
}
m_heap.clear();
}
@ -356,13 +360,9 @@ template<class T, class LessPredicate, class IndexSetter, std::size_t blocking,
inline void MutableSkipHeapPriorityQueue<T, LessPredicate, IndexSetter, blocking, ResetIndexWhenRemoved>::pop()
{
assert(! m_heap.empty());
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
// Mark as removed from the queue.
m_index_setter(m_heap[1], std::numeric_limits<size_t>::max());
m_index_setter(m_heap[1], this->invalid_id());
}
// Zero'th element is padding, thus non-empty queue must have at least two elements.
if (m_heap.size() > 2) {
@ -379,13 +379,9 @@ inline void MutableSkipHeapPriorityQueue<T, LessPredicate, IndexSetter, blocking
{
assert(idx < m_heap.size());
assert(! address::is_padding(idx));
#ifdef NDEBUG
// Only mark as removed from the queue in release mode, if configured so.
if (ResetIndexWhenRemoved)
#endif /* NDEBUG */
{
if constexpr (ResetIndexWhenRemoved) {
// Mark as removed from the queue.
m_index_setter(m_heap[idx], std::numeric_limits<size_t>::max());
m_index_setter(m_heap[idx], this->invalid_id());
}
if (idx + 1 == m_heap.size()) {
this->pop_back();
@ -458,4 +454,6 @@ inline void MutableSkipHeapPriorityQueue<T, LessPredicate, IndexSetter, blocking
}
}
} // namespace Slic3r
#endif /* slic3r_MutablePriorityQueue_hpp_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#include <cassert>
#include "PresetBundle.hpp"
#include "libslic3r.h"
#include "PresetBundle.hpp"
#include "Utils.hpp"
#include "Model.hpp"
#include "format.hpp"
@ -453,6 +453,11 @@ void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::
presets.get_edited_preset().config.apply_only(presets.get_selected_preset().config, unselected_options);
}
#if ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
if (type == Preset::TYPE_PRINTER)
copy_bed_model_and_texture_if_needed(presets.get_edited_preset().config);
#endif // ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
presets.save_current_preset(new_name);
// Mark the print & filament enabled if they are compatible with the currently selected preset.
@ -1860,4 +1865,32 @@ void PresetBundle::set_default_suppressed(bool default_suppressed)
printers.set_default_suppressed(default_suppressed);
}
#if ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
void copy_bed_model_and_texture_if_needed(DynamicPrintConfig& config)
{
const boost::filesystem::path user_dir = boost::filesystem::absolute(boost::filesystem::path(data_dir()) / "printer").make_preferred();
const boost::filesystem::path res_dir = boost::filesystem::absolute(boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
auto do_copy = [&user_dir, &res_dir](ConfigOptionString* cfg, const std::string& type) {
if (cfg == nullptr || cfg->value.empty())
return;
const boost::filesystem::path src_dir = boost::filesystem::absolute(boost::filesystem::path(cfg->value)).make_preferred().parent_path();
if (src_dir != user_dir && src_dir.parent_path() != res_dir) {
const std::string dst_value = (user_dir / boost::filesystem::path(cfg->value).filename()).string();
std::string error;
if (copy_file_inner(cfg->value, dst_value, error) == SUCCESS)
cfg->value = dst_value;
else {
BOOST_LOG_TRIVIAL(error) << "Copying from " << cfg->value << " to " << dst_value << " failed. Unable to set custom bed " << type << ". [" << error << "]";
cfg->value = "";
}
}
};
do_copy(config.option<ConfigOptionString>("bed_custom_texture"), "texture");
do_copy(config.option<ConfigOptionString>("bed_custom_model"), "model");
}
#endif // ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
} // namespace Slic3r

View File

@ -178,6 +178,12 @@ private:
ENABLE_ENUM_BITMASK_OPERATORS(PresetBundle::LoadConfigBundleAttribute)
#if ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
// Copies bed texture and model files to 'data_dir()\printer' folder, if needed
// and updates the config accordingly
extern void copy_bed_model_and_texture_if_needed(DynamicPrintConfig& config);
#endif // ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE
} // namespace Slic3r
#endif /* slic3r_PresetBundle_hpp_ */

View File

@ -13,6 +13,7 @@
#include "GCode.hpp"
#include "GCode/WipeTower.hpp"
#include "Utils.hpp"
#include "BuildVolume.hpp"
#include <float.h>
@ -387,7 +388,7 @@ bool Print::sequential_print_horizontal_clearance_valid(const Print& print, Poly
Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(), model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
float(scale_(0.5 * print.config().extruder_clearance_radius.value - BuildVolume::BedEpsilon)),
jtRound, scale_(0.1)).front());
}
// Make a copy, so it may be rotated for instances.

File diff suppressed because it is too large Load Diff

View File

@ -464,7 +464,7 @@ FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data()
break;
}
return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this)) : FillLightning::GeneratorPtr();
return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this), [this]() -> void { this->throw_if_canceled(); }) : FillLightning::GeneratorPtr();
}
void PrintObject::clear_layers()

View File

@ -288,7 +288,7 @@ template<unsigned MAX_ITER>
struct RotfinderBoilerplate {
static constexpr unsigned MAX_TRIES = MAX_ITER;
int status = 0;
int status = 0, prev_status = 0;
TriangleMesh mesh;
unsigned max_tries;
const RotOptimizeParams &params;
@ -314,13 +314,20 @@ struct RotfinderBoilerplate {
RotfinderBoilerplate(const ModelObject &mo, const RotOptimizeParams &p)
: mesh{get_mesh_to_rotate(mo)}
, params{p}
, max_tries(p.accuracy() * MAX_TRIES)
{
, params{p}
{}
void statusfn() {
int s = status * 100 / max_tries;
if (s != prev_status) {
params.statuscb()(s);
prev_status = s;
}
++status;
}
void statusfn() { params.statuscb()(++status * 100.0 / max_tries); }
bool stopcond() { return ! params.statuscb()(-1); }
};

View File

@ -195,7 +195,15 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
}
// Initialize a heap of end points sorted by the lowest distance to the next valid point of a path.
auto queue = make_mutable_priority_queue<EndPoint*, false>(
auto queue = make_mutable_priority_queue<EndPoint*,
#ifndef NDEBUG
// In debug mode, reset indices when removing an item from the queue for debugging purposes.
true
#else // NDEBUG
// In release mode, don't reset indices when removing an item from the queue.
false
#endif // NDEBUG
>(
[](EndPoint *ep, size_t idx){ ep->heap_idx = idx; },
[](EndPoint *l, EndPoint *r){ return l->distance_out < r->distance_out; });
queue.reserve(end_points.size() * 2 - 1);
@ -213,7 +221,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
assert(ep.chain_id == 0);
} else {
// End point is NOT on the heap, therefore it is part of the output path.
assert(ep.heap_idx == std::numeric_limits<size_t>::max());
assert(ep.heap_idx == queue.invalid_id());
assert(ep.chain_id != 0);
if (&ep == first_point) {
assert(ep.edge_out == nullptr);
@ -222,7 +230,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals
// Detect loops.
for (EndPoint *pt = &ep; pt != nullptr;) {
// Out of queue. It is a final point.
assert(pt->heap_idx == std::numeric_limits<size_t>::max());
assert(pt->heap_idx == queue.invalid_id());
EndPoint *pt_other = &end_points[(pt - &end_points.front()) ^ 1];
if (pt_other->heap_idx < queue.size())
// The other side of this segment is undecided yet.

View File

@ -50,7 +50,7 @@
// Enable showing time estimate for travel moves in legend
#define ENABLE_TRAVEL_TIME (1 && ENABLE_2_5_0_ALPHA1)
// Enable not killing focus in object manipulator fields when hovering over 3D scene
#define ENABLE_OBJECT_MANIPULATOR_FOCUS (1 && ENABLE_2_5_0_ALPHA1)
#define ENABLE_OBJECT_MANIPULATOR_FOCUS (0 && ENABLE_2_5_0_ALPHA1)
// Enable removal of wipe tower magic object_id equal to 1000
#define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1)
// Enable removal of legacy OpenGL calls
@ -69,6 +69,8 @@
#define ENABLE_SHOW_TOOLPATHS_COG (1 && ENABLE_2_5_0_ALPHA1)
// Enable recalculating toolpaths when switching to/from volumetric rate visualization
#define ENABLE_VOLUMETRIC_RATE_TOOLPATHS_RECALC (1 && ENABLE_2_5_0_ALPHA1)
// Enable editing volumes transformation in world coordinates and instances in local coordinates
#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified camera control using mouse
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified rectangle selection
@ -81,6 +83,7 @@
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
// Enable gizmo grabbers to share common models
#define ENABLE_GIZMO_GRABBER_REFACTOR (1 && ENABLE_2_5_0_ALPHA1)
// Enable copy of custom bed model and texture
#define ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_

View File

@ -15,6 +15,7 @@
#include "Thread.hpp"
#include "Utils.hpp"
#include "LocalesUtils.hpp"
namespace Slic3r {
@ -234,21 +235,8 @@ void name_tbb_thread_pool_threads_set_locale()
std::ostringstream name;
name << "slic3r_tbb_" << range.begin();
set_current_thread_name(name.str().c_str());
// Set locales of the worker thread to "C".
#ifdef _WIN32
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
std::setlocale(LC_ALL, "C");
#else
// We are leaking some memory here, because the newlocale() produced memory will never be released.
// This is not a problem though, as there will be a maximum one worker thread created per physical thread.
uselocale(newlocale(
#ifdef __APPLE__
LC_ALL_MASK
#else // some Unix / Linux / BSD
LC_ALL
#endif
, "C", nullptr));
#endif
// Set locales of the worker thread to "C".
set_c_locales();
}
});
}

View File

@ -4,7 +4,6 @@
#include "libslic3r_version.h"
#define GCODEVIEWER_APP_NAME "PrusaSlicer G-code Viewer"
#define GCODEVIEWER_APP_KEY "PrusaSlicerGcodeViewer"
#define GCODEVIEWER_BUILD_ID std::string("PrusaSlicer G-code Viewer-") + std::string(SLIC3R_VERSION) + std::string("-UNKNOWN")
// this needs to be included early for MSVC (listing it in Build.PL is not enough)
#include <memory>

View File

@ -1 +0,0 @@
Upstream source: https://github.com/memononen/nanosvg/tree/c1f6e209c16b18b46aa9f45d7e619acf42c29726

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,8 @@ set(SLIC3R_GUI_SOURCES
GUI/GUI_App.hpp
GUI/GUI_Utils.cpp
GUI/GUI_Utils.hpp
GUI/GUI_Geometry.cpp
GUI/GUI_Geometry.hpp
GUI/I18N.cpp
GUI/I18N.hpp
GUI/MainFrame.cpp
@ -129,6 +131,8 @@ set(SLIC3R_GUI_SOURCES
GUI/2DBed.hpp
GUI/3DBed.cpp
GUI/3DBed.hpp
GUI/CoordAxes.cpp
GUI/CoordAxes.hpp
GUI/Camera.cpp
GUI/Camera.hpp
GUI/wxExtensions.cpp
@ -172,6 +176,7 @@ set(SLIC3R_GUI_SOURCES
GUI/Jobs/Worker.hpp
GUI/Jobs/BoostThreadWorker.hpp
GUI/Jobs/BoostThreadWorker.cpp
GUI/Jobs/UIThreadWorker.hpp
GUI/Jobs/BusyCursorJob.hpp
GUI/Jobs/PlaterWorker.hpp
GUI/Jobs/ArrangeJob.hpp
@ -246,8 +251,12 @@ set(SLIC3R_GUI_SOURCES
Utils/TCPConsole.hpp
Utils/MKS.cpp
Utils/MKS.hpp
Utils/WinRegistry.cpp
Utils/WinRegistry.hpp
)
find_package(NanoSVG REQUIRED)
if (APPLE)
list(APPEND SLIC3R_GUI_SOURCES
Utils/RetinaHelperImpl.mm
@ -272,7 +281,7 @@ endforeach()
encoding_check(libslic3r_gui)
target_link_libraries(libslic3r_gui libslic3r avrdude libcereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES})
target_link_libraries(libslic3r_gui libslic3r avrdude libcereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES} NanoSVG::nanosvg NanoSVG::nanosvgrast)
if (MSVC)
target_link_libraries(libslic3r_gui Setupapi.lib)

View File

@ -102,6 +102,7 @@ const float* GeometryBuffer::get_vertices_data() const
}
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
#if !ENABLE_WORLD_COORDINATE
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
const float Bed3D::Axes::DefaultStemLength = 25.0f;
const float Bed3D::Axes::DefaultTipRadius = 2.5f * Bed3D::Axes::DefaultStemRadius;
@ -179,6 +180,7 @@ void Bed3D::Axes::render()
glsafe(::glDisable(GL_DEPTH_TEST));
}
#endif // !ENABLE_WORLD_COORDINATE
bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom)
{
@ -341,7 +343,11 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box() const
out.max.z() = 0.0;
// extend to contain axes
out.merge(m_axes.get_origin() + m_axes.get_total_length() * Vec3d::Ones());
#if ENABLE_WORLD_COORDINATE
out.merge(out.min + Vec3d(-m_axes.get_tip_radius(), -m_axes.get_tip_radius(), out.max.z()));
#else
out.merge(out.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, out.max.z()));
#endif // ENABLE_WORLD_COORDINATE
// extend to contain model, if any
BoundingBoxf3 model_bb = m_model.get_bounding_box();
if (model_bb.defined) {
@ -539,7 +545,15 @@ std::tuple<Bed3D::Type, std::string, std::string> Bed3D::detect_type(const Point
void Bed3D::render_axes()
{
if (m_build_volume.valid())
#if ENABLE_WORLD_COORDINATE
#if ENABLE_GL_SHADERS_ATTRIBUTES
m_axes.render(Transform3d::Identity(), 0.25f);
#else
m_axes.render(0.25f);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#else
m_axes.render();
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_GL_SHADERS_ATTRIBUTES

View File

@ -3,7 +3,11 @@
#include "GLTexture.hpp"
#include "3DScene.hpp"
#if ENABLE_WORLD_COORDINATE
#include "CoordAxes.hpp"
#else
#include "GLModel.hpp"
#endif // ENABLE_WORLD_COORDINATE
#include "libslic3r/BuildVolume.hpp"
#if ENABLE_LEGACY_OPENGL_REMOVAL
@ -44,6 +48,7 @@ public:
class Bed3D
{
#if !ENABLE_WORLD_COORDINATE
class Axes
{
public:
@ -67,6 +72,7 @@ class Bed3D
float get_total_length() const { return m_stem_length + DefaultTipLength; }
void render();
};
#endif // !ENABLE_WORLD_COORDINATE
public:
enum class Type : unsigned char
@ -107,7 +113,11 @@ private:
#if !ENABLE_LEGACY_OPENGL_REMOVAL
unsigned int m_vbo_id{ 0 };
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_WORLD_COORDINATE
CoordAxes m_axes;
#else
Axes m_axes;
#endif // ENABLE_WORLD_COORDINATE
float m_scale_factor{ 1.0f };

File diff suppressed because it is too large Load Diff

View File

@ -221,8 +221,7 @@ AboutDialog::AboutDialog()
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
// logo
m_logo_bitmap = ScalableBitmap(this, wxGetApp().logo_name(), 192);
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp());
m_logo = new wxStaticBitmap(this, wxID_ANY, *get_bmp_bundle(wxGetApp().logo_name(), 192));
hsizer->Add(m_logo, 1, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
@ -322,8 +321,8 @@ AboutDialog::AboutDialog()
void AboutDialog::on_dpi_changed(const wxRect &suggested_rect)
{
m_logo_bitmap.msw_rescale();
m_logo->SetBitmap(m_logo_bitmap.bmp());
// m_logo_bitmap.msw_rescale();
// m_logo->SetBitmap(m_logo_bitmap.bmp());
const wxFont& font = GetFont();
const int fs = font.GetPointSize() - 1;

View File

@ -15,10 +15,8 @@
#include <wx/rawbmp.h>
#endif /* __WXGTK2__ */
//#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include <nanosvg/nanosvg.h>
#include <nanosvg/nanosvgrast.h>
namespace Slic3r { namespace GUI {
@ -62,7 +60,168 @@ static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image, float scale = 1.
#endif
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height)
wxBitmapBundle* BitmapCache::insert_bndl(const std::string& name, const std::vector<wxBitmapBundle*>& bmps)
{
wxVector<wxBitmap> bitmaps;
std::set<double> scales = {1.0};
#ifndef __linux__
#ifdef __APPLE__
scales.emplace(m_scale);
#else
size_t disp_cnt = wxDisplay::GetCount();
for (size_t disp = 0; disp < disp_cnt; ++disp)
scales.emplace(wxDisplay(disp).GetScaleFactor());
#endif
#endif // !__linux__
for (double scale : scales) {
size_t width = 0;
size_t height = 0;
for (const wxBitmapBundle* bmp_bndl : bmps) {
#ifdef __APPLE__
wxSize size = bmp_bndl->GetDefaultSize();
#else
wxSize size = bmp_bndl->GetPreferredBitmapSizeAtScale(scale);
#endif
width += size.GetWidth();
height = std::max<size_t>(height, size.GetHeight());
}
std::string bitmap_key = name + "," +float_to_string_decimal_point(scale);
#ifdef __WXGTK2__
// Broken alpha workaround
wxImage image(width, height);
image.InitAlpha();
// Fill in with a white color.
memset(image.GetData(), 0x0ff, width * height * 3);
// Fill in with full transparency.
memset(image.GetAlpha(), 0, width * height);
size_t x = 0;
for (const wxBitmapBundle* bmp_bndl : bmps) {
wxBitmap bmp = bmp_bndl->GetBitmap(bmp_bndl->GetDefaultSize());
if (bmp.GetWidth() > 0) {
if (bmp.GetDepth() == 32) {
wxAlphaPixelData data(bmp);
//FIXME The following method is missing from wxWidgets 3.1.1.
// It looks like the wxWidgets 3.0.3 called the wrapped bitmap's UseAlpha().
//data.UseAlpha();
if (data) {
for (int r = 0; r < bmp.GetHeight(); ++r) {
wxAlphaPixelData::Iterator src(data);
src.Offset(data, 0, r);
unsigned char* dst_pixels = image.GetData() + (x + r * width) * 3;
unsigned char* dst_alpha = image.GetAlpha() + x + r * width;
for (int c = 0; c < bmp.GetWidth(); ++c, ++src) {
*dst_pixels++ = src.Red();
*dst_pixels++ = src.Green();
*dst_pixels++ = src.Blue();
*dst_alpha++ = src.Alpha();
}
}
}
}
else if (bmp.GetDepth() == 24) {
wxNativePixelData data(bmp);
if (data) {
for (int r = 0; r < bmp.GetHeight(); ++r) {
wxNativePixelData::Iterator src(data);
src.Offset(data, 0, r);
unsigned char* dst_pixels = image.GetData() + (x + r * width) * 3;
unsigned char* dst_alpha = image.GetAlpha() + x + r * width;
for (int c = 0; c < bmp.GetWidth(); ++c, ++src) {
*dst_pixels++ = src.Red();
*dst_pixels++ = src.Green();
*dst_pixels++ = src.Blue();
*dst_alpha++ = wxALPHA_OPAQUE;
}
}
}
}
}
x += bmp.GetScaledWidth();
}
bitmaps.push_back(* this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image))));
#else
wxBitmap* bitmap = this->insert(bitmap_key, width, height, scale);
wxMemoryDC memDC;
memDC.SelectObject(*bitmap);
memDC.SetBackground(*wxTRANSPARENT_BRUSH);
memDC.Clear();
size_t x = 0;
for (const wxBitmapBundle* bmp_bndl : bmps) {
wxBitmap bmp = bmp_bndl->GetBitmap(bmp_bndl->GetPreferredBitmapSizeAtScale(scale));
if (bmp.GetWidth() > 0)
memDC.DrawBitmap(bmp, x, 0, true);
// we should "move" with step equal to non-scaled width
#ifdef __APPLE__
x += bmp.GetScaledWidth();
#else
x += bmp.GetWidth();
#endif
}
memDC.SelectObject(wxNullBitmap);
bitmaps.push_back(*bitmap);
#endif
}
return insert_bndl(name, bitmaps);
}
wxBitmapBundle* BitmapCache::insert_bndl(const std::string &bitmap_key, const char* data, size_t width, size_t height)
{
wxBitmapBundle* bndl = nullptr;
auto it = m_bndl_map.find(bitmap_key);
if (it == m_bndl_map.end()) {
bndl = new wxBitmapBundle(wxBitmapBundle::FromSVG(data, wxSize(width, height)));
m_bndl_map[bitmap_key] = bndl;
}
else {
bndl = it->second;
*bndl = wxBitmapBundle::FromSVG(data, wxSize(width, height));
}
return bndl;
}
wxBitmapBundle* BitmapCache::insert_bndl(const std::string& bitmap_key, const wxBitmapBundle& bmp)
{
wxBitmapBundle* bndl = nullptr;
auto it = m_bndl_map.find(bitmap_key);
if (it == m_bndl_map.end()) {
bndl = new wxBitmapBundle(bmp);
m_bndl_map[bitmap_key] = bndl;
}
else {
bndl = it->second;
*bndl = wxBitmapBundle(bmp);
}
return bndl;
}
wxBitmapBundle* BitmapCache::insert_bndl(const std::string& bitmap_key, const wxVector<wxBitmap>& bmps)
{
wxBitmapBundle* bndl = nullptr;
auto it = m_bndl_map.find(bitmap_key);
if (it == m_bndl_map.end()) {
bndl = new wxBitmapBundle(wxBitmapBundle::FromBitmaps(bmps));
m_bndl_map[bitmap_key] = bndl;
}
else {
bndl = it->second;
*bndl = wxBitmapBundle::FromBitmaps(bmps);
}
return bndl;
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height, double scale/* = -1.0*/)
{
wxBitmap *bitmap = nullptr;
auto it = m_map.find(bitmap_key);
@ -78,7 +237,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_
// So, We need to let the Mac OS wxBitmap implementation
// know that the image may already be scaled appropriately for Retina,
// and thereby that it's not supposed to upscale it.
bitmap->CreateScaled(width, height, -1, m_scale);
bitmap->CreateScaled(width, height, -1, scale < 0.0 ? m_scale : scale);
#endif
m_map[bitmap_key] = bitmap;
} else {
@ -107,110 +266,6 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp
return bitmap;
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2)
{
// Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
const wxBitmap bmps[2] = { bmp, bmp2 };
return this->insert(bitmap_key, bmps, bmps + 2);
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3)
{
// Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
const wxBitmap bmps[3] = { bmp, bmp2, bmp3 };
return this->insert(bitmap_key, bmps, bmps + 3);
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *begin, const wxBitmap *end)
{
size_t width = 0;
size_t height = 0;
for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
#ifdef __APPLE__
width += bmp->GetScaledWidth();
height = std::max<size_t>(height, bmp->GetScaledHeight());
#else
width += bmp->GetWidth();
height = std::max<size_t>(height, bmp->GetHeight());
#endif
}
#ifdef __WXGTK2__
// Broken alpha workaround
wxImage image(width, height);
image.InitAlpha();
// Fill in with a white color.
memset(image.GetData(), 0x0ff, width * height * 3);
// Fill in with full transparency.
memset(image.GetAlpha(), 0, width * height);
size_t x = 0;
for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
if (bmp->GetWidth() > 0) {
if (bmp->GetDepth() == 32) {
wxAlphaPixelData data(*const_cast<wxBitmap*>(bmp));
//FIXME The following method is missing from wxWidgets 3.1.1.
// It looks like the wxWidgets 3.0.3 called the wrapped bitmap's UseAlpha().
//data.UseAlpha();
if (data) {
for (int r = 0; r < bmp->GetHeight(); ++ r) {
wxAlphaPixelData::Iterator src(data);
src.Offset(data, 0, r);
unsigned char *dst_pixels = image.GetData() + (x + r * width) * 3;
unsigned char *dst_alpha = image.GetAlpha() + x + r * width;
for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) {
*dst_pixels ++ = src.Red();
*dst_pixels ++ = src.Green();
*dst_pixels ++ = src.Blue();
*dst_alpha ++ = src.Alpha();
}
}
}
} else if (bmp->GetDepth() == 24) {
wxNativePixelData data(*const_cast<wxBitmap*>(bmp));
if (data) {
for (int r = 0; r < bmp->GetHeight(); ++ r) {
wxNativePixelData::Iterator src(data);
src.Offset(data, 0, r);
unsigned char *dst_pixels = image.GetData() + (x + r * width) * 3;
unsigned char *dst_alpha = image.GetAlpha() + x + r * width;
for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) {
*dst_pixels ++ = src.Red();
*dst_pixels ++ = src.Green();
*dst_pixels ++ = src.Blue();
*dst_alpha ++ = wxALPHA_OPAQUE;
}
}
}
}
}
x += bmp->GetWidth();
}
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
#else
wxBitmap *bitmap = this->insert(bitmap_key, width, height);
wxMemoryDC memDC;
memDC.SelectObject(*bitmap);
memDC.SetBackground(*wxTRANSPARENT_BRUSH);
memDC.Clear();
size_t x = 0;
for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
if (bmp->GetWidth() > 0)
memDC.DrawBitmap(*bmp, x, 0, true);
#ifdef __APPLE__
// we should "move" with step equal to non-scaled width
x += bmp->GetScaledWidth();
#else
x += bmp->GetWidth();
#endif
}
memDC.SelectObject(wxNullBitmap);
return bitmap;
#endif
}
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, const bool grayscale/* = false*/)
{
wxImage image(width, height);
@ -299,6 +354,92 @@ error:
return NULL;
}
void BitmapCache::nsvgGetDataFromFileWithReplace(const char* filename, std::string& data_str, const std::map<std::string, std::string>& replaces)
{
FILE* fp = NULL;
size_t size;
char* data = NULL;
fp = boost::nowide::fopen(filename, "rb");
if (!fp) goto error;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
data = (char*)malloc(size + 1);
if (data == NULL) goto error;
if (fread(data, 1, size, fp) != size) goto error;
data[size] = '\0'; // Must be null terminated.
fclose(fp);
data_str.assign(data);
for (auto val : replaces)
boost::replace_all(data_str, val.first, val.second);
free(data);
return;
error:
if (fp) fclose(fp);
if (data) free(data);
return;
}
wxBitmapBundle* BitmapCache::from_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height,
const bool dark_mode, const std::string& new_color /*= ""*/)
{
if (target_width == 0)
target_width = target_height;
std::string bitmap_key = bitmap_name + (target_height != 0 ?
"-h" + std::to_string(target_height) :
"-w" + std::to_string(target_width))
+ (dark_mode ? "-dm" : "")
+ new_color;
auto it = m_bndl_map.find(bitmap_key);
if (it != m_bndl_map.end())
return it->second;
// map of color replaces
std::map<std::string, std::string> replaces;
if (dark_mode)
replaces["\"#808080\""] = "\"#FFFFFF\"";
if (!new_color.empty())
replaces["\"#ED6B21\""] = "\"" + new_color + "\"";
std::string str;
nsvgGetDataFromFileWithReplace(Slic3r::var(bitmap_name + ".svg").c_str(), str, replaces);
if (str.empty())
return nullptr;
return insert_bndl(bitmap_key, str.data(), target_width, target_height);
}
wxBitmapBundle* BitmapCache::from_png(const std::string& bitmap_name, unsigned width, unsigned height)
{
std::string bitmap_key = bitmap_name + (height != 0 ?
"-h" + std::to_string(height) :
"-w" + std::to_string(width));
auto it = m_bndl_map.find(bitmap_key);
if (it != m_bndl_map.end())
return it->second;
wxImage image;
if (!image.LoadFile(Slic3r::GUI::from_u8(Slic3r::var(bitmap_name + ".png")), wxBITMAP_TYPE_PNG) ||
image.GetWidth() == 0 || image.GetHeight() == 0)
return nullptr;
if (height != 0 && unsigned(image.GetHeight()) != height)
width = unsigned(0.5f + float(image.GetWidth()) * height / image.GetHeight());
else if (width != 0 && unsigned(image.GetWidth()) != width)
height = unsigned(0.5f + float(image.GetHeight()) * width / image.GetWidth());
if (height != 0 && width != 0)
image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR);
return this->insert_bndl(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
}
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_width, unsigned target_height,
const bool grayscale/* = false*/, const bool dark_mode/* = false*/, const std::string& new_color /*= ""*/)
{
@ -352,9 +493,9 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
return this->insert_raw_rgba(bitmap_key, width, height, data.data(), grayscale);
}
/*
//we make scaled solid bitmaps only for the cases, when its will be used with scaled SVG icon in one output bitmap
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling/* = false*/, size_t border_width /*= 0*/, bool dark_mode/* = false*/)
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling/* = false* /, size_t border_width /*= 0* /, bool dark_mode/* = false* /)
{
double scale = suppress_scaling ? 1.0f : m_scale;
width *= scale;
@ -396,6 +537,89 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
}
*/
//we make scaled solid bitmaps only for the cases, when its will be used with scaled SVG icon in one output bitmap
wxBitmapBundle BitmapCache::mksolid(size_t width_in, size_t height_in, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, size_t border_width /*= 0*/, bool dark_mode/* = false*/)
{
wxVector<wxBitmap> bitmaps;
std::set<double> scales = { 1.0 };
#ifndef __linux__
#ifdef __APPLE__
scales.emplace(m_scale);
#else
size_t disp_cnt = wxDisplay::GetCount();
for (size_t disp = 0; disp < disp_cnt; ++disp)
scales.emplace(wxDisplay(disp).GetScaleFactor());
#endif
#endif // !__linux__
for (double scale : scales) {
size_t width = width_in * scale;
size_t height = height_in * scale;
wxImage image(width, height);
image.InitAlpha();
unsigned char* imgdata = image.GetData();
unsigned char* imgalpha = image.GetAlpha();
for (size_t i = 0; i < width * height; ++i) {
*imgdata++ = r;
*imgdata++ = g;
*imgdata++ = b;
*imgalpha++ = transparency;
}
// Add border, make white/light spools easier to see
if (border_width > 0) {
// Restrict to width of image
if (border_width > height) border_width = height - 1;
if (border_width > width) border_width = width - 1;
auto px_data = (uint8_t*)image.GetData();
auto a_data = (uint8_t*)image.GetAlpha();
for (size_t x = 0; x < width; ++x) {
for (size_t y = 0; y < height; ++y) {
if (x < border_width || y < border_width ||
x >= (width - border_width) || y >= (height - border_width)) {
const size_t idx = (x + y * width);
const size_t idx_rgb = (x + y * width) * 3;
px_data[idx_rgb] = px_data[idx_rgb + 1] = px_data[idx_rgb + 2] = dark_mode ? 245u : 110u;
a_data[idx] = 255u;
}
}
}
}
bitmaps.push_back(wxImage_to_wxBitmap_with_alpha(std::move(image), scale));
}
return wxBitmapBundle::FromBitmaps(bitmaps);
}
wxBitmapBundle* BitmapCache::mksolid_bndl(size_t width, size_t height, const std::string& color, size_t border_width, bool dark_mode)
{
std::string bitmap_key = (color.empty() ? "empty" : color) + "-h" + std::to_string(height) + "-w" + std::to_string(width) + (dark_mode ? "-dm" : "");
wxBitmapBundle* bndl = nullptr;
auto it = m_bndl_map.find(bitmap_key);
if (it == m_bndl_map.end()) {
if (color.empty())
bndl = new wxBitmapBundle(mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT, size_t(0)));
else {
ColorRGB rgb;// [3] ;
decode_color(color, rgb);
bndl = new wxBitmapBundle(mksolid(width, height, rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar(), wxALPHA_OPAQUE, border_width, dark_mode));
}
m_bndl_map[bitmap_key] = bndl;
}
else
return it->second;
return bndl;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -24,15 +24,19 @@ public:
void clear();
double scale() { return m_scale; }
wxBitmapBundle* find_bndl(const std::string &name) { auto it = m_bndl_map.find(name); return (it == m_bndl_map.end()) ? nullptr : it->second; }
const wxBitmapBundle* find_bndl(const std::string &name) const { return const_cast<BitmapCache*>(this)->find_bndl(name); }
wxBitmap* find(const std::string &name) { auto it = m_map.find(name); return (it == m_map.end()) ? nullptr : it->second; }
const wxBitmap* find(const std::string &name) const { return const_cast<BitmapCache*>(this)->find(name); }
wxBitmap* insert(const std::string &name, size_t width, size_t height);
wxBitmapBundle* insert_bndl(const std::string& bitmap_key, const char* data, size_t width, size_t height);
wxBitmapBundle* insert_bndl(const std::string& bitmap_key, const wxBitmapBundle &bmp);
wxBitmapBundle* insert_bndl(const std::string& bitmap_key, const wxVector<wxBitmap>& bmps);
wxBitmapBundle* insert_bndl(const std::string& name, const std::vector<wxBitmapBundle*>& bmps);
wxBitmapBundle* insert_raw_rgba_bndl(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, const bool grayscale = false);
wxBitmap* insert(const std::string &name, size_t width, size_t height, double scale = -1.0);
wxBitmap* insert(const std::string &name, const wxBitmap &bmp);
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2);
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3);
wxBitmap* insert(const std::string &name, const std::vector<wxBitmap> &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); }
wxBitmap* insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end);
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, const bool grayscale = false);
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
@ -42,15 +46,21 @@ public:
// And makes replases befor parsing
// replace_map containes old_value->new_value
static NSVGimage* nsvgParseFromFileWithReplace(const char* filename, const char* units, float dpi, const std::map<std::string, std::string>& replaces);
// Gets a data from SVG file and makes replases
// replace_map containes old_value->new_value
static void nsvgGetDataFromFileWithReplace(const char* filename, std::string& data_str, const std::map<std::string, std::string>& replaces);
wxBitmapBundle* from_svg(const std::string& bitmap_name, unsigned target_width, unsigned target_height, const bool dark_mode, const std::string& new_color = "");
wxBitmapBundle* from_png(const std::string& bitmap_name, unsigned width, unsigned height);
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false, const std::string& new_color = "");
wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false);
wxBitmap mksolid(size_t width, size_t height, const ColorRGB& rgb, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar(), wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); }
wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
wxBitmapBundle mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, size_t border_width = 0, bool dark_mode = false);
wxBitmapBundle* mksolid_bndl(size_t width, size_t height, const std::string& color = std::string(), size_t border_width = 0, bool dark_mode = false);
wxBitmapBundle* mkclear_bndl(size_t width, size_t height) { return mksolid_bndl(width, height); }
private:
std::map<std::string, wxBitmap*> m_map;
std::map<std::string, wxBitmapBundle*> m_bndl_map;
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
double m_scale = 1.0; // value, used for correct scaling of SVG icons on Retina display
};

View File

@ -54,17 +54,6 @@ using Slic3r::GUI::format_wxstr;
namespace Slic3r {
namespace GUI {
/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
* "please scale this to such and such" but rather
* "the wxImage is already sized for backing scale such and such". )
* Unfortunately, the constructor changes the size of wxBitmap too.
* Thus We need to use unscaled size value for bitmaps that we use
* to avoid scaled size of control items.
* For this purpose control drawing methods and
* control size calculation methods (virtual) are overridden.
**/
BitmapComboBox::BitmapComboBox(wxWindow* parent,
wxWindowID id/* = wxID_ANY*/,
const wxString& value/* = wxEmptyString*/,
@ -90,72 +79,6 @@ BitmapComboBox::~BitmapComboBox()
{
}
#ifdef __APPLE__
bool BitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
{
if (bitmap.IsOk())
{
// we should use scaled! size values of bitmap
int width = (int)bitmap.GetScaledWidth();
int height = (int)bitmap.GetScaledHeight();
if (m_usedImgSize.x < 0)
{
// If size not yet determined, get it from this image.
m_usedImgSize.x = width;
m_usedImgSize.y = height;
// Adjust control size to vertically fit the bitmap
wxWindow* ctrl = GetControl();
ctrl->InvalidateBestSize();
wxSize newSz = ctrl->GetBestSize();
wxSize sz = ctrl->GetSize();
if (newSz.y > sz.y)
ctrl->SetSize(sz.x, newSz.y);
else
DetermineIndent();
}
wxCHECK_MSG(width == m_usedImgSize.x && height == m_usedImgSize.y,
false,
"you can only add images of same size");
return true;
}
return false;
}
void BitmapComboBox::OnDrawItem(wxDC& dc,
const wxRect& rect,
int item,
int flags) const
{
const wxBitmap& bmp = *(static_cast<wxBitmap*>(m_bitmaps[item]));
if (bmp.IsOk())
{
// we should use scaled! size values of bitmap
wxCoord w = bmp.GetScaledWidth();
wxCoord h = bmp.GetScaledHeight();
const int imgSpacingLeft = 4;
// Draw the image centered
dc.DrawBitmap(bmp,
rect.x + (m_usedImgSize.x - w) / 2 + imgSpacingLeft,
rect.y + (rect.height - h) / 2,
true);
}
wxString text = GetString(item);
if (!text.empty())
dc.DrawText(text,
rect.x + m_imgAreaWidth + 1,
rect.y + (rect.height - dc.GetCharHeight()) / 2);
}
#endif
#ifdef _WIN32
int BitmapComboBox::Append(const wxString& item)
@ -166,18 +89,11 @@ int BitmapComboBox::Append(const wxString& item)
//2. But then set width to 0 value for no using of bitmap left and right spacing
//3. Set this empty bitmap to the at list one item and BitmapCombobox will be recreated correct
wxBitmap bitmap(1, int(1.6 * wxGetApp().em_unit() + 1));
{
// bitmap.SetWidth(0); is depricated now
// so, use next code
bitmap.UnShare();// AllocExclusive();
bitmap.GetGDIImageData()->m_width = 0;
}
wxBitmapBundle bitmap = *get_empty_bmp_bundle(1, 16);
OnAddBitmap(bitmap);
const int n = wxComboBox::Append(item);
if (n != wxNOT_FOUND)
DoSetItemBitmap(n, bitmap);
return n;
}

View File

@ -29,28 +29,13 @@ BitmapComboBox(wxWindow* parent,
#ifdef _WIN32
int Append(const wxString& item);
#endif
int Append(const wxString& item, const wxBitmap& bitmap)
int Append(const wxString& item, const wxBitmapBundle& bitmap)
{
return wxBitmapComboBox::Append(item, bitmap);
}
protected:
#ifdef __APPLE__
/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
* "please scale this to such and such" but rather
* "the wxImage is already sized for backing scale such and such". )
* Unfortunately, the constructor changes the size of wxBitmap too.
* Thus We need to use unscaled size value for bitmaps that we use
* to avoid scaled size of control items.
* For this purpose control drawing methods and
* control size calculation methods (virtual) are overridden.
**/
bool OnAddBitmap(const wxBitmap& bitmap) override;
void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
#endif
#ifdef _WIN32
bool MSWOnDraw(WXDRAWITEMSTRUCT* item) override;
void DrawBackground_(wxDC& dc, const wxRect& rect, int WXUNUSED(item), int flags) const;

View File

@ -17,9 +17,6 @@ void ButtonsDescription::FillSizerWithTextColorDescriptions(wxSizer* sizer, wxWi
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(3, 5, 5);
sizer->Add(grid_sizer, 0, wxEXPAND);
ScalableBitmap bmp_delete = ScalableBitmap(parent, "cross");
ScalableBitmap bmp_delete_focus = ScalableBitmap(parent, "cross_focus");
auto add_color = [grid_sizer, parent](wxColourPickerCtrl** color_picker, const wxColour& color, const wxColour& def_color, wxString label_text) {
// wrap the label_text to the max 80 characters
if (label_text.Len() > 80) {

File diff suppressed because it is too large Load Diff

View File

@ -519,7 +519,7 @@ private:
ssize_t item_hover;
size_t last_page;
int item_height() const { return std::max(bullet_black.bmp().GetSize().GetHeight(), em_w) + em_w; }
int item_height() const { return std::max(bullet_black.GetHeight(), em_w) + em_w; }
void on_paint(wxPaintEvent &evt);
void on_mouse_move(wxMouseEvent &evt);

View File

@ -0,0 +1,104 @@
#include "libslic3r/libslic3r.h"
#include "CoordAxes.hpp"
#include "GUI_App.hpp"
#include "3DScene.hpp"
#if ENABLE_GL_SHADERS_ATTRIBUTES
#include "Plater.hpp"
#include "Camera.hpp"
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#include <GL/glew.h>
#if ENABLE_WORLD_COORDINATE
namespace Slic3r {
namespace GUI {
const float CoordAxes::DefaultStemRadius = 0.5f;
const float CoordAxes::DefaultStemLength = 25.0f;
const float CoordAxes::DefaultTipRadius = 2.5f * CoordAxes::DefaultStemRadius;
const float CoordAxes::DefaultTipLength = 5.0f;
#if ENABLE_GL_SHADERS_ATTRIBUTES
void CoordAxes::render(const Transform3d& trafo, float emission_factor)
#else
void CoordAxes::render(float emission_factor)
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
{
#if ENABLE_GL_SHADERS_ATTRIBUTES
auto render_axis = [this](GLShaderProgram& shader, const Transform3d& transform) {
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d matrix = camera.get_view_matrix() * transform;
shader.set_uniform("view_model_matrix", matrix);
shader.set_uniform("projection_matrix", camera.get_projection_matrix());
shader.set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
m_arrow.render();
#else
auto render_axis = [this](const Transform3f& transform) {
glsafe(::glPushMatrix());
glsafe(::glMultMatrixf(transform.data()));
m_arrow.render();
glsafe(::glPopMatrix());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
};
if (!m_arrow.is_initialized())
m_arrow.init_from(stilized_arrow(16, m_tip_radius, m_tip_length, m_stem_radius, m_stem_length));
GLShaderProgram* curr_shader = wxGetApp().get_current_shader();
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr)
return;
if (curr_shader != nullptr)
curr_shader->stop_using();
shader->start_using();
shader->set_uniform("emission_factor", emission_factor);
// x axis
#if ENABLE_LEGACY_OPENGL_REMOVAL
m_arrow.set_color(ColorRGBA::X());
#else
m_arrow.set_color(-1, ColorRGBA::X());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }));
#else
render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast<float>());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
// y axis
#if ENABLE_LEGACY_OPENGL_REMOVAL
m_arrow.set_color(ColorRGBA::Y());
#else
m_arrow.set_color(-1, ColorRGBA::Y());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }));
#else
render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast<float>());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
// z axis
#if ENABLE_LEGACY_OPENGL_REMOVAL
m_arrow.set_color(ColorRGBA::Z());
#else
m_arrow.set_color(-1, ColorRGBA::Z());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES
render_axis(*shader, trafo * Geometry::assemble_transform(m_origin));
#else
render_axis(Geometry::assemble_transform(m_origin).cast<float>());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
shader->stop_using();
if (curr_shader != nullptr)
curr_shader->start_using();
}
} // GUI
} // Slic3r
#endif // ENABLE_WORLD_COORDINATE

View File

@ -0,0 +1,64 @@
#ifndef slic3r_CoordAxes_hpp_
#define slic3r_CoordAxes_hpp_
#if ENABLE_WORLD_COORDINATE
#include "GLModel.hpp"
namespace Slic3r {
namespace GUI {
class CoordAxes
{
public:
static const float DefaultStemRadius;
static const float DefaultStemLength;
static const float DefaultTipRadius;
static const float DefaultTipLength;
private:
Vec3d m_origin{ Vec3d::Zero() };
float m_stem_radius{ DefaultStemRadius };
float m_stem_length{ DefaultStemLength };
float m_tip_radius{ DefaultTipRadius };
float m_tip_length{ DefaultTipLength };
GLModel m_arrow;
public:
const Vec3d& get_origin() const { return m_origin; }
void set_origin(const Vec3d& origin) { m_origin = origin; }
void set_stem_radius(float radius) {
m_stem_radius = radius;
m_arrow.reset();
}
void set_stem_length(float length) {
m_stem_length = length;
m_arrow.reset();
}
void set_tip_radius(float radius) {
m_tip_radius = radius;
m_arrow.reset();
}
void set_tip_length(float length) {
m_tip_length = length;
m_arrow.reset();
}
float get_stem_radius() const { return m_stem_radius; }
float get_stem_length() const { return m_stem_length; }
float get_tip_radius() const { return m_tip_radius; }
float get_tip_length() const { return m_tip_length; }
float get_total_length() const { return m_stem_length + m_tip_length; }
#if ENABLE_GL_SHADERS_ATTRIBUTES
void render(const Transform3d& trafo, float emission_factor = 0.0f);
#else
void render(float emission_factor = 0.0f);
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
};
} // GUI
} // Slic3r
#endif // ENABLE_WORLD_COORDINATE
#endif // slic3r_CoordAxes_hpp_

View File

@ -86,24 +86,24 @@ Control::Control( wxWindow *parent,
m_bmp_thumb_higher = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "thumb_right") : ScalableBitmap(this, "thumb_up"));
m_bmp_thumb_lower = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "thumb_left") : ScalableBitmap(this, "thumb_down"));
m_thumb_size = m_bmp_thumb_lower.GetBmpSize();
m_thumb_size = m_bmp_thumb_lower.GetSize();
m_bmp_add_tick_on = ScalableBitmap(this, "colorchange_add");
m_bmp_add_tick_off = ScalableBitmap(this, "colorchange_add_f");
m_bmp_del_tick_on = ScalableBitmap(this, "colorchange_del");
m_bmp_del_tick_off = ScalableBitmap(this, "colorchange_del_f");
m_tick_icon_dim = m_bmp_add_tick_on.GetBmpWidth();
m_tick_icon_dim = m_bmp_add_tick_on.GetWidth();
m_bmp_one_layer_lock_on = ScalableBitmap(this, "lock_closed");
m_bmp_one_layer_lock_off = ScalableBitmap(this, "lock_closed_f");
m_bmp_one_layer_unlock_on = ScalableBitmap(this, "lock_open");
m_bmp_one_layer_unlock_off = ScalableBitmap(this, "lock_open_f");
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetBmpWidth();
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetWidth();
m_bmp_revert = ScalableBitmap(this, "undo");
m_revert_icon_dim = m_bmp_revert.GetBmpWidth();
m_revert_icon_dim = m_bmp_revert.GetWidth();
m_bmp_cog = ScalableBitmap(this, "cog");
m_cog_icon_dim = m_bmp_cog.GetBmpWidth();
m_cog_icon_dim = m_bmp_cog.GetWidth();
m_selection = ssUndef;
m_ticks.set_pause_print_msg(_utf8(L("Place bearings in slots and resume printing")));
@ -155,26 +155,11 @@ void Control::msw_rescale()
{
m_font = GUI::wxGetApp().normal_font();
m_bmp_thumb_higher.msw_rescale();
m_bmp_thumb_lower .msw_rescale();
m_thumb_size = m_bmp_thumb_lower.bmp().GetSize();
m_bmp_add_tick_on .msw_rescale();
m_bmp_add_tick_off.msw_rescale();
m_bmp_del_tick_on .msw_rescale();
m_bmp_del_tick_off.msw_rescale();
m_tick_icon_dim = m_bmp_add_tick_on.bmp().GetSize().x;
m_bmp_one_layer_lock_on .msw_rescale();
m_bmp_one_layer_lock_off .msw_rescale();
m_bmp_one_layer_unlock_on .msw_rescale();
m_bmp_one_layer_unlock_off.msw_rescale();
m_lock_icon_dim = m_bmp_one_layer_lock_on.bmp().GetSize().x;
m_bmp_revert.msw_rescale();
m_revert_icon_dim = m_bmp_revert.bmp().GetSize().x;
m_bmp_cog.msw_rescale();
m_cog_icon_dim = m_bmp_cog.bmp().GetSize().x;
m_thumb_size = m_bmp_thumb_lower.GetSize();
m_tick_icon_dim = m_bmp_add_tick_on.GetWidth();
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetWidth();
m_revert_icon_dim = m_bmp_revert.GetWidth();
m_cog_icon_dim = m_bmp_cog.GetWidth();
SLIDER_MARGIN = 4 + GUI::wxGetApp().em_unit();
@ -189,22 +174,18 @@ void Control::sys_color_changed()
{
GUI::wxGetApp().UpdateDarkUI(GetParent());
m_bmp_add_tick_on .msw_rescale();
m_bmp_add_tick_off.msw_rescale();
m_bmp_del_tick_on .msw_rescale();
m_bmp_del_tick_off.msw_rescale();
m_tick_icon_dim = m_bmp_add_tick_on.GetBmpWidth();
m_bmp_add_tick_on .sys_color_changed();
m_bmp_add_tick_off.sys_color_changed();
m_bmp_del_tick_on .sys_color_changed();
m_bmp_del_tick_off.sys_color_changed();
m_bmp_one_layer_lock_on .msw_rescale();
m_bmp_one_layer_lock_off .msw_rescale();
m_bmp_one_layer_unlock_on .msw_rescale();
m_bmp_one_layer_unlock_off.msw_rescale();
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetBmpWidth();
m_bmp_one_layer_lock_on .sys_color_changed();
m_bmp_one_layer_lock_off .sys_color_changed();
m_bmp_one_layer_unlock_on .sys_color_changed();
m_bmp_one_layer_unlock_off.sys_color_changed();
m_bmp_revert.msw_rescale();
m_revert_icon_dim = m_bmp_revert.GetBmpWidth();
m_bmp_cog.msw_rescale();
m_cog_icon_dim = m_bmp_cog.GetBmpWidth();
m_bmp_revert.sys_color_changed();
m_bmp_cog .sys_color_changed();
}
int Control::GetActiveValue() const
@ -604,9 +585,12 @@ void Control::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_
return;
}
wxBitmap* icon = m_focus == fiActionIcon ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp();
//wxBitmap* icon = m_focus == fiActionIcon ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp();
//if (m_ticks.ticks.find(TickCode{tick}) != m_ticks.ticks.end())
// icon = m_focus == fiActionIcon ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp();
ScalableBitmap* icon = m_focus == fiActionIcon ? &m_bmp_add_tick_off : &m_bmp_add_tick_on;
if (m_ticks.ticks.find(TickCode{tick}) != m_ticks.ticks.end())
icon = m_focus == fiActionIcon ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp();
icon = m_focus == fiActionIcon ? &m_bmp_del_tick_off : &m_bmp_del_tick_on;
wxCoord x_draw, y_draw;
is_horizontal() ? x_draw = pt_beg.x - 0.5*m_tick_icon_dim : y_draw = pt_beg.y - 0.5*m_tick_icon_dim;
@ -615,10 +599,12 @@ void Control::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_
else
is_horizontal() ? y_draw = pt_beg.y - m_tick_icon_dim-2 : x_draw = pt_end.x + 3;
if (m_draw_mode == dmSequentialFffPrint)
dc.DrawBitmap(create_scaled_bitmap("colorchange_add", nullptr, 16, true), x_draw, y_draw);
if (m_draw_mode == dmSequentialFffPrint) {
wxBitmap disabled_add = get_bmp_bundle("colorchange_add")->GetBitmapFor(this).ConvertToDisabled();
dc.DrawBitmap(disabled_add, x_draw, y_draw);
}
else
dc.DrawBitmap(*icon, x_draw, y_draw);
dc.DrawBitmap((*icon).get_bitmap(), x_draw, y_draw);
//update rect of the tick action icon
m_rect_tick_action = wxRect(x_draw, y_draw, m_tick_icon_dim, m_tick_icon_dim);
@ -851,7 +837,7 @@ void Control::draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider
{
wxCoord x_draw = pos.x - int(0.5 * m_thumb_size.x);
wxCoord y_draw = pos.y - int(0.5 * m_thumb_size.y);
dc.DrawBitmap(selection == ssLower ? m_bmp_thumb_lower.bmp() : m_bmp_thumb_higher.bmp(), x_draw, y_draw);
dc.DrawBitmap(selection == ssLower ? m_bmp_thumb_lower.get_bitmap() : m_bmp_thumb_higher.get_bitmap(), x_draw, y_draw);
// Update thumb rect
update_thumb_rect(x_draw, y_draw, selection);
@ -945,12 +931,12 @@ void Control::draw_ticks(wxDC& dc)
// Draw icon for "Pause print", "Custom Gcode" or conflict tick
if (!icon_name.empty()) {
wxBitmap icon = create_scaled_bitmap(icon_name);
wxBitmapBundle* icon = get_bmp_bundle(icon_name);
wxCoord x_draw, y_draw;
is_horizontal() ? x_draw = pos - 0.5 * m_tick_icon_dim : y_draw = pos - 0.5 * m_tick_icon_dim;
is_horizontal() ? y_draw = mid + 22 : x_draw = mid + m_thumb_size.x + 3;
dc.DrawBitmap(icon, x_draw, y_draw);
dc.DrawBitmap(icon->GetBitmapFor(this), x_draw, y_draw);
}
}
}
@ -1262,9 +1248,12 @@ void Control::draw_one_layer_icon(wxDC& dc)
if (m_draw_mode == dmSequentialGCodeView)
return;
const wxBitmap& icon = m_is_one_layer ?
m_focus == fiOneLayerIcon ? m_bmp_one_layer_lock_off.bmp() : m_bmp_one_layer_lock_on.bmp() :
m_focus == fiOneLayerIcon ? m_bmp_one_layer_unlock_off.bmp() : m_bmp_one_layer_unlock_on.bmp();
//const wxBitmap& icon = m_is_one_layer ?
// m_focus == fiOneLayerIcon ? m_bmp_one_layer_lock_off.bmp() : m_bmp_one_layer_lock_on.bmp() :
// m_focus == fiOneLayerIcon ? m_bmp_one_layer_unlock_off.bmp() : m_bmp_one_layer_unlock_on.bmp();
const ScalableBitmap& icon = m_is_one_layer ?
m_focus == fiOneLayerIcon ? m_bmp_one_layer_lock_off : m_bmp_one_layer_lock_on :
m_focus == fiOneLayerIcon ? m_bmp_one_layer_unlock_off : m_bmp_one_layer_unlock_on;
int width, height;
get_size(&width, &height);
@ -1273,7 +1262,7 @@ void Control::draw_one_layer_icon(wxDC& dc)
is_horizontal() ? x_draw = width-2 : x_draw = 0.5*width - 0.5*m_lock_icon_dim;
is_horizontal() ? y_draw = 0.5*height - 0.5*m_lock_icon_dim : y_draw = height-2;
dc.DrawBitmap(icon, x_draw, y_draw);
dc.DrawBitmap(icon.bmp().GetBitmapFor(this), x_draw, y_draw);
//update rect of the lock/unlock icon
m_rect_one_layer_icon = wxRect(x_draw, y_draw, m_lock_icon_dim, m_lock_icon_dim);
@ -1291,7 +1280,7 @@ void Control::draw_revert_icon(wxDC& dc)
is_horizontal() ? x_draw = width-2 : x_draw = 0.25*SLIDER_MARGIN;
is_horizontal() ? y_draw = 0.25*SLIDER_MARGIN: y_draw = height-2;
dc.DrawBitmap(m_bmp_revert.bmp(), x_draw, y_draw);
dc.DrawBitmap(m_bmp_revert.get_bitmap(), x_draw, y_draw);
//update rect of the lock/unlock icon
m_rect_revert_icon = wxRect(x_draw, y_draw, m_revert_icon_dim, m_revert_icon_dim);
@ -1315,7 +1304,7 @@ void Control::draw_cog_icon(wxDC& dc)
is_horizontal() ? y_draw = height - m_cog_icon_dim - 2 : y_draw = height - 2;
}
dc.DrawBitmap(m_bmp_cog.bmp(), x_draw, y_draw);
dc.DrawBitmap(m_bmp_cog.get_bitmap(), x_draw, y_draw);
//update rect of the lock/unlock icon
m_rect_cog_icon = wxRect(x_draw, y_draw, m_cog_icon_dim, m_cog_icon_dim);
@ -1673,7 +1662,7 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current
if (extruders_cnt > 1) {
std::array<int, 2> active_extruders = get_active_extruders_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
std::vector<wxBitmapBundle*> icons = get_extruder_color_icons(true);
wxMenu* change_extruder_menu = new wxMenu();
@ -1684,7 +1673,7 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current
if (m_mode == MultiAsSingle)
append_menu_item(change_extruder_menu, wxID_ANY, item_name, "",
[this, i](wxCommandEvent&) { add_code_as_tick(ToolChange, i); }, *icons[i-1], menu,
[this, i](wxCommandEvent&) { add_code_as_tick(ToolChange, i); }, icons[i-1], menu,
[is_active_extruder]() { return !is_active_extruder; }, GUI::wxGetApp().plater());
}
@ -1722,7 +1711,7 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren
format_wxstr(_L("Switch code to Color change (%1%) for:"), gcode(ColorChange)) :
format_wxstr(_L("Add color change (%1%) for:"), gcode(ColorChange));
wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
add_color_change_menu_item->SetBitmap(create_menu_bitmap("colorchange_add_m"));
add_color_change_menu_item->SetBitmap(*get_bmp_bundle("colorchange_add_m"));
}
}

View File

@ -33,6 +33,15 @@ wxIMPLEMENT_DYNAMIC_CLASS(DataViewBitmapText, wxObject)
IMPLEMENT_VARIANT_OBJECT(DataViewBitmapText)
static wxSize get_size(const wxBitmap& icon)
{
#ifdef __WIN32__
return icon.GetSize();
#else
return icon.GetScaledSize();
#endif
}
// ---------------------------------------------------------
// BitmapTextRenderer
// ---------------------------------------------------------
@ -124,11 +133,7 @@ bool BitmapTextRenderer::Render(wxRect rect, wxDC *dc, int state)
const wxBitmap& icon = m_value.GetBitmap();
if (icon.IsOk())
{
#ifdef __APPLE__
wxSize icon_sz = icon.GetScaledSize();
#else
wxSize icon_sz = icon.GetSize();
#endif
wxSize icon_sz = get_size(icon);
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon_sz.y) / 2);
xoffset = icon_sz.x + 4;
}
@ -264,11 +269,13 @@ bool BitmapChoiceRenderer::Render(wxRect rect, wxDC* dc, int state)
const wxBitmap& icon = m_value.GetBitmap();
if (icon.IsOk())
{
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon.GetHeight()) / 2);
xoffset = icon.GetWidth() + 4;
wxSize icon_sz = get_size(icon);
dc->DrawBitmap(icon, rect.x, rect.y + (rect.height - icon_sz.GetHeight()) / 2);
xoffset = icon_sz.GetWidth() + 4;
if (rect.height==0)
rect.height= icon.GetHeight();
rect.height= icon_sz.GetHeight();
}
#ifdef _WIN32
@ -297,7 +304,7 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
if (can_create_editor_ctrl && !can_create_editor_ctrl())
return nullptr;
std::vector<wxBitmap*> icons = get_extruder_color_icons();
std::vector<wxBitmapBundle*> icons = get_extruder_color_icons();
if (icons.empty())
return nullptr;

View File

@ -264,9 +264,6 @@ void ExtruderSequenceDialog::on_dpi_changed(const wxRect& suggested_rect)
{
SetFont(wxGetApp().normal_font());
m_bmp_add.msw_rescale();
m_bmp_del.msw_rescale();
const int em = em_unit();
m_intervals_grid_sizer->SetHGap(em);

View File

@ -106,14 +106,14 @@ public:
bool set_undo_to_sys_tooltip(const wxString* tip) { return m_undo_ui.set_undo_to_sys_tooltip(tip); }
// ui items used for revert line value
bool has_undo_ui() const { return m_undo_ui.undo_bitmap != nullptr; }
const wxBitmap& undo_bitmap() const { return m_undo_ui.undo_bitmap->bmp(); }
const wxString* undo_tooltip() const { return m_undo_ui.undo_tooltip; }
const wxBitmap& undo_to_sys_bitmap() const { return m_undo_ui.undo_to_sys_bitmap->bmp(); }
const wxString* undo_to_sys_tooltip() const { return m_undo_ui.undo_to_sys_tooltip; }
const wxColour* label_color() const { return m_undo_ui.label_color; }
const bool blink() const { return m_undo_ui.blink; }
bool* get_blink_ptr() { return &m_undo_ui.blink; }
bool has_undo_ui() const { return m_undo_ui.undo_bitmap != nullptr; }
const wxBitmapBundle& undo_bitmap() const { return m_undo_ui.undo_bitmap->bmp(); }
const wxString* undo_tooltip() const { return m_undo_ui.undo_tooltip; }
const wxBitmapBundle& undo_to_sys_bitmap() const { return m_undo_ui.undo_to_sys_bitmap->bmp(); }
const wxString* undo_to_sys_tooltip() const { return m_undo_ui.undo_to_sys_tooltip; }
const wxColour* label_color() const { return m_undo_ui.label_color; }
const bool blink() const { return m_undo_ui.blink; }
bool* get_blink_ptr() { return &m_undo_ui.blink; }
};

View File

@ -386,14 +386,14 @@ void GCodeViewer::SequentialView::Marker::render()
ImGui::PopStyleVar();
}
void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, std::vector<size_t> &&lines_ends)
void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, const std::vector<size_t>& lines_ends)
{
assert(! m_file.is_open());
if (m_file.is_open())
return;
m_filename = filename;
m_lines_ends = std::move(lines_ends);
m_lines_ends = lines_ends;
m_selected_line_id = 0;
m_last_lines_size = 0;
@ -771,9 +771,7 @@ void GCodeViewer::load(const GCodeProcessorResult& gcode_result, const Print& pr
// release gpu memory, if used
reset();
m_sequential_view.gcode_window.load_gcode(gcode_result.filename,
// Stealing out lines_ends should be safe because this gcode_result is processed only once (see the 1st if in this function).
std::move(const_cast<std::vector<size_t>&>(gcode_result.lines_ends)));
m_sequential_view.gcode_window.load_gcode(gcode_result.filename, gcode_result.lines_ends);
if (wxGetApp().is_gcode_viewer())
m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z;
@ -993,11 +991,13 @@ void GCodeViewer::render()
render_toolpaths();
render_shells();
float legend_height = 0.0f;
render_legend(legend_height);
if (m_sequential_view.current.last != m_sequential_view.endpoints.last) {
m_sequential_view.marker.set_world_position(m_sequential_view.current_position);
m_sequential_view.marker.set_world_offset(m_sequential_view.current_offset);
m_sequential_view.render(legend_height);
if (!m_layers.empty()) {
render_legend(legend_height);
if (m_sequential_view.current.last != m_sequential_view.endpoints.last) {
m_sequential_view.marker.set_world_position(m_sequential_view.current_position);
m_sequential_view.marker.set_world_offset(m_sequential_view.current_offset);
m_sequential_view.render(legend_height);
}
}
#if ENABLE_GCODE_VIEWER_STATISTICS
render_statistics();

File diff suppressed because it is too large Load Diff

View File

@ -1101,6 +1101,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>);
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
#if ENABLE_WORLD_COORDINATE
wxDEFINE_EVENT(EVT_GLCANVAS_RESET_SKEW, SimpleEvent);
#endif // ENABLE_WORLD_COORDINATE
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
@ -2914,7 +2917,13 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
else
displacement = multiplier * direction;
#if ENABLE_WORLD_COORDINATE
TransformationType trafo_type;
trafo_type.set_relative();
m_selection.translate(displacement, trafo_type);
#else
m_selection.translate(displacement);
#endif // ENABLE_WORLD_COORDINATE
m_dirty = true;
}
);
@ -3584,7 +3593,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
#if ENABLE_WORLD_COORDINATE
TransformationType trafo_type;
trafo_type.set_relative();
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type);
#else
m_selection.translate(cur_pos - m_mouse.drag.start_position_3D);
#endif // ENABLE_WORLD_COORDINATE
if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects)
update_sequential_clearance();
wxGetApp().obj_manipul()->set_dirty();
@ -3830,9 +3845,17 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance)
#if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
#else
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_WORLD_COORDINATE
else if (selection_mode == Selection::Volume)
#if ENABLE_WORLD_COORDINATE
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
#endif // ENABLE_WORLD_COORDINATE
object_moved = true;
model_object->invalidate_bounding_box();
@ -3912,8 +3935,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
int object_idx = v->object_idx();
if (object_idx == 1000) { // the wipe tower
#endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
Vec3d offset = v->get_volume_offset();
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset(0), offset(1), v->get_volume_rotation()(2))));
const Vec3d offset = v->get_volume_offset();
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
}
#if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL
int object_idx = v->object_idx();
@ -3921,8 +3944,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
continue;
int instance_idx = v->instance_idx();
int volume_idx = v->volume_idx();
const int instance_idx = v->instance_idx();
const int volume_idx = v->volume_idx();
done.insert(std::pair<int, int>(object_idx, instance_idx));
@ -3930,12 +3953,20 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance) {
#if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
#else
model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_WORLD_COORDINATE
}
else if (selection_mode == Selection::Volume) {
#if ENABLE_WORLD_COORDINATE
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else
model_object->volumes[volume_idx]->set_rotation(v->get_volume_rotation());
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
#endif // ENABLE_WORLD_COORDINATE
}
model_object->invalidate_bounding_box();
}
@ -3985,12 +4016,12 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
Selection::EMode selection_mode = m_selection.get_mode();
for (const GLVolume* v : m_volumes.volumes) {
int object_idx = v->object_idx();
const int object_idx = v->object_idx();
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
continue;
int instance_idx = v->instance_idx();
int volume_idx = v->volume_idx();
const int instance_idx = v->instance_idx();
const int volume_idx = v->volume_idx();
done.insert(std::pair<int, int>(object_idx, instance_idx));
@ -3998,13 +4029,22 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance) {
#if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
#else
model_object->instances[instance_idx]->set_scaling_factor(v->get_instance_scaling_factor());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
#endif // ENABLE_WORLD_COORDINATE
}
else if (selection_mode == Selection::Volume) {
#if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor());
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
#endif // ENABLE_WORLD_COORDINATE
}
model_object->invalidate_bounding_box();
}
@ -4013,10 +4053,10 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
// Fixes sinking/flying instances
for (const std::pair<int, int>& i : done) {
ModelObject* m = m_model->objects[i.first];
double shift_z = m->get_instance_min_z(i.second);
const double shift_z = m->get_instance_min_z(i.second);
// leave sinking instances as sinking
if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) {
Vec3d shift(0.0, 0.0, -shift_z);
const Vec3d shift(0.0, 0.0, -shift_z);
m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift);
}
@ -4066,9 +4106,17 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance)
#if ENABLE_WORLD_COORDINATE
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
#else
model_object->instances[instance_idx]->set_mirror(v->get_instance_mirror());
#endif // ENABLE_WORLD_COORDINATE
else if (selection_mode == Selection::Volume)
#if ENABLE_WORLD_COORDINATE
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
#else
model_object->volumes[volume_idx]->set_mirror(v->get_volume_mirror());
#endif // ENABLE_WORLD_COORDINATE
model_object->invalidate_bounding_box();
}
@ -4092,6 +4140,44 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
m_dirty = true;
}
#if ENABLE_WORLD_COORDINATE
void GLCanvas3D::do_reset_skew(const std::string& snapshot_type)
{
if (m_model == nullptr)
return;
if (!snapshot_type.empty())
wxGetApp().plater()->take_snapshot(_(snapshot_type));
std::set<std::pair<int, int>> done; // keeps track of modified instances
const Selection::IndicesList& idxs = m_selection.get_volume_idxs();
for (unsigned int id : idxs) {
const GLVolume* v = m_volumes.volumes[id];
int object_idx = v->object_idx();
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
continue;
int instance_idx = v->instance_idx();
int volume_idx = v->volume_idx();
done.insert(std::pair<int, int>(object_idx, instance_idx));
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
model_object->invalidate_bounding_box();
}
}
post_event(SimpleEvent(EVT_GLCANVAS_RESET_SKEW));
m_dirty = true;
}
#endif // ENABLE_WORLD_COORDINATE
void GLCanvas3D::update_gizmos_on_off_state()
{
set_as_dirty();
@ -5339,7 +5425,7 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
void GLCanvas3D::_picking_pass()
{
if (m_picking_enabled && !m_mouse.dragging && m_mouse.position != Vec2d(DBL_MAX, DBL_MAX)) {
if (m_picking_enabled && !m_mouse.dragging && m_mouse.position != Vec2d(DBL_MAX, DBL_MAX) && !m_gizmos.is_dragging()) {
m_hover_volume_idxs.clear();
// Render the object for picking.
@ -7352,12 +7438,13 @@ bool GLCanvas3D::_is_any_volume_outside() const
void GLCanvas3D::_update_selection_from_hover()
{
bool ctrl_pressed = wxGetKeyState(WXK_CONTROL);
bool selection_changed = false;
if (m_hover_volume_idxs.empty()) {
if (!ctrl_pressed && m_rectangle_selection.get_state() == GLSelectionRectangle::EState::Select)
if (!ctrl_pressed && m_rectangle_selection.get_state() == GLSelectionRectangle::EState::Select) {
selection_changed = ! m_selection.is_empty();
m_selection.remove_all();
return;
}
}
GLSelectionRectangle::EState state = m_rectangle_selection.get_state();
@ -7370,7 +7457,6 @@ void GLCanvas3D::_update_selection_from_hover()
}
}
bool selection_changed = false;
#if ENABLE_NEW_RECTANGLE_SELECTION
if (!m_rectangle_selection.is_empty()) {
#endif // ENABLE_NEW_RECTANGLE_SELECTION

View File

@ -156,6 +156,9 @@ wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_FORCE_UPDATE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
#if ENABLE_WORLD_COORDINATE
wxDECLARE_EVENT(EVT_GLCANVAS_RESET_SKEW, SimpleEvent);
#endif // ENABLE_WORLD_COORDINATE
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
@ -739,7 +742,11 @@ public:
void update_volumes_colors_by_extruder();
#if ENABLE_WORLD_COORDINATE
bool is_dragging() const { return m_gizmos.is_dragging() || (m_moving && !m_mouse.scene_position.isApprox(m_mouse.drag.start_position_3D)); }
#else
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
#endif // ENABLE_WORLD_COORDINATE
void render();
// printable_only == false -> render also non printable volumes as grayed
@ -807,6 +814,9 @@ public:
void do_rotate(const std::string& snapshot_type);
void do_scale(const std::string& snapshot_type);
void do_mirror(const std::string& snapshot_type);
#if ENABLE_WORLD_COORDINATE
void do_reset_skew(const std::string& snapshot_type);
#endif // ENABLE_WORLD_COORDINATE
void update_gizmos_on_off_state();
void reset_all_gizmos() { m_gizmos.reset_all_states(); }
@ -844,7 +854,6 @@ public:
// Returns the view ray line, in world coordinate, at the given mouse position.
Linef3 mouse_ray(const Point& mouse_pos);
void set_mouse_as_dragging() { m_mouse.dragging = true; }
bool is_mouse_dragging() const { return m_mouse.dragging; }
double get_size_proportional_to_max_bed_size(double factor) const;

View File

@ -7,6 +7,7 @@
#include "GUI_App.hpp"
#include "GLModel.hpp"
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#include "BitmapCache.hpp"
#include <GL/glew.h>
@ -22,8 +23,8 @@
#define STB_DXT_IMPLEMENTATION
#include "stb_dxt/stb_dxt.h"
#include "nanosvg/nanosvg.h"
#include "nanosvg/nanosvgrast.h"
#include <nanosvg/nanosvg.h>
#include <nanosvg/nanosvgrast.h>
#include "libslic3r/Utils.hpp"
@ -204,7 +205,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
if (!boost::algorithm::iends_with(filename, ".svg"))
continue;
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
NSVGimage* image = BitmapCache::nsvgParseFromFileWithReplace(filename.c_str(), "px", 96.0f, {});
if (image == nullptr)
continue;
@ -536,7 +537,7 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
{
bool compression_enabled = compress && GLEW_EXT_texture_compression_s3tc;
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
NSVGimage* image = BitmapCache::nsvgParseFromFileWithReplace(filename.c_str(), "px", 96.0f, {});
if (image == nullptr) {
reset();
return false;

File diff suppressed because it is too large Load Diff

View File

@ -142,14 +142,13 @@ std::map<std::string, std::string> SettingsFactory::CATEGORY_ICON =
{ L("Hollowing") , "hollowing" }
};
wxBitmap SettingsFactory::get_category_bitmap(const std::string& category_name, bool menu_bmp /*= true*/)
wxBitmapBundle* SettingsFactory::get_category_bitmap(const std::string& category_name)
{
if (CATEGORY_ICON.find(category_name) == CATEGORY_ICON.end())
return wxNullBitmap;
return menu_bmp ? create_menu_bitmap(CATEGORY_ICON.at(category_name)) : create_scaled_bitmap(CATEGORY_ICON.at(category_name));
return get_bmp_bundle("empty");
return get_bmp_bundle(CATEGORY_ICON.at(category_name));
}
//-------------------------------------
// MenuFactory
//-------------------------------------
@ -430,12 +429,12 @@ static void create_freq_settings_popupmenu(wxMenu* menu, const bool is_object_se
#endif
}
std::vector<wxBitmap> MenuFactory::get_volume_bitmaps()
std::vector<wxBitmapBundle*> MenuFactory::get_volume_bitmaps()
{
std::vector<wxBitmap> volume_bmps;
std::vector<wxBitmapBundle*> volume_bmps;
volume_bmps.reserve(ADD_VOLUME_MENU_ITEMS.size());
for (auto item : ADD_VOLUME_MENU_ITEMS)
volume_bmps.push_back(create_menu_bitmap(item.second));
volume_bmps.push_back(get_bmp_bundle(item.second));
return volume_bmps;
}
@ -620,7 +619,7 @@ wxMenuItem* MenuFactory::append_menu_item_settings(wxMenu* menu_)
// Add full settings list
auto menu_item = new wxMenuItem(menu, wxID_ANY, menu_name);
menu_item->SetBitmap(create_menu_bitmap("cog"));
menu_item->SetBitmap(*get_bmp_bundle("cog"));
menu_item->SetSubMenu(create_settings_popupmenu(menu, is_object_settings, item));
return menu->Append(menu_item);
@ -765,7 +764,7 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
return;
}
std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
std::vector<wxBitmapBundle*> icons = get_extruder_color_icons(true);
wxMenu* extruder_selection_menu = new wxMenu();
const wxString& name = sels.Count() == 1 ? names[0] : names[1];
@ -784,7 +783,7 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
(is_active_extruder ? " (" + _L("active") + ")" : "");
append_menu_item(extruder_selection_menu, wxID_ANY, item_name, "",
[i](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(i); }, *icons[icon_idx], menu,
[i](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(i); }, icons[icon_idx], menu,
[is_active_extruder]() { return !is_active_extruder; }, m_parent);
}
@ -1144,12 +1143,6 @@ void MenuFactory::update_default_menu()
create_default_menu();
}
void MenuFactory::msw_rescale()
{
for (MenuWithSeparators* menu : { &m_object_menu, &m_sla_object_menu, &m_part_menu, &m_default_menu })
msw_rescale_menu(dynamic_cast<wxMenu*>(menu));
}
#ifdef _WIN32
// For this class is used code from stackoverflow:
// https://stackoverflow.com/questions/257288/is-it-possible-to-write-a-template-to-check-for-a-functions-existence
@ -1179,7 +1172,7 @@ static void update_menu_item_def_colors(T* item)
void MenuFactory::sys_color_changed()
{
for (MenuWithSeparators* menu : { &m_object_menu, &m_sla_object_menu, &m_part_menu, &m_default_menu }) {
msw_rescale_menu(dynamic_cast<wxMenu*>(menu));// msw_rescale_menu updates just icons, so use it
sys_color_changed_menu(dynamic_cast<wxMenu*>(menu));// msw_rescale_menu updates just icons, so use it
#ifdef _WIN32
// but under MSW we have to update item's bachground color
for (wxMenuItem* item : menu->GetMenuItems())
@ -1192,14 +1185,17 @@ void MenuFactory::sys_color_changed(wxMenuBar* menubar)
{
for (size_t id = 0; id < menubar->GetMenuCount(); id++) {
wxMenu* menu = menubar->GetMenu(id);
msw_rescale_menu(menu);
sys_color_changed_menu(menu);
#ifndef __linux__
menu->SetupBitmaps();
#ifdef _WIN32
// but under MSW we have to update item's bachground color
for (wxMenuItem* item : menu->GetMenuItems())
update_menu_item_def_colors(item);
#endif
#endif
}
menubar->Refresh();
// menubar->Refresh();
}

View File

@ -25,7 +25,7 @@ struct SettingsFactory
typedef std::map<std::string, std::vector<std::string>> Bundle;
static std::map<std::string, std::string> CATEGORY_ICON;
static wxBitmap get_category_bitmap(const std::string& category_name, bool menu_bmp = true);
static wxBitmapBundle* get_category_bitmap(const std::string& category_name);
static Bundle get_bundle(const DynamicPrintConfig* config, bool is_object_settings);
static std::vector<std::string> get_options(bool is_part);
};
@ -34,7 +34,7 @@ class MenuFactory
{
public:
static const std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS;
static std::vector<wxBitmap> get_volume_bitmaps();
static std::vector<wxBitmapBundle*> get_volume_bitmaps();
MenuFactory();
~MenuFactory() = default;
@ -43,7 +43,6 @@ public:
void update();
void update_object_menu();
void update_default_menu();
void msw_rescale();
void sys_color_changed();
static void sys_color_changed(wxMenuBar* menu_bar);

View File

@ -0,0 +1,9 @@
#include "libslic3r/libslic3r.h"
#include "GUI_Geometry.hpp"
namespace Slic3r {
namespace GUI {
} // namespace Slic3r
} // namespace GUI

View File

@ -0,0 +1,81 @@
#ifndef slic3r_GUI_Geometry_hpp_
#define slic3r_GUI_Geometry_hpp_
namespace Slic3r {
namespace GUI {
#if ENABLE_WORLD_COORDINATE
enum class ECoordinatesType : unsigned char
{
World,
Instance,
Local
};
class TransformationType
{
public:
enum Enum {
// Transforming in a world coordinate system
World = 0,
// Transforming in a instance coordinate system
Instance = 1,
// Transforming in a local coordinate system
Local = 2,
// Absolute transformations, allowed in local coordinate system only.
Absolute = 0,
// Relative transformations, allowed in both local and world coordinate system.
Relative = 4,
// For group selection, the transformation is performed as if the group made a single solid body.
Joint = 0,
// For group selection, the transformation is performed on each object independently.
Independent = 8,
World_Relative_Joint = World | Relative | Joint,
World_Relative_Independent = World | Relative | Independent,
Instance_Absolute_Joint = Instance | Absolute | Joint,
Instance_Absolute_Independent = Instance | Absolute | Independent,
Instance_Relative_Joint = Instance | Relative | Joint,
Instance_Relative_Independent = Instance | Relative | Independent,
Local_Absolute_Joint = Local | Absolute | Joint,
Local_Absolute_Independent = Local | Absolute | Independent,
Local_Relative_Joint = Local | Relative | Joint,
Local_Relative_Independent = Local | Relative | Independent,
};
TransformationType() : m_value(World) {}
TransformationType(Enum value) : m_value(value) {}
TransformationType& operator=(Enum value) { m_value = value; return *this; }
Enum operator()() const { return m_value; }
bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
void set_world() { this->remove(Instance); this->remove(Local); }
void set_instance() { this->remove(Local); this->add(Instance); }
void set_local() { this->remove(Instance); this->add(Local); }
void set_absolute() { this->remove(Relative); }
void set_relative() { this->add(Relative); }
void set_joint() { this->remove(Independent); }
void set_independent() { this->add(Independent); }
bool world() const { return !this->has(Instance) && !this->has(Local); }
bool instance() const { return this->has(Instance); }
bool local() const { return this->has(Local); }
bool absolute() const { return !this->has(Relative); }
bool relative() const { return this->has(Relative); }
bool joint() const { return !this->has(Independent); }
bool independent() const { return this->has(Independent); }
private:
void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
Enum m_value;
};
#endif // ENABLE_WORLD_COORDINATE
} // namespace Slic3r
} // namespace GUI
#endif // slic3r_GUI_Geometry_hpp_

View File

@ -234,47 +234,47 @@ void ObjectLayers::UpdateAndShow(const bool show)
void ObjectLayers::msw_rescale()
{
m_bmp_delete.msw_rescale();
m_bmp_add.msw_rescale();
//m_bmp_delete.msw_rescale();
//m_bmp_add.msw_rescale();
m_grid_sizer->SetHGap(wxGetApp().em_unit());
//m_grid_sizer->SetHGap(wxGetApp().em_unit());
// rescale edit-boxes
const int cells_cnt = m_grid_sizer->GetCols() * m_grid_sizer->GetEffectiveRowsCount();
for (int i = 0; i < cells_cnt; ++i) {
const wxSizerItem* item = m_grid_sizer->GetItem(i);
if (item->IsWindow()) {
LayerRangeEditor* editor = dynamic_cast<LayerRangeEditor*>(item->GetWindow());
if (editor != nullptr)
editor->msw_rescale();
}
else if (item->IsSizer()) // case when we have editor with buttons
{
wxSizerItem* e_item = item->GetSizer()->GetItem(size_t(0)); // editor
if (e_item->IsWindow()) {
LayerRangeEditor* editor = dynamic_cast<LayerRangeEditor*>(e_item->GetWindow());
if (editor != nullptr)
editor->msw_rescale();
}
//// rescale edit-boxes
//const int cells_cnt = m_grid_sizer->GetCols() * m_grid_sizer->GetEffectiveRowsCount();
//for (int i = 0; i < cells_cnt; ++i) {
// const wxSizerItem* item = m_grid_sizer->GetItem(i);
// if (item->IsWindow()) {
// LayerRangeEditor* editor = dynamic_cast<LayerRangeEditor*>(item->GetWindow());
// if (editor != nullptr)
// editor->msw_rescale();
// }
// else if (item->IsSizer()) // case when we have editor with buttons
// {
// wxSizerItem* e_item = item->GetSizer()->GetItem(size_t(0)); // editor
// if (e_item->IsWindow()) {
// LayerRangeEditor* editor = dynamic_cast<LayerRangeEditor*>(e_item->GetWindow());
// if (editor != nullptr)
// editor->msw_rescale();
// }
if (item->GetSizer()->GetItemCount() > 2) // if there are Add/Del buttons
for (size_t btn : {2, 3}) { // del_btn, add_btn
wxSizerItem* b_item = item->GetSizer()->GetItem(btn);
if (b_item->IsWindow()) {
auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
if (button != nullptr)
button->msw_rescale();
}
}
}
}
// if (item->GetSizer()->GetItemCount() > 2) // if there are Add/Del buttons
// for (size_t btn : {2, 3}) { // del_btn, add_btn
// wxSizerItem* b_item = item->GetSizer()->GetItem(btn);
// if (b_item->IsWindow()) {
// auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
// if (button != nullptr)
// button->msw_rescale();
// }
// }
// }
//}
m_grid_sizer->Layout();
}
void ObjectLayers::sys_color_changed()
{
m_bmp_delete.msw_rescale();
m_bmp_add.msw_rescale();
m_bmp_delete.sys_color_changed();
m_bmp_add.sys_color_changed();
// rescale edit-boxes
const int cells_cnt = m_grid_sizer->GetCols() * m_grid_sizer->GetEffectiveRowsCount();
@ -286,7 +286,7 @@ void ObjectLayers::sys_color_changed()
if (b_item->IsWindow()) {
auto button = dynamic_cast<PlusMinusButton*>(b_item->GetWindow());
if (button != nullptr)
button->msw_rescale();
button->sys_color_changed();
}
}
}

View File

@ -973,12 +973,11 @@ void ObjectList::extruder_editing()
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
return;
const int column_width = GetColumn(colExtruder)->GetWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X) + 5;
wxPoint pos = this->get_mouse_position_in_control();
wxSize size = wxSize(column_width, -1);
pos.x = GetColumn(colName)->GetWidth() + GetColumn(colPrint)->GetWidth() + 5;
pos.y -= GetTextExtent("m").y;
wxRect rect = this->GetItemRect(item, GetColumn(colExtruder));
wxPoint pos = rect.GetPosition();
pos.y -= 4;
wxSize size = rect.GetSize();
size.SetWidth(size.GetWidth() + 8);
apply_extruder_selector(&m_extruder_editor, this, L("default"), pos, size);
@ -1541,9 +1540,13 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
const BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* v = selection.get_first_volume();
const Geometry::Transformation inst_transform = v->get_instance_transformation();
#if ENABLE_WORLD_COORDINATE
const Transform3d inv_inst_transform = inst_transform.get_matrix_no_offset().inverse();
#else
const Transform3d inv_inst_transform = inst_transform.get_matrix(true).inverse();
#endif // ENABLE_WORLD_COORDINATE
const Vec3d instance_offset = v->get_instance_offset();
for (size_t i = 0; i < input_files.size(); ++i) {
@ -1591,9 +1594,15 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset;
if (from_galery) {
#if ENABLE_WORLD_COORDINATE
// Transform the new modifier to be aligned with the print bed.
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
#else
// Transform the new modifier to be aligned with the print bed.
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(inst_transform, mesh_bb));
#endif // ENABLE_WORLD_COORDINATE
// Set the modifier position.
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset;
@ -1661,17 +1670,27 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
ModelVolume *new_volume = model_object.add_volume(std::move(mesh), type);
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* v = selection.get_first_volume();
#if ENABLE_WORLD_COORDINATE
// Transform the new modifier to be aligned with the print bed.
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
#else
// Transform the new modifier to be aligned with the print bed.
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
#endif // ENABLE_WORLD_COORDINATE
// Set the modifier position.
auto offset = (type_name == "Slab") ?
// Slab: Lift to print bed
Vec3d(0., 0., 0.5 * mesh_bb.size().z() + instance_bb.min.z() - v->get_instance_offset().z()) :
// Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - v->get_instance_offset();
#if ENABLE_WORLD_COORDINATE
new_volume->set_offset(v->get_instance_transformation().get_matrix_no_offset().inverse() * offset);
#else
new_volume->set_offset(v->get_instance_transformation().get_matrix(true).inverse() * offset);
#endif // ENABLE_WORLD_COORDINATE
const wxString name = _L("Generic") + "-" + _(type_name);
new_volume->name = into_u8(name);
@ -2444,6 +2463,21 @@ bool ObjectList::can_merge_to_single_object() const
return (*m_objects)[obj_idx]->volumes.size() > 1;
}
wxPoint ObjectList::get_mouse_position_in_control() const
{
wxPoint pt = wxGetMousePosition() - this->GetScreenPosition();
#ifdef __APPLE__
// Workaround for OSX. From wxWidgets 3.1.6 Hittest doesn't respect to the header of wxDataViewCtrl
if (wxDataViewItem top_item = this->GetTopItem(); top_item.IsOk()) {
auto rect = this->GetItemRect(top_item, this->GetColumn(0));
pt.y -= rect.y;
}
#endif // __APPLE__
return pt;
}
// NO_PARAMETERS function call means that changed object index will be determine from Selection()
void ObjectList::changed_object(const int obj_idx/* = -1*/) const
{
@ -2627,8 +2661,14 @@ void ObjectList::part_selection_changed()
Sidebar& panel = wxGetApp().sidebar();
panel.Freeze();
#if ENABLE_WORLD_COORDINATE
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
const std::string opt_key = (editor != nullptr) ? editor->get_full_opt_name() : "";
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, !opt_key.empty());
#else
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
wxGetApp().plater()->canvas3D()->enable_moving(enable_manipulation);
#endif // ENABLE_WORLD_COORDINATE
wxGetApp().plater()->canvas3D()->enable_moving(enable_manipulation); // ysFIXME
wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers);
@ -3373,8 +3413,12 @@ void ObjectList::update_selections()
return;
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
}
#if ENABLE_WORLD_COORDINATE
else if (selection.is_single_volume_or_modifier()) {
#else
else if (selection.is_single_volume() || selection.is_any_modifier()) {
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
#endif // ENABLE_WORLD_COORDINATE
const auto gl_vol = selection.get_first_volume();
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
return;
}
@ -4388,9 +4432,6 @@ void ObjectList::msw_rescale()
GetColumn(colExtruder)->SetWidth( 8 * em);
GetColumn(colEditing )->SetWidth( 3 * em);
// rescale/update existing items with bitmaps
m_objects_model->Rescale();
Layout();
}
@ -4398,7 +4439,10 @@ void ObjectList::sys_color_changed()
{
wxGetApp().UpdateDVCDarkUI(this, true);
msw_rescale();
// update existing items with bitmaps
m_objects_model->UpdateBitmaps();
Layout();
}
void ObjectList::ItemValueChanged(wxDataViewEvent &event)

View File

@ -280,7 +280,7 @@ public:
bool can_merge_to_multipart_object() const;
bool can_merge_to_single_object() const;
wxPoint get_mouse_position_in_control() const { return wxGetMousePosition() - this->GetScreenPosition(); }
wxPoint get_mouse_position_in_control() const;
wxBoxSizer* get_sizer() {return m_sizer;}
int get_selected_obj_idx() const;
ModelConfig& get_item_config(const wxDataViewItem& item) const;

View File

@ -52,10 +52,17 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent)
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
#if ENABLE_WORLD_COORDINATE
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::World));
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Instance));
temp->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Local));
temp->Select((int)ECoordinatesType::World);
#else
temp->Append(_L("World coordinates"));
temp->Append(_L("Local coordinates"));
temp->SetSelection(0);
temp->SetValue(temp->GetString(0));
#endif // ENABLE_WORLD_COORDINATE
temp->SetToolTip(_L("Select coordinate space, in which the transformation will be performed."));
return temp;
@ -81,8 +88,14 @@ void msw_rescale_word_local_combo(choice_ctrl* combo)
// Set rescaled size
combo->SetSize(size);
#if ENABLE_WORLD_COORDINATE
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::World));
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Instance));
combo->Append(ObjectManipulation::coordinate_type_str(ECoordinatesType::Local));
#else
combo->Append(_L("World coordinates"));
combo->Append(_L("Local coordinates"));
#endif // ENABLE_WORLD_COORDINATE
combo->SetValue(selection);
#else
@ -101,6 +114,7 @@ static void set_font_and_background_style(wxWindow* win, const wxFont& font)
static const wxString axes_color_text[] = { "#990000", "#009900", "#000099" };
static const wxString axes_color_back[] = { "#f5dcdc", "#dcf5dc", "#dcdcf5" };
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
OG_Settings(parent, true)
{
@ -112,7 +126,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// Load bitmaps to be used for the mirroring buttons:
m_mirror_bitmap_on = ScalableBitmap(parent, "mirroring_on");
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off");
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent.png");
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent");
const int border = wxOSX ? 0 : 4;
const int em = wxGetApp().em_unit();
@ -157,8 +171,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// Add world local combobox
m_word_local_combo = create_word_local_combo(parent);
m_word_local_combo->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent& evt) {
#if ENABLE_WORLD_COORDINATE
this->set_coordinates_type(evt.GetString());
#else
this->set_world_coordinates(evt.GetSelection() != 1);
}), m_word_local_combo->GetId());
#endif // ENABLE_WORLD_COORDINATE
}), m_word_local_combo->GetId());
// Small trick to correct layouting in different view_mode :
// Show empty string of a same height as a m_word_local_combo, when m_word_local_combo is hidden
@ -264,8 +282,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier()) {
#else
if (selection.is_single_volume() || selection.is_single_modifier()) {
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
#endif // ENABLE_WORLD_COORDINATE
GLVolume* volume = const_cast<GLVolume*>(selection.get_first_volume());
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
}
else if (selection.is_single_full_instance()) {
@ -278,7 +300,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
return;
// Update mirroring at the GLVolumes.
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
selection.synchronize_unselected_volumes();
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
canvas->do_mirror(L("Set Mirror"));
@ -327,28 +349,60 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
if (selection.is_single_volume() || selection.is_single_modifier()) {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier()) {
const GLVolume* volume = selection.get_first_volume();
const double min_z = get_volume_min_z(*volume);
if (!is_world_coordinates()) {
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix_no_offset().inverse() * (min_z * Vec3d::UnitZ());
const Geometry::Transformation& instance_trafo = volume->get_instance_transformation();
const Vec3d diff = m_cache.position - instance_trafo.get_matrix(true).inverse() * Vec3d(0., 0., get_volume_min_z(*volume));
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
change_position_value(0, diff.x());
change_position_value(1, diff.y());
change_position_value(2, diff.z());
}
else {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
change_position_value(2, m_cache.position.z() - min_z);
}
#else
if (selection.is_single_volume() || selection.is_single_modifier()) {
const GLVolume* volume = selection.get_first_volume();
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix(true).inverse() * (get_volume_min_z(*volume) * Vec3d::UnitZ());
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
change_position_value(0, diff.x());
change_position_value(1, diff.y());
change_position_value(2, diff.z());
#endif // ENABLE_WORLD_COORDINATE
}
else if (selection.is_single_full_instance()) {
#if ENABLE_WORLD_COORDINATE
const double min_z = selection.get_scaled_instance_bounding_box().min.z();
if (!is_world_coordinates()) {
const GLVolume* volume = selection.get_first_volume();
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix_no_offset().inverse() * (min_z * Vec3d::UnitZ());
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
change_position_value(0, diff.x());
change_position_value(1, diff.y());
change_position_value(2, diff.z());
}
else {
#else
const ModelObjectPtrs& objects = wxGetApp().model().objects;
const int idx = selection.get_object_idx();
if (0 <= idx && idx < static_cast<int>(objects.size())) {
const ModelObject* mo = wxGetApp().model().objects[idx];
const double min_z = mo->bounding_box().min.z();
if (std::abs(min_z) > SINKING_Z_THRESHOLD) {
#endif // ENABLE_WORLD_COORDINATE
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
change_position_value(2, m_cache.position.z() - min_z);
}
#if !ENABLE_WORLD_COORDINATE
}
#endif // !ENABLE_WORLD_COORDINATE
}
});
editors_grid_sizer->Add(m_drop_to_bed_button);
@ -365,21 +419,22 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
if (selection.is_single_volume() || selection.is_single_modifier()) {
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
volume->set_volume_rotation(Vec3d::Zero());
}
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier())
#else
if (selection.is_single_volume() || selection.is_single_modifier())
#endif // ENABLE_WORLD_COORDINATE
const_cast<GLVolume*>(selection.get_first_volume())->set_volume_rotation(Vec3d::Zero());
else if (selection.is_single_full_instance()) {
for (unsigned int idx : selection.get_volume_idxs()) {
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(idx));
volume->set_instance_rotation(Vec3d::Zero());
const_cast<GLVolume*>(selection.get_volume(idx))->set_instance_rotation(Vec3d::Zero());
}
}
else
return;
// Update rotation at the GLVolumes.
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
selection.synchronize_unselected_volumes();
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
canvas->do_rotate(L("Reset Rotation"));
@ -397,11 +452,29 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
m_reset_scale_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo"));
m_reset_scale_button->SetToolTip(_L("Reset scale"));
m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
#if ENABLE_WORLD_COORDINATE
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
if (selection.is_single_volume_or_modifier())
const_cast<GLVolume*>(selection.get_first_volume())->set_volume_scaling_factor(Vec3d::Ones());
else if (selection.is_single_full_instance()) {
for (unsigned int idx : selection.get_volume_idxs()) {
const_cast<GLVolume*>(selection.get_volume(idx))->set_instance_scaling_factor(Vec3d::Ones());
}
}
else
return;
canvas->do_scale(L("Reset scale"));
UpdateAndShow(true);
#else
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale"));
change_scale_value(0, 100.);
change_scale_value(1, 100.);
change_scale_value(2, 100.);
});
#endif // ENABLE_WORLD_COORDINATE
});
editors_grid_sizer->Add(m_reset_scale_button);
for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++)
@ -411,6 +484,25 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
m_main_grid_sizer->Add(editors_grid_sizer, 1, wxEXPAND);
#if ENABLE_WORLD_COORDINATE
m_skew_label = new wxStaticText(parent, wxID_ANY, _L("Skew"));
m_main_grid_sizer->Add(m_skew_label, 1, wxEXPAND);
m_reset_skew_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo"));
m_reset_skew_button->SetToolTip(_L("Reset skew"));
m_reset_skew_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
selection.setup_cache();
selection.reset_skew();
canvas->do_reset_skew(L("Reset skew"));
UpdateAndShow(true);
}
});
m_main_grid_sizer->Add(m_reset_skew_button);
#endif // ENABLE_WORLD_COORDINATE
m_check_inch = new wxCheckBox(parent, wxID_ANY, _L("Inches"));
m_check_inch->SetFont(wxGetApp().normal_font());
@ -444,8 +536,27 @@ void ObjectManipulation::Show(const bool show)
if (show) {
// Show the "World Coordinates" / "Local Coordintes" Combo in Advanced / Expert mode only.
bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple;
m_word_local_combo->Show(show_world_local_combo);
#if ENABLE_WORLD_COORDINATE
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) {
#ifdef __linux__
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), 1);
#else
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), wxNullBitmap, 1);
#endif // __linux__
m_word_local_combo->Select((int)ECoordinatesType::World);
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
}
else if (selection.is_single_full_instance() && m_word_local_combo->GetCount() > 2) {
m_word_local_combo->Delete(1);
m_word_local_combo->Select((int)ECoordinatesType::World);
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
}
#else
bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple;
#endif // ENABLE_WORLD_COORDINATE
m_word_local_combo->Show(show_world_local_combo);
m_empty_str->Show(!show_world_local_combo);
}
}
@ -505,8 +616,7 @@ void ObjectManipulation::update_ui_from_settings()
}
m_check_inch->SetValue(m_imperial_units);
if (m_use_colors != (wxGetApp().app_config->get("color_mapinulation_panel") == "1"))
{
if (m_use_colors != (wxGetApp().app_config->get("color_mapinulation_panel") == "1")) {
m_use_colors = wxGetApp().app_config->get("color_mapinulation_panel") == "1";
// update colors for edit-boxes
int axis_id = 0;
@ -538,33 +648,49 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_rotate_label_string = L("Rotation");
m_new_scale_label_string = L("Scale factors");
#if !ENABLE_WORLD_COORDINATE
if (wxGetApp().get_mode() == comSimple)
m_world_coordinates = true;
#endif // !ENABLE_WORLD_COORDINATE
ObjectList* obj_list = wxGetApp().obj_list();
if (selection.is_single_full_instance()) {
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* volume = selection.get_first_volume();
#if !ENABLE_WORLD_COORDINATE
m_new_position = volume->get_instance_offset();
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
if (m_world_coordinates && ! m_uniform_scale &&
if (m_world_coordinates && ! m_uniform_scale &&
! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling.
m_uniform_scale = true;
m_lock_bnt->SetLock(true);
}
#endif // !ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
if (is_world_coordinates()) {
m_new_position = volume->get_instance_offset();
#else
if (m_world_coordinates) {
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_size = selection.get_scaled_instance_bounding_box().size();
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.;
}
#endif // ENABLE_WORLD_COORDINATE
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_size = selection.get_scaled_instance_bounding_box().size();
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
}
else {
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
m_new_scale = volume->get_instance_scaling_factor() * 100.;
#if ENABLE_WORLD_COORDINATE
m_new_move_label_string = L("Translate");
m_new_rotate_label_string = L("Rotate");
m_new_position = Vec3d::Zero();
m_new_rotation = Vec3d::Zero();
#else
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
#endif // ENABLE_WORLD_COORDINATE
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
}
m_new_enabled = true;
@ -573,19 +699,52 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
const BoundingBoxf3& box = selection.get_bounding_box();
m_new_position = box.center();
m_new_rotation = Vec3d::Zero();
m_new_scale = Vec3d(100., 100., 100.);
m_new_scale = Vec3d(100.0, 100.0, 100.0);
m_new_size = box.size();
m_new_rotate_label_string = L("Rotate");
m_new_scale_label_string = L("Scale");
m_new_enabled = true;
}
#if ENABLE_WORLD_COORDINATE
else if (selection.is_single_volume_or_modifier()) {
#else
else if (selection.is_single_modifier() || selection.is_single_volume()) {
#endif // ENABLE_WORLD_COORDINATE
// the selection contains a single volume
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* volume = selection.get_first_volume();
#if ENABLE_WORLD_COORDINATE
if (is_world_coordinates()) {
const Geometry::Transformation trafo(volume->world_matrix());
const Vec3d& offset = trafo.get_offset();
m_new_position = offset;
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size();
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
}
else if (is_local_coordinates()) {
m_new_move_label_string = L("Translate");
m_new_rotate_label_string = L("Rotate");
m_new_position = Vec3d::Zero();
m_new_rotation = Vec3d::Zero();
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
m_new_size = volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size());
}
else {
#endif // ENABLE_WORLD_COORDINATE
m_new_position = volume->get_volume_offset();
m_new_rotation = volume->get_volume_rotation() * (180. / M_PI);
m_new_scale = volume->get_volume_scaling_factor() * 100.;
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
#if ENABLE_WORLD_COORDINATE
m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size();
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
}
#else
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
#endif // ENABLE_WORLD_COORDINATE
m_new_enabled = true;
}
else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
@ -651,22 +810,26 @@ void ObjectManipulation::update_if_dirty()
update(m_cache.rotation, m_cache.rotation_rounded, meRotation, m_new_rotation);
}
#if !ENABLE_WORLD_COORDINATE
if (selection.requires_uniform_scale()) {
m_lock_bnt->SetLock(true);
m_lock_bnt->SetToolTip(_L("You cannot use non-uniform scaling mode for multiple objects/parts selection"));
m_lock_bnt->disable();
}
else {
#endif // !ENABLE_WORLD_COORDINATE
m_lock_bnt->SetLock(m_uniform_scale);
m_lock_bnt->SetToolTip(wxEmptyString);
m_lock_bnt->enable();
#if !ENABLE_WORLD_COORDINATE
}
{
{
int new_selection = m_world_coordinates ? 0 : 1;
if (m_word_local_combo->GetSelection() != new_selection)
m_word_local_combo->SetSelection(new_selection);
}
#endif // !ENABLE_WORLD_COORDINATE
if (m_new_enabled)
m_og->enable();
@ -693,29 +856,75 @@ void ObjectManipulation::update_reset_buttons_visibility()
bool show_rotation = false;
bool show_scale = false;
bool show_drop_to_bed = false;
#if ENABLE_WORLD_COORDINATE
bool show_skew = false;
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
const double min_z = selection.is_single_full_instance() ? selection.get_scaled_instance_bounding_box().min.z() :
get_volume_min_z(*selection.get_first_volume());
show_drop_to_bed = std::abs(min_z) > EPSILON;
const GLVolume* volume = selection.get_first_volume();
Transform3d rotation = Transform3d::Identity();
Transform3d scale = Transform3d::Identity();
Geometry::Transformation skew;
#else
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* volume = selection.get_first_volume();
Vec3d rotation;
Vec3d scale;
double min_z = 0.;
double min_z = 0.0;
#endif // ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance()) {
#if ENABLE_WORLD_COORDINATE
const Geometry::Transformation& trafo = volume->get_instance_transformation();
rotation = trafo.get_rotation_matrix();
scale = trafo.get_scaling_factor_matrix();
const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int id : idxs) {
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
if (world_trafo.has_skew()) {
skew = world_trafo;
break;
}
}
#else
rotation = volume->get_instance_rotation();
scale = volume->get_instance_scaling_factor();
min_z = wxGetApp().model().objects[volume->composite_id.object_id]->bounding_box().min.z();
min_z = selection.get_scaled_instance_bounding_box().min.z();
#endif // ENABLE_WORLD_COORDINATE
}
else {
#if ENABLE_WORLD_COORDINATE
const Geometry::Transformation& trafo = volume->get_volume_transformation();
rotation = trafo.get_rotation_matrix();
scale = trafo.get_scaling_factor_matrix();
const Geometry::Transformation world_trafo(volume->world_matrix());
if (world_trafo.has_skew())
skew = world_trafo;
#else
rotation = volume->get_volume_rotation();
scale = volume->get_volume_scaling_factor();
min_z = get_volume_min_z(*volume);
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
show_rotation = !rotation.isApprox(Transform3d::Identity());
show_scale = !scale.isApprox(Transform3d::Identity());
show_skew = skew.has_skew();
#else
show_rotation = !rotation.isApprox(Vec3d::Zero());
show_scale = !scale.isApprox(Vec3d::Ones());
show_drop_to_bed = std::abs(min_z) > SINKING_Z_THRESHOLD;
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew] {
#else
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
#endif // ENABLE_WORLD_COORDINATE
// There is a case (under OSX), when this function is called after the Manipulation panel is hidden
// So, let check if Manipulation panel is still shown for this moment
if (!this->IsShown())
@ -723,6 +932,10 @@ void ObjectManipulation::update_reset_buttons_visibility()
m_reset_rotation_button->Show(show_rotation);
m_reset_scale_button->Show(show_scale);
m_drop_to_bed_button->Show(show_drop_to_bed);
#if ENABLE_WORLD_COORDINATE
m_reset_skew_button->Show(show_skew);
m_skew_label->Show(show_skew);
#endif // ENABLE_WORLD_COORDINATE
// Because of CallAfter we need to layout sidebar after Show/hide of reset buttons one more time
Sidebar& panel = wxGetApp().sidebar();
@ -742,9 +955,17 @@ void ObjectManipulation::update_mirror_buttons_visibility()
Selection& selection = canvas->get_selection();
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
#if ENABLE_WORLD_COORDINATE
if (is_local_coordinates()) {
#else
if (!m_world_coordinates) {
#endif // ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
#else
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
#endif // ENABLE_WORLD_COORDINATE
const GLVolume* volume = selection.get_first_volume();
Vec3d mirror;
if (selection.is_single_full_instance())
@ -804,10 +1025,23 @@ void ObjectManipulation::update_warning_icon_state(const MeshErrorsInfo& warning
m_manifold_warning_bmp = ScalableBitmap(m_parent, warning_icon_name);
const wxString& tooltip = warning.tooltip;
m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp());
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0,0) : m_manifold_warning_bmp.bmp().GetSize());
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0,0) : m_manifold_warning_bmp.GetSize());
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
}
#if ENABLE_WORLD_COORDINATE
wxString ObjectManipulation::coordinate_type_str(ECoordinatesType type)
{
switch (type)
{
case ECoordinatesType::World: { return _L("World coordinates"); }
case ECoordinatesType::Instance: { return _L("Instance coordinates"); }
case ECoordinatesType::Local: { return _L("Local coordinates"); }
default: { assert(false); return _L("Unknown"); }
}
}
#endif // ENABLE_WORLD_COORDINATE
void ObjectManipulation::reset_settings_value()
{
m_new_position = Vec3d::Zero();
@ -831,7 +1065,19 @@ void ObjectManipulation::change_position_value(int axis, double value)
auto canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
selection.setup_cache();
#if ENABLE_WORLD_COORDINATE
TransformationType trafo_type;
trafo_type.set_relative();
switch (get_coordinates_type())
{
case ECoordinatesType::Instance: { trafo_type.set_instance(); break; }
case ECoordinatesType::Local: { trafo_type.set_local(); break; }
default: { break; }
}
selection.translate(position - m_cache.position, trafo_type);
#else
selection.translate(position - m_cache.position, selection.requires_local_axes());
#endif // ENABLE_WORLD_COORDINATE
canvas->do_move(L("Set Position"));
m_cache.position = position;
@ -850,6 +1096,18 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
#if ENABLE_WORLD_COORDINATE
TransformationType transformation_type;
transformation_type.set_relative();
if (selection.is_single_full_instance())
transformation_type.set_independent();
if (is_local_coordinates())
transformation_type.set_local();
if (is_instance_coordinates())
transformation_type.set_instance();
#else
TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance() || selection.requires_local_axes())
transformation_type.set_independent();
@ -858,6 +1116,7 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
// transformation_type.set_absolute();
transformation_type.set_local();
}
#endif // ENABLE_WORLD_COORDINATE
selection.setup_cache();
selection.rotate(
@ -903,8 +1162,12 @@ void ObjectManipulation::change_size_value(int axis, double value)
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
Vec3d ref_size = m_cache.size;
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier()) {
#else
if (selection.is_single_volume() || selection.is_single_modifier()) {
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
#endif // ENABLE_WORLD_COORDINATE
const GLVolume* v = selection.get_first_volume();
const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor());
const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor());
const Vec3d local_change = local_size.cwiseQuotient(local_ref_size);
@ -913,11 +1176,19 @@ void ObjectManipulation::change_size_value(int axis, double value)
ref_size = Vec3d::Ones();
}
else if (selection.is_single_full_instance())
ref_size = m_world_coordinates ?
#if ENABLE_WORLD_COORDINATE
ref_size = is_world_coordinates() ?
#else
ref_size = m_world_coordinates ?
#endif // ENABLE_WORLD_COORDINATE
selection.get_unscaled_instance_bounding_box().size() :
wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size();
wxGetApp().model().objects[selection.get_first_volume()->object_idx()]->raw_mesh_bounding_box().size();
#if ENABLE_WORLD_COORDINATE
this->do_size(axis, size.cwiseQuotient(ref_size));
#else
this->do_scale(axis, size.cwiseQuotient(ref_size));
#endif // ENABLE_WORLD_COORDINATE
m_cache.size = size;
m_cache.size_rounded(axis) = DBL_MAX;
@ -927,8 +1198,22 @@ void ObjectManipulation::change_size_value(int axis, double value)
void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
{
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
#if !ENABLE_WORLD_COORDINATE
Vec3d scaling_factor = scale;
#endif // !ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
TransformationType transformation_type;
if (is_local_coordinates())
transformation_type.set_local();
else if (is_instance_coordinates())
transformation_type.set_instance();
if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier())
transformation_type.set_relative();
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
#else
TransformationType transformation_type(TransformationType::World_Relative_Joint);
if (selection.is_single_full_instance()) {
transformation_type.set_absolute();
@ -938,12 +1223,31 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
if (m_uniform_scale || selection.requires_uniform_scale())
scaling_factor = scale(axis) * Vec3d::Ones();
#endif // ENABLE_WORLD_COORDINATE
selection.setup_cache();
selection.scale(scaling_factor, transformation_type);
wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
}
#if ENABLE_WORLD_COORDINATE
void ObjectManipulation::do_size(int axis, const Vec3d& scale) const
{
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
TransformationType transformation_type;
if (is_local_coordinates())
transformation_type.set_local();
else if (is_instance_coordinates())
transformation_type.set_instance();
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
selection.setup_cache();
selection.scale(scaling_factor, transformation_type);
wxGetApp().plater()->canvas3D()->do_scale(L("Set Size"));
}
#endif // ENABLE_WORLD_COORDINATE
void ObjectManipulation::on_change(const std::string& opt_key, int axis, double new_value)
{
if (!m_cache.is_valid())
@ -978,17 +1282,26 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
}
}
void ObjectManipulation::set_uniform_scaling(const bool new_value)
void ObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
{
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
#if ENABLE_WORLD_COORDINATE
if (!use_uniform_scale)
// Recalculate cached values at this panel, refresh the screen.
this->UpdateAndShow(true);
m_uniform_scale = use_uniform_scale;
set_dirty();
#else
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
if (selection.is_single_full_instance() && m_world_coordinates && !use_uniform_scale) {
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
const GLVolume* volume = selection.get_first_volume();
// Is the angle close to a multiple of 90 degrees?
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
if (!Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Cannot apply scaling in the world coordinate system.
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
MessageDialog dlg(GUI::wxGetApp().mainframe,
_L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n"
"Non-uniform scaling of tilted objects is only possible in the World coordinate system,\n"
@ -996,7 +1309,7 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
_L("This operation is irreversible.\n"
"Do you want to proceed?"),
SLIC3R_APP_NAME,
wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION);
wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES) {
// Enforce uniform scaling.
m_lock_bnt->SetLock(true);
@ -1010,31 +1323,39 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
this->UpdateAndShow(true);
}
}
m_uniform_scale = new_value;
m_uniform_scale = use_uniform_scale;
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
void ObjectManipulation::set_coordinates_type(ECoordinatesType type)
{
if (wxGetApp().get_mode() == comSimple)
type = ECoordinatesType::World;
if (m_coordinates_type == type)
return;
m_coordinates_type = type;
this->UpdateAndShow(true);
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
canvas->get_gizmos_manager().update_data();
canvas->set_as_dirty();
canvas->request_extra_frame();
}
#endif // ENABLE_WORLD_COORDINATE
void ObjectManipulation::msw_rescale()
{
const int em = wxGetApp().em_unit();
m_item_name->SetMinSize(wxSize(20*em, wxDefaultCoord));
msw_rescale_word_local_combo(m_word_local_combo);
m_word_local_combo_sizer->SetMinSize(wxSize(-1, m_word_local_combo->GetBestHeight(-1)));
m_manifold_warning_bmp.msw_rescale();
const wxString& tooltip = m_fix_throught_netfab_bitmap->GetToolTipText();
m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp());
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0, 0) : m_manifold_warning_bmp.bmp().GetSize());
m_mirror_bitmap_on.msw_rescale();
m_mirror_bitmap_off.msw_rescale();
m_mirror_bitmap_hidden.msw_rescale();
m_reset_scale_button->msw_rescale();
m_reset_rotation_button->msw_rescale();
m_drop_to_bed_button->msw_rescale();
m_lock_bnt->msw_rescale();
for (int id = 0; id < 3; ++id)
m_mirror_buttons[id].first->msw_rescale();
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0, 0) : m_manifold_warning_bmp.GetSize());
// rescale label-heights
// Text trick to grid sizer layout:
@ -1063,19 +1384,31 @@ void ObjectManipulation::sys_color_changed()
for (ManipulationEditor* editor : m_editors)
editor->sys_color_changed(this);
// btn...->msw_rescale() updates icon on button, so use it
m_mirror_bitmap_on.msw_rescale();
m_mirror_bitmap_off.msw_rescale();
m_mirror_bitmap_hidden.msw_rescale();
m_reset_scale_button->msw_rescale();
m_reset_rotation_button->msw_rescale();
m_drop_to_bed_button->msw_rescale();
m_lock_bnt->msw_rescale();
m_mirror_bitmap_on.sys_color_changed();
m_mirror_bitmap_off.sys_color_changed();
m_mirror_bitmap_hidden.sys_color_changed();
m_reset_scale_button->sys_color_changed();
m_reset_rotation_button->sys_color_changed();
m_drop_to_bed_button->sys_color_changed();
m_lock_bnt->sys_color_changed();
for (int id = 0; id < 3; ++id)
m_mirror_buttons[id].first->msw_rescale();
m_mirror_buttons[id].first->sys_color_changed();
}
#if ENABLE_WORLD_COORDINATE
void ObjectManipulation::set_coordinates_type(const wxString& type_string)
{
ECoordinatesType type = ECoordinatesType::World;
if (type_string == coordinate_type_str(ECoordinatesType::Instance))
type = ECoordinatesType::Instance;
else if (type_string == coordinate_type_str(ECoordinatesType::Local))
type = ECoordinatesType::Local;
this->set_coordinates_type(type);
}
#endif // ENABLE_WORLD_COORDINATE
static const char axes[] = { 'x', 'y', 'z' };
ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
const std::string& opt_key,
@ -1117,8 +1450,8 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
parent->set_focused_editor(nullptr);
#if ENABLE_OBJECT_MANIPULATOR_FOCUS
// if the widgets exchanging focus are both manipulator fields, call kill_focus
if (dynamic_cast<ManipulationEditor*>(e.GetEventObject()) != nullptr && dynamic_cast<ManipulationEditor*>(e.GetWindow()) != nullptr)
// if the widgets loosing focus is a manipulator field, call kill_focus
if (dynamic_cast<ManipulationEditor*>(e.GetEventObject()) != nullptr)
#else
if (!m_enter_pressed)
#endif // ENABLE_OBJECT_MANIPULATOR_FOCUS

View File

@ -5,6 +5,9 @@
#include "GUI_ObjectSettings.hpp"
#include "GUI_ObjectList.hpp"
#if ENABLE_WORLD_COORDINATE
#include "GUI_Geometry.hpp"
#endif // ENABLE_WORLD_COORDINATE
#include "libslic3r/Point.hpp"
#include <float.h>
@ -57,6 +60,10 @@ public:
void set_value(const wxString& new_value);
void kill_focus(ObjectManipulation *parent);
#if ENABLE_WORLD_COORDINATE
const std::string& get_full_opt_name() const { return m_full_opt_name; }
#endif // ENABLE_WORLD_COORDINATE
bool has_opt_key(const std::string& key) { return m_opt_key == key; }
private:
@ -115,9 +122,12 @@ private:
wxStaticText* m_empty_str = nullptr;
// Non-owning pointers to the reset buttons, so we can hide and show them.
ScalableButton* m_reset_scale_button = nullptr;
ScalableButton* m_reset_rotation_button = nullptr;
ScalableButton* m_drop_to_bed_button = nullptr;
ScalableButton* m_reset_scale_button{ nullptr };
ScalableButton* m_reset_rotation_button{ nullptr };
#if ENABLE_WORLD_COORDINATE
ScalableButton* m_reset_skew_button{ nullptr };
#endif // ENABLE_WORLD_COORDINATE
ScalableButton* m_drop_to_bed_button{ nullptr };
wxCheckBox* m_check_inch {nullptr};
@ -146,22 +156,35 @@ private:
Vec3d m_new_size;
bool m_new_enabled {true};
bool m_uniform_scale {true};
#if ENABLE_WORLD_COORDINATE
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
#else
// Does the object manipulation panel work in World or Local coordinates?
bool m_world_coordinates = true;
#endif // ENABLE_WORLD_COORDINATE
LockButton* m_lock_bnt{ nullptr };
choice_ctrl* m_word_local_combo { nullptr };
ScalableBitmap m_manifold_warning_bmp;
wxStaticBitmap* m_fix_throught_netfab_bitmap;
#if ENABLE_WORLD_COORDINATE
// Currently focused editor (nullptr if none)
ManipulationEditor* m_focused_editor{ nullptr };
#else
#ifndef __APPLE__
// Currently focused editor (nullptr if none)
ManipulationEditor* m_focused_editor {nullptr};
#endif // __APPLE__
#endif // ENABLE_WORLD_COORDINATE
wxFlexGridSizer* m_main_grid_sizer;
wxFlexGridSizer* m_labels_grid_sizer;
#if ENABLE_WORLD_COORDINATE
wxStaticText* m_skew_label{ nullptr };
#endif // ENABLE_WORLD_COORDINATE
// sizers, used for msw_rescale
wxBoxSizer* m_word_local_combo_sizer;
std::vector<wxBoxSizer*> m_rescalable_sizers;
@ -185,11 +208,19 @@ public:
// Called from the App to update the UI if dirty.
void update_if_dirty();
void set_uniform_scaling(const bool uniform_scale);
void set_uniform_scaling(const bool use_uniform_scale);
bool get_uniform_scaling() const { return m_uniform_scale; }
#if ENABLE_WORLD_COORDINATE
void set_coordinates_type(ECoordinatesType type);
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
#else
// Does the object manipulation panel work in World or Local coordinates?
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
bool get_world_coordinates() const { return m_world_coordinates; }
#endif // ENABLE_WORLD_COORDINATE
void reset_cache() { m_cache.reset(); }
#ifndef __APPLE__
@ -205,11 +236,23 @@ public:
void sys_color_changed();
void on_change(const std::string& opt_key, int axis, double new_value);
void set_focused_editor(ManipulationEditor* focused_editor) {
#if ENABLE_WORLD_COORDINATE
m_focused_editor = focused_editor;
#else
#ifndef __APPLE__
m_focused_editor = focused_editor;
#endif // __APPLE__
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
ManipulationEditor* get_focused_editor() { return m_focused_editor; }
#endif // ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
static wxString coordinate_type_str(ECoordinatesType type);
#endif // ENABLE_WORLD_COORDINATE
private:
void reset_settings_value();
void update_settings_value(const Selection& selection);
@ -225,6 +268,11 @@ private:
void change_scale_value(int axis, double value);
void change_size_value(int axis, double value);
void do_scale(int axis, const Vec3d &scale) const;
#if ENABLE_WORLD_COORDINATE
void do_size(int axis, const Vec3d& scale) const;
void set_coordinates_type(const wxString& type_string);
#endif // ENABLE_WORLD_COORDINATE
};
}}

View File

@ -99,7 +99,7 @@ bool ObjectSettings::update_settings_list()
btn->SetToolTip(_(L("Remove parameter")));
btn->SetBitmapFocus(m_bmp_delete_focus.bmp());
btn->SetBitmapHover(m_bmp_delete_focus.bmp());
btn->SetBitmapCurrent(m_bmp_delete_focus.bmp());
btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) {
wxGetApp().plater()->take_snapshot(from_u8((boost::format(_utf8(L("Delete Option %s"))) % opt_key).str()));
@ -133,7 +133,7 @@ bool ObjectSettings::update_settings_list()
return;
ctrl->SetBitmap_(m_bmp_delete);
ctrl->SetBitmapFocus(m_bmp_delete_focus.bmp());
ctrl->SetBitmapHover(m_bmp_delete_focus.bmp());
ctrl->SetBitmapCurrent(m_bmp_delete_focus.bmp());
};
const bool is_extruders_cat = cat.first == "Extruders";
@ -268,15 +268,6 @@ void ObjectSettings::UpdateAndShow(const bool show)
OG_Settings::UpdateAndShow(show ? update_settings_list() : false);
}
void ObjectSettings::msw_rescale()
{
m_bmp_delete.msw_rescale();
m_bmp_delete_focus.msw_rescale();
for (auto group : m_og_settings)
group->msw_rescale();
}
void ObjectSettings::sys_color_changed()
{
m_og->sys_color_changed();

View File

@ -56,7 +56,6 @@ public:
bool add_missed_options(ModelConfig *config_to, const DynamicPrintConfig &config_from);
void update_config_values(ModelConfig *config);
void UpdateAndShow(const bool show) override;
void msw_rescale();
void sys_color_changed();
};

View File

@ -983,10 +983,11 @@ void Preview::load_print_as_fff(bool keep_z_range)
if (gcode_preview_data_valid) {
// Load the real G-code preview.
m_canvas->load_gcode_preview(*m_gcode_result, colors);
m_left_sizer->Show(m_bottom_toolbar_panel);
m_left_sizer->Layout();
Refresh();
zs = m_canvas->get_gcode_layers_zs();
if (!zs.empty())
m_left_sizer->Show(m_bottom_toolbar_panel);
m_loaded = true;
}
else if (wxGetApp().is_editor()) {

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