More stable hash function (the previous one was too sparse for small coordinates). Test updates for this reason.

This commit is contained in:
Matthias Koefferlein 2021-01-18 20:26:03 +01:00
parent 757543ec48
commit 9b275d85a6
3 changed files with 458 additions and 128 deletions

View File

@ -50,6 +50,11 @@
namespace std
{
inline size_t hcombine (size_t h1, size_t h2)
{
return (h1 << 4) ^ (h1 >> 4) ^ h2;
}
template <class T>
inline size_t hfunc (const T &t)
{
@ -57,11 +62,6 @@ namespace std
return hf (t);
}
inline size_t hcombine (size_t h1, size_t h2)
{
return (h1 << 4) ^ (h1 >> 4) ^ h2;
}
template <class T>
inline size_t hfunc (const T &t, size_t h)
{
@ -82,365 +82,695 @@ namespace std
template <class C>
inline size_t hfunc_coord (C d, size_t h)
{
return hcombine (hfunc_coord (d), h);
return hcombine (h, hfunc_coord (d));
}
/**
* @brief Hash value for a point
*/
template <class C>
size_t hfunc (const db::point<C> &o, size_t h)
{
return hfunc_coord (o.x (), hfunc_coord (o.y (), h));
}
template <class C>
size_t hfunc (const db::point<C> &o)
{
return hfunc_coord (o.x (), hfunc_coord (o.y ()));
}
template <class C>
struct hash <db::point<C> >
{
size_t operator() (const db::point<C> &o) const
{
return hfunc_coord (o.x (), hfunc_coord (o.y ()));
return hfunc (o);
}
};
/**
* @brief Hash value for a vector
*/
template <class C>
size_t hfunc (const db::vector<C> &o, size_t h)
{
return hfunc_coord (o.x (), hfunc_coord (o.y (), h));
}
template <class C>
size_t hfunc (const db::vector<C> &o)
{
return hfunc_coord (o.x (), hfunc_coord (o.y ()));
}
template <class C>
struct hash <db::vector<C> >
{
size_t operator() (const db::vector<C> &o) const
{
return hfunc_coord (o.x (), hfunc_coord (o.y ()));
return hfunc (o);
}
};
/**
* @brief Hash value for a box
*/
template <class C>
size_t hfunc (const db::box<C> &o, size_t h)
{
return hfunc (o.p1 (), hfunc (o.p2 (), h));
}
template <class C>
size_t hfunc (const db::box<C> &o)
{
return hfunc (o.p1 (), hfunc (o.p2 ()));
}
template <class C>
struct hash <db::box<C> >
{
size_t operator() (const db::box<C> &o) const
{
return hfunc (o.p1 (), hfunc (o.p2 ()));
return hfunc (o);
}
};
/**
* @brief Hash value for an edge
*/
template <class C>
size_t hfunc (const db::edge<C> &o, size_t h)
{
return hfunc (o.p1 (), hfunc (o.p2 (), h));
}
template <class C>
size_t hfunc (const db::edge<C> &o)
{
return hfunc (o.p1 (), hfunc (o.p2 ()));
}
template <class C>
struct hash <db::edge<C> >
{
size_t operator() (const db::edge<C> &o) const
{
return hfunc (o.p1 (), hfunc (o.p2 ()));
return hfunc (o);
}
};
/**
* @brief Hash value for an edge pair
*/
template <class C>
size_t hfunc (const db::edge_pair<C> &o, size_t h)
{
return hfunc (o.lesser (), hfunc (o.greater (), hfunc (int (o.is_symmetric ()), h)));
}
template <class C>
size_t hfunc (const db::edge_pair<C> &o)
{
return hfunc (o.lesser (), hfunc (o.greater (), hfunc (int (o.is_symmetric ()))));
}
template <class C>
struct hash <db::edge_pair<C> >
{
size_t operator() (const db::edge_pair<C> &o) const
{
return hfunc (o.lesser (), hfunc (o.greater (), hfunc (int (o.is_symmetric ()))));
return hfunc (o);
}
};
/**
* @brief Hash value for a text object
*/
template <class C>
size_t hfunc (const db::text<C> &o, size_t h)
{
h = hfunc (int (o.halign ()), h);
h = hfunc (int (o.valign ()), h);
h = hfunc (o.trans ().rot (), h);
h = hfunc (o.trans ().disp (), h);
// NOTE: using std::string for the value makes sure the default hasher doesn't use the pointer value
h = hfunc (hfunc (std::string (o.string ())), h);
return h;
}
template <class C>
size_t hfunc (const db::text<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::text<C> >
{
size_t operator() (const db::text<C> &o) const
{
size_t h = hfunc (int (o.halign ()));
h = hfunc (int (o.valign ()), h);
h = hfunc (o.trans ().rot (), h);
h = hfunc (o.trans ().disp (), h);
// NOTE: using std::string for the value makes sure the default hasher doesn't use the pointer value
h = hfunc (hfunc (std::string (o.string ())), h);
return h;
return hfunc (o);
}
};
/**
* @brief Hash value for a path
*/
template <class C>
size_t hfunc (const db::path<C> &o, size_t h)
{
h = hfunc (int (o.round ()), h);
h = hfunc_coord (o.bgn_ext (), h);
h = hfunc_coord (o.end_ext (), h);
h = hfunc_coord (o.width (), h);
for (typename db::path<C>::iterator p = o.begin (); p != o.end (); ++p) {
h = hfunc (*p, h);
}
return h;
}
template <class C>
size_t hfunc (const db::path<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::path<C> >
{
size_t operator() (const db::path<C> &o) const
{
size_t h = hfunc (int (o.round ()));
h = hfunc_coord (o.bgn_ext (), h);
h = hfunc_coord (o.end_ext (), h);
h = hfunc_coord (o.width (), h);
for (typename db::path<C>::iterator p = o.begin (); p != o.end (); ++p) {
h = hfunc (*p, h);
}
return h;
return hfunc (o);
}
};
/**
* @brief Hash value for a polygon contour
*/
template <class C>
size_t hfunc (const db::polygon_contour<C> &o, size_t h)
{
for (typename db::polygon_contour<C>::simple_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (*i, h);
}
return h;
}
template <class C>
size_t hfunc (const db::polygon_contour<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::polygon_contour<C> >
{
size_t operator() (const db::polygon_contour<C> &o) const
size_t operator() (const db::path<C> &o) const
{
size_t h = 0;
for (typename db::polygon_contour<C>::simple_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (*i, h);
}
return h;
return hfunc (o);
}
};
/**
* @brief Hash value for a polygon
*/
template <class C>
size_t hfunc (const db::polygon<C> &o, size_t h)
{
h = hfunc (o.hull (), h);
for (size_t i = 0; i < o.holes (); ++i) {
h = hfunc (o.hole (int (i)), h);
}
return h;
}
template <class C>
size_t hfunc (const db::polygon<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::polygon<C> >
{
size_t operator() (const db::polygon<C> &o) const
{
size_t h = hfunc (o.hull ());
for (size_t i = 0; i < o.holes (); ++i) {
h = hfunc (o.hole (int (i)), h);
}
return h;
return hfunc (o);
}
};
/**
* @brief Hash value for a simple polygon
*/
template <class C>
size_t hfunc (const db::simple_polygon<C> &o, size_t h)
{
return hfunc (o.hull (), h);
}
template <class C>
size_t hfunc (const db::simple_polygon<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::simple_polygon<C> >
{
size_t operator() (const db::simple_polygon<C> &o) const
{
return hfunc (o.hull ());
return hfunc (o);
}
};
/**
* @brief Hash value for a simple transformation
*/
template <class C>
size_t hfunc (const db::simple_trans<C> &t, size_t h)
{
return hfunc (int (t.rot ()), hfunc (t.disp (), h));
}
template <class C>
size_t hfunc (const db::simple_trans<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::simple_trans<C> >
{
size_t operator() (const db::simple_trans<C> &t) const
size_t operator() (const db::simple_trans<C> &o) const
{
return hfunc (int (t.rot ()), hfunc (t.disp ()));
return hfunc (o);
}
};
/**
* @brief A hash function for a displacement transformation
*/
template <class C>
size_t hfunc (const db::disp_trans<C> &t, size_t h)
{
return hfunc (t.disp (), h);
}
template <class C>
size_t hfunc (const db::disp_trans<C> &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::disp_trans<C> >
{
size_t operator() (const db::disp_trans<C> &t) const
size_t operator() (const db::disp_trans<C> &o) const
{
return hfunc (t.disp ());
return hfunc (o);
}
};
/**
* @brief Hash value for a complex transformation
*/
template <class I, class F, class R>
size_t hfunc (const db::complex_trans<I, F, R> &t, size_t h)
{
h = hfunc (int64_t (0.5 + t.angle () / db::epsilon), h);
h = hfunc (int64_t (0.5 + t.mag () / db::epsilon), h);
h = hfunc (int (t.is_mirror ()), h);
h = hfunc (t.disp (), h);
return h;
}
template <class I, class F, class R>
size_t hfunc (const db::complex_trans<I, F, R> &o)
{
return hfunc (o, size_t (0));
}
template <class I, class F, class R>
struct hash <db::complex_trans<I, F, R> >
{
size_t operator() (const db::complex_trans<I, F, R> &t) const
size_t operator() (const db::complex_trans<I, F, R> &o) const
{
size_t h = hfunc (int64_t (0.5 + t.angle () / db::epsilon));
h = hfunc (int64_t (0.5 + t.mag () / db::epsilon), h);
h = hfunc (int (t.is_mirror ()), h);
h = hfunc (t.disp (), h);
return h;
return hfunc (o);
}
};
/**
* @brief A hash value for a db::CellInstArray and db::DCellInstArray
*/
template <class C>
size_t hfunc (const db::array <db::CellInst, db::simple_trans<C> > &o, size_t h)
{
h = hfunc (o.object ().cell_index (), h);
db::vector<C> a, b;
unsigned long na = 1, nb = 1;
if (o.is_regular_array (a, b, na, nb)) {
h = hfunc (a, h);
h = hfunc (b, h);
h = hfunc (na, h);
h = hfunc (nb, h);
} else if (o.size () > 1) {
// iterated array
typename db::array <db::CellInst, db::simple_trans<C> >::iterator i = o.begin ();
while (! (++i).at_end ()) {
h = hfunc (*i, h);
}
}
if (o.is_complex ()) {
h = hfunc (o.complex_trans (), h);
} else {
h = hfunc (o.front (), h);
}
return h;
}
template <class C>
size_t hfunc (const db::array <db::CellInst, db::simple_trans<C> > &o)
{
return hfunc (o, size_t (0));
}
template <class C>
struct hash <db::array <db::CellInst, db::simple_trans<C> > >
{
size_t operator() (const db::array <db::CellInst, db::simple_trans<C> > &o) const
{
size_t h = hfunc (o.object ().cell_index ());
db::vector<C> a, b;
unsigned long na = 1, nb = 1;
if (o.is_regular_array (a, b, na, nb)) {
h = hfunc (a, h);
h = hfunc (b, h);
h = hfunc (na, h);
h = hfunc (nb, h);
} else if (o.size () > 1) {
// iterated array
typename db::array <db::CellInst, db::simple_trans<C> >::iterator i = o.begin ();
while (! (++i).at_end ()) {
h = hfunc (*i, h);
}
}
if (o.is_complex ()) {
h = hfunc (o.complex_trans (), h);
} else {
h = hfunc (o.front (), h);
}
return h;
return hfunc (o);
}
};
/**
* @brief Hash value for an object with properties
*/
template <class O>
template <class O>
size_t hfunc (const db::object_with_properties<O> &o, size_t h)
{
return hfunc ((const O &) o, hfunc (o.properties_id (), h));
}
template <class O>
size_t hfunc (const db::object_with_properties<O> &o)
{
return hfunc ((const O &) o, hfunc (o.properties_id ()));
}
template <class O>
struct hash <db::object_with_properties<O> >
{
size_t operator() (const db::object_with_properties<O> &o) const
{
return hfunc ((const O &) o, hfunc (o.properties_id ()));
return hfunc (o);
}
};
/**
* @brief A hash function for a shape reference
*/
template <class Shape, class Trans>
struct hash<db::shape_ref<Shape, Trans> >
size_t hfunc (const db::shape_ref<Shape, Trans> &o, size_t h)
{
return hfunc (*o.ptr (), hfunc (o.trans (), h));
}
template <class Shape, class Trans>
size_t hfunc (const db::shape_ref<Shape, Trans> &o)
{
return hfunc (*o.ptr (), hfunc (o.trans ()));
}
template <class Shape, class Trans>
struct hash <db::shape_ref<Shape, Trans> >
{
size_t operator() (const db::shape_ref<Shape, Trans> &o) const
{
return hfunc (std::hash<Shape> () (*o.ptr ()), std::hash<Trans> () (o.trans ()));
return hfunc (o);
}
};
/**
* @brief A hash function for a polygon reference
*/
template <class Shape, class Trans>
struct hash<db::polygon_ref<Shape, Trans> >
size_t hfunc (const db::polygon_ref<Shape, Trans> &o, size_t h)
{
return hfunc (*o.ptr (), hfunc (o.trans (), h));
}
template <class Shape, class Trans>
size_t hfunc (const db::polygon_ref<Shape, Trans> &o)
{
return hfunc (*o.ptr (), hfunc (o.trans ()));
}
template <class Shape, class Trans>
struct hash <db::polygon_ref<Shape, Trans> >
{
size_t operator() (const db::polygon_ref<Shape, Trans> &o) const
{
return std::hash<db::shape_ref<Shape, Trans> > () (o);
return hfunc (o);
}
};
/**
* @brief A hash function for a path reference
*/
template <class Shape, class Trans>
struct hash<db::path_ref<Shape, Trans> >
size_t hfunc (const db::path_ref<Shape, Trans> &o, size_t h)
{
return hfunc (*o.ptr (), hfunc (o.trans (), h));
}
template <class Shape, class Trans>
size_t hfunc (const db::path_ref<Shape, Trans> &o)
{
return hfunc (*o.ptr (), hfunc (o.trans ()));
}
template <class Shape, class Trans>
struct hash <db::path_ref<Shape, Trans> >
{
size_t operator() (const db::path_ref<Shape, Trans> &o) const
{
return std::hash<db::shape_ref<Shape, Trans> > () (o);
return hfunc (o);
}
};
/**
* @brief A hash function for a text reference
*/
template <class Shape, class Trans>
struct hash<db::text_ref<Shape, Trans> >
size_t hfunc (const db::text_ref<Shape, Trans> &o, size_t h)
{
return hfunc (*o.ptr (), hfunc (o.trans (), h));
}
template <class Shape, class Trans>
size_t hfunc (const db::text_ref<Shape, Trans> &o)
{
return hfunc (*o.ptr (), hfunc (o.trans ()));
}
template <class Shape, class Trans>
struct hash <db::text_ref<Shape, Trans> >
{
size_t operator() (const db::text_ref<Shape, Trans> &o) const
{
return std::hash<db::shape_ref<Shape, Trans> > () (o);
return hfunc (o);
}
};
/**
* @brief A hash value for a db::LayerProperties object
*/
inline size_t hfunc (const db::LayerProperties &o, size_t h)
{
if (o.is_named ()) {
return hfunc (o.name, h);
} else {
h = hfunc (o.layer, h);
h = hfunc (o.datatype, h);
h = hfunc (o.name, h);
return h;
}
}
inline size_t hfunc (const db::LayerProperties &o)
{
return hfunc (o, size_t (0));
}
template <>
struct hash <db::LayerProperties>
{
size_t operator() (const db::LayerProperties &o) const
{
if (o.is_named ()) {
return hfunc (o.name);
} else {
size_t h = hfunc (o.layer);
h = hfunc (o.datatype, h);
h = hfunc (o.name, h);
return h;
}
return hfunc (o);
}
};
/**
* @brief Generic hash for a pair of objects
*/
template <class T1, class T2>
size_t hfunc (const std::pair <T1, T2> &o, size_t h)
{
return hfunc (o.first, hfunc (o.second, h));
}
template <class T1, class T2>
size_t hfunc (const std::pair <T1, T2> &o)
{
return hfunc (o.first, hfunc (o.second));
}
template <class T1, class T2>
struct hash <std::pair <T1, T2> >
{
size_t operator() (const std::pair<T1, T2> &p) const
size_t operator() (const std::pair<T1, T2> &o) const
{
hash <T1> hf1;
hash <T2> hf2;
size_t h = hf1 (p.first);
return hfunc (hf2 (p.second), h);
return hfunc (o);
}
};
/**
* @brief Generic hash for an unordered set
*/
template <class T>
struct hash<std::unordered_set<T> >
size_t hfunc (const std::unordered_set <T> &o, size_t h)
{
for (typename std::unordered_set<T>::const_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (*i, h);
}
return h;
}
template <class T>
size_t hfunc (const std::unordered_set <T> &o)
{
return hfunc (o, size_t (0));
}
template <class T>
struct hash <std::unordered_set <T> >
{
size_t operator() (const std::unordered_set<T> &o) const
{
size_t hf = 0;
for (typename std::unordered_set<T>::const_iterator i = o.begin (); i != o.end (); ++i) {
hf = hfunc (hf, std::hash <T> () (*i));
}
return hf;
return hfunc (o);
}
};
/**
* @brief Generic hash for an ordered set
*/
template <class T>
struct hash<std::set<T> >
size_t hfunc (const std::set <T> &o, size_t h)
{
for (typename std::set<T>::const_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (*i, h);
}
return h;
}
template <class T>
size_t hfunc (const std::set <T> &o)
{
return hfunc (o, size_t (0));
}
template <class T>
struct hash <std::set <T> >
{
size_t operator() (const std::set<T> &o) const
{
size_t hf = 0;
for (typename std::set<T>::const_iterator i = o.begin (); i != o.end (); ++i) {
hf = hfunc (hf, std::hash <T> () (*i));
}
return hf;
return hfunc (o);
}
};
/**
* @brief Generic hash for an unordered map
*/
template <class T1, class T2>
size_t hfunc (const std::unordered_map<T1, T2> &o, size_t h)
{
for (typename std::unordered_map<T1, T2>::const_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (i->first, hfunc (i->second, h));
}
return h;
}
template <class T1, class T2>
size_t hfunc (const std::unordered_map<T1, T2> &o)
{
return hfunc (o, size_t (0));
}
template <class T1, class T2>
struct hash <std::unordered_map<T1, T2> >
{
size_t operator() (const std::unordered_map<T1, T2> &o) const
{
return hfunc (o);
}
};
/**
* @brief Generic hash for an ordered map
*/
template <class T1, class T2>
struct hash<std::map<T1, T2> >
size_t hfunc (const std::map<T1, T2> &o, size_t h)
{
for (typename std::map<T1, T2>::const_iterator i = o.begin (); i != o.end (); ++i) {
h = hfunc (i->first, hfunc (i->second, h));
}
return h;
}
template <class T1, class T2>
size_t hfunc (const std::map<T1, T2> &o)
{
return hfunc (o, size_t (0));
}
template <class T1, class T2>
struct hash <std::map<T1, T2> >
{
size_t operator() (const std::map<T1, T2> &o) const
{
size_t hf = 0;
for (typename std::map<T1, T2>::const_iterator i = o.begin (); i != o.end (); ++i) {
hf = hfunc (hf, std::hash <T1> () (i->first));
hf = hfunc (hf, std::hash <T2> () (i->second));
}
return hf;
return hfunc (o);
}
};

View File

@ -581,11 +581,11 @@ TEST(15d)
r.insert (db::Box (db::Point (0, 140), db::Point (350, 160)));
EXPECT_EQ (r.space_check (120, db::RegionCheckOptions (false, db::Projection)).to_string (),
"(300,100;350,100)|(350,140;300,140);"
"(0,100;100,100)|(100,140;0,140);"
"(0,160;100,160)|(100,200;0,200);"
"(300,160;350,160)|(350,200;300,200);"
"(300,100;350,100)|(350,140;300,140);"
"(300,100;400,100)|(400,200;300,200);"
"(0,160;100,160)|(100,200;0,200);"
"(600,100;700,100)|(700,200;600,200)"
);
}
@ -845,17 +845,17 @@ TEST(18a)
o.select_inside (rr);
EXPECT_EQ (o.to_string (), "(20,30;20,50;40,50;40,30)");
o = r;
EXPECT_EQ (o.selected_not_inside (rr).to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(0,60;0,80;60,80;60,60);(70,60;70,80;90,80;90,60);(0,100;0,130;30,130;30,100)");
EXPECT_EQ (o.selected_not_inside (rr).to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
EXPECT_EQ (o.selected_inside (rr).count () + o.selected_not_inside (rr).count (), size_t (6));
EXPECT_EQ (o.selected_inside (rr).hier_count () + o.selected_not_inside (rr).hier_count (), size_t (6));
o.select_not_inside (rr);
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(0,60;0,80;60,80;60,60);(70,60;70,80;90,80;90,60);(0,100;0,130;30,130;30,100)");
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
}
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(50,10;50,30;70,30;70,10);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
{
db::Region o = r;
o.select_interacting (rr);
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(50,10;50,30;70,30;70,10);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60);(0,100;0,130;30,130;30,100)");
o = r;
EXPECT_EQ (o.selected_not_interacting (rr).to_string (), "(70,60;70,80;90,80;90,60)");
EXPECT_EQ (o.selected_interacting (rr).count () + o.selected_not_interacting (rr).count (), size_t (6));
@ -881,11 +881,11 @@ TEST(18a)
o.select_enclosing (rr);
EXPECT_EQ (o.to_string (), "(0,100;0,130;30,130;30,100)");
o = r;
EXPECT_EQ (o.selected_not_enclosing (rr).to_string (), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60)");
EXPECT_EQ (o.selected_not_enclosing (rr).to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)");
EXPECT_EQ (o.selected_enclosing (rr).count () + o.selected_not_enclosing (rr).count (), size_t (6));
EXPECT_EQ (o.selected_enclosing (rr).hier_count () + o.selected_not_enclosing (rr).hier_count (), size_t (6));
o.select_not_enclosing (rr);
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(20,30;20,50;40,50;40,30);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(0,60;0,80;60,80;60,60)");
EXPECT_EQ (o.to_string (), "(0,0;0,20;20,20;20,0);(50,10;50,30;70,30;70,10);(70,60;70,80;90,80;90,60);(20,30;20,50;40,50;40,30);(0,60;0,80;60,80;60,60)");
}
}
@ -957,7 +957,7 @@ TEST(18c)
EXPECT_EQ (r.selected_outside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_inside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_overlapping (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(-20,0;-20,20;20,20;20,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-20,0;-20,20;20,20;20,0);(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_outside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_not_inside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
@ -976,7 +976,7 @@ TEST(18c)
EXPECT_EQ (r.selected_outside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_inside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_overlapping (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(-20,0;-20,20;20,20;20,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-20,0;-20,20;20,20;20,0);(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_outside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_not_inside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
@ -994,7 +994,7 @@ TEST(18c)
EXPECT_EQ (r.selected_outside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_inside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_overlapping (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(-20,0;-20,20;20,20;20,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-20,0;-20,20;20,20;20,0);(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_outside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_not_inside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
@ -1013,10 +1013,10 @@ TEST(18c)
EXPECT_EQ (r.selected_outside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_inside (rr).to_string (), "");
EXPECT_EQ (r.selected_overlapping (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(-20,0;-20,20;20,20;20,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-20,0;-20,20;20,20;20,0);(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_outside (rr).to_string (), "(-20,0;-20,20;20,20;20,0)");
EXPECT_EQ (r.selected_not_inside (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(-20,0;-20,20;20,20;20,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_inside (rr).to_string (), "(-20,0;-20,20;20,20;20,0);(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_overlapping (rr).to_string (), "(-120,0;-120,20;-100,20;-100,0);(100,0;100,20;120,20;120,0)");
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
@ -1251,7 +1251,7 @@ TEST(20)
EXPECT_EQ (r1.has_valid_polygons (), false);
db::Region r2 (db::RecursiveShapeIterator (ly, ly.cell (top), l2));
EXPECT_EQ (r2.has_valid_polygons (), false);
EXPECT_EQ (r1.separation_check (r2, 20).to_string (), "(50,0;50,30)/(40,40;40,10);(63,30;80,30)/(97,40;80,40);(80,70;80,40)/(80,40;80,70);(50,40;50,57)/(40,40;40,23)");
EXPECT_EQ (r1.separation_check (r2, 20).to_string (), "(63,30;80,30)/(97,40;80,40);(50,0;50,30)/(40,40;40,10);(80,70;80,40)/(80,40;80,70);(50,40;50,57)/(40,40;40,23)");
}
{

Binary file not shown.