Merge branch 'master' into fs_mouse
# Conflicts: # src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp # src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
This commit is contained in:
commit
0c40e2f8c8
@ -33,6 +33,7 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
||||
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
||||
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
|
||||
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||
option(SLIC3R_UBSAN "Enable UBSan on Clang and GCC" 0)
|
||||
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
|
||||
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
|
||||
|
||||
@ -239,6 +240,11 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
|
||||
add_compile_options(-Wno-deprecated-declarations)
|
||||
endif()
|
||||
|
||||
# Clang reports misleading indentation for some IF blocks because of mixing tabs with spaces.
|
||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
add_compile_options(-Wno-misleading-indentation)
|
||||
endif()
|
||||
|
||||
#GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
|
||||
@ -266,6 +272,32 @@ if (SLIC3R_ASAN)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_UBSAN)
|
||||
# Stacktrace for every report is enabled by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
|
||||
|
||||
# Define macro SLIC3R_UBSAN to allow detection in the source code if this sanitizer is enabled.
|
||||
add_compile_definitions(SLIC3R_UBSAN)
|
||||
|
||||
# Clang supports much more useful checks than GCC, so when Clang is detected, another checks will be enabled.
|
||||
# List of what GCC is checking: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
|
||||
# List of what Clang is checking: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(_ubsan_flags "-fsanitize=undefined,integer")
|
||||
else ()
|
||||
set(_ubsan_flags "-fsanitize=undefined")
|
||||
endif ()
|
||||
|
||||
add_compile_options(${_ubsan_flags} -fno-omit-frame-pointer)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_ubsan_flags}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${_ubsan_flags}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${_ubsan_flags}")
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lubsan")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
|
||||
@ -496,6 +528,8 @@ foreach(po_file ${L10N_PO_FILES})
|
||||
add_custom_command(
|
||||
TARGET gettext_merge_po_with_pot PRE_BUILD
|
||||
COMMAND msgmerge -N -o ${po_file} ${po_file} "${L10N_DIR}/PrusaSlicer.pot"
|
||||
# delete obsolete lines from resulting PO to avoid conflicts after a merging of it with wxWidgets.po
|
||||
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
endforeach()
|
||||
@ -513,7 +547,9 @@ foreach(po_file ${L10N_PO_FILES})
|
||||
#SET(po_new_file "${po_dir}/PrusaSlicer_.po")
|
||||
add_custom_command(
|
||||
TARGET gettext_concat_wx_po_with_po PRE_BUILD
|
||||
COMMAND msgcat --use-first -o ${po_file} ${po_file} ${wx_po_file}
|
||||
COMMAND msgcat --use-first -o ${po_file} ${po_file} ${wx_po_file}
|
||||
# delete obsolete lines from resulting PO
|
||||
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
endforeach()
|
||||
|
@ -10,6 +10,7 @@
|
||||
@ECHO [-PRODUCT ^<product^>] [-DESTDIR ^<directory^>]
|
||||
@ECHO [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>]
|
||||
@ECHO [-RUN ^<console^|custom^|none^|viewer^|window^>]
|
||||
@ECHO [-PRIORITY ^<normal^|low^>]
|
||||
@ECHO.
|
||||
@ECHO -a -ARCH Target processor architecture
|
||||
@ECHO Default: %PS_ARCH_HOST%
|
||||
@ -38,6 +39,8 @@
|
||||
@ECHO -d -DESTDIR Deps destination directory
|
||||
@ECHO Warning: Changing destdir path will not delete the old destdir.
|
||||
@ECHO Default: %PS_DESTDIR_DEFAULT_MSG%
|
||||
@ECHO -p -PRIORITY Build CPU priority
|
||||
@ECHO Default: normal
|
||||
@ECHO.
|
||||
@ECHO Examples:
|
||||
@ECHO.
|
||||
@ -86,6 +89,7 @@ SET PS_RUN=none
|
||||
SET PS_DESTDIR=
|
||||
SET PS_VERSION=
|
||||
SET PS_PRODUCT=%PS_PRODUCT_DEFAULT%
|
||||
SET PS_PRIORITY=normal
|
||||
CALL :RESOLVE_DESTDIR_CACHE
|
||||
|
||||
REM Set up parameters used by help menu
|
||||
@ -99,7 +103,7 @@ SET EXIT_STATUS=1
|
||||
SET PS_CURRENT_STEP=arguments
|
||||
SET PARSER_STATE=
|
||||
SET PARSER_FAIL=
|
||||
FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS RUN VERSION PRODUCT" PARSER_STATE "%%~I"
|
||||
FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS RUN VERSION PRODUCT PRIORITY" PARSER_STATE "%%~I"
|
||||
IF "%PARSER_FAIL%" NEQ "" (
|
||||
@ECHO ERROR: Invalid switch: %PARSER_FAIL% 1>&2
|
||||
GOTO :HELP
|
||||
@ -114,6 +118,9 @@ CALL :TOLOWER PS_ARCH
|
||||
SET PS_ARCH=%PS_ARCH:amd64=x64%
|
||||
CALL :PARSE_OPTION_VALUE %PS_CONFIG_LIST:;= % PS_CONFIG
|
||||
IF "%PS_CONFIG%" EQU "" GOTO :HELP
|
||||
CALL :PARSE_OPTION_VALUE "normal low" PS_PRIORITY
|
||||
SET PS_PRIORITY=%PS_PRIORITY:normal= %
|
||||
SET PS_PRIORITY=%PS_PRIORITY:low=-low%
|
||||
REM RESOLVE_DESTDIR_CACHE must go after PS_ARCH and PS_CONFIG, but before PS STEPS
|
||||
CALL :RESOLVE_DESTDIR_CACHE
|
||||
IF "%PS_STEPS%" EQU "" SET PS_STEPS=%PS_STEPS_DEFAULT%
|
||||
@ -200,7 +207,7 @@ IF %ERRORLEVEL% NEQ 0 IF "%PS_STEPS_DIRTY%" NEQ "" (
|
||||
(del CMakeCache.txt && cmake.exe .. -DDESTDIR="%PS_DESTDIR%") || GOTO :END
|
||||
) ELSE GOTO :END
|
||||
(echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE%"
|
||||
msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet || GOTO :END
|
||||
msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet %PS_PRIORITY% || GOTO :END
|
||||
cd ..\..
|
||||
IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :RUN_APP
|
||||
|
||||
@ -223,7 +230,7 @@ IF %ERRORLEVEL% NEQ 0 IF "%PS_STEPS_DIRTY%" NEQ "" (
|
||||
(del CMakeCache.txt && cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG_LIST%) || GOTO :END
|
||||
) ELSE GOTO :END
|
||||
REM Skip the build step if we're using the undocumented app-cmake to regenerate the full config from inside devenv
|
||||
IF "%PS_STEPS%" NEQ "app-cmake" msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet || GOTO :END
|
||||
IF "%PS_STEPS%" NEQ "app-cmake" msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet %PS_PRIORITY% || GOTO :END
|
||||
(echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE_FOR_CONFIG%"
|
||||
|
||||
REM Run app
|
||||
|
@ -293,7 +293,7 @@ if(NOT TBB_FOUND)
|
||||
# Create targets
|
||||
##################################
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND AND NOT TARGET TBB::tbb)
|
||||
add_library(TBB::tbb UNKNOWN IMPORTED)
|
||||
set_target_properties(TBB::tbb PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS}"
|
||||
|
6
deps/Boost/Boost.cmake
vendored
6
deps/Boost/Boost.cmake
vendored
@ -120,6 +120,12 @@ set(_build_cmd ${_build_cmd}
|
||||
|
||||
set(_install_cmd ${_build_cmd} --prefix=${_prefix} install)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
|
||||
# Because of that, UndefinedBehaviorSanitizer is disabled for those functions that use __int128.
|
||||
list(APPEND _patch_command COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/Boost.patch)
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
dep_Boost
|
||||
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"
|
||||
|
23
deps/Boost/Boost.patch
vendored
Normal file
23
deps/Boost/Boost.patch
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
diff -u ../boost_1_75_0-orig/boost/rational.hpp ./boost/rational.hpp
|
||||
--- ../boost_1_75_0-orig/boost/rational.hpp 2020-12-03 06:02:19.000000000 +0100
|
||||
+++ ./boost/rational.hpp 2022-01-27 16:02:27.993848905 +0100
|
||||
@@ -302,6 +302,9 @@
|
||||
return *this;
|
||||
}
|
||||
template <class T>
|
||||
+ #if defined(__clang__)
|
||||
+ __attribute__((no_sanitize("undefined")))
|
||||
+ #endif
|
||||
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator*= (const T& i)
|
||||
{
|
||||
// Avoid overflow and preserve normalization
|
||||
@@ -311,6 +314,9 @@
|
||||
return *this;
|
||||
}
|
||||
template <class T>
|
||||
+ #if defined(__clang__)
|
||||
+ __attribute__((no_sanitize("undefined")))
|
||||
+ #endif
|
||||
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator/= (const T& i)
|
||||
{
|
||||
// Avoid repeated construction
|
@ -123,7 +123,7 @@ hypertext_settings_category = Infill
|
||||
disabled_tags = SLA; simple
|
||||
|
||||
[hint:Variable layer height]
|
||||
text = Variable layer height\nDid you know that you can print different regions of your model with a different layer height and smooth the transitions between them? Try the<a>Variable layer height tool.</a>(Not available for SLA printers.)
|
||||
text = Variable layer height\nDid you know that you can print different regions of your model with a different layer height and smooth the transitions between them? Try the<a>Variable layer height tool</a>. (Not available for SLA printers.)
|
||||
hypertext_type = plater
|
||||
hypertext_plater_item = layersediting
|
||||
disabled_tags = SLA
|
||||
@ -139,7 +139,7 @@ documentation_link= https://help.prusa3d.com/en/article/per-model-settings_1674
|
||||
disabled_tags = SLA
|
||||
|
||||
[hint:Solid infill threshold area]
|
||||
text = Solid infill threshold area\nDid you know that you can make parts of your model with a small cross-section be filled with solid infill automatically? Set the<a>Solid infill threshold area.</a>(Expert mode only.)
|
||||
text = Solid infill threshold area\nDid you know that you can make parts of your model with a small cross-section be filled with solid infill automatically? Set the<a>Solid infill threshold area</a>. (Expert mode only.)
|
||||
hypertext_type = settings
|
||||
hypertext_settings_opt = solid_infill_below_area
|
||||
hypertext_settings_type = 1
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
resources/localization/hu/PrusaSlicer.mo
Normal file
BIN
resources/localization/hu/PrusaSlicer.mo
Normal file
Binary file not shown.
24675
resources/localization/hu/PrusaSlicer_hu.po
Normal file
24675
resources/localization/hu/PrusaSlicer_hu.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
2
resources/profiles/Jubilee.idx
Normal file
2
resources/profiles/Jubilee.idx
Normal file
@ -0,0 +1,2 @@
|
||||
min_slic3r_version = 2.4.1-alpha
|
||||
1.0.0 Initial Jubilee bundle
|
516
resources/profiles/Jubilee.ini
Normal file
516
resources/profiles/Jubilee.ini
Normal file
@ -0,0 +1,516 @@
|
||||
# Jubilee profiles
|
||||
|
||||
# Based on the profiles from: https://github.com/machineagency/jubilee/tree/main/software/slicer_settings/prusa_slic3r by yvessa
|
||||
|
||||
[vendor]
|
||||
# Vendor name will be shown by the Config Wizard.
|
||||
name = Jubilee
|
||||
# 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/Jubilee/
|
||||
# The printer models will be shown by the Configuration Wizard in this order,
|
||||
|
||||
[printer_model:Jubilee]
|
||||
name = Jubilee
|
||||
variants = 0.4; Volcano 0.4
|
||||
technology = FFF
|
||||
bed_model = Jubilee_bed.stl
|
||||
bed_texture = Jubilee_texture.svg
|
||||
default_materials = Generic PLA @Jubilee; Generic PETG @Jubilee
|
||||
|
||||
[print:*common*]
|
||||
avoid_crossing_perimeters = 0
|
||||
bottom_fill_pattern = monotonic
|
||||
bottom_solid_layers = 3
|
||||
bridge_acceleration = 0
|
||||
bridge_angle = 0
|
||||
bridge_flow_ratio = 1
|
||||
bridge_speed = 80
|
||||
brim_width = 0
|
||||
clip_multipart_objects = 0
|
||||
compatible_printers_condition = printer_notes=~/.*V6.*/
|
||||
complete_objects = 0
|
||||
default_acceleration = 0
|
||||
dont_support_bridges = 1
|
||||
elefant_foot_compensation = 0
|
||||
ensure_vertical_shell_thickness = 0
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
external_perimeter_speed = 50%
|
||||
external_perimeters_first = 0
|
||||
extra_perimeters = 1
|
||||
extruder_clearance_height = 20
|
||||
extruder_clearance_radius = 20
|
||||
extrusion_width = 0.45
|
||||
fill_angle = 45
|
||||
fill_density = 10%
|
||||
fill_pattern = rectilinear
|
||||
first_layer_acceleration = 0
|
||||
first_layer_extrusion_width = 0.45
|
||||
first_layer_height = 0.2
|
||||
first_layer_speed = 30
|
||||
gap_fill_speed = 50
|
||||
gcode_comments = 0
|
||||
gcode_label_objects = 0
|
||||
infill_acceleration = 0
|
||||
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 = 160
|
||||
interface_shells = 0
|
||||
layer_height = 0.2
|
||||
max_print_speed = 150
|
||||
max_volumetric_speed = 0
|
||||
min_skirt_length = 12
|
||||
notes =
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = [input_filename_base].gcode
|
||||
overhangs = 1
|
||||
perimeter_acceleration = 0
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.45
|
||||
perimeter_speed = 130
|
||||
perimeters = 2
|
||||
post_process =
|
||||
print_settings_id =
|
||||
raft_layers = 0
|
||||
resolution = 0
|
||||
seam_position = nearest
|
||||
single_extruder_multi_material_priming = 1
|
||||
skirt_distance = 6
|
||||
skirt_height = 1
|
||||
skirts = 1
|
||||
slice_closing_radius = 0.049
|
||||
small_perimeter_speed = 40
|
||||
solid_infill_below_area = 70
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_extrusion_width = 0.45
|
||||
solid_infill_speed = 100
|
||||
spiral_vase = 0
|
||||
standby_temperature_delta = -5
|
||||
support_material = 0
|
||||
support_material_angle = 0
|
||||
support_material_auto = 1
|
||||
support_material_buildplate_only = 0
|
||||
support_material_contact_distance = 0.2
|
||||
support_material_enforce_layers = 0
|
||||
support_material_extruder = 1
|
||||
support_material_extrusion_width = 0.35
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_extruder = 1
|
||||
support_material_interface_layers = 3
|
||||
support_material_interface_spacing = 0
|
||||
support_material_interface_speed = 100%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2.5
|
||||
support_material_speed = 50
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 0
|
||||
support_material_with_sheath = 1
|
||||
support_material_xy_spacing = 50%
|
||||
thin_walls = 1
|
||||
threads = 12
|
||||
top_fill_pattern = monotonic
|
||||
top_infill_extrusion_width = 0.45
|
||||
top_solid_infill_speed = 70
|
||||
top_solid_layers = 3
|
||||
travel_speed = 333
|
||||
wipe_tower = 0
|
||||
wipe_tower_bridging = 10
|
||||
wipe_tower_rotation_angle = 0
|
||||
wipe_tower_width = 60
|
||||
wipe_tower_x = 180
|
||||
wipe_tower_y = 140
|
||||
xy_size_compensation = 0
|
||||
|
||||
[print:0.2mm V6, aesthetic @Jubilee]
|
||||
inherits = *common*
|
||||
|
||||
[print:0.2mm V6, functional @Jubilee]
|
||||
inherits = *common*
|
||||
perimeters = 6
|
||||
fill_density = 30%
|
||||
fill_pattern = rectilinear
|
||||
perimeter_speed = 80
|
||||
small_perimeter_speed = 50
|
||||
external_perimeter_speed = 70%
|
||||
infill_speed = 120
|
||||
solid_infill_speed = 100
|
||||
top_solid_infill_speed = 60
|
||||
support_material_speed = 60
|
||||
bridge_speed = 90
|
||||
first_layer_speed = 40
|
||||
|
||||
[print:0.2mm Volcano, aesthetic @Jubilee]
|
||||
inherits = *common*
|
||||
compatible_printers_condition = printer_notes=~/.*Volcano.*/
|
||||
max_print_speed = 200
|
||||
|
||||
[print:0.2mm Volcano, functional @Jubilee]
|
||||
inherits = *common*
|
||||
compatible_printers_condition = printer_notes=~/.*Volcano.*/
|
||||
perimeters = 6
|
||||
fill_density = 30%
|
||||
fill_pattern = rectilinear
|
||||
perimeter_speed = 120
|
||||
small_perimeter_speed = 40
|
||||
external_perimeter_speed = 80
|
||||
infill_speed = 170
|
||||
solid_infill_speed = 100
|
||||
top_solid_infill_speed = 70
|
||||
support_material_speed = 70
|
||||
bridge_speed = 90
|
||||
gap_fill_speed = 50
|
||||
first_layer_speed = 40
|
||||
max_print_speed = 200
|
||||
|
||||
[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 = 1
|
||||
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
|
||||
extrusion_multiplier = 0.92
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 600
|
||||
filament_colour = #29B2B2
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 4
|
||||
filament_cost = 24
|
||||
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_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 = 190
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
min_print_speed = 30
|
||||
slowdown_below_layer_time = 1
|
||||
start_filament_gcode = "; Filament gcode\n"
|
||||
temperature = 190
|
||||
|
||||
[filament:*PLA*]
|
||||
inherits = *common*
|
||||
|
||||
[filament:Generic PLA @Jubilee]
|
||||
inherits = *common*
|
||||
filament_vendor = Generic
|
||||
|
||||
[filament:Hatchbox PLA @Jubilee]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Hatchbox
|
||||
|
||||
[filament:Generic PETG @Jubilee]
|
||||
filament_vendor = Generic
|
||||
bed_temperature = 65
|
||||
bridge_fan_speed = 0
|
||||
compatible_printers =
|
||||
compatible_prints =
|
||||
compatible_prints_condition =
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 3
|
||||
end_filament_gcode = "; Filament-specific end gcode"
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #FF8000
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 4
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
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 = 8
|
||||
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 = 2
|
||||
filament_retract_lift = 0.5
|
||||
filament_retract_lift_above = nil
|
||||
filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = 150
|
||||
filament_settings_id = ""
|
||||
filament_soluble = 0
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = PETG
|
||||
filament_unload_time = 0
|
||||
filament_unloading_speed = 90
|
||||
filament_unloading_speed_start = 100
|
||||
filament_wipe = nil
|
||||
first_layer_bed_temperature = 65
|
||||
first_layer_temperature = 230
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 0
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
temperature = 240
|
||||
|
||||
[filament: Proto-pasta HTPLA @Jubilee]
|
||||
filament_vendor = Proto-pasta
|
||||
bed_temperature = 50
|
||||
bridge_fan_speed = 100
|
||||
compatible_printers =
|
||||
compatible_printers_condition =
|
||||
compatible_prints =
|
||||
compatible_prints_condition =
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 1
|
||||
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
|
||||
extrusion_multiplier = 0.96
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 600
|
||||
filament_colour = #29B2B2
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 0
|
||||
filament_cost = 24
|
||||
filament_density = 0
|
||||
filament_deretract_speed = nil
|
||||
filament_diameter = 1.75
|
||||
filament_load_time = 10
|
||||
filament_loading_speed = 28
|
||||
filament_loading_speed_start = 3
|
||||
filament_max_volumetric_speed = 0
|
||||
filament_minimal_purge_on_wipe_tower = 0
|
||||
filament_notes = ""
|
||||
filament_ramming_parameters = "120 100| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 8.87097 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_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 = 50
|
||||
first_layer_temperature = 200
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
min_print_speed = 30
|
||||
slowdown_below_layer_time = 1
|
||||
start_filament_gcode = "; Filament gcode\n"
|
||||
temperature = 200
|
||||
|
||||
[filament:Prusa PLA @Jubilee]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Made for Prusa
|
||||
bed_temperature = 50
|
||||
bridge_fan_speed = 100
|
||||
cooling = 1
|
||||
disable_fan_first_layers = 1
|
||||
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
|
||||
extrusion_multiplier = 0.96
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 600
|
||||
filament_colour = #29B2B2
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 4
|
||||
filament_cost = 24
|
||||
filament_density = 0
|
||||
filament_deretract_speed = nil
|
||||
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_unloading_speed = 90
|
||||
filament_unloading_speed_start = 100
|
||||
filament_wipe = nil
|
||||
first_layer_bed_temperature = 50
|
||||
first_layer_temperature = 210
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
min_print_speed = 30
|
||||
slowdown_below_layer_time = 1
|
||||
start_filament_gcode = "; Filament gcode\n"
|
||||
temperature = 210
|
||||
|
||||
[filament:Solutech PLA @Jubilee]
|
||||
inherits = *PLA*
|
||||
filament_vendor = Solutech
|
||||
bed_temperature = 50
|
||||
bridge_fan_speed = 100
|
||||
extrusion_multiplier = 0.96
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 600
|
||||
filament_colour = #29B2B2
|
||||
first_layer_bed_temperature = 50
|
||||
first_layer_temperature = 200
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
min_print_speed = 30
|
||||
slowdown_below_layer_time = 1
|
||||
start_filament_gcode = "; Filament gcode\n"
|
||||
temperature = 200
|
||||
|
||||
[filament:Verbatim BVOH @Jubilee]
|
||||
filament_vendor = Verbatim
|
||||
bed_temperature = 60
|
||||
bridge_fan_speed = 100
|
||||
cooling = 0
|
||||
disable_fan_first_layers = 1
|
||||
end_filament_gcode = "; Filament-specific end gcode"
|
||||
extrusion_multiplier = 1
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #FFFFD7
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 4
|
||||
filament_cost = 218
|
||||
filament_density = 1.23
|
||||
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 = 4
|
||||
filament_minimal_purge_on_wipe_tower = 15
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH"
|
||||
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_soluble = 1
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = PVA
|
||||
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
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
temperature = 210
|
||||
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
bed_shape = 0x0,300x0,300x300,0x300
|
||||
cooling_tube_length = 5
|
||||
cooling_tube_retraction = 91.5
|
||||
deretract_speed = 0,0
|
||||
end_gcode = T-1 ; desect current tool\nG0 Z305 ; move bed all the way to the bottom\nM104 S0 T0; turn off extruder 0\nM104 S0 T1; turn off extruder 1\nM140 S0 ; turn off bed\nG0 X0 Y0 F30000; return home\nM84 S600; disable motors after ten mins of inactivity\n
|
||||
extra_loading_move = -2
|
||||
extruder_colour = #FF8000;#0080FF
|
||||
extruder_offset = 0x0,0x0
|
||||
gcode_flavor = marlin
|
||||
high_current_on_filament_swap = 0
|
||||
layer_gcode =
|
||||
machine_max_acceleration_e = 1500
|
||||
machine_max_acceleration_extruding = 1500
|
||||
machine_max_acceleration_retracting = 1500
|
||||
machine_max_acceleration_x = 1000
|
||||
machine_max_acceleration_y = 1000
|
||||
machine_max_acceleration_z = 20
|
||||
machine_max_feedrate_e = 8000
|
||||
machine_max_feedrate_x = 13000
|
||||
machine_max_feedrate_y = 13000
|
||||
machine_max_feedrate_z = 800
|
||||
machine_max_jerk_e = 50
|
||||
machine_max_jerk_x = 17
|
||||
machine_max_jerk_y = 17
|
||||
machine_max_jerk_z = 0.1
|
||||
machine_min_extruding_rate = 0
|
||||
machine_min_travel_rate = 0
|
||||
machine_limits_usage = time_estimate_only
|
||||
max_layer_height = 0.3,0.3
|
||||
max_print_height = 300
|
||||
min_layer_height = 0.05,0.05
|
||||
nozzle_diameter = 0.4,0.4
|
||||
parking_pos_retraction = 92
|
||||
printer_model =
|
||||
printer_technology = FFF
|
||||
remaining_times = 0
|
||||
retract_before_travel = 2,2
|
||||
retract_before_wipe = 0%,0%
|
||||
retract_layer_change = 0,0
|
||||
retract_length = 1,1
|
||||
retract_length_toolchange = 1,1
|
||||
retract_lift = 0.2,0.2
|
||||
retract_lift_above = 0,0
|
||||
retract_lift_below = 0,0
|
||||
retract_restart_extra = 0.05,0.05
|
||||
retract_restart_extra_toolchange = 0,0
|
||||
retract_speed = 133,133
|
||||
silent_mode = 0
|
||||
single_extruder_multi_material = 0
|
||||
start_gcode = G91 ; relative moves\nG1 Z1 F900 ; raise tool 1mm\nG90 ; absolute moves\nT-1 ; Make sure nothing is parked on the carriage\nG0 X150 Y150 F10000; Move to the center of the print area\nM558 F500 ; Set the probing speed\nG30 ; Do a single probe\nM558 F50 ; Set a slower probing speed\nG30 ; Do a second probe\nT[current_extruder]
|
||||
thumbnails =
|
||||
toolchange_gcode = T[next_extruder]
|
||||
use_firmware_retraction = 0
|
||||
use_relative_e_distances = 1
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 0
|
||||
wipe = 0,0
|
||||
z_offset = 0
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0
|
||||
default_filament_profile = "Generic PLA @Jubilee; Generic PLA @Jubilee"
|
||||
default_print_profile = 0.2mm V6, aesthetic @Jubilee
|
||||
|
||||
[printer:Jubilee]
|
||||
inherits = *common*
|
||||
printer_model = Jubilee
|
||||
printer_variant = 0.4
|
||||
printer_notes = V6
|
||||
|
||||
[printer:Jubilee Volcano 0.4mm]
|
||||
inherits = *common*
|
||||
printer_model = Jubilee
|
||||
printer_variant = Volcano 0.4
|
||||
printer_notes = Volcano
|
||||
default_print_profile = 0.2mm Volcano, aesthetic @Jubilee
|
BIN
resources/profiles/Jubilee/Jubilee_bed.stl
Normal file
BIN
resources/profiles/Jubilee/Jubilee_bed.stl
Normal file
Binary file not shown.
232
resources/profiles/Jubilee/Jubilee_texture.svg
Normal file
232
resources/profiles/Jubilee/Jubilee_texture.svg
Normal file
@ -0,0 +1,232 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 680.31502 680.31502"
|
||||
enable-background="new 0 0 680.3149 680.3149"
|
||||
xml:space="preserve"
|
||||
id="svg66"
|
||||
sodipodi:docname="Jubilee_texture.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
width="680.315"
|
||||
height="680.315"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs70" /><sodipodi:namedview
|
||||
id="namedview68"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="true"
|
||||
inkscape:zoom="0.64161465"
|
||||
inkscape:cx="225.21306"
|
||||
inkscape:cy="295.34862"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1129"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g24"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4311"
|
||||
empcolor="#ffffff"
|
||||
empopacity="0.49803922"
|
||||
color="#ffffff"
|
||||
opacity="0.50196078"
|
||||
spacingx="37.795277"
|
||||
spacingy="37.795277"
|
||||
units="cm"
|
||||
dotted="false"
|
||||
originx="340.1575"
|
||||
originy="340.1575" /></sodipodi:namedview>
|
||||
|
||||
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 37.795277,0 V 680.31498"
|
||||
id="path4436" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 75.590554,680.31498 V 0"
|
||||
id="path4438" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 113.38583,0 V 680.31498"
|
||||
id="path4553" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 151.1811,680.31498 V 0"
|
||||
id="path4555" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 188.97638,0 V 680.31498"
|
||||
id="path4557" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 226.77166,680.31498 V 0"
|
||||
id="path4559" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 264.56694,0 V 680.31498"
|
||||
id="path4561" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 302.36221,680.31498 V 0"
|
||||
id="path4563" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 340.15749,0 V 680.31498"
|
||||
id="path4565" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 377.95277,680.31498 V 0"
|
||||
id="path4567" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 415.74804,0 V 680.31498"
|
||||
id="path4569" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 453.54332,680.31498 V 0"
|
||||
id="path4571" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 491.3386,0 V 680.31498"
|
||||
id="path4573" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 529.13388,680.31498 529.13387,0"
|
||||
id="path4575" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 566.92915,0 V 680.31498"
|
||||
id="path4577" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 604.72443,680.31498 V 0"
|
||||
id="path4579" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 642.51971,0 V 680.31498"
|
||||
id="path4581" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,642.51971 H 0"
|
||||
id="path4583" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,604.72443 H 680.31498"
|
||||
id="path4585" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,566.92915 H 0"
|
||||
id="path4587" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,529.13387 H 680.31498"
|
||||
id="path4589" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,491.3386 H 0"
|
||||
id="path4591" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,453.54332 H 680.31498"
|
||||
id="path4593" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,415.74804 H 0"
|
||||
id="path4595" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,377.95277 H 680.31498"
|
||||
id="path4597" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,340.15749 H 0"
|
||||
id="path4599" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,302.36221 H 680.31498"
|
||||
id="path4601" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,264.56694 H 0"
|
||||
id="path4603" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,226.77166 H 680.31498"
|
||||
id="path4605" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,188.97638 H 0"
|
||||
id="path4607" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,151.1811 H 680.31498"
|
||||
id="path4609" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,113.38583 H 0"
|
||||
id="path4611" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 0,75.590554 H 680.31498"
|
||||
id="path4613" /><path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 680.31498,37.795277 H 0"
|
||||
id="path4615" /><g
|
||||
id="logo"
|
||||
transform="rotate(180,347.24687,326.4726)">
|
||||
<g
|
||||
id="g24">
|
||||
<path
|
||||
d="m 280.4813,484.2325 c 18.38,7.6201 38.54,11.83 59.6801,11.83 v -14.17 c -19.22,0 -37.54,-3.82 -54.25,-10.75 h -0.01 c -17.3201,-7.18 -32.9,-17.7 -45.9599,-30.77 -13.05,-13.04 -23.5801,-28.63 -30.76,-45.96 l -13.1001,5.43 c 7.9,19.05 19.47,36.2 33.8301,50.56 14.3598,14.3601 31.5098,25.9301 50.5698,33.83 z"
|
||||
id="path2"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 196.0813,280.4726 c 7.9,-19.05 19.47,-36.2 33.8301,-50.56 l -10.02,-10.02 c -15.67,15.67 -28.29,34.37 -36.9,55.16 -8.3199,20.05 -12.91,42.04 -12.91,65.1 0,23.06 4.5901,45.06 12.91,65.11 l 13.09,-5.42 c -7.6199,-18.39 -11.83,-38.54 -11.83,-59.69 -1e-4,-21.14 4.21,-41.3 11.8299,-59.68 z"
|
||||
id="path4"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 209.1814,394.4126 13.1099,-5.4301 c -6.25,-15.04 -9.6899,-31.54 -9.6899,-48.83 h -14.1799 c -2e-4,19.2201 3.8298,37.5501 10.7599,54.2601 z"
|
||||
id="path6"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 240.9414,340.1526 c 0,-13.45 2.6799,-26.28 7.5299,-37.97 l -13.09,-5.43 c -5.55,13.37 -8.61,28.03 -8.61,43.4 z"
|
||||
id="path8"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 313.0412,405.6426 c 8.3501,3.47 17.51,5.38 27.1201,5.38 9.61,0 18.77,-1.91 27.1199,-5.38 l -5.4199,-13.09 c -6.6899,2.77 -14.02,4.3 -21.7,4.3 -7.6801,0 -15.01,-1.53 -21.7,-4.3 -6.9302,-2.87 -13.1702,-7.08 -18.3901,-12.3 v -0.01 c -5.23,-5.22 -9.4299,-11.45 -12.2999,-18.38 l -13.1,5.42 c 3.59,8.66 8.85,16.45 15.3799,22.98 6.53,6.5299 14.3301,11.8 22.99,15.38 z"
|
||||
id="path10"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 248.4813,378.1326 c 5.02,12.13 12.38,23.04 21.52,32.18 9.14,9.14 20.0499,16.51 32.1801,21.52 11.7,4.86 24.53,7.54 37.98,7.54 13.45,0 26.27,-2.68 37.97,-7.54 12.13,-5.01 23.04,-12.38 32.1799,-21.52 9.1401,-9.14 16.5,-20.05 21.52,-32.18 l -13.09,-5.42 c -4.3099,10.4 -10.63,19.75 -18.4601,27.57 -7.8298,7.84 -17.1799,14.15 -27.5698,18.45 -10.03,4.16 -21.02,6.46 -32.55,6.46 -11.53,0 -22.52,-2.29 -32.55,-6.45 -10.3999,-4.31 -19.75,-10.62 -27.5801,-18.46 -7.8298,-7.83 -14.1499,-17.19 -18.45,-27.58 -4.1599,-10.03 -6.4599,-21.02 -6.4599,-32.55 h -14.1799 c -1e-4,13.4599 2.6798,26.28 7.5398,37.98 z"
|
||||
id="path12"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 383.5623,444.9326 c -13.36,5.55 -28.02,8.61 -43.4,8.61 -15.37,0 -30.03,-3.06 -43.3999,-8.61 -13.8601,-5.74 -26.3301,-14.15 -36.78,-24.6 -10.44,-10.44 -18.8601,-22.91 -24.6001,-36.77 l -13.09,5.42 c 6.4601,15.59 15.92,29.6201 27.67,41.3701 11.75,11.75 25.78,21.21 41.37,27.68 15.0399,6.24 31.5299,9.68 48.83,9.68 17.3001,0 33.79,-3.44 48.8301,-9.68 15.58,-6.46 29.61,-15.93 41.36,-27.68 11.75,-11.7401 21.22,-25.77 27.6801,-41.36 6.25,-15.04 9.6899,-31.54 9.6899,-48.84 v -204.44 c -4.5601,-2.85 -9.23,-5.56 -13.99,-8.1 -0.0701,-0.04 -0.13,-0.08 -0.1901,-0.1 v 212.64 c 0,7.69 -0.7699,15.2 -2.22,22.46 -1.4601,7.26 -3.61,14.26 -6.39,20.95 -5.74,13.86 -14.1599,26.33 -24.6,36.77 -10.4401,10.44 -22.91,18.8599 -36.77,24.5999 z"
|
||||
id="path14"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 394.4123,471.1326 5.4301,13.1 c 19.0499,-7.9 36.2,-19.47 50.5599,-33.83 14.3601,-14.36 25.9301,-31.51 33.8301,-50.56 7.62,-18.39 11.83,-38.54 11.83,-59.68 v -183.72 c -4.49,-3.81 -9.12,-7.47 -13.89,-10.95 -0.09,-0.07 -0.1899,-0.14 -0.28,-0.2 v 194.87 c 0,9.61 -0.96,18.99 -2.78,28.06 -1.8199,9.0699 -4.5099,17.83 -7.98,26.19 -7.1799,17.33 -17.71,32.92 -30.76,45.96 -13.0501,13.07 -28.64,23.58 -45.9601,30.76 z"
|
||||
id="path16"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 510.6122,169.8626 c -0.1199,-0.12 -0.24,-0.25 -0.3699,-0.37 v 170.66 h -0.01 c 0,23.06 -4.5901,45.06 -12.91,65.11 -8.62,20.79 -21.24,39.49 -36.9,55.16 -15.6699,15.66 -34.37,28.28 -55.1599,36.9 -20.05,8.32 -42.04,12.91 -65.1001,12.91 -23.0599,0 -45.05,-4.59 -65.1,-12.91 -20.7899,-8.61 -39.5,-21.24 -55.17,-36.9 l -10.02,10.02 c 33.3401,33.35 79.4101,53.97 130.29,53.97 50.8701,0 96.9301,-20.6201 130.28,-53.97 33.3401,-33.34 53.97,-79.4 53.97,-130.28 v -155.27 c -4.3899,-5.2 -8.99,-10.22 -13.8001,-15.03 z"
|
||||
id="path18"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 439.3923,120.5326 c -4.6199,-2.09 -9.3199,-4.04 -14.1,-5.85 -0.0199,-0.01 -0.0399,-0.01 -0.0699,-0.02 v 225.5 h 14.1699 z"
|
||||
id="path20"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 405.6423,367.2826 c 3.47,-8.36 5.3801,-17.52 5.3801,-27.12 h 0.0299 v -230.35 c -4.67,-1.44 -9.4,-2.73 -14.1801,-3.88 v 234.22 h -0.0199 c 0,7.69 -1.53,15.02 -4.3,21.71 -2.87,6.93 -7.08,13.17 -12.2999,18.39 l 10.01,10.01 c 6.5299,-6.5301 11.7899,-14.32 15.3799,-22.98 z"
|
||||
id="path22"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#d4d4d4;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
d="m 418.7413,307.6026 c -2.1,-5.0601 -4.68,-9.88 -7.67,-14.4 v 46.95 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -63.37 c -7.08,-6.34 -15.23,-11.51 -24.14,-15.2 -10.03,-4.16 -21.02,-6.46 -32.55,-6.46 -11.53,0 -22.52,2.29 -32.55,6.45 -10.4,4.31 -19.75,10.62 -27.58,18.46 -7.83,7.83 -14.15,17.18 -18.45,27.57 -4.16,10.03 -6.46,21.02 -6.46,32.55 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 4.16,-10.03 6.46,-21.03 6.46,-32.56 1e-4,-11.53 -2.2999,-22.52 -6.4599,-32.55 z m -78.58,103.42 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path26" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 425.2913,340.1526 v -50.97 c -4.01,-6.69 -8.79,-12.86 -14.22,-18.4 v 69.37 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -81.42 c -5.81,-4.06 -12.08,-7.5 -18.72,-10.25 -11.7,-4.86 -24.52,-7.54 -37.97,-7.54 -13.45,0 -26.28,2.68 -37.98,7.54 -12.13,5.02 -23.04,12.38 -32.18,21.52 -9.14,9.14 -16.5,20.05 -21.53,32.18 -4.85,11.69 -7.53,24.52 -7.53,37.97 h 14.18 c 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 l 13.09,5.42 c 4.86,-11.7 7.54,-24.52 7.54,-37.98 z m -85.13,70.87 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path28" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 411.0713,270.7826 v 69.37 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -98.2 c -4.26,-2.47 -8.7,-4.67 -13.29,-6.57 -13.36,-5.55 -28.02,-8.61 -43.4,-8.61 -15.37,0 -30.03,3.06 -43.4,8.61 -13.86,5.74 -26.33,14.15 -36.78,24.6 -10.45,10.44 -18.86,22.91 -24.6,36.77 l 13.09,5.43 c -4.85,11.69 -7.53,24.52 -7.53,37.97 h 14.18 c 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 l 13.09,5.42 c -5.02,12.13 -12.38,23.04 -21.52,32.18 -9.14,9.14 -20.05,16.51 -32.18,21.52 -11.7,4.86 -24.52,7.54 -37.97,7.54 -13.45,0 -26.28,-2.68 -37.98,-7.54 -12.13,-5.01 -23.04,-12.38 -32.18,-21.52 -9.14,-9.14 -16.5,-20.05 -21.52,-32.18 -4.86,-11.7 -7.54,-24.52 -7.54,-37.98 h -14.17 c 0,15.38 3.06,30.04 8.61,43.41 5.74,13.86 14.16,26.33 24.6,36.77 10.45,10.45 22.92,18.86 36.78,24.6 13.37,5.55 28.03,8.61 43.4,8.61 15.38,0 30.04,-3.06 43.4,-8.61 13.86,-5.74 26.33,-14.16 36.77,-24.6 10.44,-10.44 18.86,-22.91 24.6,-36.77 5.55,-13.37 8.61,-28.03 8.61,-43.41 0,-15.37 -3.06,-30.03 -8.61,-43.4 -1.6,-3.86 -3.41,-7.62 -5.42,-11.25 v 54.65 h -14.22 v -74.88 c -1.6,-1.82 -3.25,-3.58 -4.96,-5.29 -2.93,-2.93 -6.02,-5.6999 -9.26,-8.29 v 17.55 m -70.9099,141.78 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path30" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 400.2813,400.2826 c 7.83,-7.82 14.15,-17.17 18.46,-27.57 l 13.09,5.42 c -5.02,12.13 -12.38,23.04 -21.52,32.18 -9.14,9.14 -20.05,16.51 -32.18,21.52 -11.7,4.86 -24.52,7.54 -37.97,7.54 -13.45,0 -26.28,-2.68 -37.98,-7.54 -12.13,-5.01 -23.04,-12.38 -32.18,-21.52 -9.14,-9.14 -16.5,-20.05 -21.52,-32.18 -4.86,-11.7 -7.54,-24.52 -7.54,-37.98 h -14.17 c 0,-15.37 3.06,-30.03 8.61,-43.4 l 13.09,5.43 c -4.85,11.69 -7.53,24.52 -7.53,37.97 h 14.18 c 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.57,-18.45 z m -33,5.36 c -8.35,3.47 -17.5099,5.38 -27.12,5.38 -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 z"
|
||||
id="path32" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 418.7413,307.6026 c -2.1,-5.0601 -4.68,-9.88 -7.67,-14.4 v 46.95 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -63.37 c -7.08,-6.34 -15.23,-11.51 -24.14,-15.2 -10.03,-4.16 -21.02,-6.46 -32.55,-6.46 -11.53,0 -22.52,2.29 -32.55,6.45 -10.4,4.31 -19.75,10.62 -27.58,18.46 -7.83,7.83 -14.15,17.18 -18.45,27.57 -4.16,10.03 -6.46,21.02 -6.46,32.55 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 4.16,-10.03 6.46,-21.03 6.46,-32.56 1e-4,-11.53 -2.2999,-22.52 -6.4599,-32.55 z m -78.58,103.42 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path34" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 425.2913,340.1526 v -50.97 c -4.01,-6.69 -8.79,-12.86 -14.22,-18.4 v 69.37 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -81.42 c -5.81,-4.06 -12.08,-7.5 -18.72,-10.25 -11.7,-4.86 -24.52,-7.54 -37.97,-7.54 -13.45,0 -26.28,2.68 -37.98,7.54 -12.13,5.02 -23.04,12.38 -32.18,21.52 -9.14,9.14 -16.5,20.05 -21.53,32.18 -4.85,11.69 -7.53,24.52 -7.53,37.97 h 14.18 c 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 l 13.09,5.42 c 4.86,-11.7 7.54,-24.52 7.54,-37.98 z m -85.13,70.87 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path36" />
|
||||
<path
|
||||
fill="none"
|
||||
d="m 411.0713,270.7826 v 69.37 h -0.05 c 0,9.61 -1.91,18.77 -5.38,27.13 -3.59,8.66 -8.85,16.45 -15.38,22.98 l -10.01,-10.01 c 5.22,-5.22 9.43,-11.46 12.3,-18.39 2.77,-6.69 4.3,-14.02 4.3,-21.71 v -98.2 c -4.26,-2.47 -8.7,-4.67 -13.29,-6.57 -13.36,-5.55 -28.02,-8.61 -43.4,-8.61 -15.37,0 -30.03,3.06 -43.4,8.61 -13.86,5.74 -26.33,14.15 -36.78,24.6 -10.45,10.44 -18.86,22.91 -24.6,36.77 l 13.09,5.43 c -4.85,11.69 -7.53,24.52 -7.53,37.97 h 14.18 c 0,11.53 2.3,22.52 6.46,32.55 4.3,10.39 10.62,19.75 18.45,27.58 7.83,7.84 17.1801,14.15 27.58,18.46 10.03,4.16 21.02,6.45 32.55,6.45 11.53,0 22.52,-2.3 32.55,-6.46 10.39,-4.3 19.74,-10.61 27.5699,-18.45 7.83,-7.82 14.15,-17.17 18.46,-27.57 l 13.09,5.42 c -5.02,12.13 -12.38,23.04 -21.52,32.18 -9.14,9.14 -20.05,16.51 -32.18,21.52 -11.7,4.86 -24.52,7.54 -37.97,7.54 -13.45,0 -26.28,-2.68 -37.98,-7.54 -12.13,-5.01 -23.04,-12.38 -32.18,-21.52 -9.14,-9.14 -16.5,-20.05 -21.52,-32.18 -4.86,-11.7 -7.54,-24.52 -7.54,-37.98 h -14.17 c 0,15.38 3.06,30.04 8.61,43.41 5.74,13.86 14.16,26.33 24.6,36.77 10.45,10.45 22.92,18.86 36.78,24.6 13.37,5.55 28.03,8.61 43.4,8.61 15.38,0 30.04,-3.06 43.4,-8.61 13.86,-5.74 26.33,-14.16 36.77,-24.6 10.44,-10.44 18.86,-22.91 24.6,-36.77 5.55,-13.37 8.61,-28.03 8.61,-43.41 0,-15.37 -3.06,-30.03 -8.61,-43.4 -1.6,-3.86 -3.41,-7.62 -5.42,-11.25 v 54.65 h -14.22 v -74.88 c -1.6,-1.82 -3.25,-3.58 -4.96,-5.29 -2.93,-2.93 -6.02,-5.6999 -9.26,-8.29 v 17.55 m -70.9099,141.78 c -9.61,0 -18.77,-1.91 -27.12,-5.38 -8.66,-3.58 -16.46,-8.85 -22.99,-15.38 -6.53,-6.53 -11.79,-14.32 -15.38,-22.98 l 13.1,-5.42 c 2.87,6.93 7.0699,13.16 12.3,18.38 v 0.01 c 5.22,5.22 11.46,9.43 18.39,12.3 6.69,2.77 14.02,4.3 21.7,4.3 7.68,0 15.01,-1.53 21.7,-4.3 l 5.42,13.09 c -8.35,3.4699 -17.51,5.38 -27.12,5.38 z"
|
||||
id="path38" />
|
||||
</g></svg>
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/profiles/Jubilee/Jubilee_thumbnail.png
Normal file
BIN
resources/profiles/Jubilee/Jubilee_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.4.0-rc
|
||||
1.4.2 Added SLA material profiles.
|
||||
1.4.1 Updated firmware version.
|
||||
1.4.0 Updated for the PrusaSlicer 2.4.0-rc release. Updated SLA material colors.
|
||||
min_slic3r_version = 2.4.0-beta2
|
||||
|
@ -5,7 +5,7 @@
|
||||
name = Prusa Research
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 1.4.1
|
||||
config_version = 1.4.2
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
|
||||
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -4875,6 +4875,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Prusa 0.025
|
||||
|
||||
[sla_material:Prusa Orange Tough @0.025]
|
||||
@ -5052,6 +5076,14 @@ material_type = Casting
|
||||
material_vendor = Made for Prusa
|
||||
material_colour = #FFFF6F
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 4
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Siraya Tech Simple Clear @0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 8
|
||||
@ -5190,6 +5222,14 @@ material_type = Tough
|
||||
material_vendor = Asiga
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
|
||||
[sla_material:Ameralabs AMD 3 LED @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 5
|
||||
@ -5728,6 +5768,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Prusa 0.05
|
||||
|
||||
[sla_material:Prusa Beige Tough @0.05]
|
||||
@ -6018,6 +6082,14 @@ material_type = Tough
|
||||
material_vendor = BlueCast
|
||||
material_colour = #FFEEE6
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
|
||||
## Prusa Polymers 0.1
|
||||
|
||||
[sla_material:Prusament Resin Tough Prusa Orange @0.1]
|
||||
@ -6084,6 +6156,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 45
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Prusa 0.1
|
||||
|
||||
[sla_material:Prusa Orange Tough @0.1]
|
||||
@ -6244,6 +6340,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
exposure_time = 1.8
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
exposure_time = 2
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
exposure_time = 1.8
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Made for Prusa 0.025
|
||||
|
||||
[sla_material:Prusa Orange Tough @0.025 SL1S]
|
||||
@ -6366,6 +6486,15 @@ material_type = Casting
|
||||
material_vendor = Made for Prusa
|
||||
material_colour = #00B900
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
exposure_time = 1.8
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
exposure_time = 1.8
|
||||
@ -6413,6 +6542,7 @@ initial_exposure_time = 15
|
||||
material_type = Dental
|
||||
material_vendor = DruckWege
|
||||
material_colour = #FFEEE6
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:DruckWege Type D Standard White @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
@ -6421,6 +6551,7 @@ initial_exposure_time = 15
|
||||
material_type = Tough
|
||||
material_vendor = DruckWege
|
||||
material_colour = #FFFFFF
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:DruckWege Type D Standard Pigmentfrei Clear @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
@ -6429,6 +6560,7 @@ initial_exposure_time = 15
|
||||
material_type = Tough
|
||||
material_vendor = DruckWege
|
||||
material_colour = #F8F8F8
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:3DM-ABS Orange @0.025 SL1S]
|
||||
inherits = *0.025_sl1s*
|
||||
@ -6530,6 +6662,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Made for Prusa 0.05
|
||||
|
||||
[sla_material:Prusa Orange Tough @0.05 SL1S]
|
||||
@ -6652,6 +6808,15 @@ material_type = Casting
|
||||
material_vendor = Made for Prusa
|
||||
material_colour = #00B900
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
exposure_time = 2.4
|
||||
@ -6699,6 +6864,7 @@ initial_exposure_time = 15
|
||||
material_type = Dental
|
||||
material_vendor = DruckWege
|
||||
material_colour = #FFEEE6
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:DruckWege Type D Standard White @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
@ -6707,6 +6873,7 @@ initial_exposure_time = 15
|
||||
material_type = Tough
|
||||
material_vendor = DruckWege
|
||||
material_colour = #FFFFFF
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:DruckWege Type D Standard Pigmentfrei Clear @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
@ -6715,6 +6882,7 @@ initial_exposure_time = 15
|
||||
material_type = Tough
|
||||
material_vendor = DruckWege
|
||||
material_colour = #F8F8F8
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:3DM-ABS Orange @0.05 SL1S]
|
||||
inherits = *0.05_sl1s*
|
||||
@ -6816,6 +6984,30 @@ material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #F9DB4C
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Green @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
exposure_time = 2.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #1DAf5E
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Red @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
exposure_time = 3
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #D21B31
|
||||
|
||||
[sla_material:Prusament Resin Tough Transparent Amber @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
exposure_time = 3.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Prusa Polymers
|
||||
material_colour = #FCB30E
|
||||
|
||||
## Made for Prusa 0.1
|
||||
|
||||
[sla_material:Prusa Orange Tough @0.1 SL1S]
|
||||
@ -6938,6 +7130,15 @@ material_type = Casting
|
||||
material_vendor = Made for Prusa
|
||||
material_colour = #00B900
|
||||
|
||||
[sla_material:Ameralabs TGM-7 LED @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
exposure_time = 2.6
|
||||
initial_exposure_time = 25
|
||||
material_type = Tough
|
||||
material_vendor = Ameralabs
|
||||
material_colour = #C0C0C0
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:PrimaCreator Tough Light Grey @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
exposure_time = 3
|
||||
@ -6985,6 +7186,7 @@ initial_exposure_time = 15
|
||||
material_type = Dental
|
||||
material_vendor = DruckWege
|
||||
material_colour = #FFEEE6
|
||||
material_print_speed = slow
|
||||
|
||||
[sla_material:3DM-ABS Orange @0.1 SL1S]
|
||||
inherits = *0.1_sl1s*
|
||||
@ -7695,7 +7897,7 @@ retract_lift_below = 179
|
||||
retract_layer_change = 1
|
||||
silent_mode = 0
|
||||
remaining_times = 1
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S170 ; set extruder temp for bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM109 R170 ; wait for bed leveling temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM204 T1250 ; set travel acceleration\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling \nM204 T[machine_max_acceleration_travel] ; restore travel acceleration\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0\nG1 Y-2 X179 F2400\nG1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\n\n; intro line\nG1 X170 F1000\nG1 Z0.2 F720\nG1 X110 E8 F900\nG1 X40 E10 F700\nG92 E0\n\nM221 S95 ; set flow
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S170 ; set extruder temp for bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM109 R170 ; wait for bed leveling temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM204 T1250 ; set travel acceleration\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling \nM204 T[machine_max_acceleration_travel] ; restore travel acceleration\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0\nG1 Y-2 X179 F2400\nG1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\n\n; intro line\nG1 X170 F1000\nG1 Z0.2 F720\nG1 X110 E8 F900\nG1 X40 E10 F700\nG92 E0\n\nM221 S95 ; set flow
|
||||
end_gcode = G1 E-1 F2100 ; retract\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F720 ; Move print head up{endif}\nG1 X178 Y178 F4200 ; park print head\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM221 S100 ; reset flow\nM900 K0 ; reset LA\nM84 ; disable motors
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MINI\n
|
||||
extruder_colour =
|
||||
@ -7712,7 +7914,7 @@ default_print_profile = 0.10mm DETAIL @0.25 nozzle MINI
|
||||
retract_length = 3
|
||||
retract_lift = 0.15
|
||||
retract_before_travel = 1
|
||||
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S170 ; set extruder temp for bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM109 R170 ; wait for bed leveling temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM204 T1250 ; set travel acceleration\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling \nM204 T[machine_max_acceleration_travel] ; restore travel acceleration\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0\nG1 Y-2 X179 F2400\nG1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\n\n; intro line\nG1 X170 F1000\nG1 Z0.2 F720\nG1 X110 E8 F600\nG1 X40 E10 F400\nG92 E0\n\nM221 S95 ; set flow
|
||||
start_gcode = M862.3 P \"[printer_model]\" ; printer model check\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S170 ; set extruder temp for bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM109 R170 ; wait for bed leveling temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM204 T1250 ; set travel acceleration\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling \nM204 T[machine_max_acceleration_travel] ; restore travel acceleration\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0\nG1 Y-2 X179 F2400\nG1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\n\n; intro line\nG1 X170 F1000\nG1 Z0.2 F720\nG1 X110 E8 F600\nG1 X40 E10 F400\nG92 E0\n\nM221 S95 ; set flow
|
||||
|
||||
[printer:Original Prusa MINI & MINI+ 0.6 nozzle]
|
||||
inherits = Original Prusa MINI & MINI+
|
||||
|
@ -83,7 +83,7 @@ extruder_clearance_radius = 45
|
||||
extrusion_width = 0.4
|
||||
fill_angle = 45
|
||||
fill_density = 15%
|
||||
fill_pattern = adaptivecubic
|
||||
fill_pattern = cubic
|
||||
first_layer_acceleration = 1000
|
||||
first_layer_extrusion_width = 0.45
|
||||
first_layer_height = 0.2
|
||||
@ -198,7 +198,7 @@ dont_support_bridges = 1
|
||||
draft_shield = 0
|
||||
ensure_vertical_shell_thickness = 1
|
||||
external_perimeter_extrusion_width = 0.4
|
||||
external_perimeter_speed = 100
|
||||
external_perimeter_speed = 110
|
||||
extra_perimeters = 0
|
||||
extra_perimeters_overhangs = 0
|
||||
extruder_clearance_height = 25
|
||||
@ -206,7 +206,7 @@ extruder_clearance_radius = 45
|
||||
extrusion_width = 0.4
|
||||
fill_angle = 45
|
||||
fill_density = 15%
|
||||
fill_pattern = rectilinear
|
||||
fill_pattern = cubic
|
||||
first_layer_acceleration = 1000
|
||||
first_layer_extrusion_width = 0.45
|
||||
first_layer_height = 0.2
|
||||
@ -215,7 +215,7 @@ gap_fill = 1
|
||||
gap_fill_speed = 50
|
||||
gcode_comments = 0
|
||||
gcode_label_objects = 1
|
||||
infill_acceleration = 2000
|
||||
infill_acceleration = 3000
|
||||
infill_anchor = 600%
|
||||
infill_anchor_max = 5
|
||||
infill_every_layers = 1
|
||||
@ -239,13 +239,13 @@ notes =
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{print_time}.gcode
|
||||
perimeter_acceleration = 1500
|
||||
perimeter_acceleration = 2500
|
||||
perimeter_bonding = 0%
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.4
|
||||
perimeter_overlap = 100%
|
||||
perimeter_round_corners = 0
|
||||
perimeter_speed = 100
|
||||
perimeter_speed = 120
|
||||
perimeters = 2
|
||||
post_process =
|
||||
print_settings_id =
|
||||
@ -344,11 +344,11 @@ perimeter_speed = 160
|
||||
small_perimeter_speed = 25
|
||||
solid_infill_speed = 80%
|
||||
top_solid_infill_speed = 60%
|
||||
fill_pattern = rectilinear
|
||||
fill_pattern = cubic
|
||||
|
||||
[print:0.20mm NORMAL @RatRig]
|
||||
inherits = *common*; *0.2mm*
|
||||
fill_pattern = rectilinear
|
||||
fill_pattern = cubic
|
||||
external_perimeter_speed = 120
|
||||
infill_speed = 160
|
||||
compatible_printers_condition = printer_model=~/.*VC3_.*/ and nozzle_diameter[0]==0.4
|
||||
@ -361,7 +361,7 @@ bottom_solid_layers = 3
|
||||
[print:0.15mm QUALITY V-Minion @RatRig]
|
||||
inherits = *common_minion*; *0.15mm*
|
||||
compatible_printers_condition = printer_model=~/.*MINION.*/
|
||||
solid_infill_speed = 100
|
||||
solid_infill_speed = 120
|
||||
|
||||
[print:0.20mm HF @RatRig]
|
||||
inherits = 0.15mm HF @RatRig; *0.2mm*
|
||||
@ -384,7 +384,7 @@ top_solid_infill_speed = 60%
|
||||
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
|
||||
between_objects_gcode =
|
||||
color_change_gcode = M600
|
||||
cooling_tube_length = 5
|
||||
@ -436,7 +436,7 @@ retract_restart_extra_toolchange = 0
|
||||
retract_speed = 40
|
||||
silent_mode = 0
|
||||
single_extruder_multi_material = 0
|
||||
start_gcode = START_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\n;SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n
|
||||
start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\nSET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n
|
||||
thumbnails = 16x16,220x220
|
||||
toolchange_gcode =
|
||||
use_firmware_retraction = 0
|
||||
@ -453,7 +453,7 @@ printer_variant = 0.4
|
||||
|
||||
[printer:*vminion-klipper*]
|
||||
inherits = *common*
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n
|
||||
default_filament_profile = "Generic PLA @RatRig"
|
||||
default_print_profile = 0.20mm NORMAL V-Minion @RatRig
|
||||
deretract_speed = 40
|
||||
@ -499,7 +499,7 @@ retract_restart_extra_toolchange = 0
|
||||
retract_speed = 40
|
||||
silent_mode = 0
|
||||
single_extruder_multi_material = 0
|
||||
start_gcode = START_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\n;SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n
|
||||
start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\nSET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n
|
||||
start_gcode_manual = 0
|
||||
template_custom_gcode =
|
||||
thumbnails = 16x16,220x220
|
||||
|
@ -168,7 +168,7 @@ default_print_profile = 0.4mm 1.2nozzle
|
||||
# Common printer preset
|
||||
[printer:*common*]
|
||||
printer_technology = FFF
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n
|
||||
between_objects_gcode =
|
||||
deretract_speed = 25
|
||||
end_gcode = print_end ;end script from macro
|
||||
|
11
resources/shaders/background.fs
Normal file
11
resources/shaders/background.fs
Normal file
@ -0,0 +1,11 @@
|
||||
#version 110
|
||||
|
||||
uniform vec4 top_color;
|
||||
uniform vec4 bottom_color;
|
||||
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = mix(bottom_color, top_color, tex_coord.y);
|
||||
}
|
9
resources/shaders/background.vs
Normal file
9
resources/shaders/background.vs
Normal file
@ -0,0 +1,9 @@
|
||||
#version 110
|
||||
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_Vertex;
|
||||
tex_coord = gl_MultiTexCoord0.xy;
|
||||
}
|
10
resources/shaders/flat_texture.fs
Normal file
10
resources/shaders/flat_texture.fs
Normal file
@ -0,0 +1,10 @@
|
||||
#version 110
|
||||
|
||||
uniform sampler2D uniform_texture;
|
||||
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uniform_texture, tex_coord);
|
||||
}
|
9
resources/shaders/flat_texture.vs
Normal file
9
resources/shaders/flat_texture.vs
Normal file
@ -0,0 +1,9 @@
|
||||
#version 110
|
||||
|
||||
varying vec2 tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ftransform();
|
||||
tex_coord = gl_MultiTexCoord0.xy;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#version 110
|
||||
|
||||
const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
|
||||
const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
|
||||
const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
|
||||
|
||||
uniform sampler2D texture;
|
||||
|
@ -1,14 +1,9 @@
|
||||
#version 110
|
||||
|
||||
attribute vec3 v_position;
|
||||
attribute vec2 v_tex_coords;
|
||||
|
||||
varying vec2 tex_coords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position.x, v_position.y, v_position.z, 1.0);
|
||||
// the following line leads to crash on some Intel graphics card
|
||||
//gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position, 1.0);
|
||||
tex_coords = v_tex_coords;
|
||||
gl_Position = ftransform();
|
||||
tex_coords = gl_MultiTexCoord0.xy;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ add_subdirectory(Shiny)
|
||||
add_subdirectory(semver)
|
||||
add_subdirectory(libigl)
|
||||
add_subdirectory(hints)
|
||||
add_subdirectory(qoi)
|
||||
|
||||
# Adding libnest2d project for bin packing...
|
||||
add_subdirectory(libnest2d)
|
||||
|
@ -498,8 +498,6 @@ int CLI::run(int argc, char **argv)
|
||||
std::string outfile = m_config.opt_string("output");
|
||||
Print fff_print;
|
||||
SLAPrint sla_print;
|
||||
SL1Archive sla_archive(sla_print.printer_config());
|
||||
sla_print.set_printer(&sla_archive);
|
||||
sla_print.set_status_callback(
|
||||
[](const PrintBase::SlicingStatus& s)
|
||||
{
|
||||
@ -539,7 +537,7 @@ int CLI::run(int argc, char **argv)
|
||||
outfile = sla_print.output_filepath(outfile);
|
||||
// We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata
|
||||
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
||||
sla_archive.export_print(outfile_final, sla_print);
|
||||
sla_print.export_print(outfile_final);
|
||||
}
|
||||
if (outfile != outfile_final) {
|
||||
if (Slic3r::rename_file(outfile, outfile_final)) {
|
||||
@ -823,6 +821,36 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co
|
||||
return proposed_path.string();
|
||||
}
|
||||
|
||||
// __has_feature() is used later for Clang, this is for compatibility with other compilers (such as GCC and MSVC)
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
extern "C" {
|
||||
// Based on https://github.com/google/skia/blob/main/tools/LsanSuppressions.cpp
|
||||
const char *__lsan_default_suppressions() {
|
||||
return "leak:libfontconfig\n" // FontConfig looks like it leaks, but it doesn't.
|
||||
"leak:libfreetype\n" // Unsure, appeared upgrading Debian 9->10.
|
||||
"leak:libGLX_nvidia.so\n" // For NVidia driver.
|
||||
"leak:libnvidia-glcore.so\n" // For NVidia driver.
|
||||
"leak:libnvidia-tls.so\n" // For NVidia driver.
|
||||
"leak:terminator_CreateDevice\n" // For Intel Vulkan drivers.
|
||||
"leak:swrast_dri.so\n" // For Mesa 3D software driver.
|
||||
;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SLIC3R_UBSAN)
|
||||
extern "C" {
|
||||
// Enable printing stacktrace by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
|
||||
const char *__ubsan_default_options() {
|
||||
return "print_stacktrace=1";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
extern "C" {
|
||||
__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv)
|
||||
|
@ -150,6 +150,11 @@ void AppConfig::set_defaults()
|
||||
if (get("order_volumes").empty())
|
||||
set("order_volumes", "1");
|
||||
|
||||
#if ENABLE_SHOW_NON_MANIFOLD_EDGES
|
||||
if (get("non_manifold_edges").empty())
|
||||
set("non_manifold_edges", "1");
|
||||
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
|
||||
|
||||
if (get("clear_undo_redo_stack_on_new_project").empty())
|
||||
set("clear_undo_redo_stack_on_new_project", "1");
|
||||
}
|
||||
|
@ -96,8 +96,12 @@ set(SLIC3R_SOURCES
|
||||
Format/STL.hpp
|
||||
Format/SL1.hpp
|
||||
Format/SL1.cpp
|
||||
Format/SL1_SVG.hpp
|
||||
Format/SL1_SVG.cpp
|
||||
GCode/ThumbnailData.cpp
|
||||
GCode/ThumbnailData.hpp
|
||||
GCode/Thumbnails.cpp
|
||||
GCode/Thumbnails.hpp
|
||||
GCode/CoolingBuffer.cpp
|
||||
GCode/CoolingBuffer.hpp
|
||||
GCode/FindReplace.cpp
|
||||
@ -344,6 +348,9 @@ encoding_check(libslic3r)
|
||||
target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0)
|
||||
target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(libslic3r PUBLIC ${EXPAT_INCLUDE_DIRS})
|
||||
|
||||
find_package(JPEG REQUIRED)
|
||||
|
||||
target_link_libraries(libslic3r
|
||||
libnest2d
|
||||
admesh
|
||||
@ -362,6 +369,8 @@ target_link_libraries(libslic3r
|
||||
${CMAKE_DL_LIBS}
|
||||
PNG::PNG
|
||||
ZLIB::ZLIB
|
||||
JPEG::JPEG
|
||||
qoi
|
||||
)
|
||||
|
||||
if (TARGET OpenVDB::openvdb)
|
||||
|
@ -48,12 +48,14 @@ public:
|
||||
static const ColorRGB BLACK() { return { 0.0f, 0.0f, 0.0f }; }
|
||||
static const ColorRGB BLUE() { return { 0.0f, 0.0f, 1.0f }; }
|
||||
static const ColorRGB BLUEISH() { return { 0.5f, 0.5f, 1.0f }; }
|
||||
static const ColorRGB CYAN() { return { 0.0f, 1.0f, 1.0f }; }
|
||||
static const ColorRGB DARK_GRAY() { return { 0.25f, 0.25f, 0.25f }; }
|
||||
static const ColorRGB DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f }; }
|
||||
static const ColorRGB GRAY() { return { 0.5f, 0.5f, 0.5f }; }
|
||||
static const ColorRGB GREEN() { return { 0.0f, 1.0f, 0.0f }; }
|
||||
static const ColorRGB GREENISH() { return { 0.5f, 1.0f, 0.5f }; }
|
||||
static const ColorRGB LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f }; }
|
||||
static const ColorRGB MAGENTA() { return { 1.0f, 0.0f, 1.0f }; }
|
||||
static const ColorRGB ORANGE() { return { 0.92f, 0.50f, 0.26f }; }
|
||||
static const ColorRGB RED() { return { 1.0f, 0.0f, 0.0f }; }
|
||||
static const ColorRGB REDISH() { return { 1.0f, 0.5f, 0.5f }; }
|
||||
@ -112,12 +114,14 @@ public:
|
||||
static const ColorRGBA BLACK() { return { 0.0f, 0.0f, 0.0f, 1.0f }; }
|
||||
static const ColorRGBA BLUE() { return { 0.0f, 0.0f, 1.0f, 1.0f }; }
|
||||
static const ColorRGBA BLUEISH() { return { 0.5f, 0.5f, 1.0f, 1.0f }; }
|
||||
static const ColorRGBA CYAN() { return { 0.0f, 1.0f, 1.0f, 1.0f }; }
|
||||
static const ColorRGBA DARK_GRAY() { return { 0.25f, 0.25f, 0.25f, 1.0f }; }
|
||||
static const ColorRGBA DARK_YELLOW() { return { 0.5f, 0.5f, 0.0f, 1.0f }; }
|
||||
static const ColorRGBA GRAY() { return { 0.5f, 0.5f, 0.5f, 1.0f }; }
|
||||
static const ColorRGBA GREEN() { return { 0.0f, 1.0f, 0.0f, 1.0f }; }
|
||||
static const ColorRGBA GREENISH() { return { 0.5f, 1.0f, 0.5f, 1.0f }; }
|
||||
static const ColorRGBA LIGHT_GRAY() { return { 0.75f, 0.75f, 0.75f, 1.0f }; }
|
||||
static const ColorRGBA MAGENTA() { return { 1.0f, 0.0f, 1.0f, 1.0f }; }
|
||||
static const ColorRGBA ORANGE() { return { 0.923f, 0.504f, 0.264f, 1.0f }; }
|
||||
static const ColorRGBA RED() { return { 1.0f, 0.0f, 0.0f, 1.0f }; }
|
||||
static const ColorRGBA REDISH() { return { 1.0f, 0.5f, 0.5f, 1.0f }; }
|
||||
|
@ -73,7 +73,7 @@ std::string escape_strings_cstyle(const std::vector<std::string> &strs)
|
||||
bool should_quote = strs.size() == 1 && str.empty();
|
||||
for (size_t i = 0; i < str.size(); ++ i) {
|
||||
char c = str[i];
|
||||
if (c == ' ' || c == '\t' || c == '\\' || c == '"' || c == '\r' || c == '\n') {
|
||||
if (c == ' ' || c == ';' || c == '\t' || c == '\\' || c == '"' || c == '\r' || c == '\n') {
|
||||
should_quote = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "Extruder.hpp"
|
||||
#include "GCodeWriter.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
@ -7,24 +8,24 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config) :
|
||||
m_id(id),
|
||||
m_config(config)
|
||||
{
|
||||
reset();
|
||||
|
||||
// cache values that are going to be called often
|
||||
m_e_per_mm3 = this->extrusion_multiplier();
|
||||
if (! m_config->use_volumetric_e)
|
||||
m_e_per_mm3 /= this->filament_crossection();
|
||||
}
|
||||
|
||||
double Extruder::extrude(double dE)
|
||||
std::pair<double, double> Extruder::extrude(double dE)
|
||||
{
|
||||
// in case of relative E distances we always reset to 0 before any output
|
||||
if (m_config->use_relative_e_distances)
|
||||
m_E = 0.;
|
||||
// Quantize extruder delta to G-code resolution.
|
||||
dE = GCodeFormatter::quantize_e(dE);
|
||||
m_E += dE;
|
||||
m_absolute_E += dE;
|
||||
if (dE < 0.)
|
||||
m_retracted -= dE;
|
||||
return dE;
|
||||
return std::make_pair(dE, m_E);
|
||||
}
|
||||
|
||||
/* This method makes sure the extruder is retracted by the specified amount
|
||||
@ -34,28 +35,33 @@ double Extruder::extrude(double dE)
|
||||
The restart_extra argument sets the extra length to be used for
|
||||
unretraction. If we're actually performing a retraction, any restart_extra
|
||||
value supplied will overwrite the previous one if any. */
|
||||
double Extruder::retract(double length, double restart_extra)
|
||||
std::pair<double, double> Extruder::retract(double retract_length, double restart_extra)
|
||||
{
|
||||
// in case of relative E distances we always reset to 0 before any output
|
||||
if (m_config->use_relative_e_distances)
|
||||
m_E = 0.;
|
||||
double to_retract = std::max(0., length - m_retracted);
|
||||
// Quantize extruder delta to G-code resolution.
|
||||
double to_retract = this->retract_to_go(retract_length);
|
||||
if (to_retract > 0.) {
|
||||
m_E -= to_retract;
|
||||
m_absolute_E -= to_retract;
|
||||
m_retracted += to_retract;
|
||||
m_restart_extra = restart_extra;
|
||||
m_restart_extra = restart_extra;
|
||||
}
|
||||
return to_retract;
|
||||
return std::make_pair(to_retract, m_E);
|
||||
}
|
||||
|
||||
double Extruder::unretract()
|
||||
double Extruder::retract_to_go(double retract_length) const
|
||||
{
|
||||
double dE = m_retracted + m_restart_extra;
|
||||
this->extrude(dE);
|
||||
return std::max(0., GCodeFormatter::quantize_e(retract_length - m_retracted));
|
||||
}
|
||||
|
||||
std::pair<double, double> Extruder::unretract()
|
||||
{
|
||||
auto [dE, emitE] = this->extrude(m_retracted + m_restart_extra);
|
||||
m_retracted = 0.;
|
||||
m_restart_extra = 0.;
|
||||
return dE;
|
||||
return std::make_pair(dE, emitE);
|
||||
}
|
||||
|
||||
// Used filament volume in mm^3.
|
||||
|
@ -12,22 +12,24 @@ class Extruder
|
||||
{
|
||||
public:
|
||||
Extruder(unsigned int id, GCodeConfig *config);
|
||||
virtual ~Extruder() {}
|
||||
|
||||
void reset() {
|
||||
m_E = 0;
|
||||
m_absolute_E = 0;
|
||||
m_retracted = 0;
|
||||
m_restart_extra = 0;
|
||||
}
|
||||
~Extruder() = default;
|
||||
|
||||
unsigned int id() const { return m_id; }
|
||||
|
||||
double extrude(double dE);
|
||||
double retract(double length, double restart_extra);
|
||||
double unretract();
|
||||
double E() const { return m_E; }
|
||||
void reset_E() { m_E = 0.; }
|
||||
// Following three methods emit:
|
||||
// first - extrusion delta
|
||||
// second - number to emit to G-code: This may be delta for relative mode or a distance from last reset_E() for absolute mode.
|
||||
// They also quantize the E axis to G-code resolution.
|
||||
std::pair<double, double> extrude(double dE);
|
||||
std::pair<double, double> retract(double retract_length, double restart_extra);
|
||||
std::pair<double, double> unretract();
|
||||
// How much to retract yet before retract_length is reached?
|
||||
// The value is quantized to G-code resolution.
|
||||
double retract_to_go(double retract_length) const;
|
||||
|
||||
// Reset the current state of the E axis (this is only needed for relative extruder addressing mode anyways).
|
||||
// Returns true if the extruder was non-zero before reset.
|
||||
bool reset_E() { bool modified = m_E != 0; m_E = 0.; return modified; }
|
||||
double e_per_mm(double mm3_per_mm) const { return mm3_per_mm * m_e_per_mm3; }
|
||||
double e_per_mm3() const { return m_e_per_mm3; }
|
||||
// Used filament volume in mm^3.
|
||||
@ -57,14 +59,16 @@ private:
|
||||
GCodeConfig *m_config;
|
||||
// Print-wide global ID of this extruder.
|
||||
unsigned int m_id;
|
||||
// Current state of the extruder axis, may be resetted if use_relative_e_distances.
|
||||
double m_E;
|
||||
// Current state of the extruder axis.
|
||||
// For absolute extruder addressing, it is the current state since the last reset (G92 E0) issued at the end of the last retraction.
|
||||
// For relative extruder addressing, it is the E axis difference emitted into the G-code the last time.
|
||||
double m_E { 0 };
|
||||
// Current state of the extruder tachometer, used to output the extruded_volume() and used_filament() statistics.
|
||||
double m_absolute_E;
|
||||
double m_absolute_E { 0 };
|
||||
// Current positive amount of retraction.
|
||||
double m_retracted;
|
||||
double m_retracted { 0 };
|
||||
// When retracted, this value stores the extra amount of priming on deretraction.
|
||||
double m_restart_extra;
|
||||
double m_restart_extra { 0 };
|
||||
double m_e_per_mm3;
|
||||
};
|
||||
|
||||
@ -76,4 +80,4 @@ inline bool operator> (const Extruder &e1, const Extruder &e2) { return e1.id()
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // slic3r_Extruder_hpp_
|
||||
|
@ -56,12 +56,9 @@ ExtrusionEntityCollection::operator ExtrusionPaths() const
|
||||
return paths;
|
||||
}
|
||||
|
||||
ExtrusionEntity* ExtrusionEntityCollection::clone() const
|
||||
ExtrusionEntity *ExtrusionEntityCollection::clone() const
|
||||
{
|
||||
ExtrusionEntityCollection* coll = new ExtrusionEntityCollection(*this);
|
||||
for (size_t i = 0; i < coll->entities.size(); ++i)
|
||||
coll->entities[i] = this->entities[i]->clone();
|
||||
return coll;
|
||||
return new ExtrusionEntityCollection(*this);
|
||||
}
|
||||
|
||||
void ExtrusionEntityCollection::reverse()
|
||||
|
@ -2391,7 +2391,7 @@ static std::vector<MonotonicRegionLink> chain_monotonic_regions(
|
||||
|
||||
// Probability (unnormalized) of traversing a link between two monotonic regions.
|
||||
auto path_probability = [
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(__clang__)
|
||||
// clang complains when capturing constexpr constants.
|
||||
pheromone_alpha, pheromone_beta
|
||||
#endif // __APPLE__
|
||||
|
@ -121,18 +121,21 @@ static constexpr const char* LAST_TRIANGLE_ID_ATTR = "lastid";
|
||||
static constexpr const char* OBJECT_TYPE = "object";
|
||||
static constexpr const char* VOLUME_TYPE = "volume";
|
||||
|
||||
static constexpr const char* NAME_KEY = "name";
|
||||
static constexpr const char* MODIFIER_KEY = "modifier";
|
||||
static constexpr const char* NAME_KEY = "name";
|
||||
static constexpr const char* MODIFIER_KEY = "modifier";
|
||||
static constexpr const char* VOLUME_TYPE_KEY = "volume_type";
|
||||
static constexpr const char* MATRIX_KEY = "matrix";
|
||||
static constexpr const char* SOURCE_FILE_KEY = "source_file";
|
||||
static constexpr const char* SOURCE_OBJECT_ID_KEY = "source_object_id";
|
||||
static constexpr const char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
|
||||
static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
|
||||
static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
|
||||
static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
||||
static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
|
||||
static constexpr const char* SOURCE_IN_METERS = "source_in_meters";
|
||||
static constexpr const char* MATRIX_KEY = "matrix";
|
||||
static constexpr const char* SOURCE_FILE_KEY = "source_file";
|
||||
static constexpr const char* SOURCE_OBJECT_ID_KEY = "source_object_id";
|
||||
static constexpr const char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
|
||||
static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
|
||||
static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
|
||||
static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
|
||||
static constexpr const char* SOURCE_IN_INCHES_KEY = "source_in_inches";
|
||||
static constexpr const char* SOURCE_IN_METERS_KEY = "source_in_meters";
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
static constexpr const char* SOURCE_IS_BUILTIN_VOLUME_KEY = "source_is_builtin_volume";
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
|
||||
static constexpr const char* MESH_STAT_EDGES_FIXED = "edges_fixed";
|
||||
static constexpr const char* MESH_STAT_DEGENERATED_FACETS = "degenerate_facets";
|
||||
@ -816,6 +819,20 @@ namespace Slic3r {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
for (int obj_id = 0; obj_id < int(model.objects.size()); ++obj_id) {
|
||||
ModelObject* o = model.objects[obj_id];
|
||||
for (int vol_id = 0; vol_id < int(o->volumes.size()); ++vol_id) {
|
||||
ModelVolume* v = o->volumes[vol_id];
|
||||
if (v->source.input_file.empty())
|
||||
v->source.input_file = v->name.empty() ? filename : v->name;
|
||||
if (v->source.volume_idx == -1)
|
||||
v->source.volume_idx = vol_id;
|
||||
if (v->source.object_idx == -1)
|
||||
v->source.object_idx = obj_id;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int object_idx = 0;
|
||||
for (ModelObject* o : model.objects) {
|
||||
int volume_idx = 0;
|
||||
@ -831,6 +848,7 @@ namespace Slic3r {
|
||||
}
|
||||
++object_idx;
|
||||
}
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
|
||||
// // fixes the min z of the model if negative
|
||||
// model.adjust_min_z();
|
||||
@ -2052,15 +2070,19 @@ namespace Slic3r {
|
||||
else if (metadata.key == SOURCE_VOLUME_ID_KEY)
|
||||
volume->source.volume_idx = ::atoi(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_OFFSET_X_KEY)
|
||||
volume->source.mesh_offset(0) = ::atof(metadata.value.c_str());
|
||||
volume->source.mesh_offset.x() = ::atof(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_OFFSET_Y_KEY)
|
||||
volume->source.mesh_offset(1) = ::atof(metadata.value.c_str());
|
||||
volume->source.mesh_offset.y() = ::atof(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_OFFSET_Z_KEY)
|
||||
volume->source.mesh_offset(2) = ::atof(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_IN_INCHES)
|
||||
volume->source.mesh_offset.z() = ::atof(metadata.value.c_str());
|
||||
else if (metadata.key == SOURCE_IN_INCHES_KEY)
|
||||
volume->source.is_converted_from_inches = metadata.value == "1";
|
||||
else if (metadata.key == SOURCE_IN_METERS)
|
||||
else if (metadata.key == SOURCE_IN_METERS_KEY)
|
||||
volume->source.is_converted_from_meters = metadata.value == "1";
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
else if (metadata.key == SOURCE_IS_BUILTIN_VOLUME_KEY)
|
||||
volume->source.is_from_builtin_objects = metadata.value == "1";
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
else
|
||||
volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
|
||||
}
|
||||
@ -2981,7 +3003,7 @@ namespace Slic3r {
|
||||
|
||||
// stores volume's local matrix
|
||||
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\"";
|
||||
Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix();
|
||||
const Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix();
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
stream << matrix(r, c);
|
||||
@ -3005,9 +3027,13 @@ namespace Slic3r {
|
||||
}
|
||||
assert(! volume->source.is_converted_from_inches || ! volume->source.is_converted_from_meters);
|
||||
if (volume->source.is_converted_from_inches)
|
||||
stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
stream << prefix << SOURCE_IN_INCHES_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
else if (volume->source.is_converted_from_meters)
|
||||
stream << prefix << SOURCE_IN_METERS << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
stream << prefix << SOURCE_IN_METERS_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
if (volume->source.is_from_builtin_objects)
|
||||
stream << prefix << SOURCE_IS_BUILTIN_VOLUME_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
}
|
||||
|
||||
// stores volume's config data
|
||||
@ -3110,6 +3136,36 @@ static void handle_legacy_project_loaded(unsigned int version_project_file, Dyna
|
||||
}
|
||||
}
|
||||
|
||||
bool is_project_3mf(const std::string& filename)
|
||||
{
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
if (!open_zip_reader(&archive, filename))
|
||||
return false;
|
||||
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
|
||||
|
||||
// loop the entries to search for config
|
||||
mz_zip_archive_file_stat stat;
|
||||
bool config_found = false;
|
||||
for (mz_uint i = 0; i < num_entries; ++i) {
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
|
||||
std::string name(stat.m_filename);
|
||||
std::replace(name.begin(), name.end(), '\\', '/');
|
||||
|
||||
if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) {
|
||||
config_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close_zip_reader(&archive);
|
||||
|
||||
return config_found;
|
||||
}
|
||||
|
||||
bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version)
|
||||
{
|
||||
if (path == nullptr || model == nullptr)
|
||||
|
@ -29,6 +29,9 @@ namespace Slic3r {
|
||||
class DynamicPrintConfig;
|
||||
struct ThumbnailData;
|
||||
|
||||
// Returns true if the 3mf file with the given filename is a PrusaSlicer project file (i.e. if it contains a config).
|
||||
extern bool is_project_3mf(const std::string& filename);
|
||||
|
||||
// Load the content of a 3mf file into the given model and preset bundle.
|
||||
extern bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version);
|
||||
|
||||
|
@ -283,25 +283,28 @@ void AMFParserContext::startElement(const char *name, const char **atts)
|
||||
m_value[0] = type;
|
||||
node_type_new = NODE_TYPE_METADATA;
|
||||
}
|
||||
} else if (strcmp(name, "material") == 0) {
|
||||
}
|
||||
else if (strcmp(name, "material") == 0) {
|
||||
const char *material_id = get_attribute(atts, "id");
|
||||
m_material = m_model.add_material((material_id == nullptr) ? "_" : material_id);
|
||||
node_type_new = NODE_TYPE_MATERIAL;
|
||||
} else if (strcmp(name, "object") == 0) {
|
||||
}
|
||||
else if (strcmp(name, "object") == 0) {
|
||||
const char *object_id = get_attribute(atts, "id");
|
||||
if (object_id == nullptr)
|
||||
this->stop();
|
||||
else {
|
||||
assert(m_object_vertices.empty());
|
||||
m_object = m_model.add_object();
|
||||
m_object->name = std::string(object_id);
|
||||
m_object_instances_map[object_id].idx = int(m_model.objects.size())-1;
|
||||
node_type_new = NODE_TYPE_OBJECT;
|
||||
}
|
||||
} else if (strcmp(name, "constellation") == 0) {
|
||||
node_type_new = NODE_TYPE_CONSTELLATION;
|
||||
} else if (strcmp(name, "custom_gcodes_per_height") == 0) {
|
||||
node_type_new = NODE_TYPE_CUSTOM_GCODE;
|
||||
}
|
||||
else if (strcmp(name, "constellation") == 0)
|
||||
node_type_new = NODE_TYPE_CONSTELLATION;
|
||||
else if (strcmp(name, "custom_gcodes_per_height") == 0)
|
||||
node_type_new = NODE_TYPE_CUSTOM_GCODE;
|
||||
break;
|
||||
case 2:
|
||||
if (strcmp(name, "metadata") == 0) {
|
||||
@ -309,12 +312,14 @@ void AMFParserContext::startElement(const char *name, const char **atts)
|
||||
m_value[0] = get_attribute(atts, "type");
|
||||
node_type_new = NODE_TYPE_METADATA;
|
||||
}
|
||||
} else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
|
||||
}
|
||||
else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
|
||||
node_type_new = NODE_TYPE_LAYER_CONFIG;
|
||||
else if (strcmp(name, "mesh") == 0) {
|
||||
if (m_path[1] == NODE_TYPE_OBJECT)
|
||||
node_type_new = NODE_TYPE_MESH;
|
||||
} else if (strcmp(name, "instance") == 0) {
|
||||
}
|
||||
else if (strcmp(name, "instance") == 0) {
|
||||
if (m_path[1] == NODE_TYPE_CONSTELLATION) {
|
||||
const char *object_id = get_attribute(atts, "objectid");
|
||||
if (object_id == nullptr)
|
||||
@ -652,11 +657,16 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
if (bool has_transform = !m_volume_transform.isApprox(Transform3d::Identity(), 1e-10); has_transform)
|
||||
m_volume->source.transform = Slic3r::Geometry::Transformation(m_volume_transform);
|
||||
|
||||
if (m_volume->source.input_file.empty() && (m_volume->type() == ModelVolumeType::MODEL_PART)) {
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
if (m_volume->source.input_file.empty()) {
|
||||
#else
|
||||
if (m_volume->source.input_file.empty() && m_volume->type() == ModelVolumeType::MODEL_PART) {
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
m_volume->source.object_idx = (int)m_model.objects.size() - 1;
|
||||
m_volume->source.volume_idx = (int)m_model.objects.back()->volumes.size() - 1;
|
||||
m_volume->center_geometry_after_creation();
|
||||
} else
|
||||
}
|
||||
else
|
||||
// pass false if the mesh offset has been already taken from the data
|
||||
m_volume->center_geometry_after_creation(m_volume->source.input_file.empty());
|
||||
|
||||
@ -787,46 +797,44 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
// Is this volume a modifier volume?
|
||||
// "modifier" flag comes first in the XML file, so it may be later overwritten by the "type" flag.
|
||||
m_volume->set_type((atoi(m_value[1].c_str()) == 1) ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART);
|
||||
} else if (strcmp(opt_key, "volume_type") == 0) {
|
||||
}
|
||||
else if (strcmp(opt_key, "volume_type") == 0)
|
||||
m_volume->set_type(ModelVolume::type_from_string(m_value[1]));
|
||||
}
|
||||
else if (strcmp(opt_key, "matrix") == 0) {
|
||||
else if (strcmp(opt_key, "matrix") == 0)
|
||||
m_volume_transform = Slic3r::Geometry::transform3d_from_string(m_value[1]);
|
||||
}
|
||||
else if (strcmp(opt_key, "source_file") == 0) {
|
||||
else if (strcmp(opt_key, "source_file") == 0)
|
||||
m_volume->source.input_file = m_value[1];
|
||||
}
|
||||
else if (strcmp(opt_key, "source_object_id") == 0) {
|
||||
else if (strcmp(opt_key, "source_object_id") == 0)
|
||||
m_volume->source.object_idx = ::atoi(m_value[1].c_str());
|
||||
}
|
||||
else if (strcmp(opt_key, "source_volume_id") == 0) {
|
||||
else if (strcmp(opt_key, "source_volume_id") == 0)
|
||||
m_volume->source.volume_idx = ::atoi(m_value[1].c_str());
|
||||
}
|
||||
else if (strcmp(opt_key, "source_offset_x") == 0) {
|
||||
m_volume->source.mesh_offset(0) = ::atof(m_value[1].c_str());
|
||||
}
|
||||
else if (strcmp(opt_key, "source_offset_y") == 0) {
|
||||
m_volume->source.mesh_offset(1) = ::atof(m_value[1].c_str());
|
||||
}
|
||||
else if (strcmp(opt_key, "source_offset_z") == 0) {
|
||||
m_volume->source.mesh_offset(2) = ::atof(m_value[1].c_str());
|
||||
}
|
||||
else if (strcmp(opt_key, "source_in_inches") == 0) {
|
||||
else if (strcmp(opt_key, "source_offset_x") == 0)
|
||||
m_volume->source.mesh_offset.x() = ::atof(m_value[1].c_str());
|
||||
else if (strcmp(opt_key, "source_offset_y") == 0)
|
||||
m_volume->source.mesh_offset.y() = ::atof(m_value[1].c_str());
|
||||
else if (strcmp(opt_key, "source_offset_z") == 0)
|
||||
m_volume->source.mesh_offset.z() = ::atof(m_value[1].c_str());
|
||||
else if (strcmp(opt_key, "source_in_inches") == 0)
|
||||
m_volume->source.is_converted_from_inches = m_value[1] == "1";
|
||||
}
|
||||
else if (strcmp(opt_key, "source_in_meters") == 0) {
|
||||
else if (strcmp(opt_key, "source_in_meters") == 0)
|
||||
m_volume->source.is_converted_from_meters = m_value[1] == "1";
|
||||
}
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
else if (strcmp(opt_key, "source_is_builtin_volume") == 0)
|
||||
m_volume->source.is_from_builtin_objects = m_value[1] == "1";
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
}
|
||||
} else if (m_path.size() == 3) {
|
||||
}
|
||||
else if (m_path.size() == 3) {
|
||||
if (m_path[1] == NODE_TYPE_MATERIAL) {
|
||||
if (m_material)
|
||||
m_material->attributes[m_value[0]] = m_value[1];
|
||||
} else if (m_path[1] == NODE_TYPE_OBJECT) {
|
||||
}
|
||||
else if (m_path[1] == NODE_TYPE_OBJECT) {
|
||||
if (m_object && m_value[0] == "name")
|
||||
m_object->name = std::move(m_value[1]);
|
||||
}
|
||||
} else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME) {
|
||||
}
|
||||
else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME) {
|
||||
if (m_volume && m_value[0] == "name")
|
||||
m_volume->name = std::move(m_value[1]);
|
||||
}
|
||||
@ -910,12 +918,21 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, ConfigSubstitut
|
||||
if (result)
|
||||
ctx.endDocument();
|
||||
|
||||
for (ModelObject* o : model->objects)
|
||||
{
|
||||
for (ModelVolume* v : o->volumes)
|
||||
{
|
||||
if (v->source.input_file.empty() && (v->type() == ModelVolumeType::MODEL_PART))
|
||||
for (ModelObject* o : model->objects) {
|
||||
unsigned int counter = 0;
|
||||
for (ModelVolume* v : o->volumes) {
|
||||
++counter;
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
if (v->source.input_file.empty())
|
||||
#else
|
||||
if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART)
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
v->source.input_file = path;
|
||||
if (v->name.empty()) {
|
||||
v->name = o->name;
|
||||
if (o->volumes.size() > 1)
|
||||
v->name += "_" + std::to_string(counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1058,7 +1075,11 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, ConfigSubsti
|
||||
|
||||
for (ModelObject *o : model->objects)
|
||||
for (ModelVolume *v : o->volumes)
|
||||
if (v->source.input_file.empty() && (v->type() == ModelVolumeType::MODEL_PART))
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
if (v->source.input_file.empty())
|
||||
#else
|
||||
if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART)
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
v->source.input_file = path;
|
||||
|
||||
return true;
|
||||
@ -1227,18 +1248,15 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
|
||||
stream << " <metadata type=\"slic3r.matrix\">";
|
||||
const Transform3d& matrix = volume->get_matrix() * volume->source.transform.get_matrix();
|
||||
stream << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
for (int r = 0; r < 4; ++r)
|
||||
{
|
||||
for (int c = 0; c < 4; ++c)
|
||||
{
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
stream << matrix(r, c);
|
||||
if ((r != 3) || (c != 3))
|
||||
if (r != 3 || c != 3)
|
||||
stream << " ";
|
||||
}
|
||||
}
|
||||
stream << "</metadata>\n";
|
||||
if (!volume->source.input_file.empty())
|
||||
{
|
||||
if (!volume->source.input_file.empty()) {
|
||||
std::string input_file = xml_escape(fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string());
|
||||
stream << " <metadata type=\"slic3r.source_file\">" << input_file << "</metadata>\n";
|
||||
stream << " <metadata type=\"slic3r.source_object_id\">" << volume->source.object_idx << "</metadata>\n";
|
||||
@ -1252,12 +1270,16 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
|
||||
stream << " <metadata type=\"slic3r.source_in_inches\">1</metadata>\n";
|
||||
else if (volume->source.is_converted_from_meters)
|
||||
stream << " <metadata type=\"slic3r.source_in_meters\">1</metadata>\n";
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
#if ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
if (volume->source.is_from_builtin_objects)
|
||||
stream << " <metadata type=\"slic3r.source_is_builtin_volume\">1</metadata>\n";
|
||||
#endif // ENABLE_RELOAD_FROM_DISK_REWORK
|
||||
stream << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
const indexed_triangle_set &its = volume->mesh().its;
|
||||
for (size_t i = 0; i < its.indices.size(); ++i) {
|
||||
stream << " <triangle>\n";
|
||||
for (int j = 0; j < 3; ++j)
|
||||
stream << " <v" << j + 1 << ">" << its.indices[i][j] + vertices_offset << "</v" << j + 1 << ">\n";
|
||||
stream << " <v" << j + 1 << ">" << its.indices[i][j] + vertices_offset << "</v" << j + 1 << ">\n";
|
||||
stream << " </triangle>\n";
|
||||
}
|
||||
stream << " </volume>\n";
|
||||
|
@ -446,8 +446,8 @@ void fill_slicerconf(ConfMap &m, const SLAPrint &print)
|
||||
|
||||
std::unique_ptr<sla::RasterBase> SL1Archive::create_raster() const
|
||||
{
|
||||
sla::RasterBase::Resolution res;
|
||||
sla::RasterBase::PixelDim pxdim;
|
||||
sla::Resolution res;
|
||||
sla::PixelDim pxdim;
|
||||
std::array<bool, 2> mirror;
|
||||
|
||||
double w = m_cfg.display_width.getFloat();
|
||||
@ -468,8 +468,8 @@ std::unique_ptr<sla::RasterBase> SL1Archive::create_raster() const
|
||||
std::swap(pw, ph);
|
||||
}
|
||||
|
||||
res = sla::RasterBase::Resolution{pw, ph};
|
||||
pxdim = sla::RasterBase::PixelDim{w / pw, h / ph};
|
||||
res = sla::Resolution{pw, ph};
|
||||
pxdim = sla::PixelDim{w / pw, h / ph};
|
||||
sla::RasterBase::Trafo tr{orientation, mirror};
|
||||
|
||||
double gamma = m_cfg.gamma_correction.getFloat();
|
||||
|
@ -15,27 +15,16 @@ protected:
|
||||
std::unique_ptr<sla::RasterBase> create_raster() const override;
|
||||
sla::RasterEncoder get_encoder() const override;
|
||||
|
||||
SLAPrinterConfig & cfg() { return m_cfg; }
|
||||
const SLAPrinterConfig & cfg() const { return m_cfg; }
|
||||
|
||||
public:
|
||||
|
||||
SL1Archive() = default;
|
||||
explicit SL1Archive(const SLAPrinterConfig &cfg): m_cfg(cfg) {}
|
||||
explicit SL1Archive(SLAPrinterConfig &&cfg): m_cfg(std::move(cfg)) {}
|
||||
|
||||
void export_print(Zipper &zipper, const SLAPrint &print, const std::string &projectname = "");
|
||||
void export_print(const std::string &fname, const SLAPrint &print, const std::string &projectname = "")
|
||||
{
|
||||
Zipper zipper(fname);
|
||||
export_print(zipper, print, projectname);
|
||||
}
|
||||
|
||||
void apply(const SLAPrinterConfig &cfg) override
|
||||
{
|
||||
auto diff = m_cfg.diff(cfg);
|
||||
if (!diff.empty()) {
|
||||
m_cfg.apply_only(cfg, diff);
|
||||
m_layers = {};
|
||||
}
|
||||
}
|
||||
void export_print(Zipper &zipper, const SLAPrint &print, const std::string &projectname = "") override;
|
||||
};
|
||||
|
||||
ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrintConfig &out);
|
||||
|
221
src/libslic3r/Format/SL1_SVG.cpp
Normal file
221
src/libslic3r/Format/SL1_SVG.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "SL1_SVG.hpp"
|
||||
#include "SLA/RasterBase.hpp"
|
||||
#include "libslic3r/LocalesUtils.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t constexpr coord_t_bufsize = 40;
|
||||
|
||||
char const* decimal_from(coord_t snumber, char* buffer)
|
||||
{
|
||||
std::make_unsigned_t<coord_t> number = 0;
|
||||
|
||||
char* ret = buffer;
|
||||
|
||||
if( snumber < 0 ) {
|
||||
*buffer++ = '-';
|
||||
number = -snumber;
|
||||
} else
|
||||
number = snumber;
|
||||
|
||||
if( number == 0 ) {
|
||||
*buffer++ = '0';
|
||||
} else {
|
||||
char* p_first = buffer;
|
||||
while( number != 0 ) {
|
||||
*buffer++ = '0' + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
std::reverse( p_first, buffer );
|
||||
}
|
||||
|
||||
*buffer = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string coord2str(coord_t crd)
|
||||
{
|
||||
char buf[coord_t_bufsize];
|
||||
return decimal_from(crd, buf);
|
||||
}
|
||||
|
||||
void transform(ExPolygon &ep, const sla::RasterBase::Trafo &tr, const BoundingBox &bb)
|
||||
{
|
||||
if (tr.flipXY) {
|
||||
for (auto &p : ep.contour.points) std::swap(p.x(), p.y());
|
||||
for (auto &h : ep.holes)
|
||||
for (auto &p : h.points) std::swap(p.x(), p.y());
|
||||
}
|
||||
|
||||
if (tr.mirror_x){
|
||||
for (auto &p : ep.contour.points) p.x() = bb.max.x() - p.x() + bb.min.x();
|
||||
for (auto &h : ep.holes)
|
||||
for (auto &p : h.points) p.x() = bb.max.x() - p.x() + bb.min.x();
|
||||
}
|
||||
|
||||
if (tr.mirror_y){
|
||||
for (auto &p : ep.contour.points) p.y() = bb.max.y() - p.y() + bb.min.y();
|
||||
for (auto &h : ep.holes)
|
||||
for (auto &p : h.points) p.y() = bb.max.y() - p.y() + bb.min.y();
|
||||
}
|
||||
}
|
||||
|
||||
void append_svg(std::string &buf, const Polygon &poly)
|
||||
{
|
||||
if (poly.points.empty())
|
||||
return;
|
||||
|
||||
auto c = poly.points.front();
|
||||
|
||||
char intbuf[coord_t_bufsize];
|
||||
|
||||
buf += std::string("<path d=\"M ") + decimal_from(c.x(), intbuf);
|
||||
buf += std::string(" ") + decimal_from(c.y(), intbuf) + " m";
|
||||
|
||||
for (auto &p : poly) {
|
||||
auto d = p - c;
|
||||
if (d.squaredNorm() == 0) continue;
|
||||
buf += " ";
|
||||
buf += decimal_from(p.x() - c.x(), intbuf);
|
||||
buf += " ";
|
||||
buf += decimal_from(p.y() - c.y(), intbuf);
|
||||
c = p;
|
||||
}
|
||||
buf += " z\""; // mark path as closed
|
||||
buf += " />\n";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// A fake raster from SVG
|
||||
class SVGRaster : public sla::RasterBase {
|
||||
// Resolution here will be used for svg boundaries
|
||||
BoundingBox m_bb;
|
||||
sla::Resolution m_res;
|
||||
Trafo m_trafo;
|
||||
Vec2d m_sc;
|
||||
|
||||
std::string m_svg;
|
||||
|
||||
public:
|
||||
SVGRaster(const BoundingBox &svgarea, sla::Resolution res, Trafo tr = {})
|
||||
: m_bb{svgarea}
|
||||
, m_res{res}
|
||||
, m_trafo{tr}
|
||||
, m_sc{double(m_res.width_px) / m_bb.size().x(), double(m_res.height_px) / m_bb.size().y()}
|
||||
{
|
||||
// Inside the svg header, the boundaries will be defined in mm to
|
||||
// the actual bed size. The viewport is then defined to work with our
|
||||
// scaled coordinates. All the exported polygons will be in these scaled
|
||||
// coordinates but svg rendering software will interpret them correctly
|
||||
// in mm due to the header's definition.
|
||||
std::string wf = float_to_string_decimal_point(unscaled<float>(m_bb.size().x()));
|
||||
std::string hf = float_to_string_decimal_point(unscaled<float>(m_bb.size().y()));
|
||||
std::string w = coord2str(coord_t(m_res.width_px));
|
||||
std::string h = coord2str(coord_t(m_res.height_px));
|
||||
|
||||
// Notice the header also defines the fill-rule as nonzero which should
|
||||
// generate correct results for our ExPolygons.
|
||||
|
||||
// Add svg header.
|
||||
m_svg =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
|
||||
"<svg height=\"" + hf + "mm" + "\" width=\"" + wf + "mm" + "\" viewBox=\"0 0 " + w + " " + h +
|
||||
"\" style=\"fill: white; stroke: none; fill-rule: nonzero\" "
|
||||
"xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||
|
||||
// Add black background;
|
||||
m_svg += "<rect fill='black' stroke='none' x='0' y='0' width='" + w + "' height='" + h + "'/>\n";
|
||||
}
|
||||
|
||||
void draw(const ExPolygon& poly) override
|
||||
{
|
||||
auto cpoly = poly;
|
||||
|
||||
double tol = std::min(m_bb.size().x() / double(m_res.width_px),
|
||||
m_bb.size().y() / double(m_res.height_px));
|
||||
|
||||
ExPolygons cpolys = poly.simplify(tol);
|
||||
|
||||
for (auto &cpoly : cpolys) {
|
||||
transform(cpoly, m_trafo, m_bb);
|
||||
|
||||
for (auto &p : cpoly.contour.points)
|
||||
p = {std::round(p.x() * m_sc.x()), std::round(p.y() * m_sc.y())};
|
||||
|
||||
for (auto &h : cpoly.holes)
|
||||
for (auto &p : h)
|
||||
p = {std::round(p.x() * m_sc.x()), std::round(p.y() * m_sc.y())};
|
||||
|
||||
append_svg(m_svg, cpoly.contour);
|
||||
for (auto &h : cpoly.holes)
|
||||
append_svg(m_svg, h);
|
||||
}
|
||||
}
|
||||
|
||||
Trafo trafo() const override { return m_trafo; }
|
||||
|
||||
sla::EncodedRaster encode(sla::RasterEncoder /*encoder*/) const override
|
||||
{
|
||||
std::vector<uint8_t> data;
|
||||
constexpr const char finish[] = "</svg>\n";
|
||||
|
||||
data.reserve(m_svg.size() + std::size(finish));
|
||||
|
||||
std::copy(m_svg.begin(), m_svg.end(), std::back_inserter(data));
|
||||
std::copy(finish, finish + std::size(finish) - 1, std::back_inserter(data));
|
||||
|
||||
return sla::EncodedRaster{std::move(data), "svg"};
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<sla::RasterBase> SL1_SVGArchive::create_raster() const
|
||||
{
|
||||
auto w = cfg().display_width.getFloat();
|
||||
auto h = cfg().display_height.getFloat();
|
||||
|
||||
// auto res_x = size_t(cfg().display_pixels_x.getInt());
|
||||
// auto res_y = size_t(cfg().display_pixels_y.getInt());
|
||||
float precision_nm = scaled<float>(cfg().sla_output_precision.getFloat());
|
||||
size_t res_x = std::round(scaled(w) / precision_nm);
|
||||
size_t res_y = std::round(scaled(h) / precision_nm);
|
||||
|
||||
std::array<bool, 2> mirror;
|
||||
|
||||
mirror[X] = cfg().display_mirror_x.getBool();
|
||||
mirror[Y] = cfg().display_mirror_y.getBool();
|
||||
|
||||
auto ro = cfg().display_orientation.getInt();
|
||||
sla::RasterBase::Orientation orientation =
|
||||
ro == sla::RasterBase::roPortrait ? sla::RasterBase::roPortrait :
|
||||
sla::RasterBase::roLandscape;
|
||||
|
||||
if (orientation == sla::RasterBase::roPortrait) {
|
||||
std::swap(w, h);
|
||||
std::swap(res_x, res_y);
|
||||
}
|
||||
|
||||
BoundingBox svgarea{{0, 0}, {scaled(w), scaled(h)}};
|
||||
|
||||
sla::RasterBase::Trafo tr{orientation, mirror};
|
||||
|
||||
// Gamma does not really make sense in an svg, right?
|
||||
// double gamma = cfg().gamma_correction.getFloat();
|
||||
return std::make_unique<SVGRaster>(svgarea, sla::Resolution{res_x, res_y}, tr);
|
||||
}
|
||||
|
||||
sla::RasterEncoder SL1_SVGArchive::get_encoder() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
22
src/libslic3r/Format/SL1_SVG.hpp
Normal file
22
src/libslic3r/Format/SL1_SVG.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef SL1_SVG_HPP
|
||||
#define SL1_SVG_HPP
|
||||
|
||||
#include "SL1.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class SL1_SVGArchive: public SL1Archive {
|
||||
protected:
|
||||
|
||||
// Override the factory methods to produce svg instead of a real raster.
|
||||
std::unique_ptr<sla::RasterBase> create_raster() const override;
|
||||
sla::RasterEncoder get_encoder() const override;
|
||||
|
||||
public:
|
||||
|
||||
using SL1Archive::SL1Archive;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // SL1_SVG_HPP
|
@ -6,6 +6,7 @@
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "Geometry/ConvexHull.hpp"
|
||||
#include "GCode/PrintExtents.hpp"
|
||||
#include "GCode/Thumbnails.hpp"
|
||||
#include "GCode/WipeTower.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "Print.hpp"
|
||||
@ -26,7 +27,6 @@
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
@ -54,8 +54,6 @@
|
||||
|
||||
#include <Shiny/Shiny.h>
|
||||
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
using namespace std::literals::string_view_literals;
|
||||
|
||||
#if 0
|
||||
@ -156,63 +154,52 @@ namespace Slic3r {
|
||||
|
||||
std::string Wipe::wipe(GCode& gcodegen, bool toolchange)
|
||||
{
|
||||
std::string gcode;
|
||||
std::string gcode;
|
||||
const Extruder &extruder = *gcodegen.writer().extruder();
|
||||
|
||||
/* Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
Too fast = ripping of existing material; too slow = short wipe path, thus more blob. */
|
||||
double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
|
||||
// get the retraction length
|
||||
double length = toolchange
|
||||
? gcodegen.writer().extruder()->retract_length_toolchange()
|
||||
: gcodegen.writer().extruder()->retract_length();
|
||||
// Shorten the retraction length by the amount already retracted before wipe.
|
||||
length *= (1. - gcodegen.writer().extruder()->retract_before_wipe());
|
||||
|
||||
if (length > 0) {
|
||||
/* Calculate how long we need to travel in order to consume the required
|
||||
amount of retraction. In other words, how far do we move in XY at wipe_speed
|
||||
for the time needed to consume retract_length at retract_speed? */
|
||||
double wipe_dist = scale_(length / gcodegen.writer().extruder()->retract_speed() * wipe_speed);
|
||||
|
||||
/* Take the stored wipe path and replace first point with the current actual position
|
||||
(they might be different, for example, in case of loop clipping). */
|
||||
Polyline wipe_path;
|
||||
wipe_path.append(gcodegen.last_pos());
|
||||
wipe_path.append(
|
||||
this->path.points.begin() + 1,
|
||||
this->path.points.end()
|
||||
);
|
||||
|
||||
wipe_path.clip_end(wipe_path.length() - wipe_dist);
|
||||
|
||||
// subdivide the retraction in segments
|
||||
if (!wipe_path.empty()) {
|
||||
// add tag for processor
|
||||
// Remaining quantized retraction length.
|
||||
if (double retract_length = extruder.retract_to_go(toolchange ? extruder.retract_length_toolchange() : extruder.retract_length());
|
||||
retract_length > 0 && this->path.size() >= 2) {
|
||||
// Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
// Too fast = ripping of existing material; too slow = short wipe path, thus more blob.
|
||||
const double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
// Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
// due to rounding (TODO: test and/or better math for this).
|
||||
const double xy_to_e = 0.95 * extruder.retract_speed() / wipe_speed;
|
||||
// Start with the current position, which may be different from the wipe path start in case of loop clipping.
|
||||
Vec2d prev = gcodegen.point_to_gcode_quantized(gcodegen.last_pos());
|
||||
auto it = this->path.points.begin();
|
||||
Vec2d p = gcodegen.point_to_gcode_quantized(*(++ it));
|
||||
if (p != prev) {
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n";
|
||||
for (const Line& line : wipe_path.lines()) {
|
||||
double segment_length = line.length();
|
||||
/* Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
due to rounding (TODO: test and/or better math for this) */
|
||||
double dE = length * (segment_length / wipe_dist) * 0.95;
|
||||
auto end = this->path.points.end();
|
||||
bool done = false;
|
||||
for (; it != end; ++ it) {
|
||||
p = gcodegen.point_to_gcode_quantized(*it);
|
||||
double segment_length = (p - prev).norm();
|
||||
double dE = GCodeFormatter::quantize_e(xy_to_e * segment_length);
|
||||
if (dE > retract_length - EPSILON) {
|
||||
if (dE > retract_length + EPSILON)
|
||||
// Shorten the segment.
|
||||
p = prev + (p - prev) * (retract_length / dE);
|
||||
dE = retract_length;
|
||||
done = true;
|
||||
}
|
||||
//FIXME one shall not generate the unnecessary G1 Fxxx commands, here wipe_speed is a constant inside this cycle.
|
||||
// Is it here for the cooling markers? Or should it be outside of the cycle?
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, "", gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(
|
||||
gcodegen.point_to_gcode(line.b),
|
||||
-dE,
|
||||
"wipe and retract"
|
||||
);
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, {}, gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(p, -dE, "wipe and retract");
|
||||
prev = p;
|
||||
retract_length -= dE;
|
||||
}
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n";
|
||||
gcodegen.set_last_pos(wipe_path.points.back());
|
||||
gcodegen.set_last_pos(gcodegen.gcode_to_point(prev));
|
||||
}
|
||||
|
||||
// prevent wiping again on same path
|
||||
this->reset_path();
|
||||
}
|
||||
|
||||
// Prevent wiping again on the same path.
|
||||
this->reset_path();
|
||||
return gcode;
|
||||
}
|
||||
|
||||
@ -937,49 +924,6 @@ namespace DoExport {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||
static void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, const std::vector<Vec2d> &sizes, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
// Write thumbnails using base64 encoding
|
||||
if (thumbnail_cb != nullptr)
|
||||
{
|
||||
const size_t max_row_length = 78;
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ sizes, true, true, true, true });
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
{
|
||||
if (data.is_valid())
|
||||
{
|
||||
size_t png_size = 0;
|
||||
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||
if (png_data != nullptr)
|
||||
{
|
||||
std::string encoded;
|
||||
encoded.resize(boost::beast::detail::base64::encoded_size(png_size));
|
||||
encoded.resize(boost::beast::detail::base64::encode((void*)&encoded[0], (const void*)png_data, png_size));
|
||||
|
||||
output((boost::format("\n;\n; thumbnail begin %dx%d %d\n") % data.width % data.height % encoded.size()).str().c_str());
|
||||
|
||||
unsigned int row_count = 0;
|
||||
while (encoded.size() > max_row_length)
|
||||
{
|
||||
output((boost::format("; %s\n") % encoded.substr(0, max_row_length)).str().c_str());
|
||||
encoded = encoded.substr(max_row_length);
|
||||
++row_count;
|
||||
}
|
||||
|
||||
if (encoded.size() > 0)
|
||||
output((boost::format("; %s\n") % encoded).str().c_str());
|
||||
|
||||
output("; thumbnail end\n;\n");
|
||||
|
||||
mz_free(png_data);
|
||||
}
|
||||
}
|
||||
throw_if_canceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in print_statistics and return formatted string containing filament statistics to be inserted into G-code comment section.
|
||||
static std::string update_print_stats_and_format_filament_stats(
|
||||
const bool has_wipe_tower,
|
||||
@ -1163,9 +1107,16 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// Write information on the generator.
|
||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||
|
||||
DoExport::export_thumbnails_to_file(thumbnail_cb, print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
[&file](const char* sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
// Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
||||
// If "thumbnails_format" is not defined, export to PNG.
|
||||
if (const auto [thumbnails, thumbnails_format] = std::make_pair(
|
||||
print.full_print_config().option<ConfigOptionPoints>("thumbnails"),
|
||||
print.full_print_config().option<ConfigOptionEnum<GCodeThumbnailsFormat>>("thumbnails_format"));
|
||||
thumbnails)
|
||||
GCodeThumbnails::export_thumbnails_to_file(
|
||||
thumbnail_cb, thumbnails->values, thumbnails_format ? thumbnails_format->value : GCodeThumbnailsFormat::PNG,
|
||||
[&file](const char* sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
|
||||
// Write notes (content of the Print Settings tab -> Notes)
|
||||
{
|
||||
@ -2129,13 +2080,13 @@ GCode::LayerResult GCode::process_layer(
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Layer_Change) + "\n";
|
||||
// export layer z
|
||||
char buf[64];
|
||||
sprintf(buf, ";Z:%g\n", print_z);
|
||||
gcode += buf;
|
||||
gcode += std::string(";Z:") + float_to_string_decimal_point(print_z) + "\n";
|
||||
|
||||
// export layer height
|
||||
float height = first_layer ? static_cast<float>(print_z) : static_cast<float>(print_z) - m_last_layer_z;
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), height);
|
||||
gcode += buf;
|
||||
gcode += std::string(";") + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height)
|
||||
+ float_to_string_decimal_point(height) + "\n";
|
||||
|
||||
// update caches
|
||||
m_last_layer_z = static_cast<float>(print_z);
|
||||
m_max_layer_z = std::max(m_max_layer_z, m_last_layer_z);
|
||||
@ -3002,33 +2953,34 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
// PrusaMultiMaterial::Writer may generate GCodeProcessor::Height_Tag lines without updating m_last_height
|
||||
// so, if the last role was erWipeTower we force export of GCodeProcessor::Height_Tag lines
|
||||
bool last_was_wipe_tower = (m_last_processor_extrusion_role == erWipeTower);
|
||||
char buf[64];
|
||||
assert(is_decimal_separator_point());
|
||||
|
||||
if (path.role() != m_last_processor_extrusion_role) {
|
||||
m_last_processor_extrusion_role = path.role();
|
||||
char buf[64];
|
||||
sprintf(buf, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(m_last_processor_extrusion_role).c_str());
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
if (last_was_wipe_tower || m_last_width != path.width) {
|
||||
m_last_width = path.width;
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width).c_str(), m_last_width);
|
||||
gcode += buf;
|
||||
gcode += std::string(";") + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width)
|
||||
+ float_to_string_decimal_point(m_last_width) + "\n";
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
if (last_was_wipe_tower || (m_last_mm3_per_mm != path.mm3_per_mm)) {
|
||||
m_last_mm3_per_mm = path.mm3_per_mm;
|
||||
sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
|
||||
gcode += buf;
|
||||
gcode += std::string(";") + GCodeProcessor::Mm3_Per_Mm_Tag
|
||||
+ float_to_string_decimal_point(m_last_mm3_per_mm) + "\n";
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
if (last_was_wipe_tower || std::abs(m_last_height - path.height) > EPSILON) {
|
||||
m_last_height = path.height;
|
||||
sprintf(buf, ";%s%g\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height).c_str(), m_last_height);
|
||||
gcode += buf;
|
||||
|
||||
gcode += std::string(";") + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height)
|
||||
+ float_to_string_decimal_point(m_last_height) + "\n";
|
||||
}
|
||||
|
||||
std::string comment;
|
||||
@ -3046,13 +2998,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
double path_length = 0.;
|
||||
{
|
||||
std::string comment = m_config.gcode_comments ? description : "";
|
||||
for (const Line &line : path.polyline.lines()) {
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
Vec2d prev = this->point_to_gcode_quantized(path.polyline.points.front());
|
||||
auto it = path.polyline.points.begin();
|
||||
auto end = path.polyline.points.end();
|
||||
for (++ it; it != end; ++ it) {
|
||||
Vec2d p = this->point_to_gcode_quantized(*it);
|
||||
const double line_length = (p - prev).norm();
|
||||
path_length += line_length;
|
||||
gcode += m_writer.extrude_to_xy(
|
||||
this->point_to_gcode(line.b),
|
||||
e_per_mm * line_length,
|
||||
comment);
|
||||
gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment);
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
if (m_enable_cooling_markers)
|
||||
@ -3275,7 +3229,13 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||
Vec2d GCode::point_to_gcode(const Point &point) const
|
||||
{
|
||||
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
|
||||
return unscale(point) + m_origin - extruder_offset;
|
||||
return unscaled<double>(point) + m_origin - extruder_offset;
|
||||
}
|
||||
|
||||
Vec2d GCode::point_to_gcode_quantized(const Point &point) const
|
||||
{
|
||||
Vec2d p = this->point_to_gcode(point);
|
||||
return { GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()) };
|
||||
}
|
||||
|
||||
// convert a model-space scaled point into G-code coordinates
|
||||
|
@ -55,9 +55,9 @@ public:
|
||||
Polyline path;
|
||||
|
||||
Wipe() : enable(false) {}
|
||||
bool has_path() const { return !this->path.points.empty(); }
|
||||
void reset_path() { this->path = Polyline(); }
|
||||
std::string wipe(GCode &gcodegen, bool toolchange = false);
|
||||
bool has_path() const { return ! this->path.empty(); }
|
||||
void reset_path() { this->path.clear(); }
|
||||
std::string wipe(GCode &gcodegen, bool toolchange);
|
||||
};
|
||||
|
||||
class WipeTowerIntegration {
|
||||
@ -151,7 +151,10 @@ public:
|
||||
void set_origin(const Vec2d &pointf);
|
||||
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
|
||||
const Point& last_pos() const { return m_last_pos; }
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset.
|
||||
Vec2d point_to_gcode(const Point &point) const;
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset and quantized to G-code resolution.
|
||||
Vec2d point_to_gcode_quantized(const Point &point) const;
|
||||
Point gcode_to_point(const Vec2d &point) const;
|
||||
const FullPrintConfig &config() const { return m_config; }
|
||||
const Layer* layer() const { return m_layer; }
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../Utils.hpp"
|
||||
|
||||
#include <cctype> // isalpha
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -23,11 +24,11 @@ const void unescape_extended_search_mode(std::string &s)
|
||||
|
||||
GCodeFindReplace::GCodeFindReplace(const std::vector<std::string> &gcode_substitutions)
|
||||
{
|
||||
if ((gcode_substitutions.size() % 3) != 0)
|
||||
if ((gcode_substitutions.size() % 4) != 0)
|
||||
throw RuntimeError("Invalid length of gcode_substitutions parameter");
|
||||
|
||||
m_substitutions.reserve(gcode_substitutions.size() / 3);
|
||||
for (size_t i = 0; i < gcode_substitutions.size(); i += 3) {
|
||||
m_substitutions.reserve(gcode_substitutions.size() / 4);
|
||||
for (size_t i = 0; i < gcode_substitutions.size(); i += 4) {
|
||||
Substitution out;
|
||||
try {
|
||||
out.plain_pattern = gcode_substitutions[i];
|
||||
@ -36,6 +37,7 @@ GCodeFindReplace::GCodeFindReplace(const std::vector<std::string> &gcode_substit
|
||||
out.regexp = strchr(params.c_str(), 'r') != nullptr || strchr(params.c_str(), 'R') != nullptr;
|
||||
out.case_insensitive = strchr(params.c_str(), 'i') != nullptr || strchr(params.c_str(), 'I') != nullptr;
|
||||
out.whole_word = strchr(params.c_str(), 'w') != nullptr || strchr(params.c_str(), 'W') != nullptr;
|
||||
out.single_line = strchr(params.c_str(), 's') != nullptr || strchr(params.c_str(), 'S') != nullptr;
|
||||
if (out.regexp) {
|
||||
out.regexp_pattern.assign(
|
||||
out.whole_word ?
|
||||
@ -115,7 +117,8 @@ std::string GCodeFindReplace::process_layer(const std::string &ain)
|
||||
temp.clear();
|
||||
temp.reserve(in->size());
|
||||
boost::regex_replace(ToStringIterator(temp), in->begin(), in->end(),
|
||||
substitution.regexp_pattern, substitution.format, boost::match_default | boost::match_not_dot_newline | boost::match_not_dot_null | boost::format_all);
|
||||
substitution.regexp_pattern, substitution.format,
|
||||
(substitution.single_line ? boost::match_single_line | boost::match_default : boost::match_not_dot_newline | boost::match_default) | boost::format_all);
|
||||
std::swap(out, temp);
|
||||
} else {
|
||||
if (in == &ain)
|
||||
|
@ -24,6 +24,8 @@ private:
|
||||
bool regexp { false };
|
||||
bool case_insensitive { false };
|
||||
bool whole_word { false };
|
||||
// Valid for regexp only. Equivalent to Perl's /s modifier.
|
||||
bool single_line { false };
|
||||
};
|
||||
std::vector<Substitution> m_substitutions;
|
||||
};
|
||||
|
@ -910,6 +910,12 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
||||
if (spiral_vase != nullptr)
|
||||
m_spiral_vase_active = spiral_vase->value;
|
||||
#endif // ENABLE_SPIRAL_VASE_LAYERS
|
||||
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
const ConfigOptionFloat* z_offset = config.option<ConfigOptionFloat>("z_offset");
|
||||
if (z_offset != nullptr)
|
||||
m_z_offset = z_offset->value;
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
}
|
||||
|
||||
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
@ -1159,6 +1165,12 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
if (spiral_vase != nullptr)
|
||||
m_spiral_vase_active = spiral_vase->value;
|
||||
#endif // ENABLE_SPIRAL_VASE_LAYERS
|
||||
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
const ConfigOptionFloat* z_offset = config.option<ConfigOptionFloat>("z_offset");
|
||||
if (z_offset != nullptr)
|
||||
m_z_offset = z_offset->value;
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
}
|
||||
|
||||
void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
|
||||
@ -1176,6 +1188,7 @@ void GCodeProcessor::reset()
|
||||
|
||||
m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
m_saved_position = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
m_origin = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
m_cached_position.reset();
|
||||
m_wiping = false;
|
||||
@ -1189,6 +1202,9 @@ void GCodeProcessor::reset()
|
||||
m_forced_height = 0.0f;
|
||||
m_mm3_per_mm = 0.0f;
|
||||
m_fan_speed = 0.0f;
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
m_z_offset = 0.0f;
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
|
||||
m_extrusion_role = erNone;
|
||||
m_extruder_id = 0;
|
||||
@ -1601,6 +1617,13 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case '6':
|
||||
switch (cmd[2]) {
|
||||
case '0': { process_G60(line); break; } // Save Current Position
|
||||
case '1': { process_G61(line); break; } // Return to Saved Position
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case '9':
|
||||
switch (cmd[2]) {
|
||||
case '0': { process_G90(line); break; } // Set to Absolute Positioning
|
||||
@ -1932,7 +1955,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
|
||||
if (!m_result.spiral_vase_layers.empty() && m_end_position[Z] == m_result.spiral_vase_layers.back().first)
|
||||
m_result.spiral_vase_layers.back().second.second = move_id;
|
||||
else
|
||||
m_result.spiral_vase_layers.push_back({ m_end_position[Z], { move_id, move_id } });
|
||||
m_result.spiral_vase_layers.push_back({ static_cast<float>(m_end_position[Z]), { move_id, move_id } });
|
||||
}
|
||||
#endif // ENABLE_SPIRAL_VASE_LAYERS
|
||||
return;
|
||||
@ -2482,7 +2505,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
AxisCoords delta_pos;
|
||||
for (unsigned char a = X; a <= E; ++a) {
|
||||
delta_pos[a] = m_end_position[a] - m_start_position[a];
|
||||
max_abs_delta = std::max(max_abs_delta, std::abs(delta_pos[a]));
|
||||
max_abs_delta = std::max<float>(max_abs_delta, std::abs(delta_pos[a]));
|
||||
}
|
||||
|
||||
// no displacement, return
|
||||
@ -2592,7 +2615,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
if (curr.abs_axis_feedrate[a] != 0.0f) {
|
||||
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (axis_max_feedrate != 0.0f)
|
||||
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
||||
min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2727,7 +2750,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
// the threshold value = 0.0625f == 0.25 * 0.25 is arbitrary, we may find some smarter condition later
|
||||
|
||||
if ((new_pos - *first_vertex).squaredNorm() < 0.0625f) {
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
set_end_position(0.5f * (new_pos + *first_vertex) + m_z_offset * Vec3f::UnitZ());
|
||||
#else
|
||||
set_end_position(0.5f * (new_pos + *first_vertex));
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
store_move_vertex(EMoveType::Seam);
|
||||
set_end_position(curr_pos);
|
||||
}
|
||||
@ -2809,6 +2836,43 @@ void GCodeProcessor::process_G28(const GCodeReader::GCodeLine& line)
|
||||
process_G1(new_gline);
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_G60(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware)
|
||||
m_saved_position = m_end_position;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_G61(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) {
|
||||
bool modified = false;
|
||||
if (line.has_x()) {
|
||||
m_end_position[X] = m_saved_position[X];
|
||||
modified = true;
|
||||
}
|
||||
if (line.has_y()) {
|
||||
m_end_position[Y] = m_saved_position[Y];
|
||||
modified = true;
|
||||
}
|
||||
if (line.has_z()) {
|
||||
m_end_position[Z] = m_saved_position[Z];
|
||||
modified = true;
|
||||
}
|
||||
if (line.has_e()) {
|
||||
m_end_position[E] = m_saved_position[E];
|
||||
modified = true;
|
||||
}
|
||||
if (line.has_f())
|
||||
m_feedrate = line.f();
|
||||
|
||||
if (!modified)
|
||||
m_end_position = m_saved_position;
|
||||
|
||||
|
||||
store_move_vertex(EMoveType::Travel);
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_G90(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
m_global_positioning_type = EPositioningType::Absolute;
|
||||
@ -3210,8 +3274,12 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
||||
m_extrusion_role,
|
||||
m_extruder_id,
|
||||
m_cp_color.current,
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id],
|
||||
#else
|
||||
Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
|
||||
m_end_position[E] - m_start_position[E],
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
static_cast<float>(m_end_position[E] - m_start_position[E]),
|
||||
m_feedrate,
|
||||
m_width,
|
||||
m_height,
|
||||
|
@ -178,7 +178,7 @@ namespace Slic3r {
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
private:
|
||||
using AxisCoords = std::array<float, 4>;
|
||||
using AxisCoords = std::array<double, 4>;
|
||||
using ExtruderColors = std::vector<unsigned char>;
|
||||
using ExtruderTemps = std::vector<float>;
|
||||
|
||||
@ -517,6 +517,7 @@ namespace Slic3r {
|
||||
|
||||
AxisCoords m_start_position; // mm
|
||||
AxisCoords m_end_position; // mm
|
||||
AxisCoords m_saved_position; // mm
|
||||
AxisCoords m_origin; // mm
|
||||
CachedPosition m_cached_position;
|
||||
bool m_wiping;
|
||||
@ -530,6 +531,9 @@ namespace Slic3r {
|
||||
float m_forced_height; // mm
|
||||
float m_mm3_per_mm;
|
||||
float m_fan_speed; // percentage
|
||||
#if ENABLE_Z_OFFSET_CORRECTION
|
||||
float m_z_offset; // mm
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
ExtrusionRole m_extrusion_role;
|
||||
unsigned char m_extruder_id;
|
||||
ExtruderColors m_extruder_colors;
|
||||
@ -658,6 +662,12 @@ namespace Slic3r {
|
||||
// Move to origin
|
||||
void process_G28(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Save Current Position
|
||||
void process_G60(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Return to Saved Position
|
||||
void process_G61(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set to Absolute Positioning
|
||||
void process_G90(const GCodeReader::GCodeLine& line);
|
||||
|
||||
|
@ -23,28 +23,35 @@ static constexpr float ENFORCER_CENTER_PENALTY = -10.f;
|
||||
|
||||
|
||||
|
||||
|
||||
// This function was introduced in 2016 to assign penalties to overhangs.
|
||||
// LukasM thinks that it discriminated a bit too much, so especially external
|
||||
// seams were than placed in funny places (non-overhangs were preferred too much).
|
||||
// He implemented his own version (below) which applies fixed penalty for really big overlaps.
|
||||
// static float extrudate_overlap_penalty(float nozzle_r, float weight_zero, float overlap_distance)
|
||||
// {
|
||||
// // The extrudate is not fully supported by the lower layer. Fit a polynomial penalty curve.
|
||||
// // Solved by sympy package:
|
||||
// /*
|
||||
// from sympy import *
|
||||
// (x,a,b,c,d,r,z)=symbols('x a b c d r z')
|
||||
// p = a + b*x + c*x*x + d*x*x*x
|
||||
// p2 = p.subs(solve([p.subs(x, -r), p.diff(x).subs(x, -r), p.diff(x,x).subs(x, -r), p.subs(x, 0)-z], [a, b, c, d]))
|
||||
// from sympy.plotting import plot
|
||||
// plot(p2.subs(r,0.2).subs(z,1.), (x, -1, 3), adaptive=False, nb_of_points=400)
|
||||
// */
|
||||
// if (overlap_distance < - nozzle_r) {
|
||||
// // The extrudate is fully supported by the lower layer. This is the ideal case, therefore zero penalty.
|
||||
// return 0.f;
|
||||
// } else {
|
||||
// float x = overlap_distance / nozzle_r;
|
||||
// float x2 = x * x;
|
||||
// float x3 = x2 * x;
|
||||
// return weight_zero * (1.f + 3.f * x + 3.f * x2 + x3);
|
||||
// }
|
||||
// }
|
||||
static float extrudate_overlap_penalty(float nozzle_r, float weight_zero, float overlap_distance)
|
||||
{
|
||||
// The extrudate is not fully supported by the lower layer. Fit a polynomial penalty curve.
|
||||
// Solved by sympy package:
|
||||
/*
|
||||
from sympy import *
|
||||
(x,a,b,c,d,r,z)=symbols('x a b c d r z')
|
||||
p = a + b*x + c*x*x + d*x*x*x
|
||||
p2 = p.subs(solve([p.subs(x, -r), p.diff(x).subs(x, -r), p.diff(x,x).subs(x, -r), p.subs(x, 0)-z], [a, b, c, d]))
|
||||
from sympy.plotting import plot
|
||||
plot(p2.subs(r,0.2).subs(z,1.), (x, -1, 3), adaptive=False, nb_of_points=400)
|
||||
*/
|
||||
if (overlap_distance < - nozzle_r) {
|
||||
// The extrudate is fully supported by the lower layer. This is the ideal case, therefore zero penalty.
|
||||
return 0.f;
|
||||
} else {
|
||||
float x = overlap_distance / nozzle_r;
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
return weight_zero * (1.f + 3.f * x + 3.f * x2 + x3);
|
||||
}
|
||||
return overlap_distance > nozzle_r ? weight_zero : 0.f;
|
||||
}
|
||||
|
||||
|
||||
@ -313,12 +320,12 @@ void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perim
|
||||
if (perimeters[i]->role() == erExternalPerimeter && perimeters[i]->is_loop()) {
|
||||
last_pos = this->calculate_seam(
|
||||
layer, seam_position, *dynamic_cast<const ExtrusionLoop*>(perimeters[i]), nozzle_dmr,
|
||||
po, lower_layer_edge_grid, last_pos);
|
||||
po, lower_layer_edge_grid, last_pos, false);
|
||||
m_plan[i].external = true;
|
||||
m_plan[i].seam_position = seam_position;
|
||||
m_plan[i].layer = &layer;
|
||||
m_plan[i].po = po;
|
||||
}
|
||||
m_plan[i].seam_position = seam_position;
|
||||
m_plan[i].layer = &layer;
|
||||
m_plan[i].po = po;
|
||||
m_plan[i].pt = last_pos;
|
||||
}
|
||||
}
|
||||
@ -327,7 +334,7 @@ void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perim
|
||||
void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid)
|
||||
{
|
||||
const double seam_offset = nozzle_diameter;
|
||||
// const double seam_offset = nozzle_diameter;
|
||||
|
||||
Point seam = last_pos;
|
||||
if (! m_plan.empty() && m_plan_idx < m_plan.size()) {
|
||||
@ -339,75 +346,100 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
|
||||
// far from each other.
|
||||
if ((seam.cast<double>() - last_pos.cast<double>()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.))
|
||||
seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter,
|
||||
m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos);
|
||||
}
|
||||
else if (! external_first) {
|
||||
// Internal perimeter printed before the external.
|
||||
// First get list of external seams.
|
||||
std::vector<size_t> ext_seams;
|
||||
for (size_t i = 0; i < m_plan.size(); ++i) {
|
||||
if (m_plan[i].external)
|
||||
ext_seams.emplace_back(i);
|
||||
}
|
||||
m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos, false);
|
||||
|
||||
if (! ext_seams.empty()) {
|
||||
// First find the line segment closest to an external seam:
|
||||
int path_idx = 0;
|
||||
int line_idx = 0;
|
||||
size_t ext_seam_idx = size_t(-1);
|
||||
double min_dist_sqr = std::numeric_limits<double>::max();
|
||||
std::vector<Lines> lines_vect;
|
||||
for (int i = 0; i < int(loop.paths.size()); ++i) {
|
||||
lines_vect.emplace_back(loop.paths[i].polyline.lines());
|
||||
const Lines& lines = lines_vect.back();
|
||||
for (int j = 0; j < int(lines.size()); ++j) {
|
||||
for (size_t k : ext_seams) {
|
||||
double d_sqr = lines[j].distance_to_squared(m_plan[k].pt);
|
||||
if (d_sqr < min_dist_sqr) {
|
||||
path_idx = i;
|
||||
line_idx = j;
|
||||
ext_seam_idx = k;
|
||||
min_dist_sqr = d_sqr;
|
||||
if (m_plan[m_plan_idx].seam_position == spAligned)
|
||||
m_seam_history.add_seam(m_plan[m_plan_idx].po, m_plan[m_plan_idx].pt, loop.polygon().bounding_box());
|
||||
}
|
||||
else {
|
||||
if (!external_first) {
|
||||
// Internal perimeter printed before the external.
|
||||
// First get list of external seams.
|
||||
std::vector<size_t> ext_seams;
|
||||
size_t external_cnt = 0;
|
||||
for (size_t i = 0; i < m_plan.size(); ++i) {
|
||||
if (m_plan[i].external) {
|
||||
ext_seams.emplace_back(i);
|
||||
++external_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ext_seams.empty()) {
|
||||
// First find the line segment closest to an external seam:
|
||||
//int path_idx = 0;
|
||||
//int line_idx = 0;
|
||||
size_t ext_seam_idx = size_t(-1);
|
||||
double min_dist_sqr = std::numeric_limits<double>::max();
|
||||
std::vector<Lines> lines_vect;
|
||||
for (int i = 0; i < int(loop.paths.size()); ++i) {
|
||||
lines_vect.emplace_back(loop.paths[i].polyline.lines());
|
||||
const Lines& lines = lines_vect.back();
|
||||
for (int j = 0; j < int(lines.size()); ++j) {
|
||||
for (size_t k : ext_seams) {
|
||||
double d_sqr = lines[j].distance_to_squared(m_plan[k].pt);
|
||||
if (d_sqr < min_dist_sqr) {
|
||||
//path_idx = i;
|
||||
//line_idx = j;
|
||||
ext_seam_idx = k;
|
||||
min_dist_sqr = d_sqr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only accept seam that is reasonably close.
|
||||
double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.);
|
||||
if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) {
|
||||
// Now find a projection of the external seam
|
||||
const Lines& lines = lines_vect[path_idx];
|
||||
Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
|
||||
double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
|
||||
// Only accept seam that is reasonably close.
|
||||
if (ext_seam_idx != size_t(-1)) {
|
||||
// How many nozzle diameters is considered "close"?
|
||||
const double nozzle_d_limit = 2. * (1. + m_plan.size() / external_cnt);
|
||||
const double limit_dist_sqr = double(scale_(scale_((unscale(m_plan[ext_seam_idx].pt) - unscale(m_plan[m_plan_idx].pt)).squaredNorm() * std::pow(nozzle_d_limit * nozzle_diameter, 2.))));
|
||||
|
||||
// And walk along the perimeter until we make enough space for
|
||||
// seams of all perimeters beforethe external one.
|
||||
double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset);
|
||||
double last_offset = offset;
|
||||
offset -= dist;
|
||||
const Point* a = &closest;
|
||||
const Point* b = &lines[line_idx].b;
|
||||
while (++line_idx < int(lines.size()) && offset > 0.) {
|
||||
last_offset = offset;
|
||||
offset -= lines[line_idx].length();
|
||||
a = &lines[line_idx].a;
|
||||
b = &lines[line_idx].b;
|
||||
if (min_dist_sqr < limit_dist_sqr) {
|
||||
// Now find a projection of the external seam
|
||||
//const Lines& lines = lines_vect[path_idx];
|
||||
//Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
|
||||
|
||||
// This code does staggering of internal perimeters, turned off for now.
|
||||
//
|
||||
// double dist = (closest.cast<double>() - lines[line_idx].b.cast<double>()).norm();
|
||||
//
|
||||
// // And walk along the perimeter until we make enough space for
|
||||
// // seams of all perimeters beforethe external one.
|
||||
// double offset = (ext_seam_idx - m_plan_idx) * scale_(seam_offset);
|
||||
// double last_offset = offset;
|
||||
// offset -= dist;
|
||||
// const Point* a = &closest;
|
||||
// const Point* b = &lines[line_idx].b;
|
||||
// while (++line_idx < int(lines.size()) && offset > 0.) {
|
||||
// last_offset = offset;
|
||||
// offset -= lines[line_idx].length();
|
||||
// a = &lines[line_idx].a;
|
||||
// b = &lines[line_idx].b;
|
||||
// }
|
||||
//
|
||||
// // We have walked far enough, too far maybe. Interpolate on the
|
||||
// // last segment to find the end precisely.
|
||||
// offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around")
|
||||
// double ratio = last_offset / (last_offset - offset);
|
||||
// seam = (a->cast<double>() + ((b->cast<double>() - a->cast<double>()) * ratio)).cast<coord_t>();
|
||||
seam = m_plan[ext_seam_idx].pt;
|
||||
}
|
||||
}
|
||||
|
||||
// We have walked far enough, too far maybe. Interpolate on the
|
||||
// last segment to find the end precisely.
|
||||
offset = std::min(0., offset); // In case that offset is still positive (we may have "wrapped around")
|
||||
double ratio = last_offset / (last_offset - offset);
|
||||
seam = (a->cast<double>() + ((b->cast<double>() - a->cast<double>()) * ratio)).cast<coord_t>();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We should have a candidate ready from before. If not, use last_pos.
|
||||
if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated)
|
||||
seam = m_plan[m_plan_idx - 1].pt;
|
||||
}
|
||||
|
||||
// seam now contains a hot candidate for internal seam. Use it unless there is a sharp corner nearby.
|
||||
// We will call the normal seam planning function, pretending that we are currently at the candidate point
|
||||
// and set to spNearest. If the ideal seam it finds is close to current candidate, use it.
|
||||
// This is to prevent having seams very close to corners, just because of external seam position.
|
||||
seam = calculate_seam(*m_plan[m_plan_idx].layer, spNearest, loop, nozzle_diameter,
|
||||
m_plan[m_plan_idx].po, lower_layer_edge_grid, seam, true);
|
||||
}
|
||||
else {
|
||||
// We should have a candidate ready from before. If not, use last_pos.
|
||||
if (m_plan_idx > 0 && m_plan[m_plan_idx - 1].precalculated)
|
||||
seam = m_plan[m_plan_idx - 1].pt;
|
||||
}
|
||||
m_plan[m_plan_idx].pt = seam;
|
||||
}
|
||||
|
||||
|
||||
@ -417,41 +449,42 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
|
||||
loop.split_at(seam, true);
|
||||
|
||||
if (external_first && m_plan_idx+1<m_plan.size() && ! m_plan[m_plan_idx+1].external) {
|
||||
// Next perimeter should start near this one.
|
||||
const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.);
|
||||
double running_sqr = 0.;
|
||||
double running_sqr_last = 0.;
|
||||
if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) {
|
||||
const ExtrusionPath& last = loop.paths.back();
|
||||
auto it = last.polyline.points.crbegin() + 1;
|
||||
for (; it != last.polyline.points.crend(); ++it) {
|
||||
running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm();
|
||||
if (running_sqr > dist_sqr)
|
||||
break;
|
||||
running_sqr_last = running_sqr;
|
||||
}
|
||||
if (running_sqr <= dist_sqr)
|
||||
it = last.polyline.points.crend() - 1;
|
||||
// Now interpolate.
|
||||
double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last));
|
||||
m_plan[m_plan_idx + 1].pt = ((it - 1)->cast<double>() + (it->cast<double>() - (it - 1)->cast<double>()) * std::min(ratio, 1.)).cast<coord_t>();
|
||||
// This code does staggering of internal perimeters, turned off for now.
|
||||
// Next perimeter should start near this one.
|
||||
// const double dist_sqr = std::pow(double(scale_(seam_offset)), 2.);
|
||||
// double running_sqr = 0.;
|
||||
// double running_sqr_last = 0.;
|
||||
// if (!loop.paths.empty() && loop.paths.back().polyline.points.size() > 1) {
|
||||
// const ExtrusionPath& last = loop.paths.back();
|
||||
// auto it = last.polyline.points.crbegin() + 1;
|
||||
// for (; it != last.polyline.points.crend(); ++it) {
|
||||
// running_sqr += (it->cast<double>() - (it - 1)->cast<double>()).squaredNorm();
|
||||
// if (running_sqr > dist_sqr)
|
||||
// break;
|
||||
// running_sqr_last = running_sqr;
|
||||
// }
|
||||
// if (running_sqr <= dist_sqr)
|
||||
// it = last.polyline.points.crend() - 1;
|
||||
// // Now interpolate.
|
||||
// double ratio = (std::sqrt(dist_sqr) - std::sqrt(running_sqr_last)) / (std::sqrt(running_sqr) - std::sqrt(running_sqr_last));
|
||||
// m_plan[m_plan_idx + 1].pt = ((it - 1)->cast<double>() + (it->cast<double>() - (it - 1)->cast<double>()) * std::min(ratio, 1.)).cast<coord_t>();
|
||||
// m_plan[m_plan_idx + 1].precalculated = true;
|
||||
m_plan[m_plan_idx + 1].pt = m_plan[m_plan_idx].pt;
|
||||
m_plan[m_plan_idx + 1].precalculated = true;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
++m_plan_idx;
|
||||
}
|
||||
|
||||
|
||||
// Returns a seam for an EXTERNAL perimeter.
|
||||
// Returns "best" seam for a given perimeter.
|
||||
Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_position,
|
||||
const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos)
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest)
|
||||
{
|
||||
assert(loop.role() == erExternalPerimeter);
|
||||
Polygon polygon = loop.polygon();
|
||||
bool was_clockwise = polygon.make_counter_clockwise();
|
||||
BoundingBox polygon_bb = polygon.bounding_box();
|
||||
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
|
||||
|
||||
size_t po_idx = std::find(m_po_list.begin(), m_po_list.end(), po) - m_po_list.begin();
|
||||
@ -462,7 +495,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
if (po == m_last_po && layer.print_z == m_last_print_z)
|
||||
layer_po = m_last_layer_po;
|
||||
else {
|
||||
layer_po = po->get_layer_at_printz(layer.print_z);
|
||||
layer_po = po ? po->get_layer_at_printz(layer.print_z) : nullptr;
|
||||
m_last_po = po;
|
||||
m_last_print_z = layer.print_z;
|
||||
m_last_layer_po = layer_po;
|
||||
@ -475,7 +508,9 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
|
||||
assert(layer_idx < po->layer_count());
|
||||
|
||||
if (this->is_custom_seam_on_layer(layer_idx, po_idx)) {
|
||||
const bool custom_seam = loop.role() == erExternalPerimeter && this->is_custom_seam_on_layer(layer_idx, po_idx);
|
||||
|
||||
if (custom_seam) {
|
||||
// Seam enf/blockers can begin and end in between the original vertices.
|
||||
// Let add extra points in between and update the leghths.
|
||||
polygon.densify(MINIMAL_POLYGON_SIDE);
|
||||
@ -488,7 +523,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
if (seam_position == spAligned) {
|
||||
// Seam is aligned to the seam at the preceding layer.
|
||||
if (po != nullptr) {
|
||||
std::optional<Point> pos = m_seam_history.get_last_seam(m_po_list[po_idx], layer_idx, polygon_bb);
|
||||
std::optional<Point> pos = m_seam_history.get_last_seam(m_po_list[po_idx], layer_idx, loop.polygon().bounding_box());
|
||||
if (pos.has_value()) {
|
||||
last_pos = *pos;
|
||||
last_pos_weight = is_custom_enforcer_on_layer(layer_idx, po_idx) ? 0.f : 1.f;
|
||||
@ -519,7 +554,7 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
std::vector<float> penalties = polygon_angles_at_vertices(polygon, lengths, float(nozzle_r));
|
||||
// No penalty for reflex points, slight penalty for convex points, high penalty for flat surfaces.
|
||||
const float penaltyConvexVertex = 1.f;
|
||||
const float penaltyFlatSurface = 5.f;
|
||||
const float penaltyFlatSurface = 3.f;
|
||||
const float penaltyOverhangHalf = 10.f;
|
||||
// Penalty for visible seams.
|
||||
for (size_t i = 0; i < polygon.points.size(); ++ i) {
|
||||
@ -548,8 +583,12 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
float dist_max = 0.1f * lengths.back(); // 5.f * nozzle_dmr
|
||||
penalty -= last_pos_weight * bspline_kernel(dist_to_last_pos_proj / dist_max);
|
||||
penalties[i] = std::max(0.f, penalty);
|
||||
if (prefer_nearest) {
|
||||
// This hack limits the search around the nearest position projection.
|
||||
penalties[i] += dist_to_last_pos_proj > 6.f * nozzle_r ? 100.f : 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Penalty for overhangs.
|
||||
if (lower_layer_edge_grid) {
|
||||
// Use the edge grid distance field structure over the lower layer to calculate overhangs.
|
||||
@ -568,10 +607,11 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
penalties[i] += extrudate_overlap_penalty(float(nozzle_r), penaltyOverhangHalf, float(dist));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Custom seam. Huge (negative) constant penalty is applied inside
|
||||
// blockers (enforcers) to rule out points that should not win.
|
||||
this->apply_custom_seam(polygon, po_idx, penalties, lengths, layer_idx, seam_position);
|
||||
if (custom_seam)
|
||||
this->apply_custom_seam(polygon, po_idx, penalties, lengths, layer_idx, seam_position);
|
||||
|
||||
// Find a point with a minimum penalty.
|
||||
size_t idx_min = std::min_element(penalties.begin(), penalties.end()) - penalties.begin();
|
||||
@ -592,9 +632,6 @@ Point SeamPlacer::calculate_seam(const Layer& layer, const SeamPosition seam_pos
|
||||
}
|
||||
}
|
||||
|
||||
if (seam_position == spAligned)
|
||||
m_seam_history.add_seam(po, polygon.points[idx_min], polygon_bb);
|
||||
|
||||
|
||||
// Export the contour into a SVG file.
|
||||
#if 0
|
||||
|
@ -65,7 +65,7 @@ private:
|
||||
// When given an external perimeter (!), returns the seam.
|
||||
Point calculate_seam(const Layer& layer, const SeamPosition seam_position,
|
||||
const ExtrusionLoop& loop, coordf_t nozzle_dmr, const PrintObject* po,
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos);
|
||||
const EdgeGrid::Grid* lower_layer_edge_grid, Point last_pos, bool prefer_nearest);
|
||||
|
||||
struct CustomTrianglesPerLayer {
|
||||
Polygons polys;
|
||||
|
119
src/libslic3r/GCode/Thumbnails.cpp
Normal file
119
src/libslic3r/GCode/Thumbnails.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "Thumbnails.hpp"
|
||||
#include "../miniz_extension.hpp"
|
||||
|
||||
#include <qoi/qoi.h>
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
|
||||
namespace Slic3r::GCodeThumbnails {
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
struct CompressedPNG : CompressedImageBuffer
|
||||
{
|
||||
~CompressedPNG() override { if (data) mz_free(data); }
|
||||
std::string_view tag() const override { return "thumbnail"sv; }
|
||||
};
|
||||
|
||||
struct CompressedJPG : CompressedImageBuffer
|
||||
{
|
||||
~CompressedJPG() override { free(data); }
|
||||
std::string_view tag() const override { return "thumbnail_JPG"sv; }
|
||||
};
|
||||
|
||||
struct CompressedQOI : CompressedImageBuffer
|
||||
{
|
||||
~CompressedQOI() override { free(data); }
|
||||
std::string_view tag() const override { return "thumbnail_QOI"sv; }
|
||||
};
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_png(const ThumbnailData &data)
|
||||
{
|
||||
auto out = std::make_unique<CompressedPNG>();
|
||||
out->data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &out->size, MZ_DEFAULT_LEVEL, 1);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_jpg(const ThumbnailData& data)
|
||||
{
|
||||
// Take vector of RGBA pixels and flip the image vertically
|
||||
std::vector<unsigned char> rgba_pixels(data.pixels.size());
|
||||
const unsigned int row_size = data.width * 4;
|
||||
for (unsigned int y = 0; y < data.height; ++y) {
|
||||
::memcpy(rgba_pixels.data() + (data.height - y - 1) * row_size, data.pixels.data() + y * row_size, row_size);
|
||||
}
|
||||
|
||||
// Store pointers to scanlines start for later use
|
||||
std::vector<unsigned char*> rows_ptrs;
|
||||
rows_ptrs.reserve(data.height);
|
||||
for (unsigned int y = 0; y < data.height; ++y) {
|
||||
rows_ptrs.emplace_back(&rgba_pixels[y * row_size]);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> compressed_data(data.pixels.size());
|
||||
unsigned char* compressed_data_ptr = compressed_data.data();
|
||||
unsigned long compressed_data_size = data.pixels.size();
|
||||
|
||||
jpeg_error_mgr err;
|
||||
jpeg_compress_struct info;
|
||||
info.err = jpeg_std_error(&err);
|
||||
jpeg_create_compress(&info);
|
||||
jpeg_mem_dest(&info, &compressed_data_ptr, &compressed_data_size);
|
||||
|
||||
info.image_width = data.width;
|
||||
info.image_height = data.height;
|
||||
info.input_components = 4;
|
||||
info.in_color_space = JCS_EXT_RGBA;
|
||||
|
||||
jpeg_set_defaults(&info);
|
||||
jpeg_set_quality(&info, 85, TRUE);
|
||||
jpeg_start_compress(&info, TRUE);
|
||||
|
||||
jpeg_write_scanlines(&info, rows_ptrs.data(), data.height);
|
||||
jpeg_finish_compress(&info);
|
||||
jpeg_destroy_compress(&info);
|
||||
|
||||
// FIXME -> Add error checking
|
||||
|
||||
auto out = std::make_unique<CompressedJPG>();
|
||||
out->data = malloc(compressed_data_size);
|
||||
out->size = size_t(compressed_data_size);
|
||||
::memcpy(out->data, (const void*)compressed_data.data(), out->size);
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail_qoi(const ThumbnailData &data)
|
||||
{
|
||||
qoi_desc desc;
|
||||
desc.width = data.width;
|
||||
desc.height = data.height;
|
||||
desc.channels = 4;
|
||||
desc.colorspace = QOI_SRGB;
|
||||
|
||||
// Take vector of RGBA pixels and flip the image vertically
|
||||
std::vector<uint8_t> rgba_pixels(data.pixels.size() * 4);
|
||||
size_t row_size = data.width * 4;
|
||||
for (size_t y = 0; y < data.height; ++ y)
|
||||
memcpy(rgba_pixels.data() + (data.height - y - 1) * row_size, data.pixels.data() + y * row_size, row_size);
|
||||
|
||||
auto out = std::make_unique<CompressedQOI>();
|
||||
int size;
|
||||
out->data = qoi_encode((const void*)rgba_pixels.data(), &desc, &size);
|
||||
out->size = size;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case GCodeThumbnailsFormat::PNG:
|
||||
default:
|
||||
return compress_thumbnail_png(data);
|
||||
case GCodeThumbnailsFormat::JPG:
|
||||
return compress_thumbnail_jpg(data);
|
||||
case GCodeThumbnailsFormat::QOI:
|
||||
return compress_thumbnail_qoi(data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GCodeThumbnails
|
60
src/libslic3r/GCode/Thumbnails.hpp
Normal file
60
src/libslic3r/GCode/Thumbnails.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef slic3r_GCodeThumbnails_hpp_
|
||||
#define slic3r_GCodeThumbnails_hpp_
|
||||
|
||||
#include "../Point.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "ThumbnailData.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
namespace Slic3r::GCodeThumbnails {
|
||||
|
||||
struct CompressedImageBuffer
|
||||
{
|
||||
void *data { nullptr };
|
||||
size_t size { 0 };
|
||||
virtual ~CompressedImageBuffer() {}
|
||||
virtual std::string_view tag() const = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<CompressedImageBuffer> compress_thumbnail(const ThumbnailData &data, GCodeThumbnailsFormat format);
|
||||
|
||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||
inline void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, const std::vector<Vec2d> &sizes, GCodeThumbnailsFormat format, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
// Write thumbnails using base64 encoding
|
||||
if (thumbnail_cb != nullptr) {
|
||||
static constexpr const size_t max_row_length = 78;
|
||||
ThumbnailsList thumbnails = thumbnail_cb(ThumbnailsParams{ sizes, true, true, true, true });
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
if (data.is_valid()) {
|
||||
auto compressed = compress_thumbnail(data, format);
|
||||
if (compressed->data && compressed->size) {
|
||||
std::string encoded;
|
||||
encoded.resize(boost::beast::detail::base64::encoded_size(compressed->size));
|
||||
encoded.resize(boost::beast::detail::base64::encode((void*)encoded.data(), (const void*)compressed->data, compressed->size));
|
||||
|
||||
output((boost::format("\n;\n; %s begin %dx%d %d\n") % compressed->tag() % data.width % data.height % encoded.size()).str().c_str());
|
||||
|
||||
while (encoded.size() > max_row_length) {
|
||||
output((boost::format("; %s\n") % encoded.substr(0, max_row_length)).str().c_str());
|
||||
encoded = encoded.substr(max_row_length);
|
||||
}
|
||||
|
||||
if (encoded.size() > 0)
|
||||
output((boost::format("; %s\n") % encoded).str().c_str());
|
||||
|
||||
output((boost::format("; %s end\n;\n") % compressed->tag()).str().c_str());
|
||||
}
|
||||
throw_if_canceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GCodeThumbnails
|
||||
|
||||
#endif // slic3r_GCodeThumbnails_hpp_
|
@ -74,7 +74,7 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object
|
||||
{
|
||||
double max_layer_height = std::numeric_limits<double>::max();
|
||||
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
||||
double mlh = config.max_layer_height.values[i];
|
||||
double mlh = config.max_layer_height.get_at(i);
|
||||
if (mlh == 0.)
|
||||
mlh = 0.75 * config.nozzle_diameter.values[i];
|
||||
max_layer_height = std::min(max_layer_height, mlh);
|
||||
|
@ -74,7 +74,8 @@ const char* GCodeReader::parse_line_internal(const char *ptr, const char *end, G
|
||||
if (axis != NUM_AXES_WITH_UNKNOWN) {
|
||||
// Try to parse the numeric value.
|
||||
double v;
|
||||
auto [pend, ec] = fast_float::from_chars(++ c, end, v);
|
||||
c = skip_whitespaces(++c);
|
||||
auto [pend, ec] = fast_float::from_chars(c, end, v);
|
||||
if (pend != c && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
if (axis != UNKNOWN_AXIS)
|
||||
|
@ -79,7 +79,7 @@ std::string GCodeWriter::postamble() const
|
||||
std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, int tool) const
|
||||
{
|
||||
if (wait && (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)))
|
||||
return "";
|
||||
return {};
|
||||
|
||||
std::string code, comment;
|
||||
if (wait && FLAVOR_IS_NOT(gcfTeacup) && FLAVOR_IS_NOT(gcfRepRapFirmware)) {
|
||||
@ -192,32 +192,18 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
||||
|
||||
std::string GCodeWriter::reset_e(bool force)
|
||||
{
|
||||
if (FLAVOR_IS(gcfMach3)
|
||||
|| FLAVOR_IS(gcfMakerWare)
|
||||
|| FLAVOR_IS(gcfSailfish))
|
||||
return "";
|
||||
|
||||
if (m_extruder != nullptr) {
|
||||
if (m_extruder->E() == 0. && ! force)
|
||||
return "";
|
||||
m_extruder->reset_E();
|
||||
}
|
||||
|
||||
if (! m_extrusion_axis.empty() && ! this->config.use_relative_e_distances) {
|
||||
std::ostringstream gcode;
|
||||
gcode << "G92 " << m_extrusion_axis << "0";
|
||||
if (this->config.gcode_comments) gcode << " ; reset extrusion distance";
|
||||
gcode << "\n";
|
||||
return gcode.str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return
|
||||
FLAVOR_IS(gcfMach3) || FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish) || this->config.use_relative_e_distances ||
|
||||
(m_extruder != nullptr && ! m_extruder->reset_E() && ! force) ||
|
||||
m_extrusion_axis.empty() ?
|
||||
std::string{} :
|
||||
std::string("G92 ") + m_extrusion_axis + (this->config.gcode_comments ? "0 ; reset extrusion distance\n" : "0\n");
|
||||
}
|
||||
|
||||
std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, bool allow_100) const
|
||||
{
|
||||
if (FLAVOR_IS_NOT(gcfMakerWare) && FLAVOR_IS_NOT(gcfSailfish))
|
||||
return "";
|
||||
return {};
|
||||
|
||||
unsigned int percent = (unsigned int)floor(100.0 * num / tot + 0.5);
|
||||
if (!allow_100) percent = std::min(percent, (unsigned int)99);
|
||||
@ -269,8 +255,8 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s
|
||||
|
||||
std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment)
|
||||
{
|
||||
m_pos(0) = point(0);
|
||||
m_pos(1) = point(1);
|
||||
m_pos.x() = point.x();
|
||||
m_pos.y() = point.y();
|
||||
|
||||
GCodeG1Formatter w;
|
||||
w.emit_xy(point);
|
||||
@ -290,9 +276,9 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
|
||||
don't perform the Z move but we only move in the XY plane and
|
||||
adjust the nominal Z by reducing the lift amount that will be
|
||||
used for unlift. */
|
||||
if (!this->will_move_z(point(2))) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
m_lifted -= (point(2) - nominal_z);
|
||||
if (!this->will_move_z(point.z())) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted -= (point.z() - nominal_z);
|
||||
// In case that retract_lift == layer_height we could end up with almost zero in_m_lifted
|
||||
// and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
@ -318,11 +304,11 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
||||
we don't perform the move but we only adjust the nominal Z by
|
||||
reducing the lift amount that will be used for unlift. */
|
||||
if (!this->will_move_z(z)) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted -= (z - nominal_z);
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
m_lifted = 0.;
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
/* In all the other cases, we perform an actual Z move and cancel
|
||||
@ -333,7 +319,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
||||
|
||||
std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
|
||||
{
|
||||
m_pos(2) = z;
|
||||
m_pos.z() = z;
|
||||
|
||||
double speed = this->config.travel_speed_z.value;
|
||||
if (speed == 0.)
|
||||
@ -351,8 +337,8 @@ bool GCodeWriter::will_move_z(double z) const
|
||||
/* If target Z is lower than current Z but higher than nominal Z
|
||||
we don't perform an actual Z move. */
|
||||
if (m_lifted > 0) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
if (z >= nominal_z && z <= m_pos(2))
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
if (z >= nominal_z && z <= m_pos.z())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -360,17 +346,17 @@ bool GCodeWriter::will_move_z(double z) const
|
||||
|
||||
std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std::string &comment)
|
||||
{
|
||||
m_pos(0) = point(0);
|
||||
m_pos(1) = point(1);
|
||||
m_extruder->extrude(dE);
|
||||
m_pos.x() = point.x();
|
||||
m_pos.y() = point.y();
|
||||
|
||||
GCodeG1Formatter w;
|
||||
w.emit_xy(point);
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, m_extruder->extrude(dE).second);
|
||||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
return w.string();
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment)
|
||||
{
|
||||
m_pos = point;
|
||||
@ -383,6 +369,7 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
|
||||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
return w.string();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string GCodeWriter::retract(bool before_wipe)
|
||||
{
|
||||
@ -422,14 +409,13 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
|
||||
restart_extra = restart_extra * area;
|
||||
}
|
||||
|
||||
|
||||
std::string gcode;
|
||||
if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
|
||||
if (auto [dE, emitE] = m_extruder->retract(length, restart_extra); dE != 0) {
|
||||
if (this->config.use_firmware_retraction) {
|
||||
gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
|
||||
} else if (! m_extrusion_axis.empty()) {
|
||||
GCodeG1Formatter w;
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, emitE);
|
||||
w.emit_f(m_extruder->retract_speed() * 60.);
|
||||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
gcode = w.string();
|
||||
@ -449,14 +435,14 @@ std::string GCodeWriter::unretract()
|
||||
if (FLAVOR_IS(gcfMakerWare))
|
||||
gcode = "M101 ; extruder on\n";
|
||||
|
||||
if (double dE = m_extruder->unretract(); dE != 0) {
|
||||
if (auto [dE, emitE] = m_extruder->unretract(); dE != 0) {
|
||||
if (this->config.use_firmware_retraction) {
|
||||
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
|
||||
gcode += this->reset_e();
|
||||
} else if (! m_extrusion_axis.empty()) {
|
||||
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
|
||||
GCodeG1Formatter w;
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, emitE);
|
||||
w.emit_f(m_extruder->deretract_speed() * 60.);
|
||||
w.emit_comment(this->config.gcode_comments, " ; unretract");
|
||||
gcode += w.string();
|
||||
@ -476,21 +462,21 @@ std::string GCodeWriter::lift()
|
||||
{
|
||||
double above = this->config.retract_lift_above.get_at(m_extruder->id());
|
||||
double below = this->config.retract_lift_below.get_at(m_extruder->id());
|
||||
if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below))
|
||||
if (m_pos.z() >= above && (below == 0 || m_pos.z() <= below))
|
||||
target_lift = this->config.retract_lift.get_at(m_extruder->id());
|
||||
}
|
||||
if (m_lifted == 0 && target_lift > 0) {
|
||||
m_lifted = target_lift;
|
||||
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z");
|
||||
return this->_travel_to_z(m_pos.z() + target_lift, "lift Z");
|
||||
}
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string GCodeWriter::unlift()
|
||||
{
|
||||
std::string gcode;
|
||||
if (m_lifted > 0) {
|
||||
gcode += this->_travel_to_z(m_pos(2) - m_lifted, "restore layer Z");
|
||||
gcode += this->_travel_to_z(m_pos.z() - m_lifted, "restore layer Z");
|
||||
m_lifted = 0;
|
||||
}
|
||||
return gcode;
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
std::string travel_to_z(double z, const std::string &comment = std::string());
|
||||
bool will_move_z(double z) const;
|
||||
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string());
|
||||
std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string());
|
||||
// std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string());
|
||||
std::string retract(bool before_wipe = false);
|
||||
std::string retract_for_toolchange(bool before_wipe = false);
|
||||
std::string unretract();
|
||||
@ -121,6 +121,14 @@ public:
|
||||
// static constexpr const int E_EXPORT_DIGITS = 9;
|
||||
#endif
|
||||
|
||||
static constexpr const std::array<double, 10> pow_10 { 1., 10., 100., 1000., 10000., 100000., 1000000., 10000000., 100000000., 1000000000.};
|
||||
static constexpr const std::array<double, 10> pow_10_inv{1./1., 1./10., 1./100., 1./1000., 1./10000., 1./100000., 1./1000000., 1./10000000., 1./100000000., 1./1000000000.};
|
||||
|
||||
// Quantize doubles to a resolution of the G-code.
|
||||
static double quantize(double v, size_t ndigits) { return std::round(v * pow_10[ndigits]) * pow_10_inv[ndigits]; }
|
||||
static double quantize_xyzf(double v) { return quantize(v, XYZF_EXPORT_DIGITS); }
|
||||
static double quantize_e(double v) { return quantize(v, E_EXPORT_DIGITS); }
|
||||
|
||||
void emit_axis(const char axis, const double v, size_t digits);
|
||||
|
||||
void emit_xy(const Vec2d &point) {
|
||||
|
@ -325,40 +325,36 @@ Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>&
|
||||
// reference: http://www.gregslabaugh.net/publications/euler.pdf
|
||||
Vec3d angles1 = Vec3d::Zero();
|
||||
Vec3d angles2 = Vec3d::Zero();
|
||||
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5)
|
||||
{
|
||||
angles1(2) = 0.0;
|
||||
if (rotation_matrix(2, 0) < 0.0) // == -1.0
|
||||
{
|
||||
angles1(1) = 0.5 * (double)PI;
|
||||
angles1(0) = angles1(2) + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
|
||||
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5) {
|
||||
angles1.z() = 0.0;
|
||||
if (rotation_matrix(2, 0) < 0.0) { // == -1.0
|
||||
angles1.y() = 0.5 * double(PI);
|
||||
angles1.x() = angles1.z() + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
|
||||
}
|
||||
else // == 1.0
|
||||
{
|
||||
angles1(1) = - 0.5 * (double)PI;
|
||||
angles1(0) = - angles1(2) + ::atan2(- rotation_matrix(0, 1), - rotation_matrix(0, 2));
|
||||
else { // == 1.0
|
||||
angles1.y() = - 0.5 * double(PI);
|
||||
angles1.x() = - angles1.y() + ::atan2(- rotation_matrix(0, 1), - rotation_matrix(0, 2));
|
||||
}
|
||||
angles2 = angles1;
|
||||
}
|
||||
else
|
||||
{
|
||||
angles1(1) = -::asin(rotation_matrix(2, 0));
|
||||
double inv_cos1 = 1.0 / ::cos(angles1(1));
|
||||
angles1(0) = ::atan2(rotation_matrix(2, 1) * inv_cos1, rotation_matrix(2, 2) * inv_cos1);
|
||||
angles1(2) = ::atan2(rotation_matrix(1, 0) * inv_cos1, rotation_matrix(0, 0) * inv_cos1);
|
||||
else {
|
||||
angles1.y() = -::asin(rotation_matrix(2, 0));
|
||||
const double inv_cos1 = 1.0 / ::cos(angles1.y());
|
||||
angles1.x() = ::atan2(rotation_matrix(2, 1) * inv_cos1, rotation_matrix(2, 2) * inv_cos1);
|
||||
angles1.z() = ::atan2(rotation_matrix(1, 0) * inv_cos1, rotation_matrix(0, 0) * inv_cos1);
|
||||
|
||||
angles2(1) = (double)PI - angles1(1);
|
||||
double inv_cos2 = 1.0 / ::cos(angles2(1));
|
||||
angles2(0) = ::atan2(rotation_matrix(2, 1) * inv_cos2, rotation_matrix(2, 2) * inv_cos2);
|
||||
angles2(2) = ::atan2(rotation_matrix(1, 0) * inv_cos2, rotation_matrix(0, 0) * inv_cos2);
|
||||
angles2.y() = double(PI) - angles1.y();
|
||||
const double inv_cos2 = 1.0 / ::cos(angles2.y());
|
||||
angles2.x() = ::atan2(rotation_matrix(2, 1) * inv_cos2, rotation_matrix(2, 2) * inv_cos2);
|
||||
angles2.z() = ::atan2(rotation_matrix(1, 0) * inv_cos2, rotation_matrix(0, 0) * inv_cos2);
|
||||
}
|
||||
|
||||
// The following euristic is the best found up to now (in the sense that it works fine with the greatest number of edge use-cases)
|
||||
// but there are other use-cases were it does not
|
||||
// We need to improve it
|
||||
double min_1 = angles1.cwiseAbs().minCoeff();
|
||||
double min_2 = angles2.cwiseAbs().minCoeff();
|
||||
bool use_1 = (min_1 < min_2) || (is_approx(min_1, min_2) && (angles1.norm() <= angles2.norm()));
|
||||
const double min_1 = angles1.cwiseAbs().minCoeff();
|
||||
const double min_2 = angles2.cwiseAbs().minCoeff();
|
||||
const bool use_1 = (min_1 < min_2) || (is_approx(min_1, min_2) && (angles1.norm() <= angles2.norm()));
|
||||
|
||||
return use_1 ? angles1 : angles2;
|
||||
}
|
||||
@ -374,14 +370,6 @@ Vec3d extract_euler_angles(const Transform3d& transform)
|
||||
return extract_euler_angles(m);
|
||||
}
|
||||
|
||||
Transformation::Flags::Flags()
|
||||
: dont_translate(true)
|
||||
, dont_rotate(true)
|
||||
, dont_scale(true)
|
||||
, dont_mirror(true)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
@ -407,15 +395,14 @@ Transformation::Transformation(const Transform3d& transform)
|
||||
|
||||
void Transformation::set_offset(const Vec3d& offset)
|
||||
{
|
||||
set_offset(X, offset(0));
|
||||
set_offset(Y, offset(1));
|
||||
set_offset(Z, offset(2));
|
||||
set_offset(X, offset.x());
|
||||
set_offset(Y, offset.y());
|
||||
set_offset(Z, offset.z());
|
||||
}
|
||||
|
||||
void Transformation::set_offset(Axis axis, double offset)
|
||||
{
|
||||
if (m_offset(axis) != offset)
|
||||
{
|
||||
if (m_offset(axis) != offset) {
|
||||
m_offset(axis) = offset;
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -423,19 +410,18 @@ void Transformation::set_offset(Axis axis, double offset)
|
||||
|
||||
void Transformation::set_rotation(const Vec3d& rotation)
|
||||
{
|
||||
set_rotation(X, rotation(0));
|
||||
set_rotation(Y, rotation(1));
|
||||
set_rotation(Z, rotation(2));
|
||||
set_rotation(X, rotation.x());
|
||||
set_rotation(Y, rotation.y());
|
||||
set_rotation(Z, rotation.z());
|
||||
}
|
||||
|
||||
void Transformation::set_rotation(Axis axis, double rotation)
|
||||
{
|
||||
rotation = angle_to_0_2PI(rotation);
|
||||
if (is_approx(std::abs(rotation), 2.0 * (double)PI))
|
||||
if (is_approx(std::abs(rotation), 2.0 * double(PI)))
|
||||
rotation = 0.0;
|
||||
|
||||
if (m_rotation(axis) != rotation)
|
||||
{
|
||||
if (m_rotation(axis) != rotation) {
|
||||
m_rotation(axis) = rotation;
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -443,15 +429,14 @@ void Transformation::set_rotation(Axis axis, double rotation)
|
||||
|
||||
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
|
||||
{
|
||||
set_scaling_factor(X, scaling_factor(0));
|
||||
set_scaling_factor(Y, scaling_factor(1));
|
||||
set_scaling_factor(Z, scaling_factor(2));
|
||||
set_scaling_factor(X, scaling_factor.x());
|
||||
set_scaling_factor(Y, scaling_factor.y());
|
||||
set_scaling_factor(Z, scaling_factor.z());
|
||||
}
|
||||
|
||||
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
||||
{
|
||||
if (m_scaling_factor(axis) != std::abs(scaling_factor))
|
||||
{
|
||||
if (m_scaling_factor(axis) != std::abs(scaling_factor)) {
|
||||
m_scaling_factor(axis) = std::abs(scaling_factor);
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -459,9 +444,9 @@ void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
|
||||
|
||||
void Transformation::set_mirror(const Vec3d& mirror)
|
||||
{
|
||||
set_mirror(X, mirror(0));
|
||||
set_mirror(Y, mirror(1));
|
||||
set_mirror(Z, mirror(2));
|
||||
set_mirror(X, mirror.x());
|
||||
set_mirror(Y, mirror.y());
|
||||
set_mirror(Z, mirror.z());
|
||||
}
|
||||
|
||||
void Transformation::set_mirror(Axis axis, double mirror)
|
||||
@ -472,8 +457,7 @@ void Transformation::set_mirror(Axis axis, double mirror)
|
||||
else if (abs_mirror != 1.0)
|
||||
mirror /= abs_mirror;
|
||||
|
||||
if (m_mirror(axis) != mirror)
|
||||
{
|
||||
if (m_mirror(axis) != mirror) {
|
||||
m_mirror(axis) = mirror;
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -491,9 +475,8 @@ void Transformation::set_from_transform(const Transform3d& transform)
|
||||
// we can only detect if the matrix contains a left handed reference system
|
||||
// in which case we reorient it back to right handed by mirroring the x axis
|
||||
Vec3d mirror = Vec3d::Ones();
|
||||
if (m3x3.col(0).dot(m3x3.col(1).cross(m3x3.col(2))) < 0.0)
|
||||
{
|
||||
mirror(0) = -1.0;
|
||||
if (m3x3.col(0).dot(m3x3.col(1).cross(m3x3.col(2))) < 0.0) {
|
||||
mirror.x() = -1.0;
|
||||
// remove mirror
|
||||
m3x3.col(0) *= -1.0;
|
||||
}
|
||||
@ -530,8 +513,7 @@ void Transformation::reset()
|
||||
|
||||
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))
|
||||
{
|
||||
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) {
|
||||
m_matrix = Geometry::assemble_transform(
|
||||
dont_translate ? Vec3d::Zero() : m_offset,
|
||||
dont_rotate ? Vec3d::Zero() : m_rotation,
|
||||
@ -560,8 +542,7 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
|
||||
// Just set the inverse.
|
||||
out.set_from_transform(instance_transformation.get_matrix(true).inverse());
|
||||
}
|
||||
else if (is_rotation_ninety_degrees(instance_transformation.get_rotation()))
|
||||
{
|
||||
else if (is_rotation_ninety_degrees(instance_transformation.get_rotation())) {
|
||||
// Anisotropic scaling, rotation by multiples of ninety degrees.
|
||||
Eigen::Matrix3d instance_rotation_trafo =
|
||||
(Eigen::AngleAxisd(instance_transformation.get_rotation().z(), Vec3d::UnitZ()) *
|
||||
@ -594,8 +575,8 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
|
||||
scale(i) = pts.col(i).dot(qs.col(i)) / pts.col(i).dot(pts.col(i));
|
||||
|
||||
out.set_rotation(Geometry::extract_euler_angles(volume_rotation_trafo));
|
||||
out.set_scaling_factor(Vec3d(std::abs(scale(0)), std::abs(scale(1)), std::abs(scale(2))));
|
||||
out.set_mirror(Vec3d(scale(0) > 0 ? 1. : -1, scale(1) > 0 ? 1. : -1, scale(2) > 0 ? 1. : -1));
|
||||
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
|
||||
{
|
||||
@ -614,19 +595,15 @@ Transform3d transform3d_from_string(const std::string& transform_str)
|
||||
assert(is_decimal_separator_point()); // for atof
|
||||
Transform3d transform = Transform3d::Identity();
|
||||
|
||||
if (!transform_str.empty())
|
||||
{
|
||||
if (!transform_str.empty()) {
|
||||
std::vector<std::string> mat_elements_str;
|
||||
boost::split(mat_elements_str, transform_str, boost::is_any_of(" "), boost::token_compress_on);
|
||||
|
||||
unsigned int size = (unsigned int)mat_elements_str.size();
|
||||
if (size == 16)
|
||||
{
|
||||
const unsigned int size = (unsigned int)mat_elements_str.size();
|
||||
if (size == 16) {
|
||||
unsigned int i = 0;
|
||||
for (unsigned int r = 0; r < 4; ++r)
|
||||
{
|
||||
for (unsigned int c = 0; c < 4; ++c)
|
||||
{
|
||||
for (unsigned int r = 0; r < 4; ++r) {
|
||||
for (unsigned int c = 0; c < 4; ++c) {
|
||||
transform(r, c) = ::atof(mat_elements_str[i++].c_str());
|
||||
}
|
||||
}
|
||||
@ -640,17 +617,17 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
|
||||
{
|
||||
return
|
||||
// From the current coordinate system to world.
|
||||
Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
|
||||
Eigen::AngleAxisd(rot_xyz_to.z(), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to.x(), Vec3d::UnitX()) *
|
||||
// From world to the initial coordinate system.
|
||||
Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
|
||||
Eigen::AngleAxisd(-rot_xyz_from.x(), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from.z(), Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
Vec3d axis = angle_axis.axis();
|
||||
double angle = angle_axis.angle();
|
||||
const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
const Vec3d axis = angle_axis.axis();
|
||||
const double angle = angle_axis.angle();
|
||||
#ifndef NDEBUG
|
||||
if (std::abs(angle) > 1e-8) {
|
||||
assert(std::abs(axis.x()) < 1e-8);
|
||||
|
@ -347,25 +347,23 @@ class Transformation
|
||||
{
|
||||
struct Flags
|
||||
{
|
||||
bool dont_translate;
|
||||
bool dont_rotate;
|
||||
bool dont_scale;
|
||||
bool dont_mirror;
|
||||
|
||||
Flags();
|
||||
bool dont_translate{ true };
|
||||
bool dont_rotate{ true };
|
||||
bool dont_scale{ true };
|
||||
bool dont_mirror{ true };
|
||||
|
||||
bool needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const;
|
||||
void set(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror);
|
||||
};
|
||||
|
||||
Vec3d m_offset; // In unscaled coordinates
|
||||
Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point
|
||||
Vec3d m_scaling_factor; // Scaling factors along the three axes
|
||||
Vec3d m_mirror; // Mirroring along the three axes
|
||||
Vec3d m_offset{ Vec3d::Zero() }; // In unscaled coordinates
|
||||
Vec3d m_rotation{ Vec3d::Zero() }; // Rotation around the three axes, in radians around mesh center point
|
||||
Vec3d m_scaling_factor{ Vec3d::Ones() }; // Scaling factors along the three axes
|
||||
Vec3d m_mirror{ Vec3d::Ones() }; // Mirroring along the three axes
|
||||
|
||||
mutable Transform3d m_matrix;
|
||||
mutable Transform3d m_matrix{ Transform3d::Identity() };
|
||||
mutable Flags m_flags;
|
||||
mutable bool m_dirty;
|
||||
mutable bool m_dirty{ false };
|
||||
|
||||
public:
|
||||
Transformation();
|
||||
@ -435,7 +433,7 @@ extern double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to
|
||||
// Is the angle close to a multiple of 90 degrees?
|
||||
inline bool is_rotation_ninety_degrees(double a)
|
||||
{
|
||||
a = fmod(std::abs(a), 0.5 * M_PI);
|
||||
a = fmod(std::abs(a), 0.5 * PI);
|
||||
if (a > 0.25 * PI)
|
||||
a = 0.5 * PI - a;
|
||||
return a < 0.001;
|
||||
|
@ -105,6 +105,11 @@ public:
|
||||
|
||||
static inline Int128 multiply(int64_t lhs, int64_t rhs) { return Int128(__int128(lhs) * __int128(rhs)); }
|
||||
|
||||
#if defined(__clang__)
|
||||
// When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
|
||||
// Because of that, UndefinedBehaviorSanitizer is disabled for this function.
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#endif
|
||||
// Evaluate signum of a 2x2 determinant.
|
||||
static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <charconv>
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <fast_float/fast_float.h>
|
||||
|
||||
|
@ -2264,7 +2264,7 @@ void check_model_ids_validity(const Model &model)
|
||||
for (const ModelInstance *model_instance : model_object->instances)
|
||||
check(model_instance->id());
|
||||
}
|
||||
for (const auto mm : model.materials) {
|
||||
for (const auto &mm : model.materials) {
|
||||
check(mm.second->id());
|
||||
check(mm.second->config.id());
|
||||
}
|
||||
|
@ -17,7 +17,8 @@ class MultiPoint
|
||||
public:
|
||||
Points points;
|
||||
|
||||
MultiPoint() {}
|
||||
MultiPoint() = default;
|
||||
virtual ~MultiPoint() = default;
|
||||
MultiPoint(const MultiPoint &other) : points(other.points) {}
|
||||
MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {}
|
||||
MultiPoint(std::initializer_list<Point> list) : points(list) {}
|
||||
|
@ -501,6 +501,7 @@ namespace client
|
||||
boost::throw_exception(qi::expectation_failure<Iterator>(
|
||||
lhs.it_range.begin(), rhs.it_range.end(), spirit::info("*Cannot compare the types.")));
|
||||
}
|
||||
lhs.reset();
|
||||
lhs.type = TYPE_BOOL;
|
||||
lhs.data.b = invert ? ! value : value;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class Polygon : public MultiPoint
|
||||
{
|
||||
public:
|
||||
Polygon() = default;
|
||||
virtual ~Polygon() = default;
|
||||
~Polygon() override = default;
|
||||
explicit Polygon(const Points &points) : MultiPoint(points) {}
|
||||
Polygon(std::initializer_list<Point> points) : MultiPoint(points) {}
|
||||
Polygon(const Polygon &other) : MultiPoint(other.points) {}
|
||||
|
@ -16,7 +16,8 @@ typedef std::vector<ThickPolyline> ThickPolylines;
|
||||
|
||||
class Polyline : public MultiPoint {
|
||||
public:
|
||||
Polyline() {};
|
||||
Polyline() = default;
|
||||
~Polyline() override = default;
|
||||
Polyline(const Polyline &other) : MultiPoint(other.points) {}
|
||||
Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {}
|
||||
Polyline(std::initializer_list<Point> list) : MultiPoint(list) {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user