Merge branch 'master' into fs_emboss
# Conflicts: # src/slic3r/GUI/GLCanvas3D.cpp
This commit is contained in:
commit
7c1a513e5a
@ -1,9 +1,13 @@
|
|||||||
min_slic3r_version = 2.5.0-alpha0
|
min_slic3r_version = 2.5.0-alpha0
|
||||||
|
1.5.4 Added material profiles for Prusament Resin BioBased60.
|
||||||
|
1.5.3 Added filament profiles for ColorFabb VarioShore TPU, FormFutura PP, NinjaTek NinjaFlex/Cheetah TPU and for multiple Eolas Prints filaments. Updated bridging settings in 50um and 70um profiles.
|
||||||
|
1.5.2 Added SLA material profiles.
|
||||||
1.5.1 Renamed filament type "NYLON" to "PA". Updated Adura X profile. Updated PETG fan settings for Prusa MINI (removed fan ramp up).
|
1.5.1 Renamed filament type "NYLON" to "PA". Updated Adura X profile. Updated PETG fan settings for Prusa MINI (removed fan ramp up).
|
||||||
1.5.0 Updated arachne parameters. Added profiles for Jessie filaments.
|
1.5.0 Updated arachne parameters. Added profiles for Jessie filaments.
|
||||||
1.5.0-alpha1 Added filament profile for Prusament PA11 Carbon Fiber. Added profiles for multiple 3D-Fuel filaments.
|
1.5.0-alpha1 Added filament profile for Prusament PA11 Carbon Fiber. Added profiles for multiple 3D-Fuel filaments.
|
||||||
1.5.0-alpha0 Added parameters for Arachne perimeter generator. Changed default seam position. Updated output filename format.
|
1.5.0-alpha0 Added parameters for Arachne perimeter generator. Changed default seam position. Updated output filename format.
|
||||||
min_slic3r_version = 2.4.0-rc
|
min_slic3r_version = 2.4.0-rc
|
||||||
|
1.4.8 Added filament and SLA material profiles. Updated settings.
|
||||||
1.4.7 Added filament profile for Prusament PA11 Carbon Fiber. Added profiles for multiple 3D-Fuel filaments.
|
1.4.7 Added filament profile for Prusament PA11 Carbon Fiber. Added profiles for multiple 3D-Fuel filaments.
|
||||||
1.4.6 Added SLA materials. Updated filament profiles.
|
1.4.6 Added SLA materials. Updated filament profiles.
|
||||||
1.4.5 Added MMU2/S profiles for 0.25mm nozzle. Updated FW version. Enabled g-code thumbnails for MK3 family printers. Updated end g-code.
|
1.4.5 Added MMU2/S profiles for 0.25mm nozzle. Updated FW version. Enabled g-code thumbnails for MK3 family printers. Updated end g-code.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
name = Prusa Research
|
name = Prusa Research
|
||||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
# 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.
|
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||||
config_version = 1.5.1
|
config_version = 1.5.4
|
||||||
# Where to get the updates from?
|
# Where to get the updates from?
|
||||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/
|
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%
|
changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||||
@ -441,8 +441,8 @@ inherits = *common*
|
|||||||
layer_height = 0.05
|
layer_height = 0.05
|
||||||
bottom_solid_layers = 10
|
bottom_solid_layers = 10
|
||||||
bridge_acceleration = 300
|
bridge_acceleration = 300
|
||||||
bridge_flow_ratio = 1.15
|
bridge_flow_ratio = 0.6
|
||||||
bridge_speed = 15
|
bridge_speed = 25
|
||||||
default_acceleration = 1000
|
default_acceleration = 1000
|
||||||
external_perimeter_speed = 20
|
external_perimeter_speed = 20
|
||||||
fill_density = 20%
|
fill_density = 20%
|
||||||
@ -463,12 +463,13 @@ perimeters = 3
|
|||||||
support_material_speed = 30
|
support_material_speed = 30
|
||||||
top_solid_infill_speed = 20
|
top_solid_infill_speed = 20
|
||||||
top_solid_layers = 15
|
top_solid_layers = 15
|
||||||
|
thick_bridges = 1
|
||||||
|
|
||||||
[print:*0.07mm*]
|
[print:*0.07mm*]
|
||||||
inherits = *0.05mm*
|
inherits = *0.05mm*
|
||||||
layer_height = 0.07
|
layer_height = 0.07
|
||||||
bottom_solid_layers = 8
|
bottom_solid_layers = 8
|
||||||
bridge_flow_ratio = 1
|
bridge_flow_ratio = 0.6
|
||||||
fill_density = 15%
|
fill_density = 15%
|
||||||
infill_speed = 40
|
infill_speed = 40
|
||||||
solid_infill_speed = 40
|
solid_infill_speed = 40
|
||||||
@ -583,6 +584,8 @@ top_solid_layers = 4
|
|||||||
inherits = *0.05mm*
|
inherits = *0.05mm*
|
||||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders==1
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders==1
|
||||||
infill_extrusion_width = 0.5
|
infill_extrusion_width = 0.5
|
||||||
|
support_material_contact_distance = 0.1
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
|
||||||
[print:0.10mm DETAIL]
|
[print:0.10mm DETAIL]
|
||||||
inherits = *0.10mm*
|
inherits = *0.10mm*
|
||||||
@ -892,12 +895,16 @@ fill_pattern = gyroid
|
|||||||
fill_density = 15%
|
fill_density = 15%
|
||||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||||
top_infill_extrusion_width = 0.4
|
top_infill_extrusion_width = 0.4
|
||||||
|
support_material_contact_distance = 0.1
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
|
||||||
[print:0.07mm ULTRADETAIL @MK3]
|
[print:0.07mm ULTRADETAIL @MK3]
|
||||||
inherits = *0.07mm*; *MK3*
|
inherits = *0.07mm*; *MK3*
|
||||||
fill_pattern = gyroid
|
fill_pattern = gyroid
|
||||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||||
top_infill_extrusion_width = 0.4
|
top_infill_extrusion_width = 0.4
|
||||||
|
support_material_contact_distance = 0.1
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
|
||||||
[print:0.10mm DETAIL @MK3]
|
[print:0.10mm DETAIL @MK3]
|
||||||
inherits = *0.10mm*; *MK3*
|
inherits = *0.10mm*; *MK3*
|
||||||
@ -1269,6 +1276,8 @@ support_material_xy_spacing = 60%
|
|||||||
support_material_speed = 30
|
support_material_speed = 30
|
||||||
support_material_extrusion_width = 0.35
|
support_material_extrusion_width = 0.35
|
||||||
bridge_acceleration = 300
|
bridge_acceleration = 300
|
||||||
|
support_material_contact_distance = 0.1
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
|
||||||
[print:0.07mm ULTRADETAIL @MINI]
|
[print:0.07mm ULTRADETAIL @MINI]
|
||||||
inherits = *0.07mm*; *MINI*
|
inherits = *0.07mm*; *MINI*
|
||||||
@ -1282,6 +1291,8 @@ external_perimeter_extrusion_width = 0.4
|
|||||||
support_material_xy_spacing = 60%
|
support_material_xy_spacing = 60%
|
||||||
support_material_extrusion_width = 0.35
|
support_material_extrusion_width = 0.35
|
||||||
bridge_acceleration = 300
|
bridge_acceleration = 300
|
||||||
|
support_material_contact_distance = 0.1
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
|
||||||
[print:0.10mm DETAIL @MINI]
|
[print:0.10mm DETAIL @MINI]
|
||||||
inherits = *0.10mm*; *MINI*
|
inherits = *0.10mm*; *MINI*
|
||||||
@ -1652,7 +1663,7 @@ filament_retract_length = 4
|
|||||||
filament_retract_speed = 40
|
filament_retract_speed = 40
|
||||||
filament_deretract_speed = 15
|
filament_deretract_speed = 15
|
||||||
filament_retract_lift = 0
|
filament_retract_lift = 0
|
||||||
filament_retract_before_travel = 7
|
filament_retract_before_travel = 6
|
||||||
filament_wipe = 0
|
filament_wipe = 0
|
||||||
bridge_fan_speed = 80
|
bridge_fan_speed = 80
|
||||||
fan_always_on = 1
|
fan_always_on = 1
|
||||||
@ -2879,6 +2890,55 @@ min_print_speed = 15
|
|||||||
slowdown_below_layer_time = 10
|
slowdown_below_layer_time = 10
|
||||||
cooling = 1
|
cooling = 1
|
||||||
|
|
||||||
|
[filament:NinjaTek NinjaFlex TPU]
|
||||||
|
inherits = *FLEX*
|
||||||
|
filament_vendor = NinjaTek
|
||||||
|
fan_always_on = 1
|
||||||
|
filament_max_volumetric_speed = 1.2
|
||||||
|
extrusion_multiplier = 1.2
|
||||||
|
first_layer_temperature = 238
|
||||||
|
first_layer_bed_temperature = 50
|
||||||
|
temperature = 238
|
||||||
|
bed_temperature = 50
|
||||||
|
bridge_fan_speed = 75
|
||||||
|
max_fan_speed = 60
|
||||||
|
min_fan_speed = 60
|
||||||
|
filament_retract_before_travel = 3
|
||||||
|
filament_cost = 85
|
||||||
|
filament_density = 1.19
|
||||||
|
filament_retract_length = 2.5
|
||||||
|
filament_retract_speed = 60
|
||||||
|
filament_deretract_speed = 25
|
||||||
|
filament_retract_lift = 0
|
||||||
|
filament_wipe = 0
|
||||||
|
disable_fan_first_layers = 1
|
||||||
|
full_fan_speed_layer = 3
|
||||||
|
min_print_speed = 10
|
||||||
|
slowdown_below_layer_time = 10
|
||||||
|
cooling = 1
|
||||||
|
|
||||||
|
[filament:NinjaTek Cheetah TPU]
|
||||||
|
inherits = NinjaTek NinjaFlex TPU
|
||||||
|
filament_retract_length = 1.5
|
||||||
|
filament_density = 1.22
|
||||||
|
filament_max_volumetric_speed = 4
|
||||||
|
extrusion_multiplier = 1.05
|
||||||
|
filament_retract_speed = 45
|
||||||
|
filament_deretract_speed = 25
|
||||||
|
first_layer_temperature = 240
|
||||||
|
temperature = 240
|
||||||
|
|
||||||
|
[filament:NinjaTek Cheetah TPU @MINI]
|
||||||
|
inherits = NinjaTek NinjaFlex TPU; *FLEXMINI*
|
||||||
|
filament_density = 1.22
|
||||||
|
filament_max_volumetric_speed = 3.5
|
||||||
|
extrusion_multiplier = 1.05
|
||||||
|
first_layer_temperature = 240
|
||||||
|
temperature = 240
|
||||||
|
filament_retract_speed = 50
|
||||||
|
filament_deretract_speed = 25
|
||||||
|
filament_retract_length = 4.8
|
||||||
|
|
||||||
[filament:Filatech FilaFlex40]
|
[filament:Filatech FilaFlex40]
|
||||||
inherits = *FLEX*
|
inherits = *FLEX*
|
||||||
filament_vendor = Filatech
|
filament_vendor = Filatech
|
||||||
@ -3174,7 +3234,8 @@ filament_retract_layer_change = nil
|
|||||||
inherits = Ultrafuse ABS
|
inherits = Ultrafuse ABS
|
||||||
filament_density = 1.08
|
filament_density = 1.08
|
||||||
first_layer_bed_temperature = 105
|
first_layer_bed_temperature = 105
|
||||||
temperature = 250
|
first_layer_temperature = 270
|
||||||
|
temperature = 270
|
||||||
filament_colour = #FFF8D9
|
filament_colour = #FFF8D9
|
||||||
filament_notes = "Material Description\nABS Fusion+ made with Polyscope XILOY™ 3D is an engineering filament which has been optimized for 3D-printing. This special grade has been developed in collaboration with Polyscope Polymers - renowned for its material solutions in the automotive industry. ABS is a thermoplastic which is used in many applications. Although ABS has been classified as a standard material in 3D-printing it is known to be quite challenging to process. ABS Fusion+ combines the properties of ABS with an improved processability. The filament is based on an ABS grade which can be directly printed on glass without any adhesives or tape and has a higher success rate of prints due to extreme low warping."
|
filament_notes = "Material Description\nABS Fusion+ made with Polyscope XILOY™ 3D is an engineering filament which has been optimized for 3D-printing. This special grade has been developed in collaboration with Polyscope Polymers - renowned for its material solutions in the automotive industry. ABS is a thermoplastic which is used in many applications. Although ABS has been classified as a standard material in 3D-printing it is known to be quite challenging to process. ABS Fusion+ combines the properties of ABS with an improved processability. The filament is based on an ABS grade which can be directly printed on glass without any adhesives or tape and has a higher success rate of prints due to extreme low warping."
|
||||||
filament_retract_before_travel = 2
|
filament_retract_before_travel = 2
|
||||||
@ -3943,6 +4004,76 @@ filament_density = 1.24
|
|||||||
filament_spool_weight = 230
|
filament_spool_weight = 230
|
||||||
compatible_printers_condition = nozzle_diameter[0]!=0.8 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
compatible_printers_condition = nozzle_diameter[0]!=0.8 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||||
|
|
||||||
|
[filament:Eolas Prints PLA]
|
||||||
|
inherits = *PLA*
|
||||||
|
filament_vendor = Eolas Prints
|
||||||
|
filament_cost = 23.50
|
||||||
|
filament_density = 1.24
|
||||||
|
filament_spool_weight = 0
|
||||||
|
filament_colour = #4D9398
|
||||||
|
filament_max_volumetric_speed = 15
|
||||||
|
temperature = 208
|
||||||
|
|
||||||
|
[filament:Eolas Prints PLA Matte]
|
||||||
|
inherits = Eolas Prints PLA
|
||||||
|
filament_cost = 25.50
|
||||||
|
filament_max_volumetric_speed = 14
|
||||||
|
temperature = 212
|
||||||
|
|
||||||
|
[filament:Eolas Prints INGEO 850]
|
||||||
|
inherits = Eolas Prints PLA
|
||||||
|
filament_cost = 25.90
|
||||||
|
temperature = 210
|
||||||
|
|
||||||
|
[filament:Eolas Prints INGEO 870]
|
||||||
|
inherits = Eolas Prints PLA
|
||||||
|
filament_cost = 25.90
|
||||||
|
temperature = 215
|
||||||
|
first_layer_bed_temperature = 68
|
||||||
|
first_layer_temperature = 220
|
||||||
|
bed_temperature = 65
|
||||||
|
|
||||||
|
[filament:Eolas Prints PETG]
|
||||||
|
inherits = *PET*
|
||||||
|
filament_vendor = Eolas Prints
|
||||||
|
filament_cost = 29.90
|
||||||
|
filament_density = 1.27
|
||||||
|
filament_spool_weight = 0
|
||||||
|
filament_colour = #4D9398
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
temperature = 240
|
||||||
|
first_layer_bed_temperature = 85
|
||||||
|
first_layer_temperature = 235
|
||||||
|
bed_temperature = 90
|
||||||
|
filament_retract_length = 1.1
|
||||||
|
filament_retract_lift = 0.22
|
||||||
|
|
||||||
|
[filament:Eolas Prints PETG @MINI]
|
||||||
|
inherits = Eolas Prints PETG; *PETMINI*
|
||||||
|
|
||||||
|
[filament:Eolas Prints PETG - UV Resistant]
|
||||||
|
inherits = Eolas Prints PETG
|
||||||
|
filament_cost = 35.90
|
||||||
|
temperature = 237
|
||||||
|
first_layer_temperature = 232
|
||||||
|
|
||||||
|
[filament:Eolas Prints PETG - UV Resistant @MINI]
|
||||||
|
inherits = Eolas Prints PETG - UV Resistant; *PETMINI*
|
||||||
|
|
||||||
|
[filament:Eolas Prints TPU 93A]
|
||||||
|
inherits = *FLEX*
|
||||||
|
filament_vendor = Eolas Prints
|
||||||
|
filament_cost = 34.99
|
||||||
|
filament_density = 1.21
|
||||||
|
filament_spool_weight = 1000
|
||||||
|
filament_colour = #4D9398
|
||||||
|
filament_max_volumetric_speed = 1.2
|
||||||
|
temperature = 235
|
||||||
|
first_layer_bed_temperature = 30
|
||||||
|
bed_temperature = 30
|
||||||
|
filament_retract_length = 0
|
||||||
|
extrusion_multiplier = 1.16
|
||||||
|
|
||||||
[filament:Fiberlogy Easy PLA]
|
[filament:Fiberlogy Easy PLA]
|
||||||
inherits = *PLA*
|
inherits = *PLA*
|
||||||
renamed_from = Fiberlogy PLA
|
renamed_from = Fiberlogy PLA
|
||||||
@ -4041,22 +4172,19 @@ disable_fan_first_layers = 5
|
|||||||
|
|
||||||
[filament:Fiberlogy PCTG]
|
[filament:Fiberlogy PCTG]
|
||||||
inherits = Fiberlogy CPE HT
|
inherits = Fiberlogy CPE HT
|
||||||
filament_vendor = Fiberlogy
|
|
||||||
filament_cost = 29.41
|
filament_cost = 29.41
|
||||||
filament_density = 1.23
|
filament_density = 1.23
|
||||||
extrusion_multiplier = 0.98
|
extrusion_multiplier = 0.98
|
||||||
min_fan_speed = 10
|
min_fan_speed = 10
|
||||||
max_fan_speed = 15
|
max_fan_speed = 15
|
||||||
bridge_fan_speed = 50
|
|
||||||
min_print_speed = 15
|
|
||||||
first_layer_temperature = 265
|
first_layer_temperature = 265
|
||||||
temperature = 265
|
temperature = 265
|
||||||
first_layer_bed_temperature = 90
|
first_layer_bed_temperature = 90
|
||||||
bed_temperature = 90
|
bed_temperature = 90
|
||||||
filament_type = CPE
|
filament_type = PCTG
|
||||||
fan_below_layer_time = 20
|
|
||||||
slowdown_below_layer_time = 15
|
[filament:Fiberlogy PCTG @MINI]
|
||||||
disable_fan_first_layers = 5
|
inherits = Fiberlogy PCTG; *PETMINI*
|
||||||
|
|
||||||
[filament:Fiberlogy FiberFlex 40D]
|
[filament:Fiberlogy FiberFlex 40D]
|
||||||
inherits = *FLEX*
|
inherits = *FLEX*
|
||||||
@ -4331,7 +4459,7 @@ filament_loading_speed_start = 19
|
|||||||
filament_minimal_purge_on_wipe_tower = 15
|
filament_minimal_purge_on_wipe_tower = 15
|
||||||
filament_unloading_speed_start = 100
|
filament_unloading_speed_start = 100
|
||||||
full_fan_speed_layer = 4
|
full_fan_speed_layer = 4
|
||||||
filament_max_volumetric_speed = 13
|
filament_max_volumetric_speed = 12
|
||||||
|
|
||||||
[filament:Generic PLA @MMU2]
|
[filament:Generic PLA @MMU2]
|
||||||
inherits = *PLA MMU2*
|
inherits = *PLA MMU2*
|
||||||
@ -4350,6 +4478,13 @@ filament_cost = 36.29
|
|||||||
filament_density = 1.24
|
filament_density = 1.24
|
||||||
filament_spool_weight = 201
|
filament_spool_weight = 201
|
||||||
|
|
||||||
|
[filament:Jessie PLA @MMU2]
|
||||||
|
inherits = *PLA MMU2*
|
||||||
|
filament_vendor = Printed Solid
|
||||||
|
filament_cost = 21
|
||||||
|
filament_density = 1.24
|
||||||
|
filament_max_volumetric_speed = 10
|
||||||
|
|
||||||
[filament:Prusament PVB @MMU2]
|
[filament:Prusament PVB @MMU2]
|
||||||
inherits = *PLA MMU2*
|
inherits = *PLA MMU2*
|
||||||
filament_vendor = Prusa Polymers
|
filament_vendor = Prusa Polymers
|
||||||
@ -4402,6 +4537,17 @@ full_fan_speed_layer = 6
|
|||||||
filament_retract_length = 1.2
|
filament_retract_length = 1.2
|
||||||
filament_deretract_speed = 20
|
filament_deretract_speed = 20
|
||||||
|
|
||||||
|
[filament:ColorFabb VarioShore TPU]
|
||||||
|
inherits = Fillamentum Flexfill 98A
|
||||||
|
filament_vendor = ColorFabb
|
||||||
|
filament_colour = #BBBBBB
|
||||||
|
filament_cost = 71.35
|
||||||
|
filament_density = 1.22
|
||||||
|
filament_spool_weight = 0
|
||||||
|
extrusion_multiplier = 0.85
|
||||||
|
first_layer_temperature = 220
|
||||||
|
temperature = 220
|
||||||
|
|
||||||
[filament:Taulman Bridge]
|
[filament:Taulman Bridge]
|
||||||
inherits = *common*
|
inherits = *common*
|
||||||
filament_vendor = Taulman
|
filament_vendor = Taulman
|
||||||
@ -4653,6 +4799,42 @@ min_fan_speed = 100
|
|||||||
start_filament_gcode = "M900 K0 ; Filament gcode"
|
start_filament_gcode = "M900 K0 ; Filament gcode"
|
||||||
temperature = 220
|
temperature = 220
|
||||||
|
|
||||||
|
[filament:FormFutura Centaur PP]
|
||||||
|
inherits = *common*
|
||||||
|
filament_vendor = FormFutura
|
||||||
|
filament_cost = 70
|
||||||
|
filament_density = 0.89
|
||||||
|
filament_spool_weight = 212
|
||||||
|
bridge_fan_speed = 100
|
||||||
|
cooling = 1
|
||||||
|
disable_fan_first_layers = 2
|
||||||
|
extrusion_multiplier = 1.05
|
||||||
|
fan_always_on = 1
|
||||||
|
fan_below_layer_time = 100
|
||||||
|
filament_colour = #DEE0E6
|
||||||
|
filament_max_volumetric_speed = 4
|
||||||
|
filament_type = PP
|
||||||
|
first_layer_bed_temperature = 85
|
||||||
|
bed_temperature = 85
|
||||||
|
first_layer_temperature = 235
|
||||||
|
max_fan_speed = 70
|
||||||
|
min_fan_speed = 70
|
||||||
|
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.02{elsif nozzle_diameter[0]==0.6}0.05{else}0.1{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K28{elsif nozzle_diameter[0]==0.8};{else}M900 K48{endif} ; Filament gcode LA 1.0"
|
||||||
|
temperature = 235
|
||||||
|
filament_wipe = 0
|
||||||
|
filament_retract_lift = 0
|
||||||
|
compatible_printers_condition = nozzle_diameter[0]>=0.35 and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||||
|
|
||||||
|
[filament:FormFutura Centaur PP @MINI]
|
||||||
|
inherits = FormFutura Centaur PP
|
||||||
|
filament_max_volumetric_speed = 3
|
||||||
|
filament_retract_length = 3.5
|
||||||
|
filament_retract_speed = 45
|
||||||
|
filament_deretract_speed = 20
|
||||||
|
filament_retract_lift = 0
|
||||||
|
filament_retract_before_travel = 4
|
||||||
|
compatible_printers_condition = nozzle_diameter[0]>=0.35 and printer_model=="MINI"
|
||||||
|
|
||||||
## Filaments MMU1
|
## Filaments MMU1
|
||||||
|
|
||||||
[filament:ColorFabb HT @MMU1]
|
[filament:ColorFabb HT @MMU1]
|
||||||
@ -5775,6 +5957,30 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.025]
|
||||||
|
inherits = *common 0.025*
|
||||||
|
exposure_time = 7
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.025]
|
||||||
|
inherits = *common 0.025*
|
||||||
|
exposure_time = 7
|
||||||
|
initial_exposure_time = 35
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.025]
|
||||||
|
inherits = *common 0.025*
|
||||||
|
exposure_time = 6
|
||||||
|
initial_exposure_time = 35
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
|
||||||
## Prusa 0.025
|
## Prusa 0.025
|
||||||
|
|
||||||
[sla_material:Prusa Orange Tough @0.025]
|
[sla_material:Prusa Orange Tough @0.025]
|
||||||
@ -6732,6 +6938,30 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.05]
|
||||||
|
inherits = *common 0.05*
|
||||||
|
exposure_time = 8
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.05]
|
||||||
|
inherits = *common 0.05*
|
||||||
|
exposure_time = 8
|
||||||
|
initial_exposure_time = 35
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.05]
|
||||||
|
inherits = *common 0.05*
|
||||||
|
exposure_time = 7
|
||||||
|
initial_exposure_time = 35
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
|
||||||
## Prusa 0.05
|
## Prusa 0.05
|
||||||
|
|
||||||
[sla_material:Prusa Beige Tough @0.05]
|
[sla_material:Prusa Beige Tough @0.05]
|
||||||
@ -7120,6 +7350,30 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.1]
|
||||||
|
inherits = *common 0.1*
|
||||||
|
exposure_time = 13
|
||||||
|
initial_exposure_time = 45
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.1]
|
||||||
|
inherits = *common 0.1*
|
||||||
|
exposure_time = 13
|
||||||
|
initial_exposure_time = 45
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.1]
|
||||||
|
inherits = *common 0.1*
|
||||||
|
exposure_time = 8
|
||||||
|
initial_exposure_time = 35
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
|
||||||
## Prusa 0.1
|
## Prusa 0.1
|
||||||
|
|
||||||
[sla_material:Prusa Orange Tough @0.1]
|
[sla_material:Prusa Orange Tough @0.1]
|
||||||
@ -7336,6 +7590,31 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.025 SL1S]
|
||||||
|
inherits = *0.025_sl1s*
|
||||||
|
exposure_time = 3.5
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.025 SL1S]
|
||||||
|
inherits = *0.025_sl1s*
|
||||||
|
exposure_time = 3.5
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.025 SL1S]
|
||||||
|
inherits = *0.025_sl1s*
|
||||||
|
exposure_time = 2.8
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
## Made for Prusa 0.025
|
## Made for Prusa 0.025
|
||||||
|
|
||||||
[sla_material:Prusa Orange Tough @0.025 SL1S]
|
[sla_material:Prusa Orange Tough @0.025 SL1S]
|
||||||
@ -7531,6 +7810,15 @@ material_type = Flexible
|
|||||||
material_vendor = BASF
|
material_vendor = BASF
|
||||||
material_colour = #595959
|
material_colour = #595959
|
||||||
|
|
||||||
|
[sla_material:BlueCast X-One @0.025 SL1S]
|
||||||
|
inherits = *0.025_sl1s*
|
||||||
|
exposure_time = 6
|
||||||
|
initial_exposure_time = 25
|
||||||
|
material_type = Casting
|
||||||
|
material_vendor = BlueCast
|
||||||
|
material_colour = #C0C0C0
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
[sla_material:PrimaCreator Tough Light Grey @0.025 SL1S]
|
[sla_material:PrimaCreator Tough Light Grey @0.025 SL1S]
|
||||||
inherits = *0.025_sl1s*
|
inherits = *0.025_sl1s*
|
||||||
exposure_time = 1.8
|
exposure_time = 1.8
|
||||||
@ -7754,6 +8042,31 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.05 SL1S]
|
||||||
|
inherits = *0.05_sl1s*
|
||||||
|
exposure_time = 4
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.05 SL1S]
|
||||||
|
inherits = *0.05_sl1s*
|
||||||
|
exposure_time = 4
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.05 SL1S]
|
||||||
|
inherits = *0.05_sl1s*
|
||||||
|
exposure_time = 3
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
## Made for Prusa 0.05
|
## Made for Prusa 0.05
|
||||||
|
|
||||||
[sla_material:Prusa Orange Tough @0.05 SL1S]
|
[sla_material:Prusa Orange Tough @0.05 SL1S]
|
||||||
@ -8128,6 +8441,15 @@ material_type = Tough
|
|||||||
material_vendor = BlueCast
|
material_vendor = BlueCast
|
||||||
material_colour = #007EFD
|
material_colour = #007EFD
|
||||||
|
|
||||||
|
[sla_material:BlueCast X-One @0.05 SL1S]
|
||||||
|
inherits = *0.05_sl1s*
|
||||||
|
exposure_time = 7
|
||||||
|
initial_exposure_time = 25
|
||||||
|
material_type = Casting
|
||||||
|
material_vendor = BlueCast
|
||||||
|
material_colour = #C0C0C0
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
[sla_material:NextDent Model 2.0 Grey @0.05 SL1S]
|
[sla_material:NextDent Model 2.0 Grey @0.05 SL1S]
|
||||||
inherits = *0.05_sl1s*
|
inherits = *0.05_sl1s*
|
||||||
exposure_time = 4
|
exposure_time = 4
|
||||||
@ -8476,6 +8798,31 @@ material_type = Tough
|
|||||||
material_vendor = Prusa Polymers
|
material_vendor = Prusa Polymers
|
||||||
material_colour = #FCB30E
|
material_colour = #FCB30E
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Herbal Green @0.1 SL1S]
|
||||||
|
inherits = *0.1_sl1s*
|
||||||
|
exposure_time = 5
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #3AD200
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Magma Red @0.1 SL1S]
|
||||||
|
inherits = *0.1_sl1s*
|
||||||
|
exposure_time = 5
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #D20202
|
||||||
|
|
||||||
|
[sla_material:Prusament Resin BioBased60 Natural Yellow @0.1 SL1S]
|
||||||
|
inherits = *0.1_sl1s*
|
||||||
|
exposure_time = 4
|
||||||
|
initial_exposure_time = 30
|
||||||
|
material_type = Tough
|
||||||
|
material_vendor = Prusa Polymers
|
||||||
|
material_colour = #ECDE05
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
## Made for Prusa 0.1
|
## Made for Prusa 0.1
|
||||||
|
|
||||||
[sla_material:Prusa Orange Tough @0.1 SL1S]
|
[sla_material:Prusa Orange Tough @0.1 SL1S]
|
||||||
@ -8671,6 +9018,15 @@ material_type = Flexible
|
|||||||
material_vendor = BASF
|
material_vendor = BASF
|
||||||
material_colour = #595959
|
material_colour = #595959
|
||||||
|
|
||||||
|
[sla_material:BlueCast X-One @0.1 SL1S]
|
||||||
|
inherits = *0.1_sl1s*
|
||||||
|
exposure_time = 8.5
|
||||||
|
initial_exposure_time = 25
|
||||||
|
material_type = Casting
|
||||||
|
material_vendor = BlueCast
|
||||||
|
material_colour = #C0C0C0
|
||||||
|
material_print_speed = slow
|
||||||
|
|
||||||
[sla_material:PrimaCreator Tough Light Grey @0.1 SL1S]
|
[sla_material:PrimaCreator Tough Light Grey @0.1 SL1S]
|
||||||
inherits = *0.1_sl1s*
|
inherits = *0.1_sl1s*
|
||||||
exposure_time = 3
|
exposure_time = 3
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// execute fn for each pixel on the line. If fn returns false, terminate the iteration
|
||||||
template<typename PointFn> void dda(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
|
template<typename PointFn> void dda(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
|
||||||
{
|
{
|
||||||
coord_t dx = abs(x1 - x0);
|
coord_t dx = abs(x1 - x0);
|
||||||
@ -39,7 +40,7 @@ template<typename PointFn> void dda(coord_t x0, coord_t y0, coord_t x1, coord_t
|
|||||||
dy *= 2;
|
dy *= 2;
|
||||||
|
|
||||||
for (; n > 0; --n) {
|
for (; n > 0; --n) {
|
||||||
fn(x, y);
|
if (!fn(x, y)) return;
|
||||||
|
|
||||||
if (error > 0) {
|
if (error > 0) {
|
||||||
x += x_inc;
|
x += x_inc;
|
||||||
@ -58,8 +59,8 @@ template<typename PointFn> void double_dda_with_offset(coord_t x0, coord_t y0, c
|
|||||||
Vec2d normal = Point{y1 - y0, x1 - x0}.cast<double>().normalized();
|
Vec2d normal = Point{y1 - y0, x1 - x0}.cast<double>().normalized();
|
||||||
normal.x() = ceil(normal.x());
|
normal.x() = ceil(normal.x());
|
||||||
normal.y() = ceil(normal.y());
|
normal.y() = ceil(normal.y());
|
||||||
Point start_offset = Point(x0,y0) + (normal).cast<coord_t>();
|
Point start_offset = Point(x0, y0) + (normal).cast<coord_t>();
|
||||||
Point end_offset = Point(x1,y1) + (normal).cast<coord_t>();
|
Point end_offset = Point(x1, y1) + (normal).cast<coord_t>();
|
||||||
|
|
||||||
dda(x0, y0, x1, y1, fn);
|
dda(x0, y0, x1, y1, fn);
|
||||||
dda(start_offset.x(), start_offset.y(), end_offset.x(), end_offset.y(), fn);
|
dda(start_offset.x(), start_offset.y(), end_offset.x(), end_offset.y(), fn);
|
||||||
@ -169,7 +170,10 @@ public:
|
|||||||
|
|
||||||
float goal_heuristic(Node n) const { return n.position == target ? -1.f : (target - n.position).template cast<double>().norm(); }
|
float goal_heuristic(Node n) const { return n.position == target ? -1.f : (target - n.position).template cast<double>().norm(); }
|
||||||
|
|
||||||
size_t unique_id(Node n) const { return (static_cast<size_t>(uint16_t(n.position.x())) << 16) + static_cast<size_t>(uint16_t(n.position.y())); }
|
size_t unique_id(Node n) const
|
||||||
|
{
|
||||||
|
return (static_cast<size_t>(uint16_t(n.position.x())) << 16) + static_cast<size_t>(uint16_t(n.position.y()));
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<CellPositionType> all_directions{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
|
const std::vector<CellPositionType> all_directions{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
|
||||||
};
|
};
|
||||||
@ -189,6 +193,7 @@ void JPSPathFinder::add_obstacles(const Lines &obstacles)
|
|||||||
obstacle_min.x() = std::min(obstacle_min.x(), x);
|
obstacle_min.x() = std::min(obstacle_min.x(), x);
|
||||||
obstacle_min.y() = std::min(obstacle_min.y(), y);
|
obstacle_min.y() = std::min(obstacle_min.y(), y);
|
||||||
inpassable.insert(Pixel{x, y});
|
inpassable.insert(Pixel{x, y});
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const Line &l : obstacles) {
|
for (const Line &l : obstacles) {
|
||||||
@ -200,36 +205,13 @@ void JPSPathFinder::add_obstacles(const Lines &obstacles)
|
|||||||
|
|
||||||
void JPSPathFinder::add_obstacles(const Layer *layer, const Point &global_origin)
|
void JPSPathFinder::add_obstacles(const Layer *layer, const Point &global_origin)
|
||||||
{
|
{
|
||||||
if (layer != nullptr) { this->print_z = layer->print_z; }
|
if (layer == nullptr) return;
|
||||||
|
|
||||||
auto store_obstacle = [&](coord_t x, coord_t y) {
|
this->print_z = layer->print_z;
|
||||||
obstacle_max.x() = std::max(obstacle_max.x(), x);
|
|
||||||
obstacle_max.y() = std::max(obstacle_max.y(), y);
|
|
||||||
obstacle_min.x() = std::min(obstacle_min.x(), x);
|
|
||||||
obstacle_min.y() = std::min(obstacle_min.y(), y);
|
|
||||||
inpassable.insert(Pixel{x, y});
|
|
||||||
};
|
|
||||||
Lines obstacles;
|
Lines obstacles;
|
||||||
for (size_t step = 0; step < 3; step++) {
|
obstacles.reserve(layer->malformed_lines.size());
|
||||||
if (layer != nullptr) {
|
for (const Line &l : layer->malformed_lines) { obstacles.push_back(Line{l.a + global_origin, l.b + global_origin}); }
|
||||||
obstacles.insert(obstacles.end(), layer->malformed_lines.begin(), layer->malformed_lines.end());
|
add_obstacles(obstacles);
|
||||||
layer = layer->lower_layer;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const Line &l : obstacles) {
|
|
||||||
Pixel start = pixelize(l.a + global_origin);
|
|
||||||
Pixel end = pixelize(l.b + global_origin);
|
|
||||||
double_dda_with_offset(start.x(), start.y(), end.x(), end.y(), store_obstacle);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_FILES
|
|
||||||
::Slic3r::SVG svg(debug_out_path(("obstacles_jps" + std::to_string(print_z) + "_" + std::to_string(rand() % 1000)).c_str()).c_str(),
|
|
||||||
get_extents(obstacles));
|
|
||||||
svg.draw(obstacles);
|
|
||||||
svg.Close();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
||||||
@ -238,15 +220,34 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
|||||||
Pixel end = pixelize(p1);
|
Pixel end = pixelize(p1);
|
||||||
if (inpassable.empty() || (start - end).cast<float>().norm() < 3.0) { return Polyline{p0, p1}; }
|
if (inpassable.empty() || (start - end).cast<float>().norm() < 3.0) { return Polyline{p0, p1}; }
|
||||||
|
|
||||||
BoundingBox search_box({start,end,obstacle_max,obstacle_min});
|
if (inpassable.find(start) != inpassable.end()) {
|
||||||
search_box.max += Pixel(1,1);
|
dda(start.x(), start.y(), end.x(), end.y(), [&](coord_t x, coord_t y) {
|
||||||
search_box.min -= Pixel(1,1);
|
if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
|
||||||
|
start = Pixel(x, y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inpassable.find(end) != inpassable.end()) {
|
||||||
|
dda(end.x(), end.y(), start.x(), start.y(), [&](coord_t x, coord_t y) {
|
||||||
|
if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
|
||||||
|
end = Pixel(x, y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox bounding_square(Points{start,end});
|
BoundingBox search_box({start, end, obstacle_max, obstacle_min});
|
||||||
bounding_square.max += Pixel(5,5);
|
search_box.max += Pixel(1, 1);
|
||||||
bounding_square.min -= Pixel(5,5);
|
search_box.min -= Pixel(1, 1);
|
||||||
coord_t bounding_square_size = 2*std::max(bounding_square.size().x(),bounding_square.size().y());
|
|
||||||
|
BoundingBox bounding_square(Points{start, end});
|
||||||
|
bounding_square.max += Pixel(5, 5);
|
||||||
|
bounding_square.min -= Pixel(5, 5);
|
||||||
|
coord_t bounding_square_size = 2 * std::max(bounding_square.size().x(), bounding_square.size().y());
|
||||||
bounding_square.max.x() += (bounding_square_size - bounding_square.size().x()) / 2;
|
bounding_square.max.x() += (bounding_square_size - bounding_square.size().x()) / 2;
|
||||||
bounding_square.min.x() -= (bounding_square_size - bounding_square.size().x()) / 2;
|
bounding_square.min.x() -= (bounding_square_size - bounding_square.size().x()) / 2;
|
||||||
bounding_square.max.y() += (bounding_square_size - bounding_square.size().y()) / 2;
|
bounding_square.max.y() += (bounding_square_size - bounding_square.size().y()) / 2;
|
||||||
@ -283,9 +284,7 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
|||||||
closest_qnode = astar_cache[closest_qnode].parent;
|
closest_qnode = astar_cache[closest_qnode].parent;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const auto& node : out_nodes) {
|
for (const auto &node : out_nodes) { out_path.push_back(node.position); }
|
||||||
out_path.push_back(node.position);
|
|
||||||
}
|
|
||||||
out_path.push_back(start);
|
out_path.push_back(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +334,11 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
|||||||
if (i - index_of_last_stored_point < 2) continue;
|
if (i - index_of_last_stored_point < 2) continue;
|
||||||
bool passable = true;
|
bool passable = true;
|
||||||
auto store_obstacle = [&](coord_t x, coord_t y) {
|
auto store_obstacle = [&](coord_t x, coord_t y) {
|
||||||
if (Pixel(x, y) != start && Pixel(x, y) != end && inpassable.find(Pixel(x, y)) != inpassable.end()) { passable = false; };
|
if (Pixel(x, y) != start && Pixel(x, y) != end && inpassable.find(Pixel(x, y)) != inpassable.end()) {
|
||||||
|
passable = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
dda(tmp_path.back().x(), tmp_path.back().y(), out_path[i].x(), out_path[i].y(), store_obstacle);
|
dda(tmp_path.back().x(), tmp_path.back().y(), out_path[i].x(), out_path[i].y(), store_obstacle);
|
||||||
if (!passable) {
|
if (!passable) {
|
||||||
|
@ -339,32 +339,9 @@ void MeasuringImpl::extract_features()
|
|||||||
}
|
}
|
||||||
circles_lengths.clear(); // no longer needed, make it obvious
|
circles_lengths.clear(); // no longer needed, make it obvious
|
||||||
|
|
||||||
// Some of the "circles" may actually be polygons (5-8 vertices). We want them
|
|
||||||
// detected as edges, but also to remember the center and save it into those edges.
|
|
||||||
// We will add all such edges manually and delete the detected circles, leaving it
|
|
||||||
// in circles_idxs so they are not picked again.
|
|
||||||
assert(circles.size() == circles_idxs.size());
|
|
||||||
for (int i=circles.size()-1; i>=0; --i) {
|
|
||||||
if (circles_idxs[i].first == 0 && circles_idxs[i].second == border.size()-1) {
|
|
||||||
int N = circles_idxs[i].second - circles_idxs[i].first;
|
|
||||||
if (N <= 8) {
|
|
||||||
if (N >= 5) { // polygon = 5,6,7,8 vertices
|
|
||||||
const Vec3d center = std::get<0>(circles[i].get_circle());
|
|
||||||
for (int j=(int)circles_idxs[i].first + 1; j<=(int)circles_idxs[i].second; ++j)
|
|
||||||
edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge,
|
|
||||||
border[j - 1], border[j], std::make_optional(center)));
|
|
||||||
} else {
|
|
||||||
// This will be handled just like a regular edge (squares, triangles).
|
|
||||||
circles_idxs.erase(circles_idxs.begin() + i);
|
|
||||||
}
|
|
||||||
circles.erase(circles.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anything under 5 vertices shall not be considered a circle.
|
// Anything under 5 vertices shall not be considered a circle.
|
||||||
assert(circles_idxs.size() == circles.size());
|
assert(circles_idxs.size() == circles.size());
|
||||||
for (int i=0; i<int(circles_idxs.size()); ++i) {
|
for (int i=int(circles_idxs.size())-1; i>=0; --i) {
|
||||||
const auto& [start, end] = circles_idxs[i];
|
const auto& [start, end] = circles_idxs[i];
|
||||||
int N = start >= 0
|
int N = start >= 0
|
||||||
? end - start + (start == 0 && end == border.size()-1 ? 0 : 1) // last point is the same as first
|
? end - start + (start == 0 && end == border.size()-1 ? 0 : 1) // last point is the same as first
|
||||||
@ -372,7 +349,15 @@ void MeasuringImpl::extract_features()
|
|||||||
if (N < 5) {
|
if (N < 5) {
|
||||||
circles.erase(circles.begin() + i);
|
circles.erase(circles.begin() + i);
|
||||||
circles_idxs.erase(circles_idxs.begin() + i);
|
circles_idxs.erase(circles_idxs.begin() + i);
|
||||||
--i;
|
} else if (N <= 8 && start == 0 && end == border.size()-1) {
|
||||||
|
// This is a regular 5-8 polygon. Add the edges as edges with a special
|
||||||
|
// point and remove the circle. Leave the indices in circles_idxs, so
|
||||||
|
// the edges are not picked up again later.
|
||||||
|
const Vec3d center = std::get<0>(circles[i].get_circle());
|
||||||
|
for (int j=1; j<=end; ++j)
|
||||||
|
edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge,
|
||||||
|
border[j - 1], border[j], std::make_optional(center)));
|
||||||
|
circles.erase(circles.begin() + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,54 +768,47 @@ ExtrusionPaths sort_and_connect_extra_perimeters(const std::vector<ExtrusionPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define EXTRA_PERIMETER_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
|
#define EXTRA_PERIMETER_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
|
||||||
//#define EXTRA_PERIM_DEBUG_FILES
|
// #define EXTRA_PERIM_DEBUG_FILES
|
||||||
// Function will generate extra perimeters clipped over nonbridgeable areas of the provided surface and returns both the new perimeters and
|
// Function will generate extra perimeters clipped over nonbridgeable areas of the provided surface and returns both the new perimeters and
|
||||||
// Polygons filled by those clipped perimeters
|
// Polygons filled by those clipped perimeters
|
||||||
std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over_overhangs(const Surface &surface,
|
std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over_overhangs(ExPolygons infill_area,
|
||||||
ExPolygons infill_area,
|
|
||||||
const Polygons &lower_slices_polygons,
|
const Polygons &lower_slices_polygons,
|
||||||
const Flow &overhang_flow,
|
const Flow &overhang_flow,
|
||||||
size_t standard_perimeters_count,
|
|
||||||
double scaled_resolution,
|
double scaled_resolution,
|
||||||
const PrintObjectConfig &object_config,
|
const PrintObjectConfig &object_config,
|
||||||
const PrintConfig &print_config)
|
const PrintConfig &print_config)
|
||||||
{
|
{
|
||||||
coord_t anchors_size = scale_(EXTERNAL_INFILL_MARGIN);
|
coord_t anchors_size = scale_(EXTERNAL_INFILL_MARGIN);
|
||||||
|
|
||||||
ExPolygons local_area = intersection_ex({surface.expolygon}, infill_area);
|
Polygons anchors = intersection(infill_area, lower_slices_polygons);
|
||||||
ExPolygons anchors = intersection_ex(local_area, lower_slices_polygons);
|
Polygons overhangs = diff(infill_area, lower_slices_polygons);
|
||||||
ExPolygons overhangs = diff_ex(local_area, lower_slices_polygons);
|
if (overhangs.empty()) { return {}; }
|
||||||
if (overhangs.empty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ExPolygons inset_anchors; // anchored area inset by the anchor length
|
Polygons inset_anchors; // anchored area inset by the anchor length
|
||||||
{
|
{
|
||||||
std::vector<double> deltas{anchors_size * 0.15 + 0.5 * overhang_flow.scaled_spacing(),
|
std::vector<double> deltas{anchors_size * 0.15 + 0.5 * overhang_flow.scaled_spacing(),
|
||||||
anchors_size * 0.33 + 0.5 * overhang_flow.scaled_spacing(),
|
anchors_size * 0.33 + 0.5 * overhang_flow.scaled_spacing(),
|
||||||
anchors_size * 0.66 + 0.5 * overhang_flow.scaled_spacing(), anchors_size * 1.00};
|
anchors_size * 0.66 + 0.5 * overhang_flow.scaled_spacing(), anchors_size * 1.00};
|
||||||
|
|
||||||
std::vector<ExPolygons> anchor_areas_w_delta_anchor_size{};
|
std::vector<Polygons> anchor_areas_w_delta_anchor_size{};
|
||||||
for (double delta : deltas) {
|
for (double delta : deltas) {
|
||||||
anchor_areas_w_delta_anchor_size.push_back(diff_ex(anchors, offset_ex(overhangs, delta, EXTRA_PERIMETER_OFFSET_PARAMETERS)));
|
anchor_areas_w_delta_anchor_size.push_back(diff(anchors, expand(overhangs, delta, EXTRA_PERIMETER_OFFSET_PARAMETERS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size() - 1; i++) {
|
for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size() - 1; i++) {
|
||||||
ExPolygons clipped = diff_ex(anchor_areas_w_delta_anchor_size[i], offset_ex(anchor_areas_w_delta_anchor_size[i + 1],
|
Polygons clipped = diff(anchor_areas_w_delta_anchor_size[i], expand(anchor_areas_w_delta_anchor_size[i + 1],
|
||||||
deltas[i + 1], EXTRA_PERIMETER_OFFSET_PARAMETERS));
|
deltas[i + 1], EXTRA_PERIMETER_OFFSET_PARAMETERS));
|
||||||
anchor_areas_w_delta_anchor_size[i] = intersection_ex(anchor_areas_w_delta_anchor_size[i],
|
anchor_areas_w_delta_anchor_size[i] = intersection(anchor_areas_w_delta_anchor_size[i],
|
||||||
offset_ex(clipped, deltas[i] + deltas[i + 1],
|
expand(clipped, deltas[i+1] + 0.1*overhang_flow.scaled_spacing(),
|
||||||
EXTRA_PERIMETER_OFFSET_PARAMETERS));
|
EXTRA_PERIMETER_OFFSET_PARAMETERS));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size(); i++) {
|
for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size(); i++) {
|
||||||
inset_anchors.insert(inset_anchors.end(), anchor_areas_w_delta_anchor_size[i].begin(),
|
inset_anchors = union_(inset_anchors, anchor_areas_w_delta_anchor_size[i]);
|
||||||
anchor_areas_w_delta_anchor_size[i].end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inset_anchors = union_ex(inset_anchors);
|
inset_anchors = opening(inset_anchors, 0.8 * deltas[0], EXTRA_PERIMETER_OFFSET_PARAMETERS);
|
||||||
inset_anchors = closing_ex(to_polygons(inset_anchors), 1.0 * overhang_flow.scaled_spacing(), 1.0 * overhang_flow.scaled_spacing(),
|
inset_anchors = closing(inset_anchors, 0.8 * deltas[0], EXTRA_PERIMETER_OFFSET_PARAMETERS);
|
||||||
EXTRA_PERIMETER_OFFSET_PARAMETERS);
|
|
||||||
|
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
{
|
{
|
||||||
@ -832,58 +825,57 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons inset_overhang_area = diff_ex(local_area, inset_anchors);
|
Polygons inset_overhang_area = diff(infill_area, inset_anchors);
|
||||||
ExPolygons repeated_area = offset_ex(intersection_ex(offset_ex(inset_overhang_area, 1.10 * overhang_flow.scaled_spacing(),
|
|
||||||
EXTRA_PERIMETER_OFFSET_PARAMETERS),
|
|
||||||
inset_anchors),
|
|
||||||
0.1 * overhang_flow.scaled_spacing(), EXTRA_PERIMETER_OFFSET_PARAMETERS);
|
|
||||||
|
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
{
|
{
|
||||||
BoundingBox bbox = get_extents(inset_overhangs_w_anchors);
|
BoundingBox bbox = get_extents(inset_overhang_area);
|
||||||
bbox.offset(scale_(1.));
|
bbox.offset(scale_(1.));
|
||||||
::Slic3r::SVG svg(debug_out_path("inset_overhangs_w_anchors").c_str(), bbox);
|
::Slic3r::SVG svg(debug_out_path("inset_overhang_area").c_str(), bbox);
|
||||||
for (const Line &line : to_lines(inset_overhangs_w_anchors)) svg.draw(line, "purple", scale_(0.25));
|
for (const Line &line : to_lines(inset_anchors)) svg.draw(line, "purple", scale_(0.25));
|
||||||
for (const Line &line : to_lines(inset_overhang_area)) svg.draw(line, "red", scale_(0.20));
|
for (const Line &line : to_lines(inset_overhang_area)) svg.draw(line, "red", scale_(0.15));
|
||||||
for (const Line &line : to_lines(repeated_area)) svg.draw(line, "green", scale_(0.15));
|
|
||||||
for (const Line &line : to_lines(inset_anchors)) svg.draw(line, "yellow", scale_(0.10));
|
|
||||||
svg.Close();
|
svg.Close();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Polygons area_left_unfilled;
|
Polygons inset_overhang_area_left_unfilled;
|
||||||
|
|
||||||
std::vector<std::vector<ExtrusionPaths>> extra_perims; // overhang region -> shell -> shell parts
|
std::vector<std::vector<ExtrusionPaths>> extra_perims; // overhang region -> shell -> shell parts
|
||||||
for (const ExPolygon &overhang : inset_overhang_area) {
|
for (const ExPolygon &overhang : union_ex(to_expolygons(inset_overhang_area))) {
|
||||||
ExPolygons overhang_to_cover = {overhang};
|
Polygons overhang_to_cover = to_polygons(overhang);
|
||||||
overhang_to_cover.insert(overhang_to_cover.end(), repeated_area.begin(), repeated_area.end());
|
Polygons expanded_overhang_to_cover = expand(overhang_to_cover, 1.1 * overhang_flow.scaled_spacing());
|
||||||
overhang_to_cover = union_ex(overhang_to_cover);
|
Polygons shrinked_overhang_to_cover = shrink(overhang_to_cover, 0.1 * overhang_flow.scaled_spacing());
|
||||||
|
|
||||||
ExPolygons real_overhang = intersection_ex({overhang_to_cover}, overhangs);
|
Polygons real_overhang = intersection(overhang_to_cover, overhangs);
|
||||||
if (real_overhang.empty()) {
|
if (real_overhang.empty()) {
|
||||||
area_left_unfilled = union_(area_left_unfilled, to_polygons(overhang_to_cover));
|
inset_overhang_area_left_unfilled.insert(inset_overhang_area_left_unfilled.end(), overhang_to_cover.begin(),
|
||||||
|
overhang_to_cover.end());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
extra_perims.emplace_back();
|
extra_perims.emplace_back();
|
||||||
std::vector<ExtrusionPaths> &overhang_region = extra_perims.back();
|
std::vector<ExtrusionPaths> &overhang_region = extra_perims.back();
|
||||||
|
|
||||||
ExPolygons anchoring = intersection_ex({overhang_to_cover}, inset_anchors);
|
Polygons anchoring = intersection(expanded_overhang_to_cover, inset_anchors);
|
||||||
ExPolygons perimeter_polygon = offset_ex(overhang_to_cover, -overhang_flow.scaled_spacing() * 0.6);
|
Polygons perimeter_polygon = offset(union_(expand(overhang_to_cover, 0.1 * overhang_flow.scaled_spacing()), anchoring),
|
||||||
|
-overhang_flow.scaled_spacing() * 0.6);
|
||||||
|
|
||||||
double perimeter_polygon_area = area(perimeter_polygon);
|
|
||||||
Polygon anchoring_convex_hull = Geometry::convex_hull(anchoring);
|
Polygon anchoring_convex_hull = Geometry::convex_hull(anchoring);
|
||||||
double unbridgeable_area = area(diff_ex(perimeter_polygon, {anchoring_convex_hull}));
|
double unbridgeable_area = area(diff(real_overhang, {anchoring_convex_hull}));
|
||||||
for (const ExPolygon &exp : perimeter_polygon) {
|
// penalize also holes
|
||||||
for (const Polygon &hole : exp.holes) { unbridgeable_area += std::abs(area(hole)); }
|
for (const Polygon &poly : perimeter_polygon) {
|
||||||
|
if (poly.is_clockwise()) { // hole, penalize bridges.
|
||||||
|
unbridgeable_area += std::abs(area(poly));
|
||||||
}
|
}
|
||||||
auto [dir, unsupp_dist] = detect_bridging_direction(to_polygons(real_overhang), to_polygons(anchors));
|
}
|
||||||
|
|
||||||
|
auto [dir, unsupp_dist] = detect_bridging_direction(real_overhang, anchors);
|
||||||
|
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
{
|
{
|
||||||
BoundingBox bbox = get_extents(inset_overhang_area);
|
BoundingBox bbox = get_extents(anchoring_convex_hull);
|
||||||
bbox.offset(scale_(1.));
|
bbox.offset(scale_(1.));
|
||||||
::Slic3r::SVG svg(debug_out_path(("bridge_check").c_str()).c_str(), bbox);
|
::Slic3r::SVG svg(debug_out_path("bridge_check").c_str(), bbox);
|
||||||
for (const Line &line : to_lines(perimeter_polygon)) svg.draw(line, "purple", scale_(0.25));
|
for (const Line &line : to_lines(perimeter_polygon)) svg.draw(line, "purple", scale_(0.25));
|
||||||
for (const Line &line : to_lines(real_overhang)) svg.draw(line, "red", scale_(0.20));
|
for (const Line &line : to_lines(real_overhang)) svg.draw(line, "red", scale_(0.20));
|
||||||
for (const Line &line : to_lines(anchoring_convex_hull)) svg.draw(line, "green", scale_(0.15));
|
for (const Line &line : to_lines(anchoring_convex_hull)) svg.draw(line, "green", scale_(0.15));
|
||||||
@ -892,10 +884,8 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
svg.Close();
|
svg.Close();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (unbridgeable_area < 0.2 * area(real_overhang) && unsupp_dist < total_length(real_overhang) * 0.125) {
|
||||||
auto total_length_of_real_overhang = total_length(to_polygons(real_overhang));
|
inset_overhang_area_left_unfilled.insert(inset_overhang_area_left_unfilled.end(),overhang_to_cover.begin(),overhang_to_cover.end());
|
||||||
if (unbridgeable_area < 0.2 * perimeter_polygon_area && unsupp_dist < total_length_of_real_overhang * 0.5) {
|
|
||||||
area_left_unfilled = union_(area_left_unfilled, to_polygons(overhang_to_cover));
|
|
||||||
perimeter_polygon.clear();
|
perimeter_polygon.clear();
|
||||||
} else {
|
} else {
|
||||||
// fill the overhang with perimeters
|
// fill the overhang with perimeters
|
||||||
@ -903,16 +893,15 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
while (continuation_loops > 0) {
|
while (continuation_loops > 0) {
|
||||||
auto prev = perimeter_polygon;
|
auto prev = perimeter_polygon;
|
||||||
// prepare next perimeter lines
|
// prepare next perimeter lines
|
||||||
Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), inset_overhang_area);
|
Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), shrinked_overhang_to_cover);
|
||||||
|
|
||||||
// do not add the perimeter to result yet, first check if perimeter_polygon is not empty after shrinking - this would mean
|
// do not add the perimeter to result yet, first check if perimeter_polygon is not empty after shrinking - this would mean
|
||||||
// that the polygon was possibly too small for full perimeter loop and in that case try gap fill first
|
// that the polygon was possibly too small for full perimeter loop and in that case try gap fill first
|
||||||
perimeter_polygon.insert(perimeter_polygon.end(), anchoring.begin(), anchoring.end());
|
perimeter_polygon = union_(perimeter_polygon, anchoring);
|
||||||
perimeter_polygon = union_ex(perimeter_polygon);
|
perimeter_polygon = intersection(offset(perimeter_polygon, -overhang_flow.scaled_spacing()), expanded_overhang_to_cover);
|
||||||
perimeter_polygon = intersection_ex({overhang_to_cover}, offset_ex(perimeter_polygon, -overhang_flow.scaled_spacing()));
|
|
||||||
|
|
||||||
if (perimeter_polygon.empty()) { // fill possible gaps of single extrusion width
|
if (perimeter_polygon.empty()) { // fill possible gaps of single extrusion width
|
||||||
ExPolygons shrinked = offset_ex(prev, -0.4 * overhang_flow.scaled_spacing());
|
Polygons shrinked = offset(prev, -0.4 * overhang_flow.scaled_spacing());
|
||||||
if (!shrinked.empty()) {
|
if (!shrinked.empty()) {
|
||||||
overhang_region.emplace_back();
|
overhang_region.emplace_back();
|
||||||
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(),
|
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(),
|
||||||
@ -922,8 +911,10 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
Polylines fills;
|
Polylines fills;
|
||||||
ExPolygons gap = shrinked.empty() ? offset_ex(prev, overhang_flow.scaled_spacing() * 0.5) :
|
ExPolygons gap = shrinked.empty() ? offset_ex(prev, overhang_flow.scaled_spacing() * 0.5) :
|
||||||
offset_ex(prev, -overhang_flow.scaled_spacing() * 0.5);
|
offset_ex(prev, -overhang_flow.scaled_spacing() * 0.5);
|
||||||
|
|
||||||
|
//gap = expolygons_simplify(gap, overhang_flow.scaled_spacing());
|
||||||
for (const ExPolygon &ep : gap) {
|
for (const ExPolygon &ep : gap) {
|
||||||
ep.medial_axis(overhang_flow.scaled_spacing() * 2.0, 0.35 * overhang_flow.scaled_width(), &fills);
|
ep.medial_axis(overhang_flow.scaled_spacing() * 2.0, 0.3 * overhang_flow.scaled_width(), &fills);
|
||||||
}
|
}
|
||||||
if (!fills.empty()) {
|
if (!fills.empty()) {
|
||||||
fills = intersection_pl(fills, inset_overhang_area);
|
fills = intersection_pl(fills, inset_overhang_area);
|
||||||
@ -938,10 +929,7 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
overhang_flow.width(), overhang_flow.height());
|
overhang_flow.width(), overhang_flow.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intersection(perimeter_polygon, real_overhang).empty()) {
|
if (intersection(perimeter_polygon, real_overhang).empty()) { continuation_loops--; }
|
||||||
continuation_loops--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (prev == perimeter_polygon) {
|
if (prev == perimeter_polygon) {
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
@ -957,15 +945,14 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), inset_overhang_area);
|
Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), shrinked_overhang_to_cover);
|
||||||
overhang_region.emplace_back();
|
overhang_region.emplace_back();
|
||||||
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(),
|
extrusion_paths_append(overhang_region.back(), perimeter, erOverhangPerimeter, overhang_flow.mm3_per_mm(),
|
||||||
overhang_flow.width(), overhang_flow.height());
|
overhang_flow.width(), overhang_flow.height());
|
||||||
|
|
||||||
perimeter_polygon = offset_ex(perimeter_polygon, 0.5 * overhang_flow.scaled_spacing());
|
perimeter_polygon = expand(perimeter_polygon, 0.5 * overhang_flow.scaled_spacing());
|
||||||
perimeter_polygon.insert(perimeter_polygon.end(), anchoring.begin(), anchoring.end());
|
perimeter_polygon = union_(perimeter_polygon, anchoring);
|
||||||
perimeter_polygon = union_ex(perimeter_polygon);
|
inset_overhang_area_left_unfilled.insert(inset_overhang_area_left_unfilled.end(), perimeter_polygon.begin(),perimeter_polygon.end());
|
||||||
area_left_unfilled = union_(area_left_unfilled, to_polygons(perimeter_polygon));
|
|
||||||
|
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
BoundingBox bbox = get_extents(inset_overhang_area);
|
BoundingBox bbox = get_extents(inset_overhang_area);
|
||||||
@ -974,30 +961,32 @@ std::tuple<std::vector<ExtrusionPaths>, Polygons> generate_extra_perimeters_over
|
|||||||
for (const Line &line : to_lines(perimeter_polygon)) svg.draw(line, "blue", scale_(0.05));
|
for (const Line &line : to_lines(perimeter_polygon)) svg.draw(line, "blue", scale_(0.05));
|
||||||
for (const Line &line : to_lines(anchoring)) svg.draw(line, "green", scale_(0.05));
|
for (const Line &line : to_lines(anchoring)) svg.draw(line, "green", scale_(0.05));
|
||||||
for (const Line &line : to_lines(overhang_to_cover)) svg.draw(line, "yellow", scale_(0.05));
|
for (const Line &line : to_lines(overhang_to_cover)) svg.draw(line, "yellow", scale_(0.05));
|
||||||
for (const Line &line : to_lines(area_left_unfilled)) svg.draw(line, "red", scale_(0.05));
|
for (const Line &line : to_lines(inset_overhang_area_left_unfilled)) svg.draw(line, "red", scale_(0.05));
|
||||||
svg.Close();
|
svg.Close();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::reverse(overhang_region.begin(), overhang_region.end()); //reverse the order, It shall be printed from inside out
|
std::reverse(overhang_region.begin(), overhang_region.end()); // reverse the order, It shall be printed from inside out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ExtrusionPaths> result{};
|
std::vector<ExtrusionPaths> result{};
|
||||||
for (const std::vector<ExtrusionPaths> &paths : extra_perims) {
|
for (const std::vector<ExtrusionPaths> &paths : extra_perims) {
|
||||||
result.push_back(sort_and_connect_extra_perimeters(paths, 1.5 * overhang_flow.scaled_spacing()));
|
result.push_back(sort_and_connect_extra_perimeters(paths, 2.0 * overhang_flow.scaled_spacing()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXTRA_PERIM_DEBUG_FILES
|
#ifdef EXTRA_PERIM_DEBUG_FILES
|
||||||
BoundingBox bbox = get_extents(inset_overhang_area);
|
BoundingBox bbox = get_extents(inset_overhang_area);
|
||||||
bbox.offset(scale_(2.));
|
bbox.offset(scale_(2.));
|
||||||
::Slic3r::SVG svg(debug_out_path(("final" + std::to_string(rand())).c_str()).c_str(), bbox);
|
::Slic3r::SVG svg(debug_out_path(("final" + std::to_string(rand())).c_str()).c_str(), bbox);
|
||||||
for (const Line &line : to_lines(area_left_unfilled)) svg.draw(line, "blue", scale_(0.05));
|
for (const Line &line : to_lines(inset_overhang_area_left_unfilled)) svg.draw(line, "blue", scale_(0.05));
|
||||||
for (const Line &line : to_lines(inset_overhangs_w_anchors)) svg.draw(line, "green", scale_(0.05));
|
for (const Line &line : to_lines(inset_overhang_area)) svg.draw(line, "green", scale_(0.05));
|
||||||
for (const Line &line : to_lines(diff(inset_overhangs_w_anchors, area_left_unfilled))) svg.draw(line, "yellow", scale_(0.05));
|
for (const Line &line : to_lines(diff(inset_overhang_area, inset_overhang_area_left_unfilled))) svg.draw(line, "yellow", scale_(0.05));
|
||||||
svg.Close();
|
svg.Close();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return {result, diff(inset_overhang_area, area_left_unfilled)};
|
inset_overhang_area_left_unfilled = union_(inset_overhang_area_left_unfilled);
|
||||||
|
|
||||||
|
return {result, diff(inset_overhang_area, inset_overhang_area_left_unfilled)};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||||
@ -1215,31 +1204,23 @@ void PerimeterGenerator::process_arachne()
|
|||||||
// collapse too narrow infill areas
|
// collapse too narrow infill areas
|
||||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||||
// append infill areas to fill_surfaces
|
// append infill areas to fill_surfaces
|
||||||
this->fill_surfaces->append(
|
// append infill areas to fill_surfaces
|
||||||
offset2_ex(
|
ExPolygons infill_areas = offset2_ex(union_ex(pp), float(-min_perimeter_infill_spacing / 2.),
|
||||||
union_ex(pp),
|
float(inset + min_perimeter_infill_spacing / 2.));
|
||||||
float(- min_perimeter_infill_spacing / 2.),
|
this->fill_surfaces->append(infill_areas, stInternal);
|
||||||
float(inset + min_perimeter_infill_spacing / 2.)),
|
|
||||||
stInternal);
|
|
||||||
|
|
||||||
if (this->lower_slices != nullptr && this->config->overhangs && this->config->extra_perimeters_on_overhangs &&
|
if (this->lower_slices != nullptr && this->config->overhangs && this->config->extra_perimeters_on_overhangs &&
|
||||||
this->config->perimeters > 0 && this->layer_id > this->object_config->raft_layers) {
|
this->config->perimeters > 0 && this->layer_id > this->object_config->raft_layers) {
|
||||||
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
||||||
ExPolygons infill_area;
|
auto [extra_perimeters, filled_area] = generate_extra_perimeters_over_overhangs(infill_areas,
|
||||||
for (const auto &internal_surface : this->fill_surfaces->surfaces) { infill_area.push_back(internal_surface.expolygon); }
|
|
||||||
auto [extra_perimeters,
|
|
||||||
filled_area] = generate_extra_perimeters_over_overhangs(surface, infill_area,
|
|
||||||
this->lower_slices_polygons(),
|
this->lower_slices_polygons(),
|
||||||
this->overhang_flow, this->config->perimeters,
|
this->overhang_flow, this->m_scaled_resolution,
|
||||||
this->m_scaled_resolution,
|
|
||||||
*this->object_config, *this->print_config);
|
*this->object_config, *this->print_config);
|
||||||
if (!extra_perimeters.empty()) {
|
if (!extra_perimeters.empty()) {
|
||||||
ExtrusionEntityCollection *this_islands_perimeters = static_cast<ExtrusionEntityCollection *>(this->loops->entities.back());
|
ExtrusionEntityCollection *this_islands_perimeters = static_cast<ExtrusionEntityCollection *>(this->loops->entities.back());
|
||||||
ExtrusionEntityCollection new_perimeters{};
|
ExtrusionEntityCollection new_perimeters{};
|
||||||
new_perimeters.no_sort = this_islands_perimeters->no_sort;
|
new_perimeters.no_sort = this_islands_perimeters->no_sort;
|
||||||
for (const ExtrusionPaths& paths : extra_perimeters) {
|
for (const ExtrusionPaths &paths : extra_perimeters) { new_perimeters.append(paths); }
|
||||||
new_perimeters.append(paths);
|
|
||||||
}
|
|
||||||
new_perimeters.append(this_islands_perimeters->entities);
|
new_perimeters.append(this_islands_perimeters->entities);
|
||||||
this_islands_perimeters->swap(new_perimeters);
|
this_islands_perimeters->swap(new_perimeters);
|
||||||
|
|
||||||
@ -1516,34 +1497,25 @@ void PerimeterGenerator::process_classic()
|
|||||||
// collapse too narrow infill areas
|
// collapse too narrow infill areas
|
||||||
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||||
// append infill areas to fill_surfaces
|
// append infill areas to fill_surfaces
|
||||||
this->fill_surfaces->append(
|
ExPolygons infill_areas = offset2_ex(union_ex(pp), float(-inset - min_perimeter_infill_spacing / 2.),
|
||||||
offset2_ex(
|
float(min_perimeter_infill_spacing / 2.));
|
||||||
union_ex(pp),
|
this->fill_surfaces->append(infill_areas, stInternal);
|
||||||
float(- inset - min_perimeter_infill_spacing / 2.),
|
|
||||||
float(min_perimeter_infill_spacing / 2.)),
|
|
||||||
stInternal);
|
|
||||||
|
|
||||||
if (this->lower_slices != nullptr && this->config->overhangs && this->config->extra_perimeters_on_overhangs &&
|
if (this->lower_slices != nullptr && this->config->overhangs && this->config->extra_perimeters_on_overhangs &&
|
||||||
this->config->perimeters > 0 && this->layer_id > this->object_config->raft_layers) {
|
this->config->perimeters > 0 && this->layer_id > this->object_config->raft_layers) {
|
||||||
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
// Generate extra perimeters on overhang areas, and cut them to these parts only, to save print time and material
|
||||||
ExPolygons infill_area;
|
auto [extra_perimeters, filled_area] = generate_extra_perimeters_over_overhangs(infill_areas,
|
||||||
for (const auto &internal_surface : this->fill_surfaces->surfaces) { infill_area.push_back(internal_surface.expolygon); }
|
|
||||||
auto [extra_perimeters, filled_area] = generate_extra_perimeters_over_overhangs(surface, infill_area,
|
|
||||||
this->lower_slices_polygons(),
|
this->lower_slices_polygons(),
|
||||||
this->overhang_flow, this->config->perimeters,
|
this->overhang_flow, this->m_scaled_resolution,
|
||||||
this->m_scaled_resolution,
|
|
||||||
*this->object_config, *this->print_config);
|
*this->object_config, *this->print_config);
|
||||||
if (!extra_perimeters.empty()) {
|
if (!extra_perimeters.empty()) {
|
||||||
ExtrusionEntityCollection *this_islands_perimeters = static_cast<ExtrusionEntityCollection *>(this->loops->entities.back());
|
ExtrusionEntityCollection *this_islands_perimeters = static_cast<ExtrusionEntityCollection *>(this->loops->entities.back());
|
||||||
ExtrusionEntityCollection new_perimeters{};
|
ExtrusionEntityCollection new_perimeters{};
|
||||||
new_perimeters.no_sort = this_islands_perimeters->no_sort;
|
new_perimeters.no_sort = this_islands_perimeters->no_sort;
|
||||||
for (const ExtrusionPaths& paths : extra_perimeters) {
|
for (const ExtrusionPaths &paths : extra_perimeters) { new_perimeters.append(paths); }
|
||||||
new_perimeters.append(paths);
|
|
||||||
}
|
|
||||||
new_perimeters.append(this_islands_perimeters->entities);
|
new_perimeters.append(this_islands_perimeters->entities);
|
||||||
this_islands_perimeters->swap(new_perimeters);
|
this_islands_perimeters->swap(new_perimeters);
|
||||||
|
|
||||||
|
|
||||||
SurfaceCollection orig_surfaces = *this->fill_surfaces;
|
SurfaceCollection orig_surfaces = *this->fill_surfaces;
|
||||||
this->fill_surfaces->clear();
|
this->fill_surfaces->clear();
|
||||||
for (const auto &surface : orig_surfaces.surfaces) {
|
for (const auto &surface : orig_surfaces.surfaces) {
|
||||||
|
@ -58,7 +58,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||||||
// Cache the plenty of parameters, which influence the G-code generator only,
|
// Cache the plenty of parameters, which influence the G-code generator only,
|
||||||
// or they are only notes not influencing the generated G-code.
|
// or they are only notes not influencing the generated G-code.
|
||||||
static std::unordered_set<std::string> steps_gcode = {
|
static std::unordered_set<std::string> steps_gcode = {
|
||||||
"avoid_curled_filament_during_travels",
|
|
||||||
"avoid_crossing_perimeters",
|
"avoid_crossing_perimeters",
|
||||||
"avoid_crossing_perimeters_max_detour",
|
"avoid_crossing_perimeters_max_detour",
|
||||||
"bed_shape",
|
"bed_shape",
|
||||||
@ -223,6 +222,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||||||
osteps.emplace_back(posInfill);
|
osteps.emplace_back(posInfill);
|
||||||
osteps.emplace_back(posSupportMaterial);
|
osteps.emplace_back(posSupportMaterial);
|
||||||
steps.emplace_back(psSkirtBrim);
|
steps.emplace_back(psSkirtBrim);
|
||||||
|
} else if (opt_key == "avoid_curled_filament_during_travels") {
|
||||||
|
osteps.emplace_back(posEstimateCurledExtrusions);
|
||||||
} else {
|
} else {
|
||||||
// for legacy, if we can't handle this option let's invalidate all steps
|
// for legacy, if we can't handle this option let's invalidate all steps
|
||||||
//FIXME invalidate all steps of all objects as well?
|
//FIXME invalidate all steps of all objects as well?
|
||||||
|
@ -1231,13 +1231,13 @@ struct LayerCurlingEstimator
|
|||||||
|
|
||||||
if (fabs(dist_from_prev_layer) < 2.0f * flow_width) {
|
if (fabs(dist_from_prev_layer) < 2.0f * flow_width) {
|
||||||
const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx);
|
const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx);
|
||||||
current_line.malformation += 0.85 * nearest_line.malformation;
|
current_line.malformation += 0.9 * nearest_line.malformation;
|
||||||
}
|
}
|
||||||
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
|
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
|
||||||
float factor = std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) /
|
float factor = 0.5f + 0.5f * std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) /
|
||||||
(max_malformation_dist - min_malformation_dist);
|
(max_malformation_dist - min_malformation_dist);
|
||||||
malformation_acc.add_distance(current_line.len);
|
malformation_acc.add_distance(current_line.len);
|
||||||
current_line.malformation += l->height * factor * (2.0f + 3.0f * (malformation_acc.max_curvature / PI));
|
current_line.malformation += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI));
|
||||||
current_line.malformation = std::min(current_line.malformation, float(l->height * params.max_malformation_factor));
|
current_line.malformation = std::min(current_line.malformation, float(l->height * params.max_malformation_factor));
|
||||||
} else {
|
} else {
|
||||||
malformation_acc.reset();
|
malformation_acc.reset();
|
||||||
|
@ -26,7 +26,7 @@ struct Params {
|
|||||||
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
||||||
const float bridge_distance = 12.0f; //mm
|
const float bridge_distance = 12.0f; //mm
|
||||||
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
||||||
const std::pair<float,float> malformation_overlap_factor = std::pair<float, float> { 0.45, -0.1 };
|
const std::pair<float,float> malformation_overlap_factor = std::pair<float, float> { 0.50, -0.1 };
|
||||||
const float max_malformation_factor = 10.0f;
|
const float max_malformation_factor = 10.0f;
|
||||||
|
|
||||||
const float min_distance_between_support_points = 3.0f; //mm
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
|
@ -5174,6 +5174,8 @@ bool GLCanvas3D::_init_main_toolbar()
|
|||||||
item.left.toggable = true;
|
item.left.toggable = true;
|
||||||
item.left.render_callback = [this](float left, float right, float, float) {
|
item.left.render_callback = [this](float left, float right, float, float) {
|
||||||
if (m_canvas != nullptr) {
|
if (m_canvas != nullptr) {
|
||||||
|
if (!m_canvas->HasFocus())
|
||||||
|
m_canvas->SetFocus();
|
||||||
if (_render_search_list(0.5f * (left + right)))
|
if (_render_search_list(0.5f * (left + right)))
|
||||||
_deactivate_search_toolbar_item();
|
_deactivate_search_toolbar_item();
|
||||||
}
|
}
|
||||||
|
@ -217,9 +217,7 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||||||
Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this);
|
Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this);
|
||||||
Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this);
|
Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this);
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
|
||||||
Bind(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, &ObjectList::OnEditingStarted, this);
|
Bind(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, &ObjectList::OnEditingStarted, this);
|
||||||
#endif /* __WXMSW__ */
|
|
||||||
Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &ObjectList::OnEditingDone, this);
|
Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &ObjectList::OnEditingDone, this);
|
||||||
|
|
||||||
Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &ObjectList::ItemValueChanged, this);
|
Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &ObjectList::ItemValueChanged, this);
|
||||||
@ -1897,11 +1895,9 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item)
|
|||||||
|
|
||||||
// If last volume item with warning was deleted, unmark object item
|
// If last volume item with warning was deleted, unmark object item
|
||||||
if (type & itVolume) {
|
if (type & itVolume) {
|
||||||
add_volumes_to_object_in_list(obj_idx);
|
|
||||||
const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats());
|
const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats());
|
||||||
m_objects_model->UpdateWarningIcon(parent, icon_name);
|
m_objects_model->UpdateWarningIcon(parent, icon_name);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_objects_model->Delete(item);
|
m_objects_model->Delete(item);
|
||||||
|
|
||||||
update_info_items(obj_idx);
|
update_info_items(obj_idx);
|
||||||
@ -3065,7 +3061,7 @@ bool ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
|
|||||||
if (!del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type))
|
if (!del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type))
|
||||||
continue;
|
continue;
|
||||||
if (item->type&itVolume) {
|
if (item->type&itVolume) {
|
||||||
add_volumes_to_object_in_list(item->obj_idx);
|
m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item->obj_idx, item->sub_obj_idx));
|
||||||
ModelObject* obj = object(item->obj_idx);
|
ModelObject* obj = object(item->obj_idx);
|
||||||
if (obj->volumes.size() == 1) {
|
if (obj->volumes.size() == 1) {
|
||||||
wxDataViewItem parent = m_objects_model->GetItemById(item->obj_idx);
|
wxDataViewItem parent = m_objects_model->GetItemById(item->obj_idx);
|
||||||
@ -4653,17 +4649,19 @@ void ObjectList::ItemValueChanged(wxDataViewEvent &event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectList::OnEditingStarted(wxDataViewEvent &event)
|
||||||
|
{
|
||||||
|
m_is_editing_started = true;
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
||||||
// Here the last active column is forgotten, so when leaving the editing mode, the next mouse click will not enter the editing mode of the newly selected column.
|
// Here the last active column is forgotten, so when leaving the editing mode, the next mouse click will not enter the editing mode of the newly selected column.
|
||||||
void ObjectList::OnEditingStarted(wxDataViewEvent &event)
|
|
||||||
{
|
|
||||||
m_last_selected_column = -1;
|
m_last_selected_column = -1;
|
||||||
}
|
|
||||||
#endif //__WXMSW__
|
#endif //__WXMSW__
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectList::OnEditingDone(wxDataViewEvent &event)
|
void ObjectList::OnEditingDone(wxDataViewEvent &event)
|
||||||
{
|
{
|
||||||
|
m_is_editing_started = false;
|
||||||
if (event.GetColumn() != colName)
|
if (event.GetColumn() != colName)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -176,6 +176,7 @@ private:
|
|||||||
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
||||||
int m_last_selected_column = -1;
|
int m_last_selected_column = -1;
|
||||||
#endif /* __MSW__ */
|
#endif /* __MSW__ */
|
||||||
|
bool m_is_editing_started{ false };
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
SettingsFactory::Bundle m_freq_settings_fff;
|
SettingsFactory::Bundle m_freq_settings_fff;
|
||||||
@ -406,6 +407,8 @@ public:
|
|||||||
void apply_volumes_order();
|
void apply_volumes_order();
|
||||||
bool has_paint_on_segmentation();
|
bool has_paint_on_segmentation();
|
||||||
|
|
||||||
|
bool is_editing() const { return m_is_editing_started; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef __WXOSX__
|
#ifdef __WXOSX__
|
||||||
// void OnChar(wxKeyEvent& event);
|
// void OnChar(wxKeyEvent& event);
|
||||||
@ -419,10 +422,8 @@ private:
|
|||||||
bool can_drop(const wxDataViewItem& item) const ;
|
bool can_drop(const wxDataViewItem& item) const ;
|
||||||
|
|
||||||
void ItemValueChanged(wxDataViewEvent &event);
|
void ItemValueChanged(wxDataViewEvent &event);
|
||||||
#ifdef __WXMSW__
|
|
||||||
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
|
||||||
void OnEditingStarted(wxDataViewEvent &event);
|
void OnEditingStarted(wxDataViewEvent &event);
|
||||||
#endif /* __WXMSW__ */
|
|
||||||
void OnEditingDone(wxDataViewEvent &event);
|
void OnEditingDone(wxDataViewEvent &event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,14 +75,25 @@ static std::string point_on_feature_type_as_string(Measure::SurfaceFeatureType t
|
|||||||
std::string ret;
|
std::string ret;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Measure::SurfaceFeatureType::Point: { ret = _u8L("Vertex"); break; }
|
case Measure::SurfaceFeatureType::Point: { ret = _u8L("Vertex"); break; }
|
||||||
case Measure::SurfaceFeatureType::Edge: { ret = (hover_id == POINT_ID) ? _u8L("Center of edge") : _u8L("Point on edge"); break; }
|
case Measure::SurfaceFeatureType::Edge: { ret = _u8L("Point on edge"); break; }
|
||||||
case Measure::SurfaceFeatureType::Circle: { ret = (hover_id == POINT_ID) ? _u8L("Center of circle") : _u8L("Point on circle"); break; }
|
case Measure::SurfaceFeatureType::Circle: { ret = _u8L("Point on circle"); break; }
|
||||||
case Measure::SurfaceFeatureType::Plane: { ret = _u8L("Point on plane"); break; }
|
case Measure::SurfaceFeatureType::Plane: { ret = _u8L("Point on plane"); break; }
|
||||||
default: { assert(false); break; }
|
default: { assert(false); break; }
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string center_on_feature_type_as_string(Measure::SurfaceFeatureType type)
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
switch (type) {
|
||||||
|
case Measure::SurfaceFeatureType::Edge: { ret = _u8L("Center of edge"); break; }
|
||||||
|
case Measure::SurfaceFeatureType::Circle: { ret = _u8L("Center of circle"); break; }
|
||||||
|
default: { assert(false); break; }
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static GLModel::Geometry init_plane_data(const indexed_triangle_set& its, const std::vector<std::vector<int>>& planes_triangles, int idx)
|
static GLModel::Geometry init_plane_data(const indexed_triangle_set& its, const std::vector<std::vector<int>>& planes_triangles, int idx)
|
||||||
{
|
{
|
||||||
assert(0 <= idx && idx < (int)planes_triangles.size());
|
assert(0 <= idx && idx < (int)planes_triangles.size());
|
||||||
@ -251,7 +262,21 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
m_mouse_left_down = false;
|
m_mouse_left_down = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (mouse_event.Dragging()) {
|
||||||
|
// Enable/Disable panning/rotating the 3D scene
|
||||||
|
// Ctrl is pressed or the mouse is not hovering a selected volume
|
||||||
|
bool unlock_dragging = mouse_event.CmdDown() || (m_hover_id == -1 && !m_parent.get_selection().contains_volume(m_parent.get_first_hover_volume_idx()));
|
||||||
|
// mode is not center selection or mouse is not hovering a center
|
||||||
|
unlock_dragging &= !mouse_event.ShiftDown() || (m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID && m_hover_id != POINT_ID);
|
||||||
|
return !unlock_dragging;
|
||||||
|
}
|
||||||
else if (mouse_event.LeftDown()) {
|
else if (mouse_event.LeftDown()) {
|
||||||
|
// let the event pass through to allow panning/rotating the 3D scene
|
||||||
|
if ((m_mode != EMode::CenterSelection && mouse_event.CmdDown()) ||
|
||||||
|
(m_mode == EMode::CenterSelection && m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID && m_hover_id != POINT_ID)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_hover_id != -1) {
|
if (m_hover_id != -1) {
|
||||||
SelectedFeatures selected_features_old = m_selected_features;
|
SelectedFeatures selected_features_old = m_selected_features;
|
||||||
m_mouse_left_down = true;
|
m_mouse_left_down = true;
|
||||||
@ -263,10 +288,41 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
else if (m_hover_id == SELECTION_2_ID && m_selected_features.second.feature.has_value())
|
else if (m_hover_id == SELECTION_2_ID && m_selected_features.second.feature.has_value())
|
||||||
item = m_selected_features.second;
|
item = m_selected_features.second;
|
||||||
else {
|
else {
|
||||||
item = {
|
switch (m_mode)
|
||||||
(m_mode == EMode::ExtendedSelection) ? point_on_feature_type_as_string(m_curr_feature->get_type(), m_hover_id) : surface_feature_type_as_string(m_curr_feature->get_type()),
|
{
|
||||||
(m_mode == EMode::ExtendedSelection) ? Measure::SurfaceFeature(*m_curr_point_on_feature_position) : m_curr_feature
|
case EMode::FeatureSelection:
|
||||||
};
|
{
|
||||||
|
item = { surface_feature_type_as_string(m_curr_feature->get_type()), m_curr_feature };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EMode::PointSelection:
|
||||||
|
{
|
||||||
|
item = { point_on_feature_type_as_string(m_curr_feature->get_type(), m_hover_id), Measure::SurfaceFeature(*m_curr_point_on_feature_position) };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EMode::CenterSelection:
|
||||||
|
{
|
||||||
|
Vec3d position;
|
||||||
|
switch (m_curr_feature->get_type())
|
||||||
|
{
|
||||||
|
case Measure::SurfaceFeatureType::Circle:
|
||||||
|
{
|
||||||
|
position = std::get<0>(m_curr_feature->get_circle());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Measure::SurfaceFeatureType::Edge:
|
||||||
|
{
|
||||||
|
assert(m_curr_feature->get_extra_point().has_value());
|
||||||
|
position = *m_curr_feature->get_extra_point();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { assert(false); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
item = { center_on_feature_type_as_string(m_curr_feature->get_type()), Measure::SurfaceFeature(position) };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
@ -284,8 +340,14 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
m_selected_features.second.reset();
|
m_selected_features.second.reset();
|
||||||
else {
|
else {
|
||||||
m_selected_features.second = item;
|
m_selected_features.second = item;
|
||||||
if (m_mode == EMode::ExtendedSelection)
|
if (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection)
|
||||||
m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_2_ID, *m_sphere.mesh_raycaster));
|
m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_2_ID, *m_sphere.mesh_raycaster));
|
||||||
|
if (m_mode == EMode::CenterSelection) {
|
||||||
|
// Fake ctrl up event to exit the center selection mode
|
||||||
|
gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), true, false, false);
|
||||||
|
// increase counter to avoid that keeping the ctrl key pressed triggers a ctrl down event
|
||||||
|
m_ctrl_kar_filter.increase_count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -296,8 +358,14 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
else {
|
else {
|
||||||
const SelectedFeatures::Item item = item_from_feature();
|
const SelectedFeatures::Item item = item_from_feature();
|
||||||
m_selected_features.first = item;
|
m_selected_features.first = item;
|
||||||
if (m_mode == EMode::ExtendedSelection)
|
if (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection)
|
||||||
m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_1_ID, *m_sphere.mesh_raycaster));
|
m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_1_ID, *m_sphere.mesh_raycaster));
|
||||||
|
if (m_mode == EMode::CenterSelection) {
|
||||||
|
// Fake ctrl up event to exit the center selection mode
|
||||||
|
gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), true, false, false);
|
||||||
|
// increase counter to avoid that keeping the ctrl key pressed triggers a ctrl down event
|
||||||
|
m_ctrl_kar_filter.increase_count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) {
|
if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) {
|
||||||
@ -330,11 +398,19 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
// avoid closing the gizmo if the user clicks outside of any volume
|
// avoid closing the gizmo if the user clicks outside of any volume
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mouse_event.RightDown() && mouse_event.CmdDown()) {
|
else if (mouse_event.RightDown()) {
|
||||||
|
// let the event pass through to allow panning/rotating the 3D scene
|
||||||
|
if ((m_mode != EMode::CenterSelection && mouse_event.CmdDown()) || (m_mode == EMode::CenterSelection && m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID)) {
|
||||||
|
std::cout << "RightDown -> false\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse_event.ShiftDown()) {
|
||||||
m_selected_features.reset();
|
m_selected_features.reset();
|
||||||
m_selection_raycasters.clear();
|
m_selection_raycasters.clear();
|
||||||
m_parent.request_extra_frame();
|
m_parent.request_extra_frame();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (mouse_event.Leaving())
|
else if (mouse_event.Leaving())
|
||||||
m_mouse_left_down = false;
|
m_mouse_left_down = false;
|
||||||
|
|
||||||
@ -369,21 +445,50 @@ void GLGizmoMeasure::data_changed()
|
|||||||
m_is_editing_distance_first_frame = true;
|
m_is_editing_distance_first_frame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool feature_has_center(std::optional<Measure::SurfaceFeature> feature)
|
||||||
|
{
|
||||||
|
return feature.has_value() ?
|
||||||
|
(feature->get_type() == Measure::SurfaceFeatureType::Circle || (feature->get_type() == Measure::SurfaceFeatureType::Edge && feature->get_extra_point().has_value()))
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
||||||
{
|
{
|
||||||
if (action == SLAGizmoEventType::CtrlDown) {
|
auto activate_center_selection = [this, shift_down, control_down](SLAGizmoEventType action) {
|
||||||
|
bool ret = false;
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case SLAGizmoEventType::CtrlDown: { ret = shift_down && feature_has_center(m_curr_feature); break; }
|
||||||
|
case SLAGizmoEventType::ShiftDown: { ret = control_down && feature_has_center(m_curr_feature); break; }
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (action == SLAGizmoEventType::ShiftDown) {
|
||||||
|
if (m_shift_kar_filter.is_first()) {
|
||||||
|
m_mode = activate_center_selection(SLAGizmoEventType::ShiftDown) ? EMode::CenterSelection : EMode::PointSelection;
|
||||||
|
disable_scene_raycasters();
|
||||||
|
}
|
||||||
|
m_shift_kar_filter.increase_count();
|
||||||
|
}
|
||||||
|
else if (action == SLAGizmoEventType::ShiftUp) {
|
||||||
|
m_shift_kar_filter.reset_count();
|
||||||
|
m_mode = EMode::FeatureSelection;
|
||||||
|
restore_scene_raycasters_state();
|
||||||
|
}
|
||||||
|
else if (action == SLAGizmoEventType::CtrlDown) {
|
||||||
if (m_ctrl_kar_filter.is_first()) {
|
if (m_ctrl_kar_filter.is_first()) {
|
||||||
if (m_curr_feature.has_value()) {
|
if (activate_center_selection(SLAGizmoEventType::CtrlDown)) {
|
||||||
m_mode = EMode::ExtendedSelection;
|
m_mode = EMode::CenterSelection;
|
||||||
disable_scene_raycasters();
|
disable_scene_raycasters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ctrl_kar_filter.increase_count();
|
m_ctrl_kar_filter.increase_count();
|
||||||
}
|
}
|
||||||
else if (action == SLAGizmoEventType::CtrlUp) {
|
else if (action == SLAGizmoEventType::CtrlUp) {
|
||||||
m_ctrl_kar_filter.reset_count();
|
m_ctrl_kar_filter.reset_count();
|
||||||
m_mode = EMode::BasicSelection;
|
m_mode = control_down ? EMode::PointSelection : EMode::FeatureSelection;
|
||||||
restore_scene_raycasters_state();
|
restore_scene_raycasters_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,6 +505,7 @@ void GLGizmoMeasure::on_set_state()
|
|||||||
{
|
{
|
||||||
if (m_state == Off) {
|
if (m_state == Off) {
|
||||||
m_ctrl_kar_filter.reset_count();
|
m_ctrl_kar_filter.reset_count();
|
||||||
|
m_shift_kar_filter.reset_count();
|
||||||
m_curr_feature.reset();
|
m_curr_feature.reset();
|
||||||
m_curr_point_on_feature_position.reset();
|
m_curr_point_on_feature_position.reset();
|
||||||
restore_scene_raycasters_state();
|
restore_scene_raycasters_state();
|
||||||
@ -408,7 +514,7 @@ void GLGizmoMeasure::on_set_state()
|
|||||||
m_measuring.reset();
|
m_measuring.reset();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_mode = EMode::BasicSelection;
|
m_mode = EMode::FeatureSelection;
|
||||||
// store current state of scene raycaster for later use
|
// store current state of scene raycaster for later use
|
||||||
m_scene_raycasters.clear();
|
m_scene_raycasters.clear();
|
||||||
auto scene_raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
auto scene_raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||||
@ -467,7 +573,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
Vec3f normal_on_model;
|
Vec3f normal_on_model;
|
||||||
size_t model_facet_idx;
|
size_t model_facet_idx;
|
||||||
const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx);
|
const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx);
|
||||||
const bool is_hovering_on_locked_feature = m_mode == EMode::ExtendedSelection && m_hover_id != -1;
|
const bool is_hovering_on_feature = (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) && m_hover_id != -1;
|
||||||
|
|
||||||
auto update_circle = [this, inv_zoom]() {
|
auto update_circle = [this, inv_zoom]() {
|
||||||
if (m_last_inv_zoom != inv_zoom || m_last_circle != m_curr_feature) {
|
if (m_last_inv_zoom != inv_zoom || m_last_circle != m_curr_feature) {
|
||||||
@ -483,9 +589,19 @@ void GLGizmoMeasure::on_render()
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_mode == EMode::BasicSelection) {
|
if (m_mode == EMode::FeatureSelection || m_mode == EMode::PointSelection) {
|
||||||
std::optional<Measure::SurfaceFeature> curr_feature = mouse_on_object ? m_measuring->get_feature(model_facet_idx, position_on_model.cast<double>()) : std::nullopt;
|
if ((m_hover_id == SELECTION_1_ID && boost::algorithm::istarts_with(m_selected_features.first.source, _u8L("Center"))) ||
|
||||||
|
(m_hover_id == SELECTION_2_ID && boost::algorithm::istarts_with(m_selected_features.second.source, _u8L("Center")))) {
|
||||||
|
// Skip feature detection if hovering on a selected center
|
||||||
|
m_curr_feature.reset();
|
||||||
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID);
|
||||||
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID);
|
||||||
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID);
|
||||||
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID);
|
||||||
m_curr_point_on_feature_position.reset();
|
m_curr_point_on_feature_position.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::optional<Measure::SurfaceFeature> curr_feature = mouse_on_object ? m_measuring->get_feature(model_facet_idx, position_on_model.cast<double>()) : std::nullopt;
|
||||||
if (m_curr_feature != curr_feature ||
|
if (m_curr_feature != curr_feature ||
|
||||||
(curr_feature.has_value() && curr_feature->get_type() == Measure::SurfaceFeatureType::Circle && (m_curr_feature != curr_feature || m_last_inv_zoom != inv_zoom))) {
|
(curr_feature.has_value() && curr_feature->get_type() == Measure::SurfaceFeatureType::Circle && (m_curr_feature != curr_feature || m_last_inv_zoom != inv_zoom))) {
|
||||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID);
|
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID);
|
||||||
@ -537,7 +653,11 @@ void GLGizmoMeasure::on_render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_hovering_on_locked_feature) {
|
}
|
||||||
|
|
||||||
|
if (m_mode != EMode::PointSelection)
|
||||||
|
m_curr_point_on_feature_position.reset();
|
||||||
|
else if (is_hovering_on_feature) {
|
||||||
auto position_on_feature = [this](int feature_type_id, const Camera& camera, std::function<Vec3f(const Vec3f&)> callback = nullptr) -> Vec3d {
|
auto position_on_feature = [this](int feature_type_id, const Camera& camera, std::function<Vec3f(const Vec3f&)> callback = nullptr) -> Vec3d {
|
||||||
auto it = m_raycasters.find(feature_type_id);
|
auto it = m_raycasters.find(feature_type_id);
|
||||||
if (it != m_raycasters.end() && it->second != nullptr) {
|
if (it != m_raycasters.end() && it->second != nullptr) {
|
||||||
@ -554,6 +674,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
return Vec3d::Zero();
|
return Vec3d::Zero();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (m_curr_feature.has_value()) {
|
||||||
switch (m_curr_feature->get_type())
|
switch (m_curr_feature->get_type())
|
||||||
{
|
{
|
||||||
default: { assert(false); break; }
|
default: { assert(false); break; }
|
||||||
@ -583,7 +704,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
m_curr_point_on_feature_position = center;
|
m_curr_point_on_feature_position = center;
|
||||||
else {
|
else {
|
||||||
const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; });
|
const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; });
|
||||||
const Eigen::Hyperplane<double, 3> plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()* normal, m_volume_matrix * center);
|
const Eigen::Hyperplane<double, 3> plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal, m_volume_matrix * center);
|
||||||
const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), normal);
|
const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), normal);
|
||||||
const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof);
|
const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof);
|
||||||
double angle = std::atan2(local_proj.y(), local_proj.x());
|
double angle = std::atan2(local_proj.y(), local_proj.x());
|
||||||
@ -597,6 +718,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (m_curr_feature.has_value() && m_curr_feature->get_type() == Measure::SurfaceFeatureType::Circle) {
|
if (m_curr_feature.has_value() && m_curr_feature->get_type() == Measure::SurfaceFeatureType::Circle) {
|
||||||
if (update_circle()) {
|
if (update_circle()) {
|
||||||
@ -617,7 +739,6 @@ void GLGizmoMeasure::on_render()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.25f);
|
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
|
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
@ -634,8 +755,13 @@ void GLGizmoMeasure::on_render()
|
|||||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto render_feature = [this, set_matrix_uniforms](const Measure::SurfaceFeature& feature, const std::vector<ColorRGBA>& colors,
|
auto set_emission_uniform = [this, shader](const ColorRGBA& color, bool hover) {
|
||||||
float inv_zoom, bool update_raycasters_transform) {
|
shader->set_uniform("emission_factor", (color == m_parent.get_selection().get_first_volume()->render_color) ? 0.0f :
|
||||||
|
hover ? 0.5f : 0.25f);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto render_feature = [this, set_matrix_uniforms, set_emission_uniform](const Measure::SurfaceFeature& feature, const std::vector<ColorRGBA>& colors,
|
||||||
|
float inv_zoom, bool hover, bool update_raycasters_transform) {
|
||||||
switch (feature.get_type())
|
switch (feature.get_type())
|
||||||
{
|
{
|
||||||
default: { assert(false); break; }
|
default: { assert(false); break; }
|
||||||
@ -644,6 +770,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix);
|
const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix);
|
||||||
const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
|
const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
|
||||||
set_matrix_uniforms(feature_matrix);
|
set_matrix_uniforms(feature_matrix);
|
||||||
|
set_emission_uniform(colors.front(), hover);
|
||||||
m_sphere.model.set_color(colors.front());
|
m_sphere.model.set_color(colors.front());
|
||||||
m_sphere.model.render();
|
m_sphere.model.render();
|
||||||
if (update_raycasters_transform) {
|
if (update_raycasters_transform) {
|
||||||
@ -657,20 +784,23 @@ void GLGizmoMeasure::on_render()
|
|||||||
{
|
{
|
||||||
const auto& [center, radius, normal] = feature.get_circle();
|
const auto& [center, radius, normal] = feature.get_circle();
|
||||||
// render center
|
// render center
|
||||||
|
if (update_raycasters_transform) {
|
||||||
const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix);
|
const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix);
|
||||||
const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom);
|
const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom);
|
||||||
set_matrix_uniforms(center_matrix);
|
set_matrix_uniforms(center_matrix);
|
||||||
|
set_emission_uniform(colors.front(), hover);
|
||||||
m_sphere.model.set_color(colors.front());
|
m_sphere.model.set_color(colors.front());
|
||||||
m_sphere.model.render();
|
m_sphere.model.render();
|
||||||
if (update_raycasters_transform) {
|
|
||||||
auto it = m_raycasters.find(POINT_ID);
|
auto it = m_raycasters.find(POINT_ID);
|
||||||
if (it != m_raycasters.end() && it->second != nullptr)
|
if (it != m_raycasters.end() && it->second != nullptr)
|
||||||
it->second->set_transform(center_matrix);
|
it->second->set_transform(center_matrix);
|
||||||
}
|
}
|
||||||
// render circle
|
// render circle
|
||||||
|
if (m_mode != EMode::CenterSelection) {
|
||||||
const Transform3d circle_matrix = Transform3d::Identity();
|
const Transform3d circle_matrix = Transform3d::Identity();
|
||||||
set_matrix_uniforms(circle_matrix);
|
set_matrix_uniforms(circle_matrix);
|
||||||
if (update_raycasters_transform) {
|
if (update_raycasters_transform) {
|
||||||
|
set_emission_uniform(colors.back(), hover);
|
||||||
m_circle.model.set_color(colors.back());
|
m_circle.model.set_color(colors.back());
|
||||||
m_circle.model.render();
|
m_circle.model.render();
|
||||||
auto it = m_raycasters.find(CIRCLE_ID);
|
auto it = m_raycasters.find(CIRCLE_ID);
|
||||||
@ -681,35 +811,40 @@ void GLGizmoMeasure::on_render()
|
|||||||
GLModel circle;
|
GLModel circle;
|
||||||
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>());
|
GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast<float>(), float(radius), 5.0f * inv_zoom, normal.cast<float>(), m_volume_matrix.cast<float>());
|
||||||
circle.init_from(std::move(circle_geometry));
|
circle.init_from(std::move(circle_geometry));
|
||||||
|
set_emission_uniform(colors.back(), hover);
|
||||||
circle.set_color(colors.back());
|
circle.set_color(colors.back());
|
||||||
circle.render();
|
circle.render();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Measure::SurfaceFeatureType::Edge:
|
case Measure::SurfaceFeatureType::Edge:
|
||||||
{
|
{
|
||||||
const auto& [from, to] = feature.get_edge();
|
const auto& [from, to] = feature.get_edge();
|
||||||
// render extra point
|
// render extra point
|
||||||
|
if (update_raycasters_transform) {
|
||||||
const std::optional<Vec3d> extra = feature.get_extra_point();
|
const std::optional<Vec3d> extra = feature.get_extra_point();
|
||||||
if (extra.has_value()) {
|
if (extra.has_value()) {
|
||||||
const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix);
|
const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix);
|
||||||
const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom);
|
const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom);
|
||||||
set_matrix_uniforms(point_matrix);
|
set_matrix_uniforms(point_matrix);
|
||||||
|
set_emission_uniform(colors.front(), hover);
|
||||||
m_sphere.model.set_color(colors.front());
|
m_sphere.model.set_color(colors.front());
|
||||||
m_sphere.model.render();
|
m_sphere.model.render();
|
||||||
if (update_raycasters_transform) {
|
|
||||||
auto it = m_raycasters.find(POINT_ID);
|
auto it = m_raycasters.find(POINT_ID);
|
||||||
if (it != m_raycasters.end() && it->second != nullptr)
|
if (it != m_raycasters.end() && it->second != nullptr)
|
||||||
it->second->set_transform(point_matrix);
|
it->second->set_transform(point_matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// render edge
|
// render edge
|
||||||
|
if (m_mode != EMode::CenterSelection) {
|
||||||
const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix);
|
const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix);
|
||||||
const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix);
|
const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix);
|
||||||
const Transform3d edge_matrix = Geometry::translation_transform(from_world) *
|
const Transform3d edge_matrix = Geometry::translation_transform(from_world) *
|
||||||
Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) *
|
Eigen::Quaternion<double>::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) *
|
||||||
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() });
|
Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() });
|
||||||
set_matrix_uniforms(edge_matrix);
|
set_matrix_uniforms(edge_matrix);
|
||||||
|
set_emission_uniform(colors.back(), hover);
|
||||||
m_cylinder.model.set_color(colors.back());
|
m_cylinder.model.set_color(colors.back());
|
||||||
m_cylinder.model.render();
|
m_cylinder.model.render();
|
||||||
if (update_raycasters_transform) {
|
if (update_raycasters_transform) {
|
||||||
@ -717,6 +852,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
if (it != m_raycasters.end() && it->second != nullptr)
|
if (it != m_raycasters.end() && it->second != nullptr)
|
||||||
it->second->set_transform(edge_matrix);
|
it->second->set_transform(edge_matrix);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Measure::SurfaceFeatureType::Plane:
|
case Measure::SurfaceFeatureType::Plane:
|
||||||
@ -724,6 +860,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
const auto& [idx, normal, pt] = feature.get_plane();
|
const auto& [idx, normal, pt] = feature.get_plane();
|
||||||
assert(idx < m_plane_models_cache.size());
|
assert(idx < m_plane_models_cache.size());
|
||||||
set_matrix_uniforms(m_volume_matrix);
|
set_matrix_uniforms(m_volume_matrix);
|
||||||
|
set_emission_uniform(colors.front(), hover);
|
||||||
m_plane_models_cache[idx].set_color(colors.front());
|
m_plane_models_cache[idx].set_color(colors.front());
|
||||||
m_plane_models_cache[idx].render();
|
m_plane_models_cache[idx].render();
|
||||||
if (update_raycasters_transform) {
|
if (update_raycasters_transform) {
|
||||||
@ -737,19 +874,19 @@ void GLGizmoMeasure::on_render()
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto hover_selection_color = [this]() {
|
auto hover_selection_color = [this]() {
|
||||||
return saturate(!m_selected_features.first.feature.has_value() ? SELECTED_1ST_COLOR : SELECTED_2ND_COLOR, 1.5f);
|
return !m_selected_features.first.feature.has_value() ? SELECTED_1ST_COLOR : SELECTED_2ND_COLOR;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto hovering_color = [this, hover_selection_color, &selection]() {
|
auto hovering_color = [this, hover_selection_color, &selection]() {
|
||||||
return (m_mode == EMode::ExtendedSelection) ? selection.get_first_volume()->render_color : hover_selection_color();
|
return (m_mode == EMode::PointSelection) ? selection.get_first_volume()->render_color : hover_selection_color();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_curr_feature.has_value()) {
|
if (m_curr_feature.has_value()) {
|
||||||
std::vector<ColorRGBA> colors;
|
std::vector<ColorRGBA> colors;
|
||||||
if (m_selected_features.first.feature.has_value() && *m_curr_feature == *m_selected_features.first.feature)
|
if (m_selected_features.first.feature.has_value() && *m_curr_feature == *m_selected_features.first.feature)
|
||||||
colors.emplace_back(SELECTED_1ST_COLOR);
|
colors.emplace_back(hovering_color());
|
||||||
else if (m_selected_features.second.feature.has_value() && *m_curr_feature == *m_selected_features.second.feature)
|
else if (m_selected_features.second.feature.has_value() && *m_curr_feature == *m_selected_features.second.feature)
|
||||||
colors.emplace_back(SELECTED_2ND_COLOR);
|
colors.emplace_back(hovering_color());
|
||||||
else {
|
else {
|
||||||
switch (m_curr_feature->get_type())
|
switch (m_curr_feature->get_type())
|
||||||
{
|
{
|
||||||
@ -774,12 +911,12 @@ void GLGizmoMeasure::on_render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_feature(*m_curr_feature, colors, inv_zoom, true);
|
render_feature(*m_curr_feature, colors, inv_zoom, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_selected_features.first.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.first.feature)) {
|
if (m_selected_features.first.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.first.feature)) {
|
||||||
const std::vector<ColorRGBA> colors = { SELECTED_1ST_COLOR };
|
const std::vector<ColorRGBA> colors = { SELECTED_1ST_COLOR };
|
||||||
render_feature(*m_selected_features.first.feature, colors, inv_zoom, false);
|
render_feature(*m_selected_features.first.feature, colors, inv_zoom, m_hover_id == SELECTION_1_ID, false);
|
||||||
if (m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Point) {
|
if (m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Point) {
|
||||||
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
|
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
|
||||||
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; });
|
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; });
|
||||||
@ -789,7 +926,7 @@ void GLGizmoMeasure::on_render()
|
|||||||
}
|
}
|
||||||
if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) {
|
if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) {
|
||||||
const std::vector<ColorRGBA> colors = { SELECTED_2ND_COLOR };
|
const std::vector<ColorRGBA> colors = { SELECTED_2ND_COLOR };
|
||||||
render_feature(*m_selected_features.second.feature, colors, inv_zoom, false);
|
render_feature(*m_selected_features.second.feature, colors, inv_zoom, m_hover_id == SELECTION_2_ID, false);
|
||||||
if (m_selected_features.second.feature->get_type() == Measure::SurfaceFeatureType::Point) {
|
if (m_selected_features.second.feature->get_type() == Measure::SurfaceFeatureType::Point) {
|
||||||
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
|
auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(),
|
||||||
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; });
|
[](std::shared_ptr<SceneRaycasterItem> item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; });
|
||||||
@ -798,12 +935,14 @@ void GLGizmoMeasure::on_render()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_hovering_on_locked_feature && m_curr_point_on_feature_position.has_value()) {
|
if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) {
|
||||||
if (m_hover_id != POINT_ID) {
|
if (m_hover_id != POINT_ID) {
|
||||||
const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix);
|
const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix);
|
||||||
const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
|
const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom);
|
||||||
set_matrix_uniforms(matrix);
|
set_matrix_uniforms(matrix);
|
||||||
m_sphere.model.set_color(hover_selection_color());
|
const ColorRGBA color = hover_selection_color();
|
||||||
|
set_emission_uniform(color, true);
|
||||||
|
m_sphere.model.set_color(color);
|
||||||
m_sphere.model.render();
|
m_sphere.model.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1343,12 +1482,15 @@ void GLGizmoMeasure::render_debug_dialog()
|
|||||||
{
|
{
|
||||||
case Measure::SurfaceFeatureType::Point:
|
case Measure::SurfaceFeatureType::Point:
|
||||||
{
|
{
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(item.feature->get_point()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
const Vec3d position = m_volume_matrix * item.feature->get_point();
|
||||||
|
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Measure::SurfaceFeatureType::Edge:
|
case Measure::SurfaceFeatureType::Edge:
|
||||||
{
|
{
|
||||||
auto [from, to] = item.feature->get_edge();
|
auto [from, to] = item.feature->get_edge();
|
||||||
|
from = m_volume_matrix * from;
|
||||||
|
to = m_volume_matrix * to;
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
break;
|
break;
|
||||||
@ -1356,6 +1498,8 @@ void GLGizmoMeasure::render_debug_dialog()
|
|||||||
case Measure::SurfaceFeatureType::Plane:
|
case Measure::SurfaceFeatureType::Plane:
|
||||||
{
|
{
|
||||||
auto [idx, normal, origin] = item.feature->get_plane();
|
auto [idx, normal, origin] = item.feature->get_plane();
|
||||||
|
origin = m_volume_matrix * origin;
|
||||||
|
normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal;
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
@ -1364,6 +1508,10 @@ void GLGizmoMeasure::render_debug_dialog()
|
|||||||
case Measure::SurfaceFeatureType::Circle:
|
case Measure::SurfaceFeatureType::Circle:
|
||||||
{
|
{
|
||||||
auto [center, radius, normal] = item.feature->get_circle();
|
auto [center, radius, normal] = item.feature->get_circle();
|
||||||
|
const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true));
|
||||||
|
center = m_volume_matrix * center;
|
||||||
|
normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized();
|
||||||
|
radius = (on_circle - center).norm();
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(radius), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(radius), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
@ -1376,6 +1524,28 @@ void GLGizmoMeasure::render_debug_dialog()
|
|||||||
};
|
};
|
||||||
|
|
||||||
m_imgui->begin(_L("Measure tool debug"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
m_imgui->begin(_L("Measure tool debug"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
if (ImGui::BeginTable("Mode", 2)) {
|
||||||
|
std::string txt;
|
||||||
|
switch (m_mode)
|
||||||
|
{
|
||||||
|
case EMode::FeatureSelection: { txt = "Feature selection"; break; }
|
||||||
|
case EMode::PointSelection: { txt = "Point selection"; break; }
|
||||||
|
case EMode::CenterSelection: { txt = "Center selection"; break; }
|
||||||
|
default: { assert(false); break; }
|
||||||
|
}
|
||||||
|
add_strings_row_to_table(*m_imgui, "Mode", ImGuiWrapper::COL_ORANGE_LIGHT, txt, ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::BeginTable("Hover", 2)) {
|
||||||
|
add_strings_row_to_table(*m_imgui, "Hover id", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(m_hover_id), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
|
const std::string txt = m_curr_feature.has_value() ? surface_feature_type_as_string(m_curr_feature->get_type()) : "None";
|
||||||
|
add_strings_row_to_table(*m_imgui, "Current feature", ImGuiWrapper::COL_ORANGE_LIGHT, txt, ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
if (!m_selected_features.first.feature.has_value() && !m_selected_features.second.feature.has_value())
|
if (!m_selected_features.first.feature.has_value() && !m_selected_features.second.feature.has_value())
|
||||||
m_imgui->text("Empty selection");
|
m_imgui->text("Empty selection");
|
||||||
else {
|
else {
|
||||||
@ -1402,7 +1572,7 @@ void GLGizmoMeasure::render_debug_dialog()
|
|||||||
void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit)
|
void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit)
|
||||||
{
|
{
|
||||||
static std::optional<Measure::SurfaceFeature> last_feature;
|
static std::optional<Measure::SurfaceFeature> last_feature;
|
||||||
static EMode last_mode = EMode::BasicSelection;
|
static EMode last_mode = EMode::FeatureSelection;
|
||||||
static SelectedFeatures last_selected_features;
|
static SelectedFeatures last_selected_features;
|
||||||
|
|
||||||
static float last_y = 0.0f;
|
static float last_y = 0.0f;
|
||||||
@ -1436,12 +1606,13 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||||||
std::string text;
|
std::string text;
|
||||||
ColorRGBA color;
|
ColorRGBA color;
|
||||||
if (m_selected_features.second.feature.has_value()) {
|
if (m_selected_features.second.feature.has_value()) {
|
||||||
if (m_selected_features.second.feature == m_curr_feature && m_mode == EMode::BasicSelection)
|
if (m_selected_features.second.feature == m_curr_feature && m_mode == EMode::FeatureSelection)
|
||||||
text = _u8L("Unselect feature");
|
text = _u8L("Unselect feature");
|
||||||
else if (m_hover_id == SELECTION_2_ID)
|
else if (m_hover_id == SELECTION_2_ID)
|
||||||
text = _u8L("Unselect point");
|
text = (m_mode == EMode::CenterSelection) ? _u8L("Unselect center") : _u8L("Unselect point");
|
||||||
else
|
else
|
||||||
text = (m_mode == EMode::BasicSelection) ? _u8L("Select feature") : _u8L("Select point");
|
text = (m_mode == EMode::PointSelection) ? _u8L("Select point") :
|
||||||
|
(m_mode == EMode::CenterSelection) ? _u8L("Select center") : _u8L("Select feature");
|
||||||
color = SELECTED_2ND_COLOR;
|
color = SELECTED_2ND_COLOR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1449,11 +1620,12 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||||||
if (m_selected_features.first.feature == m_curr_feature)
|
if (m_selected_features.first.feature == m_curr_feature)
|
||||||
text = _u8L("Unselect feature");
|
text = _u8L("Unselect feature");
|
||||||
else if (m_hover_id == SELECTION_1_ID)
|
else if (m_hover_id == SELECTION_1_ID)
|
||||||
text = _u8L("Unselect point");
|
text = (m_mode == EMode::CenterSelection) ? _u8L("Unselect center") : _u8L("Unselect point");
|
||||||
color = SELECTED_1ST_COLOR;
|
color = SELECTED_1ST_COLOR;
|
||||||
}
|
}
|
||||||
if (text.empty()) {
|
if (text.empty()) {
|
||||||
text = (m_mode == EMode::BasicSelection) ? _u8L("Select feature") : _u8L("Select point");
|
text = (m_mode == EMode::PointSelection) ? _u8L("Select point") :
|
||||||
|
(m_mode == EMode::CenterSelection) ? _u8L("Select center") : _u8L("Select feature");
|
||||||
color = m_selected_features.first.feature.has_value() ? SELECTED_2ND_COLOR : SELECTED_1ST_COLOR;
|
color = m_selected_features.first.feature.has_value() ? SELECTED_2ND_COLOR : SELECTED_1ST_COLOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1467,18 +1639,23 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (m_selected_features.first.feature.has_value()) {
|
if (m_mode == EMode::FeatureSelection && m_hover_id != -1) {
|
||||||
add_strings_row_to_table(*m_imgui, CTRL_STR + "+" + _u8L("Right mouse button"), ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Restart selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, _u8L("Shift"), ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Enable point selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
++row_count;
|
++row_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mode == EMode::BasicSelection && m_hover_id != -1) {
|
if (m_mode != EMode::CenterSelection && feature_has_center(m_curr_feature)) {
|
||||||
add_strings_row_to_table(*m_imgui, CTRL_STR, ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Enable point selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, _u8L("Shift") + "+" + CTRL_STR, ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Enable center selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
|
++row_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_selected_features.first.feature.has_value()) {
|
||||||
|
add_strings_row_to_table(*m_imgui, _u8L("Shift") + "+" + _u8L("Right mouse button"), ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Restart selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
++row_count;
|
++row_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add dummy rows to keep dialog size fixed
|
// add dummy rows to keep dialog size fixed
|
||||||
for (unsigned int i = row_count; i < 3; ++i) {
|
for (unsigned int i = row_count; i < 4; ++i) {
|
||||||
add_strings_row_to_table(*m_imgui, " ", ImGuiWrapper::COL_ORANGE_LIGHT, " ", ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
add_strings_row_to_table(*m_imgui, " ", ImGuiWrapper::COL_ORANGE_LIGHT, " ", ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1492,16 +1669,22 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||||||
//bool data_text_set = false;
|
//bool data_text_set = false;
|
||||||
//ImGui::Separator();
|
//ImGui::Separator();
|
||||||
//if (feature_type != Measure::SurfaceFeatureType::Undef) {
|
//if (feature_type != Measure::SurfaceFeatureType::Undef) {
|
||||||
// if (m_mode == EMode::BasicSelection) {
|
// if (m_mode == EMode::FeatureSelection) {
|
||||||
// m_imgui->text(surface_feature_type_as_string(feature_type));
|
// m_imgui->text(surface_feature_type_as_string(feature_type));
|
||||||
// data_text_set = true;
|
// data_text_set = true;
|
||||||
// }
|
// }
|
||||||
// else if (m_mode == EMode::ExtendedSelection) {
|
// else if (m_mode == EMode::PointSelection) {
|
||||||
// if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) {
|
// if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) {
|
||||||
// m_imgui->text(point_on_feature_type_as_string(feature_type, m_hover_id));
|
// m_imgui->text(point_on_feature_type_as_string(feature_type, m_hover_id));
|
||||||
// data_text_set = true;
|
// data_text_set = true;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
// else if (m_mode == EMode::CenterSelection) {
|
||||||
|
// if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) {
|
||||||
|
// m_imgui->text(center_on_feature_type_as_string(feature_type));
|
||||||
|
// data_text_set = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
//}
|
//}
|
||||||
//if (!data_text_set)
|
//if (!data_text_set)
|
||||||
// m_imgui->text(_u8L("No feature"));
|
// m_imgui->text(_u8L("No feature"));
|
||||||
@ -1509,7 +1692,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
|
|||||||
//const unsigned int max_data_row_count = 3;
|
//const unsigned int max_data_row_count = 3;
|
||||||
//unsigned int data_row_count = 0;
|
//unsigned int data_row_count = 0;
|
||||||
//if (ImGui::BeginTable("Data", 2)) {
|
//if (ImGui::BeginTable("Data", 2)) {
|
||||||
// if (m_mode == EMode::BasicSelection) {
|
// if (m_mode == EMode::FeatureSelection) {
|
||||||
// switch (feature_type)
|
// switch (feature_type)
|
||||||
// {
|
// {
|
||||||
// default: { break; }
|
// default: { break; }
|
||||||
|
@ -23,8 +23,9 @@ class GLGizmoMeasure : public GLGizmoBase
|
|||||||
{
|
{
|
||||||
enum class EMode : unsigned char
|
enum class EMode : unsigned char
|
||||||
{
|
{
|
||||||
BasicSelection,
|
FeatureSelection,
|
||||||
ExtendedSelection
|
PointSelection,
|
||||||
|
CenterSelection
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SelectedFeatures
|
struct SelectedFeatures
|
||||||
@ -67,7 +68,7 @@ class GLGizmoMeasure : public GLGizmoBase
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EMode m_mode{ EMode::BasicSelection };
|
EMode m_mode{ EMode::FeatureSelection };
|
||||||
Measure::MeasurementResult m_measurement_result;
|
Measure::MeasurementResult m_measurement_result;
|
||||||
|
|
||||||
std::unique_ptr<Measure::Measuring> m_measuring; // PIMPL
|
std::unique_ptr<Measure::Measuring> m_measuring; // PIMPL
|
||||||
@ -114,6 +115,7 @@ class GLGizmoMeasure : public GLGizmoBase
|
|||||||
Vec2d m_mouse_pos{ Vec2d::Zero() };
|
Vec2d m_mouse_pos{ Vec2d::Zero() };
|
||||||
|
|
||||||
KeyAutoRepeatFilter m_ctrl_kar_filter;
|
KeyAutoRepeatFilter m_ctrl_kar_filter;
|
||||||
|
KeyAutoRepeatFilter m_shift_kar_filter;
|
||||||
|
|
||||||
SelectedFeatures m_selected_features;
|
SelectedFeatures m_selected_features;
|
||||||
bool m_pending_scale{ false };
|
bool m_pending_scale{ false };
|
||||||
|
@ -26,6 +26,7 @@ enum class SLAGizmoEventType : unsigned char {
|
|||||||
SelectAll,
|
SelectAll,
|
||||||
CtrlDown,
|
CtrlDown,
|
||||||
CtrlUp,
|
CtrlUp,
|
||||||
|
ShiftDown,
|
||||||
ShiftUp,
|
ShiftUp,
|
||||||
AltUp,
|
AltUp,
|
||||||
ApplyChanges,
|
ApplyChanges,
|
||||||
|
@ -608,10 +608,8 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
|||||||
const int keyCode = evt.GetKeyCode();
|
const int keyCode = evt.GetKeyCode();
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
|
|
||||||
if (evt.GetEventType() == wxEVT_KEY_UP)
|
if (evt.GetEventType() == wxEVT_KEY_UP) {
|
||||||
{
|
if (m_current == SlaSupports || m_current == Hollow || m_current == Cut) {
|
||||||
if (m_current == SlaSupports || m_current == Hollow || m_current == Cut)
|
|
||||||
{
|
|
||||||
GLGizmoBase* gizmo = get_current();
|
GLGizmoBase* gizmo = get_current();
|
||||||
const bool is_editing = m_current == Hollow ? true : gizmo->is_in_editing_mode();
|
const bool is_editing = m_current == Hollow ? true : gizmo->is_in_editing_mode();
|
||||||
const bool is_rectangle_dragging = gizmo->is_selection_rectangle_dragging();
|
const bool is_rectangle_dragging = gizmo->is_selection_rectangle_dragging();
|
||||||
@ -627,18 +625,19 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
|||||||
processed = true;
|
processed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_current == Measure && keyCode == WXK_CONTROL) {
|
else if (m_current == Measure) {
|
||||||
gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), false);
|
if (keyCode == WXK_CONTROL)
|
||||||
|
gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.CmdDown());
|
||||||
|
else if (keyCode == WXK_SHIFT)
|
||||||
|
gizmo_event(SLAGizmoEventType::ShiftUp, Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.CmdDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (processed)
|
// if (processed)
|
||||||
// m_parent.set_cursor(GLCanvas3D::Standard);
|
// m_parent.set_cursor(GLCanvas3D::Standard);
|
||||||
}
|
}
|
||||||
else if (evt.GetEventType() == wxEVT_KEY_DOWN)
|
else if (evt.GetEventType() == wxEVT_KEY_DOWN) {
|
||||||
{
|
if (m_current == SlaSupports && (keyCode == WXK_SHIFT || keyCode == WXK_ALT)
|
||||||
if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT))
|
&& get_current()->is_in_editing_mode()) {
|
||||||
&& get_current()->is_in_editing_mode())
|
|
||||||
{
|
|
||||||
// m_parent.set_cursor(GLCanvas3D::Cross);
|
// m_parent.set_cursor(GLCanvas3D::Cross);
|
||||||
processed = true;
|
processed = true;
|
||||||
}
|
}
|
||||||
@ -664,8 +663,11 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
|||||||
if (simplify != nullptr)
|
if (simplify != nullptr)
|
||||||
processed = simplify->on_esc_key_down();
|
processed = simplify->on_esc_key_down();
|
||||||
}
|
}
|
||||||
else if (m_current == Measure && keyCode == WXK_CONTROL) {
|
else if (m_current == Measure) {
|
||||||
gizmo_event(SLAGizmoEventType::CtrlDown, Vec2d::Zero(), true);
|
if (keyCode == WXK_CONTROL)
|
||||||
|
gizmo_event(SLAGizmoEventType::CtrlDown, Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.CmdDown());
|
||||||
|
else if (keyCode == WXK_SHIFT)
|
||||||
|
gizmo_event(SLAGizmoEventType::ShiftDown, Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.CmdDown());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4890,12 +4890,12 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const double max_print_he
|
|||||||
|
|
||||||
bool Plater::priv::can_delete() const
|
bool Plater::priv::can_delete() const
|
||||||
{
|
{
|
||||||
return !get_selection().is_empty() && !get_selection().is_wipe_tower();
|
return !get_selection().is_empty() && !get_selection().is_wipe_tower() && !sidebar->obj_list()->is_editing();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Plater::priv::can_delete_all() const
|
bool Plater::priv::can_delete_all() const
|
||||||
{
|
{
|
||||||
return !model.objects.empty();
|
return !model.objects.empty() && !sidebar->obj_list()->is_editing();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Plater::priv::can_fix_through_netfabb() const
|
bool Plater::priv::can_fix_through_netfabb() const
|
||||||
|
Loading…
Reference in New Issue
Block a user