mirror of https://github.com/KLayout/klayout.git
WIP
This commit is contained in:
parent
82b49dfb77
commit
576eacd0bf
|
|
@ -133,13 +133,13 @@ Vertex::in_circle (const DPoint &point, const DPoint ¢er, double radius)
|
|||
// TriangleEdge implementation
|
||||
|
||||
TriangleEdge::TriangleEdge ()
|
||||
: mp_v1 (0), mp_v2 (0), mp_left (), mp_right (), m_level (0), m_is_segment (false)
|
||||
: mp_v1 (0), mp_v2 (0), mp_left (), mp_right (), m_level (0), m_id (0), m_is_segment (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
TriangleEdge::TriangleEdge (Vertex *v1, Vertex *v2)
|
||||
: mp_v1 (v1), mp_v2 (v2), mp_left (), mp_right (), m_level (0), m_is_segment (false)
|
||||
: mp_v1 (v1), mp_v2 (v2), mp_left (), mp_right (), m_level (0), m_id (0), m_is_segment (false)
|
||||
{
|
||||
v1->m_edges.push_back (this);
|
||||
v2->m_edges.push_back (this);
|
||||
|
|
@ -148,14 +148,12 @@ TriangleEdge::TriangleEdge (Vertex *v1, Vertex *v2)
|
|||
void
|
||||
TriangleEdge::set_left (Triangle *t)
|
||||
{
|
||||
tl_assert (t == 0 || left () == 0);
|
||||
mp_left = t;
|
||||
}
|
||||
|
||||
void
|
||||
TriangleEdge::set_right (Triangle *t)
|
||||
{
|
||||
tl_assert (t == 0 || right () == 0);
|
||||
mp_right = t;
|
||||
}
|
||||
|
||||
|
|
@ -305,13 +303,13 @@ TriangleEdge::has_triangle (const Triangle *t) const
|
|||
// Triangle implementation
|
||||
|
||||
Triangle::Triangle ()
|
||||
: m_is_outside (false), mp_v1 (0), mp_v2 (0), mp_v3 (0)
|
||||
: m_is_outside (false), mp_v1 (0), mp_v2 (0), mp_v3 (0), m_id (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
Triangle::Triangle (TriangleEdge *e1, TriangleEdge *e2, TriangleEdge *e3)
|
||||
: m_is_outside (false), mp_e1 (e1), mp_e2 (e2), mp_e3 (e3)
|
||||
: m_is_outside (false), mp_e1 (e1), mp_e2 (e2), mp_e3 (e3), m_id (0)
|
||||
{
|
||||
mp_v1 = e1->v1 ();
|
||||
mp_v2 = e1->other (mp_v1);
|
||||
|
|
@ -348,6 +346,7 @@ Triangle::Triangle (TriangleEdge *e1, TriangleEdge *e2, TriangleEdge *e3)
|
|||
void
|
||||
Triangle::unlink ()
|
||||
{
|
||||
// @@@ Is this really needed???
|
||||
for (int i = 0; i != 3; ++i) {
|
||||
db::TriangleEdge *e = edge (i);
|
||||
if (e->left () == this) {
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@ public:
|
|||
void set_level (size_t l) { m_level = l; }
|
||||
size_t level () const { return m_level; }
|
||||
|
||||
void set_id (size_t id) { m_id = id; }
|
||||
size_t id () const { return m_id; }
|
||||
|
||||
void set_is_segment (bool is_seg) { m_is_segment = is_seg; }
|
||||
bool is_segment () const { return m_is_segment; }
|
||||
|
||||
|
|
@ -388,6 +391,7 @@ private:
|
|||
Vertex *mp_v1, *mp_v2;
|
||||
tl::weak_ptr<Triangle> mp_left, mp_right;
|
||||
size_t m_level;
|
||||
size_t m_id;
|
||||
bool m_is_segment;
|
||||
|
||||
// no copying
|
||||
|
|
@ -398,6 +402,19 @@ private:
|
|||
void set_right (Triangle *t);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A compare function that compares triangles by ID
|
||||
*
|
||||
* The ID acts as a more predicable unique ID for the object in sets and maps.
|
||||
*/
|
||||
struct TriangleEdgeLessFunc
|
||||
{
|
||||
bool operator () (TriangleEdge *a, TriangleEdge *b) const
|
||||
{
|
||||
return a->id () < b->id ();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class representing a triangle
|
||||
*/
|
||||
|
|
@ -410,6 +427,9 @@ public:
|
|||
|
||||
void unlink ();
|
||||
|
||||
void set_id (size_t id) { m_id = id; }
|
||||
size_t id () const { return m_id; }
|
||||
|
||||
bool is_outside () const { return m_is_outside; }
|
||||
void set_outside (bool o) { m_is_outside = o; }
|
||||
|
||||
|
|
@ -476,12 +496,25 @@ private:
|
|||
bool m_is_outside;
|
||||
tl::weak_ptr<TriangleEdge> mp_e1, mp_e2, mp_e3;
|
||||
db::Vertex *mp_v1, *mp_v2, *mp_v3;
|
||||
size_t m_id;
|
||||
|
||||
// no copying
|
||||
Triangle &operator= (const Triangle &);
|
||||
Triangle (const Triangle &);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A compare function that compares triangles by ID
|
||||
*
|
||||
* The ID acts as a more predicable unique ID for the object in sets and maps.
|
||||
*/
|
||||
struct TriangleLessFunc
|
||||
{
|
||||
bool operator () (Triangle *a, Triangle *b) const
|
||||
{
|
||||
return a->id () < b->id ();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ db::TriangleEdge *
|
|||
Triangles::create_edge (db::Vertex *v1, db::Vertex *v2)
|
||||
{
|
||||
db::TriangleEdge *res = new db::TriangleEdge (v1, v2);
|
||||
res->set_id (++m_id);
|
||||
mp_edges.push_back (res);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -73,6 +74,7 @@ db::Triangle *
|
|||
Triangles::create_triangle (TriangleEdge *e1, TriangleEdge *e2, TriangleEdge *e3)
|
||||
{
|
||||
db::Triangle *res = new db::Triangle (e1, e2, e3);
|
||||
res->set_id (++m_id);
|
||||
mp_triangles.push_back (res);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -180,6 +182,11 @@ Triangles::check (bool check_delaunay) const
|
|||
}
|
||||
}
|
||||
|
||||
if (!e->left () && !e->right ()) {
|
||||
tl::error << "(check error) found orphan edge " << e->to_string (true);
|
||||
res = false;
|
||||
}
|
||||
|
||||
for (auto t = e->begin_triangles (); t != e->end_triangles (); ++t) {
|
||||
if (! t->has_edge (e.operator-> ())) {
|
||||
tl::error << "(check error) edge " << e->to_string (true) << " not found in adjacent triangle " << t->to_string (true);
|
||||
|
|
@ -259,7 +266,9 @@ Triangles::to_layout () const
|
|||
}
|
||||
|
||||
for (auto e = mp_edges.begin (); e != mp_edges.end (); ++e) {
|
||||
top.shapes (l10).insert (dbu_trans * e->edge ());
|
||||
if (e->is_segment ()) {
|
||||
top.shapes (l10).insert (dbu_trans * e->edge ());
|
||||
}
|
||||
}
|
||||
|
||||
return layout;
|
||||
|
|
@ -677,8 +686,7 @@ Triangles::remove_outside_vertex (db::Vertex *vertex, std::vector<db::Triangle *
|
|||
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;
|
||||
std::set<db::Triangle *, TriangleLessFunc> triangles_to_fix;
|
||||
|
||||
bool make_new_triangle = true;
|
||||
|
||||
|
|
@ -695,18 +703,16 @@ Triangles::remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *>
|
|||
}
|
||||
|
||||
// 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 ());
|
||||
triangles_to_fix.erase (to_flip->left ());
|
||||
triangles_to_fix.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);
|
||||
triangles_to_fix.insert (pp.first.first);
|
||||
triangles_to_fix.insert (pp.first.second);
|
||||
|
||||
}
|
||||
|
||||
while (vertex->num_edges () > 3) {
|
||||
if (vertex->num_edges () > 3) {
|
||||
|
||||
tl_assert (vertex->num_edges () == 4);
|
||||
|
||||
|
|
@ -739,10 +745,8 @@ Triangles::remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *>
|
|||
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);
|
||||
triangles_to_fix.insert (t1);
|
||||
triangles_to_fix.insert (t2);
|
||||
|
||||
make_new_triangle = false;
|
||||
|
||||
|
|
@ -755,33 +759,28 @@ Triangles::remove_inside_vertex (db::Vertex *vertex, std::vector<db::Triangle *>
|
|||
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);
|
||||
triangles_to_fix.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);
|
||||
}
|
||||
for (auto t = to_remove.begin (); t != to_remove.end (); ++t) {
|
||||
triangles_to_fix.erase (*t);
|
||||
remove (*t);
|
||||
}
|
||||
|
||||
if (new_triangles_out) {
|
||||
for (auto t = triangles_to_fix.begin (); t != triangles_to_fix.end (); ++t) {
|
||||
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);
|
||||
std::vector<db::Triangle *> to_fix_a (triangles_to_fix.begin (), triangles_to_fix.end ());
|
||||
fix_triangles (to_fix_a, std::vector<db::TriangleEdge *> (), new_triangles_out);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -794,13 +793,13 @@ Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::ve
|
|||
(*e)->set_level (m_level);
|
||||
}
|
||||
|
||||
std::vector<db::TriangleEdge *> queue, todo;
|
||||
std::set<db::TriangleEdge *, TriangleEdgeLessFunc> queue, todo;
|
||||
|
||||
for (auto t = tris.begin (); t != tris.end (); ++t) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
db::TriangleEdge *e = (*t)->edge (i);
|
||||
if (e->level () < m_level && ! e->is_segment ()) {
|
||||
queue.push_back (e);
|
||||
queue.insert (e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -809,7 +808,6 @@ Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::ve
|
|||
|
||||
todo.clear ();
|
||||
todo.swap (queue);
|
||||
std::set<db::TriangleEdge *> queued;
|
||||
|
||||
// NOTE: we cannot be sure that already treated edges will not become
|
||||
// illegal by neighbor edges flipping ..
|
||||
|
|
@ -820,7 +818,7 @@ Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::ve
|
|||
|
||||
if (is_illegal_edge (*e)) {
|
||||
|
||||
queued.erase (*e);
|
||||
queue.erase (*e);
|
||||
|
||||
auto pp = flip (*e);
|
||||
auto t1 = pp.first.first;
|
||||
|
|
@ -837,17 +835,15 @@ Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::ve
|
|||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
db::TriangleEdge *s1 = t1->edge (i);
|
||||
if (s1->level () < m_level && ! s1->is_segment () && queued.find (s1) == queued.end ()) {
|
||||
queue.push_back (s1);
|
||||
queued.insert (s1);
|
||||
if (s1->level () < m_level && ! s1->is_segment ()) {
|
||||
queue.insert (s1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
db::TriangleEdge *s2 = t2->edge (i);
|
||||
if (s2->level () < m_level && ! s2->is_segment () && queued.find (s2) == queued.end ()) {
|
||||
queue.push_back (s2);
|
||||
queued.insert (s2);
|
||||
if (s2->level () < m_level && ! s2->is_segment ()) {
|
||||
queue.insert (s2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -855,14 +851,6 @@ Triangles::fix_triangles (const std::vector<db::Triangle *> &tris, const std::ve
|
|||
|
||||
}
|
||||
|
||||
std::vector<db::TriangleEdge *>::iterator wp = queue.begin ();
|
||||
for (auto e = queue.begin (); e != queue.end (); ++e) {
|
||||
if (queued.find (*e) != queued.end ()) {
|
||||
*wp++ = *e;
|
||||
}
|
||||
}
|
||||
queue.erase (wp, queue.end ());
|
||||
|
||||
}
|
||||
|
||||
return flips;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ private:
|
|||
std::list<db::Vertex> m_vertex_heap;
|
||||
bool m_is_constrained;
|
||||
size_t m_level;
|
||||
size_t m_id;
|
||||
|
||||
db::Vertex *create_vertex (double x, double y);
|
||||
db::Vertex *create_vertex (const db::DPoint &pt);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "dbTriangles.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
|
|
@ -187,7 +189,7 @@ TEST(Triangle_test_heavy_insert)
|
|||
}
|
||||
|
||||
// not strictly true, but very likely with at least 10 vertexes:
|
||||
EXPECT_EQ (tris.num_triangles () >= 1, true);
|
||||
EXPECT_EQ (tris.num_triangles () > 0, true);
|
||||
EXPECT_EQ (tris.bbox ().to_string (), bbox.to_string ());
|
||||
|
||||
bool ok = true;
|
||||
|
|
@ -216,3 +218,59 @@ TEST(Triangle_test_heavy_insert)
|
|||
|
||||
tl::info << tl::endl << "done.";
|
||||
}
|
||||
|
||||
TEST(Triangle_test_heavy_remove)
|
||||
{
|
||||
tl::info << "Running test_heavy_remove " << tl::noendl;
|
||||
|
||||
for (unsigned int l = 0; l < 100; ++l) {
|
||||
|
||||
srand (l);
|
||||
tl::info << "." << tl::noendl;
|
||||
|
||||
db::Triangles tris;
|
||||
double res = 128.0;
|
||||
|
||||
unsigned int n = rand () % 190 + 10;
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
double x = round (flt_rand () * res) * (1.0 / res);
|
||||
double y = round (flt_rand () * res) * (1.0 / res);
|
||||
tris.insert_point (x, y);
|
||||
}
|
||||
|
||||
EXPECT_EQ (tris.check(), true);
|
||||
|
||||
std::set<db::Vertex *> vset;
|
||||
std::vector<db::Vertex *> vertexes;
|
||||
for (auto t = tris.begin (); t != tris.end (); ++t) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
db::Vertex *v = t->vertex (i);
|
||||
if (vset.insert (v).second) {
|
||||
vertexes.push_back (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int loop = 0; // @@@
|
||||
while (! vertexes.empty ()) {
|
||||
++loop; printf("@@@ %d\n", loop); fflush(stdout);
|
||||
if (loop == 38) {
|
||||
printf("@@@BANG!\n"); // @@@
|
||||
}
|
||||
|
||||
unsigned int n = rand () % (unsigned int) vertexes.size ();
|
||||
db::Vertex *v = vertexes [n];
|
||||
tris.remove (v);
|
||||
vertexes.erase (vertexes.begin () + n);
|
||||
|
||||
EXPECT_EQ (tris.check (), true);
|
||||
|
||||
}
|
||||
|
||||
EXPECT_EQ (tris.num_triangles (), size_t (0));
|
||||
|
||||
}
|
||||
|
||||
tl::info << tl::endl << "done.";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue