Fixed Z chaining of layer islands.

This commit is contained in:
Vojtech Bubnik 2022-11-16 18:14:42 +01:00
parent 70b1b4dfbf
commit 30fbdd1235

View File

@ -120,22 +120,40 @@ static void connect_layer_slices(
void visit(const ClipperLib_Z::PolyNode &polynode) void visit(const ClipperLib_Z::PolyNode &polynode)
{ {
#ifndef NDEBUG
auto assert_intersection_valid = [this](int i, int j) {
assert(i != j);
if (i > j)
std::swap(i, j);
assert(i >= m_offset_below);
assert(i < m_offset_above);
assert(j >= m_offset_above);
assert(j < m_offset_end);
return true;
};
#endif // NDEBUG
if (polynode.Contour.size() >= 3) { if (polynode.Contour.size() >= 3) {
// If there is an intersection point, it should indicate which contours (one from layer below, the other from layer above) intersect.
// Otherwise the contour is fully inside another contour.
int32_t i = 0, j = 0; int32_t i = 0, j = 0;
double area = 0;
for (int icontour = 0; icontour <= polynode.ChildCount(); ++ icontour) { for (int icontour = 0; icontour <= polynode.ChildCount(); ++ icontour) {
const ClipperLib_Z::Path &contour = icontour == 0 ? polynode.Contour : polynode.Childs[icontour - 1]->Contour; const bool first = icontour == 0;
const ClipperLib_Z::Path &contour = first ? polynode.Contour : polynode.Childs[icontour - 1]->Contour;
if (contour.size() >= 3) { if (contour.size() >= 3) {
area = ClipperLib_Z::Area(contour); if (first) {
int32_t i = contour.front().z(); i = contour.front().z();
int32_t j = i; j = i;
if (i < 0) { if (i < 0) {
std::tie(i, j) = m_intersections[-i - 1]; std::tie(i, j) = m_intersections[-i - 1];
} else { assert(assert_intersection_valid(i, j));
goto end;
}
}
for (const ClipperLib_Z::IntPoint& pt : contour) { for (const ClipperLib_Z::IntPoint& pt : contour) {
j = pt.z(); j = pt.z();
if (j < 0) { if (j < 0) {
std::tie(i, j) = m_intersections[-j - 1]; std::tie(i, j) = m_intersections[-j - 1];
assert(assert_intersection_valid(i, j));
goto end; goto end;
} }
else if (i != j) else if (i != j)
@ -143,7 +161,6 @@ static void connect_layer_slices(
} }
} }
} }
}
end: end:
bool found = false; bool found = false;
if (i == j) { if (i == j) {
@ -175,23 +192,21 @@ static void connect_layer_slices(
} }
} }
} else { } else {
assert(assert_intersection_valid(i, j));
if (i > j) if (i > j)
std::swap(i, j); std::swap(i, j);
assert(i >= m_offset_below);
assert(i < m_offset_above);
i -= m_offset_below; i -= m_offset_below;
assert(j >= m_offset_above);
assert(j < m_offset_end);
j -= m_offset_above; j -= m_offset_above;
found = true; found = true;
} }
if (found) { if (found) {
// Subtract area of holes from the area of outer contour. // Subtract area of holes from the area of outer contour.
double area = ClipperLib_Z::Area(polynode.Contour);
for (int icontour = 0; icontour < polynode.ChildCount(); ++ icontour) for (int icontour = 0; icontour < polynode.ChildCount(); ++ icontour)
area -= ClipperLib_Z::Area(polynode.Childs[icontour]->Contour); area -= ClipperLib_Z::Area(polynode.Childs[icontour]->Contour);
// Store the links and area into the contours. // Store the links and area into the contours.
LayerSlice::Links &links_below = m_below.lslices_ex[i].overlaps_above; LayerSlice::Links &links_below = m_below.lslices_ex[i].overlaps_above;
LayerSlice::Links &links_above = m_above.lslices_ex[i].overlaps_below; LayerSlice::Links &links_above = m_above.lslices_ex[j].overlaps_below;
LayerSlice::Link key{ j }; LayerSlice::Link key{ j };
auto it_below = std::lower_bound(links_below.begin(), links_below.end(), key, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; }); auto it_below = std::lower_bound(links_below.begin(), links_below.end(), key, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; });
if (it_below != links_below.end() && it_below->slice_idx == j) { if (it_below != links_below.end() && it_below->slice_idx == j) {