mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-20 22:18:30 +00:00
ENH: add timelapse pos picker
1. refine code structure 2. prevent moving tool head between camera and object 3. consider raft layer jira: NONE Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: Ic0004791bfd4036d4323045a041709d861e5c8d0 (cherry picked from commit 7dc269f99473421162ad89c555bfac7ace0e9a6b)
This commit is contained in:
1 parent
5647312a16
commit
b5756d1702
8 files changed
+504
-8
No files matched your search
@@ -118,6 +118,6 @@
|
||||
"machine_start_gcode": ";===== machine: H2D =========================\n;===== date: 20250418 =====================\n\n;M1002 set_flag extrude_cali_flag=1\n;M1002 set_flag g29_before_print_flag=1\n;M1002 set_flag auto_cali_toolhead_offset_flag=1\n;M1002 set_flag build_plate_detect_flag=1\n\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\nM400\n;M73 P99\n\n;=====printer start sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99 \nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99 \nM1006 A61 B9 L99 C61 D9 M99 E61 F9 N99 \nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99 \nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99 \nM1006 A61 B18 L99 C61 D18 M99 E61 F18 N99 \nM1006 W\n;=====printer start sound ===================\n\n;===== reset machine status =================\nM204 S10000\nM630 S0 P0\n\nG90\nM17 D ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nG29.1 Z{+0.0} ; clear z-trim value first\nM983.1 M1 \nM901 D4\nM481 S0 ; turn off cutter pos comp\n;===== reset machine status =================\n\nM620 M ;enable remap\n\n;===== avoid end stop =================\nG91\nG380 S2 Z22 F1200\nG380 S2 Z-12 F1200\nG90\n;===== avoid end stop =================\n\n;==== set airduct mode ==== \n\n{if (overall_chamber_temperature >= 40)}\n\n M145 P1 ; set airduct mode to heating mode for heating\n M106 P2 S0 ; turn off auxiliary fan\n M106 P3 S0 ; turn off chamber fan\n\n{else}\n M145 P0 ; set airduct mode to cooling mode for cooling\n M106 P2 S178 ; turn on auxiliary fan for cooling\n M106 P3 S127 ; turn on chamber fan for cooling\n M140 S0 ; stop heatbed from heating\n\n M1002 gcode_claim_action : 29\n M191 S0 ; wait for chamber temp\n M142 P1 R35 S40 U0.3 V0.5 ; set chamber autocooling\n M106 P2 S0 ; turn off auxiliary fan\n\n{endif}\n;==== set airduct mode ==== \n\n;===== start to heat heatbed & hotend==========\n\n M1002 set_filament_type:{filament_type[initial_no_support_extruder]}\n\n M104 S140 A\n M140 S[bed_temperature_initial_layer_single]\n\n ;===== set chamber temperature ==========\n {if (overall_chamber_temperature >= 40)}\n M145 P1 ; set airduct mode to heating mode\n M141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n {endif}\n ;===== set chamber temperature ==========\n\n;===== start to heat heatbead & hotend==========\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== first homing start =====\nM1002 gcode_claim_action : 13\n\nG28 X T300\n\nG150.1 F18000 ; wipe mouth to avoid filament stick to heatbed\nG150.3 F18000\nM400 P200\nM972 S24 P0 T2000\n{if curr_bed_type==\"Textured PEI Plate\"}\nM972 S26 P0 C0\n{elsif curr_bed_type==\"High Temp Plate\"}\nM972 S36 P0 C0 X1\n{endif}\nM972 S35 P0 C0\n\nG90\nG1 X175 Y160 F30000\n\nG28 Z P0 T250\n\n;===== first homign end =====\n\nM400\n;M73 P99\n\n;===== detection start =====\n\n T1001\n G383.4 ; left-extruder load status detection\n \n M104 S{nozzle_temperature_initial_layer[initial_no_support_extruder]-80} A ; rise temp in advance\n\nM1002 judge_flag build_plate_detect_flag\nM622 S1\n M972 S19 P0 C0 ; heatbed presence detection\nM623\n\n M972 S14 P0 ; nozzle type detection\n\n;===== detection end =====\n\nM400\n;M73 P99\n\n;===== prepare print temperature and material ==========\nM400\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on input shaping\n\nG29.2 S0 ; avoid invalid abl data\n\nM620.10 A0 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} H{nozzle_diameter[initial_no_support_extruder]} T{nozzle_temperature_range_high[initial_no_support_extruder]} P{nozzle_temperature_initial_layer[initial_no_support_extruder]} S1\nM620.10 A1 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60} H{nozzle_diameter[initial_no_support_extruder]} T{nozzle_temperature_range_high[initial_no_support_extruder]} P{nozzle_temperature_initial_layer[initial_no_support_extruder]} S1\n\n{if filament_type[initial_no_support_extruder] == \"TPU\"}\n M620.11 S0 L0 I[initial_no_support_extruder] E-{retraction_distances_when_cut[initial_no_support_extruder]} F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n{else}\n{if (filament_type[initial_no_support_extruder] == \"PA\") || (filament_type[initial_no_support_extruder] == \"PA-GF\")}\n M620.11 S1 L0 I[initial_no_support_extruder] R4 D2 E-{retraction_distances_when_cut[initial_no_support_extruder]} F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n{else}\n M620.11 S1 L0 I[initial_no_support_extruder] R10 D8 E-{retraction_distances_when_cut[initial_no_support_extruder]} F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n{endif}\n{endif}\n\nM620 S[initial_no_support_extruder]A ; switch material if AMS exist\nM1002 gcode_claim_action : 4\nM1002 Line truncated
|
||||
"machine_end_gcode": ";===== date: 2024/12/19 =====================\n;===== H2D =====================\nG392 S0 ;turn off nozzle clog detect\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if timelapse_type == 2}\nM991 S0 P-1 ;end timelapse immediately\n{endif}\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\n\nG90\nG150.3\n\n{if timelapse_type == 1}\nM991 S0 P-1 ;end timelapse at safe pos\n{endif}\n\nM141 S0 ; turn off chamber heating\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n; pull back filament to AMS\nM620 S65535\nT65535\nG150.2\nM621 S65535\n\nM620 S65279\nT65279\nG150.2\nM621 S65279\n\nG150.3\n\nM104 S0 T0; turn off hotend\nM104 S0 T1; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 320}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z320 F600\n G1 Z320\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM1015.4 S0 K0 ;disable air printing detect\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A48 B10 L99 C48 D10 M99 E48 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A60 B10 L99 C60 D10 M99 E60 F10 N99 \nM1006 W\n;=====printer finish sound=========\nM400\nM18\n\n",
|
||||
"layer_change_gcode": ";======== H2D 20250414========\n; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change\n\n{if !spiral_mode && print_sequence != \"by object\" && filament_type[initial_no_support_extruder] != \"TPU\"}\n M622.1 S0 ; for previous firmware, default turn off\n M1002 set_flag g39_forced_detection_flag=1\n M1002 judge_flag g39_forced_detection_flag\n M622 J1\n {if layer_num == 3}\n M993 A2 B2 C2 ; nozzle cam detection allow status save.\n M993 A0 B0 C0 ; nozzle cam detection not allowed.\n \n G39 R{-retraction_length} E{retraction_length} M30 N{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053}\n G130 O0 X285 Y-0.5 Z0.8 F{filament_max_volumetric_speed[initial_no_support_extruder]/2/2.4053} L10 E2 D0\n M83\n G1 E{-retraction_length} F1800\n G3 Z{layer_z + 0.4} I1.217 J0 P1 F60000\n \n M993 A3 B3 C3 ; nozzle cam detection allow status restore.\n {elsif layer_z == 2}\n M993 A2 B2 C2 ; nozzle cam detection allow status save.\n M993 A0 B0 C0 ; nozzle cam detection not allowed.\n \n G39 R{-retraction_length} E{retraction_length} M30 N{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053}\n G130 O0 X290 Y-0.5 Z0.8 F{filament_max_volumetric_speed[initial_no_support_extruder]/2/2.4053} L10 E2 D0\n M83\n G1 E{-retraction_length} F1800\n G3 Z{layer_z + 0.4} I1.217 J0 P1 F60000\n \n M993 A3 B3 C3 ; nozzle cam detection allow status restore.\n {elsif layer_z == 4}\n M993 A2 B2 C2 ; nozzle cam detection allow status save.\n M993 A0 B0 C0 ; nozzle cam detection not allowed.\n \n G39 R{-retraction_length} E{retraction_length} M30 N{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053}\n G130 O0 X295 Y-0.5 Z0.8 F{filament_max_volumetric_speed[initial_no_support_extruder]/2/2.4053} L10 E2 D0\n M83\n G1 E{-retraction_length} F1800\n G3 Z{layer_z + 0.4} I1.217 J0 P1 F60000\n \n M993 A3 B3 C3 ; nozzle cam detection allow status restore.\n {endif}\n M623\n{endif}\n",
|
||||
"time_lapse_gcode": ";======== H2D 20250213========\n; SKIPPABLE_START\n; SKIPTYPE: timelapse\nM622.1 S1 ; for prev firware, default turned on\n\nM1002 judge_flag timelapse_record_flag\n\nM622 J1\nM993 A2 B2 C2\nM993 A0 B0 C0\n\n{if !spiral_mode }\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nM83\nG1 Z{max_layer_z + 0.4} F1200\nM400\nM9713\n{endif}\n\nM9711 M{timelapse_type} E{most_used_physical_extruder_id} Z{layer_z} S11 C10 O0 T3000\n\n{if !spiral_mode }\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nG90\nG1 Z{max_layer_z + 3.0} F1200\nG1 Y295 F30000\nG1 Y265 F18000\nM83\nM9713\n{endif}\nM993 A3 B3 C3\n\nM623\n; SKIPPABLE_END\n",
|
||||
"time_lapse_gcode": ";======== H2D 20250213========\n; SKIPPABLE_START\n; SKIPTYPE: timelapse\nM622.1 S1 ; for prev firware, default turned on\n\nM1002 judge_flag timelapse_record_flag\n\nM622 J1\nM993 A2 B2 C2\nM993 A0 B0 C0\n\n{if !spiral_mode && !has_timelapse_safe_pos }\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nM83\nG1 Z{max_layer_z + 0.4} F1200\nM400\nM9713\n{endif}\n\n{if has_timelapse_safe_pos}\nM9711 M{timelapse_type} E{most_used_physical_extruder_id} X{timelapse_pos_x} Y{timelapse_pos_y} Z{layer_z} S11 C10 O0 T3000\n{else}\nM9711 M{timelapse_type} E{most_used_physical_extruder_id} Z{layer_z} S11 C10 O0 T3000\n{endif}\n\n{if !spiral_mode && !has_timelapse_safe_pos }\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nG90\nG1 Z{max_layer_z + 3.0} F1200\nG1 Y295 F30000\nG1 Y265 F18000\nM83\nM9713\n{endif}\nM993 A3 B3 C3\n\nM623\n; SKIPPABLE_END\n",
|
||||
"change_filament_gcode": ";======== H2D ========\n;===== 20250417 =====\nM993 A2 B2 C2 ; nozzle cam detection allow status save.\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")}\nM1015.4 S1 K0 ;disable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620 S[next_extruder]A\nM1002 gcode_claim_action : 4\nM204 S9000\n\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\n\nM620.10 A0 F{filament_max_volumetric_speed[current_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[current_extruder]} T{nozzle_temperature_range_high[current_extruder]} P{nozzle_temperature[current_extruder]} S1\nM620.10 A1 F{filament_max_volumetric_speed[next_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[next_extruder]} T{nozzle_temperature_range_high[next_extruder]} P{nozzle_temperature[next_extruder]} S1\n\n{if filament_type[current_extruder] == \"TPU\"}\nM620.11 S0 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\n{if (filament_type[current_extruder] == \"PA\") || (filament_type[current_extruder] == \"PA-GF\")}\nM620.11 S1 L0 I[current_extruder] R4 D2 E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\nM620.11 S1 L0 I[current_extruder] R10 D8 E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{endif}\n{endif}\n\n{if filament_type[current_extruder] == \"TPU\" || filament_type[next_extruder] == \"TPU\"}\nM620.11 H2 C331\n{else}\nM620.11 H0\n{endif}\n\nT[next_extruder]\n\n;deretract\n{if filament_type[next_extruder] == \"TPU\"}\n{else}\n{if (filament_type[next_extruder] == \"PA\") || (filament_type[next_extruder] == \"PA-GF\")}\n;VG1 E1 F{max(new_filament_e_feedrate, 200)}\n;VG1 E1 F{max(new_filament_e_feedrate/2, 100)}\n{else}\n;VG1 E4 F{max(new_filament_e_feedrate, 200)}\n;VG1 E4 F{max(new_filament_e_feedrate/2, 100)}\n{endif}\n{endif}\n\n; VFLUSH_START\n\n{if flush_length>41.5}\n;VG1 E41.5 F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n;VG1 E{flush_length-41.5} F{new_filament_e_feedrate}\n{else}\n;VG1 E{flush_length} F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n{endif}\n\nSYNC T{ceil(flush_length / 125) * 5}\n\n; VFLUSH_END\n\nM1002 set_filament_type:{filament_type[next_extruder]}\n\nM400\nM83\n{if next_extruder < 255}\n\nM628 S0\n;VM109 S[new_filament_temp]\nM629\nM400\n\nM983.3 F{filament_max_volumetric_speed[next_extruder]/2.4} A0.4\n\nM400\n{if wipe_avoid_perimeter}\nG1 Y320 F30000\nG1 X{wipe_avoid_pos_x} F30000\n{endif}\nG1 Y295 F30000\nG1 Y265 F18000\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n\nM993 A3 B3 C3 ; nozzle cam detection allow status restore.\n\n{if (filament_type[next_extruder] == \"TPU\")}\nM1015.3 S1;enable tpu clog detect\n{else}\nM1015.3 S0;disable tpu clog detect\n{endif}\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")}\nM1015.4 S1 K1 H[nozzle_diameter] ;enable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620.6 I[next_extruder] W1 ;enable ams air printing detect\nM1002 gcode_claim_action : 0\n"
|
||||
}
|
||||
@@ -207,6 +207,8 @@ set(lisbslic3r_sources
|
||||
GCode/ConflictChecker.hpp
|
||||
GCode/CoolingBuffer.cpp
|
||||
GCode/CoolingBuffer.hpp
|
||||
GCode/TimelapsePosPicker.cpp
|
||||
GCode/TimelapsePosPicker.hpp
|
||||
GCode.cpp
|
||||
GCode/ExtrusionProcessor.hpp
|
||||
GCode/FanMover.cpp
|
||||
|
||||
+27
-5
@@ -2117,6 +2117,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
PROFILE_FUNC();
|
||||
|
||||
m_print = &print;
|
||||
m_timelapse_pos_picker.init(&print,m_writer.get_xy_offset().cast<coord_t>());
|
||||
|
||||
// modifies m_silent_time_estimator_enabled
|
||||
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
|
||||
@@ -2864,7 +2865,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
|
||||
// and export G-code into file.
|
||||
tool_ordering.cal_most_used_extruder(print.config());
|
||||
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file, prime_extruder);
|
||||
m_printed_objects.insert(&object);
|
||||
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file,
|
||||
prime_extruder);
|
||||
{
|
||||
// save the flush statitics stored in tool ordering by object
|
||||
print.m_statistics_by_extruder_count.stats_by_single_extruder += tool_ordering.get_filament_change_stats(ToolOrdering::FilamentChangeMode::SingleExt);
|
||||
@@ -4112,7 +4115,6 @@ LayerResult GCode::process_layer(
|
||||
bool has_insert_timelapse_gcode = false;
|
||||
bool has_wipe_tower = (layer_tools.has_wipe_tower && m_wipe_tower);
|
||||
|
||||
int physical_extruder_id = print.config().physical_extruder_map.get_at(most_used_extruder);
|
||||
|
||||
ZHopType z_hope_type = ZHopType(FILAMENT_CONFIG(z_hop_types));
|
||||
LiftType auto_lift_type = LiftType::NormalLift;
|
||||
@@ -4137,7 +4139,7 @@ LayerResult GCode::process_layer(
|
||||
}
|
||||
if (! m_config.layer_change_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id));
|
||||
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(m_config.physical_extruder_map.get_at(most_used_extruder)));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
gcode += this->placeholder_parser_process("layer_change_gcode",
|
||||
@@ -4561,14 +4563,34 @@ LayerResult GCode::process_layer(
|
||||
}
|
||||
}
|
||||
|
||||
auto insert_timelapse_gcode = [this, print_z, &print, &physical_extruder_id, &layer_object_label_ids]() -> std::string {
|
||||
auto insert_timelapse_gcode = [this, print_z, &print, &most_used_extruder, &layer_object_label_ids,&printed_objects = std::as_const(m_printed_objects)]() -> std::string {
|
||||
PosPickCtx ctx;
|
||||
ctx.curr_pos = { (coord_t)(scale_(m_writer.get_position().x())),(coord_t)(scale_(m_writer.get_position().y())) };
|
||||
ctx.curr_layer = this->layer();
|
||||
ctx.curr_extruder_id = m_writer.filament()->extruder_id();
|
||||
ctx.picture_extruder_id = most_used_extruder;
|
||||
if (m_config.nozzle_diameter.size() > 1) {
|
||||
ctx.extruder_height_gap = m_config.extruder_printable_height.values[0] - m_config.extruder_printable_height.values[1];
|
||||
ctx.liftable_extruder_id = m_config.extruder_printable_height.values[0] < m_config.extruder_printable_height.values[0] ? 0 : 1;
|
||||
}
|
||||
|
||||
ctx.print_sequence = m_config.print_sequence;
|
||||
if (m_config.print_sequence == PrintSequence::ByObject)
|
||||
ctx.printed_objects = printed_objects;
|
||||
ctx.based_on_all_layer = m_config.timelapse_type == TimelapseType::tlSmooth;
|
||||
|
||||
auto timelapse_pos=m_timelapse_pos_picker.pick_pos(ctx);
|
||||
|
||||
std::string timepals_gcode;
|
||||
if (!print.config().time_lapse_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(physical_extruder_id));
|
||||
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(m_config.physical_extruder_map.get_at(most_used_extruder)));
|
||||
config.set_key_value("timelapse_pos_x", new ConfigOptionInt((int)timelapse_pos.x()));
|
||||
config.set_key_value("timelapse_pos_y", new ConfigOptionInt((int)timelapse_pos.y()));
|
||||
config.set_key_value("has_timelapse_safe_pos", new ConfigOptionBool(timelapse_pos != DefaultTimelapsePos));
|
||||
timepals_gcode = this->placeholder_parser_process("timelapse_gcode", print.config().time_lapse_gcode.value, m_writer.filament()->id(), &config) + "\n";
|
||||
}
|
||||
if (!timepals_gcode.empty()) {
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
// ORCA: post processor below used for Dynamic Pressure advance
|
||||
#include "GCode/AdaptivePAProcessor.hpp"
|
||||
|
||||
#include "GCode/TimelapsePosPicker.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -523,6 +525,7 @@ private:
|
||||
Wipe m_wipe;
|
||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||
RetractWhenCrossingPerimeters m_retract_when_crossing_perimeters;
|
||||
TimelapsePosPicker m_timelapse_pos_picker;
|
||||
bool m_enable_loop_clipping;
|
||||
//resonance avoidance
|
||||
bool m_resonance_avoidance;
|
||||
@@ -607,6 +610,8 @@ private:
|
||||
|
||||
Print *m_print{nullptr};
|
||||
|
||||
std::set<const PrintObject*> m_printed_objects;
|
||||
|
||||
// Processor
|
||||
GCodeProcessor m_processor;
|
||||
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
#include "TimelapsePosPicker.hpp"
|
||||
#include "Layer.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
void TimelapsePosPicker::init(const Print* print_, const Point& plate_offset)
|
||||
{
|
||||
reset();
|
||||
m_plate_offset = plate_offset;
|
||||
print = print_;
|
||||
construct_printable_area_by_printer();
|
||||
}
|
||||
|
||||
void TimelapsePosPicker::reset()
|
||||
{
|
||||
print = nullptr;
|
||||
m_bed_polygon.clear();
|
||||
m_extruder_printable_area.clear();
|
||||
m_all_layer_pos = std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a list of print objects based on the provided optional set of printed objects.
|
||||
*
|
||||
* If the optional set of printed objects is provided, it converts the set into a vector.
|
||||
* Otherwise, it retrieves all objects from the print instance.
|
||||
*/
|
||||
std::vector<const PrintObject*> TimelapsePosPicker::get_object_list(const std::optional<std::set<const PrintObject*>>& printed_objects)
|
||||
{
|
||||
std::vector<const PrintObject*> object_list;
|
||||
if (printed_objects.has_value()) {
|
||||
object_list = std::vector<const PrintObject*>(printed_objects->begin(), printed_objects->end());
|
||||
}
|
||||
else {
|
||||
object_list = std::vector<const PrintObject*>(print->objects().begin(), print->objects().end());
|
||||
}
|
||||
return object_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs the printable area based on printer configuration.
|
||||
*
|
||||
* This function initializes the bed polygon, excludes specific areas, accounts for wipe towers,
|
||||
* and calculates the printable area for each extruder.
|
||||
*/
|
||||
void TimelapsePosPicker::construct_printable_area_by_printer()
|
||||
{
|
||||
auto config = print->config();
|
||||
size_t extruder_count = config.nozzle_diameter.size();
|
||||
m_extruder_printable_area.clear();
|
||||
m_extruder_printable_area.resize(extruder_count);
|
||||
|
||||
for (size_t idx = 0; idx < config.printable_area.values.size(); ++idx)
|
||||
m_bed_polygon.points.emplace_back(coord_t(scale_(config.printable_area.values[idx].x())), coord_t(scale_(config.printable_area.values[idx].y())));
|
||||
|
||||
Polygon bed_exclude_area;
|
||||
for (size_t idx = 0; idx < config.bed_exclude_area.values.size(); ++idx)
|
||||
bed_exclude_area.points.emplace_back(coord_t(scale_(config.bed_exclude_area.values[idx].x())), coord_t(scale_(config.bed_exclude_area.values[idx].y())));
|
||||
|
||||
Point base_wp_pt = print->get_fake_wipe_tower().pos.cast<coord_t>();
|
||||
base_wp_pt = Point{ scale_(base_wp_pt.x()),scale_(base_wp_pt.y()) };
|
||||
|
||||
auto transform_wt_pt = [base_wp_pt](const Point& pt) -> Point {
|
||||
Point out =pt;
|
||||
out += base_wp_pt;
|
||||
return out;
|
||||
};
|
||||
auto wt_box = print->wipe_tower_data().bbx;
|
||||
Polygon wipe_tower_area{
|
||||
{transform_wt_pt({scale_(wt_box.min.x()),scale_(wt_box.min.y())})},
|
||||
{transform_wt_pt({scale_(wt_box.max.x()),scale_(wt_box.min.y())})},
|
||||
{transform_wt_pt({scale_(wt_box.max.x()),scale_(wt_box.max.y())})},
|
||||
{transform_wt_pt({scale_(wt_box.min.x()),scale_(wt_box.max.y())})}
|
||||
};
|
||||
|
||||
for (size_t idx = 0; idx < extruder_count; ++idx) {
|
||||
ExPolygons printable_area = diff_ex(diff(m_bed_polygon, bed_exclude_area), { wipe_tower_area });
|
||||
if (idx < config.extruder_printable_area.size()) {
|
||||
Polygon extruder_printable_area;
|
||||
for (size_t j = 0; j < config.extruder_printable_area.values[idx].size(); ++j)
|
||||
extruder_printable_area.points.emplace_back(coord_t(scale_(config.extruder_printable_area.values[idx][j].x())), coord_t(scale_(config.extruder_printable_area.values[idx][j].y())));
|
||||
printable_area = intersection_ex(printable_area, Polygons{ extruder_printable_area });
|
||||
}
|
||||
m_extruder_printable_area[idx] = printable_area;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Collects object slice data within a specified height range for a given layer.
|
||||
*
|
||||
* @param layer The layer for which slices are being collected.
|
||||
* @param height_range The height range to consider for collecting slices.
|
||||
* @param object_list List of print objects to process.
|
||||
* @return ExPolygons representing the collected slice data.
|
||||
*/
|
||||
ExPolygons TimelapsePosPicker::collect_object_slices_data(const Layer* layer, float height_range, const std::vector<const PrintObject*>& object_list)
|
||||
{
|
||||
auto range_intersect = [](int left1, int right1, int left2, int right2) {
|
||||
if (left1 <= left2 && left2 <= right1)
|
||||
return true;
|
||||
if (left2 <= left1 && left1 <= right2)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
ExPolygons ret;
|
||||
float z_target = layer->print_z;
|
||||
float z_low = height_range < 0 ? layer->print_z + height_range : layer->print_z;
|
||||
float z_high = height_range < 0 ? layer->print_z : layer->print_z + height_range;
|
||||
if (z_low <= 0)
|
||||
return to_expolygons({ m_bed_polygon });
|
||||
|
||||
for (auto& obj : object_list) {
|
||||
for (auto& instance : obj->instances()) {
|
||||
auto instance_bbox = get_real_instance_bbox(instance);
|
||||
if(range_intersect(instance_bbox.min.z(), instance_bbox.max.z(), layer->print_z + height_range, layer->print_z)){
|
||||
ExPolygon expoly;
|
||||
expoly.contour = {
|
||||
{scale_(instance_bbox.min.x()), scale_(instance_bbox.min.y())},
|
||||
{scale_(instance_bbox.max.x()), scale_(instance_bbox.min.y())},
|
||||
{scale_(instance_bbox.max.x()), scale_(instance_bbox.max.y())},
|
||||
{scale_(instance_bbox.min.x()), scale_(instance_bbox.max.y())}
|
||||
};
|
||||
expoly.contour = expand_object_projection(expoly.contour);
|
||||
ret.emplace_back(std::move(expoly));
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = union_ex(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Polygons TimelapsePosPicker::collect_limit_areas_for_camera(const std::vector<const PrintObject*>& object_list)
|
||||
{
|
||||
Polygons ret;
|
||||
for (auto& obj : object_list)
|
||||
ret.emplace_back(get_limit_area_for_camera(obj));
|
||||
ret = union_(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// expand the object expolygon by safe distance
|
||||
Polygon TimelapsePosPicker::expand_object_projection(const Polygon& poly)
|
||||
{
|
||||
// the input poly is bounding box, so we get the first offseted polygon is ok
|
||||
float radius = scale_(print->config().extruder_clearance_radius.value / 2);
|
||||
return offset(poly, radius)[0];
|
||||
}
|
||||
|
||||
double TimelapsePosPicker::get_raft_height(const PrintObject* obj)
|
||||
{
|
||||
if (!obj || !obj->has_raft())
|
||||
return 0;
|
||||
auto slice_params = obj->slicing_parameters();
|
||||
int base_raft_layers = slice_params.base_raft_layers;
|
||||
double base_raft_height = slice_params.base_raft_layer_height;
|
||||
int interface_raft_layers = slice_params.interface_raft_layers;
|
||||
double interface_raft_height = slice_params.interface_raft_layer_height;
|
||||
double contact_raft_layer_height = slice_params.contact_raft_layer_height;
|
||||
|
||||
double ret = print->config().initial_layer_print_height;
|
||||
if (base_raft_layers - 1 > 0)
|
||||
ret += (base_raft_layers - 1) * base_raft_height;
|
||||
if (interface_raft_layers - 1 > 0)
|
||||
ret += (interface_raft_layers - 1) * interface_raft_height;
|
||||
if (obj->config().raft_layers > 1)
|
||||
ret += contact_raft_layer_height;
|
||||
|
||||
return ret + slice_params.gap_raft_object;
|
||||
}
|
||||
|
||||
// get the real instance bounding box, remove the plate offset and add raft height
|
||||
BoundingBoxf3 TimelapsePosPicker::get_real_instance_bbox(const PrintInstance& instance)
|
||||
{
|
||||
auto bbox = instance.get_bounding_box();
|
||||
double raft_height =get_raft_height(instance.print_object);
|
||||
bbox.max.z() += raft_height;
|
||||
// remove plate offset
|
||||
bbox.min.x() -= m_plate_offset.x();
|
||||
bbox.max.x() -= m_plate_offset.x();
|
||||
bbox.min.y() -= m_plate_offset.y();
|
||||
bbox.max.y() -= m_plate_offset.y();
|
||||
return bbox;
|
||||
}
|
||||
|
||||
Polygon TimelapsePosPicker::get_limit_area_for_camera(const PrintObject* obj)
|
||||
{
|
||||
if (!obj)
|
||||
return {};
|
||||
auto bbox = get_real_instance_bbox(obj->instances().front());
|
||||
float radius = print->config().extruder_clearance_radius.value / 2;
|
||||
|
||||
auto offset_bbox = bbox.inflated(sqrt(2) * radius);
|
||||
Polygon ret = {
|
||||
DefaultCameraPos,
|
||||
{scale_(offset_bbox.max.x()),scale_(offset_bbox.min.y())},
|
||||
{scale_(offset_bbox.max.x()),scale_(offset_bbox.max.y())},
|
||||
{scale_(offset_bbox.min.x()),scale_(offset_bbox.max.y())}
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects the nearest position within the given safe areas relative to the current position.
|
||||
*
|
||||
* This function determines the closest point in the safe areas to the provided current position.
|
||||
* If the current position is already inside a safe area, it returns the current position.
|
||||
* If no safe areas are defined, return default timelapse position.
|
||||
*
|
||||
* @param curr_pos The reference point representing the current position.
|
||||
* @param safe_areas A collection of extended polygons defining the safe areas.
|
||||
* @return Point The nearest point within the safe areas or the default timelapse position if no safe areas exist.
|
||||
*/
|
||||
Point pick_pos_internal(const Point& curr_pos, const ExPolygons& safe_areas)
|
||||
{
|
||||
if (std::any_of(safe_areas.begin(), safe_areas.end(), [&curr_pos](const ExPolygon& p) { return p.contains(curr_pos);}))
|
||||
return curr_pos;
|
||||
|
||||
if (safe_areas.empty())
|
||||
return DefaultTimelapsePos;
|
||||
|
||||
double min_distance = std::numeric_limits<double>::max();
|
||||
Point nearest_point =DefaultTimelapsePos;
|
||||
#if 0
|
||||
for (const auto& expoly : safe_areas) {
|
||||
Polygons polys = to_polygons(expoly);
|
||||
for (auto& poly : polys) {
|
||||
auto nearest_point_ptr = poly.closest_point(curr_pos);
|
||||
if (nearest_point_ptr) {
|
||||
double dist = (*nearest_point_ptr - curr_pos).cast<double>().norm();
|
||||
if (min_distance > dist) {
|
||||
min_distance = dist;
|
||||
nearest_point = *nearest_point_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (const auto& expoly : safe_areas) {
|
||||
Polygons polys = to_polygons(expoly);
|
||||
for (auto& poly : polys) {
|
||||
for (size_t idx = 0; idx < poly.points.size(); ++idx) {
|
||||
Line line(poly.points[idx], poly.points[next_idx_modulo(idx, poly.points)]);
|
||||
Point candidate;
|
||||
double dist = line.distance_to_squared(curr_pos, &candidate);
|
||||
if (min_distance > dist) {
|
||||
min_distance = dist;
|
||||
nearest_point = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return nearest_point;
|
||||
}
|
||||
|
||||
Point TimelapsePosPicker::pick_pos(const PosPickCtx& ctx)
|
||||
{
|
||||
Point res;
|
||||
if (ctx.based_on_all_layer)
|
||||
res = pick_pos_for_all_layer(ctx);
|
||||
else
|
||||
res = pick_pos_for_curr_layer(ctx);
|
||||
|
||||
return { unscale_(res.x()), unscale_(res.y()) };
|
||||
}
|
||||
|
||||
// get center point of curr object
|
||||
Point TimelapsePosPicker::get_object_center(const PrintObject* obj)
|
||||
{
|
||||
if (!obj)
|
||||
return {};
|
||||
// in bambu studio, each object only has one instance
|
||||
auto instance = obj->instances().front();
|
||||
auto instance_bbox = get_real_instance_bbox(instance);
|
||||
Point min_p{ instance_bbox.min.x(),instance_bbox.min.y() };
|
||||
Point max_p{ instance_bbox.max.x(),instance_bbox.max.y() };
|
||||
|
||||
return { scale_((min_p.x() + max_p.x()) / 2),scale_(min_p.y() + max_p.y() / 2) };
|
||||
}
|
||||
|
||||
Point TimelapsePosPicker::pick_nearest_object_center(const Point& curr_pos, const std::vector<const PrintObject*>& object_list)
|
||||
{
|
||||
if (object_list.empty())
|
||||
return {};
|
||||
const PrintObject* ptr = object_list.front();
|
||||
double distance = std::numeric_limits<double>::max();
|
||||
for (auto& obj : object_list) {
|
||||
Point obj_center = get_object_center(obj);
|
||||
double dist = (obj_center - curr_pos).cast<double>().norm();
|
||||
if (distance > dist) {
|
||||
distance = dist;
|
||||
ptr = obj;
|
||||
}
|
||||
}
|
||||
return get_object_center(ptr);
|
||||
}
|
||||
|
||||
Point TimelapsePosPicker::pick_pos_for_curr_layer(const PosPickCtx& ctx)
|
||||
{
|
||||
float height_gap = 0;
|
||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
||||
if (ctx.liftable_extruder_id.has_value() && ctx.picture_extruder_id != ctx.liftable_extruder_id && ctx.extruder_height_gap.has_value())
|
||||
height_gap = -*ctx.extruder_height_gap;
|
||||
}
|
||||
|
||||
std::vector<const PrintObject*> object_list = get_object_list(ctx.printed_objects);
|
||||
|
||||
ExPolygons layer_slices = collect_object_slices_data(ctx.curr_layer,height_gap, object_list);
|
||||
Polygons camera_limit_areas = collect_limit_areas_for_camera(object_list);
|
||||
ExPolygons unplacable_area = union_ex(layer_slices, camera_limit_areas);
|
||||
ExPolygons extruder_printable_area = m_extruder_printable_area[ctx.picture_extruder_id];
|
||||
|
||||
ExPolygons safe_area = diff_ex(extruder_printable_area, unplacable_area);
|
||||
Point objs_center = get_objects_center(object_list);
|
||||
return pick_pos_internal(objs_center, safe_area);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the center of multiple objects.
|
||||
*
|
||||
* This function computes the average center of all instances of the provided objects.
|
||||
*
|
||||
* @param object_list A vector of pointers to PrintObject instances.
|
||||
* @return Point The average center of all objects.
|
||||
*/
|
||||
Point TimelapsePosPicker::get_objects_center(const std::vector<const PrintObject*>& object_list)
|
||||
{
|
||||
if (object_list.empty())
|
||||
return Point(0,0);
|
||||
double sum_x = 0.0;
|
||||
double sum_y = 0.0;
|
||||
size_t total_instances = 0;
|
||||
for (auto& obj : object_list) {
|
||||
for (auto& instance : obj->instances()) {
|
||||
const auto& bbox = get_real_instance_bbox(instance);
|
||||
Point min_p{ bbox.min.x(),bbox.min.y() };
|
||||
Point max_p{ bbox.max.x(),bbox.max.y() };
|
||||
double center_x = (min_p.x() + max_p.x()) / 2.f;
|
||||
double center_y = (min_p.y() + max_p.y()) / 2.f;
|
||||
sum_x += center_x;
|
||||
sum_y += center_y;
|
||||
total_instances += 1;
|
||||
}
|
||||
}
|
||||
return Point{ coord_t(scale_(sum_x / total_instances)),coord_t(scale_(sum_y / total_instances)) };
|
||||
}
|
||||
|
||||
Point TimelapsePosPicker::pick_pos_for_all_layer(const PosPickCtx& ctx)
|
||||
{
|
||||
float height_gap = 0;
|
||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
||||
if (ctx.liftable_extruder_id.has_value() && ctx.picture_extruder_id != ctx.liftable_extruder_id && ctx.extruder_height_gap.has_value())
|
||||
height_gap = *ctx.extruder_height_gap;
|
||||
}
|
||||
if (ctx.curr_layer->print_z < height_gap)
|
||||
return DefaultTimelapsePos;
|
||||
if (m_all_layer_pos)
|
||||
return *m_all_layer_pos;
|
||||
|
||||
Polygons object_projections;
|
||||
|
||||
auto object_list = get_object_list(std::nullopt);
|
||||
|
||||
for (auto& obj : object_list) {
|
||||
for (auto& instance : obj->instances()) {
|
||||
const auto& bbox = get_real_instance_bbox(instance);
|
||||
Point min_p{ scale_(bbox.min.x()),scale_(bbox.min.y()) };
|
||||
Point max_p{ scale_(bbox.max.x()),scale_(bbox.max.y()) };
|
||||
Polygon obj_proj{ { min_p.x(),min_p.y() },
|
||||
{ max_p.x(),min_p.y() },
|
||||
{ max_p.x(),max_p.y() },
|
||||
{ min_p.x(),max_p.y() }
|
||||
};
|
||||
object_projections.emplace_back(expand_object_projection(obj_proj));
|
||||
}
|
||||
};
|
||||
|
||||
object_projections = union_(object_projections);
|
||||
Polygons camera_limit_areas = collect_limit_areas_for_camera(object_list);
|
||||
Polygons unplacable_area = union_(object_projections, camera_limit_areas);
|
||||
|
||||
ExPolygons extruder_printable_area;
|
||||
if (m_extruder_printable_area.size() > 1)
|
||||
extruder_printable_area = intersection_ex(m_extruder_printable_area[0], m_extruder_printable_area[1]);
|
||||
else if (m_extruder_printable_area.size() == 1)
|
||||
extruder_printable_area = m_extruder_printable_area.front();
|
||||
|
||||
ExPolygons safe_area = diff_ex(extruder_printable_area, unplacable_area);
|
||||
|
||||
Point starting_pos = get_objects_center(object_list);
|
||||
|
||||
m_all_layer_pos = pick_pos_internal(starting_pos, safe_area);
|
||||
return *m_all_layer_pos;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef TIMELAPSE_POS_PICKER_HPP
|
||||
#define TIMELAPSE_POS_PICKER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
const Point DefaultTimelapsePos = Point(0, 0);
|
||||
const Point DefaultCameraPos = Point(0, 0);
|
||||
|
||||
class Layer;
|
||||
class Print;
|
||||
|
||||
struct PosPickCtx
|
||||
{
|
||||
Point curr_pos;
|
||||
const Layer* curr_layer;
|
||||
int picture_extruder_id; // the extruder id to take picture
|
||||
int curr_extruder_id;
|
||||
bool based_on_all_layer; // whether to calculate the safe position based all layers
|
||||
PrintSequence print_sequence; // print sequence: by layer or by object
|
||||
std::optional<std::set<const PrintObject*>> printed_objects; // printed objects, only have value in by object mode
|
||||
std::optional<int> liftable_extruder_id; // extruder id that can be lifted, cause bed height to change
|
||||
std::optional<int> extruder_height_gap; // the height gap caused by extruder lift
|
||||
};
|
||||
|
||||
// data are stored without plate offset
|
||||
class TimelapsePosPicker
|
||||
{
|
||||
public:
|
||||
TimelapsePosPicker() = default;
|
||||
~TimelapsePosPicker() = default;
|
||||
|
||||
Point pick_pos(const PosPickCtx& ctx);
|
||||
void init(const Print* print, const Point& plate_offset);
|
||||
void reset();
|
||||
private:
|
||||
void construct_printable_area_by_printer();
|
||||
|
||||
Point pick_pos_for_curr_layer(const PosPickCtx& ctx);
|
||||
Point pick_pos_for_all_layer(const PosPickCtx& ctx);
|
||||
|
||||
ExPolygons collect_object_slices_data(const Layer* curr_layer, float height_range, const std::vector<const PrintObject*>& object_list);
|
||||
Polygons collect_limit_areas_for_camera(const std::vector<const PrintObject*>& object_list);
|
||||
|
||||
Polygon expand_object_projection(const Polygon& poly);
|
||||
|
||||
Point pick_nearest_object_center(const Point& curr_pos, const std::vector<const PrintObject*>& object_list);
|
||||
Point get_objects_center(const std::vector<const PrintObject*>& object_list);
|
||||
|
||||
Polygon get_limit_area_for_camera(const PrintObject* obj);
|
||||
std::vector<const PrintObject*> get_object_list(const std::optional<std::set<const PrintObject*>>& printed_objects);
|
||||
|
||||
double get_raft_height(const PrintObject* obj);
|
||||
BoundingBoxf3 get_real_instance_bbox(const PrintInstance& instance);
|
||||
Point get_object_center(const PrintObject* obj);
|
||||
private:
|
||||
const Print* print{ nullptr };
|
||||
std::vector<ExPolygons> m_extruder_printable_area;
|
||||
Polygon m_bed_polygon;
|
||||
Point m_plate_offset;
|
||||
|
||||
std::optional<Point> m_all_layer_pos;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -4638,7 +4638,7 @@ int Print::load_cached_data(const std::string& directory)
|
||||
return ret;
|
||||
}
|
||||
|
||||
BoundingBoxf3 PrintInstance::get_bounding_box() {
|
||||
BoundingBoxf3 PrintInstance::get_bounding_box() const {
|
||||
return print_object->model_object()->instance_bounding_box(*model_instance, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ struct PrintInstance
|
||||
// Shift of this instance's center into the world coordinates.
|
||||
Point shift;
|
||||
|
||||
BoundingBoxf3 get_bounding_box();
|
||||
BoundingBoxf3 get_bounding_box() const;
|
||||
Polygon get_convex_hull_2d();
|
||||
// SoftFever
|
||||
//
|
||||
|
||||
Reference in new issue
Block a user