From 88fd5ad8cac48afae75e6e2b4e421209aaa8711c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 13 Aug 2023 18:13:33 +0200 Subject: [PATCH] WIP --- src/db/db/dbTriangles.cc | 159 ++++++++++++++++---------- src/db/db/dbTriangles.h | 51 +++++---- src/db/unit_tests/dbTrianglesTests.cc | 66 +++++------ 3 files changed, 153 insertions(+), 123 deletions(-) diff --git a/src/db/db/dbTriangles.cc b/src/db/db/dbTriangles.cc index 5ac17e981..d58f2493b 100644 --- a/src/db/db/dbTriangles.cc +++ b/src/db/db/dbTriangles.cc @@ -312,6 +312,12 @@ Triangles::insert_point (const db::DPoint &point, std::vector *n return insert (create_vertex (point), new_triangles); } +db::Vertex * +Triangles::insert_point (db::DCoord x, db::DCoord y, std::vector *new_triangles) +{ + return insert (create_vertex (x, y), new_triangles); +} + db::Vertex * Triangles::insert (db::Vertex *vertex, std::vector *new_triangles) { @@ -443,6 +449,8 @@ Triangles::insert_new_vertex (db::Vertex *vertex, std::vector *n { if (mp_triangles.empty ()) { + tl_assert (m_vertex_heap.size () <= size_t (3)); // fails if vertexes were created but not inserted. + if (m_vertex_heap.size () == 3) { std::vector vv; @@ -1043,6 +1051,94 @@ Triangles::fill_concave_corners (const std::vector &edges) return res; } +std::vector +Triangles::search_edges_crossing (Vertex *from, Vertex *to) +{ + db::Vertex *v = from; + db::Vertex *vv = to; + db::DEdge edge (*from, *to); + + db::Triangle *current_triangle = 0; + db::TriangleEdge *next_edge = 0; + + std::vector result; + + for (auto e = v->begin_edges (); e != v->end_edges () && ! next_edge; ++e) { + for (auto t = e->begin_triangles (); t != e->end_triangles (); ++t) { + db::TriangleEdge *os = t->opposite (v); + if (os->has_vertex (vv)) { + return result; + } + if (os->crosses (edge)) { + result.push_back (os); + current_triangle = t.operator-> (); + next_edge = os; + break; + } + } + } + + tl_assert (current_triangle != 0); + + while (true) { + + current_triangle = next_edge->other (current_triangle); + + // Note that we're convex, so there has to be a path across triangles + tl_assert (current_triangle != 0); + + db::TriangleEdge *cs = next_edge; + next_edge = 0; + for (int i = 0; i < 3; ++i) { + db::TriangleEdge *e = current_triangle->edge (i); + if (e != cs) { + if (e->has_vertex (vv)) { + return result; + } + if (e->crosses (edge)) { + result.push_back (e); + next_edge = e; + break; + } + } + } + + tl_assert (next_edge != 0); + + } +} + +db::Vertex * +Triangles::find_vertex_for_point (const db::DPoint &pt) +{ + db::TriangleEdge *edge = find_closest_edge (pt); + if (!edge) { + return 0; + } + db::Vertex *v = 0; + if (edge->v1 ()->equal (pt)) { + v = edge->v1 (); + } else if (edge->v2 ()->equal (pt)) { + v = edge->v2 (); + } + return v; +} + +db::TriangleEdge * +Triangles::find_edge_for_points (const db::DPoint &p1, const db::DPoint &p2) +{ + db::Vertex *v = find_vertex_for_point (p1); + if (!v) { + return 0; + } + for (auto e = v->begin_edges (); e != v->end_edges (); ++e) { + if (e->other (v)->equal (p2)) { + return const_cast (e.operator-> ()); + } + } + return 0; +} + } #if 0 @@ -1052,69 +1148,6 @@ from .triangle import * class Triangles(object): - def find_edge_for_points(self, p1: Point, p2: Point) -> TriangleEdge: - - v = self.find_vertex_for_point(p1) - if v is None: - return None - for s in v.edges: - if equals(s.other_vertex(v), p2): - return s - return None - - def search_edges_crossing(self, edge: TriangleEdge) -> set: - """ - Finds all edges that cross the given one for a convex triangulation - - Requirements: - * self must be a convex triangulation - * edge must not contain another vertex from the triangulation except p1 and p2 - """ - - v = edge.p1 - vv = edge.p2 - - current_triangle = None - next_edge = None - - result = [] - - for s in v.edges: - for t in [s.left, s.right]: - if t is not None: - os = t.opposite_edge(v) - if os.has_vertex(vv): - return result - if os.crosses(edge): - result.append(os) - current_triangle = t - next_edge = os - break - if next_edge is not None: - break - - assert (current_triangle is not None) - - while True: - - current_triangle = next_edge.other(current_triangle) - - # Note that we're convex, so there has to be a path across triangles - assert (current_triangle is not None) - - cs = next_edge - next_edge = None - for s in current_triangle.edges(): - if s != cs: - if s.has_vertex(vv): - return result - if s.crosses(edge): - result.append(s) - next_edge = s - break - - assert (next_edge is not None) - def _ensure_edge_inner(self, edge: Edge) -> [TriangleEdge]: crossed_edges = self.search_edges_crossing(edge) diff --git a/src/db/db/dbTriangles.h b/src/db/db/dbTriangles.h index d1ed0c8e4..b27d08bc1 100644 --- a/src/db/db/dbTriangles.h +++ b/src/db/db/dbTriangles.h @@ -94,24 +94,6 @@ public: */ db::Layout *to_layout () const; - /** - * @brief Creates a new vertex object - * - * In order to insert the new vertex into the graph, use "insert". - * Normally, "insert_point" should be used which creates a vertex and - * inserts it. - */ - db::Vertex *create_vertex (double x, double y); - - /** - * @brief Creates a new vertex object - * - * In order to insert the new vertex into the graph, use "insert". - * Normally, "insert_point" should be used which creates a vertex and - * inserts it. - */ - db::Vertex *create_vertex (const db::DPoint &pt); - /** * @brief Finds the points within (not "on") a circle of radius "radius" around the given vertex. */ @@ -126,15 +108,12 @@ public: db::Vertex *insert_point (const db::DPoint &point, std::vector *new_triangles = 0); /** - * @brief Inserts the given vertex + * @brief Inserts a new vertex as the given point * * If "new_triangles" is not null, it will receive the list of new triangles created during * the remove step. - * The return value is the actual vertex created. It is no necessarily the one passed. When - * a vertex already exists at the given location, the input vertex is ignored and the present - * vertex is returned. */ - db::Vertex *insert (db::Vertex *vertex, std::vector *new_triangles = 0); + db::Vertex *insert_point (db::DCoord x, db::DCoord y, std::vector *new_triangles = 0); /** * @brief Removes the given vertex @@ -146,8 +125,31 @@ public: // exposed for testing purposes: + + /** + * @brief Flips the given edge + */ std::pair, db::TriangleEdge *> flip (TriangleEdge *edge); + /** + * @brief Finds all edges that cross the given one for a convex triangulation + * + * Requirements: + * * self must be a convex triangulation + * * edge must not contain another vertex from the triangulation except p1 and p2 + */ + std::vector search_edges_crossing (db::Vertex *from, db::Vertex *to); + + /** + * @brief Finds the edge for two given points + */ + db::TriangleEdge *find_edge_for_points (const db::DPoint &p1, const db::DPoint &p2); + + /** + * @brief Finds the vertex for a point + */ + db::Vertex *find_vertex_for_point (const db::DPoint &pt); + private: tl::shared_collection mp_triangles; tl::weak_collection mp_edges; @@ -155,6 +157,8 @@ private: bool m_is_constrained; size_t m_level; + db::Vertex *create_vertex (double x, double y); + db::Vertex *create_vertex (const db::DPoint &pt); db::TriangleEdge *create_edge (db::Vertex *v1, db::Vertex *v2); db::Triangle *create_triangle (db::TriangleEdge *e1, db::TriangleEdge *e2, db::TriangleEdge *e3); void remove (db::Triangle *tri); @@ -170,6 +174,7 @@ private: static bool is_illegal_edge (db::TriangleEdge *edge); std::vector find_triangle_for_point (const db::DPoint &point); db::TriangleEdge *find_closest_edge (const db::DPoint &p, db::Vertex *vstart = 0, bool inside_only = false); + db::Vertex *insert (db::Vertex *vertex, std::vector *new_triangles = 0); void split_triangle (db::Triangle *t, db::Vertex *vertex, std::vector *new_triangles_out); void split_triangles_on_edge (const std::vector &tris, db::Vertex *vertex, db::TriangleEdge *split_edge, std::vector *new_triangles_out); void add_more_triangles (std::vector &new_triangles, diff --git a/src/db/unit_tests/dbTrianglesTests.cc b/src/db/unit_tests/dbTrianglesTests.cc index a293bdc82..4696e4144 100644 --- a/src/db/unit_tests/dbTrianglesTests.cc +++ b/src/db/unit_tests/dbTrianglesTests.cc @@ -61,7 +61,7 @@ TEST(Triangle_insert) db::Triangles tris; tris.init_box (db::DBox (0, 0, 1, 1)); - tris.insert (tris.create_vertex (0.2, 0.2)); + tris.insert_point (0.2, 0.2); EXPECT_EQ (tris.to_string (), "((0, 0), (0, 1), (0.2, 0.2)), ((1, 0), (0, 0), (0.2, 0.2)), ((1, 1), (0.2, 0.2), (0, 1)), ((1, 1), (1, 0), (0.2, 0.2))"); EXPECT_EQ (tris.check (), true); } @@ -71,7 +71,7 @@ TEST(Triangle_split_segment) db::Triangles tris; tris.init_box (db::DBox (0, 0, 1, 1)); - tris.insert (tris.create_vertex (0.5, 0.5)); + tris.insert_point (0.5, 0.5); EXPECT_EQ (tris.to_string (), "((1, 1), (1, 0), (0.5, 0.5)), ((1, 1), (0.5, 0.5), (0, 1)), ((0, 0), (0, 1), (0.5, 0.5)), ((0, 0), (0.5, 0.5), (1, 0))"); EXPECT_EQ (tris.check(), true); } @@ -81,9 +81,9 @@ TEST(Triangle_insert_vertex_twice) db::Triangles tris; tris.init_box (db::DBox (0, 0, 1, 1)); - tris.insert (tris.create_vertex (0.5, 0.5)); + tris.insert_point (0.5, 0.5); // inserted a vertex twice does not change anything - tris.insert (tris.create_vertex (0.5, 0.5)); + tris.insert_point (0.5, 0.5); EXPECT_EQ (tris.to_string (), "((1, 1), (1, 0), (0.5, 0.5)), ((1, 1), (0.5, 0.5), (0, 1)), ((0, 0), (0, 1), (0.5, 0.5)), ((0, 0), (0.5, 0.5), (1, 0))"); EXPECT_EQ (tris.check(), true); } @@ -91,11 +91,11 @@ TEST(Triangle_insert_vertex_twice) TEST(Triangle_insert_vertex_convex) { db::Triangles tris; - tris.insert (tris.create_vertex (0.2, 0.2)); - tris.insert (tris.create_vertex (0.2, 0.8)); - tris.insert (tris.create_vertex (0.6, 0.5)); - tris.insert (tris.create_vertex (0.7, 0.5)); - tris.insert (tris.create_vertex (0.6, 0.4)); + tris.insert_point (0.2, 0.2); + tris.insert_point (0.2, 0.8); + tris.insert_point (0.6, 0.5); + tris.insert_point (0.7, 0.5); + tris.insert_point (0.6, 0.4); EXPECT_EQ (tris.to_string (), "((0.2, 0.2), (0.2, 0.8), (0.6, 0.5)), ((0.7, 0.5), (0.6, 0.5), (0.2, 0.8)), ((0.6, 0.5), (0.6, 0.4), (0.2, 0.2)), ((0.6, 0.5), (0.7, 0.5), (0.6, 0.4))"); EXPECT_EQ (tris.check(), true); } @@ -103,10 +103,10 @@ TEST(Triangle_insert_vertex_convex) TEST(Triangle_insert_vertex_convex2) { db::Triangles tris; - tris.insert (tris.create_vertex (0.25, 0.1)); - tris.insert (tris.create_vertex (0.1, 0.4)); - tris.insert (tris.create_vertex (0.4, 0.15)); - tris.insert (tris.create_vertex (1, 0.7)); + tris.insert_point (0.25, 0.1); + tris.insert_point (0.1, 0.4); + tris.insert_point (0.4, 0.15); + tris.insert_point (1, 0.7); EXPECT_EQ (tris.to_string (), "((0.25, 0.1), (0.1, 0.4), (0.4, 0.15)), ((1, 0.7), (0.4, 0.15), (0.1, 0.4))"); EXPECT_EQ (tris.check(), true); } @@ -114,38 +114,30 @@ TEST(Triangle_insert_vertex_convex2) TEST(Triangle_insert_vertex_convex3) { db::Triangles tris; - tris.insert (tris.create_vertex (0.25, 0.5)); - tris.insert (tris.create_vertex (0.25, 0.55)); - tris.insert (tris.create_vertex (0.15, 0.8)); - tris.insert (tris.create_vertex (1, 0.4)); + tris.insert_point (0.25, 0.5); + tris.insert_point (0.25, 0.55); + tris.insert_point (0.15, 0.8); + tris.insert_point (1, 0.4); EXPECT_EQ (tris.to_string (), "((0.25, 0.5), (0.15, 0.8), (0.25, 0.55)), ((1, 0.4), (0.25, 0.5), (0.25, 0.55)), ((0.15, 0.8), (1, 0.4), (0.25, 0.55))"); EXPECT_EQ (tris.check(), true); } -#if 0 -TEST(Triangle_find_crossing_segments) +TEST(Triangle_search_edges_crossing) { db::Triangles tris; - v1 = tris.create_vertex (0.2, 0.2); - v2 = tris.create_vertex (0.2, 0.8); - v3 = tris.create_vertex (0.6, 0.5); - v4 = tris.create_vertex (0.7, 0.5); - v5 = tris.create_vertex (0.6, 0.4); - v6 = tris.create_vertex (0.7, 0.2); - tris.insert (v1); - tris.insert (v2); - tris.insert (v3); - tris.insert (v4); - tris.insert (v5); - tris.insert (v6); + db::Vertex *v1 = tris.insert_point (0.2, 0.2); + db::Vertex *v2 = tris.insert_point (0.2, 0.8); + db::Vertex *v3 = tris.insert_point (0.6, 0.5); + /*db::Vertex *v4 =*/ tris.insert_point (0.7, 0.5); + db::Vertex *v5 = tris.insert_point (0.6, 0.4); + db::Vertex *v6 = tris.insert_point (0.7, 0.2); EXPECT_EQ (tris.check(), true); - auto xedges = tris.search_edges_crossing (db::DEdge (*v2, *v6)); + auto xedges = tris.search_edges_crossing (v2, v6); EXPECT_EQ (xedges.size (), size_t (2)); - auto s1 = tris.find_edge_for_points (v1, v3); - auto s2 = tris.find_edge_for_points (v1, v5); - EXPECT_EQ (s1 in xedges, true); - EXPECT_EQ (s2 in xedges, true); + auto s1 = tris.find_edge_for_points (*v1, *v3); + auto s2 = tris.find_edge_for_points (*v1, *v5); + EXPECT_EQ (std::find (xedges.begin (), xedges.end (), s1) != xedges.end (), true); + EXPECT_EQ (std::find (xedges.begin (), xedges.end (), s2) != xedges.end (), true); } -#endif