mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-29 03:41:31 +00:00
Fix inner-outer-inner wall ordering falling back to outer-inner on narrow walls with Arachne (#15924)
* Fix wall ordering edge case * IOI performance tuning - greedy stop when a first touch is identified.
This commit is contained in:
@@ -2256,13 +2256,45 @@ void PerimeterGenerator::process_no_bridge(Surfaces& all_surfaces, coord_t perim
|
|||||||
|
|
||||||
// ORCA:
|
// ORCA:
|
||||||
// Inner Outer Inner wall ordering mode perimeter order optimisation functions
|
// Inner Outer Inner wall ordering mode perimeter order optimisation functions
|
||||||
|
|
||||||
|
// Whether two Arachne lines touch: somewhere the gap between their centrelines is no more than the
|
||||||
|
// touching distance there. Each junction of one line is measured against the segments of the other,
|
||||||
|
// both ways, and the search stops at the first spot that touches.
|
||||||
|
// Arachne varies line width to fill the region (e.g. the odd centre line of a narrow wall is wider
|
||||||
|
// than nominal), so the touching distance is half the combined width at the closest points, not the
|
||||||
|
// nominal spacing. Widths are taken locally so a line widened in one place (a wedge tip, a wall
|
||||||
|
// transition) does not count as touching where it passes close to other perimeters. min_threshold keeps
|
||||||
|
// the nominal spacing threshold as the lower bound.
|
||||||
|
static bool arachne_lines_touch(const Arachne::ExtrusionLine &a, const Arachne::ExtrusionLine &b, double min_threshold)
|
||||||
|
{
|
||||||
|
auto one_way = [min_threshold](const Arachne::ExtrusionLine &from, const Arachne::ExtrusionLine &to) {
|
||||||
|
for (const Arachne::ExtrusionJunction &j : from.junctions) {
|
||||||
|
const Vec2d p = j.p.cast<double>();
|
||||||
|
for (size_t k = 0; k + 1 < to.junctions.size(); ++k) {
|
||||||
|
const Arachne::ExtrusionJunction &j0 = to.junctions[k];
|
||||||
|
const Arachne::ExtrusionJunction &j1 = to.junctions[k + 1];
|
||||||
|
const Vec2d s0 = j0.p.cast<double>();
|
||||||
|
const Vec2d seg = j1.p.cast<double>() - s0;
|
||||||
|
const double l2 = seg.squaredNorm();
|
||||||
|
const double t = l2 > 0. ? std::clamp((p - s0).dot(seg) / l2, 0., 1.) : 0.;
|
||||||
|
const double w = double(j0.w) + t * double(j1.w - j0.w); // width of `to` at the closest point
|
||||||
|
const double touch_distance = std::max(min_threshold, 0.5 * (double(j.w) + w));
|
||||||
|
if ((s0 + t * seg - p).norm() <= touch_distance)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return one_way(a, b) || one_way(b, a);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Finds all perimeters touching a given set of reference lines, given as indexes.
|
* @brief Finds all perimeters touching a given set of reference lines, given as indexes.
|
||||||
*
|
*
|
||||||
* @param entities The list of PerimeterGeneratorArachneExtrusion entities.
|
* @param entities The list of PerimeterGeneratorArachneExtrusion entities.
|
||||||
* @param referenceIndices A set of indices representing the reference points.
|
* @param referenceIndices A set of indices representing the reference points.
|
||||||
* @param threshold_external The distance threshold to consider for proximity for a reference perimeter with inset index 0
|
* @param threshold_external The minimum touching distance for a reference perimeter with inset index 0
|
||||||
* @param threshold_internal The distance threshold to consider for proximity for a reference perimeter with inset index 1+
|
* @param threshold_internal The minimum touching distance for a reference perimeter with inset index 1+
|
||||||
* @param considered_inset_idx What perimeter inset index are we searching for (eg. if we are searching for first internal perimeters proximate to the current reference perimeter, this value should be set to 1 etc).
|
* @param considered_inset_idx What perimeter inset index are we searching for (eg. if we are searching for first internal perimeters proximate to the current reference perimeter, this value should be set to 1 etc).
|
||||||
* @return std::vector<int> A vector of indices representing the touching perimeters.
|
* @return std::vector<int> A vector of indices representing the touching perimeters.
|
||||||
*/
|
*/
|
||||||
@@ -2271,7 +2303,6 @@ std::vector<int> findAllTouchingPerimeters(const std::vector<PerimeterGeneratorA
|
|||||||
|
|
||||||
for (const int refIdx : referenceIndices) {
|
for (const int refIdx : referenceIndices) {
|
||||||
const auto& referenceEntity = entities[refIdx];
|
const auto& referenceEntity = entities[refIdx];
|
||||||
Points referencePoints = Arachne::to_points(*referenceEntity.extrusion);
|
|
||||||
for (size_t i = 0; i < entities.size(); ++i) {
|
for (size_t i = 0; i < entities.size(); ++i) {
|
||||||
// Skip already considered references and the reference entity
|
// Skip already considered references and the reference entity
|
||||||
if (referenceIndices.count(i) > 0) continue;
|
if (referenceIndices.count(i) > 0) continue;
|
||||||
@@ -2282,15 +2313,9 @@ std::vector<int> findAllTouchingPerimeters(const std::vector<PerimeterGeneratorA
|
|||||||
continue; // skip if they dont match
|
continue; // skip if they dont match
|
||||||
}
|
}
|
||||||
|
|
||||||
Points points = Arachne::to_points(*entity.extrusion);
|
// Add to touchingIndices if the lines touch.
|
||||||
double distance = MultiPoint::minimumDistanceBetweenLinesDefinedByPoints(referencePoints, points);
|
const double threshold = double(referenceEntity.extrusion->inset_idx == 0 ? threshold_external : threshold_internal);
|
||||||
// Add to touchingIndices if within threshold distance
|
if (arachne_lines_touch(*referenceEntity.extrusion, *entity.extrusion, threshold)) {
|
||||||
size_t threshold=0;
|
|
||||||
if(referenceEntity.extrusion->inset_idx == 0)
|
|
||||||
threshold = threshold_external;
|
|
||||||
else
|
|
||||||
threshold = threshold_internal;
|
|
||||||
if (distance <= threshold) {
|
|
||||||
touchingIndices.insert(i);
|
touchingIndices.insert(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user