This commit is contained in:
Matthias Koefferlein 2023-08-13 18:13:33 +02:00
parent 745eb9b625
commit 88fd5ad8ca
3 changed files with 153 additions and 123 deletions

View File

@ -312,6 +312,12 @@ Triangles::insert_point (const db::DPoint &point, std::vector<db::Triangle *> *n
return insert (create_vertex (point), new_triangles);
}
db::Vertex *
Triangles::insert_point (db::DCoord x, db::DCoord y, std::vector<db::Triangle *> *new_triangles)
{
return insert (create_vertex (x, y), new_triangles);
}
db::Vertex *
Triangles::insert (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles)
{
@ -443,6 +449,8 @@ Triangles::insert_new_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *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<db::Vertex *> vv;
@ -1043,6 +1051,94 @@ Triangles::fill_concave_corners (const std::vector<db::TriangleEdge *> &edges)
return res;
}
std::vector<db::TriangleEdge *>
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<db::TriangleEdge *> 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 <db::TriangleEdge *>(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)

View File

@ -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<db::Triangle *> *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<db::Triangle *> *new_triangles = 0);
db::Vertex *insert_point (db::DCoord x, db::DCoord y, std::vector<db::Triangle *> *new_triangles = 0);
/**
* @brief Removes the given vertex
@ -146,8 +125,31 @@ public:
// exposed for testing purposes:
/**
* @brief Flips the given edge
*/
std::pair<std::pair<db::Triangle *, db::Triangle *>, 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<db::TriangleEdge *> 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<db::Triangle> mp_triangles;
tl::weak_collection<db::TriangleEdge> 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<db::Triangle *> 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<db::Triangle *> *new_triangles = 0);
void split_triangle (db::Triangle *t, db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles_out);
void split_triangles_on_edge (const std::vector<db::Triangle *> &tris, db::Vertex *vertex, db::TriangleEdge *split_edge, std::vector<db::Triangle *> *new_triangles_out);
void add_more_triangles (std::vector<Triangle *> &new_triangles,

View File

@ -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