mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-08-05 16:20:40 +08:00
FIX: collision caused by pick safe pos in object mode
jira:NONE Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: Ic9a45e314ffa1115854736516cc06dfd976c28f9
This commit is contained in:
parent
17a5a415e6
commit
04d90ac16d
@ -2,6 +2,7 @@
|
||||
#include "Layer.hpp"
|
||||
|
||||
constexpr int FILTER_THRESHOLD = 5;
|
||||
constexpr int MAX_CANDIDATE_SIZE = 5;
|
||||
|
||||
namespace Slic3r {
|
||||
void TimelapsePosPicker::init(const Print* print_, const Point& plate_offset)
|
||||
@ -209,7 +210,7 @@ namespace Slic3r {
|
||||
object_y_ranges.emplace_back(m_plate_height, m_plate_height);
|
||||
|
||||
int lower_y_pos = -1, upper_y_pos =-1;
|
||||
auto unscaled_curr_pos = unscale(ctx.curr_pos);
|
||||
Point unscaled_curr_pos = {unscale_(ctx.curr_pos.x())-m_plate_offset.x(), unscale_(ctx.curr_pos.y()) - m_plate_offset.y()};
|
||||
|
||||
for (size_t idx = 1; idx < object_y_ranges.size(); ++idx) {
|
||||
if (unscaled_curr_pos.y() >= object_y_ranges[idx - 1].second && unscaled_curr_pos.y() <= object_y_ranges[idx].first) {
|
||||
@ -353,31 +354,28 @@ namespace Slic3r {
|
||||
* @param safe_areas A collection of extended polygons defining the safe areas.
|
||||
* @return Point The nearest point within the safe areas or the default timelapse position if no safe areas exist.
|
||||
*/
|
||||
Point pick_pos_internal(const Point& curr_pos, const ExPolygons& safe_areas)
|
||||
Point pick_pos_internal(const Point& curr_pos, const ExPolygons& safe_areas, const ExPolygons& path_collision_area, bool detect_path_collision)
|
||||
{
|
||||
if (std::any_of(safe_areas.begin(), safe_areas.end(), [&curr_pos](const ExPolygon& p) { return p.contains(curr_pos);}))
|
||||
struct CandidatePoint
|
||||
{
|
||||
double dist;
|
||||
Point point;
|
||||
bool operator<(const CandidatePoint& other) const {
|
||||
return dist < other.dist;
|
||||
}
|
||||
};
|
||||
|
||||
if (std::any_of(safe_areas.begin(), safe_areas.end(), [&curr_pos](const ExPolygon& p) { return p.contains(curr_pos); }))
|
||||
return curr_pos;
|
||||
|
||||
if (safe_areas.empty())
|
||||
return DefaultTimelapsePos;
|
||||
|
||||
std::priority_queue<CandidatePoint> max_heap;
|
||||
|
||||
double min_distance = std::numeric_limits<double>::max();
|
||||
Point nearest_point =DefaultTimelapsePos;
|
||||
#if 0
|
||||
for (const auto& expoly : safe_areas) {
|
||||
Polygons polys = to_polygons(expoly);
|
||||
for (auto& poly : polys) {
|
||||
auto nearest_point_ptr = poly.closest_point(curr_pos);
|
||||
if (nearest_point_ptr) {
|
||||
double dist = (*nearest_point_ptr - curr_pos).cast<double>().norm();
|
||||
if (min_distance > dist) {
|
||||
min_distance = dist;
|
||||
nearest_point = *nearest_point_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
Point nearest_point = DefaultTimelapsePos;
|
||||
|
||||
for (const auto& expoly : safe_areas) {
|
||||
Polygons polys = to_polygons(expoly);
|
||||
for (auto& poly : polys) {
|
||||
@ -385,15 +383,31 @@ namespace Slic3r {
|
||||
Line line(poly.points[idx], poly.points[next_idx_modulo(idx, poly.points)]);
|
||||
Point candidate;
|
||||
double dist = line.distance_to_squared(curr_pos, &candidate);
|
||||
if (min_distance > dist) {
|
||||
min_distance = dist;
|
||||
nearest_point = candidate;
|
||||
}
|
||||
max_heap.push({ dist,candidate });
|
||||
if (max_heap.size() > MAX_CANDIDATE_SIZE)
|
||||
max_heap.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return nearest_point;
|
||||
|
||||
std::vector<Point> top_candidates;
|
||||
while (!max_heap.empty()) {
|
||||
top_candidates.push_back(max_heap.top().point);
|
||||
max_heap.pop();
|
||||
}
|
||||
std::reverse(top_candidates.begin(), top_candidates.end());
|
||||
|
||||
for (auto& p : top_candidates) {
|
||||
if (!detect_path_collision)
|
||||
return p;
|
||||
|
||||
Polyline path(curr_pos, p);
|
||||
|
||||
if (intersection_pl(path, path_collision_area).empty())
|
||||
return p;
|
||||
}
|
||||
|
||||
return DefaultTimelapsePos;
|
||||
}
|
||||
|
||||
Point TimelapsePosPicker::pick_pos(const PosPickCtx& ctx)
|
||||
@ -418,7 +432,7 @@ namespace Slic3r {
|
||||
Point min_p{ instance_bbox.min.x(),instance_bbox.min.y() };
|
||||
Point max_p{ instance_bbox.max.x(),instance_bbox.max.y() };
|
||||
|
||||
return { scale_((min_p.x() + max_p.x()) / 2),scale_(min_p.y() + max_p.y() / 2) };
|
||||
return { scale_((min_p.x() + max_p.x()) / 2),scale_((min_p.y() + max_p.y()) / 2) };
|
||||
}
|
||||
|
||||
// scaled data
|
||||
@ -444,7 +458,7 @@ namespace Slic3r {
|
||||
{
|
||||
float height_gap = 0;
|
||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
||||
if(m_liftable_extruder_id.has_value() && ctx.picture_extruder_id != m_liftable_extruder_id && m_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 = -*m_extruder_height_gap;
|
||||
}
|
||||
|
||||
@ -454,16 +468,32 @@ namespace Slic3r {
|
||||
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 rod_limit_areas;
|
||||
if (m_print_seq == PrintSequence::ByObject) {
|
||||
rod_limit_areas = collect_limit_areas_for_rod(object_list,ctx);
|
||||
if (by_object) {
|
||||
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);
|
||||
ExPolygons extruder_printable_area = m_extruder_printable_area[ctx.picture_extruder_id];
|
||||
|
||||
ExPolygons safe_area = diff_ex(extruder_printable_area, unplacable_area);
|
||||
safe_area = opening_ex(safe_area, scale_(FILTER_THRESHOLD));
|
||||
Point objs_center = get_objects_center(object_list);
|
||||
return pick_pos_internal(objs_center, safe_area);
|
||||
|
||||
Point center_p;
|
||||
if (by_object && ctx.printed_objects && !ctx.printed_objects->empty())
|
||||
center_p = get_object_center(ctx.printed_objects->back());
|
||||
else
|
||||
center_p = get_objects_center(object_list);
|
||||
|
||||
ExPolygons path_collision_area;
|
||||
if (by_object) {
|
||||
auto object_without_curr = ctx.printed_objects;
|
||||
if (object_without_curr && !object_without_curr->empty())
|
||||
object_without_curr->pop_back();
|
||||
|
||||
ExPolygons layer_slices_without_curr = collect_object_slices_data(ctx.curr_layer, height_gap, get_object_list(object_without_curr), by_object);
|
||||
path_collision_area = union_ex(layer_slices_without_curr, rod_limit_areas);
|
||||
}
|
||||
|
||||
return pick_pos_internal(center_p, safe_area,path_collision_area, by_object);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -498,6 +528,10 @@ namespace Slic3r {
|
||||
|
||||
Point TimelapsePosPicker::pick_pos_for_all_layer(const PosPickCtx& ctx)
|
||||
{
|
||||
bool by_object = m_print_seq == PrintSequence::ByObject;
|
||||
if (by_object)
|
||||
return DefaultTimelapsePos;
|
||||
|
||||
float height_gap = 0;
|
||||
if (ctx.curr_extruder_id != ctx.picture_extruder_id) {
|
||||
if (m_liftable_extruder_id.has_value() && ctx.picture_extruder_id != m_liftable_extruder_id && m_extruder_height_gap.has_value())
|
||||
@ -508,8 +542,6 @@ namespace Slic3r {
|
||||
if (m_all_layer_pos)
|
||||
return *m_all_layer_pos;
|
||||
|
||||
bool by_object = m_print_seq == PrintSequence::ByObject;
|
||||
|
||||
Polygons object_projections;
|
||||
|
||||
auto object_list = get_object_list(std::nullopt);
|
||||
@ -517,10 +549,6 @@ namespace Slic3r {
|
||||
for (auto& obj : object_list) {
|
||||
for (auto& instance : obj->instances()) {
|
||||
const auto& bbox = get_real_instance_bbox(instance);
|
||||
if (m_print_seq == PrintSequence::ByObject && bbox.max.z() >= m_nozzle_height_to_rod) {
|
||||
m_all_layer_pos = DefaultTimelapsePos;
|
||||
return *m_all_layer_pos;
|
||||
}
|
||||
Point min_p{ scale_(bbox.min.x()),scale_(bbox.min.y()) };
|
||||
Point max_p{ scale_(bbox.max.x()),scale_(bbox.max.y()) };
|
||||
Polygon obj_proj{ { min_p.x(),min_p.y() },
|
||||
@ -548,7 +576,7 @@ namespace Slic3r {
|
||||
|
||||
Point starting_pos = get_objects_center(object_list);
|
||||
|
||||
m_all_layer_pos = pick_pos_internal(starting_pos, safe_area);
|
||||
m_all_layer_pos = pick_pos_internal(starting_pos, safe_area, {}, by_object);
|
||||
return *m_all_layer_pos;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user