Needs testing - Improving algorithm for hole insertion

This is for the edge processor / polygon generator:
The algorithm tries to find a better place
for hooking stitch lines for holes in
"resolve_holes" mode.
This commit is contained in:
Matthias Koefferlein 2024-09-15 00:10:36 +02:00
parent 97dcf0aa0b
commit aed3f1862b
2 changed files with 64 additions and 14 deletions

View File

@ -410,6 +410,8 @@ PolygonGenerator::begin_scanline (db::Coord y)
m_open_pos = m_open.begin ();
m_y = y;
m_prev_stitch_index = std::numeric_limits<size_t>::max ();
#ifdef DEBUG_POLYGON_GENERATOR
printf ("m_open=");
for (open_map_type::const_iterator o = m_open.begin (); o != m_open.end (); ++o) {
@ -820,27 +822,68 @@ PolygonGenerator::join_contours (db::Coord x)
tl_assert (c1.size () >= 2);
PGPolyContour::iterator ins = cprev.end ();
db::Coord xprev = 0;
db::Edge eprev;
#if 1
PGPolyContour::iterator ii = ins;
--ii;
PGPolyContour::iterator iii = ii;
--iii;
// shallow analysis: insert the cutline at the end of the sequence - this may
// cut lines collinear with contour edges
eprev = db::Edge (*(ins - 2), *(ins - 1));
xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (*(ins - 2), *(ins - 1)), m_y));
#else
// deep analysis: determine insertion point: pick the one where the cutline is shortest
db::Edge eprev = db::Edge (*iii, *ii);
db::Coord xprev = db::coord_traits<db::Coord>::rounded (edge_xaty (eprev, m_y));
for (PGPolyContour::iterator i = ins; i > cprev.begin () + 1; --i) {
#if 1 // experimental
if (m_prev_stitch_index == iprev) {
db::Edge ecut (i[-2], i[-1]);
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (db::Edge (i[-2], i[-1]), m_y));
auto i = m_prev_stitch_ins;
ii = i;
iii = --ii;
--iii;
if (ii->y () >= m_y) {
db::Edge ecut (*iii, *ii);
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (ecut, m_y));
if (iii->y () < m_y && xcut < c1.back ().x () && xcut > xprev) {
xprev = xcut;
eprev = ecut;
ins = i;
}
}
} else {
// deep analysis: determine insertion point: pick the one where the cutline is shortest
// CAUTION: this may introduce a O(2) complexity in the number of holes along the x axis
while (true) {
auto i = ii;
ii = iii;
if (ii == cprev.begin ()) {
break;
}
--iii;
if (ii->y () >= m_y) {
db::Edge ecut (*iii, *ii);
db::Coord xcut = db::coord_traits<db::Coord>::rounded (edge_xaty (ecut, m_y));
if (iii->y () < m_y && xcut < c1.back ().x () && xcut > xprev) {
xprev = xcut;
eprev = ecut;
ins = i;
}
}
if (ins == i || (i[-1].y () >= m_y && i[-2].y () < m_y && xcut < c1.back ().x () && xcut > xprev)) {
xprev = xcut;
eprev = ecut;
ins = i;
}
}
@ -864,6 +907,11 @@ PolygonGenerator::join_contours (db::Coord x)
}
ins = cprev.insert (ins, pprev);
// remember the insertion point - it may be a candidate to attach the next hole
m_prev_stitch_ins = ins;
m_prev_stitch_index = iprev;
++ins;
if (eprev.p2 () != pprev) {
cprev.insert (ins, eprev.p2 ());

View File

@ -183,6 +183,8 @@ private:
db::SimplePolygon m_spoly;
static bool ms_compress;
bool m_compress;
size_t m_prev_stitch_index;
std::list<db::Point>::iterator m_prev_stitch_ins;
void join_contours (db::Coord x);
void produce_poly (const PGPolyContour &c);