mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-01 10:27:53 +02:00
Fixing issue #2429 by introducing a rectangular envelope for triangulation
Previously the algorithm tried to dynamically build a convex envelope. However, in case of the #2429 polygon, this rendered extremely skinny triangles which could not be removed. These caused numerical issues.
This commit is contained in:
+4
-4
@@ -903,10 +903,10 @@ Graph::bbox () const
|
||||
}
|
||||
|
||||
db::Layout *
|
||||
Graph::to_layout (bool decompose_by_id) const
|
||||
Graph::to_layout (bool decompose_by_id, double dbu) const
|
||||
{
|
||||
db::Layout *layout = new db::Layout ();
|
||||
layout->dbu (0.001);
|
||||
layout->dbu (dbu);
|
||||
|
||||
auto dbu_trans = db::CplxTrans (layout->dbu ()).inverted ();
|
||||
|
||||
@@ -950,9 +950,9 @@ Graph::to_layout (bool decompose_by_id) const
|
||||
}
|
||||
|
||||
void
|
||||
Graph::dump (const std::string &path, bool decompose_by_id) const
|
||||
Graph::dump (const std::string &path, bool decompose_by_id, double dbu) const
|
||||
{
|
||||
std::unique_ptr<db::Layout> ly (to_layout (decompose_by_id));
|
||||
std::unique_ptr<db::Layout> ly (to_layout (decompose_by_id, dbu));
|
||||
|
||||
tl::OutputStream stream (path);
|
||||
|
||||
|
||||
+2
-2
@@ -879,13 +879,13 @@ public:
|
||||
* according to bit 0, 1 and 2 of the ID (useful with the 'mark_polygons'
|
||||
* flat in TriangulateParameters).
|
||||
*/
|
||||
void dump (const std::string &path, bool decompose_by_id = false) const;
|
||||
void dump (const std::string &path, bool decompose_by_id = false, double dbu = 0.001) const;
|
||||
|
||||
/**
|
||||
* @brief Creates a new layout object representing the polygon graph
|
||||
* This method is for testing purposes mainly.
|
||||
*/
|
||||
db::Layout *to_layout (bool decompose_by_id = false) const;
|
||||
db::Layout *to_layout (bool decompose_by_id = false, double dbu = 0.001) const;
|
||||
|
||||
protected:
|
||||
Vertex *create_vertex (double x, double y);
|
||||
|
||||
@@ -42,9 +42,6 @@ static inline bool is_equal (const db::DPoint &a, const db::DPoint &b)
|
||||
std::abs (a.y () - b.y ()) < std::max (1.0, (std::abs (a.y ()) + std::abs (b.y ()))) * db::epsilon;
|
||||
}
|
||||
|
||||
// distance of point to vertex to be considered "on edge vertex" relative to edge length involved
|
||||
const double snap_to_edge_vertex = 1e-5;
|
||||
|
||||
// distance of point to edge center to be considered "on edge center" relative to edge length involved
|
||||
const double snap_to_edge_center = 1e-3;
|
||||
|
||||
@@ -252,7 +249,6 @@ Triangulation::insert (Vertex *vertex, std::list<tl::weak_ptr<Polygon> > *new_tr
|
||||
|
||||
if (on_edge) {
|
||||
|
||||
// double snap_range = std::max (db::epsilon, snap_to_edge_vertex * e->length ()); @@@
|
||||
double snap_range = std::max (db::epsilon, snap * on_edge->length ());
|
||||
|
||||
if (snap > 0.0 ? vertex->distance (*on_edge->v1 ()) < snap_range : is_equal (*vertex, *on_edge->v1 ())) {
|
||||
@@ -1142,17 +1138,23 @@ static bool is_touching (const db::DEdge &a, const db::DEdge &b)
|
||||
std::vector<Edge *>
|
||||
Triangulation::ensure_edge_inner (Vertex *from, Vertex *to)
|
||||
{
|
||||
auto crossed_edges = search_edges_crossing (from, to);
|
||||
std::vector<Edge *> result;
|
||||
|
||||
// check if there is an edge already
|
||||
Edge *already_there = find_edge_for_points (*from, *to);
|
||||
if (already_there) {
|
||||
result.push_back (already_there);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto crossed_edges = search_edges_crossing (from, to);
|
||||
|
||||
db::DEdge dedge (*from , *to);
|
||||
|
||||
if (crossed_edges.empty ()) {
|
||||
|
||||
// no crossing edge - there should be a edge already
|
||||
Edge *res = find_edge_for_points (*from, *to);
|
||||
tl_assert (res != 0);
|
||||
result.push_back (res);
|
||||
tl_assert (false);
|
||||
|
||||
} else if (crossed_edges.size () == 1 && ! is_touching (dedge, crossed_edges.front ()->edge ())) {
|
||||
|
||||
@@ -1173,7 +1175,7 @@ Triangulation::ensure_edge_inner (Vertex *from, Vertex *to)
|
||||
db::DPoint p = (*e)->intersection_point (dedge);
|
||||
double dp = fabs ((p - *from).sq_length () - l_half);
|
||||
if (d < 0.0 || dp < d) {
|
||||
dp = d;
|
||||
d = dp;
|
||||
split_point = p;
|
||||
split_edge = *e;
|
||||
}
|
||||
@@ -1380,14 +1382,8 @@ void
|
||||
Triangulation::make_contours (const Poly &poly, const Trans &trans, std::vector<std::vector<Vertex *> > &edge_contours)
|
||||
{
|
||||
edge_contours.push_back (std::vector<Vertex *> ());
|
||||
// @@@int id = 0; // @@@
|
||||
for (auto pt = poly.begin_hull (); pt != poly.end_hull (); ++pt) {
|
||||
// @@@if (id == 27) { // @@@
|
||||
// @@@tl::info << "@@@ BANG!"; // @@@
|
||||
// @@@} // @@@
|
||||
// @@@ edge_contours.back ().push_back (insert_point (trans * *pt, 0, snap_to_edge_vertex));
|
||||
edge_contours.back ().push_back (insert_point (trans * *pt));
|
||||
// @@@++id; mp_graph->dump ("xxx" + tl::to_string(id) + ".gds"); tl::info << "@@@ xxx" << id; // @@@
|
||||
}
|
||||
|
||||
for (unsigned int h = 0; h < poly.holes (); ++h) {
|
||||
@@ -1404,6 +1400,9 @@ template DB_PUBLIC void Triangulation::make_contours (const db::DPolygon &, cons
|
||||
void
|
||||
Triangulation::create_constrained_delaunay (const db::Region ®ion, const CplxTrans &trans)
|
||||
{
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::Polygon (region.bbox ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
|
||||
for (auto p = region.begin_merged (); ! p.at_end (); ++p) {
|
||||
@@ -1416,6 +1415,9 @@ Triangulation::create_constrained_delaunay (const db::Region ®ion, const Cplx
|
||||
void
|
||||
Triangulation::create_constrained_delaunay (const db::Polygon &p, const CplxTrans &trans)
|
||||
{
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::Polygon (p.box ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (p, trans, edge_contours);
|
||||
|
||||
@@ -1425,6 +1427,9 @@ Triangulation::create_constrained_delaunay (const db::Polygon &p, const CplxTran
|
||||
void
|
||||
Triangulation::create_constrained_delaunay (const db::DPolygon &p, const DCplxTrans &trans)
|
||||
{
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::DPolygon (p.box ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (p, trans, edge_contours);
|
||||
|
||||
@@ -1493,6 +1498,9 @@ Triangulation::triangulate (const db::Region ®ion, const std::vector<db::Poin
|
||||
|
||||
clear ();
|
||||
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::Polygon (region.bbox ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
for (auto p = region.begin_merged (); ! p.at_end (); ++p) {
|
||||
make_contours (*p, trans, edge_contours);
|
||||
@@ -1522,6 +1530,9 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
|
||||
|
||||
clear ();
|
||||
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::Polygon (poly.box ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (poly, trans, edge_contours);
|
||||
|
||||
@@ -1547,6 +1558,9 @@ Triangulation::triangulate (const db::Polygon &poly, const std::vector<db::Point
|
||||
|
||||
clear ();
|
||||
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::Polygon (poly.box ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (poly, trans, edge_contours);
|
||||
|
||||
@@ -1572,6 +1586,9 @@ Triangulation::triangulate (const db::DPolygon &poly, const std::vector<db::DPoi
|
||||
|
||||
clear ();
|
||||
|
||||
std::vector<std::vector<Vertex *> > box_contours;
|
||||
make_contours (db::DPolygon (poly.box ()), trans, box_contours);
|
||||
|
||||
std::vector<std::vector<Vertex *> > edge_contours;
|
||||
make_contours (poly, trans, edge_contours);
|
||||
|
||||
|
||||
@@ -896,8 +896,8 @@ TEST(triangulate_geo)
|
||||
}
|
||||
|
||||
EXPECT_LT (n_skinny, size_t (20));
|
||||
EXPECT_GT (plc.num_polygons (), size_t (29000));
|
||||
EXPECT_LT (plc.num_polygons (), size_t (30000));
|
||||
EXPECT_GT (plc.num_polygons (), size_t (30000));
|
||||
EXPECT_LT (plc.num_polygons (), size_t (30200));
|
||||
}
|
||||
|
||||
TEST(triangulate_analytic)
|
||||
@@ -951,8 +951,8 @@ TEST(triangulate_analytic)
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GT (plc.num_polygons (), size_t (1250));
|
||||
EXPECT_LT (plc.num_polygons (), size_t (1300));
|
||||
EXPECT_GT (plc.num_polygons (), size_t (1300));
|
||||
EXPECT_LT (plc.num_polygons (), size_t (1340));
|
||||
}
|
||||
|
||||
TEST(triangulate_problematic)
|
||||
@@ -1116,26 +1116,74 @@ TEST(triangulate_issue_2429)
|
||||
|
||||
double dbu = 1.0;
|
||||
|
||||
db::plc::TriangulationParameters param;
|
||||
param.min_b = 0.3;
|
||||
param.max_area = 500.0; // @@@
|
||||
{
|
||||
db::plc::TriangulationParameters param;
|
||||
param.min_b = 0.3;
|
||||
param.max_area = 0.0;
|
||||
|
||||
db::plc::Graph plc;
|
||||
TestableTriangulation tri (&plc);
|
||||
db::DCplxTrans trans = db::DCplxTrans (dbu) * db::DCplxTrans (db::DTrans (db::DPoint () - poly.box ().center ()));
|
||||
tri.triangulate (trans * poly, param);
|
||||
db::plc::Graph plc;
|
||||
TestableTriangulation tri (&plc);
|
||||
db::DCplxTrans trans = db::DCplxTrans (dbu) * db::DCplxTrans (db::DTrans (db::DPoint () - poly.box ().center ()));
|
||||
tri.triangulate (trans * poly, param);
|
||||
|
||||
EXPECT_EQ (tri.check (false), true);
|
||||
EXPECT_EQ (tri.check (false), true);
|
||||
|
||||
// for debugging:
|
||||
// tri.dump ("debug.gds");
|
||||
// for debugging:
|
||||
// tri.dump ("debug.gds");
|
||||
|
||||
for (auto t = plc.begin (); t != plc.end (); ++t) {
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
for (auto t = plc.begin (); t != plc.end (); ++t) {
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GE (plc.num_polygons (), size_t (65));
|
||||
EXPECT_LE (plc.num_polygons (), size_t (67));
|
||||
}
|
||||
|
||||
EXPECT_GE (plc.num_polygons (), size_t (70));
|
||||
EXPECT_LE (plc.num_polygons (), size_t (72));
|
||||
{
|
||||
db::plc::TriangulationParameters param;
|
||||
param.min_b = 0.3;
|
||||
param.max_area = 500.0;
|
||||
|
||||
db::plc::Graph plc;
|
||||
TestableTriangulation tri (&plc);
|
||||
db::DCplxTrans trans = db::DCplxTrans (dbu) * db::DCplxTrans (db::DTrans (db::DPoint () - poly.box ().center ()));
|
||||
tri.triangulate (trans * poly, param);
|
||||
|
||||
EXPECT_EQ (tri.check (false), true);
|
||||
|
||||
// for debugging:
|
||||
// tri.dump ("debug.gds");
|
||||
|
||||
for (auto t = plc.begin (); t != plc.end (); ++t) {
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GE (plc.num_polygons (), size_t (94));
|
||||
EXPECT_LE (plc.num_polygons (), size_t (96));
|
||||
}
|
||||
|
||||
{
|
||||
db::plc::TriangulationParameters param;
|
||||
param.min_b = 0.9;
|
||||
param.max_area = 50.0;
|
||||
|
||||
db::plc::Graph plc;
|
||||
TestableTriangulation tri (&plc);
|
||||
db::DCplxTrans trans = db::DCplxTrans (dbu) * db::DCplxTrans (db::DTrans (db::DPoint () - poly.box ().center ()));
|
||||
tri.triangulate (trans * poly, param);
|
||||
|
||||
EXPECT_EQ (tri.check (false), true);
|
||||
|
||||
// for debugging:
|
||||
// tri.dump ("debug.gds");
|
||||
|
||||
for (auto t = plc.begin (); t != plc.end (); ++t) {
|
||||
EXPECT_GE (t->b (), param.min_b);
|
||||
}
|
||||
|
||||
EXPECT_GE (plc.num_polygons (), size_t (670));
|
||||
EXPECT_LE (plc.num_polygons (), size_t (676));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(triangulate_with_vertexes)
|
||||
|
||||
@@ -357,7 +357,7 @@ TEST(extraction_meander)
|
||||
rex.extract (poly, vertex_ports, polygon_ports, rn);
|
||||
|
||||
EXPECT_EQ (rn.to_string (),
|
||||
"R V0 V1 8.61417" // what is the "real" value?
|
||||
"R V0 V1 8.60459" // what is the "real" value?
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user