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:
Matthias Koefferlein 2017-08-11 22:00:07 +02:00
parent 4ec8a838d5
commit a6723a8155
7 changed files with 161 additions and 107 deletions

View File

@ -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);
}
}
}

View File

@ -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); }

View File

@ -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 ());
}
/**

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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);