mirror of https://github.com/KLayout/klayout.git
WIP: new classes for hier network processor.
This commit is contained in:
parent
3609bdda81
commit
59d1aead59
|
|
@ -129,6 +129,14 @@ struct box_scanner_receiver
|
|||
* definition.
|
||||
*/
|
||||
void add (const Obj * /*o1*/, const Prop & /*p1*/, const Obj * /*o2*/, const Prop & /*p2*/) { }
|
||||
|
||||
/**
|
||||
* @brief Indicates whether the scanner may stop
|
||||
*
|
||||
* The scanner will stop if this method returns true. This feature can be used to
|
||||
* terminate the scan process early if the outcome is known.
|
||||
*/
|
||||
bool stop () const { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -250,9 +258,13 @@ public:
|
|||
*
|
||||
* The box converter must be capable of converting the Obj object into a box.
|
||||
* It must provide a box_type typedef.
|
||||
*
|
||||
* The scanner process can be terminated early by making the receiver's
|
||||
* stop() method return true. In this case, this method will return false.
|
||||
* Otherwise it will return true.
|
||||
*/
|
||||
template <class Rec, class BoxConvert>
|
||||
void process (Rec &rec, typename BoxConvert::box_type::coord_type enl, const BoxConvert &bc = BoxConvert ())
|
||||
bool process (Rec &rec, typename BoxConvert::box_type::coord_type enl, const BoxConvert &bc = BoxConvert ())
|
||||
{
|
||||
typedef typename BoxConvert::box_type box_type;
|
||||
typedef typename box_type::coord_type coord_type;
|
||||
|
|
@ -269,6 +281,9 @@ public:
|
|||
for (iterator_type j = i + 1; j != m_pp.end (); ++j) {
|
||||
if (bs_boxes_overlap (bc (*i->first), bc (*j->first), enl)) {
|
||||
rec.add (i->first, i->second, j->first, j->second);
|
||||
if (rec.stop ()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -355,6 +370,9 @@ public:
|
|||
if (seen.insert (std::make_pair (i->first, j->first)).second) {
|
||||
seen.insert (std::make_pair (j->first, i->first));
|
||||
rec.add (i->first, i->second, j->first, j->second);
|
||||
if (rec.stop ()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -379,6 +397,8 @@ public:
|
|||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -421,6 +441,14 @@ struct box_scanner_receiver2
|
|||
* definition.
|
||||
*/
|
||||
void add (const Obj1 * /*o1*/, const Prop1 & /*p1*/, const Obj2 * /*o2*/, const Prop2 & /*p2*/) { }
|
||||
|
||||
/**
|
||||
* @brief Indicates whether the scanner may stop
|
||||
*
|
||||
* The scanner will stop if this method returns true. This feature can be used to
|
||||
* terminate the scan process early if the outcome is known.
|
||||
*/
|
||||
bool stop () const { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -558,9 +586,13 @@ public:
|
|||
* The box converter 1 must be capable of converting the Obj1 object into a box.
|
||||
* It must provide a box_type typedef. The box converter 2 must be able to convert Obj2 to
|
||||
* a box. The box type of both box converters must be identical.
|
||||
*
|
||||
* The scanner process can be terminated early by making the receiver's
|
||||
* stop() method return true. In this case, this method will return false.
|
||||
* Otherwise it will return true.
|
||||
*/
|
||||
template <class Rec, class BoxConvert1, class BoxConvert2>
|
||||
void process (Rec &rec, typename BoxConvert1::box_type::coord_type enl, const BoxConvert1 &bc1 = BoxConvert1 (), const BoxConvert2 &bc2 = BoxConvert2 ())
|
||||
bool process (Rec &rec, typename BoxConvert1::box_type::coord_type enl, const BoxConvert1 &bc1 = BoxConvert1 (), const BoxConvert2 &bc2 = BoxConvert2 ())
|
||||
{
|
||||
typedef typename BoxConvert1::box_type box_type; // must be same as BoxConvert2::box_type
|
||||
typedef typename box_type::coord_type coord_type;
|
||||
|
|
@ -592,6 +624,9 @@ public:
|
|||
for (iterator_type2 j = m_pp2.begin (); j != m_pp2.end (); ++j) {
|
||||
if (bs_boxes_overlap (bc1 (*i->first), bc2 (*j->first), enl)) {
|
||||
rec.add (i->first, i->second, j->first, j->second);
|
||||
if (rec.stop ()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -716,6 +751,9 @@ public:
|
|||
if (seen1.insert (std::make_pair (i->first, j->first)).second) {
|
||||
seen2.insert (std::make_pair (j->first, i->first));
|
||||
rec.add (i->first, i->second, j->first, j->second);
|
||||
if (rec.stop ()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -747,6 +785,8 @@ public:
|
|||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "dbInstElement.h"
|
||||
#include "dbPolygon.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbBoxScanner.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
|
@ -95,62 +95,193 @@ Connectivity::end_connected (unsigned int layer)
|
|||
}
|
||||
}
|
||||
|
||||
template <class Trans>
|
||||
static bool
|
||||
interaction_test (const db::PolygonRef &a, const db::PolygonRef &b)
|
||||
interaction_test (const db::PolygonRef &a, const db::PolygonRef &b, const Trans &trans)
|
||||
{
|
||||
// TODO: this could be part of db::interact (including transformation)
|
||||
if (a.obj ().is_box () && b.obj ().is_box ()) {
|
||||
return db::interact (a.obj ().box ().transformed (b.trans ().inverted () * a.trans ()), b.obj ().box ());
|
||||
return db::interact (a.obj ().box ().transformed (b.trans ().inverted () * a.trans ()), b.obj ().box ().transformed (trans));
|
||||
} else {
|
||||
return db::interact (a.obj ().transformed (b.trans ().inverted () * a.trans ()), b.obj ());
|
||||
return db::interact (a.obj ().transformed (b.trans ().inverted () * a.trans ()), b.obj ().transformed (trans));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool Connectivity::interacts (const T &a, unsigned int la, T &b, unsigned int lb) const
|
||||
template <class T, class Trans>
|
||||
bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans) const
|
||||
{
|
||||
std::map<unsigned int, layers_type>::const_iterator i = m_connected.find (la);
|
||||
if (i == m_connected.end () || i->second.find (lb) == i->second.end ()) {
|
||||
return false;
|
||||
} else {
|
||||
return interaction_test (a, b);
|
||||
return interaction_test (a, b, trans);
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, db::PolygonRef &b, unsigned int lb) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans) const;
|
||||
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// ...
|
||||
// local_cluster implementation
|
||||
|
||||
template <class T>
|
||||
local_cluster<T>::local_cluster ()
|
||||
: m_id (0), m_needs_update (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
local_cluster<T>::add (const T &s, unsigned int la)
|
||||
{
|
||||
m_shapes[la].insert (s);
|
||||
m_needs_update = true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
local_cluster<T>::join_with (const local_cluster<T> &other)
|
||||
{
|
||||
for (typename std::map<unsigned int, tree_type>::const_iterator s = other.m_shapes.begin (); s != other.m_shapes.end (); ++s) {
|
||||
tree_type &other_tree = m_shapes[s->first];
|
||||
other_tree.insert (s->second.begin (), s->second.end ());
|
||||
}
|
||||
|
||||
m_needs_update = true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
local_cluster<T>::ensure_sorted ()
|
||||
{
|
||||
if (! m_needs_update) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sort the shape trees
|
||||
for (typename std::map<unsigned int, tree_type>::iterator s = m_shapes.begin (); s != m_shapes.end (); ++s) {
|
||||
s->second.sort (db::box_convert<T> ());
|
||||
}
|
||||
|
||||
// recompute bounding box
|
||||
m_bbox = box_type ();
|
||||
db::box_convert<T> bc;
|
||||
for (typename std::map<unsigned int, tree_type>::const_iterator s = m_shapes.begin (); s != m_shapes.end (); ++s) {
|
||||
for (typename tree_type::const_iterator i = s->second.begin (); i != s->second.end (); ++i) {
|
||||
m_bbox += bc (*i);
|
||||
}
|
||||
}
|
||||
|
||||
m_needs_update = false;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct interaction_receiver
|
||||
: public box_scanner_receiver2<T, unsigned int, T, unsigned int>
|
||||
{
|
||||
public:
|
||||
typedef typename local_cluster<T>::box_type box_type;
|
||||
|
||||
interaction_receiver (const Connectivity &conn, const db::ICplxTrans &trans)
|
||||
: mp_conn (&conn), m_any (false), m_trans (trans)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void add (const T *s1, unsigned int l1, const T *s2, unsigned int l2)
|
||||
{
|
||||
if (mp_conn->interacts (*s1, l1, *s2, l2, m_trans)) {
|
||||
m_any = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool stop () const
|
||||
{
|
||||
return m_any;
|
||||
}
|
||||
|
||||
private:
|
||||
const Connectivity *mp_conn;
|
||||
bool m_any;
|
||||
db::ICplxTrans m_trans;
|
||||
};
|
||||
|
||||
template <class T, class Trans>
|
||||
struct transformed_box
|
||||
{
|
||||
typedef db::box_convert<T> base_bc;
|
||||
typedef typename T::box_type box_type;
|
||||
|
||||
transformed_box (const Trans &trans)
|
||||
: m_trans (trans)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
box_type operator() (const T &t) const
|
||||
{
|
||||
return m_bc (t).transformed (m_trans);
|
||||
}
|
||||
|
||||
private:
|
||||
base_bc m_bc;
|
||||
Trans m_trans;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
local_cluster<T>::interacts (const local_cluster<T> &other, const db::ICplxTrans &trans, const Connectivity &conn) const
|
||||
{
|
||||
const_cast<local_cluster<T> *> (this)->ensure_sorted ();
|
||||
|
||||
if (! other.bbox ().overlaps (bbox ())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
box_type common = other.bbox () & bbox ();
|
||||
|
||||
db::box_scanner2<T, unsigned int, T, unsigned int> scanner;
|
||||
transformed_box <T, db::ICplxTrans> bc_t (trans);
|
||||
db::box_convert<T> bc;
|
||||
|
||||
bool any = false;
|
||||
for (typename std::map<unsigned int, tree_type>::const_iterator s = m_shapes.begin (); s != m_shapes.end (); ++s) {
|
||||
for (typename tree_type::overlapping_iterator i = s->second.begin_overlapping (common, bc); ! i.at_end (); ++i) {
|
||||
scanner.insert1 (i.operator-> (), s->first);
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (typename std::map<unsigned int, tree_type>::const_iterator s = other.m_shapes.begin (); s != other.m_shapes.end (); ++s) {
|
||||
for (typename tree_type::overlapping_iterator i = s->second.begin_overlapping (common.transformed (trans.inverted ()), bc); ! i.at_end (); ++i) {
|
||||
scanner.insert2 (i.operator-> (), s->first);
|
||||
}
|
||||
}
|
||||
|
||||
interaction_receiver<T> rec (conn, trans);
|
||||
return ! scanner.process (rec, 0, bc, bc_t);
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC local_cluster<db::PolygonRef>;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// local_cluster implementation
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Represents a cluster of shapes
|
||||
*
|
||||
* A cluster of shapes is a set of shapes which are connected in terms
|
||||
* of a given connectivity.
|
||||
*/
|
||||
class LocalCluster
|
||||
{
|
||||
public:
|
||||
typedef size_t id_type;
|
||||
|
||||
LocalCluster ();
|
||||
|
||||
void connect (const db::Shape &a, unsigned int la, const db::Shape &b, unsigned int lb);
|
||||
id_type id () const;
|
||||
|
||||
// @@@ Trans is the transformation of the cluster to the shape (instance transformation)
|
||||
void interacts (const db::Shape &s, unsigned int ls, const db::ICplxTrans &trans, const Connectivity &conn);
|
||||
const db::Box &bbox () const;
|
||||
|
||||
private:
|
||||
friend class LocalClusters;
|
||||
|
||||
void set_id (id_type id);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a collection of clusters in a cell
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
#define HDR_dbHierNetworkProcessor
|
||||
|
||||
#include "dbCommon.h"
|
||||
#include "dbTrans.h"
|
||||
#include "dbBoxConvert.h"
|
||||
#include "dbBoxTree.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -81,17 +84,112 @@ public:
|
|||
*/
|
||||
layer_iterator end_connected (unsigned int layer);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given shapes on the given layers interact
|
||||
*
|
||||
* This method accepts a transformation. This transformation is applied
|
||||
* to the b shape before checking against a.
|
||||
*/
|
||||
template <class T, class Trans>
|
||||
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true, if the given shapes on the given layers interact
|
||||
*/
|
||||
template <class T>
|
||||
bool interacts (const T &a, unsigned int la, T &b, unsigned int lb) const;
|
||||
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb) const
|
||||
{
|
||||
return interacts (a, la, b, lb, UnitTrans ());
|
||||
}
|
||||
|
||||
private:
|
||||
layers_type m_all_layers;
|
||||
std::map<unsigned int, layers_type> m_connected;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a cluster of shapes
|
||||
*
|
||||
* A cluster of shapes is a set of shapes of type T which are connected in terms
|
||||
* of a given connectivity. The shapes will still be organised in layers.
|
||||
*/
|
||||
template <class T>
|
||||
class DB_PUBLIC local_cluster
|
||||
{
|
||||
public:
|
||||
typedef size_t id_type;
|
||||
typedef typename T::box_type box_type;
|
||||
|
||||
/**
|
||||
* @brief Creates an empty cluster
|
||||
*/
|
||||
local_cluster ();
|
||||
|
||||
/**
|
||||
* @brief Adds a shape with the given layer to the cluster
|
||||
*/
|
||||
void add (const T &s, unsigned int la);
|
||||
|
||||
/**
|
||||
* @brief Joins this cluster with the other one
|
||||
*
|
||||
* This will copy all shapes from the other cluster into ourself.
|
||||
*/
|
||||
void join_with (const local_cluster<T> &other);
|
||||
|
||||
/**
|
||||
* @brief Gets the cluster's ID
|
||||
*
|
||||
* The ID is a unique identifier for the cluster. An ID value of 0 is reserved for
|
||||
* "no cluster".
|
||||
*/
|
||||
id_type id () const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tests whether this cluster interacts with another cluster
|
||||
*
|
||||
* "trans" is the transformation which is applied to the other cluster before
|
||||
* the test.
|
||||
*/
|
||||
bool interacts (const local_cluster<T> &other, const db::ICplxTrans &trans, const Connectivity &conn) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the bounding box of this cluster
|
||||
*/
|
||||
const box_type &bbox () const
|
||||
{
|
||||
const_cast<local_cluster<T> *> (this)->ensure_sorted (); // also updates bbox
|
||||
return m_bbox;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename> friend class local_clusters;
|
||||
template <typename> friend class interaction_receiver;
|
||||
typedef db::unstable_box_tree<box_type, T, db::box_convert<T> > tree_type;
|
||||
|
||||
void set_id (id_type id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
const T &shape (unsigned int l, size_t index) const
|
||||
{
|
||||
typename std::map<unsigned int, tree_type>::const_iterator s = m_shapes.find (l);
|
||||
tl_assert (s != m_shapes.end ());
|
||||
return s->second.objects () [index];
|
||||
}
|
||||
|
||||
void ensure_sorted ();
|
||||
|
||||
id_type m_id;
|
||||
bool m_needs_update;
|
||||
std::map<unsigned int, tree_type> m_shapes;
|
||||
box_type m_bbox;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ struct BoxScannerTestRecorder
|
|||
str += "<" + tl::to_string (p) + ">";
|
||||
}
|
||||
|
||||
bool stop () const { return false; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2)
|
||||
{
|
||||
str += "(" + tl::to_string (p1) + "-" + tl::to_string (p2) + ")";
|
||||
|
|
@ -43,10 +45,32 @@ struct BoxScannerTestRecorder
|
|||
std::string str;
|
||||
};
|
||||
|
||||
struct BoxScannerTestRecorderStopping
|
||||
{
|
||||
BoxScannerTestRecorderStopping () : do_stop (false) { }
|
||||
|
||||
void finish (const db::Box * /*box*/, size_t p) {
|
||||
str += "<" + tl::to_string (p) + ">";
|
||||
}
|
||||
|
||||
bool stop () const { return do_stop; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2)
|
||||
{
|
||||
str += "(" + tl::to_string (p1) + "-" + tl::to_string (p2) + ")";
|
||||
do_stop = true;
|
||||
}
|
||||
|
||||
std::string str;
|
||||
bool do_stop;
|
||||
};
|
||||
|
||||
struct BoxScannerTestRecorder2
|
||||
{
|
||||
void finish (const db::Box *, size_t) { }
|
||||
|
||||
bool stop () const { return false; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2)
|
||||
{
|
||||
interactions.insert (std::make_pair (p1, p2));
|
||||
|
|
@ -66,6 +90,8 @@ struct BoxScannerTestRecorderTwo
|
|||
str += "<" + tl::to_string (p) + ">";
|
||||
}
|
||||
|
||||
bool stop () const { return false; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2)
|
||||
{
|
||||
str += "(" + tl::to_string (p1) + "-" + tl::to_string (p2) + ")";
|
||||
|
|
@ -74,11 +100,37 @@ struct BoxScannerTestRecorderTwo
|
|||
std::string str;
|
||||
};
|
||||
|
||||
struct BoxScannerTestRecorderTwoStopping
|
||||
{
|
||||
BoxScannerTestRecorderTwoStopping () : do_stop (false) { }
|
||||
|
||||
void finish1 (const db::Box * /*box*/, size_t p) {
|
||||
str += "<" + tl::to_string (p) + ">";
|
||||
}
|
||||
|
||||
void finish2 (const db::SimplePolygon * /*poly*/, int p) {
|
||||
str += "<" + tl::to_string (p) + ">";
|
||||
}
|
||||
|
||||
bool stop () const { return do_stop; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2)
|
||||
{
|
||||
str += "(" + tl::to_string (p1) + "-" + tl::to_string (p2) + ")";
|
||||
do_stop = true;
|
||||
}
|
||||
|
||||
std::string str;
|
||||
bool do_stop;
|
||||
};
|
||||
|
||||
struct BoxScannerTestRecorder2Two
|
||||
{
|
||||
void finish1 (const db::Box *, size_t) { }
|
||||
void finish2 (const db::SimplePolygon *, int) { }
|
||||
|
||||
bool stop () const { return false; }
|
||||
|
||||
void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2)
|
||||
{
|
||||
interactions.insert (std::make_pair (p1, p2));
|
||||
|
|
@ -106,8 +158,12 @@ TEST(1)
|
|||
bs.set_fill_factor (0.0);
|
||||
db::box_convert<db::Box> bc;
|
||||
bs.set_scanner_threshold (0);
|
||||
bs.process (tr, 1, bc);
|
||||
EXPECT_EQ (bs.process (tr, 1, bc), true);
|
||||
EXPECT_EQ (tr.str, "(4-2)(5-2)(5-4)(3-2)(3-4)(5-3)<2><5><4><3>(1-0)<0><1>");
|
||||
|
||||
BoxScannerTestRecorderStopping trstop;
|
||||
EXPECT_EQ (bs.process (trstop, 1, bc), false);
|
||||
EXPECT_EQ (trstop.str, "(4-2)");
|
||||
}
|
||||
|
||||
TEST(1a)
|
||||
|
|
@ -920,8 +976,13 @@ TEST(two_1b)
|
|||
db::box_convert<db::Box> bc1;
|
||||
db::box_convert<db::SimplePolygon> bc2;
|
||||
bs.set_scanner_threshold (0);
|
||||
bs.process (tr, 1, bc1, bc2);
|
||||
EXPECT_EQ (bs.process (tr, 1, bc1, bc2), true);
|
||||
EXPECT_EQ (tr.str, "(1-12)(2-12)(1-11)(2-11)<1><2><11><12>(0-10)<0><10>");
|
||||
|
||||
|
||||
BoxScannerTestRecorderTwoStopping trstop;
|
||||
EXPECT_EQ (bs.process (trstop, 1, bc1, bc2), false);
|
||||
EXPECT_EQ (trstop.str, "(1-12)");
|
||||
}
|
||||
|
||||
void run_test2_two (tl::TestBase *_this, size_t n, double ff, db::Coord spread, bool touch = true)
|
||||
|
|
|
|||
|
|
@ -80,15 +80,23 @@ TEST(2_ShapeInteractions)
|
|||
tl::from_string ("(0,0;0,1000;1000,1000;1000,0)", poly);
|
||||
db::GenericRepository repo;
|
||||
db::PolygonRef ref1 (poly, repo);
|
||||
db::PolygonRef ref2 (poly.transformed (db::Trans (db::Vector (0, 10))), repo);
|
||||
db::PolygonRef ref3 (poly.transformed (db::Trans (db::Vector (0, 2000))), repo);
|
||||
db::ICplxTrans t2 (db::Trans (db::Vector (0, 10)));
|
||||
db::PolygonRef ref2 (poly.transformed (t2), repo);
|
||||
db::ICplxTrans t3 (db::Trans (db::Vector (0, 2000)));
|
||||
db::PolygonRef ref3 (poly.transformed (t3), repo);
|
||||
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2), true); // t2*ref1 == ref2
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3), false); // t3*ref1 == ref3
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2), false);
|
||||
}
|
||||
|
||||
TEST(2_ShapeInteractionsRealPolygon)
|
||||
|
|
@ -103,15 +111,25 @@ TEST(2_ShapeInteractionsRealPolygon)
|
|||
tl::from_string ("(0,0;0,1000;500,1000;500,1500;1000,1500;1000,0)", poly);
|
||||
db::GenericRepository repo;
|
||||
db::PolygonRef ref1 (poly, repo);
|
||||
db::PolygonRef ref2 (poly.transformed (db::Trans (db::Vector (0, 10))), repo);
|
||||
db::PolygonRef ref3 (poly.transformed (db::Trans (db::Vector (0, 2000))), repo);
|
||||
db::PolygonRef ref4 (poly.transformed (db::Trans (db::Vector (0, 1500))), repo);
|
||||
db::ICplxTrans t2 (db::Trans (db::Vector (0, 10)));
|
||||
db::PolygonRef ref2 (poly.transformed (t2), repo);
|
||||
db::ICplxTrans t3 (db::Trans (db::Vector (0, 2000)));
|
||||
db::PolygonRef ref3 (poly.transformed (t3), repo);
|
||||
db::ICplxTrans t4 (db::Trans (db::Vector (0, 1500)));
|
||||
db::PolygonRef ref4 (poly.transformed (t4), repo);
|
||||
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2), true); // t2*ref1 == ref2
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref4, 0), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t4), true);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
|
||||
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2), false);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue