mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-09-28 17:13:12 +08:00
FIX: potential collsion in by object seq
1. update the expand length 2. enhance rod collision detect jira:STUDIO-12199 Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: I1350ef5612b833405928e22c542a7a6f0c671105
This commit is contained in:
parent
37013329a6
commit
7a197af3e0
@ -4113,16 +4113,8 @@ GCode::LayerResult GCode::process_layer(
|
|||||||
ctx.curr_layer = this->layer();
|
ctx.curr_layer = this->layer();
|
||||||
ctx.curr_extruder_id = m_writer.filament()->extruder_id();
|
ctx.curr_extruder_id = m_writer.filament()->extruder_id();
|
||||||
ctx.picture_extruder_id = most_used_extruder;
|
ctx.picture_extruder_id = most_used_extruder;
|
||||||
if (m_config.nozzle_diameter.size() > 1) {
|
|
||||||
ctx.extruder_height_gap = std::abs(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[1] ? 0 : 1;
|
|
||||||
}
|
|
||||||
ctx.height_to_rod = m_config.extruder_clearance_height_to_rod;
|
|
||||||
|
|
||||||
ctx.print_sequence = m_config.print_sequence;
|
|
||||||
if (m_config.print_sequence == PrintSequence::ByObject)
|
if (m_config.print_sequence == PrintSequence::ByObject)
|
||||||
ctx.printed_objects = printed_objects;
|
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);
|
auto timelapse_pos=m_timelapse_pos_picker.pick_pos(ctx);
|
||||||
|
|
||||||
|
@ -9,6 +9,16 @@ namespace Slic3r {
|
|||||||
reset();
|
reset();
|
||||||
m_plate_offset = plate_offset;
|
m_plate_offset = plate_offset;
|
||||||
print = print_;
|
print = print_;
|
||||||
|
|
||||||
|
m_nozzle_height_to_rod = print_->config().extruder_clearance_height_to_rod;
|
||||||
|
m_nozzle_clearance_radius = print_->config().extruder_clearance_max_radius;
|
||||||
|
if (print_->config().nozzle_diameter.size() > 1) {
|
||||||
|
m_extruder_height_gap = std::abs(print_->config().extruder_printable_height.values[0] - print_->config().extruder_printable_height.values[1]);
|
||||||
|
m_liftable_extruder_id = print_->config().extruder_printable_height.values[0] < print_->config().extruder_printable_height.values[1] ? 0 : 1;
|
||||||
|
}
|
||||||
|
m_print_seq = print_->config().print_sequence.value;
|
||||||
|
m_based_on_all_layer = print_->config().timelapse_type == TimelapseType::tlSmooth;
|
||||||
|
|
||||||
construct_printable_area_by_printer();
|
construct_printable_area_by_printer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,6 +29,13 @@ namespace Slic3r {
|
|||||||
m_extruder_printable_area.clear();
|
m_extruder_printable_area.clear();
|
||||||
m_all_layer_pos = std::nullopt;
|
m_all_layer_pos = std::nullopt;
|
||||||
bbox_cache.clear();
|
bbox_cache.clear();
|
||||||
|
|
||||||
|
m_print_seq = PrintSequence::ByObject;
|
||||||
|
m_nozzle_height_to_rod = 0;
|
||||||
|
m_nozzle_clearance_radius = 0;
|
||||||
|
m_liftable_extruder_id = std::nullopt;
|
||||||
|
m_extruder_height_gap = std::nullopt;
|
||||||
|
m_based_on_all_layer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,7 +95,7 @@ namespace Slic3r {
|
|||||||
{transform_wt_pt({scale_(wt_box.max.x()),scale_(wt_box.max.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())})}
|
{transform_wt_pt({scale_(wt_box.min.x()),scale_(wt_box.max.y())})}
|
||||||
};
|
};
|
||||||
wipe_tower_area = expand_object_projection(wipe_tower_area);
|
wipe_tower_area = expand_object_projection(wipe_tower_area, m_print_seq == PrintSequence::ByObject);
|
||||||
|
|
||||||
for (size_t idx = 0; idx < extruder_count; ++idx) {
|
for (size_t idx = 0; idx < extruder_count; ++idx) {
|
||||||
ExPolygons printable_area = diff_ex(diff(m_bed_polygon, bed_exclude_area), { wipe_tower_area });
|
ExPolygons printable_area = diff_ex(diff(m_bed_polygon, bed_exclude_area), { wipe_tower_area });
|
||||||
@ -98,9 +115,10 @@ namespace Slic3r {
|
|||||||
* @param layer The layer for which slices are being collected.
|
* @param layer The layer for which slices are being collected.
|
||||||
* @param height_range The height range to consider for collecting slices.
|
* @param height_range The height range to consider for collecting slices.
|
||||||
* @param object_list List of print objects to process.
|
* @param object_list List of print objects to process.
|
||||||
|
* @param by_object Decides the expand length of polygon
|
||||||
* @return ExPolygons representing the collected slice data.
|
* @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)
|
ExPolygons TimelapsePosPicker::collect_object_slices_data(const Layer* layer, float height_range, const std::vector<const PrintObject*>& object_list, bool by_object)
|
||||||
{
|
{
|
||||||
auto range_intersect = [](int left1, int right1, int left2, int right2) {
|
auto range_intersect = [](int left1, int right1, int left2, int right2) {
|
||||||
if (left1 <= left2 && left2 <= right1)
|
if (left1 <= left2 && left2 <= right1)
|
||||||
@ -119,7 +137,7 @@ namespace Slic3r {
|
|||||||
for (auto& obj : object_list) {
|
for (auto& obj : object_list) {
|
||||||
for (auto& instance : obj->instances()) {
|
for (auto& instance : obj->instances()) {
|
||||||
auto instance_bbox = get_real_instance_bbox(instance);
|
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)){
|
if(range_intersect(instance_bbox.min.z(), instance_bbox.max.z(), z_low, z_high)){
|
||||||
ExPolygon expoly;
|
ExPolygon expoly;
|
||||||
expoly.contour = {
|
expoly.contour = {
|
||||||
{scale_(instance_bbox.min.x()), scale_(instance_bbox.min.y())},
|
{scale_(instance_bbox.min.x()), scale_(instance_bbox.min.y())},
|
||||||
@ -127,7 +145,7 @@ namespace Slic3r {
|
|||||||
{scale_(instance_bbox.max.x()), scale_(instance_bbox.max.y())},
|
{scale_(instance_bbox.max.x()), scale_(instance_bbox.max.y())},
|
||||||
{scale_(instance_bbox.min.x()), scale_(instance_bbox.max.y())}
|
{scale_(instance_bbox.min.x()), scale_(instance_bbox.max.y())}
|
||||||
};
|
};
|
||||||
expoly.contour = expand_object_projection(expoly.contour);
|
expoly.contour = expand_object_projection(expoly.contour, by_object);
|
||||||
ret.emplace_back(std::move(expoly));
|
ret.emplace_back(std::move(expoly));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +167,7 @@ namespace Slic3r {
|
|||||||
// scaled data
|
// scaled data
|
||||||
Polygons TimelapsePosPicker::collect_limit_areas_for_rod(const std::vector<const PrintObject*>& object_list, const PosPickCtx& ctx)
|
Polygons TimelapsePosPicker::collect_limit_areas_for_rod(const std::vector<const PrintObject*>& object_list, const PosPickCtx& ctx)
|
||||||
{
|
{
|
||||||
double rod_limit_height = ctx.height_to_rod + ctx.curr_layer->print_z;
|
double rod_limit_height = m_nozzle_height_to_rod + ctx.curr_layer->print_z;
|
||||||
std::vector<const PrintObject*> rod_collision_candidates;
|
std::vector<const PrintObject*> rod_collision_candidates;
|
||||||
for(auto& obj : object_list){
|
for(auto& obj : object_list){
|
||||||
if(ctx.printed_objects && obj == ctx.printed_objects->back())
|
if(ctx.printed_objects && obj == ctx.printed_objects->back())
|
||||||
@ -159,17 +177,28 @@ namespace Slic3r {
|
|||||||
rod_collision_candidates.push_back(obj);
|
rod_collision_candidates.push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(rod_collision_candidates.begin(), rod_collision_candidates.end(), [&](const PrintObject* lhs, const PrintObject* rhs) {
|
if (rod_collision_candidates.empty())
|
||||||
auto lbbox =get_real_instance_bbox(lhs->instances().front());
|
return {};
|
||||||
auto rbbox =get_real_instance_bbox(rhs->instances().front());
|
|
||||||
if(lbbox.min.y() == rbbox.min.y())
|
|
||||||
|
std::vector<BoundingBoxf3> collision_obj_bboxs;
|
||||||
|
for (auto obj : rod_collision_candidates) {
|
||||||
|
collision_obj_bboxs.emplace_back(
|
||||||
|
expand_object_bbox(
|
||||||
|
get_real_instance_bbox(obj->instances().front()),
|
||||||
|
m_print_seq == PrintSequence::ByObject
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(collision_obj_bboxs.begin(), collision_obj_bboxs.end(), [&](const auto& lbbox, const auto& rbbox) {
|
||||||
|
if (lbbox.min.y() == rbbox.min.y())
|
||||||
return lbbox.max.y() < rbbox.max.y();
|
return lbbox.max.y() < rbbox.max.y();
|
||||||
return lbbox.min.y() < rbbox.min.y();
|
return lbbox.min.y() < rbbox.min.y();
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<std::pair<int,int>> object_y_ranges = {{0,0}};
|
std::vector<std::pair<int,int>> object_y_ranges = {{0,0}};
|
||||||
for(auto& candidate : rod_collision_candidates){
|
for(auto& bbox : collision_obj_bboxs){
|
||||||
auto bbox = get_real_instance_bbox(candidate->instances().front());
|
|
||||||
if( object_y_ranges.back().second >= bbox.min.y())
|
if( object_y_ranges.back().second >= bbox.min.y())
|
||||||
object_y_ranges.back().second = bbox.max.y();
|
object_y_ranges.back().second = bbox.max.y();
|
||||||
else
|
else
|
||||||
@ -217,17 +246,41 @@ namespace Slic3r {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// expand the object expolygon by safe distance
|
// expand the object expolygon by safe distance, scaled data
|
||||||
Polygon TimelapsePosPicker::expand_object_projection(const Polygon& poly)
|
Polygon TimelapsePosPicker::expand_object_projection(const Polygon& poly, bool by_object)
|
||||||
{
|
{
|
||||||
|
float radius = 0;
|
||||||
|
if (by_object)
|
||||||
|
radius = scale_(print->config().extruder_clearance_max_radius.value);
|
||||||
|
else
|
||||||
|
radius = scale_(print->config().extruder_clearance_max_radius.value / 2);
|
||||||
|
|
||||||
// the input poly is bounding box, so we get the first offseted polygon is ok
|
// the input poly is bounding box, so we get the first offseted polygon is ok
|
||||||
float radius = scale_(print->config().extruder_clearance_max_radius.value / 2);
|
|
||||||
auto ret = offset(poly, radius);
|
auto ret = offset(poly, radius);
|
||||||
if (ret.empty())
|
if (ret.empty())
|
||||||
return {};
|
return {};
|
||||||
return ret[0];
|
return ret[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unscaled data
|
||||||
|
BoundingBoxf3 TimelapsePosPicker::expand_object_bbox(const BoundingBoxf3& bbox, bool by_object)
|
||||||
|
{
|
||||||
|
float radius = 0;
|
||||||
|
if (by_object)
|
||||||
|
radius = print->config().extruder_clearance_max_radius.value;
|
||||||
|
else
|
||||||
|
radius = print->config().extruder_clearance_max_radius.value / 2;
|
||||||
|
|
||||||
|
BoundingBoxf3 ret = bbox;
|
||||||
|
ret.min.x() -= radius;
|
||||||
|
ret.min.y() -= radius;
|
||||||
|
ret.max.x() += radius;
|
||||||
|
ret.max.y() += radius;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double TimelapsePosPicker::get_raft_height(const PrintObject* obj)
|
double TimelapsePosPicker::get_raft_height(const PrintObject* obj)
|
||||||
{
|
{
|
||||||
if (!obj || !obj->has_raft())
|
if (!obj || !obj->has_raft())
|
||||||
@ -276,7 +329,7 @@ namespace Slic3r {
|
|||||||
if (!obj)
|
if (!obj)
|
||||||
return {};
|
return {};
|
||||||
auto bbox = get_real_instance_bbox(obj->instances().front());
|
auto bbox = get_real_instance_bbox(obj->instances().front());
|
||||||
float radius = print->config().extruder_clearance_max_radius.value / 2;
|
float radius = m_nozzle_clearance_radius / 2;
|
||||||
|
|
||||||
auto offset_bbox = bbox.inflated(sqrt(2) * radius);
|
auto offset_bbox = bbox.inflated(sqrt(2) * radius);
|
||||||
// Constrain the coordinates to the first quadrant.
|
// Constrain the coordinates to the first quadrant.
|
||||||
@ -346,7 +399,7 @@ namespace Slic3r {
|
|||||||
Point TimelapsePosPicker::pick_pos(const PosPickCtx& ctx)
|
Point TimelapsePosPicker::pick_pos(const PosPickCtx& ctx)
|
||||||
{
|
{
|
||||||
Point res;
|
Point res;
|
||||||
if (ctx.based_on_all_layer)
|
if (m_based_on_all_layer)
|
||||||
res = pick_pos_for_all_layer(ctx);
|
res = pick_pos_for_all_layer(ctx);
|
||||||
else
|
else
|
||||||
res = pick_pos_for_curr_layer(ctx);
|
res = pick_pos_for_curr_layer(ctx);
|
||||||
@ -391,16 +444,17 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
float height_gap = 0;
|
float height_gap = 0;
|
||||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
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())
|
if(m_liftable_extruder_id.has_value() && ctx.picture_extruder_id != m_liftable_extruder_id && m_extruder_height_gap.has_value())
|
||||||
height_gap = -*ctx.extruder_height_gap;
|
height_gap = -*m_extruder_height_gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool by_object = m_print_seq == PrintSequence::ByObject;
|
||||||
std::vector<const PrintObject*> object_list = get_object_list(ctx.printed_objects);
|
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);
|
ExPolygons layer_slices = collect_object_slices_data(ctx.curr_layer, height_gap, object_list, by_object);
|
||||||
Polygons camera_limit_areas = collect_limit_areas_for_camera(object_list);
|
Polygons camera_limit_areas = collect_limit_areas_for_camera(object_list);
|
||||||
Polygons rod_limit_areas;
|
Polygons rod_limit_areas;
|
||||||
if (ctx.print_sequence == PrintSequence::ByObject) {
|
if (m_print_seq == PrintSequence::ByObject) {
|
||||||
rod_limit_areas = collect_limit_areas_for_rod(object_list,ctx);
|
rod_limit_areas = collect_limit_areas_for_rod(object_list,ctx);
|
||||||
}
|
}
|
||||||
ExPolygons unplacable_area = union_ex(union_ex(layer_slices, camera_limit_areas),rod_limit_areas);
|
ExPolygons unplacable_area = union_ex(union_ex(layer_slices, camera_limit_areas),rod_limit_areas);
|
||||||
@ -446,14 +500,16 @@ namespace Slic3r {
|
|||||||
{
|
{
|
||||||
float height_gap = 0;
|
float height_gap = 0;
|
||||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
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())
|
if (m_liftable_extruder_id.has_value() && ctx.picture_extruder_id != m_liftable_extruder_id && m_extruder_height_gap.has_value())
|
||||||
height_gap = *ctx.extruder_height_gap;
|
height_gap = *m_extruder_height_gap;
|
||||||
}
|
}
|
||||||
if (ctx.curr_layer->print_z < height_gap)
|
if (ctx.curr_layer->print_z < height_gap)
|
||||||
return DefaultTimelapsePos;
|
return DefaultTimelapsePos;
|
||||||
if (m_all_layer_pos)
|
if (m_all_layer_pos)
|
||||||
return *m_all_layer_pos;
|
return *m_all_layer_pos;
|
||||||
|
|
||||||
|
bool by_object = m_print_seq == PrintSequence::ByObject;
|
||||||
|
|
||||||
Polygons object_projections;
|
Polygons object_projections;
|
||||||
|
|
||||||
auto object_list = get_object_list(std::nullopt);
|
auto object_list = get_object_list(std::nullopt);
|
||||||
@ -461,7 +517,7 @@ namespace Slic3r {
|
|||||||
for (auto& obj : object_list) {
|
for (auto& obj : object_list) {
|
||||||
for (auto& instance : obj->instances()) {
|
for (auto& instance : obj->instances()) {
|
||||||
const auto& bbox = get_real_instance_bbox(instance);
|
const auto& bbox = get_real_instance_bbox(instance);
|
||||||
if (ctx.print_sequence == PrintSequence::ByObject && bbox.max.z() >= ctx.height_to_rod) {
|
if (m_print_seq == PrintSequence::ByObject && bbox.max.z() >= m_nozzle_height_to_rod) {
|
||||||
m_all_layer_pos = DefaultTimelapsePos;
|
m_all_layer_pos = DefaultTimelapsePos;
|
||||||
return *m_all_layer_pos;
|
return *m_all_layer_pos;
|
||||||
}
|
}
|
||||||
@ -472,7 +528,7 @@ namespace Slic3r {
|
|||||||
{ max_p.x(),max_p.y() },
|
{ max_p.x(),max_p.y() },
|
||||||
{ min_p.x(),max_p.y() }
|
{ min_p.x(),max_p.y() }
|
||||||
};
|
};
|
||||||
object_projections.emplace_back(expand_object_projection(obj_proj));
|
object_projections.emplace_back(expand_object_projection(obj_proj,by_object));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,12 +21,7 @@ namespace Slic3r {
|
|||||||
const Layer* curr_layer;
|
const Layer* curr_layer;
|
||||||
int picture_extruder_id; // the extruder id to take picture
|
int picture_extruder_id; // the extruder id to take picture
|
||||||
int curr_extruder_id;
|
int curr_extruder_id;
|
||||||
int height_to_rod;
|
|
||||||
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::vector<const PrintObject*>> printed_objects; // printed objects, only have value in by object mode
|
std::optional<std::vector<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
|
// data are stored without plate offset
|
||||||
@ -45,12 +40,13 @@ namespace Slic3r {
|
|||||||
Point pick_pos_for_curr_layer(const PosPickCtx& ctx);
|
Point pick_pos_for_curr_layer(const PosPickCtx& ctx);
|
||||||
Point pick_pos_for_all_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);
|
ExPolygons collect_object_slices_data(const Layer* curr_layer, float height_range, const std::vector<const PrintObject*>& object_list,bool by_object);
|
||||||
Polygons collect_limit_areas_for_camera(const std::vector<const PrintObject*>& object_list);
|
Polygons collect_limit_areas_for_camera(const std::vector<const PrintObject*>& object_list);
|
||||||
|
|
||||||
Polygons collect_limit_areas_for_rod(const std::vector<const PrintObject*>& object_list, const PosPickCtx& ctx);
|
Polygons collect_limit_areas_for_rod(const std::vector<const PrintObject*>& object_list, const PosPickCtx& ctx);
|
||||||
|
|
||||||
Polygon expand_object_projection(const Polygon& poly);
|
Polygon expand_object_projection(const Polygon& poly, bool by_object);
|
||||||
|
BoundingBoxf3 expand_object_bbox(const BoundingBoxf3& bbox, bool by_object);
|
||||||
|
|
||||||
Point pick_nearest_object_center(const Point& curr_pos, const std::vector<const PrintObject*>& object_list);
|
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);
|
Point get_objects_center(const std::vector<const PrintObject*>& object_list);
|
||||||
@ -69,6 +65,13 @@ namespace Slic3r {
|
|||||||
int m_plate_height; // unscaled data
|
int m_plate_height; // unscaled data
|
||||||
int m_plate_width; // unscaled data
|
int m_plate_width; // unscaled data
|
||||||
|
|
||||||
|
PrintSequence m_print_seq;
|
||||||
|
bool m_based_on_all_layer;
|
||||||
|
int m_nozzle_height_to_rod;
|
||||||
|
int m_nozzle_clearance_radius;
|
||||||
|
std::optional<int> m_liftable_extruder_id;
|
||||||
|
std::optional<int> m_extruder_height_gap;
|
||||||
|
|
||||||
std::unordered_map<const PrintInstance*, BoundingBoxf3> bbox_cache;
|
std::unordered_map<const PrintInstance*, BoundingBoxf3> bbox_cache;
|
||||||
|
|
||||||
std::optional<Point> m_all_layer_pos;
|
std::optional<Point> m_all_layer_pos;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user