mirror of https://github.com/KLayout/klayout.git
Some test updates
* Generalized Polygon to edge interaction into db::Polygon tools * Added tests for this * Equipped region to edges interaction with this feature to reduce random test fails * Multiple (reproducible) seeds for Region tests * More tolerances for TilingProcessor tests * ICplxTrans is_unity? implementation is using proper double tolerances now * File watcher tests wait longer to allow for slow response on loaded Windows build server
This commit is contained in:
parent
4ec8a838d5
commit
a6723a8155
|
|
@ -27,6 +27,7 @@
|
|||
#include "dbLayoutUtils.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbBoxScanner.h"
|
||||
#include "dbPolygonTools.h"
|
||||
|
||||
#include "tlIntervalMap.h"
|
||||
#include "tlVariant.h"
|
||||
|
|
@ -667,25 +668,10 @@ public:
|
|||
}
|
||||
|
||||
if (e && p && m_seen.find (e) == m_seen.end ()) {
|
||||
|
||||
// A polygon and an edge interact if the edge is either inside completely
|
||||
// of at least one edge of the polygon intersects with the edge
|
||||
bool interacts = false;
|
||||
if (p->box ().contains (e->p1 ()) && db::inside_poly (p->begin_edge (), e->p1 ()) >= 0) {
|
||||
interacts = true;
|
||||
} else {
|
||||
for (db::Polygon::polygon_edge_iterator pe = p->begin_edge (); ! pe.at_end () && ! interacts; ++pe) {
|
||||
if ((*pe).intersect (*e)) {
|
||||
interacts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interacts) {
|
||||
if (db::interact (*p, *e)) {
|
||||
m_seen.insert (e);
|
||||
mp_output->insert (*e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -325,6 +325,27 @@ bool interact_pp (const Polygon1 &poly1, const Polygon2 &poly2)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines whether a polygon and an edge share at least one common point.
|
||||
*/
|
||||
template <class Polygon, class Edge>
|
||||
bool interact_pe (const Polygon &poly, const Edge &edge)
|
||||
{
|
||||
// A polygon and an edge interact if the edge is either inside completely
|
||||
// of at least one edge of the polygon intersects with the edge
|
||||
if (poly.box ().contains (edge.p1 ()) && db::inside_poly (poly.begin_edge (), edge.p1 ()) >= 0) {
|
||||
return true;
|
||||
} else {
|
||||
for (typename Polygon::polygon_edge_iterator pe = poly.begin_edge (); ! pe.at_end (); ++pe) {
|
||||
if ((*pe).intersect (edge)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Some specializations that map all combinations to template versions
|
||||
inline bool interact (const db::Box &box1, const db::Box &box2) { return box1.touches (box2); }
|
||||
inline bool interact (const db::DBox &box1, const db::DBox &box2) { return box1.touches (box2); }
|
||||
|
|
@ -332,6 +353,10 @@ inline bool interact (const db::Polygon &poly, const db::Box &box)
|
|||
inline bool interact (const db::SimplePolygon &poly, const db::Box &box) { return interact_pb (poly, box); }
|
||||
inline bool interact (const db::DPolygon &poly, const db::DBox &box) { return interact_pb (poly, box); }
|
||||
inline bool interact (const db::DSimplePolygon &poly, const db::DBox &box) { return interact_pb (poly, box); }
|
||||
inline bool interact (const db::Polygon &poly, const db::Edge &edge) { return interact_pe (poly, edge); }
|
||||
inline bool interact (const db::SimplePolygon &poly, const db::Edge &edge) { return interact_pe (poly, edge); }
|
||||
inline bool interact (const db::DPolygon &poly, const db::DEdge &edge) { return interact_pe (poly, edge); }
|
||||
inline bool interact (const db::DSimplePolygon &poly, const db::DEdge &edge) { return interact_pe (poly, edge); }
|
||||
inline bool interact (const db::Polygon &poly1, const db::Polygon &poly2) { return interact_pp (poly1, poly2); }
|
||||
inline bool interact (const db::SimplePolygon &poly1, const db::Polygon &poly2) { return interact_pp (poly1, poly2); }
|
||||
inline bool interact (const db::Polygon &poly1, const db::SimplePolygon &poly2) { return interact_pp (poly1, poly2); }
|
||||
|
|
|
|||
|
|
@ -1770,8 +1770,7 @@ public:
|
|||
if (fabs (m_cos - 1.0) > eps_f ()) {
|
||||
return false;
|
||||
}
|
||||
return fabs (m_u.x ()) <= db::epsilon_f<F> () &&
|
||||
fabs (m_u.y ()) <= db::epsilon_f<F> ();
|
||||
return disp ().equal (displacement_type ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "utHead.h"
|
||||
|
||||
#include "dbEdges.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbRegion.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
|
@ -378,57 +379,64 @@ TEST(8)
|
|||
|
||||
TEST(9)
|
||||
{
|
||||
for (int pass = 0; pass < 10; ++pass) {
|
||||
for (unsigned int seed = 1; seed < 20; ++seed) {
|
||||
|
||||
int d = pass >= 5 ? 10 : 1000;
|
||||
srand(seed);
|
||||
|
||||
db::Edges e;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
e.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e.insert (db::Edge (p, p));
|
||||
}
|
||||
for (int pass = 0; pass < 10; ++pass) {
|
||||
|
||||
db::Edges e2;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
e2.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e2.insert (db::Edge (p, p));
|
||||
}
|
||||
int d = pass >= 5 ? 10 : 1000;
|
||||
|
||||
std::set<db::Edge> ea, eb;
|
||||
db::Edges e;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
e.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e.insert (db::Edge (p, p));
|
||||
}
|
||||
|
||||
e.set_merged_semantics (false);
|
||||
db::Edges ia = e.selected_interacting (e2);
|
||||
for (db::Edges::const_iterator i = ia.begin (); ! i.at_end (); ++i) {
|
||||
ea.insert (*i);
|
||||
}
|
||||
db::Edges e2;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
e2.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e2.insert (db::Edge (p, p));
|
||||
}
|
||||
|
||||
EXPECT_NE (ea.size (), size_t (0));
|
||||
std::set<db::Edge> ea, eb;
|
||||
|
||||
// brute force
|
||||
for (db::Edges::const_iterator i = e.begin (); ! i.at_end (); ++i) {
|
||||
for (db::Edges::const_iterator j = e2.begin (); ! j.at_end (); ++j) {
|
||||
if (i->intersect (*j)) {
|
||||
eb.insert (*i);
|
||||
e.set_merged_semantics (false);
|
||||
db::Edges ia = e.selected_interacting (e2);
|
||||
for (db::Edges::const_iterator i = ia.begin (); ! i.at_end (); ++i) {
|
||||
ea.insert (*i);
|
||||
}
|
||||
|
||||
EXPECT_NE (ea.size (), size_t (0));
|
||||
|
||||
// brute force
|
||||
for (db::Edges::const_iterator i = e.begin (); ! i.at_end (); ++i) {
|
||||
for (db::Edges::const_iterator j = e2.begin (); ! j.at_end (); ++j) {
|
||||
if (i->intersect (*j)) {
|
||||
eb.insert (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ea != eb) {
|
||||
tl::info << "In implementation but not in brute-force:";
|
||||
for (std::set<db::Edge>::const_iterator i = ea.begin (); i != ea.end (); ++i) {
|
||||
if (eb.find (*i) == eb.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
if (ea != eb) {
|
||||
tl::info << "Seed = " << seed;
|
||||
tl::info << "In implementation but not in brute-force:";
|
||||
for (std::set<db::Edge>::const_iterator i = ea.begin (); i != ea.end (); ++i) {
|
||||
if (eb.find (*i) == eb.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
}
|
||||
}
|
||||
}
|
||||
tl::info << "In brute-force but not in implementation:";
|
||||
for (std::set<db::Edge>::const_iterator i = eb.begin (); i != eb.end (); ++i) {
|
||||
if (ea.find (*i) == ea.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
tl::info << "In brute-force but not in implementation:";
|
||||
for (std::set<db::Edge>::const_iterator i = eb.begin (); i != eb.end (); ++i) {
|
||||
if (ea.find (*i) == ea.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
}
|
||||
}
|
||||
EXPECT_EQ (true, false);
|
||||
}
|
||||
EXPECT_EQ (true, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -436,64 +444,70 @@ TEST(9)
|
|||
|
||||
TEST(10)
|
||||
{
|
||||
for (int pass = 0; pass < 10; ++pass) {
|
||||
for (unsigned int seed = 1; seed < 20; ++seed) {
|
||||
|
||||
int d = pass >= 5 ? 10 : 1000;
|
||||
srand(seed);
|
||||
|
||||
db::Edges e;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
e.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e.insert (db::Edge (p, p));
|
||||
}
|
||||
for (int pass = 0; pass < 10; ++pass) {
|
||||
|
||||
db::Region r;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
db::Box b;
|
||||
do {
|
||||
b = db::Box (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d));
|
||||
} while (b.width () == 0 || b.height () == 0);
|
||||
r.insert (b);
|
||||
}
|
||||
int d = pass >= 5 ? 10 : 1000;
|
||||
|
||||
std::set<db::Edge> ea, eb;
|
||||
db::Edges e;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
e.insert (db::Edge (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d)));
|
||||
db::Point p (abs (rand ()) % d, abs (rand ()) % d);
|
||||
e.insert (db::Edge (p, p));
|
||||
}
|
||||
|
||||
e.set_merged_semantics (false);
|
||||
db::Edges ia = e.selected_interacting (r);
|
||||
for (db::Edges::const_iterator i = ia.begin (); ! i.at_end (); ++i) {
|
||||
ea.insert (*i);
|
||||
}
|
||||
db::Region r;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
db::Box b;
|
||||
do {
|
||||
b = db::Box (db::Point (abs (rand ()) % d, abs (rand ()) % d), db::Point (abs (rand ()) % d, abs (rand ()) % d));
|
||||
} while (b.width () == 0 || b.height () == 0);
|
||||
r.insert (b);
|
||||
}
|
||||
|
||||
EXPECT_NE (ea.size (), size_t (0));
|
||||
std::set<db::Edge> ea, eb;
|
||||
|
||||
// brute force
|
||||
for (db::Edges::const_iterator i = e.begin (); ! i.at_end (); ++i) {
|
||||
for (db::Region::const_iterator j = r.begin (); ! j.at_end (); ++j) {
|
||||
// Use the enlarged edges and box to avoid rounding issues
|
||||
if (i->transformed (db::ICplxTrans (10.0)).clipped (j->box ().transformed (db::ICplxTrans (10.0))).first) {
|
||||
eb.insert (*i);
|
||||
e.set_merged_semantics (false);
|
||||
db::Edges ia = e.selected_interacting (r);
|
||||
for (db::Edges::const_iterator i = ia.begin (); ! i.at_end (); ++i) {
|
||||
ea.insert (*i);
|
||||
}
|
||||
|
||||
EXPECT_NE (ea.size (), size_t (0));
|
||||
|
||||
// brute force
|
||||
for (db::Edges::const_iterator i = e.begin (); ! i.at_end (); ++i) {
|
||||
for (db::Region::const_iterator j = r.begin (); ! j.at_end (); ++j) {
|
||||
if (db::interact (*j, *i)) {
|
||||
eb.insert (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ea != eb) {
|
||||
tl::info << "Boxes:";
|
||||
for (db::Region::const_iterator j = r.begin (); ! j.at_end (); ++j) {
|
||||
tl::info << " " << j->to_string ();
|
||||
}
|
||||
tl::info << "In implementation but not in brute-force:";
|
||||
for (std::set<db::Edge>::const_iterator i = ea.begin (); i != ea.end (); ++i) {
|
||||
if (eb.find (*i) == eb.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
if (ea != eb) {
|
||||
tl::info << "Seed = " << seed;
|
||||
tl::info << "Boxes:";
|
||||
for (db::Region::const_iterator j = r.begin (); ! j.at_end (); ++j) {
|
||||
tl::info << " " << j->to_string ();
|
||||
}
|
||||
}
|
||||
tl::info << "In brute-force but not in implementation:";
|
||||
for (std::set<db::Edge>::const_iterator i = eb.begin (); i != eb.end (); ++i) {
|
||||
if (ea.find (*i) == ea.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
tl::info << "In implementation but not in brute-force:";
|
||||
for (std::set<db::Edge>::const_iterator i = ea.begin (); i != ea.end (); ++i) {
|
||||
if (eb.find (*i) == eb.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
}
|
||||
}
|
||||
tl::info << "In brute-force but not in implementation:";
|
||||
for (std::set<db::Edge>::const_iterator i = eb.begin (); i != eb.end (); ++i) {
|
||||
if (ea.find (*i) == ea.end ()) {
|
||||
tl::info << " " << i->to_string ();
|
||||
}
|
||||
}
|
||||
EXPECT_EQ (true, false);
|
||||
}
|
||||
EXPECT_EQ (true, false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ TEST(9d)
|
|||
|
||||
TEST(10)
|
||||
{
|
||||
// Simple test for polygon-box interaction (integer coordinates)
|
||||
// Simple test for polygon-box/edge interaction (integer coordinates)
|
||||
db::Polygon poly;
|
||||
db::Point p[] = {
|
||||
db::Point (0, 100),
|
||||
|
|
@ -613,6 +613,21 @@ TEST(10)
|
|||
};
|
||||
poly.assign_hull (p, p + sizeof (p) / sizeof (p[0]));
|
||||
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, -10, -1, -1)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, -10, 0, 0)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, -10, 1, 1)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, -10, 20, 10)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, -10, 10, 20)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (10, 20, 20, 30)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (10, 20, 15, 25)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (30, 10, 40, 20)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (30, 20, 40, 50)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, 20, 0, 30)), true);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, 20, -5, 30)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, 100, -5, 110)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, 100, 0, 110)), false);
|
||||
EXPECT_EQ (interact (poly, db::Edge (-10, 100, 5, 100)), true);
|
||||
|
||||
EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, 100, 5, 110)), true);
|
||||
EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, -10, 110, 110)), true);
|
||||
EXPECT_EQ (interact (db::Box (0, 0, 100, 100), db::Box (-10, -10, 50, 110)), true);
|
||||
|
|
@ -677,7 +692,7 @@ TEST(10)
|
|||
|
||||
TEST(11)
|
||||
{
|
||||
// Simple test for polygon-box interaction (integer coordinates)
|
||||
// Simple test for polygon-box interaction (double coordinates)
|
||||
db::DPolygon poly;
|
||||
db::DPoint p[] = {
|
||||
db::DPoint (0, 100),
|
||||
|
|
@ -686,6 +701,21 @@ TEST(11)
|
|||
};
|
||||
poly.assign_hull (p, p + sizeof (p) / sizeof (p[0]));
|
||||
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-1.0, -1.0, -0.1, -0.1)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 0, 0)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-0.01, -0.01, 0.001, 0.001)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 20, 10)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, -10, 10, 20)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (10, 20, 20, 30)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (10, 20, 15, 25)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (30, 10, 40, 20)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (30, 20, 40, 50)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, 20, 0, 30)), true);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, 20, -5, 30)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, 100, -5, 110)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10.0, 100.0, 0.0, 100.5)), false);
|
||||
EXPECT_EQ (interact (poly, db::DEdge (-10, 100, 5, 100)), true);
|
||||
|
||||
EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, 100, 5, 110)), true);
|
||||
EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, -10, 110, 110)), true);
|
||||
EXPECT_EQ (interact (db::DBox (0, 0, 100, 100), db::DBox (-10, -10, 50, 110)), true);
|
||||
|
|
|
|||
|
|
@ -274,9 +274,9 @@ TEST(3)
|
|||
}
|
||||
|
||||
EXPECT_EQ (or2.has_valid_polygons (), true);
|
||||
EXPECT_EQ (or2.size () / 1000, size_t (100)); // because we use rand () the value may vary - it's only accurate to 1%
|
||||
EXPECT_EQ (or2.size () / 2000, size_t (50)); // because we use rand () the value may vary - it's only accurate to 2%
|
||||
EXPECT_EQ (or2_copy.has_valid_polygons (), true);
|
||||
EXPECT_EQ (or2_copy.size () / 1000, size_t (81)); // because we use rand () the value may vary - it's only accurate to 1%
|
||||
EXPECT_EQ (or2_copy.size () / 2000, size_t (40)); // because we use rand () the value may vary - it's only accurate to 2%
|
||||
EXPECT_EQ ((or2 ^ or2_copy).empty (), true);
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ TEST(3)
|
|||
}
|
||||
|
||||
// make sure the events get processed
|
||||
wait_for_ms (1100);
|
||||
wait_for_ms (5000);
|
||||
|
||||
// should have modified the file
|
||||
EXPECT_EQ (changed_spy.count (), 0);
|
||||
|
|
@ -204,7 +204,7 @@ TEST(3)
|
|||
}
|
||||
|
||||
// make sure the events get processed
|
||||
wait_for_ms (1100);
|
||||
wait_for_ms (5000);
|
||||
|
||||
// should have modified the file
|
||||
EXPECT_EQ (changed_spy.count (), 50);
|
||||
|
|
|
|||
Loading…
Reference in New Issue