Merge branch 'master' into fs_emboss
This commit is contained in:
commit
ab30d37c3c
@ -1,3 +1,5 @@
|
||||
min_slic3r_version = 2.6.0-alpha4
|
||||
1.1.1 Initial official version
|
||||
1.0.1 Initial Version
|
||||
min_slic3r_version = 2.6.0-alpha1
|
||||
1.0.1 Disabled thick bridges.
|
||||
1.0.0 Initial Version
|
||||
|
@ -1,14 +1,14 @@
|
||||
# Print profiles for the AnkerMake printers.
|
||||
# https://github.com/prusa3d/PrusaSlicer/pull/9075 by @just-trey
|
||||
|
||||
[vendor]
|
||||
# Vendor name will be shown by the Config Wizard.
|
||||
name = Anker
|
||||
name = AnkerMake
|
||||
# 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.0.1
|
||||
config_version = 1.1.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anker/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
|
||||
# The printer models will be shown by the Configuration Wizard in this order,
|
||||
# also the first model installed & the first nozzle installed will be activated after install.
|
||||
@ -20,8 +20,9 @@ variants = 0.4
|
||||
technology = FFF
|
||||
family = AnkerMake
|
||||
bed_model = M5-bed.stl
|
||||
bed_texture = M5-texture.svg
|
||||
default_materials = Generic PLA+ @ANKER; Generic PLA @ANKER; Generic PET @ANKER; Generic ABS @ANKER
|
||||
bed_texture = M5-texture_v2.svg
|
||||
thumbnail = M5_thumbnail_v2.png
|
||||
default_materials = Generic PLA+ @ANKER; Generic PLA @ANKER; Generic PET @ANKER; Generic ABS @ANKER;
|
||||
|
||||
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||
# not make it into the user interface.
|
||||
@ -31,8 +32,8 @@ default_materials = Generic PLA+ @ANKER; Generic PLA @ANKER; Generic PET @ANKER;
|
||||
avoid_crossing_perimeters = 0
|
||||
bridge_acceleration = 2500
|
||||
bridge_angle = 0
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 150
|
||||
bridge_flow_ratio = 1
|
||||
bridge_speed = 50
|
||||
brim_separation = 0.1
|
||||
brim_type = outer_only
|
||||
brim_width = 0
|
||||
@ -40,32 +41,36 @@ clip_multipart_objects = 1
|
||||
complete_objects = 0
|
||||
default_acceleration = 2500
|
||||
dont_support_bridges = 1
|
||||
elefant_foot_compensation = 0.1
|
||||
elefant_foot_compensation = 0.2
|
||||
ensure_vertical_shell_thickness = 1
|
||||
external_perimeter_speed = 150
|
||||
external_perimeters_first = 0
|
||||
extra_perimeters = 0
|
||||
extruder_clearance_height = 30
|
||||
extruder_clearance_radius = 45
|
||||
extrusion_width = 0.4
|
||||
external_perimeter_extrusion_width = 0.44
|
||||
|
||||
fill_angle = 45
|
||||
fill_density = 15%
|
||||
fill_pattern = cubic
|
||||
fill_density = 10%
|
||||
fill_pattern = grid
|
||||
first_layer_acceleration = 2500
|
||||
first_layer_acceleration_over_raft = 0
|
||||
first_layer_extrusion_width = 200%
|
||||
first_layer_extrusion_width = 0.4
|
||||
first_layer_speed = 50%
|
||||
first_layer_speed_over_raft = 30
|
||||
gap_fill_enabled = 1
|
||||
gap_fill_speed = 150
|
||||
gcode_comments = 0
|
||||
infill_acceleration = 2500
|
||||
infill_anchor = 600%
|
||||
infill_anchor_max = 50
|
||||
infill_anchor = 2.5
|
||||
infill_anchor_max = 12
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_first = 0
|
||||
infill_extrusion_width = 0.4
|
||||
infill_only_where_needed = 0
|
||||
infill_overlap = 23%
|
||||
infill_overlap = 10%
|
||||
infill_speed = 250
|
||||
interface_shells = 0
|
||||
max_print_speed = 250
|
||||
@ -76,18 +81,18 @@ min_skirt_length = 4
|
||||
notes =
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = {input_filename_base}_{digits(layer_height,1,2)}mm_{filament_type[0]}_{printer_model}.gcode
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{initial_filament_type}_{printer_model}.gcode
|
||||
overhangs = 1
|
||||
perimeter_acceleration = 2500
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0
|
||||
perimeter_generator = arachne
|
||||
perimeter_extrusion_width = 0.4
|
||||
perimeter_generator = classic
|
||||
perimeter_speed = 250
|
||||
perimeters = 3
|
||||
post_process =
|
||||
print_settings_id =
|
||||
raft_layers = 0
|
||||
resolution = 0
|
||||
resolution = 0.01
|
||||
seam_position = aligned
|
||||
single_extruder_multi_material_priming = 0
|
||||
skirt_distance = 3
|
||||
@ -97,32 +102,37 @@ small_perimeter_speed = 150
|
||||
solid_infill_below_area = 0
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_speed = 175
|
||||
solid_infill_extrusion_width = 0.4
|
||||
solid_infill_speed = 250
|
||||
spiral_vase = 0
|
||||
standby_temperature_delta = -5
|
||||
support_material_auto = 0
|
||||
support_material = 0
|
||||
support_material_angle = 0
|
||||
support_material_buildplate_only = 0
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_contact_distance = 0.1
|
||||
support_material_enforce_layers = 0
|
||||
support_material_extruder = 0
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_extruder = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_interface_spacing = 0.2
|
||||
support_material_interface_speed = 100%
|
||||
support_material_interface_speed = 80%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2
|
||||
support_material_speed = 125
|
||||
support_material_speed = 150
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 40
|
||||
support_material_threshold = 55
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 60%
|
||||
support_material_xy_spacing = 50%
|
||||
thick_bridges = 0
|
||||
thin_walls = 0
|
||||
top_solid_infill_speed = 150
|
||||
travel_speed = 300
|
||||
travel_speed_z = 10
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_fill_pattern = rectilinear
|
||||
bottom_fill_pattern = rectilinear
|
||||
travel_speed = 250
|
||||
travel_speed_z = 0
|
||||
wipe_tower = 0
|
||||
wipe_tower_bridging = 10
|
||||
wipe_tower_rotation_angle = 0
|
||||
@ -131,86 +141,49 @@ wipe_tower_x = 170
|
||||
wipe_tower_y = 140
|
||||
xy_size_compensation = 0
|
||||
|
||||
[print:*0.08mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.08
|
||||
first_layer_height = 0.12
|
||||
bottom_solid_layers = 9
|
||||
top_solid_layers = 11
|
||||
bridge_flow_ratio = 0.70
|
||||
|
||||
[print:*0.10mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.10
|
||||
first_layer_height = 0.14
|
||||
first_layer_height = 0.10
|
||||
bottom_solid_layers = 7
|
||||
top_solid_layers = 9
|
||||
bridge_flow_ratio = 0.70
|
||||
|
||||
[print:*0.12mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.12
|
||||
first_layer_height = 0.16
|
||||
bottom_solid_layers = 6
|
||||
top_solid_layers = 7
|
||||
bridge_flow_ratio = 0.70
|
||||
|
||||
[print:*0.16mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.16
|
||||
first_layer_height = 0.20
|
||||
bottom_solid_layers = 5
|
||||
top_solid_layers = 7
|
||||
bridge_flow_ratio = 0.85
|
||||
bridge_flow_ratio = 1
|
||||
|
||||
[print:*0.20mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.20
|
||||
first_layer_height = 0.24
|
||||
first_layer_height = 0.14
|
||||
bottom_solid_layers = 4
|
||||
top_solid_layers = 5
|
||||
|
||||
[print:*0.24mm*]
|
||||
[print:*0.30mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.24
|
||||
first_layer_height = 0.28
|
||||
layer_height = 0.30
|
||||
first_layer_height = 0.21
|
||||
bottom_solid_layers = 3
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:*0.28mm*]
|
||||
inherits = *common*
|
||||
layer_height = 0.28
|
||||
first_layer_height = 0.28
|
||||
bottom_solid_layers = 3
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:0.08 mm SUPERDETAIL (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.08mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.10 mm HIGHDETAIL (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.10mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.12 mm DETAIL (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.12mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.16 mm OPTIMAL (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.16mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.20 mm NORMAL (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.20mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.24 mm DRAFT (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.24mm*
|
||||
|
||||
[print:0.30 mm SUPERDRAFT (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.30mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
|
||||
[print:0.28 mm SUPERDRAFT (0.4 mm nozzle) @ANKER]
|
||||
inherits = *0.28mm*
|
||||
compatible_printers_condition = printer_model=~/(M5).*/ and nozzle_diameter[0]==0.4
|
||||
# When submitting new filaments please print the following temperature tower at 0.1mm layer height:
|
||||
# https://www.thingiverse.com/thing:2615842
|
||||
# Pay particular attention to bridging, overhangs and retractions.
|
||||
# Also print the following bed adhesion test at 0.1 layer height as well:
|
||||
# https://www.prusaprinters.org/prints/4634-bed-adhesion-warp-test
|
||||
# At least for PLA, please keep bed temp at 60, as many Creality printers do not have any ABL
|
||||
# So having some leeway to get good bed adhesion is not a luxury for many users
|
||||
|
||||
[filament:*common*]
|
||||
cooling = 0
|
||||
@ -235,47 +208,47 @@ filament_type = PLA
|
||||
filament_density = 1.24
|
||||
filament_cost = 20
|
||||
first_layer_bed_temperature = 60
|
||||
first_layer_temperature = 210
|
||||
first_layer_temperature = 230
|
||||
fan_always_on = 1
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 2
|
||||
temperature = 205
|
||||
disable_fan_first_layers = 1
|
||||
temperature = 200
|
||||
|
||||
[filament:*PLA+*]
|
||||
inherits = *common*
|
||||
bed_temperature = 60
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #DDDDDD
|
||||
filament_type = PLA
|
||||
filament_type = PLA+
|
||||
filament_density = 1.24
|
||||
filament_cost = 20
|
||||
first_layer_bed_temperature = 60
|
||||
first_layer_temperature = 220
|
||||
first_layer_temperature = 230
|
||||
fan_always_on = 1
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
bridge_fan_speed = 100
|
||||
disable_fan_first_layers = 2
|
||||
temperature = 210
|
||||
disable_fan_first_layers = 1
|
||||
temperature = 200
|
||||
|
||||
[filament:*PET*]
|
||||
inherits = *common*
|
||||
bed_temperature = 70
|
||||
bed_temperature = 80
|
||||
disable_fan_first_layers = 2
|
||||
fan_below_layer_time = 20
|
||||
filament_colour = #DDDDDD
|
||||
filament_type = PETG
|
||||
filament_density = 1.27
|
||||
filament_cost = 30
|
||||
first_layer_bed_temperature = 70
|
||||
first_layer_temperature = 240
|
||||
first_layer_bed_temperature = 80
|
||||
first_layer_temperature = 260
|
||||
fan_always_on = 1
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 50
|
||||
bridge_fan_speed = 100
|
||||
temperature = 240
|
||||
temperature = 260
|
||||
|
||||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
@ -286,14 +259,14 @@ filament_colour = #DDDDDD
|
||||
filament_type = ABS
|
||||
filament_density = 1.04
|
||||
filament_cost = 20
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 245
|
||||
first_layer_bed_temperature = 90
|
||||
first_layer_temperature = 260
|
||||
fan_always_on = 0
|
||||
max_fan_speed = 0
|
||||
min_fan_speed = 0
|
||||
bridge_fan_speed = 30
|
||||
top_fan_speed = 0
|
||||
temperature = 245
|
||||
temperature = 260
|
||||
|
||||
[filament:Generic PLA @ANKER]
|
||||
inherits = *PLA*
|
||||
@ -324,8 +297,8 @@ deretract_speed = 60
|
||||
extruder_colour = #FCE94F
|
||||
extruder_offset = 0x0
|
||||
gcode_flavor = marlin
|
||||
silent_mode = 0
|
||||
remaining_times = 0
|
||||
silent_mode = 1
|
||||
remaining_times = 1
|
||||
machine_max_acceleration_e = 2500
|
||||
machine_max_acceleration_extruding = 2500
|
||||
machine_max_acceleration_retracting = 2500
|
||||
@ -338,8 +311,8 @@ machine_max_feedrate_x = 300
|
||||
machine_max_feedrate_y = 300
|
||||
machine_max_feedrate_z = 20
|
||||
machine_max_jerk_e = 3
|
||||
machine_max_jerk_x = 30
|
||||
machine_max_jerk_y = 30
|
||||
machine_max_jerk_x = 15
|
||||
machine_max_jerk_y = 15
|
||||
machine_max_jerk_z = 0.3
|
||||
machine_min_extruding_rate = 0
|
||||
machine_min_travel_rate = 0
|
||||
@ -347,10 +320,10 @@ layer_gcode = ;AFTER_LAYER_CHANGE\n;{layer_z}
|
||||
max_print_height = 250
|
||||
printer_notes =
|
||||
printer_settings_id =
|
||||
retract_before_travel = 2
|
||||
retract_before_wipe = 70%
|
||||
retract_before_travel = 3
|
||||
retract_before_wipe = 0
|
||||
retract_layer_change = 1
|
||||
retract_length_toolchange = 1
|
||||
retract_length_toolchange = 4
|
||||
retract_lift = 0
|
||||
retract_lift_above = 0
|
||||
retract_lift_below = 0
|
||||
@ -365,10 +338,10 @@ use_firmware_retraction = 0
|
||||
use_relative_e_distances = 0
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 1
|
||||
wipe = 1
|
||||
wipe = 0
|
||||
z_offset = 0
|
||||
default_filament_profile = "Generic PLA+ @ANKER"
|
||||
start_gcode = M104 S{first_layer_temperature[0]} ; set final nozzle temp\nM190 S{first_layer_bed_temperature[0]} ; set and wait for nozzle temp to stabilize\nM109 S{first_layer_temperature[0]} ; wait for nozzle temp to stabilize\nG28 ;Home\nG1 E10 F3600; push out retracted filament(fix for over retraction after prime)
|
||||
default_filament_profile = Generic PLA+ @ANKER
|
||||
start_gcode = M104 S{first_layer_temperature[0]} ; set final nozzle temp\nM190 S{first_layer_bed_temperature[0]} ; set and wait for bed temp to stabilize\nM109 S{first_layer_temperature[0]} ; wait for nozzle temp to stabilize\nG28 ;Home\nM420 S1; restore saved Auto Bed Leveling data\nG1 E10 F3600; push out retracted filament(fix for over retraction after prime)
|
||||
end_gcode = M104 S0\nM140 S0\n;Retract the filament\nG92 E1\nG1 E-1 F300\nG28 X0 Y0\nM84
|
||||
|
||||
[printer:*M5*]
|
||||
@ -376,12 +349,12 @@ inherits = *common*
|
||||
bed_shape = 0x0,235-0,235x235,0x235
|
||||
max_print_height = 250
|
||||
printer_model = M5
|
||||
retract_length = 1.25
|
||||
retract_length = 3
|
||||
retract_speed = 60
|
||||
deretract_speed = 60
|
||||
retract_before_travel = 1
|
||||
retract_before_travel = 3
|
||||
retract_before_wipe = 0%
|
||||
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_ANKERMAKE\nPRINTER_MODEL_M5
|
||||
printer_notes = Don not 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_ANKERMAKE\nPRINTER_MODEL_M5
|
||||
|
||||
[printer:AnkerMake M5 (0.4 mm nozzle)]
|
||||
inherits = *M5*
|
||||
@ -389,5 +362,5 @@ nozzle_diameter = 0.4
|
||||
printer_variant = 0.4
|
||||
min_layer_height = 0.08
|
||||
max_layer_height = 0.32
|
||||
retract_lift_above = 0.2
|
||||
default_print_profile = "0.16 mm OPTIMAL (0.4 mm nozzle) @ANKER"
|
||||
retract_lift_above = 0
|
||||
default_print_profile = 0.2 mm OPTIMAL (0.4 mm nozzle) @ANKER
|
||||
|
1
resources/profiles/Anker/M5-texture_v2.svg
Normal file
1
resources/profiles/Anker/M5-texture_v2.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 17 KiB |
BIN
resources/profiles/Anker/M5_thumbnail_v2.png
Normal file
BIN
resources/profiles/Anker/M5_thumbnail_v2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -957,7 +957,7 @@ namespace Slic3r {
|
||||
|
||||
try
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
res = mz_zip_reader_extract_to_callback(&archive, stat.m_file_index, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->importer.parse_error()) {
|
||||
char error_buf[1024];
|
||||
@ -991,7 +991,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading cut information data to buffer");
|
||||
return;
|
||||
@ -1053,7 +1053,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading config data to buffer");
|
||||
return;
|
||||
@ -1073,7 +1073,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading layer heights profile data to buffer");
|
||||
return;
|
||||
@ -1135,7 +1135,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading layer config ranges data to buffer");
|
||||
return;
|
||||
@ -1192,7 +1192,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading sla support points data to buffer");
|
||||
return;
|
||||
@ -1274,7 +1274,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer(size_t(stat.m_uncomp_size), 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading sla support points data to buffer");
|
||||
return;
|
||||
@ -1379,7 +1379,7 @@ namespace Slic3r {
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading config data to buffer");
|
||||
return false;
|
||||
@ -1399,7 +1399,7 @@ namespace Slic3r {
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading custom Gcodes per height data to buffer");
|
||||
return;
|
||||
|
@ -965,7 +965,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
|
||||
|
||||
try
|
||||
{
|
||||
res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
res = mz_zip_reader_extract_to_callback(&archive, stat.m_file_index, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t {
|
||||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->ctx.error())
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
|
||||
{
|
||||
std::string buf(size_t(entry.m_uncomp_size), '\0');
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
if (!mz_zip_reader_extract_to_mem(&zip.arch, entry.m_file_index,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
@ -35,7 +35,7 @@ EntryBuffer read_entry(const mz_zip_archive_file_stat &entry,
|
||||
{
|
||||
std::vector<uint8_t> buf(entry.m_uncomp_size);
|
||||
|
||||
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
|
||||
if (!mz_zip_reader_extract_to_mem(&zip.arch, entry.m_file_index,
|
||||
buf.data(), buf.size(), 0))
|
||||
throw Slic3r::FileIOError(zip.get_errorstr());
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "Layer.hpp"
|
||||
#include "ClipperZUtils.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "Print.hpp"
|
||||
#include "Fill/Fill.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "SVG.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "clipper/clipper.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
@ -180,6 +183,31 @@ static void connect_layer_slices(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// The check above might sometimes fail when the polygons overlap only on points, which causes the clipper to detect no intersection.
|
||||
// The problem happens rarely, mostly on simple polygons (in terms of number of points), but regardless of size!
|
||||
// example of failing link on two layers, each with single polygon without holes.
|
||||
// layer A = Polygon{(-24931238,-11153865),(-22504249,-8726874),(-22504249,11477151),(-23261469,12235585),(-23752371,12727276),(-25002495,12727276),(-27502745,10227026),(-27502745,-12727274),(-26504645,-12727274)}
|
||||
// layer B = Polygon{(-24877897,-11100524),(-22504249,-8726874),(-22504249,11477151),(-23244827,12218916),(-23752371,12727276),(-25002495,12727276),(-27502745,10227026),(-27502745,-12727274),(-26504645,-12727274)}
|
||||
// note that first point is not identical, and the check above picks (-24877897,-11100524) as the first contour point (polynode.Contour.front()).
|
||||
// that point is sadly slightly outisde of the layer A, so no link is detected, eventhough they are overlaping "completely"
|
||||
Polygon contour_poly;
|
||||
for (const auto& p : polynode.Contour) {
|
||||
contour_poly.points.emplace_back(p.x(), p.y());
|
||||
}
|
||||
BoundingBox contour_aabb{contour_poly.points};
|
||||
for (int l = int(m_above.lslices_ex.size()) - 1; l >= 0; --l) {
|
||||
LayerSlice &lslice = m_above.lslices_ex[l];
|
||||
// it is potentially slow, but should be executed rarely
|
||||
if (contour_aabb.overlap(lslice.bbox) && !intersection(Polygons{contour_poly}, m_above.lslices[l]).empty()) {
|
||||
found = true;
|
||||
j = l;
|
||||
assert(i >= 0 && i < m_below.lslices_ex.size());
|
||||
assert(j >= 0 && j < m_above.lslices_ex.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Index of an island above. Look-it up in the island below.
|
||||
assert(j < m_offset_end);
|
||||
@ -194,6 +222,23 @@ static void connect_layer_slices(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) { // Explanation for aditional check is above.
|
||||
Polygon contour_poly;
|
||||
for (const auto &p : polynode.Contour) {
|
||||
contour_poly.points.emplace_back(p.x(), p.y());
|
||||
}
|
||||
BoundingBox contour_aabb{contour_poly.points};
|
||||
for (int l = int(m_below.lslices_ex.size()) - 1; l >= 0; --l) {
|
||||
LayerSlice &lslice = m_below.lslices_ex[l];
|
||||
if (contour_aabb.overlap(lslice.bbox) && !intersection(Polygons{contour_poly}, m_below.lslices[l]).empty()) {
|
||||
found = true;
|
||||
i = l;
|
||||
assert(i >= 0 && i < m_below.lslices_ex.size());
|
||||
assert(j >= 0 && j < m_above.lslices_ex.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(assert_intersection_valid(i, j));
|
||||
|
@ -171,8 +171,13 @@ namespace client
|
||||
struct OptWithPos {
|
||||
OptWithPos() {}
|
||||
OptWithPos(ConfigOptionConstPtr opt, boost::iterator_range<Iterator> it_range) : opt(opt), it_range(it_range) {}
|
||||
ConfigOptionConstPtr opt = nullptr;
|
||||
ConfigOptionConstPtr opt { nullptr };
|
||||
bool writable { false };
|
||||
// -1 means it is a scalar variable, or it is a vector variable and index was not assigned yet or the whole vector is considered.
|
||||
int index { -1 };
|
||||
boost::iterator_range<Iterator> it_range;
|
||||
|
||||
bool has_index() const { return index != -1; }
|
||||
};
|
||||
|
||||
template<typename ITERATOR>
|
||||
@ -688,6 +693,7 @@ namespace client
|
||||
const DynamicConfig *external_config = nullptr;
|
||||
const DynamicConfig *config = nullptr;
|
||||
const DynamicConfig *config_override = nullptr;
|
||||
mutable DynamicConfig *config_outputs = nullptr;
|
||||
size_t current_extruder_id = 0;
|
||||
PlaceholderParser::ContextData *context_data = nullptr;
|
||||
// If false, the macro_processor will evaluate a full macro.
|
||||
@ -713,6 +719,7 @@ namespace client
|
||||
}
|
||||
|
||||
const ConfigOption* resolve_symbol(const std::string &opt_key) const { return this->optptr(opt_key); }
|
||||
ConfigOption* resolve_output_symbol(const std::string &opt_key) const { return this->config_outputs ? this->config_outputs->optptr(opt_key, false) : nullptr; }
|
||||
|
||||
template <typename Iterator>
|
||||
static void legacy_variable_expansion(
|
||||
@ -788,130 +795,213 @@ namespace client
|
||||
OptWithPos<Iterator> &output)
|
||||
{
|
||||
const ConfigOption *opt = ctx->resolve_symbol(std::string(opt_key.begin(), opt_key.end()));
|
||||
if (opt == nullptr)
|
||||
ctx->throw_exception("Not a variable name", opt_key);
|
||||
if (opt == nullptr) {
|
||||
opt = ctx->resolve_output_symbol(std::string(opt_key.begin(), opt_key.end()));
|
||||
if (opt == nullptr)
|
||||
ctx->throw_exception("Not a variable name", opt_key);
|
||||
output.writable = true;
|
||||
}
|
||||
output.opt = opt;
|
||||
output.it_range = opt_key;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void scalar_variable_reference(
|
||||
static void store_variable_index(
|
||||
const MyContext *ctx,
|
||||
OptWithPos<Iterator> &opt,
|
||||
expr<Iterator> &output)
|
||||
OptWithPos<Iterator> &opt,
|
||||
int index,
|
||||
Iterator it_end,
|
||||
OptWithPos<Iterator> &output)
|
||||
{
|
||||
if (opt.opt->is_vector())
|
||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||
switch (opt.opt->type()) {
|
||||
case coFloat: output.set_d(opt.opt->getFloat()); break;
|
||||
case coInt: output.set_i(opt.opt->getInt()); break;
|
||||
case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
|
||||
case coPercent: output.set_d(opt.opt->getFloat()); break;
|
||||
case coEnum:
|
||||
case coPoint: output.set_s(opt.opt->serialize()); break;
|
||||
case coBool: output.set_b(opt.opt->getBool()); break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
std::string opt_key(opt.it_range.begin(), opt.it_range.end());
|
||||
if (boost::ends_with(opt_key, "extrusion_width")) {
|
||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||
output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
|
||||
} else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
|
||||
// Not a percent, just return the value.
|
||||
output.set_d(opt.opt->getFloat());
|
||||
} else {
|
||||
// Resolve dependencies using the "ratio_over" link to a parent value.
|
||||
const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
|
||||
assert(opt_def != nullptr);
|
||||
double v = opt.opt->getFloat() * 0.01; // percent to ratio
|
||||
for (;;) {
|
||||
const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
|
||||
if (opt_parent == nullptr)
|
||||
ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
|
||||
if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) {
|
||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||
assert(opt_parent->type() == coFloatOrPercent);
|
||||
v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
|
||||
break;
|
||||
}
|
||||
if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
|
||||
v *= opt_parent->getFloat();
|
||||
if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
|
||||
break;
|
||||
v *= 0.01; // percent to ratio
|
||||
}
|
||||
// Continue one level up in the "ratio_over" hierarchy.
|
||||
opt_def = print_config_def.get(opt_def->ratio_over);
|
||||
assert(opt_def != nullptr);
|
||||
}
|
||||
output.set_d(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ctx->throw_exception("Unknown scalar variable type", opt.it_range);
|
||||
}
|
||||
output.it_range = opt.it_range;
|
||||
if (! opt.opt->is_vector())
|
||||
ctx->throw_exception("Cannot index a scalar variable", opt.it_range);
|
||||
if (index < 0)
|
||||
ctx->throw_exception("Referencing a vector variable with a negative index", opt.it_range);
|
||||
output = opt;
|
||||
output.index = index;
|
||||
output.it_range.end() = it_end;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void vector_variable_reference(
|
||||
static void variable_value(
|
||||
const MyContext *ctx,
|
||||
OptWithPos<Iterator> &opt,
|
||||
int &index,
|
||||
Iterator it_end,
|
||||
expr<Iterator> &output)
|
||||
{
|
||||
if (opt.opt->is_scalar())
|
||||
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||
if (vec->empty())
|
||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||
size_t idx = (index < 0) ? 0 : (index >= int(vec->size())) ? 0 : size_t(index);
|
||||
switch (opt.opt->type()) {
|
||||
case coFloats: output.set_d(static_cast<const ConfigOptionFloats *>(opt.opt)->values[idx]); break;
|
||||
case coInts: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
||||
case coStrings: output.set_s(static_cast<const ConfigOptionStrings *>(opt.opt)->values[idx]); break;
|
||||
case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
|
||||
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints *>(opt.opt)->values[idx])); break;
|
||||
case coBools: output.set_b(static_cast<const ConfigOptionBools *>(opt.opt)->values[idx] != 0); break;
|
||||
//case coEnums: output.set_s(opt.opt->vserialize()[idx]); break;
|
||||
default:
|
||||
ctx->throw_exception("Unknown vector variable type", opt.it_range);
|
||||
if (opt.opt->is_vector()) {
|
||||
if (! opt.has_index())
|
||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||
if (vec->empty())
|
||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||
size_t idx = (opt.index < 0) ? 0 : (opt.index >= int(vec->size())) ? 0 : size_t(opt.index);
|
||||
switch (opt.opt->type()) {
|
||||
case coFloats: output.set_d(static_cast<const ConfigOptionFloats *>(opt.opt)->values[idx]); break;
|
||||
case coInts: output.set_i(static_cast<const ConfigOptionInts *>(opt.opt)->values[idx]); break;
|
||||
case coStrings: output.set_s(static_cast<const ConfigOptionStrings *>(opt.opt)->values[idx]); break;
|
||||
case coPercents: output.set_d(static_cast<const ConfigOptionPercents*>(opt.opt)->values[idx]); break;
|
||||
case coPoints: output.set_s(to_string(static_cast<const ConfigOptionPoints *>(opt.opt)->values[idx])); break;
|
||||
case coBools: output.set_b(static_cast<const ConfigOptionBools *>(opt.opt)->values[idx] != 0); break;
|
||||
//case coEnums: output.set_s(opt.opt->vserialize()[idx]); break;
|
||||
default:
|
||||
ctx->throw_exception("Unknown vector variable type", opt.it_range);
|
||||
}
|
||||
} else {
|
||||
assert(opt.opt->is_scalar());
|
||||
switch (opt.opt->type()) {
|
||||
case coFloat: output.set_d(opt.opt->getFloat()); break;
|
||||
case coInt: output.set_i(opt.opt->getInt()); break;
|
||||
case coString: output.set_s(static_cast<const ConfigOptionString*>(opt.opt)->value); break;
|
||||
case coPercent: output.set_d(opt.opt->getFloat()); break;
|
||||
case coEnum:
|
||||
case coPoint: output.set_s(opt.opt->serialize()); break;
|
||||
case coBool: output.set_b(opt.opt->getBool()); break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
std::string opt_key(opt.it_range.begin(), opt.it_range.end());
|
||||
if (boost::ends_with(opt_key, "extrusion_width")) {
|
||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||
output.set_d(Flow::extrusion_width(opt_key, *ctx, static_cast<unsigned int>(ctx->current_extruder_id)));
|
||||
} else if (! static_cast<const ConfigOptionFloatOrPercent*>(opt.opt)->percent) {
|
||||
// Not a percent, just return the value.
|
||||
output.set_d(opt.opt->getFloat());
|
||||
} else {
|
||||
// Resolve dependencies using the "ratio_over" link to a parent value.
|
||||
const ConfigOptionDef *opt_def = print_config_def.get(opt_key);
|
||||
assert(opt_def != nullptr);
|
||||
double v = opt.opt->getFloat() * 0.01; // percent to ratio
|
||||
for (;;) {
|
||||
const ConfigOption *opt_parent = opt_def->ratio_over.empty() ? nullptr : ctx->resolve_symbol(opt_def->ratio_over);
|
||||
if (opt_parent == nullptr)
|
||||
ctx->throw_exception("FloatOrPercent variable failed to resolve the \"ratio_over\" dependencies", opt.it_range);
|
||||
if (boost::ends_with(opt_def->ratio_over, "extrusion_width")) {
|
||||
// Extrusion width supports defaults and a complex graph of dependencies.
|
||||
assert(opt_parent->type() == coFloatOrPercent);
|
||||
v *= Flow::extrusion_width(opt_def->ratio_over, static_cast<const ConfigOptionFloatOrPercent*>(opt_parent), *ctx, static_cast<unsigned int>(ctx->current_extruder_id));
|
||||
break;
|
||||
}
|
||||
if (opt_parent->type() == coFloat || opt_parent->type() == coFloatOrPercent) {
|
||||
v *= opt_parent->getFloat();
|
||||
if (opt_parent->type() == coFloat || ! static_cast<const ConfigOptionFloatOrPercent*>(opt_parent)->percent)
|
||||
break;
|
||||
v *= 0.01; // percent to ratio
|
||||
}
|
||||
// Continue one level up in the "ratio_over" hierarchy.
|
||||
opt_def = print_config_def.get(opt_def->ratio_over);
|
||||
assert(opt_def != nullptr);
|
||||
}
|
||||
output.set_d(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ctx->throw_exception("Unknown scalar variable type", opt.it_range);
|
||||
}
|
||||
}
|
||||
output.it_range = boost::iterator_range<Iterator>(opt.it_range.begin(), it_end);
|
||||
|
||||
output.it_range = opt.it_range;
|
||||
}
|
||||
|
||||
// Return a boolean value, true if the scalar variable referenced by "opt" is nullable and it has a nil value.
|
||||
// Return a boolean value, true if an element of a vector variable referenced by "opt[index]" is nullable and it has a nil value.
|
||||
template <typename Iterator>
|
||||
static void is_nil_test_scalar(
|
||||
static void is_nil_test(
|
||||
const MyContext *ctx,
|
||||
OptWithPos<Iterator> &opt,
|
||||
expr<Iterator> &output)
|
||||
{
|
||||
if (opt.opt->is_vector())
|
||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||
output.set_b(opt.opt->is_nil());
|
||||
if (opt.opt->is_vector()) {
|
||||
if (! opt.has_index())
|
||||
ctx->throw_exception("Referencing a vector variable when scalar is expected", opt.it_range);
|
||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||
if (vec->empty())
|
||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||
output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(opt.index >= int(vec->size()) ? 0 : size_t(opt.index)));
|
||||
} else {
|
||||
assert(opt.opt->is_scalar());
|
||||
output.set_b(opt.opt->is_nil());
|
||||
}
|
||||
output.it_range = opt.it_range;
|
||||
}
|
||||
|
||||
// Return a boolean value, true if an element of a vector variable referenced by "opt[index]" is nullable and it has a nil value.
|
||||
// Decoding a scalar variable symbol "opt", assigning it a value of "param".
|
||||
template <typename Iterator>
|
||||
static void is_nil_test_vector(
|
||||
static void variable_assign(
|
||||
const MyContext *ctx,
|
||||
OptWithPos<Iterator> &opt,
|
||||
int &index,
|
||||
Iterator it_end,
|
||||
expr<Iterator> &output)
|
||||
expr<Iterator> ¶m,
|
||||
// Not used, just clear it.
|
||||
std::string &out)
|
||||
{
|
||||
if (opt.opt->is_scalar())
|
||||
ctx->throw_exception("Referencing a scalar variable when vector is expected", opt.it_range);
|
||||
const ConfigOptionVectorBase *vec = static_cast<const ConfigOptionVectorBase*>(opt.opt);
|
||||
if (vec->empty())
|
||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||
size_t idx = (index < 0) ? 0 : (index >= int(vec->size())) ? 0 : size_t(index);
|
||||
output.set_b(static_cast<const ConfigOptionVectorBase*>(opt.opt)->is_nil(idx));
|
||||
output.it_range = boost::iterator_range<Iterator>(opt.it_range.begin(), it_end);
|
||||
if (! opt.writable)
|
||||
ctx->throw_exception("Cannot modify a read-only variable", opt.it_range);
|
||||
if (opt.opt->is_vector()) {
|
||||
if (! opt.has_index())
|
||||
ctx->throw_exception("Referencing an output vector variable when scalar is expected", opt.it_range);
|
||||
ConfigOptionVectorBase *vec = const_cast<ConfigOptionVectorBase*>(static_cast<const ConfigOptionVectorBase*>(opt.opt));
|
||||
if (vec->empty())
|
||||
ctx->throw_exception("Indexing an empty vector variable", opt.it_range);
|
||||
if (opt.index >= int(vec->size()))
|
||||
ctx->throw_exception("Index out of range", opt.it_range);
|
||||
switch (opt.opt->type()) {
|
||||
case coFloats:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionFloats*>(vec)->values[opt.index] = param.as_d();
|
||||
break;
|
||||
case coInts:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionInts*>(vec)->values[opt.index] = param.as_i();
|
||||
break;
|
||||
case coStrings:
|
||||
static_cast<ConfigOptionStrings*>(vec)->values[opt.index] = param.to_string();
|
||||
break;
|
||||
case coPercents:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionPercents*>(vec)->values[opt.index] = param.as_d();
|
||||
break;
|
||||
case coBools:
|
||||
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
||||
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
||||
static_cast<ConfigOptionBools*>(vec)->values[opt.index] = param.b();
|
||||
break;
|
||||
default:
|
||||
ctx->throw_exception("Unsupported output vector variable type", opt.it_range);
|
||||
}
|
||||
} else {
|
||||
assert(opt.opt->is_scalar());
|
||||
ConfigOption *wropt = const_cast<ConfigOption*>(opt.opt);
|
||||
switch (wropt->type()) {
|
||||
case coFloat:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionFloat*>(wropt)->value = param.as_d();
|
||||
break;
|
||||
case coInt:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionInt*>(wropt)->value = param.as_i();
|
||||
break;
|
||||
case coString:
|
||||
static_cast<ConfigOptionString*>(wropt)->value = param.to_string();
|
||||
break;
|
||||
case coPercent:
|
||||
if (param.type() != expr<Iterator>::TYPE_INT && param.type() != expr<Iterator>::TYPE_DOUBLE)
|
||||
ctx->throw_exception("Right side is not a numeric expression", param.it_range);
|
||||
static_cast<ConfigOptionPercent*>(wropt)->value = param.as_d();
|
||||
break;
|
||||
case coBool:
|
||||
if (param.type() != expr<Iterator>::TYPE_BOOL)
|
||||
ctx->throw_exception("Right side is not a boolean expression", param.it_range);
|
||||
static_cast<ConfigOptionBool*>(wropt)->value = param.b();
|
||||
break;
|
||||
default:
|
||||
ctx->throw_exception("Unsupported output scalar variable type", opt.it_range);
|
||||
}
|
||||
}
|
||||
out.clear();
|
||||
}
|
||||
|
||||
// Verify that the expression returns an integer, which may be used
|
||||
@ -1011,9 +1101,9 @@ namespace client
|
||||
{ "multiplicative_expression", "Expecting an expression." },
|
||||
{ "unary_expression", "Expecting an expression." },
|
||||
{ "optional_parameter", "Expecting a closing brace or an optional parameter." },
|
||||
{ "scalar_variable_reference", "Expecting a scalar variable reference."},
|
||||
{ "is_nil_test", "Expecting a scalar variable reference."},
|
||||
{ "variable_reference", "Expecting a variable reference."},
|
||||
{ "is_nil_test", "Expecting a scalar variable reference."},
|
||||
{ "variable", "Expecting a variable name."},
|
||||
{ "regular_expression", "Expecting a regular expression."}
|
||||
};
|
||||
|
||||
@ -1165,7 +1255,9 @@ namespace client
|
||||
macro =
|
||||
(kw["if"] > if_else_output(_r1) [_val = _1])
|
||||
// | (kw["switch"] > switch_output(_r1) [_val = _1])
|
||||
| additive_expression(_r1) [ px::bind(&expr<Iterator>::to_string2, _1, _val) ];
|
||||
| (assignment_statement(_r1) [_val = _1])
|
||||
| (additive_expression(_r1) [ px::bind(&expr<Iterator>::to_string2, _1, _val) ])
|
||||
;
|
||||
macro.name("macro");
|
||||
|
||||
// An if expression enclosed in {} (the outmost {} are already parsed by the caller).
|
||||
@ -1257,6 +1349,10 @@ namespace client
|
||||
);
|
||||
multiplicative_expression.name("multiplicative_expression");
|
||||
|
||||
assignment_statement =
|
||||
(variable_reference(_r1) >> '=' > additive_expression(_r1))
|
||||
[px::bind(&MyContext::variable_assign<Iterator>, _r1, _1, _2, _val)];
|
||||
|
||||
struct FactorActions {
|
||||
static void set_start_pos(Iterator &start_pos, expr<Iterator> &out)
|
||||
{ out.it_range = boost::iterator_range<Iterator>(start_pos, start_pos); }
|
||||
@ -1282,7 +1378,7 @@ namespace client
|
||||
static void noexpr(expr<Iterator> &out) { out.reset(); }
|
||||
};
|
||||
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
|
||||
scalar_variable_reference(_r1) [ _val = _1 ]
|
||||
variable_reference(_r1) [px::bind(&MyContext::variable_value<Iterator>, _r1, _1, _val)]
|
||||
| (lit('(') > conditional_expression(_r1) > ')' > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
||||
| (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ]
|
||||
| (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
|
||||
@ -1314,27 +1410,20 @@ namespace client
|
||||
);
|
||||
optional_parameter.name("optional_parameter");
|
||||
|
||||
scalar_variable_reference =
|
||||
variable_reference(_r1)[_a=_1] >>
|
||||
(
|
||||
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' >
|
||||
iter_pos[px::bind(&MyContext::vector_variable_reference<Iterator>, _r1, _a, _b, _1, _val)])
|
||||
| eps[px::bind(&MyContext::scalar_variable_reference<Iterator>, _r1, _a, _val)]
|
||||
);
|
||||
scalar_variable_reference.name("scalar variable reference");
|
||||
is_nil_test = variable_reference(_r1)[px::bind(&MyContext::is_nil_test<Iterator>, _r1, _1, _val)];
|
||||
is_nil_test.name("is_nil test");
|
||||
|
||||
variable_reference = identifier
|
||||
[ px::bind(&MyContext::resolve_variable<Iterator>, _r1, _1, _val) ];
|
||||
variable_reference =
|
||||
variable(_r1)[_a=_1] >>
|
||||
(
|
||||
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' > iter_pos)
|
||||
[px::bind(&MyContext::store_variable_index<Iterator>, _r1, _a, _b, _2, _val)]
|
||||
| eps[_val=_a]
|
||||
);
|
||||
variable_reference.name("variable reference");
|
||||
|
||||
is_nil_test =
|
||||
variable_reference(_r1)[_a=_1] >>
|
||||
(
|
||||
('[' > additive_expression(_r1)[px::bind(&MyContext::evaluate_index<Iterator>, _1, _b)] > ']' >
|
||||
iter_pos[px::bind(&MyContext::is_nil_test_vector<Iterator>, _r1, _a, _b, _1, _val)])
|
||||
| eps[px::bind(&MyContext::is_nil_test_scalar<Iterator>, _r1, _a, _val)]
|
||||
);
|
||||
is_nil_test.name("is_nil test");
|
||||
variable = identifier[ px::bind(&MyContext::resolve_variable<Iterator>, _r1, _1, _val) ];
|
||||
variable.name("variable reference");
|
||||
|
||||
regular_expression = raw[lexeme['/' > *((utf8char - char_('\\') - char_('/')) | ('\\' > char_)) > '/']];
|
||||
regular_expression.name("regular_expression");
|
||||
@ -1378,8 +1467,8 @@ namespace client
|
||||
debug(multiplicative_expression);
|
||||
debug(unary_expression);
|
||||
debug(optional_parameter);
|
||||
debug(scalar_variable_reference);
|
||||
debug(variable_reference);
|
||||
debug(variable);
|
||||
debug(is_nil_test);
|
||||
debug(regular_expression);
|
||||
}
|
||||
@ -1423,13 +1512,14 @@ namespace client
|
||||
// Evaluate boolean expression into bool.
|
||||
qi::rule<Iterator, bool(const MyContext*), spirit_encoding::space_type> bool_expr_eval;
|
||||
// Reference of a scalar variable, or reference to a field of a vector variable.
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> scalar_variable_reference;
|
||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> variable_reference;
|
||||
// Rule to translate an identifier to a ConfigOption, or to fail.
|
||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit_encoding::space_type> variable_reference;
|
||||
qi::rule<Iterator, OptWithPos<Iterator>(const MyContext*), spirit_encoding::space_type> variable;
|
||||
// Evaluating whether a nullable variable is nil.
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> is_nil_test;
|
||||
qi::rule<Iterator, expr<Iterator>(const MyContext*), spirit_encoding::space_type> is_nil_test;
|
||||
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<bool, bool>, spirit_encoding::space_type> if_else_output;
|
||||
qi::rule<Iterator, std::string(const MyContext*), qi::locals<OptWithPos<Iterator>, int>, spirit_encoding::space_type> assignment_statement;
|
||||
// qi::rule<Iterator, std::string(const MyContext*), qi::locals<expr<Iterator>, bool, std::string>, spirit_encoding::space_type> switch_output;
|
||||
|
||||
qi::symbols<char> keywords;
|
||||
@ -1461,12 +1551,13 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override, ContextData *context_data) const
|
||||
std::string PlaceholderParser::process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override, DynamicConfig *config_outputs, ContextData *context_data) const
|
||||
{
|
||||
client::MyContext context;
|
||||
context.external_config = this->external_config();
|
||||
context.config = &this->config();
|
||||
context.config_override = config_override;
|
||||
context.config_outputs = config_outputs;
|
||||
context.current_extruder_id = current_extruder_id;
|
||||
context.context_data = context_data;
|
||||
return process_macro(templ, context);
|
||||
|
@ -55,8 +55,10 @@ public:
|
||||
|
||||
// Fill in the template using a macro processing language.
|
||||
// Throws Slic3r::PlaceholderParserError on syntax or runtime error.
|
||||
std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr, ContextData *context = nullptr) const;
|
||||
|
||||
std::string process(const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override, DynamicConfig *config_outputs, ContextData *context) const;
|
||||
std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr, ContextData *context = nullptr) const
|
||||
{ return this->process(templ, current_extruder_id, config_override, nullptr /* config_outputs */, context); }
|
||||
|
||||
// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
|
||||
// Throws Slic3r::PlaceholderParserError on syntax or runtime error.
|
||||
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
|
||||
|
@ -1618,7 +1618,8 @@ void PrintObject::bridge_over_infill()
|
||||
if (layer->lower_layer == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto spacing = layer->regions().front()->flow(frSolidInfill).scaled_spacing();
|
||||
double spacing = layer->regions().front()->flow(frSolidInfill).scaled_spacing();
|
||||
// unsupported area will serve as a filter for polygons worth bridging.
|
||||
Polygons unsupported_area;
|
||||
Polygons lower_layer_solids;
|
||||
bool contains_only_lightning = true;
|
||||
@ -1627,6 +1628,7 @@ void PrintObject::bridge_over_infill()
|
||||
contains_only_lightning = false;
|
||||
}
|
||||
Polygons fill_polys = to_polygons(region->fill_expolygons());
|
||||
// initially consider the whole layer unsupported, but also gather solid layers to later cut off supported parts
|
||||
unsupported_area.insert(unsupported_area.end(), fill_polys.begin(), fill_polys.end());
|
||||
for (const Surface &surface : region->fill_surfaces()) {
|
||||
if (surface.surface_type != stInternal || region->region().config().fill_density.value == 100) {
|
||||
@ -1636,25 +1638,30 @@ void PrintObject::bridge_over_infill()
|
||||
}
|
||||
}
|
||||
unsupported_area = closing(unsupported_area, SCALED_EPSILON);
|
||||
|
||||
lower_layer_solids = expand(lower_layer_solids, 4 * spacing);
|
||||
unsupported_area = shrink(unsupported_area, 4 * spacing);
|
||||
// By expanding the lower layer solids, we avoid making bridges from the tiny internal overhangs that are (very likely) supported by previous layer solids
|
||||
// NOTE that we cannot filter out polygons worth bridging by their area, because sometimes there is a very small internal island that will grow into large hole
|
||||
lower_layer_solids = expand(lower_layer_solids, 3 * spacing);
|
||||
// By shrinking the unsupported area, we avoid making bridges from narrow ensuring region along perimeters.
|
||||
unsupported_area = shrink(unsupported_area, 3 * spacing);
|
||||
unsupported_area = diff(unsupported_area, lower_layer_solids);
|
||||
|
||||
for (const LayerRegion *region : layer->regions()) {
|
||||
SurfacesPtr region_internal_solids = region->fill_surfaces().filter_by_type(stInternalSolid);
|
||||
for (const Surface *s : region_internal_solids) {
|
||||
Polygons unsupported = intersection(to_polygons(s->expolygon), unsupported_area);
|
||||
// The following flag marks those surfaces, which overlap with unuspported area, but at least part of them is supported.
|
||||
// These regions can be filtered by area, because they for sure are touching solids on lower layers, and it does not make sense to bridge their tiny overhangs
|
||||
bool partially_supported = area(unsupported) < area(to_polygons(s->expolygon)) - EPSILON;
|
||||
if (!unsupported.empty() && (!partially_supported || area(unsupported) > 5 * 5 * spacing * spacing)) {
|
||||
Polygons worth_bridging = intersection(to_polygons(s->expolygon), expand(unsupported, 5 * spacing));
|
||||
if (!unsupported.empty() && (!partially_supported || area(unsupported) > 3 * 3 * spacing * spacing)) {
|
||||
Polygons worth_bridging = intersection(to_polygons(s->expolygon), expand(unsupported, 4 * spacing));
|
||||
// after we extracted the part worth briding, we go over the leftovers and merge the tiny ones back, to not brake the surface too much
|
||||
for (const Polygon& p : diff(to_polygons(s->expolygon), expand(worth_bridging, spacing))) {
|
||||
auto area = p.area();
|
||||
double area = p.area();
|
||||
if (area < spacing * scale_(12.0) && area > spacing * spacing) {
|
||||
worth_bridging.push_back(p);
|
||||
}
|
||||
}
|
||||
worth_bridging = intersection(closing(worth_bridging, 2 * spacing), s->expolygon);
|
||||
worth_bridging = intersection(closing(worth_bridging, SCALED_EPSILON), s->expolygon);
|
||||
candidate_surfaces.push_back(CandidateSurface(s, lidx, worth_bridging, region, 0, contains_only_lightning));
|
||||
|
||||
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
||||
@ -1663,7 +1670,7 @@ void PrintObject::bridge_over_infill()
|
||||
to_lines(unsupported_area));
|
||||
#endif
|
||||
#ifdef DEBUG_BRIDGE_OVER_INFILL
|
||||
debug_draw(std::to_string(lidx) + "_candidate_processing_" + std::to_string(area(s->expolygon)),
|
||||
debug_draw(std::to_string(lidx) + "_candidate_processing_" + std::to_string(area(unsupported)),
|
||||
to_lines(unsupported), to_lines(intersection(to_polygons(s->expolygon), expand(unsupported, 5 * spacing))),
|
||||
to_lines(diff(to_polygons(s->expolygon), expand(worth_bridging, spacing))),
|
||||
to_lines(unsupported_area));
|
||||
@ -1728,15 +1735,15 @@ void PrintObject::bridge_over_infill()
|
||||
layer_area_covered_by_candidates[pair.first] = {};
|
||||
}
|
||||
|
||||
// prepare inflated filter for each candidate on each layer. layers will be put into single thread cluster if they are close to each other (z-axis-wise)
|
||||
// and if the inflated AABB polygons overlap somewhere
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers_with_candidates.size()), [&layers_with_candidates, &surfaces_by_layer,
|
||||
&layer_area_covered_by_candidates](
|
||||
tbb::blocked_range<size_t> r) {
|
||||
for (size_t job_idx = r.begin(); job_idx < r.end(); job_idx++) {
|
||||
size_t lidx = layers_with_candidates[job_idx];
|
||||
for (const auto &candidate : surfaces_by_layer.at(lidx)) {
|
||||
Polygon candiate_inflated_aabb = get_extents(candidate.new_polys)
|
||||
.inflated(candidate.region->flow(frSolidInfill, true).scaled_spacing() * 5)
|
||||
.polygon();
|
||||
Polygon candiate_inflated_aabb = get_extents(candidate.new_polys).inflated(scale_(7)).polygon();
|
||||
layer_area_covered_by_candidates.at(lidx) = union_(layer_area_covered_by_candidates.at(lidx),
|
||||
Polygons{candiate_inflated_aabb});
|
||||
}
|
||||
@ -2088,13 +2095,13 @@ void PrintObject::bridge_over_infill()
|
||||
}
|
||||
}
|
||||
|
||||
deep_infill_area = expand(deep_infill_area, spacing);
|
||||
deep_infill_area = expand(deep_infill_area, spacing * 1.5);
|
||||
|
||||
// Now gather expansion polygons - internal infill on current layer, from which we can cut off anchors
|
||||
Polygons expansion_area;
|
||||
Polygons total_fill_area;
|
||||
for (const LayerRegion *region : layer->regions()) {
|
||||
Polygons internal_polys = to_polygons(region->fill_surfaces().filter_by_type(stInternal));
|
||||
Polygons internal_polys = to_polygons(region->fill_surfaces().filter_by_types({stInternal, stInternalSolid}));
|
||||
expansion_area.insert(expansion_area.end(), internal_polys.begin(), internal_polys.end());
|
||||
Polygons fill_polys = to_polygons(region->fill_expolygons());
|
||||
total_fill_area.insert(total_fill_area.end(), fill_polys.begin(), fill_polys.end());
|
||||
|
@ -3160,6 +3160,8 @@ void Plater::priv::split_object()
|
||||
// causing original positions not to be kept
|
||||
std::vector<size_t> idxs = load_model_objects(new_objects);
|
||||
|
||||
// clear previosli selection
|
||||
get_selection().clear();
|
||||
// select newly added objects
|
||||
for (size_t idx : idxs)
|
||||
{
|
||||
|
@ -399,7 +399,7 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
||||
std::string name(stat.m_filename);
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to unzip " << stat.m_filename;
|
||||
continue;
|
||||
|
@ -117,4 +117,17 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") {
|
||||
SECTION("complex expression2") { REQUIRE(boolean_expression("printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.6 and num_extruders>1)")); }
|
||||
SECTION("complex expression3") { REQUIRE(! boolean_expression("printer_notes=~/.*PRINTER_VEwerfNDOR_PRUSA3D.*/ or printer_notes=~/.*PRINTertER_MODEL_MK2.*/ or (nozzle_diameter[0]==0.3 and num_extruders>1)")); }
|
||||
SECTION("enum expression") { REQUIRE(boolean_expression("gcode_flavor == \"marlin\"")); }
|
||||
|
||||
SECTION("write to a scalar variable") {
|
||||
DynamicConfig config_outputs;
|
||||
config_outputs.set_key_value("writable_string", new ConfigOptionString());
|
||||
parser.process("{writable_string = \"Written\"}", 0, nullptr, &config_outputs, nullptr);
|
||||
REQUIRE(parser.process("{writable_string}", 0, nullptr, &config_outputs, nullptr) == "Written");
|
||||
}
|
||||
SECTION("write to a vector variable") {
|
||||
DynamicConfig config_outputs;
|
||||
config_outputs.set_key_value("writable_floats", new ConfigOptionFloats({ 0., 0., 0. }));
|
||||
parser.process("{writable_floats[1] = 33}", 0, nullptr, &config_outputs, nullptr);
|
||||
REQUIRE(config_outputs.opt_float("writable_floats", 1) == Approx(33.));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user