From a2ef7a28f88ffb57a7fdc53cb6696e6c8371d779 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 17 Apr 2025 23:20:37 +0200 Subject: [PATCH] WIP --- src/db/db/dbPLC.cc | 10 ++ src/db/db/dbPLC.h | 43 +++++++-- src/db/db/dbPLCConvexDecomposition.cc | 38 ++------ src/db/db/dbPLCConvexDecomposition.h | 20 ++++ src/db/db/dbPLCTriangulation.cc | 10 +- src/db/unit_tests/dbPLCGraphTests.cc | 96 ++++++++++++++++++-- src/db/unit_tests/dbPLCTests.cc | 2 + src/db/unit_tests/dbPLCTriangulationTests.cc | 7 +- 8 files changed, 174 insertions(+), 52 deletions(-) diff --git a/src/db/db/dbPLC.cc b/src/db/db/dbPLC.cc index 2bcf56202..e75673cf1 100644 --- a/src/db/db/dbPLC.cc +++ b/src/db/db/dbPLC.cc @@ -72,6 +72,11 @@ Vertex::Vertex (const Vertex &v) // NOTE: edges are not copied! } +Vertex::~Vertex () +{ + // .. nothing yet .. +} + Vertex &Vertex::operator= (const Vertex &v) { if (this != &v) { @@ -176,6 +181,11 @@ Edge::Edge (Graph *graph, Vertex *v1, Vertex *v2) // .. nothing yet .. } +Edge::~Edge () +{ + // .. nothing yet .. +} + void Edge::set_left (Polygon *t) { diff --git a/src/db/db/dbPLC.h b/src/db/db/dbPLC.h index ee7f1a4f0..c88c8a506 100644 --- a/src/db/db/dbPLC.h +++ b/src/db/db/dbPLC.h @@ -161,10 +161,12 @@ protected: Vertex (Graph *graph, const DPoint &p); Vertex (Graph *graph, const Vertex &v); Vertex (Graph *graph, db::DCoord x, db::DCoord y); + ~Vertex (); private: friend class Edge; friend class Graph; + friend class tl::stable_vector; void remove_edge (const edges_iterator_non_const &ec) { @@ -499,12 +501,14 @@ protected: Edge (Graph *graph); Edge (Graph *graph, Vertex *v1, Vertex *v2); + ~Edge (); private: friend class Polygon; friend class Graph; friend class Triangulation; friend class ConvexDecomposition; + friend class tl::stable_vector; Graph *mp_graph; Vertex *mp_v1, *mp_v2; @@ -538,23 +542,34 @@ class DB_PUBLIC Polygon : public tl::list_node, public tl::Object { public: - template - Polygon (Graph *graph, Iter from, Iter to) - : mp_graph (graph), mp_e (from, to) - { - init (); - } + /** + * @brief Destructor + * + * It is legal to delete a polygon object to remove it. + */ ~Polygon (); + /** + * @brief Detaches a polygon object from the edges + */ void unlink (); - void set_id (size_t id) { m_id = id; } + /** + * @brief Gets the polygon's unique ID + */ size_t id () const { return m_id; } + /** + * @brief Gets a value indicating whether the polygon is an outside polygon + * + * Outside polygons are polygons that fill concave parts in a triangulation for example. + */ bool is_outside () const { return m_is_outside; } - void set_outside (bool o) { m_is_outside = o; } + /** + * @brief Returns a string representation + */ std::string to_string (bool with_id = false) const; /** @@ -727,8 +742,19 @@ protected: Polygon (Graph *graph); Polygon (Graph *graph, Edge *e1, Edge *e2, Edge *e3); + template + Polygon (Graph *graph, Iter from, Iter to) + : mp_graph (graph), mp_e (from, to) + { + init (); + } + + void set_outside (bool o) { m_is_outside = o; } + void set_id (size_t id) { m_id = id; } + private: friend class Graph; + friend class Triangulation; Graph *mp_graph; bool m_is_outside; @@ -764,6 +790,7 @@ struct PolygonLessFunc * hold triangles (polygons with 3 vertexes). */ class DB_PUBLIC Graph + : public tl::Object { public: typedef tl::list polygons_type; diff --git a/src/db/db/dbPLCConvexDecomposition.cc b/src/db/db/dbPLCConvexDecomposition.cc index ad7c65735..a39b5295d 100644 --- a/src/db/db/dbPLCConvexDecomposition.cc +++ b/src/db/db/dbPLCConvexDecomposition.cc @@ -85,24 +85,6 @@ struct equal_compare_func } }; -struct ConcaveCorner -{ - ConcaveCorner () - : corner (0), incoming (0), outgoing (0) - { - // .. nothing yet .. - } - - ConcaveCorner (Vertex *_corner, Edge *_incoming, Edge *_outgoing) - : corner (_corner), incoming (_incoming), outgoing (_outgoing) - { - // .. nothing yet .. - } - - Vertex *corner; - Edge *incoming, *outgoing; -}; - Edge *find_outgoing_segment (Vertex *vertex, Edge *incoming, int &vp_max_sign) { Vertex *vfrom = incoming->other (vertex); @@ -141,20 +123,16 @@ Edge *find_outgoing_segment (Vertex *vertex, Edge *incoming, int &vp_max_sign) return outgoing; } -void collect_concave_vertexes (Graph &tris, std::vector &concave_vertexes) +void +ConvexDecomposition::collect_concave_vertexes (std::vector &concave_vertexes) { concave_vertexes.clear (); - // @@@ use edge "level" - // @@@ use edges from heap std::unordered_set left; - for (auto it = tris.begin (); it != tris.end (); ++it) { - for (unsigned int i = 0; i < 3; ++i) { - Edge *e = it->edge (i); - if (e->is_segment ()) { - left.insert (e); - } + for (auto e = mp_graph->edges ().begin (); e != mp_graph->edges ().end (); ++e) { + if (e->is_segment () && (e->left () != 0 || e->right () != 0)) { + left.insert (e.operator-> ()); } } @@ -191,7 +169,7 @@ void collect_concave_vertexes (Graph &tris, std::vector &concave_ } std::pair -search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction) +ConvexDecomposition::search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction) { auto vtri = v0->polygons (); // TODO: slow? std::vector nvv, nvv_next; @@ -253,7 +231,7 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C bool split_edges = param.split_edges; std::vector concave_vertexes; - collect_concave_vertexes (*mp_graph, concave_vertexes); + collect_concave_vertexes (concave_vertexes); // @@@ return if no concave corners @@ -302,7 +280,7 @@ ConvexDecomposition::hertel_mehlhorn_decomposition (Triangulation &tris, const C } // As the insertion invalidates the edges, we need to collect the concave vertexes again - collect_concave_vertexes (*mp_graph, concave_vertexes); + collect_concave_vertexes (concave_vertexes); } diff --git a/src/db/db/dbPLCConvexDecomposition.h b/src/db/db/dbPLCConvexDecomposition.h index a04fdd844..03a6949bb 100644 --- a/src/db/db/dbPLCConvexDecomposition.h +++ b/src/db/db/dbPLCConvexDecomposition.h @@ -121,7 +121,27 @@ public: private: Graph *mp_graph; + struct ConcaveCorner + { + ConcaveCorner () + : corner (0), incoming (0), outgoing (0) + { + // .. nothing yet .. + } + + ConcaveCorner (Vertex *_corner, Edge *_incoming, Edge *_outgoing) + : corner (_corner), incoming (_incoming), outgoing (_outgoing) + { + // .. nothing yet .. + } + + Vertex *corner; + Edge *incoming, *outgoing; + }; + void hertel_mehlhorn_decomposition (Triangulation &tris, const ConvexDecompositionParameters ¶m); + void collect_concave_vertexes (std::vector &concave_vertexes); + std::pair search_crossing_with_next_segment (const Vertex *v0, const db::DVector &direction); }; } // namespace plc diff --git a/src/db/db/dbPLCTriangulation.cc b/src/db/db/dbPLCTriangulation.cc index 02afd64da..30757e249 100644 --- a/src/db/db/dbPLCTriangulation.cc +++ b/src/db/db/dbPLCTriangulation.cc @@ -1133,12 +1133,10 @@ Triangulation::ensure_edge_inner (Vertex *from, Vertex *to) } 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 (); - } + if (dedge.side_of (*split_edge->v1 ()) == 0) { + split_vertex = split_edge->v1 (); + } else if (dedge.side_of (*split_edge->v2 ()) == 0) { + split_vertex = split_edge->v2 (); } else { split_vertex = insert_point (split_point); } diff --git a/src/db/unit_tests/dbPLCGraphTests.cc b/src/db/unit_tests/dbPLCGraphTests.cc index e02449401..3536b5ba4 100644 --- a/src/db/unit_tests/dbPLCGraphTests.cc +++ b/src/db/unit_tests/dbPLCGraphTests.cc @@ -27,15 +27,97 @@ #include #include -TEST(basic) +namespace { - db::DBox box (0, 0, 100.0, 200.0); - db::plc::Graph plc; - // @@@ pg.insert_polygon (db::DSimplePolygon (box)); +class TestableGraph + : public db::plc::Graph +{ +public: + using db::plc::Graph::Graph; + using db::plc::Graph::create_vertex; + using db::plc::Graph::create_edge; + using db::plc::Graph::create_triangle; + using db::plc::Graph::create_polygon; +}; - // @@@ - tl::info << plc.to_string (); - plc.dump ("debug.gds"); // @@@ } +TEST(basic) +{ + TestableGraph plc; + + db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2)); + EXPECT_EQ (v1->to_string (), "(1, 2)"); + + v1 = plc.create_vertex (db::DPoint (2, 1)); + EXPECT_EQ (v1->to_string (), "(2, 1)"); + + EXPECT_EQ (v1->is_precious (), false); + v1->set_is_precious (true); + EXPECT_EQ (v1->is_precious (), true); +} + +TEST(edge) +{ + TestableGraph plc; + + db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2)); + db::plc::Vertex *v2 = plc.create_vertex (db::DPoint (3, 4)); + + db::plc::Edge *e = plc.create_edge (v1, v2); + EXPECT_EQ (e->to_string (), "((1, 2), (3, 4))"); + + EXPECT_EQ (v1->num_edges (), size_t (1)); + EXPECT_EQ (v2->num_edges (), size_t (1)); + + EXPECT_EQ ((*v1->begin_edges ())->edge ().to_string (), "(1,2;3,4)"); + EXPECT_EQ ((*v2->begin_edges ())->edge ().to_string (), "(1,2;3,4)"); +} + +TEST(polygon) +{ + TestableGraph plc; + EXPECT_EQ (plc.num_polygons (), size_t (0)); + EXPECT_EQ (plc.bbox ().to_string (), "()"); + + db::plc::Vertex *v1 = plc.create_vertex (db::DPoint (1, 2)); + db::plc::Vertex *v2 = plc.create_vertex (db::DPoint (3, 4)); + db::plc::Vertex *v3 = plc.create_vertex (db::DPoint (3, 2)); + + db::plc::Edge *e1 = plc.create_edge (v1, v2); + db::plc::Edge *e2 = plc.create_edge (v1, v3); + db::plc::Edge *e3 = plc.create_edge (v2, v3); + + db::plc::Polygon *tri = plc.create_triangle (e1, e2, e3); + EXPECT_EQ (tri->to_string (), "((1, 2), (3, 4), (3, 2))"); + EXPECT_EQ (tri->polygon ().to_string (), "(1,2;3,4;3,2)"); + EXPECT_EQ (plc.bbox ().to_string (), "(1,2;3,4)"); + EXPECT_EQ (plc.num_polygons (), size_t (1)); + + EXPECT_EQ (v1->num_edges (), size_t (2)); + EXPECT_EQ (v2->num_edges (), size_t (2)); + EXPECT_EQ (v3->num_edges (), size_t (2)); + + EXPECT_EQ (tri->edge (0) == e1, true); + EXPECT_EQ (tri->edge (3) == e1, true); + EXPECT_EQ (tri->edge (1) == e3, true); + EXPECT_EQ (tri->edge (2) == e2, true); + EXPECT_EQ (tri->edge (-1) == e2, true); + + EXPECT_EQ (e1->left () == 0, true); + EXPECT_EQ (e1->right () == tri, true); + EXPECT_EQ (e2->left () == tri, true); + EXPECT_EQ (e2->right () == 0, true); + EXPECT_EQ (e3->left () == 0, true); + EXPECT_EQ (e3->right () == tri, true); + + delete tri; + + EXPECT_EQ (e1->left () == 0, true); + EXPECT_EQ (e1->right () == 0, true); + EXPECT_EQ (e2->left () == 0, true); + EXPECT_EQ (e2->right () == 0, true); + EXPECT_EQ (e3->left () == 0, true); + EXPECT_EQ (e3->right () == 0, true); +} diff --git a/src/db/unit_tests/dbPLCTests.cc b/src/db/unit_tests/dbPLCTests.cc index f93c5d373..3c7745484 100644 --- a/src/db/unit_tests/dbPLCTests.cc +++ b/src/db/unit_tests/dbPLCTests.cc @@ -71,6 +71,8 @@ public: TestablePolygon (db::plc::Edge *e1, db::plc::Edge *e2, db::plc::Edge *e3) : db::plc::Polygon (0, e1, e2, e3) { } + + using db::plc::Polygon::set_outside; }; // Tests for Vertex class diff --git a/src/db/unit_tests/dbPLCTriangulationTests.cc b/src/db/unit_tests/dbPLCTriangulationTests.cc index 0d58ffc04..ae8856bb4 100644 --- a/src/db/unit_tests/dbPLCTriangulationTests.cc +++ b/src/db/unit_tests/dbPLCTriangulationTests.cc @@ -33,6 +33,9 @@ #include #include +namespace +{ + class TestableTriangulation : public db::plc::Triangulation { @@ -64,6 +67,8 @@ public: using db::plc::Graph::create_triangle; }; +} + TEST(basic) { db::plc::Graph plc; @@ -343,7 +348,7 @@ TEST(heavy_insert) double y = round (flt_rand () * res) * (1.0 / res); db::plc::Vertex *v = tris.insert_point (x, y); bbox += db::DPoint (x, y); - vmap.insert (std::make_pair (*v, false)); + vmap.insert (std::pair (*v, false)); } // not strictly true, but very likely with at least 10 vertexes: