mirror of https://github.com/KLayout/klayout.git
Fixing issue #1996: Providing a more robust triangulation
This commit is contained in:
parent
a727ed0b1d
commit
6228668fa1
|
|
@ -363,21 +363,33 @@ Triangle::Triangle (TriangleEdge *e1, TriangleEdge *e2, TriangleEdge *e3)
|
|||
}
|
||||
mp_v[2] = mp_e[1]->other (mp_v[1]);
|
||||
|
||||
// establish link to edges
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
TriangleEdge *e = mp_e[i];
|
||||
int side_of = e->side_of (*mp_v[i == 0 ? 2 : i - 1]);
|
||||
// NOTE: in the degenerated case, the triangle is not attached to an edge!
|
||||
if (side_of < 0) {
|
||||
e->set_left (this);
|
||||
} else if (side_of > 0) {
|
||||
e->set_right (this);
|
||||
}
|
||||
// enforce clockwise orientation
|
||||
int s = db::vprod_sign (*mp_v[2] - *mp_v[0], *mp_v[1] - *mp_v[0]);
|
||||
if (s < 0) {
|
||||
std::swap (mp_v[2], mp_v[1]);
|
||||
} else if (s == 0) {
|
||||
// Triangle is not orientable
|
||||
tl_assert (false);
|
||||
}
|
||||
|
||||
// enforce clockwise orientation
|
||||
if (db::vprod_sign (*mp_v[2] - *mp_v[0], *mp_v[1] - *mp_v[0]) < 0) {
|
||||
std::swap (mp_v[2], mp_v[1]);
|
||||
// establish link to edges
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
||||
TriangleEdge *e = mp_e[i];
|
||||
|
||||
unsigned int i1 = 0;
|
||||
for ( ; e->v1 () != mp_v[i1] && i1 < 3; ++i1)
|
||||
;
|
||||
unsigned int i2 = 0;
|
||||
for ( ; e->v2 () != mp_v[i2] && i2 < 3; ++i2)
|
||||
;
|
||||
|
||||
if ((i1 + 1) % 3 == i2) {
|
||||
e->set_right (this);
|
||||
} else {
|
||||
e->set_left (this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -364,12 +364,6 @@ Triangles::insert (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *n
|
|||
|
||||
// the new vertex is outside the domain
|
||||
if (tris.empty ()) {
|
||||
// @@@
|
||||
if (m_is_constrained) {
|
||||
dump("debug.gds"); // @@@
|
||||
find_triangle_for_point (*vertex);
|
||||
}
|
||||
// @@@
|
||||
tl_assert (! m_is_constrained);
|
||||
insert_new_vertex (vertex, new_triangles);
|
||||
return vertex;
|
||||
|
|
@ -397,37 +391,7 @@ Triangles::insert (db::Vertex *vertex, std::list<tl::weak_ptr<db::Triangle> > *n
|
|||
} else if (! on_edges.empty ()) {
|
||||
|
||||
tl_assert (on_edges.size () == size_t (1));
|
||||
// @@@
|
||||
auto v1 = on_edges.front()->v1();
|
||||
auto v2 = on_edges.front()->v2();
|
||||
unsigned int ns1 = 0, ns2 = 0;
|
||||
for (auto e = v1->begin_edges (); e != v1->end_edges (); ++e) {
|
||||
if ((*e)->is_segment()) { ++ns1; }
|
||||
}
|
||||
for (auto e = v2->begin_edges (); e != v2->end_edges (); ++e) {
|
||||
if ((*e)->is_segment()) { ++ns2; }
|
||||
}
|
||||
std::string vs = vertex->to_string();
|
||||
std::string es = on_edges.front()->to_string();
|
||||
if (vs == "(-12.9999999999, 3.50126953125)" && es == "((-13, 3.5328125), (-12.9999999998, 3.4697265625))") {
|
||||
printf("@@@ BANG!\n"); fflush(stdout);
|
||||
}
|
||||
// @@@
|
||||
split_triangles_on_edge (vertex, on_edges.front (), new_triangles);
|
||||
// @@@
|
||||
unsigned int ns1p = 0, ns2p = 0;
|
||||
for (auto e = v1->begin_edges (); e != v1->end_edges (); ++e) {
|
||||
if ((*e)->is_segment()) { ++ns1p; }
|
||||
}
|
||||
for (auto e = v2->begin_edges (); e != v2->end_edges (); ++e) {
|
||||
if ((*e)->is_segment()) { ++ns2p; }
|
||||
}
|
||||
if (ns1 != ns1p || ns2 != ns2p) {
|
||||
printf("@@@ on '%s' '%s' - BANG!\n", vs.c_str(), es.c_str()); fflush(stdout);
|
||||
}
|
||||
tl_assert(ns1 == ns1p);
|
||||
tl_assert(ns2 == ns2p);
|
||||
// @@@
|
||||
return vertex;
|
||||
|
||||
} else if (tris.size () == size_t (1)) {
|
||||
|
|
@ -1638,7 +1602,6 @@ Triangles::refine (const TriangulateParameters ¶meters)
|
|||
if (tl::verbosity () >= parameters.base_verbosity + 10) {
|
||||
tl::info << "Iteration " << nloop << " ..";
|
||||
}
|
||||
printf("@@@ iteration %d ..\n", (int)nloop); fflush(stdout);
|
||||
|
||||
std::list<tl::weak_ptr<db::Triangle> > to_consider;
|
||||
for (auto t = new_triangles.begin (); t != new_triangles.end (); ++t) {
|
||||
|
|
@ -1667,7 +1630,28 @@ Triangles::refine (const TriangulateParameters ¶meters)
|
|||
auto cr = (*t)->circumcircle();
|
||||
auto center = cr.first;
|
||||
|
||||
if ((*t)->contains (center) >= 0) {
|
||||
int s = (*t)->contains (center);
|
||||
if (s >= 0) {
|
||||
|
||||
if (s > 0) {
|
||||
|
||||
double snap = 1e-3;
|
||||
|
||||
// Snap the center to a segment center if "close" to it.
|
||||
// This avoids generating very skinny triangles that can't be fixed as the
|
||||
// segment cannot be flipped. This a part of the issue #1996 problem.
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
if ((*t)->edge (i)->is_segment ()) {
|
||||
auto e = (*t)->edge (i)->edge ();
|
||||
auto c = e.p1 () + e.d () * 0.5;
|
||||
if (c.distance (center) < e.length () * 0.5 * snap - db::epsilon) {
|
||||
center = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (tl::verbosity () >= parameters.base_verbosity + 20) {
|
||||
tl::info << "Inserting in-triangle center " << center.to_string () << " of " << (*t)->to_string (true);
|
||||
|
|
@ -1677,7 +1661,7 @@ Triangles::refine (const TriangulateParameters ¶meters)
|
|||
} else {
|
||||
|
||||
db::Vertex *vstart = 0;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
db::TriangleEdge *edge = (*t)->edge (i);
|
||||
vstart = (*t)->opposite (edge);
|
||||
if (edge->side_of (*vstart) * edge->side_of (center) < 0) {
|
||||
|
|
|
|||
|
|
@ -700,6 +700,9 @@ TEST(triangulate_basic)
|
|||
EXPECT_GT (tri.num_triangles (), size_t (100));
|
||||
EXPECT_LT (tri.num_triangles (), size_t (150));
|
||||
|
||||
// for debugging:
|
||||
// tri.dump ("debug.gds");
|
||||
|
||||
param.min_b = 1.0;
|
||||
param.max_area = 0.1;
|
||||
|
||||
|
|
@ -914,8 +917,8 @@ TEST(triangulate_problematic)
|
|||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GT (tri.num_triangles (), size_t (470));
|
||||
EXPECT_LT (tri.num_triangles (), size_t (490));
|
||||
EXPECT_GT (tri.num_triangles (), size_t (540));
|
||||
EXPECT_LT (tri.num_triangles (), size_t (560));
|
||||
}
|
||||
|
||||
TEST(triangulate_thin)
|
||||
|
|
@ -978,7 +981,7 @@ TEST(triangulate_issue1996)
|
|||
|
||||
db::Triangles::TriangulateParameters param;
|
||||
param.min_b = 0.5;
|
||||
param.max_area = 500.0 * dbu * dbu;
|
||||
param.max_area = 5000.0 * dbu * dbu;
|
||||
|
||||
TestableTriangles tri;
|
||||
db::DCplxTrans trans = db::DCplxTrans (dbu) * db::DCplxTrans (db::DTrans (db::DPoint () - poly.box ().center ()));
|
||||
|
|
@ -990,9 +993,10 @@ TEST(triangulate_issue1996)
|
|||
// tri.dump ("debug.gds");
|
||||
|
||||
for (auto t = tri.begin (); t != tri.end (); ++t) {
|
||||
EXPECT_LE (t->area (), param.max_area);
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GT (tri.num_triangles (), size_t (13000));
|
||||
EXPECT_LT (tri.num_triangles (), size_t (13200));
|
||||
EXPECT_GT (tri.num_triangles (), size_t (128000));
|
||||
EXPECT_LT (tri.num_triangles (), size_t (132000));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue