mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-13 07:23:03 +00:00
Fix: collision warnings (#12122)
* Fix: Enable instance collision detection in GCode and Print clearance Squashed commit containing: - Fix gcode path conflict detection in ConflictChecker.cpp by iterating all instances. - Improve clearance validation in Print.cpp by calculating convex hulls per instance (fixes scaling/mirroring issues). - Added // Orca: comments to mark changes. * Fix Wipe Tower G-code conflict detection for WipeTower2 * Fix: Improve object/instance selection for collision and validation warnings - Updated validation logic in Print.cpp to report specific ModelInstance instead of ModelObject for collision/clearance warnings. - Updated NotificationManager and Plater to handle ModelInstance selection in 'Jump to' links. - Added fallback to object selection if specific instance cannot be selected. - Included fixes for G-code conflict detection (ConflictChecker, GLCanvas3D) to also report instances. - Improved GUI_ObjectList to update canvas selection when items are selected via API. * Fix: Prevent crash when loading .3mf projects Moved update_selections_on_canvas() out of ObjectList::select_items() to avoid premature UI updates during loading. Canvas updates are now explicitly called in NotificationManager and Plater callbacks where needed. * Fix: Address code review comments - Fix memory allocation for extrusion layers deep copy - Remove unused variable in GLCanvas3D - Fix string formatting crash risk in NotificationManager - Remove dead code in Plater --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
@@ -220,7 +220,13 @@ ConflictComputeOpt ConflictChecker::find_inter_of_lines(const LineWithIDs &lines
|
||||
ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectPtrs objs,
|
||||
std::optional<const FakeWipeTower *> wtdptr) // find the first intersection point of lines in different objects
|
||||
{
|
||||
if (objs.size() <= 1 && !wtdptr) { return {}; }
|
||||
if (objs.empty() && !wtdptr) { return {}; }
|
||||
|
||||
// Orca: check if we have enough items to potentially conflict (instances count)
|
||||
size_t total_instances = 0;
|
||||
for (auto obj : objs) total_instances += obj->instances().size();
|
||||
if (total_instances <= 1 && !wtdptr) return {};
|
||||
|
||||
LinesBucketQueue conflictQueue;
|
||||
|
||||
if (wtdptr.has_value()) { // wipe tower at 0 by default
|
||||
@@ -238,8 +244,19 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP
|
||||
}
|
||||
for (PrintObject *obj : objs) {
|
||||
auto layers = getAllLayersExtrusionPathsFromObject(obj);
|
||||
conflictQueue.emplace_back_bucket(std::move(layers.perimeters), obj, obj->instances().front().shift);
|
||||
conflictQueue.emplace_back_bucket(std::move(layers.support), obj, obj->instances().front().shift);
|
||||
// Orca: check for collisions between all instances
|
||||
const auto& instances = obj->instances();
|
||||
for (size_t inst_idx = 0; inst_idx < instances.size(); ++inst_idx) {
|
||||
const PrintInstance& inst = instances[inst_idx];
|
||||
const bool is_last_instance = inst_idx + 1 == instances.size();
|
||||
if (is_last_instance) {
|
||||
conflictQueue.emplace_back_bucket(std::move(layers.perimeters), &inst, inst.shift);
|
||||
conflictQueue.emplace_back_bucket(std::move(layers.support), &inst, inst.shift);
|
||||
} else {
|
||||
conflictQueue.emplace_back_bucket(ExtrusionLayers(layers.perimeters), &inst, inst.shift);
|
||||
conflictQueue.emplace_back_bucket(ExtrusionLayers(layers.support), &inst, inst.shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LineWithIDs> layersLines;
|
||||
@@ -272,13 +289,18 @@ ConflictResultOpt ConflictChecker::find_inter_of_lines_in_diff_objs(PrintObjectP
|
||||
const FakeWipeTower *wtdp = wtdptr.value();
|
||||
if (ptr1 == wtdp || ptr2 == wtdp) {
|
||||
if (ptr2 == wtdp) { std::swap(ptr1, ptr2); }
|
||||
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(ptr2);
|
||||
return std::make_optional<ConflictResult>("WipeTower", obj2->model_object()->name, conflictPrintZ, nullptr, ptr2);
|
||||
// ptr1 is now wipe tower, ptr2 is PrintInstance*
|
||||
const PrintInstance *inst2 = reinterpret_cast<const PrintInstance *>(ptr2);
|
||||
const PrintObject *obj2 = inst2->print_object;
|
||||
return std::make_optional<ConflictResult>("WipeTower", obj2->model_object()->name, conflictPrintZ, nullptr, inst2);
|
||||
}
|
||||
}
|
||||
const PrintObject *obj1 = reinterpret_cast<const PrintObject *>(ptr1);
|
||||
const PrintObject *obj2 = reinterpret_cast<const PrintObject *>(ptr2);
|
||||
return std::make_optional<ConflictResult>(obj1->model_object()->name, obj2->model_object()->name, conflictPrintZ, ptr1, ptr2);
|
||||
|
||||
const PrintInstance *inst1 = reinterpret_cast<const PrintInstance *>(ptr1);
|
||||
const PrintInstance *inst2 = reinterpret_cast<const PrintInstance *>(ptr2);
|
||||
const PrintObject *obj1 = inst1->print_object;
|
||||
const PrintObject *obj2 = inst2->print_object;
|
||||
return std::make_optional<ConflictResult>(obj1->model_object()->name, obj2->model_object()->name, conflictPrintZ, inst1, inst2);
|
||||
} else
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user