From e627aeb685e90f907104e395bf8f9ed7077b5b0d Mon Sep 17 00:00:00 2001 From: surynek Date: Mon, 21 Oct 2024 01:46:33 +0200 Subject: [PATCH] Implementation of object gluing into the sequential solver and more fine grained progress callback. --- src/libseqarrange/src/seq_interface.cpp | 185 +++----- src/libseqarrange/src/seq_sequential.cpp | 406 ++++++++++++++++-- src/libseqarrange/src/seq_sequential.hpp | 47 +- src/libseqarrange/src/sequential_prusa.cpp | 5 - src/libseqarrange/test/seq_test_interface.cpp | 84 +++- src/libseqarrange/test/seq_test_interface.hpp | 2 + src/slic3r/GUI/ArrangeHelper.cpp | 2 +- 7 files changed, 565 insertions(+), 166 deletions(-) diff --git a/src/libseqarrange/src/seq_interface.cpp b/src/libseqarrange/src/seq_interface.cpp index deaa4629a3..8460b414a0 100644 --- a/src/libseqarrange/src/seq_interface.cpp +++ b/src/libseqarrange/src/seq_interface.cpp @@ -320,6 +320,8 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver std::map original_index_map; std::vector lepox_to_next; + std::vector solvable_objects; + #ifdef DEBUG { printf(" Preparing objects ...\n"); @@ -333,12 +335,9 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver std::vector > extruder_convex_level_polygons; std::vector > extruder_box_level_polygons; - - std::vector scale_down_unreachable_polygons; + SolvableObject solvable_object; original_index_map[i] = objects_to_print[i].id; - - Polygon scale_down_object_polygon; prepare_ExtruderPolygons(solver_configuration, printer_geometry, @@ -354,13 +353,13 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver box_level_polygons, extruder_convex_level_polygons, extruder_box_level_polygons, - scale_down_object_polygon, - scale_down_unreachable_polygons); - - unreachable_polygons.push_back(scale_down_unreachable_polygons); - polygons.push_back(scale_down_object_polygon); + solvable_object.polygon, + solvable_object.unreachable_polygons); - lepox_to_next.push_back(objects_to_print[i].glued_to_next); + solvable_object.id = objects_to_print[i].id; + solvable_object.lepox_to_next = objects_to_print[i].glued_to_next; + + solvable_objects.push_back(solvable_object); } std::vector remaining_polygons; @@ -404,9 +403,7 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver poly_positions_X, poly_positions_Y, times_T, - polygons, - unreachable_polygons, - lepox_to_next, + solvable_objects, polygon_index_map, decided_polygons, remaining_polygons, @@ -483,28 +480,15 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver printf("Intermediate CPU time: %.3f\n", (finish - start) / (double)CLOCKS_PER_SEC); } #endif - - std::vector next_polygons; - std::vector > next_unreachable_polygons; - std::vector next_lepox_to_next; + + std::vector next_solvable_objects; for (unsigned int i = 0; i < remaining_polygons.size(); ++i) { - next_polygons.push_back(polygons[remaining_polygons[i]]); - next_unreachable_polygons.push_back(unreachable_polygons[remaining_polygons[i]]); - next_lepox_to_next.push_back(lepox_to_next[remaining_polygons[i]]); - } - - /* TODO: remove */ - polygons.clear(); - unreachable_polygons.clear(); - lepox_to_next.clear(); - + next_solvable_objects.push_back(solvable_objects[remaining_polygons[i]]); + } polygon_index_map.clear(); - - polygons = next_polygons; - unreachable_polygons = next_unreachable_polygons; - lepox_to_next = next_lepox_to_next; + solvable_objects = next_solvable_objects; std::vector next_polygon_index_map; std::map next_original_index_map; @@ -565,6 +549,8 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ std::vector > unreachable_polygons; std::vector lepox_to_next; + std::vector solvable_objects; + std::map original_index_map; #ifdef DEBUG @@ -718,10 +704,9 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ } } } - - Polygon scale_down_polygon; - scaleDown_PolygonForSequentialSolver(nozzle_polygon, scale_down_polygon); - polygons.push_back(scale_down_polygon); + SolvableObject solvable_object; + + scaleDown_PolygonForSequentialSolver(nozzle_polygon, solvable_object.polygon); std::vector convex_level_polygons; convex_level_polygons.push_back(nozzle_polygon); @@ -737,31 +722,31 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ case SEQ_PRINTER_TYPE_PRUSA_MK3S: { prepare_UnreachableZonePolygons(solver_configuration, - convex_level_polygons, - box_level_polygons, - SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_MK3S, - SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_MK3S, - scale_down_unreachable_polygons); + convex_level_polygons, + box_level_polygons, + SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_MK3S, + SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_MK3S, + solvable_object.unreachable_polygons); break; } case SEQ_PRINTER_TYPE_PRUSA_MK4: { prepare_UnreachableZonePolygons(solver_configuration, - convex_level_polygons, - box_level_polygons, - SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_MK4, - SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_MK4, - scale_down_unreachable_polygons); + convex_level_polygons, + box_level_polygons, + SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_MK4, + SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_MK4, + solvable_object.unreachable_polygons); break; } case SEQ_PRINTER_TYPE_PRUSA_XL: { prepare_UnreachableZonePolygons(solver_configuration, - convex_level_polygons, - box_level_polygons, - SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_XL, - SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_XL, - scale_down_unreachable_polygons); + convex_level_polygons, + box_level_polygons, + SEQ_UNREACHABLE_POLYGON_CONVEX_LEVELS_XL, + SEQ_UNREACHABLE_POLYGON_BOX_LEVELS_XL, + solvable_object.unreachable_polygons); break; } default: @@ -771,22 +756,24 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ } } - unreachable_polygons.push_back(scale_down_unreachable_polygons); - lepox_to_next.push_back(objects_to_print[i].glued_to_next); + solvable_object.id = objects_to_print[i].id; + solvable_object.lepox_to_next = objects_to_print[i].glued_to_next; + + solvable_objects.push_back(solvable_object); } - vector remaining_polygons; - vector polygon_index_map; - vector decided_polygons; + std::vector remaining_polygons; + std::vector polygon_index_map; + std::vector decided_polygons; for (unsigned int index = 0; index < polygons.size(); ++index) { polygon_index_map.push_back(index); } - vector poly_positions_X; - vector poly_positions_Y; - vector times_T; + std::vector poly_positions_X; + std::vector poly_positions_Y; + std::vector times_T; #ifdef DEBUG { @@ -816,9 +803,7 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ poly_positions_X, poly_positions_Y, times_T, - polygons, - unreachable_polygons, - lepox_to_next, + solvable_objects, polygon_index_map, decided_polygons, remaining_polygons, @@ -894,28 +879,15 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver_ printf("Intermediate CPU time: %.3f\n", (finish - start) / (double)CLOCKS_PER_SEC); } #endif - - std::vector next_polygons; - std::vector > next_unreachable_polygons; - std::vector next_lepox_to_next; + + std::vector next_solvable_objects; for (unsigned int i = 0; i < remaining_polygons.size(); ++i) { - next_polygons.push_back(polygons[remaining_polygons[i]]); - next_unreachable_polygons.push_back(unreachable_polygons[remaining_polygons[i]]); - next_lepox_to_next.push_back(lepox_to_next[remaining_polygons[i]]); - } - - /* TODO: remove */ - polygons.clear(); - unreachable_polygons.clear(); - lepox_to_next.clear(); - + next_solvable_objects.push_back(solvable_objects[i]); + } polygon_index_map.clear(); - - polygons = next_polygons; - unreachable_polygons = next_unreachable_polygons; - lepox_to_next = next_lepox_to_next; + solvable_objects = next_solvable_objects; std::vector next_polygon_index_map; std::map next_original_index_map; @@ -1007,11 +979,8 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration } #endif - std::vector polygons; - std::vector > unreachable_polygons; - + std::vector solvable_objects; std::map original_index_map; - std::vector lepox_to_next; #ifdef DEBUG { @@ -1020,7 +989,7 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration #endif for (unsigned int i = 0; i < objects_to_print.size(); ++i) - { + { Polygon nozzle_polygon; Polygon extruder_polygon; Polygon hose_polygon; @@ -1090,10 +1059,9 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration } ++ht; } - - Polygon scale_down_polygon; - scaleDown_PolygonForSequentialSolver(nozzle_polygon, scale_down_polygon); - polygons.push_back(scale_down_polygon); + SolvableObject solvable_object; + + scaleDown_PolygonForSequentialSolver(nozzle_polygon, solvable_object.polygon); std::vector convex_level_polygons; convex_level_polygons.push_back(nozzle_polygon); @@ -1110,17 +1078,19 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration box_level_polygons, convex_unreachable_zones, box_unreachable_zones, - scale_down_unreachable_polygons); - - unreachable_polygons.push_back(scale_down_unreachable_polygons); - lepox_to_next.push_back(objects_to_print[i].glued_to_next); + solvable_object.unreachable_polygons); + + solvable_object.id = objects_to_print[i].id; + solvable_object.lepox_to_next = objects_to_print[i].glued_to_next; + + solvable_objects.push_back(solvable_object); } std::vector remaining_polygons; std::vector polygon_index_map; std::vector decided_polygons; - for (unsigned int index = 0; index < polygons.size(); ++index) + for (unsigned int index = 0; index < solvable_objects.size(); ++index) { polygon_index_map.push_back(index); } @@ -1157,9 +1127,7 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration poly_positions_X, poly_positions_Y, times_T, - polygons, - unreachable_polygons, - lepox_to_next, + solvable_objects, polygon_index_map, decided_polygons, remaining_polygons, @@ -1236,33 +1204,20 @@ int schedule_ObjectsForSequentialPrint(const SolverConfiguration printf("Intermediate CPU time: %.3f\n", (finish - start) / (double)CLOCKS_PER_SEC); } #endif - - std::vector next_polygons; - std::vector > next_unreachable_polygons; - std::vector next_lepox_to_next; + std::vector next_solvable_objects; + for (unsigned int i = 0; i < remaining_polygons.size(); ++i) { - next_polygons.push_back(polygons[remaining_polygons[i]]); - next_unreachable_polygons.push_back(unreachable_polygons[remaining_polygons[i]]); - next_lepox_to_next.push_back(lepox_to_next[remaining_polygons[i]]); - } - - /* TODO: remove */ - polygons.clear(); - unreachable_polygons.clear(); - lepox_to_next.clear(); - + next_solvable_objects.push_back(solvable_objects[i]); + } polygon_index_map.clear(); - - polygons = next_polygons; - unreachable_polygons = next_unreachable_polygons; - lepox_to_next = next_lepox_to_next; + solvable_objects = next_solvable_objects; std::vector next_polygon_index_map; std::map next_original_index_map; - for (unsigned int index = 0; index < polygons.size(); ++index) + for (unsigned int index = 0; index < solvable_objects.size(); ++index) { next_polygon_index_map.push_back(index); next_original_index_map[index] = original_index_map[remaining_polygons[index]]; diff --git a/src/libseqarrange/src/seq_sequential.cpp b/src/libseqarrange/src/seq_sequential.cpp index 765a1e3ad4..557f6cbb54 100644 --- a/src/libseqarrange/src/seq_sequential.cpp +++ b/src/libseqarrange/src/seq_sequential.cpp @@ -343,15 +343,41 @@ void introduce_ConsequentialTemporalLepoxAgainstFixed(z3::solver const std::vector &SEQ_UNUSED(polygons), const std::vector &lepox_to_next) { - std::set fixed_(fixed.begin(), fixed.end()); - std::set undecided_(undecided.begin(), undecided.end()); - for (unsigned int i = 0; i < undecided.size(); ++i) { + if (i == 0) + { + if ((undecided[0] - 1) >= 0) + { + if (lepox_to_next[undecided[0] - 1]) + { + for (unsigned int j = 1; j < undecided.size(); ++j) + { + Solver.add(dec_vars_T[undecided[0]] + temporal_spread < dec_vars_T[undecided[j]]); + } + if (!fixed.empty()) + { + int prev_fix_i = fixed[fixed.size() - 1]; + Solver.add(Context.real_val(dec_values_T[prev_fix_i].numerator, dec_values_T[prev_fix_i].denominator) + temporal_spread < dec_vars_T[undecided[0]]); + } + } + } + } if (lepox_to_next[undecided[i]]) { - /* TODO: we know what to do */ - //Solver.add(dec_vars_T[previous_polygons[undecided[i]]] + temporal_spread < dec_vars_T[undecided[i]] && dec_vars_T[previous_polygons[undecided[i]]] + temporal_spread + temporal_spread / 2 > dec_vars_T[undecided[i]]); + printf("Lepox constraint present: %d\n", undecided[i]); + if (undecided.size() > i + 1) + { + int next_i = undecided[i + 1]; + Solver.add(dec_vars_T[undecided[i]] + temporal_spread < dec_vars_T[next_i] && dec_vars_T[undecided[i]] + temporal_spread + temporal_spread / 2 > dec_vars_T[next_i]); + } + else + { + for (unsigned int j = 0; j < undecided.size() - 1; ++j) + { + Solver.add(dec_vars_T[undecided[j]] + temporal_spread < dec_vars_T[undecided[i]]); + } + } } } @@ -8589,7 +8615,9 @@ bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver const string_map &dec_var_names_map, const std::vector &polygons, const std::vector > &unreachable_polygons, - const z3::expr_vector &presence_constraints) + const z3::expr_vector &presence_constraints, + const ProgressRange &progress_range, + std::function progress_callback) { z3::set_param("timeout", solver_configuration.optimization_timeout.c_str()); //z3::set_param("parallel.enable", "true"); @@ -8605,6 +8633,9 @@ bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver coord_t half_y_min = 0; coord_t half_y_max = box_half_y_max; + + int progress_total_estimation = MAX(1,std::log2(half_x_max - half_x_min)); + int progress = 0; while ((half_x_max - half_x_min) > 1 && (half_y_max - half_y_min) > 1) { @@ -8940,7 +8971,11 @@ bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver printf("Halves augmented: X:[%d,%d] Y:[%d,%d]\n", half_x_min, half_x_max, half_y_min, half_y_max); } #endif + + ++progress; + progress_callback(progress_range.progress_min + (progress_range.progress_max - progress_range.progress_min) * progress / progress_total_estimation); } + progress_callback(progress_range.progress_max); if (last_solvable_bounding_box_size > 0) { @@ -9987,8 +10022,8 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So const std::vector &undecided_polygons, std::vector &decided_polygons, std::vector &remaining_polygons, - int objects_done, - int total_objects, + int progress_objects_done, + int progress_total_objects, std::function progress_callback) { std::vector undecided; @@ -10067,6 +10102,26 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So decided_polygons, undecided, dec_var_names_map); + + introduce_ConsequentialTemporalOrderingAgainstFixed(z_solver, + z_context, + local_dec_vars_T, + local_values_T, + decided_polygons, + undecided, + solver_configuration.temporal_spread, + polygons); + + introduce_ConsequentialTemporalLepoxAgainstFixed(z_solver, + z_context, + local_dec_vars_T, + local_values_T, + decided_polygons, + undecided, + solver_configuration.temporal_spread, + polygons, + lepox_to_next); + #ifdef PROFILE { build_finish = clock(); @@ -10074,7 +10129,8 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So } #endif - vector missing; + std::vector missing; + std::vector remaining_local; while(object_group_size > 0) { @@ -10107,25 +10163,6 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So } #endif - introduce_ConsequentialTemporalOrderingAgainstFixed(z_solver, - z_context, - local_dec_vars_T, - local_values_T, - decided_polygons, - undecided, - solver_configuration.temporal_spread, - polygons); - - introduce_ConsequentialTemporalLepoxAgainstFixed(z_solver, - z_context, - local_dec_vars_T, - local_values_T, - decided_polygons, - undecided, - solver_configuration.temporal_spread, - polygons, - lepox_to_next); - #ifdef DEBUG { printf("%ld,%ld\n", local_values_X.size(), local_values_Y.size()); @@ -10141,7 +10178,7 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So } #endif - progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + objects_done)) / total_objects); + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); optimized = optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z_solver, z_context, @@ -10159,7 +10196,10 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So dec_var_names_map, polygons, unreachable_polygons, - presence_assumptions); + presence_assumptions, + ProgressRange((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects, + (SEQ_PROGRESS_RANGE * (decided_polygons.size() + (progress_objects_done + 1))) / progress_total_objects), + progress_callback); if (optimized) { @@ -10175,23 +10215,22 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So { dec_values_X[undecided[i]] = local_values_X[undecided[i]]; dec_values_Y[undecided[i]] = local_values_Y[undecided[i]]; - dec_values_T[undecided[i]] = local_values_T[undecided[i]]; + dec_values_T[undecided[i]] = local_values_T[undecided[i]]; decided_polygons.push_back(undecided[i]); } augment_TemporalSpread(solver_configuration, dec_values_T, decided_polygons); - - if (polygons.size() - curr_polygon > (unsigned int)solver_configuration.object_group_size) + + if (polygons.size() - curr_polygon > (unsigned int)object_group_size) { - curr_polygon += solver_configuration.object_group_size; + curr_polygon += object_group_size; } else { - curr_polygon += polygons.size() - curr_polygon; - progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + objects_done)) / total_objects); + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); return true; } - progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + objects_done)) / total_objects); + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); break; } else @@ -10201,16 +10240,18 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So printf("Remaining polygon: %d\n", curr_polygon + object_group_size - 1); } #endif - remaining_polygons.push_back(undecided_polygons[curr_polygon + object_group_size - 1]); + remaining_local.push_back(undecided_polygons[curr_polygon + object_group_size - 1]); } - missing.push_back(undecided.back()); undecided.pop_back(); --object_group_size; - progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + objects_done)) / total_objects); + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); } + std::reverse(remaining_local.begin(), remaining_local.end()); + remaining_polygons.insert(remaining_polygons.end(), remaining_local.begin(), remaining_local.end()); + #ifdef PROFILE { printf("Build: %.3f\n", build_cumul); @@ -10233,15 +10274,298 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So { remaining_polygons.push_back(undecided_polygons[curr_polygon]); } - return true; + } + return true; + } + } + assert(remaining_polygons.empty()); + } + assert(remaining_polygons.empty()); + + return true; +} + + +bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const SolverConfiguration &solver_configuration, + std::vector &dec_values_X, + std::vector &dec_values_Y, + std::vector &dec_values_T, + const std::vector &solvable_objects, + const std::vector &undecided_polygons, + std::vector &decided_polygons, + std::vector &remaining_polygons, + int progress_objects_done, + int progress_total_objects, + std::function progress_callback) +{ + std::vector undecided; + + decided_polygons.clear(); + remaining_polygons.clear(); + + dec_values_X.resize(solvable_objects.size()); + dec_values_Y.resize(solvable_objects.size()); + dec_values_T.resize(solvable_objects.size()); + + int box_half_x_max = solver_configuration.x_plate_bounding_box_size / 2; + int box_half_y_max = solver_configuration.y_plate_bounding_box_size / 2; + + std::vector polygons; + std::vector > unreachable_polygons; + std::vector lepox_to_next; + + for (const auto& solvable_object: solvable_objects) + { + polygons.push_back(solvable_object.polygon); + unreachable_polygons.push_back(solvable_object.unreachable_polygons); + lepox_to_next.push_back(solvable_object.lepox_to_next); + } + + for (unsigned int curr_polygon = 0; curr_polygon < solvable_objects.size(); /* nothing */) + { + bool optimized = false; + z3::set_param("timeout", solver_configuration.optimization_timeout.c_str()); + + z3::context z_context; + z3::solver z_solver(z_context); + + z3::expr_vector local_dec_vars_X(z_context); + z3::expr_vector local_dec_vars_Y(z_context); + z3::expr_vector local_dec_vars_T(z_context); + + vector local_values_X; + vector local_values_Y; + vector local_values_T; + + local_values_X.resize(solvable_objects.size()); + local_values_Y.resize(solvable_objects.size()); + local_values_T.resize(solvable_objects.size()); + + for (unsigned int i = 0; i < decided_polygons.size(); ++i) + { + #ifdef DEBUG + { + printf("Decided: %d %.3f, %.3f, %.3f\n", + decided_polygons[i], + dec_values_X[decided_polygons[i]].as_double(), + dec_values_Y[decided_polygons[i]].as_double(), + dec_values_T[decided_polygons[i]].as_double()); + } + #endif + + local_values_X[decided_polygons[i]] = dec_values_X[decided_polygons[i]]; + local_values_Y[decided_polygons[i]] = dec_values_Y[decided_polygons[i]]; + local_values_T[decided_polygons[i]] = dec_values_T[decided_polygons[i]]; + } + + string_map dec_var_names_map; + int object_group_size = MIN((unsigned int)solver_configuration.object_group_size, solvable_objects.size() - curr_polygon); + + undecided.clear(); + for (int i = 0; i < object_group_size; ++i) + { + undecided.push_back(curr_polygon + i); + } + + #ifdef PROFILE + { + build_start = clock(); + } + #endif + + build_ConsequentialWeakPolygonNonoverlapping(z_solver, + z_context, + polygons, + unreachable_polygons, + local_dec_vars_X, + local_dec_vars_Y, + local_dec_vars_T, + local_values_X, + local_values_Y, + local_values_T, + decided_polygons, + undecided, + dec_var_names_map); + + introduce_ConsequentialTemporalOrderingAgainstFixed(z_solver, + z_context, + local_dec_vars_T, + local_values_T, + decided_polygons, + undecided, + solver_configuration.temporal_spread, + polygons); + + introduce_ConsequentialTemporalLepoxAgainstFixed(z_solver, + z_context, + local_dec_vars_T, + local_values_T, + decided_polygons, + undecided, + solver_configuration.temporal_spread, + polygons, + lepox_to_next); + + #ifdef PROFILE + { + build_finish = clock(); + build_cumul += (build_finish - build_start) / (double)CLOCKS_PER_SEC; + } + #endif + + std::vector missing; + std::vector remaining_local; + + while(object_group_size > 0) + { + z3::expr_vector presence_assumptions(z_context); + assume_ConsequentialObjectPresence(z_context, local_dec_vars_T, undecided, missing, presence_assumptions); + + #ifdef DEBUG + { + printf("Undecided\n"); + for (unsigned int j = 0; j < undecided.size(); ++j) + { + printf(" %d\n", undecided[j]); + } + printf("Decided\n"); + for (unsigned int j = 0; j < decided_solvable_objects.size(); ++j) + { + printf(" %d\n", decided_polygons[j]); + } + printf("Locals\n"); + for (unsigned int j = 0; j < solvable_objects.size(); ++j) + { + printf("X: %ld,%ld Y: %ld,%ld T: %ld,%ld\n", + local_values_X[j].numerator, + local_values_X[j].denominator, + local_values_Y[j].numerator, + local_values_Y[j].denominator, + local_values_T[j].numerator, + local_values_T[j].denominator); + } + } + #endif + + #ifdef DEBUG + { + printf("%ld,%ld\n", local_values_X.size(), local_values_Y.size()); + + for (unsigned int i = 0; i < solvable_objects.size(); ++i) + { + printf("poly: %ld\n", polygons[i].points.size()); + for (unsigned int j = 0; j < polygons[i].points.size(); ++j) + { + printf(" %d,%d\n", polygons[i].points[j].x(), polygons[i].points[j].y()); + } + } + } + #endif + + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); + + optimized = optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z_solver, + z_context, + solver_configuration, + box_half_x_max, + box_half_y_max, + local_dec_vars_X, + local_dec_vars_Y, + local_dec_vars_T, + local_values_X, + local_values_Y, + local_values_T, + decided_polygons, + undecided, + dec_var_names_map, + polygons, + unreachable_polygons, + presence_assumptions, + ProgressRange((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects, + (SEQ_PROGRESS_RANGE * (decided_polygons.size() + (progress_objects_done + 1))) / progress_total_objects), + progress_callback); + + if (optimized) + { + /* + printf("Printing solver status:\n"); + cout << z_solver << "\n"; + + printf("Printing smt status:\n"); + cout << z_solver.to_smt2() << "\n"; + */ + + for (unsigned int i = 0; i < undecided.size(); ++i) + { + dec_values_X[undecided[i]] = local_values_X[undecided[i]]; + dec_values_Y[undecided[i]] = local_values_Y[undecided[i]]; + dec_values_T[undecided[i]] = local_values_T[undecided[i]]; + decided_polygons.push_back(undecided[i]); + } + augment_TemporalSpread(solver_configuration, dec_values_T, decided_polygons); + + if (solvable_objects.size() - curr_polygon > (unsigned int)object_group_size) + { + curr_polygon += object_group_size; } else { + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); return true; } + + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); + break; + } + else + { + #ifdef DEBUG + { + printf("Remaining polygon: %d\n", curr_polygon + object_group_size - 1); + } + #endif + remaining_local.push_back(undecided_polygons[curr_polygon + object_group_size - 1]); + } + missing.push_back(undecided.back()); + undecided.pop_back(); + + --object_group_size; + progress_callback((SEQ_PROGRESS_RANGE * (decided_polygons.size() + progress_objects_done)) / progress_total_objects); + } + + std::reverse(remaining_local.begin(), remaining_local.end()); + remaining_polygons.insert(remaining_polygons.end(), remaining_local.begin(), remaining_local.end()); + + #ifdef PROFILE + { + printf("Build: %.3f\n", build_cumul); + } + #endif + + if (!optimized) + { + if (curr_polygon <= 0) + { + return false; + } + else + { + if (solvable_objects.size() - curr_polygon > (unsigned int)solver_configuration.object_group_size) + { + curr_polygon += solver_configuration.object_group_size; + + for (; curr_polygon < solvable_objects.size(); ++curr_polygon) + { + remaining_polygons.push_back(undecided_polygons[curr_polygon]); + } + } + return true; } } + assert(remaining_polygons.empty()); } + assert(remaining_polygons.empty()); + return true; } diff --git a/src/libseqarrange/src/seq_sequential.hpp b/src/libseqarrange/src/seq_sequential.hpp index 9cd02f6e6b..b7dfae9c86 100644 --- a/src/libseqarrange/src/seq_sequential.hpp +++ b/src/libseqarrange/src/seq_sequential.hpp @@ -73,6 +73,18 @@ typedef std::basic_string string; typedef std::unordered_map string_map; +/*----------------------------------------------------------------*/ + +struct SolvableObject +{ + int id = 0; + + Slic3r::Polygon polygon; + std::vector unreachable_polygons; + bool lepox_to_next; +}; + + /*----------------------------------------------------------------*/ struct Rational @@ -179,6 +191,20 @@ struct Rational }; +/*----------------------------------------------------------------*/ + +struct ProgressRange +{ + ProgressRange(int min, int max) + : progress_min(min) + , progress_max(max) + { /* nothing */ } + + int progress_min; + int progress_max; +}; + + /*----------------------------------------------------------------*/ bool lines_intersect_(coord_t ax, coord_t ay, coord_t ux, coord_t uy, coord_t bx, coord_t by, coord_t vx, coord_t vy); @@ -1447,6 +1473,7 @@ bool optimize_SequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver const std::vector &polygons, const std::vector > &unreachable_polygons); + bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver &Solver, z3::context &Context, const SolverConfiguration &solver_configuration, @@ -1462,7 +1489,9 @@ bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver const std::vector &undecided, const string_map &dec_var_names_map, const std::vector &polygons, - const std::vector > &unreachable_polygons); + const std::vector > &unreachable_polygons, + const ProgressRange &progress_range, + std::function progress_callback); /*----------------------------------------------------------------*/ @@ -1565,10 +1594,22 @@ bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const So const std::vector &undecided_polygons, std::vector &decided_polygons, std::vector &remaining_polygons, - int objects_done, - int total_objects, + int progress_objects_done, + int progress_total_objects, std::function progress_callback = [](int progress){}); +bool optimize_SubglobalConsequentialPolygonNonoverlappingBinaryCentered(const SolverConfiguration &solver_configuration, + std::vector &dec_values_X, + std::vector &dec_values_Y, + std::vector &dec_values_T, + const std::vector &solvable_objects, + const std::vector &undecided_polygons, + std::vector &decided_polygons, + std::vector &remaining_polygons, + int progress_objects_done, + int progress_total_objects, + std::function progress_callback = [](int progress){}); + /*----------------------------------------------------------------*/ } // namespace Sequential diff --git a/src/libseqarrange/src/sequential_prusa.cpp b/src/libseqarrange/src/sequential_prusa.cpp index de752dfcb5..a1a73c40f0 100644 --- a/src/libseqarrange/src/sequential_prusa.cpp +++ b/src/libseqarrange/src/sequential_prusa.cpp @@ -751,11 +751,6 @@ int solve_SequentialPrint(const CommandParameters &command_parameters) next_unreachable_polygons.push_back(unreachable_polygons[remaining_polygons[i]]); next_lepox_to_next.push_back(lepox_to_next[remaining_polygons[i]]); } - - /* TODO: remove */ - polygons.clear(); - unreachable_polygons.clear(); - lepox_to_next.clear(); polygon_index_map.clear(); diff --git a/src/libseqarrange/test/seq_test_interface.cpp b/src/libseqarrange/test/seq_test_interface.cpp index 2753409769..ef10322ca3 100644 --- a/src/libseqarrange/test/seq_test_interface.cpp +++ b/src/libseqarrange/test/seq_test_interface.cpp @@ -401,6 +401,87 @@ int test_interface_5(void) } +int test_interface_6(void) +{ + clock_t start, finish; + + printf("Testing interface 6 ...\n"); + + start = clock(); + + SolverConfiguration solver_configuration; + solver_configuration.decimation_precision = SEQ_DECIMATION_PRECISION_LOW; + solver_configuration.object_group_size = 4; + + printf("Loading objects ...\n"); + std::vector objects_to_print = load_exported_data("arrange_data_export.txt"); + printf("Loading objects ... finished\n"); + + for (auto& object_to_print: objects_to_print) + { + object_to_print.glued_to_next = true; + } + + PrinterGeometry printer_geometry; + + printf("Loading printer geometry ...\n"); + int result = load_printer_geometry("../printers/printer_geometry.mk4.compatibility.txt", printer_geometry); + + if (result != 0) + { + printf("Cannot load printer geometry (code: %d).\n", result); + return result; + } + solver_configuration.setup(printer_geometry); + printf("Loading printer geometry ... finished\n"); + + std::vector scheduled_plates; + printf("Scheduling objects for sequential print ...\n"); + + scheduled_plates = schedule_ObjectsForSequentialPrint(solver_configuration, + printer_geometry, + objects_to_print, + [](int progress) { printf("Progress: %d\n", progress); }); + + printf("Object scheduling for sequential print SUCCESSFUL !\n"); + + printf("Number of plates: %ld\n", scheduled_plates.size()); + + for (unsigned int plate = 0; plate < scheduled_plates.size(); ++plate) + { + printf(" Number of objects on plate: %ld\n", scheduled_plates[plate].scheduled_objects.size()); + + for (const auto& scheduled_object: scheduled_plates[plate].scheduled_objects) + { + cout << " ID: " << scheduled_object.id << " X: " << scheduled_object.x << " Y: " << scheduled_object.y << endl; + } + } + + finish = clock(); + printf("Solving time: %.3f\n", (finish - start) / (double)CLOCKS_PER_SEC); + + start = clock(); + + printf("Checking sequential printability ...\n"); + + bool printable = check_ScheduledObjectsForSequentialPrintability(solver_configuration, + printer_geometry, + objects_to_print, + scheduled_plates); + + printf(" Scheduled/arranged objects are sequentially printable: %s\n", (printable ? "YES" : "NO")); + + printf("Checking sequential printability ... finished\n"); + + finish = clock(); + printf("Checking time: %.3f\n", (finish - start) / (double)CLOCKS_PER_SEC); + + printf("Testing interface 6 ... finished\n"); + + return 0; +} + + /*----------------------------------------------------------------*/ int main(int SEQ_UNUSED(argc), char **SEQ_UNUSED(argv)) @@ -409,7 +490,8 @@ int main(int SEQ_UNUSED(argc), char **SEQ_UNUSED(argv)) // test_interface_2(); // test_interface_3(); // test_interface_4(); - test_interface_5(); + test_interface_5(); +// test_interface_6(); return 0; } diff --git a/src/libseqarrange/test/seq_test_interface.hpp b/src/libseqarrange/test/seq_test_interface.hpp index de92e28f01..b9e1f54820 100644 --- a/src/libseqarrange/test/seq_test_interface.hpp +++ b/src/libseqarrange/test/seq_test_interface.hpp @@ -29,6 +29,8 @@ int test_interface_4(void); /* Interface test 5 */ int test_interface_5(void); +/* Interface test 6 */ +int test_interface_6(void); /*----------------------------------------------------------------*/ diff --git a/src/slic3r/GUI/ArrangeHelper.cpp b/src/slic3r/GUI/ArrangeHelper.cpp index 7d86da366a..9c1c71fdb7 100644 --- a/src/slic3r/GUI/ArrangeHelper.cpp +++ b/src/slic3r/GUI/ArrangeHelper.cpp @@ -59,7 +59,7 @@ static std::vector get_objects_to_print(const Model& std::vector objects; for (const ModelObject* mo : model.objects) { const ModelInstance* mi = mo->instances.front(); - objects.emplace_back(Sequential::ObjectToPrint{int(mo->id().id), scaled(mo->instance_bounding_box(0).size().z()), {}}); + objects.emplace_back(Sequential::ObjectToPrint{int(mo->id().id), false, scaled(mo->instance_bounding_box(0).size().z()), {}}); for (double height : heights) { auto tr = Transform3d::Identity(); Vec3d offset = mi->get_offset();