From 1b60adf6c1e8b5c6c946b52e5f6b5ff8dcb0b1c1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 20 Aug 2023 10:19:11 +0200 Subject: [PATCH] WIP --- src/db/db/dbRegionProcessors.cc | 11 ++++--- src/db/db/dbTriangles.cc | 40 +++++++++++++++-------- src/db/db/dbTriangles.h | 10 +++--- src/db/unit_tests/dbTrianglesTests.cc | 47 +++++++++++++++++++++++++-- 4 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/db/db/dbRegionProcessors.cc b/src/db/db/dbRegionProcessors.cc index f6c1ee9ad..959e1528c 100644 --- a/src/db/db/dbRegionProcessors.cc +++ b/src/db/db/dbRegionProcessors.cc @@ -219,7 +219,7 @@ const double triangulation_dbu = 0.001; TriangulationProcessor::TriangulationProcessor (double max_area, double min_b) { - m_param.max_area = max_area; + m_param.max_area = max_area * triangulation_dbu * triangulation_dbu; m_param.base_verbosity = 40; m_param.min_length = 2 * triangulation_dbu; m_param.min_b = min_b; @@ -228,15 +228,18 @@ TriangulationProcessor::TriangulationProcessor (double max_area, double min_b) void TriangulationProcessor::process (const db::Polygon &poly, std::vector &result) const { + // NOTE: we center the polygon for better numerical stability + db::CplxTrans trans = db::CplxTrans (triangulation_dbu) * db::ICplxTrans (db::Trans (db::Point () - poly.box ().center ())); + db::Triangles tri; - tri.triangulate (poly, m_param, triangulation_dbu); + tri.triangulate (poly, m_param, trans); db::Point pts [3]; - auto dbu_trans = db::CplxTrans (triangulation_dbu).inverted (); + auto trans_inv = trans.inverted (); for (auto t = tri.begin (); t != tri.end (); ++t) { for (int i = 0; i < 3; ++i) { - pts [i] = dbu_trans * *t->vertex (i); + pts [i] = trans_inv * *t->vertex (i); } result.push_back (db::Polygon ()); result.back ().assign_hull (pts + 0, pts + 3); diff --git a/src/db/db/dbTriangles.cc b/src/db/db/dbTriangles.cc index 6f4e928f5..b30a524f1 100644 --- a/src/db/db/dbTriangles.cc +++ b/src/db/db/dbTriangles.cc @@ -415,7 +415,7 @@ Triangles::find_closest_edge (const db::DPoint &p, db::Vertex *vstart, bool insi size_t n = m_vertex_heap.size (); size_t m = n; - // A sample heuristics that takes a sqrt(N) sample from the + // A simple heuristics that takes a sqrt(N) sample from the // vertexes to find a good starting point vstart = mp_triangles.begin ()->vertex (0); @@ -1432,13 +1432,12 @@ Triangles::make_contours (const Poly &poly, const Trans &trans, std::vector > edge_contours; - db::CplxTrans trans (dbu); for (auto p = region.begin_merged (); ! p.at_end (); ++p) { make_contours (*p, trans, edge_contours); } @@ -1447,12 +1446,12 @@ Triangles::create_constrained_delaunay (const db::Region ®ion, double dbu) } void -Triangles::create_constrained_delaunay (const db::Polygon &p, double dbu) +Triangles::create_constrained_delaunay (const db::Polygon &p, const CplxTrans &trans) { clear (); std::vector > edge_contours; - make_contours (p, db::CplxTrans (dbu), edge_contours); + make_contours (p, trans, edge_contours); constrain (edge_contours); } @@ -1506,7 +1505,16 @@ Triangles::triangulate (const db::Region ®ion, const TriangulateParameters &p { tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); - create_constrained_delaunay (region, dbu); + create_constrained_delaunay (region, db::CplxTrans (dbu)); + refine (parameters); +} + +void +Triangles::triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, const db::CplxTrans &trans) +{ + tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); + + create_constrained_delaunay (region, trans); refine (parameters); } @@ -1515,7 +1523,16 @@ Triangles::triangulate (const db::Polygon &poly, const TriangulateParameters &pa { tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); - create_constrained_delaunay (poly, dbu); + create_constrained_delaunay (poly, db::CplxTrans (dbu)); + refine (parameters); +} + +void +Triangles::triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, const db::CplxTrans &trans) +{ + tl::SelfTimer timer (tl::verbosity () > parameters.base_verbosity, "Triangles::triangulate"); + + create_constrained_delaunay (poly, trans); refine (parameters); } @@ -1582,13 +1599,10 @@ Triangles::refine (const TriangulateParameters ¶meters) if ((*t)->contains (center) >= 0) { - // heuristics #1: never insert a point into a triangle with more than one segments - if (t->get ()->num_segments () <= 1) { - if (tl::verbosity () >= parameters.base_verbosity + 20) { - tl::info << "Inserting in-triangle center " << center.to_string () << " of " << (*t)->to_string (true); - } - insert_point (center, &new_triangles); + if (tl::verbosity () >= parameters.base_verbosity + 20) { + tl::info << "Inserting in-triangle center " << center.to_string () << " of " << (*t)->to_string (true); } + insert_point (center, &new_triangles); } else { diff --git a/src/db/db/dbTriangles.h b/src/db/db/dbTriangles.h index 26bb8d88c..403d0afe4 100644 --- a/src/db/db/dbTriangles.h +++ b/src/db/db/dbTriangles.h @@ -154,10 +154,10 @@ public: */ void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, double dbu = 1.0); - /** - * @brief Triangulates a polygon - */ + // more versions void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, double dbu = 1.0); + void triangulate (const db::Region ®ion, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); + void triangulate (const db::Polygon &poly, const TriangulateParameters ¶meters, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Triangulates a floating-point polygon @@ -279,12 +279,12 @@ protected: /** * @brief Creates a constrained Delaunay triangulation from the given Region */ - void create_constrained_delaunay (const db::Region ®ion, double dbu = 1.0); + void create_constrained_delaunay (const db::Region ®ion, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Creates a constrained Delaunay triangulation from the given Polygon */ - void create_constrained_delaunay (const db::Polygon &poly, double dbu = 1.0); + void create_constrained_delaunay (const db::Polygon &poly, const db::CplxTrans &trans = db::CplxTrans ()); /** * @brief Creates a constrained Delaunay triangulation from the given DPolygon diff --git a/src/db/unit_tests/dbTrianglesTests.cc b/src/db/unit_tests/dbTrianglesTests.cc index 9f27f7f2e..a9d9e8a8c 100644 --- a/src/db/unit_tests/dbTrianglesTests.cc +++ b/src/db/unit_tests/dbTrianglesTests.cc @@ -665,7 +665,7 @@ TEST(create_constrained_delaunay) "((0, 1000), (200, 800), (200, 200))"); } -TEST(triangulate) +TEST(triangulate_basic) { db::Region r; r.insert (db::Box (0, 0, 10000, 10000)); @@ -765,7 +765,7 @@ void read_polygons (const std::string &path, db::Region ®ion, double dbu) } } -TEST(triangulate2) +TEST(triangulate_geo) { double dbu = 0.001; @@ -816,7 +816,7 @@ TEST(triangulate2) EXPECT_LT (tri.num_triangles (), size_t (30000)); } -TEST(triangulate3) +TEST(triangulate_analytic) { double dbu = 0.0001; @@ -869,3 +869,44 @@ TEST(triangulate3) EXPECT_GT (tri.num_triangles (), size_t (1250)); EXPECT_LT (tri.num_triangles (), size_t (1300)); } + +TEST(triangulate_problematic) +{ + db::DPoint contour[] = { + db::DPoint (129145.00000, -30060.80000), + db::DPoint (129145.00000, -28769.50000), + db::DPoint (129159.50000, -28754.90000), + db::DPoint (129159.60000, -28754.80000), + db::DPoint (129159.50000, -28754.70000), + db::DPoint (129366.32200, -28547.90000), + db::DPoint (130958.54600, -26955.84600), + db::DPoint (131046.25000, -27043.55000), + db::DPoint (130152.15000, -27937.65000), + db::DPoint (130152.15000, -30060.80000) + }; + + db::DPolygon poly; + poly.assign_hull (contour + 0, contour + sizeof (contour) / sizeof (contour[0])); + + db::Triangles::TriangulateParameters param; + param.min_b = 1.0; + param.max_area = 10000.0; + param.min_length = 0.002; + + TestableTriangles tri; + tri.triangulate (poly, param); + + EXPECT_EQ (tri.check (false), true); + + // for debugging: + // tri.dump ("debug.gds"); + + for (auto t = tri.begin (); t != tri.end (); ++t) { + EXPECT_LE (t->area (), param.max_area); + EXPECT_GE (t->b (), param.min_b); + } + + EXPECT_GT (tri.num_triangles (), size_t (1250)); + EXPECT_LT (tri.num_triangles (), size_t (1300)); +} +