This commit is contained in:
Matthias Koefferlein 2023-08-12 19:20:02 +02:00
parent 789ae93b52
commit f86f56fbb0
2 changed files with 149 additions and 127 deletions

View File

@ -309,9 +309,7 @@ Triangles::find_points_around (db::Vertex *vertex, double radius)
db::Vertex *
Triangles::insert_point (const db::DPoint &point, std::vector<db::Triangle *> *new_triangles)
{
// @@@
return insert (create_vertex (point), new_triangles);
}
db::Vertex *
@ -322,14 +320,6 @@ Triangles::insert (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangle
}
void
Triangles::remove (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles)
{
// @@@
}
std::vector<db::Vertex *>
Triangles::find_touching (const db::DBox &box) const
{
@ -360,22 +350,159 @@ Triangles::find_inside_circle (const db::DPoint &center, double radius) const
return res;
}
void
Triangles::remove (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles)
{
if (vertex->is_outside ()) {
remove_outside_vertex (vertex, new_triangles);
} else {
remove_inside_vertex (vertex, new_triangles);
}
}
void
Triangles::remove_outside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles)
Triangles::remove_outside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles_out)
{
auto to_remove = vertex->triangles ();
std::vector<db::TriangleEdge *> outer_edges;
for (auto t = to_remove.begin (); t != to_remove.end (); ++t) {
outer_edges.push_back ((*t)->opposite (vertex));
}
for (auto t = to_remove.begin (); t != to_remove.end (); ++t) {
remove (*t);
}
auto new_triangles = fill_concave_corners (outer_edges);
fix_triangles (new_triangles, std::vector<db::TriangleEdge *> (), new_triangles_out);
}
void
Triangles::remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles_out)
{
std::vector<db::Triangle * > triangles_to_fix;
std::set<db::Triangle * > triangles_to_fix_set;
bool make_new_triangle = true;
while (vertex->num_edges () > 3) {
db::TriangleEdge *to_flip = 0;
for (auto e = vertex->begin_edges (); e != vertex->end_edges () && to_flip == 0; ++e) {
if (e->can_flip ()) {
to_flip = const_cast<db::TriangleEdge *> (e.operator-> ());
}
}
if (! to_flip) {
break;
}
// NOTE: in the "can_join" case zero-area triangles are created which we will sort out later
triangles_to_fix_set.erase (to_flip->left ());
triangles_to_fix_set.erase (to_flip->right ());
auto pp = flip (to_flip);
triangles_to_fix.push_back (pp.first.first);
triangles_to_fix_set.insert (pp.first.first);
triangles_to_fix.push_back (pp.first.second);
triangles_to_fix_set.insert (pp.first.second);
}
while (vertex->num_edges () > 3) {
tl_assert (vertex->num_edges () == 4);
// This case can happen if two edges attached to the vertex are collinear
// in this case choose the "join" strategy
db::TriangleEdge *jseg = 0;
for (auto e = vertex->begin_edges (); e != vertex->end_edges () && !jseg; ++e) {
if (e->can_join_via (vertex)) {
jseg = const_cast <db::TriangleEdge *> (e.operator-> ());
}
}
tl_assert (jseg != 0);
db::Vertex *v1 = jseg->left ()->opposite (jseg);
db::TriangleEdge *s1 = jseg->left ()->opposite (vertex);
db::Vertex *v2 = jseg->right ()->opposite (jseg);
db::TriangleEdge *s2 = jseg->right ()->opposite (vertex);
db::TriangleEdge *jseg_opp = 0;
for (auto e = vertex->begin_edges (); e != vertex->end_edges () && !jseg_opp; ++e) {
if (!e->has_triangle (jseg->left ()) && !e->has_triangle (jseg->right ())) {
jseg_opp = const_cast <db::TriangleEdge *> (e.operator-> ());
}
}
db::TriangleEdge *s1opp = jseg_opp->left ()->opposite (vertex);
db::TriangleEdge *s2opp = jseg_opp->right ()->opposite (vertex);
db::TriangleEdge *new_edge = create_edge (v1, v2);
db::Triangle *t1 = create_triangle (s1, s2, new_edge);
db::Triangle *t2 = create_triangle (s1opp, s2opp, new_edge);
triangles_to_fix.push_back (t1);
triangles_to_fix_set.insert (t1);
triangles_to_fix.push_back (t2);
triangles_to_fix_set.insert (t2);
make_new_triangle = false;
}
auto to_remove = vertex->triangles ();
std::vector<db::TriangleEdge *> outer_edges;
for (auto t = to_remove.begin (); t != to_remove.end (); ++t) {
outer_edges.push_back ((*t)->opposite (vertex));
}
for (auto t = to_remove.begin (); t != to_remove.end (); ++t) {
triangles_to_fix_set.erase (*t);
remove (*t);
}
if (make_new_triangle) {
tl_assert (outer_edges.size () == size_t (3));
db::Triangle *nt = create_triangle (outer_edges[0], outer_edges[1], outer_edges[2]);
triangles_to_fix.push_back (nt);
triangles_to_fix_set.insert (nt);
}
std::vector<Triangle *>::iterator wp = triangles_to_fix.begin ();
for (auto t = triangles_to_fix.begin (); t != triangles_to_fix.end (); ++t) {
if (triangles_to_fix_set.find (*t) != triangles_to_fix_set.end ()) {
*wp++ = *t;
if (new_triangles_out) {
new_triangles_out->push_back (*t);
}
}
}
triangles_to_fix.erase (wp, triangles_to_fix.end ());
fix_triangles (triangles_to_fix, std::vector<db::TriangleEdge *> (), new_triangles_out);
}
void
Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::vector<db::TriangleEdge *> &fixed_edges, std::vector<db::Triangle *> *new_triangles)
{
// @@@
}
std::pair<std::pair<Triangle *, Triangle *>, TriangleEdge *> Triangles::flip(TriangleEdge *edge)
{
// @@@
}
void
Triangles::remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles)
{
// @@@
}
std::vector<db::Triangle *>
Triangles::fill_concave_corners (const std::vector<db::TriangleEdge *> &edges)
@ -513,9 +640,6 @@ from .triangle import *
class Triangles(object):
def insert_point(self, point, new_triangles: [Vertex] = None):
return self.insert(Vertex(point.x, point.y), new_triangles)
def insert(self, vertex, new_triangles: [Vertex] = None):
self.flips = 0
@ -547,110 +671,6 @@ class Triangles(object):
assert(False)
def remove_vertex(self, vertex: Vertex, new_triangles: [Vertex] = None):
if vertex.is_outside():
self._remove_outside_vertex(vertex, new_triangles)
else:
self._remove_inside_vertex(vertex, new_triangles)
def _remove_outside_vertex(self, vertex: Vertex, new_triangles_out: [Vertex] = None):
to_remove = vertex.triangles()
outer_edges = [ t.opposite_edge(vertex) for t in to_remove ]
for t in to_remove:
self.triangles.remove(t)
t.unlink()
self.vertexes.remove(vertex)
vertex.unlink()
new_triangles = self._fill_concave_corners(outer_edges)
for nt in new_triangles:
self.triangles.append(nt)
self._fix_triangles(new_triangles, [], new_triangles_out)
def _remove_inside_vertex(self, vertex: Vertex, new_triangles: [Vertex] = None):
triangles_to_fix = []
make_new_triangle = True
while len(vertex.edges) > 3:
to_flip = next((s for s in vertex.edges if s.can_flip()), None)
if to_flip is None:
break
# NOTE: in the "can_join" case zero-area triangles are created which we will sort out later
any_flipped = True
if to_flip.left in triangles_to_fix:
triangles_to_fix.remove(to_flip.left)
if to_flip.right in triangles_to_fix:
triangles_to_fix.remove(to_flip.right)
t1, t2, _ = self.flip(to_flip)
triangles_to_fix.append(t1)
triangles_to_fix.append(t2)
if len(vertex.edges) > 3:
assert(len(vertex.edges) == 4)
# This case can happen if two edges attached to the vertex are collinear
# in this case choose the "join" strategy
jseg = next((s for s in vertex.edges if s.can_join_via(vertex)), None)
assert(jseg is not None)
v1 = jseg.left.ext_vertex(jseg)
s1 = jseg.left.opposite_edge(vertex)
v2 = jseg.right.ext_vertex(jseg)
s2 = jseg.right.opposite_edge(vertex)
jseg_opp = next((s for s in vertex.edges if not s.has_triangle(jseg.left) and not s.has_triangle(jseg.right)), None)
assert(jseg_opp is not None)
s1opp = jseg_opp.left.opposite_edge(vertex)
s2opp = jseg_opp.right.opposite_edge(vertex)
new_edge = TriangleEdge(v1, v2)
t1 = Triangle(s1, s2, new_edge)
self.triangles.append(t1)
t2 = Triangle(s1opp, s2opp, new_edge)
self.triangles.append(t2)
triangles_to_fix.append(t1)
triangles_to_fix.append(t2)
make_new_triangle = False
to_remove = vertex.triangles()
outer_edges = [ t.opposite_edge(vertex) for t in to_remove ]
for t in to_remove:
self.triangles.remove(t)
t.unlink()
if t in triangles_to_fix:
triangles_to_fix.remove(t)
self.vertexes.remove(vertex)
vertex.unlink()
if make_new_triangle:
assert(len(outer_edges) == 3)
nt = Triangle(*outer_edges)
self.triangles.append(nt)
triangles_to_fix.append(nt)
if new_triangles is not None:
new_triangles += triangles_to_fix
self._fix_triangles(triangles_to_fix, [], new_triangles)
def _fill_concave_corners(self, edges: [TriangleEdge]) -> [Triangle]:

View File

@ -77,8 +77,10 @@ private:
db::Layout *to_layout () const;
void remove_outside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles = 0);
void remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles = 0);
void remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *> *new_triangles_out = 0);
std::vector<db::Triangle *> fill_concave_corners (const std::vector<TriangleEdge *> &edges);
void fix_triangles (const std::vector<db::Triangle *> &tris, const std::vector<db::TriangleEdge *> &fixed_edges, std::vector<db::Triangle *> *new_triangles);
std::pair<std::pair<db::Triangle *, db::Triangle *>, db::TriangleEdge *> flip (TriangleEdge *edge);
};
}