From aed3f1862bec9dcfa797120a78f6e26a8a185499 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 15 Sep 2024 00:10:36 +0200 Subject: [PATCH] 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. --- src/db/db/dbPolygonGenerators.cc | 76 ++++++++++++++++++++++++++------ src/db/db/dbPolygonGenerators.h | 2 + 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/db/db/dbPolygonGenerators.cc b/src/db/db/dbPolygonGenerators.cc index ddaf33268..f339611ed 100644 --- a/src/db/db/dbPolygonGenerators.cc +++ b/src/db/db/dbPolygonGenerators.cc @@ -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::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::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::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::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::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::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 ()); diff --git a/src/db/db/dbPolygonGenerators.h b/src/db/db/dbPolygonGenerators.h index cc34c8fce..b576812f5 100644 --- a/src/db/db/dbPolygonGenerators.h +++ b/src/db/db/dbPolygonGenerators.h @@ -183,6 +183,8 @@ private: db::SimplePolygon m_spoly; static bool ms_compress; bool m_compress; + size_t m_prev_stitch_index; + std::list::iterator m_prev_stitch_ins; void join_contours (db::Coord x); void produce_poly (const PGPolyContour &c);