Merge branch 'master' into fs_mouse

# Conflicts:
#	src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
#	src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
This commit is contained in:
Filip Sykala 2022-02-08 10:43:29 +01:00
commit 0c40e2f8c8
201 changed files with 259341 additions and 50166 deletions

View File

@ -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()

View File

@ -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

View File

@ -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}"

View File

@ -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
View 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

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
min_slic3r_version = 2.4.1-alpha
1.0.0 Initial Jubilee bundle

View 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

Binary file not shown.

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -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

View File

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 1.4.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+

View File

@ -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

View File

@ -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

View 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);
}

View File

@ -0,0 +1,9 @@
#version 110
varying vec2 tex_coord;
void main()
{
gl_Position = gl_Vertex;
tex_coord = gl_MultiTexCoord0.xy;
}

View File

@ -0,0 +1,10 @@
#version 110
uniform sampler2D uniform_texture;
varying vec2 tex_coord;
void main()
{
gl_FragColor = texture2D(uniform_texture, tex_coord);
}

View File

@ -0,0 +1,9 @@
#version 110
varying vec2 tex_coord;
void main()
{
gl_Position = ftransform();
tex_coord = gl_MultiTexCoord0.xy;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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");
}

View File

@ -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)

View File

@ -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 }; }

View File

@ -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;
}

View File

@ -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.

View File

@ -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_

View File

@ -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()

View File

@ -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__

View File

@ -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)

View File

@ -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);

View File

@ -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";

View File

@ -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();

View File

@ -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);

View 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

View 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

View File

@ -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

View File

@ -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; }

View File

@ -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)

View File

@ -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;
};

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;

View 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

View 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_

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -4,6 +4,7 @@
#include <charconv>
#endif
#include <stdexcept>
#include <sstream>
#include <fast_float/fast_float.h>

View File

@ -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());
}

View File

@ -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) {}

View File

@ -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;
}

View File

@ -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) {}

View File

@ -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