mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
FIX: rewrite per-object printing order logic
1. Previous logic can't guarantee left-to-right printing order, so toolhead may crash on the right side. In the new algorithm printing order is guaranteed. 2. Clearance radius should be the max of 3 directions (left, bottom, up), not including right, otherwise collision may happen on bottom or up directions. 3. Add is_extrusion_cali_object property to handle extrusion brim overlap better. Change-Id: I44868b9925d983f5cca0c31d35dfa28d895fadbf
This commit is contained in:
parent
59dfcb98fc
commit
5544e9602c
9 changed files with 97 additions and 24 deletions
|
@ -80,6 +80,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"extruder_clearance_height_to_rod",
|
||||
"extruder_clearance_height_to_lid",
|
||||
"extruder_clearance_radius",
|
||||
"extruder_clearance_max_radius",
|
||||
"extruder_colour",
|
||||
"extruder_offset",
|
||||
"filament_flow_ratio",
|
||||
|
@ -389,6 +390,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
|||
const PrintInstance *print_instance;
|
||||
BoundingBox bounding_box;
|
||||
Polygon hull_polygon;
|
||||
int index;
|
||||
double arrange_score;
|
||||
};
|
||||
std::vector<struct print_instance_info> print_instance_with_bounding_box;
|
||||
{
|
||||
|
@ -480,22 +483,71 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
|||
}
|
||||
}
|
||||
|
||||
//sort the print instance
|
||||
// calc sort order
|
||||
auto bed_points = get_bed_shape(print_config);
|
||||
float bed_width = bed_points[1].x() - bed_points[0].x();
|
||||
// 如果扩大以后的多边形的距离小于这个值,就需要严格保证从左到右的打印顺序,否则会撞工具头右侧
|
||||
float unsafe_dist = scale_(print_config.extruder_clearance_max_radius.value - print_config.extruder_clearance_radius.value);
|
||||
std::vector<Vec2i> left_right_pair; // pairs in this vector must strictly obey the left-right order
|
||||
for (size_t i = 0; i < print_instance_with_bounding_box.size();i++) {
|
||||
auto &inst = print_instance_with_bounding_box[i];
|
||||
inst.index = i;
|
||||
Point pt = inst.bounding_box.center();
|
||||
inst.arrange_score = pt.x() / 2 + pt.y(); // we prefer print row-by-row, so cost on x-direction is smaller
|
||||
}
|
||||
for (size_t i = 0; i < print_instance_with_bounding_box.size(); i++) {
|
||||
auto &inst = print_instance_with_bounding_box[i];
|
||||
for (size_t j = 0; j < print_instance_with_bounding_box.size(); j++) {
|
||||
if (j != i) {
|
||||
auto &l = print_instance_with_bounding_box[i];
|
||||
auto &r = print_instance_with_bounding_box[j];
|
||||
auto ly1 = l.bounding_box.min.y();
|
||||
auto ly2 = l.bounding_box.max.y();
|
||||
auto ry1 = r.bounding_box.min.y();
|
||||
auto ry2 = r.bounding_box.max.y();
|
||||
auto lx1 = l.bounding_box.min.x();
|
||||
auto rx1 = r.bounding_box.min.x();
|
||||
auto lx2 = l.bounding_box.max.x();
|
||||
auto rx2 = r.bounding_box.max.x();
|
||||
auto inter_min = std::max(ly1, ry1);
|
||||
auto inter_max = std::min(ly2, ry2);
|
||||
auto inter_y = inter_max - inter_min;
|
||||
inter_min = std::max(lx1, rx1);
|
||||
inter_max = std::min(lx2, rx2);
|
||||
auto inter_x = inter_max - inter_min;
|
||||
|
||||
// 如果y方向有重合,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。
|
||||
if (inter_y > 0) {
|
||||
if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) {
|
||||
std::string dir = "left";
|
||||
if (lx1 > rx1) {
|
||||
left_right_pair.emplace_back(j, i);
|
||||
print_instance_with_bounding_box[i].arrange_score = std::max(inst.arrange_score, r.arrange_score + bed_width);
|
||||
} else {
|
||||
left_right_pair.emplace_back(i, j);
|
||||
print_instance_with_bounding_box[j].arrange_score = std::max(r.arrange_score, l.arrange_score + bed_width);
|
||||
dir = "right";
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "print_instance " << inst.print_instance->model_instance->get_object()->name
|
||||
<< ", right=" << r.print_instance->model_instance->get_object()->name << ", l.score: " << l.arrange_score
|
||||
<< ", r.score: " << r.arrange_score << ", dist:" << std::max(rx1 - lx2, lx1 - rx2) << ", dir: " << dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "bed width: " << bed_width << ", unsafe_dist:" << unsafe_dist;
|
||||
for (auto& inst:print_instance_with_bounding_box) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "print_instance " << inst.print_instance->model_instance->get_object()->name
|
||||
<< ", score: " << inst.arrange_score;
|
||||
}
|
||||
// sort the print instance
|
||||
std::sort(print_instance_with_bounding_box.begin(), print_instance_with_bounding_box.end(),
|
||||
[](auto &l, auto &r) {
|
||||
auto ly1 = l.bounding_box.min.y();
|
||||
auto ly2 = l.bounding_box.max.y();
|
||||
auto ry1 = r.bounding_box.min.y();
|
||||
auto ry2 = r.bounding_box.max.y();
|
||||
auto inter_min = std::max(ly1, ry1);
|
||||
auto inter_max = std::min(ly2, ry2);
|
||||
auto lx = l.bounding_box.min.x();
|
||||
auto rx = r.bounding_box.min.x();
|
||||
if (inter_max - inter_min > 0)
|
||||
return (lx < rx) || ((lx == rx) && (ly1 < ry1));
|
||||
else
|
||||
return (ly1 < ry1);
|
||||
});
|
||||
[&left_right_pair](print_instance_info& l, print_instance_info& r) {
|
||||
if (std::find(left_right_pair.begin(),left_right_pair.end(), Vec2i(l.index, r.index)) != left_right_pair.end())
|
||||
return true;
|
||||
else
|
||||
return l.arrange_score < r.arrange_score;});
|
||||
|
||||
// sequential_print_vertical_clearance_valid
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue