From 94396da11718e7c53f6c7f726c7996bc75f0b54c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 16 Apr 2025 23:43:27 +0200 Subject: [PATCH] Fixed problem of on-edge internal vertex/precious vertex --- src/db/db/dbPLC.cc | 2 +- src/db/db/dbPLCTriangulation.cc | 45 ++++++++++++++----- .../dbPLCConvexDecompositionTests.cc | 21 ++++++--- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/db/db/dbPLC.cc b/src/db/db/dbPLC.cc index d72b57362..2bcf56202 100644 --- a/src/db/db/dbPLC.cc +++ b/src/db/db/dbPLC.cc @@ -551,7 +551,7 @@ Polygon::polygon () const } db::DPolygon poly; - poly.assign_hull (pts.begin (), pts.end ()); + poly.assign_hull (pts.begin (), pts.end (), false); return poly; } diff --git a/src/db/db/dbPLCTriangulation.cc b/src/db/db/dbPLCTriangulation.cc index 9785616a6..02afd64da 100644 --- a/src/db/db/dbPLCTriangulation.cc +++ b/src/db/db/dbPLCTriangulation.cc @@ -1017,7 +1017,7 @@ Triangulation::search_edges_crossing (Vertex *from, Vertex *to) if (os->has_vertex (vv)) { return result; } - if (os->crosses (edge)) { + if (os->crosses_including (edge)) { result.push_back (os); current_triangle = t.operator-> (); next_edge = os; @@ -1087,12 +1087,19 @@ Triangulation::find_edge_for_points (const db::DPoint &p1, const db::DPoint &p2) return 0; } +static bool is_touching (const db::DEdge &a, const db::DEdge &b) +{ + return (a.side_of (b.p1 ()) == 0 || a.side_of (b.p2 ()) == 0); +} + std::vector Triangulation::ensure_edge_inner (Vertex *from, Vertex *to) { auto crossed_edges = search_edges_crossing (from, to); std::vector result; + db::DEdge dedge (*from , *to); + if (crossed_edges.empty ()) { // no crossing edge - there should be a edge already @@ -1100,7 +1107,7 @@ Triangulation::ensure_edge_inner (Vertex *from, Vertex *to) tl_assert (res != 0); result.push_back (res); - } else if (crossed_edges.size () == 1) { + } else if (crossed_edges.size () == 1 && ! is_touching (dedge, crossed_edges.front ()->edge ())) { // can be solved by flipping auto pp = flip (crossed_edges.front ()); @@ -1112,18 +1119,29 @@ Triangulation::ensure_edge_inner (Vertex *from, Vertex *to) // split edge close to center db::DPoint split_point; + Edge *split_edge = 0; double d = -1.0; double l_half = 0.25 * (*to - *from).sq_length (); for (auto e = crossed_edges.begin (); e != crossed_edges.end (); ++e) { - db::DPoint p = (*e)->intersection_point (db::DEdge (*from, *to)); + db::DPoint p = (*e)->intersection_point (dedge); double dp = fabs ((p - *from).sq_length () - l_half); if (d < 0.0 || dp < d) { dp = d; split_point = p; + split_edge = *e; } } - Vertex *split_vertex = insert_point (split_point); + Vertex *split_vertex; + if (dedge.side_of (split_point) == 0) { + if (dedge.side_of (*split_edge->v1 ()) == 0) { + split_vertex = split_edge->v1 (); + } else { + split_vertex = split_edge->v2 (); + } + } else { + split_vertex = insert_point (split_point); + } result = ensure_edge_inner (from, split_vertex); @@ -1167,15 +1185,20 @@ Triangulation::join_edges (std::vector &edges) tl_assert (cp != 0); std::vector join_edges; - for (auto e = cp->begin_edges (); e != cp->end_edges (); ++e) { - if (*e != s1 && *e != s2) { - if ((*e)->can_join_via (cp)) { - join_edges.push_back (*e); - } else { - join_edges.clear (); - break; + + if (! cp->is_precious ()) { + + for (auto e = cp->begin_edges (); e != cp->end_edges (); ++e) { + if (*e != s1 && *e != s2) { + if ((*e)->can_join_via (cp)) { + join_edges.push_back (*e); + } else { + join_edges.clear (); + break; + } } } + } if (! join_edges.empty ()) { diff --git a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc index df2c10a89..fb6dcd245 100644 --- a/src/db/unit_tests/dbPLCConvexDecompositionTests.cc +++ b/src/db/unit_tests/dbPLCConvexDecompositionTests.cc @@ -123,7 +123,7 @@ TEST(internal_vertex) }; std::vector vertexes; - vertexes.push_back (db::Point (10, 50)); + vertexes.push_back (db::Point (0, 50)); // on edge vertexes.push_back (db::Point (200, 70)); db::Polygon poly; @@ -134,12 +134,21 @@ TEST(internal_vertex) db::plc::ConvexDecompositionParameters param; decomp.decompose (poly, vertexes, param, dbu); - for (auto p = plc.begin (); p != plc.end (); ++p) { - std::cout << p->polygon ().to_string () << std::endl; // @@@ - for (size_t i = 0; i < p->internal_vertexes (); ++i) { - std::cout << " " << p->internal_vertex (i)->to_string () << std::endl; // @@@ - } + EXPECT_EQ (plc.begin () == plc.end (), false); + if (plc.begin () == plc.end ()) { + return; } + auto p = plc.begin (); + EXPECT_EQ (p->polygon ().to_string (), "(0,0;0,0.05;0,0.1;1,0.1;1,0)"); + + std::vector ip; + for (size_t i = 0; i < p->internal_vertexes (); ++i) { + ip.push_back (p->internal_vertex (i)->to_string ()); + } + std::sort (ip.begin (), ip.end ()); + EXPECT_EQ (tl::join (ip, "/"), "(0, 0.05)/(0.2, 0.07)"); + + EXPECT_EQ (++p == plc.end (), true); }