mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-01-30 23:48:44 +03:00
Merge prusa 2.6.1
This commit is contained in:
@@ -27,7 +27,7 @@ endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
add_subdirectory(libnest2d)
|
||||
add_subdirectory(arrange)
|
||||
add_subdirectory(libslic3r)
|
||||
add_subdirectory(slic3rutils)
|
||||
add_subdirectory(fff_print)
|
||||
|
||||
17
tests/arrange/CMakeLists.txt
Normal file
17
tests/arrange/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||
add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
|
||||
test_arrange.cpp
|
||||
test_arrange_integration.cpp
|
||||
../data/qidiparts.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||
|
||||
if (WIN32)
|
||||
qidislicer_copy_dlls(${_TEST_NAME}_tests)
|
||||
endif()
|
||||
|
||||
set(_catch_args "exclude:[NotWorking] exclude:[Slow]")
|
||||
list(APPEND _catch_args "${CATCH_EXTRA_ARGS}")
|
||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${_catch_args})
|
||||
1
tests/arrange/arrange_tests_main.cpp
Normal file
1
tests/arrange/arrange_tests_main.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include <catch_main.hpp>
|
||||
1122
tests/arrange/test_arrange.cpp
Normal file
1122
tests/arrange/test_arrange.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1118
tests/arrange/test_arrange_integration.cpp
Normal file
1118
tests/arrange/test_arrange_integration.cpp
Normal file
File diff suppressed because it is too large
Load Diff
312
tests/data/default_fff.ini
Normal file
312
tests/data/default_fff.ini
Normal file
@@ -0,0 +1,312 @@
|
||||
|
||||
autoemit_temperature_commands = 1
|
||||
avoid_crossing_curled_overhangs = 0
|
||||
avoid_crossing_perimeters = 0
|
||||
avoid_crossing_perimeters_max_detour = 0
|
||||
bed_custom_model =
|
||||
bed_custom_texture =
|
||||
bed_shape = 0x0,250x0,250x210,0x210
|
||||
bed_temperature = 110
|
||||
before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z]\n\n
|
||||
between_objects_gcode =
|
||||
bottom_fill_pattern = monotonic
|
||||
bottom_solid_layers = 4
|
||||
bottom_solid_min_thickness = 0.5
|
||||
bridge_acceleration = 1000
|
||||
bridge_angle = 0
|
||||
bridge_fan_speed = 25
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 25
|
||||
brim_separation = 0.1
|
||||
brim_type = outer_only
|
||||
brim_width = 0
|
||||
color_change_gcode = M600\nG1 E0.4 F1500 ; prime after color change
|
||||
colorprint_heights =
|
||||
compatible_printers_condition_cummulative = "printer_notes=~/.*PRINTER_VENDOR_QIDI3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4";"nozzle_diameter[0]!=0.8 and printer_model!=\"MINI\" and printer_notes!~/.*PG.*/ and ! (printer_notes=~/.*PRINTER_VENDOR_QIDI3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)"
|
||||
complete_objects = 0
|
||||
cooling = 1
|
||||
cooling_tube_length = 5
|
||||
cooling_tube_retraction = 91.5
|
||||
default_acceleration = 1000
|
||||
default_filament_profile = "QIDIment PLA"
|
||||
default_print_profile = 0.15mm QUALITY @MK3
|
||||
deretract_speed = 0
|
||||
disable_fan_first_layers = 4
|
||||
dont_support_bridges = 0
|
||||
draft_shield = disabled
|
||||
duplicate_distance = 6
|
||||
elefant_foot_compensation = 0.2
|
||||
enable_dynamic_fan_speeds = 0
|
||||
enable_dynamic_overhang_speeds = 1
|
||||
end_filament_gcode = "; Filament-specific end gcode"
|
||||
end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+1, max_print_height)} F720 ; Move print head up{endif}\nG1 X0 Y200 F3600 ; park\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+49, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM221 S100 ; reset flow\nM900 K0 ; reset LA\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3|@0.25 nozzle MK3).*/}M907 E538 ; reset extruder motor current{endif}\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM84 ; disable motors\n; max_layer_z = [max_layer_z]
|
||||
external_perimeter_acceleration = 0
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
external_perimeter_speed = 25
|
||||
external_perimeters_first = 0
|
||||
extra_loading_move = -2
|
||||
extra_perimeters = 0
|
||||
extra_perimeters_on_overhangs = 0
|
||||
extruder_clearance_height = 20
|
||||
extruder_clearance_radius = 45
|
||||
extruder_colour = ""
|
||||
extruder_offset = 0x0
|
||||
extrusion_axis = E
|
||||
extrusion_multiplier = 1
|
||||
extrusion_width = 0.45
|
||||
fan_always_on = 0
|
||||
fan_below_layer_time = 30
|
||||
filament_colour = #FFF2EC
|
||||
filament_cooling_final_speed = 3.4
|
||||
filament_cooling_initial_speed = 2.2
|
||||
filament_cooling_moves = 4
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
filament_deretract_speed = nil
|
||||
filament_diameter = 1.75
|
||||
filament_load_time = 0
|
||||
filament_loading_speed = 28
|
||||
filament_loading_speed_start = 3
|
||||
filament_max_volumetric_speed = 11
|
||||
filament_minimal_purge_on_wipe_tower = 15
|
||||
filament_notes = ""
|
||||
filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_retract_before_travel = nil
|
||||
filament_retract_before_wipe = nil
|
||||
filament_retract_layer_change = nil
|
||||
filament_retract_length = nil
|
||||
filament_retract_lift = nil
|
||||
filament_retract_lift_above = nil
|
||||
filament_retract_lift_below = nil
|
||||
filament_retract_restart_extra = nil
|
||||
filament_retract_speed = nil
|
||||
filament_settings_id = "Generic ABS"
|
||||
filament_soluble = 0
|
||||
filament_spool_weight = 0
|
||||
filament_toolchange_delay = 0
|
||||
filament_type = ABS
|
||||
filament_unload_time = 0
|
||||
filament_unloading_speed = 90
|
||||
filament_unloading_speed_start = 100
|
||||
filament_vendor = Generic
|
||||
filament_wipe = nil
|
||||
fill_angle = 45
|
||||
fill_density = 15%
|
||||
fill_pattern = gyroid
|
||||
first_layer_acceleration = 800
|
||||
first_layer_acceleration_over_raft = 0
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_extrusion_width = 0.42
|
||||
first_layer_height = 0.2
|
||||
first_layer_speed = 20
|
||||
first_layer_speed_over_raft = 30
|
||||
first_layer_temperature = 255
|
||||
full_fan_speed_layer = 0
|
||||
fuzzy_skin = none
|
||||
fuzzy_skin_point_dist = 0.8
|
||||
fuzzy_skin_thickness = 0.3
|
||||
gap_fill_enabled = 1
|
||||
gap_fill_speed = 40
|
||||
gcode_comments = 0
|
||||
gcode_flavor = marlin
|
||||
gcode_label_objects = 1
|
||||
gcode_resolution = 0.0125
|
||||
gcode_substitutions =
|
||||
high_current_on_filament_swap = 0
|
||||
host_type = qidilink
|
||||
idle_temperature = nil
|
||||
infill_acceleration = 1000
|
||||
infill_anchor = 2.5
|
||||
infill_anchor_max = 12
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_extrusion_width = 0.45
|
||||
infill_first = 0
|
||||
infill_overlap = 10%
|
||||
infill_speed = 80
|
||||
interface_shells = 0
|
||||
ironing = 0
|
||||
ironing_flowrate = 15%
|
||||
ironing_spacing = 0.1
|
||||
ironing_speed = 15
|
||||
ironing_type = top
|
||||
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
|
||||
layer_height = 0.2
|
||||
machine_limits_usage = emit_to_gcode
|
||||
machine_max_acceleration_e = 5000,5000
|
||||
machine_max_acceleration_extruding = 1250,1250
|
||||
machine_max_acceleration_retracting = 1250,1250
|
||||
machine_max_acceleration_travel = 1500,1250
|
||||
machine_max_acceleration_x = 1000,960
|
||||
machine_max_acceleration_y = 1000,960
|
||||
machine_max_acceleration_z = 200,200
|
||||
machine_max_feedrate_e = 120,120
|
||||
machine_max_feedrate_x = 200,100
|
||||
machine_max_feedrate_y = 200,100
|
||||
machine_max_feedrate_z = 12,12
|
||||
machine_max_jerk_e = 4.5,4.5
|
||||
machine_max_jerk_x = 8,8
|
||||
machine_max_jerk_y = 8,8
|
||||
machine_max_jerk_z = 0.4,0.4
|
||||
machine_min_extruding_rate = 0,0
|
||||
machine_min_travel_rate = 0,0
|
||||
max_fan_speed = 15
|
||||
max_layer_height = 0.25
|
||||
max_print_height = 210
|
||||
max_print_speed = 200
|
||||
max_volumetric_extrusion_rate_slope_negative = 0
|
||||
max_volumetric_extrusion_rate_slope_positive = 0
|
||||
max_volumetric_speed = 0
|
||||
min_bead_width = 85%
|
||||
min_fan_speed = 15
|
||||
min_feature_size = 25%
|
||||
min_layer_height = 0.07
|
||||
min_print_speed = 15
|
||||
min_skirt_length = 4
|
||||
mmu_segmented_region_max_width = 0
|
||||
notes =
|
||||
nozzle_diameter = 0.4
|
||||
only_retract_when_crossing_perimeters = 0
|
||||
ooze_prevention = 0
|
||||
output_filename_format = {input_filename_base}_{layer_height}mm_{printing_filament_types}_{printer_model}_{print_time}.gcode
|
||||
overhang_fan_speed_0 = 0
|
||||
overhang_fan_speed_1 = 0
|
||||
overhang_fan_speed_2 = 0
|
||||
overhang_fan_speed_3 = 0
|
||||
overhang_speed_0 = 15
|
||||
overhang_speed_1 = 15
|
||||
overhang_speed_2 = 20
|
||||
overhang_speed_3 = 25
|
||||
overhangs = 1
|
||||
parking_pos_retraction = 92
|
||||
pause_print_gcode = M601
|
||||
perimeter_acceleration = 800
|
||||
perimeter_extruder = 1
|
||||
perimeter_extrusion_width = 0.45
|
||||
perimeter_generator = arachne
|
||||
perimeter_speed = 45
|
||||
perimeters = 2
|
||||
physical_printer_settings_id =
|
||||
post_process =
|
||||
print_settings_id = 0.20mm QUALITY @MK3
|
||||
printer_model = MK3
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
|
||||
printer_settings_id = Original QIDI i3 MK3
|
||||
printer_technology = FFF
|
||||
printer_variant = 0.4
|
||||
printer_vendor =
|
||||
raft_contact_distance = 0.2
|
||||
raft_expansion = 1.5
|
||||
raft_first_layer_density = 90%
|
||||
raft_first_layer_expansion = 3
|
||||
raft_layers = 0
|
||||
remaining_times = 1
|
||||
resolution = 0
|
||||
retract_before_travel = 1
|
||||
retract_before_wipe = 0%
|
||||
retract_layer_change = 1
|
||||
retract_length = 0.8
|
||||
retract_length_toolchange = 4
|
||||
retract_lift = 0.4
|
||||
retract_lift_above = 0
|
||||
retract_lift_below = 209
|
||||
retract_restart_extra = 0
|
||||
retract_restart_extra_toolchange = 0
|
||||
retract_speed = 35
|
||||
seam_position = aligned
|
||||
silent_mode = 1
|
||||
single_extruder_multi_material = 0
|
||||
single_extruder_multi_material_priming = 0
|
||||
skirt_distance = 2
|
||||
skirt_height = 3
|
||||
skirts = 1
|
||||
slice_closing_radius = 0.049
|
||||
slicing_mode = regular
|
||||
slowdown_below_layer_time = 20
|
||||
small_perimeter_speed = 25
|
||||
solid_infill_acceleration = 0
|
||||
solid_infill_below_area = 0
|
||||
solid_infill_every_layers = 0
|
||||
solid_infill_extruder = 1
|
||||
solid_infill_extrusion_width = 0.45
|
||||
solid_infill_speed = 80
|
||||
spiral_vase = 0
|
||||
staggered_inner_seams = 0
|
||||
standby_temperature_delta = -5
|
||||
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.01{elsif nozzle_diameter[0]==0.6}0.02{else}0.04{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 K12{elsif nozzle_diameter[0]==0.8};{else}M900 K20{endif} ; Filament gcode LA 1.0"
|
||||
start_gcode = M862.3 P "[printer_model]" ; printer model check\nM862.1 P[nozzle_diameter] ; nozzle diameter check\nM115 U3.12.2 ; tell printer latest fw version\nG90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n{if filament_settings_id[initial_tool]=~/.*QIDIment PA11.*/}\nG1 Z0.3 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E9 F1000 ; intro line\n{else}\nG1 Z0.2 F720\nG1 Y-3 F1000 ; go outside print area\nG92 E0\nG1 X60 E9 F1000 ; intro line\nG1 X100 E12.5 F1000 ; intro line\n{endif}\nG92 E0\nM221 S{if layer_height<0.075}100{else}95{endif}\n\n; Don't change E values below. Excessive value can damage the printer.\n{if print_settings_id=~/.*(DETAIL @MK3|QUALITY @MK3).*/}M907 E430 ; set extruder motor current{endif}\n{if print_settings_id=~/.*(SPEED @MK3|DRAFT @MK3).*/}M907 E538 ; set extruder motor current{endif}
|
||||
support_material = 0
|
||||
support_material_angle = 0
|
||||
support_material_auto = 1
|
||||
support_material_bottom_contact_distance = 0
|
||||
support_material_bottom_interface_layers = 0
|
||||
support_material_buildplate_only = 0
|
||||
support_material_closing_radius = 2
|
||||
support_material_contact_distance = 0.2
|
||||
support_material_enforce_layers = 0
|
||||
support_material_extruder = 0
|
||||
support_material_extrusion_width = 0.35
|
||||
support_material_interface_contact_loops = 0
|
||||
support_material_interface_extruder = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_interface_pattern = rectilinear
|
||||
support_material_interface_spacing = 0.2
|
||||
support_material_interface_speed = 80%
|
||||
support_material_pattern = rectilinear
|
||||
support_material_spacing = 2
|
||||
support_material_speed = 50
|
||||
support_material_style = grid
|
||||
support_material_synchronize_layers = 0
|
||||
support_material_threshold = 50
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 60%
|
||||
support_tree_angle = 40
|
||||
support_tree_angle_slow = 25
|
||||
support_tree_branch_diameter = 2
|
||||
support_tree_branch_diameter_angle = 5
|
||||
support_tree_branch_diameter_double_wall = 3
|
||||
support_tree_branch_distance = 1
|
||||
support_tree_tip_diameter = 0.8
|
||||
support_tree_top_rate = 15%
|
||||
temperature = 255
|
||||
template_custom_gcode =
|
||||
thick_bridges = 0
|
||||
thin_walls = 0
|
||||
threads = 24
|
||||
thumbnails = 160x120
|
||||
thumbnails_format = PNG
|
||||
toolchange_gcode =
|
||||
top_fill_pattern = monotoniclines
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_infill_acceleration = 0
|
||||
top_solid_infill_speed = 40
|
||||
top_solid_layers = 5
|
||||
top_solid_min_thickness = 0.7
|
||||
travel_acceleration = 0
|
||||
travel_speed = 180
|
||||
travel_speed_z = 12
|
||||
use_firmware_retraction = 0
|
||||
use_relative_e_distances = 1
|
||||
use_volumetric_e = 0
|
||||
variable_layer_height = 1
|
||||
wall_distribution_count = 1
|
||||
wall_transition_angle = 10
|
||||
wall_transition_filter_deviation = 25%
|
||||
wall_transition_length = 100%
|
||||
wipe = 1
|
||||
wipe_into_infill = 0
|
||||
wipe_into_objects = 0
|
||||
wipe_tower = 1
|
||||
wipe_tower_bridging = 10
|
||||
wipe_tower_brim_width = 2
|
||||
wipe_tower_cone_angle = 0
|
||||
wipe_tower_extra_spacing = 100%
|
||||
wipe_tower_no_sparse_layers = 0
|
||||
wipe_tower_rotation_angle = 0
|
||||
wipe_tower_width = 60
|
||||
wipe_tower_x = 170
|
||||
wipe_tower_y = 125
|
||||
wiping_volumes_extruders = 70,70
|
||||
wiping_volumes_matrix = 0
|
||||
xy_size_compensation = 0
|
||||
z_offset = 0
|
||||
5981
tests/data/qidiparts.cpp
Normal file
5981
tests/data/qidiparts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
14
tests/data/qidiparts.hpp
Normal file
14
tests/data/qidiparts.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef QIDIPARTS_H
|
||||
#define QIDIPARTS_H
|
||||
|
||||
#include <vector>
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
|
||||
using TestData = std::vector<Slic3r::Polygon>;
|
||||
using TestDataEx = std::vector<Slic3r::ExPolygons>;
|
||||
|
||||
extern const TestData QIDI_PART_POLYGONS;
|
||||
extern const TestData QIDI_STEGOSAUR_POLYGONS;
|
||||
extern const TestDataEx QIDI_PART_POLYGONS_EX;
|
||||
|
||||
#endif // QIDIPARTS_H
|
||||
@@ -228,7 +228,7 @@ void init_print(std::vector<TriangleMesh> &&meshes, Slic3r::Print &print, Slic3r
|
||||
object->add_volume(std::move(t));
|
||||
object->add_instance();
|
||||
}
|
||||
arrange_objects(model, InfiniteBed{}, ArrangeParams{ scaled(min_object_distance(config))});
|
||||
arrange_objects(model, arr2::to_arrange_bed(get_bed_shape(config)), arr2::ArrangeSettings{}.set_distance_from_objects(min_object_distance(config)));
|
||||
model.center_instances_around_point({100, 100});
|
||||
for (ModelObject *mo : model.objects) {
|
||||
mo->ensure_on_bed();
|
||||
|
||||
@@ -42,8 +42,12 @@ SCENARIO("Model construction", "[Model]") {
|
||||
}
|
||||
}
|
||||
model_object->add_instance();
|
||||
arrange_objects(model, InfiniteBed{scaled(Vec2d(100, 100))}, ArrangeParams{scaled(min_object_distance(config))});
|
||||
model_object->ensure_on_bed();
|
||||
arrange_objects(model,
|
||||
arr2::to_arrange_bed(get_bed_shape(config)),
|
||||
arr2::ArrangeSettings{}.set_distance_from_objects(
|
||||
min_object_distance(config)));
|
||||
|
||||
model_object->ensure_on_bed();
|
||||
print.auto_assign_extruders(model_object);
|
||||
THEN("Print works?") {
|
||||
print.set_status_silent();
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||
add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp printer_parts.cpp printer_parts.hpp)
|
||||
|
||||
# mold linker for successful linking needs also to link TBB library and link it before libslic3r.
|
||||
target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb TBB::tbbmalloc libnest2d )
|
||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||
|
||||
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||
set(_catch_args "exclude:[NotWorking]")
|
||||
list(APPEND _catch_args "${CATCH_EXTRA_ARGS}")
|
||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${_catch_args})
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
#ifndef PRINTER_PARTS_H
|
||||
#define PRINTER_PARTS_H
|
||||
|
||||
#include <vector>
|
||||
#include <libnest2d/libnest2d.hpp>
|
||||
|
||||
using TestData = std::vector<libnest2d::PathImpl>;
|
||||
using TestDataEx = std::vector<libnest2d::PolygonImpl>;
|
||||
|
||||
extern const TestData PRINTER_PART_POLYGONS;
|
||||
extern const TestData STEGOSAUR_POLYGONS;
|
||||
extern const TestDataEx PRINTER_PART_POLYGONS_EX;
|
||||
|
||||
#endif // PRINTER_PARTS_H
|
||||
@@ -31,13 +31,15 @@ add_executable(${_TEST_NAME}_tests
|
||||
test_png_io.cpp
|
||||
test_surface_mesh.cpp
|
||||
test_timeutils.cpp
|
||||
test_quadric_edge_collapse.cpp
|
||||
test_quadric_edge_collapse.cpp
|
||||
test_triangulation.cpp
|
||||
test_emboss.cpp
|
||||
test_indexed_triangle_set.cpp
|
||||
test_astar.cpp
|
||||
test_jump_point_search.cpp
|
||||
../libnest2d/printer_parts.cpp
|
||||
test_anyptr.cpp
|
||||
test_jump_point_search.cpp
|
||||
../data/qidiparts.cpp
|
||||
../data/qidiparts.hpp
|
||||
)
|
||||
|
||||
if (TARGET OpenVDB::openvdb)
|
||||
|
||||
198
tests/libslic3r/test_anyptr.cpp
Normal file
198
tests/libslic3r/test_anyptr.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <libslic3r/libslic3r.h>
|
||||
#include <libslic3r/AnyPtr.hpp>
|
||||
#include <test_utils.hpp>
|
||||
|
||||
class Foo
|
||||
{
|
||||
public:
|
||||
virtual ~Foo() = default;
|
||||
|
||||
virtual void set_foo(int) = 0;
|
||||
virtual int get_foo() const = 0;
|
||||
};
|
||||
|
||||
class Bar: public Foo
|
||||
{
|
||||
int m_i = 0;
|
||||
|
||||
public:
|
||||
virtual void set_foo(int i) { m_i = i; }
|
||||
virtual int get_foo() const { return m_i; };
|
||||
};
|
||||
|
||||
class BarPlus: public Foo {
|
||||
int m_i = 0;
|
||||
|
||||
public:
|
||||
virtual void set_foo(int i) { m_i = i + 1; }
|
||||
virtual int get_foo() const { return m_i; };
|
||||
};
|
||||
|
||||
TEST_CASE("Testing AnyPtr", "[anyptr]") {
|
||||
using Slic3r::AnyPtr;
|
||||
|
||||
SECTION("Construction with various valid arguments using operator=")
|
||||
{
|
||||
auto args = std::make_tuple(nullptr,
|
||||
AnyPtr<Foo>{nullptr},
|
||||
AnyPtr{static_cast<Foo *>(nullptr)},
|
||||
AnyPtr{static_cast<Bar *>(nullptr)},
|
||||
AnyPtr{static_cast<BarPlus *>(nullptr)},
|
||||
AnyPtr<Foo>{},
|
||||
AnyPtr<Bar>{},
|
||||
AnyPtr<BarPlus>{},
|
||||
static_cast<Foo *>(nullptr),
|
||||
static_cast<Bar *>(nullptr),
|
||||
static_cast<BarPlus *>(nullptr));
|
||||
|
||||
auto check_ptr = [](auto &ptr) {
|
||||
REQUIRE(!ptr);
|
||||
REQUIRE(!ptr.is_owned());
|
||||
|
||||
auto shp = ptr.get_shared_cpy();
|
||||
REQUIRE(!shp);
|
||||
};
|
||||
|
||||
SECTION("operator =") {
|
||||
Slic3r::for_each_in_tuple([&check_ptr](auto &arg){
|
||||
AnyPtr<const Foo> ptr = std::move(arg);
|
||||
|
||||
check_ptr(ptr);
|
||||
}, args);
|
||||
}
|
||||
|
||||
SECTION("move construction")
|
||||
{
|
||||
Slic3r::for_each_in_tuple([&check_ptr](auto &arg){
|
||||
AnyPtr<const Foo> ptr{std::move(arg)};
|
||||
|
||||
check_ptr(ptr);
|
||||
}, args);
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A polymorphic base class type Foo") {
|
||||
WHEN("Creating a subclass on the stack") {
|
||||
Bar bar;
|
||||
auto val = random_value(-100, 100);
|
||||
bar.set_foo(val);
|
||||
|
||||
THEN("Storing a raw pointer in an AnyPtr<Foo> should be valid "
|
||||
"until the object is not destroyed")
|
||||
{
|
||||
AnyPtr<Foo> ptr = &bar;
|
||||
auto val2 = random_value(-100, 100);
|
||||
ptr->set_foo(val2);
|
||||
|
||||
REQUIRE(ptr->get_foo() == val2);
|
||||
}
|
||||
|
||||
THEN("Storing a raw pointer in an AnyPtr<const Foo> should be "
|
||||
"valid until the object is not destroyed")
|
||||
{
|
||||
AnyPtr<const Foo> ptr{&bar};
|
||||
|
||||
REQUIRE(ptr->get_foo() == val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("An empty AnyPtr of type Foo")
|
||||
{
|
||||
AnyPtr<Foo> ptr;
|
||||
|
||||
WHEN("Re-assigning a new unique_ptr of object of type Bar to ptr")
|
||||
{
|
||||
auto bar = std::make_unique<Bar>();
|
||||
auto val = random_value(-100, 100);
|
||||
|
||||
bar->set_foo(val);
|
||||
|
||||
ptr = std::move(bar);
|
||||
|
||||
THEN("the ptr should contain the new object and should own it")
|
||||
{
|
||||
REQUIRE(ptr->get_foo() == val);
|
||||
REQUIRE(ptr.is_owned());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("Re-assigning a new unique_ptr of object of type BarPlus to ptr")
|
||||
{
|
||||
auto barplus = std::make_unique<BarPlus>();
|
||||
auto val = random_value(-100, 100);
|
||||
|
||||
barplus->set_foo(val);
|
||||
|
||||
ptr = std::move(barplus);
|
||||
|
||||
THEN("the ptr should contain the new object and should own it")
|
||||
{
|
||||
REQUIRE(ptr->get_foo() == val + 1);
|
||||
REQUIRE(ptr.is_owned());
|
||||
}
|
||||
|
||||
THEN("copying the stored object into a shared_ptr should be invalid")
|
||||
{
|
||||
std::shared_ptr<Foo> shptr = ptr.get_shared_cpy();
|
||||
|
||||
REQUIRE(!shptr);
|
||||
}
|
||||
|
||||
THEN("copying the stored object into a shared_ptr after calling "
|
||||
"convert_unique_to_shared should be valid")
|
||||
{
|
||||
ptr.convert_unique_to_shared();
|
||||
std::shared_ptr<Foo> shptr = ptr.get_shared_cpy();
|
||||
|
||||
REQUIRE(shptr);
|
||||
REQUIRE(shptr->get_foo() == val + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A vector of AnyPtr<Foo> pointer to random Bar or BarPlus objects")
|
||||
{
|
||||
std::vector<AnyPtr<Foo>> ptrs;
|
||||
|
||||
auto N = random_value(size_t(1), size_t(10));
|
||||
INFO("N = " << N);
|
||||
|
||||
std::generate_n(std::back_inserter(ptrs), N, []{
|
||||
auto v = random_value(0, 1);
|
||||
|
||||
std::unique_ptr<Foo> ret;
|
||||
|
||||
if (v)
|
||||
ret = std::make_unique<Bar>();
|
||||
else
|
||||
ret = std::make_unique<BarPlus>();
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
WHEN("moving the whole array into a vector of AnyPtr<const Foo>")
|
||||
{
|
||||
THEN("the move should be valid")
|
||||
{
|
||||
std::vector<AnyPtr<const Foo>> constptrs;
|
||||
std::vector<int> vals;
|
||||
std::transform(ptrs.begin(), ptrs.end(),
|
||||
std::back_inserter(vals),
|
||||
[](auto &p) { return p->get_foo(); });
|
||||
|
||||
std::move(ptrs.begin(), ptrs.end(), std::back_inserter(constptrs));
|
||||
|
||||
REQUIRE(constptrs.size() == N);
|
||||
REQUIRE(ptrs.size() == N);
|
||||
REQUIRE(std::all_of(ptrs.begin(), ptrs.end(), [](auto &p) { return !p; }));
|
||||
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
REQUIRE(vals[i] == constptrs[i]->get_foo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
//#include "libnest2d/tools/benchmark.h"
|
||||
#include "libslic3r/SVG.hpp"
|
||||
|
||||
#include "../libnest2d/printer_parts.hpp"
|
||||
#include "../data/qidiparts.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -683,15 +683,15 @@ struct Pair
|
||||
template<> struct std::hash<Pair> {
|
||||
size_t operator()(const Pair &c) const
|
||||
{
|
||||
return c.first * PRINTER_PART_POLYGONS.size() + c.second;
|
||||
return c.first * QIDI_PART_POLYGONS.size() + c.second;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("Convex polygon intersection test qidi polygons", "[Geometry][Rotcalip]") {
|
||||
|
||||
// Overlap of the same polygon should always be an intersection
|
||||
for (size_t i = 0; i < PRINTER_PART_POLYGONS.size(); ++i) {
|
||||
Polygon P = PRINTER_PART_POLYGONS[i];
|
||||
for (size_t i = 0; i < QIDI_PART_POLYGONS.size(); ++i) {
|
||||
Polygon P = QIDI_PART_POLYGONS[i];
|
||||
P = Geometry::convex_hull(P.points);
|
||||
bool res = Geometry::convex_polygons_intersect(P, P);
|
||||
if (!res) {
|
||||
@@ -703,8 +703,8 @@ TEST_CASE("Convex polygon intersection test qidi polygons", "[Geometry][Rotcalip
|
||||
}
|
||||
|
||||
std::unordered_set<Pair> combos;
|
||||
for (size_t i = 0; i < PRINTER_PART_POLYGONS.size(); ++i) {
|
||||
for (size_t j = 0; j < PRINTER_PART_POLYGONS.size(); ++j) {
|
||||
for (size_t i = 0; i < QIDI_PART_POLYGONS.size(); ++i) {
|
||||
for (size_t j = 0; j < QIDI_PART_POLYGONS.size(); ++j) {
|
||||
if (i != j) {
|
||||
size_t a = std::min(i, j), b = std::max(i, j);
|
||||
combos.insert(Pair{a, b});
|
||||
@@ -714,7 +714,7 @@ TEST_CASE("Convex polygon intersection test qidi polygons", "[Geometry][Rotcalip
|
||||
|
||||
// All disjoint
|
||||
for (const auto &combo : combos) {
|
||||
Polygon A = PRINTER_PART_POLYGONS[combo.first], B = PRINTER_PART_POLYGONS[combo.second];
|
||||
Polygon A = QIDI_PART_POLYGONS[combo.first], B = QIDI_PART_POLYGONS[combo.second];
|
||||
A = Geometry::convex_hull(A.points);
|
||||
B = Geometry::convex_hull(B.points);
|
||||
|
||||
@@ -741,7 +741,7 @@ TEST_CASE("Convex polygon intersection test qidi polygons", "[Geometry][Rotcalip
|
||||
|
||||
// All intersecting
|
||||
for (const auto &combo : combos) {
|
||||
Polygon A = PRINTER_PART_POLYGONS[combo.first], B = PRINTER_PART_POLYGONS[combo.second];
|
||||
Polygon A = QIDI_PART_POLYGONS[combo.first], B = QIDI_PART_POLYGONS[combo.second];
|
||||
A = Geometry::convex_hull(A.points);
|
||||
B = Geometry::convex_hull(B.points);
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define NOMINMAX
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <test_utils.hpp>
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
@@ -3,6 +3,7 @@ add_executable(${_TEST_NAME}_tests
|
||||
${_TEST_NAME}_tests_main.cpp
|
||||
slic3r_jobs_tests.cpp
|
||||
slic3r_version_tests.cpp
|
||||
slic3r_arrangejob_tests.cpp
|
||||
)
|
||||
|
||||
# mold linker for successful linking needs also to link TBB library and link it before libslic3r.
|
||||
|
||||
351
tests/slic3rutils/slic3r_arrangejob_tests.cpp
Normal file
351
tests/slic3rutils/slic3r_arrangejob_tests.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
#include "catch2/catch.hpp"
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
#include "slic3r/GUI/Jobs/UIThreadWorker.hpp"
|
||||
#include "slic3r/GUI/Jobs/BoostThreadWorker.hpp"
|
||||
|
||||
#include "slic3r/GUI/Jobs/ArrangeJob2.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
|
||||
class RandomArrangeSettings: public Slic3r::arr2::ArrangeSettingsView {
|
||||
Slic3r::arr2::ArrangeSettingsDb::Values m_v;
|
||||
|
||||
std::mt19937 m_rng;
|
||||
public:
|
||||
explicit RandomArrangeSettings(int seed) : m_rng(seed)
|
||||
{
|
||||
std::uniform_real_distribution<float> fdist(0., 100.f);
|
||||
std::uniform_int_distribution<> bdist(0, 1);
|
||||
std::uniform_int_distribution<> dist;
|
||||
m_v.d_obj = fdist(m_rng);
|
||||
m_v.d_bed = fdist(m_rng);
|
||||
m_v.rotations = bdist(m_rng);
|
||||
m_v.geom_handling = static_cast<GeometryHandling>(dist(m_rng) % ghCount);
|
||||
m_v.arr_strategy = static_cast<ArrangeStrategy>(dist(m_rng) % asCount);
|
||||
m_v.xl_align = static_cast<XLPivots>(dist(m_rng) % xlpCount);
|
||||
}
|
||||
explicit RandomArrangeSettings() : m_rng(std::random_device{} ()) {}
|
||||
|
||||
float get_distance_from_objects() const override { return m_v.d_obj; }
|
||||
float get_distance_from_bed() const override { return m_v.d_bed; }
|
||||
bool is_rotation_enabled() const override { return m_v.rotations; }
|
||||
XLPivots get_xl_alignment() const override { return m_v.xl_align; }
|
||||
GeometryHandling get_geometry_handling() const override { return m_v.geom_handling; }
|
||||
ArrangeStrategy get_arrange_strategy() const override { return m_v.arr_strategy; }
|
||||
};
|
||||
|
||||
TEMPLATE_TEST_CASE("Arranging empty bed should do nothing",
|
||||
"[arrangejob][fillbedjob]",
|
||||
Slic3r::GUI::ArrangeJob2,
|
||||
Slic3r::GUI::FillBedJob2)
|
||||
{
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
using JobType = TestType;
|
||||
|
||||
Model m;
|
||||
|
||||
UIThreadWorker w;
|
||||
RandomArrangeSettings settings;
|
||||
|
||||
w.push(std::make_unique<JobType>(arr2::Scene{
|
||||
arr2::SceneBuilder{}.set_model(m).set_arrange_settings(&settings)}));
|
||||
|
||||
w.process_events();
|
||||
|
||||
REQUIRE(m.objects.empty());
|
||||
}
|
||||
|
||||
static void center_first_instance(Slic3r::ModelObject *mo,
|
||||
const Slic3r::BoundingBox &bedbb)
|
||||
{
|
||||
using namespace Slic3r;
|
||||
|
||||
Vec2d d = unscaled(bedbb).center() -
|
||||
to_2d(mo->instance_bounding_box(0).center());
|
||||
auto tr = mo->instances.front()->get_transformation().get_matrix();
|
||||
tr.translate(to_3d(d, 0.));
|
||||
mo->instances.front()->set_transformation(Geometry::Transformation(tr));
|
||||
}
|
||||
|
||||
TEST_CASE("Basic arrange with cube", "[arrangejob]") {
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
std::string basepath = TEST_DATA_DIR PATH_SEPARATOR;
|
||||
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.load_from_ini(basepath + "default_fff.ini",
|
||||
ForwardCompatibilitySubstitutionRule::Enable);
|
||||
Model m = Model::read_from_file(basepath + "20mm_cube.obj", &cfg);
|
||||
|
||||
UIThreadWorker w;
|
||||
arr2::ArrangeSettings settings;
|
||||
|
||||
Points bedpts = get_bed_shape(cfg);
|
||||
arr2::ArrangeBed bed = arr2::to_arrange_bed(bedpts);
|
||||
|
||||
SECTION("Single cube needs to be centered") {
|
||||
w.push(std::make_unique<ArrangeJob2>(arr2::Scene{
|
||||
arr2::SceneBuilder{}
|
||||
.set_model(m)
|
||||
.set_arrange_settings(&settings)
|
||||
.set_bed(cfg)}));
|
||||
|
||||
w.process_events();
|
||||
|
||||
REQUIRE(m.objects.size() == 1);
|
||||
REQUIRE(m.objects.front()->instances.size() == 1);
|
||||
|
||||
Vec3d c3 = m.objects.front()->bounding_box_exact().center();
|
||||
Point c{scaled(c3.x()), scaled(c3.y())};
|
||||
|
||||
REQUIRE(c == bounding_box(bed).center());
|
||||
}
|
||||
|
||||
SECTION("Selected cube needs to go beside existing") {
|
||||
REQUIRE(m.objects.size() == 1);
|
||||
|
||||
ModelObject *mo = m.objects.front();
|
||||
|
||||
// Center the first instance within the bed
|
||||
center_first_instance(mo, bounding_box(bed));
|
||||
|
||||
m.objects.front()->add_instance();
|
||||
|
||||
REQUIRE(m.objects.front()->instances.size() == 2);
|
||||
|
||||
arr2::FixedSelection sel({ {false, true} });
|
||||
arr2::Scene scene{arr2::SceneBuilder{}
|
||||
.set_model(m)
|
||||
.set_arrange_settings(&settings)
|
||||
.set_bed(cfg)
|
||||
.set_selection(&sel)};
|
||||
|
||||
w.push(std::make_unique<ArrangeJob2>(std::move(scene)));
|
||||
w.process_events();
|
||||
|
||||
auto bb0 = m.objects.front()->instance_bounding_box(0);
|
||||
auto bb1 = m.objects.front()->instance_bounding_box(1);
|
||||
|
||||
REQUIRE(!bb0.contains(bb1));
|
||||
|
||||
bb0.merge(bb1);
|
||||
Vec2d sz = to_2d(bb0.size());
|
||||
if (sz.x() > sz.y())
|
||||
std::swap(sz.x(), sz.y());
|
||||
|
||||
double d_obj = settings.get_distance_from_objects();
|
||||
REQUIRE(sz.y() == Approx(2. * bb1.size().y() + d_obj));
|
||||
}
|
||||
|
||||
SECTION("Selected cube (different object), needs to go beside existing") {
|
||||
REQUIRE(m.objects.size() == 1);
|
||||
|
||||
ModelObject *mo = m.objects.front();
|
||||
|
||||
// Center the first instance within the bed
|
||||
center_first_instance(mo, bounding_box(bed));
|
||||
|
||||
ModelObject *mosel = m.add_object(*m.objects.front());
|
||||
|
||||
arr2::FixedSelection sel({ {false}, {true} });
|
||||
arr2::Scene scene{arr2::SceneBuilder{}
|
||||
.set_model(m)
|
||||
.set_arrange_settings(&settings)
|
||||
.set_bed(cfg)
|
||||
.set_selection(&sel)};
|
||||
|
||||
w.push(std::make_unique<ArrangeJob2>(std::move(scene)));
|
||||
w.process_events();
|
||||
|
||||
auto bb0 = mo->instance_bounding_box(0);
|
||||
auto bb1 = mosel->instance_bounding_box(0);
|
||||
|
||||
REQUIRE(!bb0.contains(bb1));
|
||||
|
||||
bb0.merge(bb1);
|
||||
Vec2d sz = to_2d(bb0.size());
|
||||
if (sz.x() > sz.y())
|
||||
std::swap(sz.x(), sz.y());
|
||||
|
||||
double d_obj = settings.get_distance_from_objects();
|
||||
REQUIRE(sz.y() == Approx(2. * bb1.size().y() + d_obj));
|
||||
}
|
||||
|
||||
SECTION("Four cubes needs to touch each other after arrange") {
|
||||
ModelObject *mo = m.objects.front();
|
||||
mo->add_instance();
|
||||
mo->add_instance();
|
||||
mo->add_instance();
|
||||
|
||||
auto bedbb = unscaled<double>(bounding_box(bed));
|
||||
ModelInstance *mi = mo->instances[0];
|
||||
|
||||
Vec2d d = bedbb.min - to_2d(mo->instance_bounding_box(0).center());
|
||||
auto tr = mi->get_transformation().get_matrix();
|
||||
tr.translate(to_3d(d, 0.));
|
||||
mi->set_transformation(Geometry::Transformation(tr));
|
||||
|
||||
mi = mo->instances[1];
|
||||
d = Vec2d(bedbb.min.x(), bedbb.max.y()) -
|
||||
to_2d(mo->instance_bounding_box(1).center());
|
||||
tr = mi->get_transformation().get_matrix();
|
||||
tr.translate(to_3d(d, 0.));
|
||||
mi->set_transformation(Geometry::Transformation(tr));
|
||||
|
||||
mi = mo->instances[2];
|
||||
d = bedbb.max - to_2d(mo->instance_bounding_box(2).center());
|
||||
tr = mi->get_transformation().get_matrix();
|
||||
tr.translate(to_3d(d, 0.));
|
||||
mi->set_transformation(Geometry::Transformation(tr));
|
||||
|
||||
mi = mo->instances[3];
|
||||
d = Vec2d(bedbb.max.x(), bedbb.min.y()) -
|
||||
to_2d(mo->instance_bounding_box(3).center());
|
||||
tr = mi->get_transformation().get_matrix();
|
||||
tr.translate(to_3d(d, 0.));
|
||||
mi->set_transformation(Geometry::Transformation(tr));
|
||||
|
||||
arr2::Scene scene{arr2::SceneBuilder{}
|
||||
.set_model(m)
|
||||
.set_arrange_settings(&settings)
|
||||
.set_bed(cfg)};
|
||||
|
||||
w.push(std::make_unique<ArrangeJob2>(std::move(scene)));
|
||||
w.process_events();
|
||||
|
||||
auto pilebb = m.objects.front()->bounding_box_exact();
|
||||
Vec3d c3 = pilebb.center();
|
||||
Point c{scaled(c3.x()), scaled(c3.y())};
|
||||
|
||||
REQUIRE(c == bounding_box(bed).center());
|
||||
|
||||
float d_obj = settings.get_distance_from_objects();
|
||||
REQUIRE(pilebb.size().x() == Approx(2. * 20. + d_obj));
|
||||
REQUIRE(pilebb.size().y() == Approx(2. * 20. + d_obj));
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyProgress: Slic3r::ProgressIndicator {
|
||||
int range = 100;
|
||||
int pr = 0;
|
||||
std::string statustxt;
|
||||
void set_range(int r) override { range = r; }
|
||||
void set_cancel_callback(CancelFn = CancelFn()) override {}
|
||||
void set_progress(int p) override { pr = p; }
|
||||
void set_status_text(const char *txt) override { statustxt = txt; }
|
||||
int get_range() const override { return range; }
|
||||
};
|
||||
|
||||
TEST_CASE("Test for modifying model during arrangement", "[arrangejob][fillbedjob]")
|
||||
{
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
std::string basepath = TEST_DATA_DIR PATH_SEPARATOR;
|
||||
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.load_from_ini(basepath + "default_fff.ini",
|
||||
ForwardCompatibilitySubstitutionRule::Enable);
|
||||
|
||||
Model m;
|
||||
|
||||
ModelObject* new_object = m.add_object();
|
||||
new_object->name = "20mm_cyl";
|
||||
new_object->add_instance();
|
||||
TriangleMesh mesh = make_cylinder(10., 10.);
|
||||
ModelVolume* new_volume = new_object->add_volume(mesh);
|
||||
new_volume->name = new_object->name;
|
||||
|
||||
Points bedpts = get_bed_shape(cfg);
|
||||
arr2::ArrangeBed bed = arr2::to_arrange_bed(bedpts);
|
||||
|
||||
BoostThreadWorker w(std::make_unique<DummyProgress>());
|
||||
RandomArrangeSettings settings;
|
||||
|
||||
SECTION("Remove 10 cylinder instances during arrange") {
|
||||
for (size_t i = 1; i < 10; ++i)
|
||||
new_object->add_instance();
|
||||
|
||||
arr2::Scene scene{arr2::SceneBuilder{}
|
||||
.set_model(m)
|
||||
.set_arrange_settings(&settings)
|
||||
.set_bed(cfg)};
|
||||
|
||||
ArrangeJob2::Callbacks cbs;
|
||||
cbs.on_prepared = [&m] (auto &) {
|
||||
m.clear_objects();
|
||||
};
|
||||
|
||||
w.push(std::make_unique<ArrangeJob2>(std::move(scene), cbs));
|
||||
w.wait_for_current_job();
|
||||
|
||||
REQUIRE(m.objects.empty());
|
||||
}
|
||||
}
|
||||
|
||||
//TEST_CASE("Logical bed needs to be used when physical bed is full",
|
||||
// "[arrangejob][fillbedjob]")
|
||||
//{
|
||||
// using namespace Slic3r;
|
||||
// using namespace Slic3r::GUI;
|
||||
|
||||
// std::string basepath = TEST_DATA_DIR PATH_SEPARATOR;
|
||||
|
||||
// DynamicPrintConfig cfg;
|
||||
// cfg.load_from_ini(basepath + "default_fff.ini",
|
||||
// ForwardCompatibilitySubstitutionRule::Enable);
|
||||
|
||||
// Model m;
|
||||
|
||||
// ModelObject* new_object = m.add_object();
|
||||
// new_object->name = "bigbox";
|
||||
// new_object->add_instance();
|
||||
// TriangleMesh mesh = make_cube(200., 200., 10.);
|
||||
// ModelVolume* new_volume = new_object->add_volume(mesh);
|
||||
// new_volume->name = new_object->name;
|
||||
|
||||
// Points bedpts = get_bed_shape(cfg);
|
||||
// arr2::ArrangeBed bed = arr2::to_arrange_bed(bedpts);
|
||||
// auto bedbb = bounding_box(bed);
|
||||
|
||||
// center_first_instance(new_object, bedbb);
|
||||
|
||||
// new_object = m.add_object();
|
||||
// new_object->name = "40x20mm_box";
|
||||
// new_object->add_instance();
|
||||
// mesh = make_cube(50., 50., 50.);
|
||||
// new_volume = new_object->add_volume(mesh);
|
||||
// new_volume->name = new_object->name;
|
||||
|
||||
// UIThreadWorker w(std::make_unique<DummyProgress>());
|
||||
// arr2::ArrangeSettings settings;
|
||||
|
||||
// SECTION("Single cube needs to be on first logical bed") {
|
||||
// {
|
||||
// arr2::Scene scene{&m, &settings, &cfg};
|
||||
|
||||
// w.push(std::make_unique<ArrangeJob2>(std::move(scene)));
|
||||
// w.process_events();
|
||||
// }
|
||||
|
||||
// store_3mf("logicalbed_10mm.3mf", &m, &cfg, false);
|
||||
|
||||
// REQUIRE(m.objects.size() == 2);
|
||||
|
||||
// Vec3d c3 = m.objects[1]->bounding_box_exact().center();
|
||||
// Point result_center{scaled(c3.x()), scaled(c3.y())};
|
||||
|
||||
// auto bedidx_ojb1 = scene.virtual_bed_handler().get_bed_index(m.objects[1]->instances[0]);
|
||||
// REQUIRE(bedidx_ojb1 == 1);
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <libslic3r/TriangleMesh.hpp>
|
||||
#include <libslic3r/Format/OBJ.hpp>
|
||||
#include <random>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define PATH_SEPARATOR R"(\)"
|
||||
@@ -18,4 +19,22 @@ inline Slic3r::TriangleMesh load_model(const std::string &obj_filename)
|
||||
return mesh;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Slic3r::FloatingOnly<T> random_value(T minv, T maxv)
|
||||
{
|
||||
static std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_real_distribution<T> dist(minv, maxv);
|
||||
|
||||
return dist(rng);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Slic3r::IntegerOnly<T> random_value(T minv, T maxv)
|
||||
{
|
||||
static std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_int_distribution<T> dist(minv, maxv);
|
||||
|
||||
return dist(rng);
|
||||
}
|
||||
|
||||
#endif // SLIC3R_TEST_UTILS
|
||||
|
||||
Reference in New Issue
Block a user