mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 07:27:41 -06:00
FIX: avoid arrange to nonprefered region
Previously we assume the NFP of exclude regions are rectangle, which was not always right. Now we calculate the NFP and find a best new position to shift. Change-Id: I02c075603cf71dd3c9146d7ac7a6706c0f850669 (cherry picked from commit 713ebd666c90d5dcfaf89914c37d211e9a470e99)
This commit is contained in:
parent
56f1a49232
commit
f49c151611
5 changed files with 63 additions and 65 deletions
|
@ -1099,8 +1099,6 @@ private:
|
|||
auto d = cb - ci;
|
||||
|
||||
// BBS make sure the item won't clash with excluded regions
|
||||
if(1)
|
||||
{
|
||||
// do we have wipe tower after arranging?
|
||||
std::set<int> extruders;
|
||||
for (const Item& item : items_) {
|
||||
|
@ -1113,8 +1111,10 @@ private:
|
|||
if (item.isFixed()) continue;
|
||||
objs.push_back(item.transformedShape());
|
||||
}
|
||||
if (objs.empty())
|
||||
return;
|
||||
{ // find a best position inside NFP of fixed items (excluded regions), so the center of pile is cloest to bed center
|
||||
RawShape objs_convex_hull = sl::convexHull(objs);
|
||||
if (objs.size() != 0) {
|
||||
for (const Item &item : config_.m_excluded_regions) { excludes.push_back(item.transformedShape()); }
|
||||
for (const Item &item : items_) {
|
||||
if (item.isFixed()) {
|
||||
|
@ -1122,19 +1122,20 @@ private:
|
|||
excludes.push_back(item.transformedShape());
|
||||
}
|
||||
}
|
||||
Box binbb = sl::boundingBox(bin_);
|
||||
auto allowShifts = calcnfp(objs_convex_hull, excludes, binbb, Lvl<MaxNfpLevel::value>());
|
||||
int maxAllowShiftX = 0;
|
||||
int maxAllowShiftY = 0;
|
||||
for (const auto &shiftShape : allowShifts) {
|
||||
auto shiftBox = sl::boundingBox(shiftShape); // assume that the exclude region is box so that the nfp is box.
|
||||
maxAllowShiftX = shiftBox.width();
|
||||
maxAllowShiftY = shiftBox.height();
|
||||
|
||||
auto nfps = calcnfp(objs_convex_hull, excludes, bbin, Lvl<MaxNfpLevel::value>());
|
||||
if (nfps.empty()) {
|
||||
return;
|
||||
}
|
||||
int finalShiftX = std::min(std::abs(maxAllowShiftX), std::abs(d.x()));
|
||||
int finalShiftY = std::min(std::abs(maxAllowShiftY), std::abs(d.y()));
|
||||
d.x() = d.x() > 0 ? finalShiftX : -finalShiftX;
|
||||
d.y() = d.y() > 0 ? finalShiftY : -finalShiftY;
|
||||
Item objs_convex_hull_item(objs_convex_hull);
|
||||
Vertex objs_convex_hull_ref = objs_convex_hull_item.referenceVertex();
|
||||
Vertex diff = objs_convex_hull_ref - sl::boundingBox(objs_convex_hull).center();
|
||||
Vertex ref_aligned = cb + diff; // reference point when pile center aligned with bed center
|
||||
bool ref_aligned_is_ok = std::any_of(nfps.begin(), nfps.end(), [&ref_aligned](auto& nfp) {return sl::isInside(ref_aligned, nfp); });
|
||||
if (!ref_aligned_is_ok) {
|
||||
// ref_aligned is not good, then find a nearest point on nfp boundary
|
||||
Vertex ref_projected = projection_onto(nfps, ref_aligned);
|
||||
d += (ref_projected - ref_aligned);
|
||||
}
|
||||
}
|
||||
for(Item& item : items_)
|
||||
|
|
|
@ -185,6 +185,25 @@ bool overlaps(const ExPolygons& expolys1, const ExPolygons& expolys2)
|
|||
return false;
|
||||
}
|
||||
|
||||
Point projection_onto(const ExPolygons& polygons, const Point& from)
|
||||
{
|
||||
Point projected_pt;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
|
||||
for (const auto& poly : polygons) {
|
||||
for (int i = 0; i < poly.num_contours(); i++) {
|
||||
Point p = from.projection_onto(poly.contour_or_hole(i));
|
||||
double dist = (from - p).cast<double>().squaredNorm();
|
||||
if (dist < min_dist) {
|
||||
projected_pt = p;
|
||||
min_dist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return projected_pt;
|
||||
}
|
||||
|
||||
void ExPolygon::simplify_p(double tolerance, Polygons* polygons) const
|
||||
{
|
||||
Polygons pp = this->simplify_p(tolerance);
|
||||
|
|
|
@ -453,6 +453,8 @@ bool expolygons_match(const ExPolygon &l, const ExPolygon &r);
|
|||
|
||||
bool overlaps(const ExPolygons& expolys1, const ExPolygons& expolys2);
|
||||
|
||||
Point projection_onto(const ExPolygons& expolys, const Point& pt);
|
||||
|
||||
BoundingBox get_extents(const ExPolygon &expolygon);
|
||||
BoundingBox get_extents(const ExPolygons &expolygons);
|
||||
BoundingBox get_extents_rotated(const ExPolygon &poly, double angle);
|
||||
|
|
|
@ -625,32 +625,11 @@ static bool is_inside_ex(const ExPolygons &polygons, const Point &pt)
|
|||
return false;
|
||||
}
|
||||
|
||||
Point projection_onto_ex(const ExPolygons& polygons, Point from)
|
||||
{
|
||||
profiler.tic();
|
||||
Point projected_pt;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
|
||||
for (auto poly : polygons) {
|
||||
for (int i = 0; i < poly.num_contours(); i++) {
|
||||
Point p = from.projection_onto(poly.contour_or_hole(i));
|
||||
double dist = (from - p).cast<double>().squaredNorm();
|
||||
if (dist < min_dist) {
|
||||
projected_pt = p;
|
||||
min_dist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.stage_add(STAGE_projection_onto_ex, true);
|
||||
return projected_pt;
|
||||
}
|
||||
|
||||
static bool move_out_expolys(const ExPolygons& polygons, Point& from, double distance, double max_move_distance)
|
||||
{
|
||||
Point from0 = from;
|
||||
ExPolygons polys_dilated = union_ex(offset_ex(polygons, scale_(distance)));
|
||||
Point pt = projection_onto_ex(polys_dilated, from);// find_closest_ex(from, polys_dilated);
|
||||
Point pt = projection_onto(polys_dilated, from);// find_closest_ex(from, polys_dilated);
|
||||
Point outward_dir = pt - from;
|
||||
Point pt_max = from + normal(outward_dir, scale_(max_move_distance));
|
||||
double dist2 = vsize2_with_unscale(outward_dir);
|
||||
|
@ -2790,7 +2769,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
|||
if (group_index > 0 && is_inside_ex(m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr), node.position))
|
||||
{
|
||||
const coordf_t branch_radius_node = calc_branch_radius(branch_radius, node.dist_mm_to_top, diameter_angle_scale_factor);
|
||||
Point to_outside = projection_onto_ex(m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr), node.position);
|
||||
Point to_outside = projection_onto(m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr), node.position);
|
||||
double dist2_to_outside = vsize2_with_unscale(node.position - to_outside);
|
||||
if (dist2_to_outside >= branch_radius_node * branch_radius_node) //Too far inside.
|
||||
{
|
||||
|
@ -2871,7 +2850,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
|||
#endif
|
||||
auto avoid_layer = m_ts_data->get_avoidance(branch_radius_node, layer_nr_next);
|
||||
|
||||
Point to_outside = projection_onto_ex(avoid_layer, node.position);
|
||||
Point to_outside = projection_onto(avoid_layer, node.position);
|
||||
Point direction_to_outer = to_outside - node.position;
|
||||
double dist2_to_outer = vsize2_with_unscale(direction_to_outer);
|
||||
// don't move if
|
||||
|
|
|
@ -301,21 +301,18 @@ void ArrangeJob::prepare_wipe_tower()
|
|||
}
|
||||
|
||||
// if wipe tower is not init yet (no wipe tower in any plate before arrangement)
|
||||
if (wipe_tower_ap.poly.empty()) {
|
||||
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
wipe_tower_ap.poly.contour.points = print.first_layer_wipe_tower_corners(false);
|
||||
//if (wipe_tower_ap.poly.empty()) {
|
||||
// auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
// wipe_tower_ap.poly.contour.points = print.first_layer_wipe_tower_corners(false);
|
||||
wipe_tower_ap.name = "WipeTower";
|
||||
wipe_tower_ap.is_virt_object = true;
|
||||
wipe_tower_ap.is_wipe_tower = true;
|
||||
}
|
||||
//}
|
||||
const GLCanvas3D* canvas3D=static_cast<const GLCanvas3D *>(m_plater->canvas3D());
|
||||
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
|
||||
if (!plates_have_wipe_tower[bedid]) {
|
||||
wipe_tower_ap.translation = {0, 0};
|
||||
bool global = true;
|
||||
int state = m_plater->get_prepare_state();
|
||||
if (state == Job::JobPrepareState::PREPARE_STATE_MENU) { global = false; }
|
||||
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, global);
|
||||
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
|
||||
wipe_tower_ap.bed_idx = bedid;
|
||||
m_unselected.emplace_back(wipe_tower_ap);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue