mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-17 14:02:35 +00:00
Keep the prime tower and its approach travel on non-rectangular beds
The placement clamps and the tower-approach router both stood in the bed's bounding box for the bed itself, so on a delta or hexagonal bed the prime tower could be parked in a corner that does not exist and the nozzle could be routed across it. Both now test the real printable outline, slicing reports a tower that does not fit instead of printing it off the bed, and a tower parked near an edge is routed along the clamped side rather than falling back to a straight line across the tower. Also fixes the placement validation rotating the tower hull by degrees read as radians about the plate origin, and never rotating the generated tower footprint at all.
This commit is contained in:
@@ -1630,25 +1630,56 @@ float WipeTower::get_auto_brim_by_height(float max_height) {
|
||||
return 8.f;
|
||||
}
|
||||
|
||||
Vec2f WipeTower::move_box_inside_box(const BoundingBox &box1, const BoundingBox &box2,int scaled_offset)
|
||||
Vec2f WipeTower::move_box_inside_polygon(const BoundingBox &box, const Polygons &polygons, coord_t offset)
|
||||
{
|
||||
Vec2f res{0, 0};
|
||||
if (box1.size()[0] >= box2.size()[0]- 2*scaled_offset || box1.size()[1] >= box2.size()[1]-2*scaled_offset) return res;
|
||||
if (polygons.empty()) return Vec2f{0.f, 0.f};
|
||||
|
||||
if (box1.max[0] > box2.max[0] - scaled_offset) {
|
||||
res[0] = unscaled<float>((box2.max[0] - scaled_offset) - box1.max[0]);
|
||||
}
|
||||
else if (box1.min[0] < box2.min[0] + scaled_offset) {
|
||||
res[0] = unscaled<float>((box2.min[0] + scaled_offset) - box1.min[0]);
|
||||
const BoundingBox bed = get_extents(polygons);
|
||||
// No position fits the footprint.
|
||||
if (box.size().x() >= bed.size().x() - 2 * offset || box.size().y() >= bed.size().y() - 2 * offset)
|
||||
return Vec2f{0.f, 0.f};
|
||||
|
||||
// Clamp against the bounding box first, moving only along the axis that is violated so a dragged
|
||||
// prime tower slides along the bed edge instead of jumping inwards.
|
||||
Point shift(0, 0);
|
||||
for (int axis = 0; axis < 2; ++axis) {
|
||||
if (box.max[axis] > bed.max[axis] - offset)
|
||||
shift[axis] = (bed.max[axis] - offset) - box.max[axis];
|
||||
else if (box.min[axis] < bed.min[axis] + offset)
|
||||
shift[axis] = (bed.min[axis] + offset) - box.min[axis];
|
||||
}
|
||||
|
||||
if (box1.max[1] > box2.max[1] - scaled_offset) {
|
||||
res[1] = unscaled<float>((box2.max[1] - scaled_offset) - box1.max[1]);
|
||||
// A bed that fills its own bounding box is fully clamped by that, so every rectangular bed — all
|
||||
// but the delta-style profiles — stops here and keeps its historic placement, including when a
|
||||
// negative margin lets the footprint hang over the edge. The tolerance is relative because an
|
||||
// exact rectangle loses a few ulps once the areas are squared world coordinates.
|
||||
double area = 0.;
|
||||
for (const Polygon &poly : polygons) area += std::abs(poly.area());
|
||||
const double bed_area = double(bed.size().x()) * double(bed.size().y());
|
||||
if (area >= bed_area * (1. - EPSILON)) return unscaled<float>(shift);
|
||||
|
||||
// Clamp a negative margin (an auto brim width that has not been resolved yet) to zero: padding by
|
||||
// it would shrink the footprint and hand back a position the validation still rejects. The
|
||||
// epsilon lets the move's round trip through millimeters land on the outline without counting as
|
||||
// a violation.
|
||||
BoundingBox padded = box.inflated(std::max<coord_t>(offset, 0) - SCALED_EPSILON);
|
||||
padded.translate(shift);
|
||||
auto fits = [&padded, &polygons](const Point &move) {
|
||||
BoundingBox moved = padded;
|
||||
moved.translate(move);
|
||||
return diff(Polygons{moved.polygon()}, polygons).empty();
|
||||
};
|
||||
if (fits(Point(0, 0))) return unscaled<float>(shift);
|
||||
|
||||
// Walk towards the middle of the bed. On every non-rectangular bed we ship, the fitting positions
|
||||
// form a convex region around it, so bisecting stops just inside the outline.
|
||||
Point lo(0, 0), hi = bed.center() - padded.center();
|
||||
if (!fits(hi)) return unscaled<float>(shift);
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
const Point mid = (lo + hi) / 2;
|
||||
if (fits(mid)) hi = mid; else lo = mid;
|
||||
}
|
||||
else if (box1.min[1] < box2.min[1] + scaled_offset) {
|
||||
res[1] = unscaled<float>((box2.min[1] + scaled_offset) - box1.min[1]);
|
||||
}
|
||||
return res;
|
||||
return unscaled<float>(Point(shift + hi));
|
||||
}
|
||||
|
||||
Polygon WipeTower::rib_section(float width, float depth, float rib_length, float rib_width,bool fillet_wall)
|
||||
|
||||
Reference in New Issue
Block a user