mirror of https://github.com/KLayout/klayout.git
WIP: Basic implementation of Region::interact with count
This commit is contained in:
parent
965d796992
commit
91e924c559
|
|
@ -36,12 +36,41 @@
|
|||
#include "dbBoxScanner.h"
|
||||
#include "dbClip.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "dbHash.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
namespace {
|
||||
|
||||
struct ResultCountingInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultCountingInserter (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > &result)
|
||||
: mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Polygon &p)
|
||||
{
|
||||
(*mp_result)[&p] += 1;
|
||||
}
|
||||
|
||||
void init (const db::Polygon *p)
|
||||
{
|
||||
(*mp_result)[p] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > *mp_result;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------
|
||||
// AsIfFlagRegion implementation
|
||||
|
||||
|
|
@ -339,9 +368,11 @@ AsIfFlatRegion::processed_to_edge_pairs (const PolygonToEdgePairProcessorBase &f
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse) const
|
||||
AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
} else {
|
||||
|
|
@ -351,23 +382,28 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
|
|||
return clone ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (size ());
|
||||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
region_to_edge_interaction_filter<Shapes, db::Polygon> filter (output->raw_polygons (), inverse);
|
||||
region_to_edge_interaction_filter<ResultCountingInserter, db::Polygon> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
filter.preset (p.operator-> ());
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
AddressableEdgeDelivery e (other.addressable_edges ());
|
||||
AddressableEdgeDelivery e (counting ? other.addressable_merged_edges () : other.addressable_edges ());
|
||||
|
||||
for ( ; ! e.at_end (); ++e) {
|
||||
scanner.insert2 (e.operator-> (), 0);
|
||||
|
|
@ -375,17 +411,24 @@ AsIfFlatRegion::selected_interacting_generic (const Edges &other, bool inverse)
|
|||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
|
||||
if (inverse) {
|
||||
filter.fill_output ();
|
||||
// select hits based on their count
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse) const
|
||||
AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
if (other.empty ()) {
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
if (max_count < min_count || other.empty ()) {
|
||||
if (! inverse) {
|
||||
return new EmptyRegion ();
|
||||
} else {
|
||||
|
|
@ -395,19 +438,23 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse)
|
|||
return clone ();
|
||||
}
|
||||
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> > counted_results;
|
||||
ResultCountingInserter inserter (counted_results);
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Text, size_t> scanner (report_progress (), progress_desc ());
|
||||
scanner.reserve1 (size ());
|
||||
scanner.reserve2 (other.size ());
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
region_to_text_interaction_filter<FlatRegion, db::Text> filter (*output, inverse);
|
||||
region_to_text_interaction_filter<ResultCountingInserter, db::Text> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
AddressablePolygonDelivery p (begin_merged (), has_valid_merged_polygons ());
|
||||
|
||||
for ( ; ! p.at_end (); ++p) {
|
||||
scanner.insert1 (p.operator-> (), 0);
|
||||
if (inverse) {
|
||||
filter.preset (p.operator-> ());
|
||||
inserter.init (p.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,23 +466,32 @@ AsIfFlatRegion::selected_interacting_generic (const Texts &other, bool inverse)
|
|||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Text> ());
|
||||
|
||||
if (inverse) {
|
||||
filter.fill_output ();
|
||||
// select hits based on their count
|
||||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (true));
|
||||
|
||||
for (std::unordered_map<const db::Polygon *, size_t, std::ptr_hash_from_value<db::Polygon> >::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= min_count && r->second <= max_count;
|
||||
if (hit != inverse) {
|
||||
output->insert (*r->first);
|
||||
}
|
||||
}
|
||||
|
||||
return output.release ();
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
|
||||
AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
min_count = std::max (size_t (1), min_count);
|
||||
|
||||
db::EdgeProcessor ep (report_progress (), progress_desc ());
|
||||
ep.set_base_verbosity (base_verbosity ());
|
||||
|
||||
// shortcut
|
||||
if (empty ()) {
|
||||
return clone ();
|
||||
} else if (other.empty ()) {
|
||||
} else if (max_count < min_count || other.empty ()) {
|
||||
// clear, if b is empty and
|
||||
// * mode is inside or interacting and inverse is false ("inside" or "interacting")
|
||||
// * mode is outside and inverse is true ("not outside")
|
||||
|
|
@ -446,13 +502,48 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
}
|
||||
}
|
||||
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, 0);
|
||||
size_t nstart = 0;
|
||||
|
||||
if (min_count == size_t (1) && max_count == std::numeric_limits<size_t>::max ()) {
|
||||
|
||||
if (mode < 0) {
|
||||
|
||||
// NOTE: on "inside", the other region must be merged
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, nstart);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (RegionIterator p = other.begin (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, nstart);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++nstart;
|
||||
|
||||
} else {
|
||||
|
||||
// with counting we need to separate the other polygons by different properties
|
||||
|
||||
// can only have min_count/max_count in interact mode
|
||||
tl_assert (mode == 0);
|
||||
|
||||
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
|
||||
if (p->box ().touches (bbox ())) {
|
||||
ep.insert (*p, nstart);
|
||||
}
|
||||
++nstart;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
size_t n = nstart;
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if (mode > 0 || p->box ().touches (other.bbox ())) {
|
||||
ep.insert (*p, n);
|
||||
|
|
@ -467,19 +558,26 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
|
|||
|
||||
std::auto_ptr<FlatRegion> output (new FlatRegion (false));
|
||||
|
||||
std::map <size_t, size_t> interaction_counts;
|
||||
n = 0;
|
||||
std::set <size_t> selected;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () ; ++i) {
|
||||
++n;
|
||||
selected.insert (i->second);
|
||||
if (i->first < nstart && i->second >= nstart) {
|
||||
interaction_counts [i->second] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
output->reserve (n);
|
||||
|
||||
n = 1;
|
||||
n = nstart;
|
||||
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
|
||||
if ((selected.find (n) == selected.end ()) == inverse) {
|
||||
output->raw_polygons ().insert (*p);
|
||||
size_t count = 0;
|
||||
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
|
||||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= min_count && count <= max_count) != inverse) {
|
||||
output->insert (*p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,34 +183,34 @@ public:
|
|||
return selected_interacting_generic (other, -1, true, true);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Region &other) const
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, false);
|
||||
return selected_interacting_generic (other, 0, true, false, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other) const
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, 0, true, true);
|
||||
return selected_interacting_generic (other, 0, true, true, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other) const
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other) const
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other) const
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, false);
|
||||
return selected_interacting_generic (other, false, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other) const
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const
|
||||
{
|
||||
return selected_interacting_generic (other, true);
|
||||
return selected_interacting_generic (other, true, min_count, max_count);
|
||||
}
|
||||
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other) const
|
||||
|
|
@ -261,9 +261,9 @@ protected:
|
|||
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const;
|
||||
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -1487,8 +1487,8 @@ class InteractingLocalOperation
|
|||
: public local_operation<db::PolygonRef, db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
InteractingLocalOperation (int mode, bool touching, bool inverse)
|
||||
: m_mode (mode), m_touching (touching), m_inverse (inverse)
|
||||
InteractingLocalOperation (int mode, bool touching, bool inverse, size_t min_count, size_t max_count)
|
||||
: m_mode (mode), m_touching (touching), m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1512,7 +1512,31 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
size_t n = 1;
|
||||
size_t nstart = 0;
|
||||
|
||||
if (m_min_count == size_t (1) && m_max_count == std::numeric_limits<size_t>::max ()) {
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, nstart);
|
||||
}
|
||||
}
|
||||
nstart++;
|
||||
|
||||
} else {
|
||||
|
||||
tl_assert (m_mode == 0);
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, nstart);
|
||||
}
|
||||
nstart++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t n = nstart;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
|
|
@ -1520,28 +1544,27 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
for (std::set<db::PolygonRef>::const_iterator o = others.begin (); o != others.end (); ++o) {
|
||||
for (db::PolygonRef::polygon_edge_iterator e = o->begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, 0);
|
||||
}
|
||||
}
|
||||
|
||||
db::InteractionDetector id (m_mode, 0);
|
||||
id.set_include_touching (m_touching);
|
||||
db::EdgeSink es;
|
||||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
n = 0;
|
||||
std::set <size_t> selected;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
|
||||
++n;
|
||||
selected.insert (i->second);
|
||||
std::map <size_t, size_t> interaction_counts;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end (); ++i) {
|
||||
if (i->first < nstart && i->second >= nstart) {
|
||||
interaction_counts[i->second] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
n = 1;
|
||||
n = nstart;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i, ++n) {
|
||||
if ((selected.find (n) == selected.end ()) == m_inverse) {
|
||||
size_t count = 0;
|
||||
std::map <size_t, size_t>::const_iterator c = interaction_counts.find (n);
|
||||
if (c != interaction_counts.end ()) {
|
||||
count = c->second;
|
||||
}
|
||||
if ((count >= m_min_count && count <= m_max_count) != m_inverse) {
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
result.insert (subject);
|
||||
}
|
||||
|
|
@ -1566,6 +1589,7 @@ private:
|
|||
int m_mode;
|
||||
bool m_touching;
|
||||
bool m_inverse;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
class PullLocalOperation
|
||||
|
|
@ -1617,10 +1641,8 @@ public:
|
|||
ep.process (es, id);
|
||||
id.finish ();
|
||||
|
||||
n = 0;
|
||||
std::set <size_t> selected;
|
||||
for (db::InteractionDetector::iterator i = id.begin (); i != id.end () && i->first == 0; ++i) {
|
||||
++n;
|
||||
selected.insert (i->second);
|
||||
}
|
||||
|
||||
|
|
@ -1667,6 +1689,31 @@ private:
|
|||
std::unordered_set<db::PolygonRef> *mp_result;
|
||||
};
|
||||
|
||||
struct ResultCountingInserter
|
||||
{
|
||||
typedef db::Polygon value_type;
|
||||
|
||||
ResultCountingInserter (db::Layout *layout, std::unordered_map<db::PolygonRef, size_t> &result)
|
||||
: mp_layout (layout), mp_result (&result)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void insert (const db::Polygon &p)
|
||||
{
|
||||
(*mp_result)[db::PolygonRef (p, mp_layout->shape_repository ())] += 1;
|
||||
}
|
||||
|
||||
void init (const db::Polygon &p)
|
||||
{
|
||||
(*mp_result)[db::PolygonRef (p, mp_layout->shape_repository ())] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
db::Layout *mp_layout;
|
||||
std::unordered_map<db::PolygonRef, size_t> *mp_result;
|
||||
};
|
||||
|
||||
struct EdgeResultInserter
|
||||
{
|
||||
typedef db::Edge value_type;
|
||||
|
|
@ -1690,8 +1737,8 @@ class InteractingWithEdgeLocalOperation
|
|||
: public local_operation<db::PolygonRef, db::Edge, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
InteractingWithEdgeLocalOperation (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
InteractingWithEdgeLocalOperation (bool inverse, size_t min_count, size_t max_count)
|
||||
: m_inverse (inverse), m_min_count (std::max (size_t (1), min_count)), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1704,20 +1751,25 @@ public:
|
|||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::Edge> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
std::unordered_map<db::PolygonRef, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::Edge, size_t> scanner;
|
||||
|
||||
ResultInserter inserter (layout, result);
|
||||
region_to_edge_interaction_filter<ResultInserter> filter (inserter, m_inverse);
|
||||
ResultCountingInserter inserter (layout, counted_results);
|
||||
region_to_edge_interaction_filter<ResultCountingInserter> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
std::set<unsigned int> intruder_ids;
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
intruder_ids.insert (*j);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
|
|
@ -1726,14 +1778,23 @@ public:
|
|||
|
||||
scanner.insert1 (&heap.back (), 0);
|
||||
if (m_inverse) {
|
||||
filter.preset (&heap.back ());
|
||||
inserter.init (heap.back ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::Edge> ());
|
||||
if (m_inverse) {
|
||||
filter.fill_output ();
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
|
||||
for (std::unordered_map<db::PolygonRef, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1753,6 +1814,7 @@ public:
|
|||
|
||||
private:
|
||||
bool m_inverse;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
class PullWithEdgeLocalOperation
|
||||
|
|
@ -1860,6 +1922,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::set<unsigned int> intruder_ids;
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
intruder_ids.insert (*j);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
|
|
@ -1888,8 +1961,8 @@ class InteractingWithTextLocalOperation
|
|||
: public local_operation<db::PolygonRef, db::TextRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
InteractingWithTextLocalOperation (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
InteractingWithTextLocalOperation (bool inverse, size_t min_count, size_t max_count)
|
||||
: m_inverse (inverse), m_min_count (min_count), m_max_count (max_count)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -1902,20 +1975,25 @@ public:
|
|||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::TextRef> &interactions, std::vector<std::unordered_set<db::PolygonRef> > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
std::unordered_map<db::PolygonRef, size_t> counted_results;
|
||||
bool counting = !(m_min_count == 1 && m_max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
db::box_scanner2<db::Polygon, size_t, db::TextRef, size_t> scanner;
|
||||
|
||||
ResultInserter inserter (layout, result);
|
||||
region_to_text_interaction_filter<ResultInserter, db::TextRef> filter (inserter, m_inverse);
|
||||
ResultCountingInserter inserter (layout, counted_results);
|
||||
region_to_text_interaction_filter<ResultCountingInserter, db::TextRef> filter (inserter, false, counting /*get all in counting mode*/);
|
||||
|
||||
for (shape_interactions<db::PolygonRef, db::Text>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Text>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
std::set<unsigned int> intruder_ids;
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::Edge>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
intruder_ids.insert (*j);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<unsigned int>::const_iterator j = intruder_ids.begin (); j != intruder_ids.end (); ++j) {
|
||||
scanner.insert2 (& interactions.intruder_shape (*j).second, 0);
|
||||
}
|
||||
|
||||
std::list<db::Polygon> heap;
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
|
|
@ -1924,14 +2002,23 @@ public:
|
|||
|
||||
scanner.insert1 (&heap.back (), 0);
|
||||
if (m_inverse) {
|
||||
filter.preset (&heap.back ());
|
||||
inserter.init (heap.back ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scanner.process (filter, 1, db::box_convert<db::Polygon> (), db::box_convert<db::TextRef> ());
|
||||
if (m_inverse) {
|
||||
filter.fill_output ();
|
||||
|
||||
// select hits based on their count
|
||||
|
||||
tl_assert (results.size () == 1);
|
||||
std::unordered_set<db::PolygonRef> &result = results.front ();
|
||||
|
||||
for (std::unordered_map<db::PolygonRef, size_t>::const_iterator r = counted_results.begin (); r != counted_results.end (); ++r) {
|
||||
bool hit = r->second >= m_min_count && r->second <= m_max_count;
|
||||
if (hit != m_inverse) {
|
||||
result.insert (r->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1951,13 +2038,16 @@ public:
|
|||
|
||||
private:
|
||||
bool m_inverse;
|
||||
size_t m_min_count, m_max_count;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const
|
||||
DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
|
|
@ -1970,12 +2060,12 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
}
|
||||
|
||||
const db::DeepLayer &polygons = merged_deep_layer ();
|
||||
// NOTE: on "inside", the other polygons must be merged
|
||||
const db::DeepLayer &other_polygons = mode < 0 ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
|
||||
// NOTE: on "inside" or with counting, the other polygons must be merged
|
||||
const db::DeepLayer &other_polygons = (mode < 0 || counting) ? other_deep->merged_deep_layer () : other_deep->deep_layer ();
|
||||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingLocalOperation op (mode, touching, inverse);
|
||||
db::InteractingLocalOperation op (mode, touching, inverse, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -1995,8 +2085,10 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) const
|
||||
DeepRegion::selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
bool counting = !(min_count == 1 && max_count == std::numeric_limits<size_t>::max ());
|
||||
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
||||
|
|
@ -2012,7 +2104,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
|
|||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithEdgeLocalOperation op (inverse);
|
||||
db::InteractingWithEdgeLocalOperation op (inverse, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
@ -2022,7 +2114,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
|
|||
proc.set_max_vertex_count (polygons.store ()->max_vertex_count ());
|
||||
}
|
||||
|
||||
proc.run (&op, polygons.layer (), other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
proc.run (&op, polygons.layer (), counting ? other_deep->merged_deep_layer ().layer () : other_deep->deep_layer ().layer (), dl_out.layer ());
|
||||
|
||||
db::DeepRegion *res = new db::DeepRegion (dl_out);
|
||||
if (! split_after) {
|
||||
|
|
@ -2129,7 +2221,7 @@ DeepRegion::pull_generic (const Texts &other) const
|
|||
}
|
||||
|
||||
RegionDelegate *
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, bool inverse) const
|
||||
DeepRegion::selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const
|
||||
{
|
||||
// with these flag set to true, the resulting polygons are broken again.
|
||||
bool split_after = false;
|
||||
|
|
@ -2146,7 +2238,7 @@ DeepRegion::selected_interacting_generic (const Texts &other, bool inverse) cons
|
|||
|
||||
DeepLayer dl_out (polygons.derived ());
|
||||
|
||||
db::InteractingWithTextLocalOperation op (inverse);
|
||||
db::InteractingWithTextLocalOperation op (inverse, min_count, max_count);
|
||||
|
||||
db::local_processor<db::PolygonRef, db::TextRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
|
|
|
|||
|
|
@ -188,9 +188,9 @@ private:
|
|||
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other) const;
|
||||
EdgePairsDelegate *run_check (db::edge_relation_type rel, bool different_polygons, const Region *other, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const;
|
||||
EdgePairsDelegate *run_single_polygon_check (db::edge_relation_type rel, db::Coord d, bool whole_edges, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, bool shielded) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Region &other, int mode, bool touching, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *selected_interacting_generic (const Texts &other, bool inverse, size_t min_count, size_t max_count) const;
|
||||
virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const;
|
||||
virtual EdgesDelegate *pull_generic (const Edges &other) const;
|
||||
virtual TextsDelegate *pull_generic (const Texts &other) const;
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@ InteractionDetector::edge (bool north, bool enter, property_type p)
|
|||
for (std::set <property_type>::const_iterator i = m_inside_n.begin (); i != m_inside_n.end (); ++i) {
|
||||
if (*i < p) {
|
||||
m_interactions.insert (std::make_pair (*i, p));
|
||||
} else if (*i > p) {
|
||||
} else if (p < *i) {
|
||||
m_interactions.insert (std::make_pair (p, *i));
|
||||
}
|
||||
}
|
||||
|
|
@ -725,7 +725,7 @@ InteractionDetector::edge (bool north, bool enter, property_type p)
|
|||
for (std::set <property_type>::const_iterator i = m_inside_s.begin (); i != m_inside_s.end (); ++i) {
|
||||
if (*i < p) {
|
||||
m_interactions.insert (std::make_pair (*i, p));
|
||||
} else if (*i > p) {
|
||||
} else if (p < *i) {
|
||||
m_interactions.insert (std::make_pair (p, *i));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,8 +245,11 @@ public:
|
|||
* Mode -1 (inside) and +1 (outside) requires a single property value for the containing region.
|
||||
* This property value must be specified in the container_id parameter.
|
||||
* For correct operation, the container_id must be the lowest property ID and
|
||||
* the interacting edges must have higher property id's.
|
||||
* the interacting objects must have higher property id's.
|
||||
* The reported interactions will be (container_id,polygon_id) even for outside mode.
|
||||
*
|
||||
* For mode 0, property ids <= container_id are considered to belong to the first
|
||||
* container and property ids > container_id to the second container.
|
||||
*/
|
||||
InteractionDetector (int mode = 0, property_type container_id = 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -105,12 +105,12 @@ public:
|
|||
virtual RegionDelegate *selected_not_outside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_inside (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Edges &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Texts &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &, size_t, size_t) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &) const { return new EmptyRegion (); }
|
||||
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
|
||||
|
|
|
|||
|
|
@ -443,6 +443,19 @@ namespace std
|
|||
return hf;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a pointer hash from the pointer's value
|
||||
*/
|
||||
template <class X>
|
||||
struct ptr_hash_from_value
|
||||
{
|
||||
size_t operator() (const X *ptr) const
|
||||
{
|
||||
return ptr ? hash<X> () (*ptr) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1251,22 +1251,30 @@ public:
|
|||
/**
|
||||
* @brief Selects all polygons of this region which overlap or touch polygons from the other region
|
||||
*
|
||||
* The argument (if given) specifies and range of interaction counts: polygons will only be selected
|
||||
* if the number of interacting (different) polygons from the other region is between min_count and
|
||||
* max_count (inclusive).
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region &select_interacting (const Region &other)
|
||||
Region &select_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_interacting (other));
|
||||
set_delegate (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects all polygons of this region which do not overlap or touch polygons from the other region
|
||||
*
|
||||
* The argument (if given) specifies and range of interaction counts: polygons will not be selected
|
||||
* if the number of interacting (different) polygons from the other region is between min_count and
|
||||
* max_count (inclusive).
|
||||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region &select_not_interacting (const Region &other)
|
||||
Region &select_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_interacting (other));
|
||||
set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1277,9 +1285,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region selected_interacting (const Region &other) const
|
||||
Region selected_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_interacting (other));
|
||||
return Region (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1289,9 +1297,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region selected_not_interacting (const Region &other) const
|
||||
Region selected_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_not_interacting (other));
|
||||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1299,9 +1307,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies to both operators.
|
||||
*/
|
||||
Region &select_interacting (const Edges &other)
|
||||
Region &select_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_interacting (other));
|
||||
set_delegate (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1310,9 +1318,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies to both operators.
|
||||
*/
|
||||
Region &select_not_interacting (const Edges &other)
|
||||
Region &select_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_interacting (other));
|
||||
set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1323,9 +1331,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies to both operators.
|
||||
*/
|
||||
Region selected_interacting (const Edges &other) const
|
||||
Region selected_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_interacting (other));
|
||||
return Region (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1335,9 +1343,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies to both operators.
|
||||
*/
|
||||
Region selected_not_interacting (const Edges &other) const
|
||||
Region selected_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_not_interacting (other));
|
||||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1345,9 +1353,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region &select_interacting (const Texts &other)
|
||||
Region &select_interacting (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_interacting (other));
|
||||
set_delegate (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1356,9 +1364,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region &select_not_interacting (const Texts &other)
|
||||
Region &select_not_interacting (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
|
||||
{
|
||||
set_delegate (mp_delegate->selected_not_interacting (other));
|
||||
set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1369,9 +1377,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region selected_interacting (const Texts &other) const
|
||||
Region selected_interacting (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_interacting (other));
|
||||
return Region (mp_delegate->selected_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1381,9 +1389,9 @@ public:
|
|||
*
|
||||
* Merged semantics applies.
|
||||
*/
|
||||
Region selected_not_interacting (const Texts &other) const
|
||||
Region selected_not_interacting (const Texts &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
|
||||
{
|
||||
return Region (mp_delegate->selected_not_interacting (other));
|
||||
return Region (mp_delegate->selected_not_interacting (other, min_count, max_count));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -269,12 +269,12 @@ public:
|
|||
virtual RegionDelegate *selected_not_outside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_inside (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_not_interacting (const Texts &other, size_t min_count, size_t max_count) const = 0;
|
||||
virtual RegionDelegate *selected_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *selected_not_overlapping (const Region &other) const = 0;
|
||||
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
|
||||
|
|
|
|||
|
|
@ -364,8 +364,8 @@ Poly2PolyCheckBase::enter (const db::Polygon &o1, size_t p1, const db::Polygon &
|
|||
// RegionToEdgeInteractionFilterBase implementation
|
||||
|
||||
template <class OutputType>
|
||||
region_to_edge_interaction_filter_base<OutputType>::region_to_edge_interaction_filter_base (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
region_to_edge_interaction_filter_base<OutputType>::region_to_edge_interaction_filter_base (bool inverse, bool get_all)
|
||||
: m_inverse (inverse), m_get_all (get_all)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -384,7 +384,7 @@ region_to_edge_interaction_filter_base<OutputType>::add (const db::Polygon *p, s
|
|||
const OutputType *o = 0;
|
||||
tl::select (o, p, e);
|
||||
|
||||
if ((m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
if (m_get_all || (m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
|
||||
// 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
|
||||
|
|
@ -403,7 +403,9 @@ region_to_edge_interaction_filter_base<OutputType>::add (const db::Polygon *p, s
|
|||
if (m_inverse) {
|
||||
m_seen.erase (o);
|
||||
} else {
|
||||
m_seen.insert (o);
|
||||
if (! m_get_all) {
|
||||
m_seen.insert (o);
|
||||
}
|
||||
put (*o);
|
||||
}
|
||||
}
|
||||
|
|
@ -428,8 +430,8 @@ template class region_to_edge_interaction_filter_base<db::Edge>;
|
|||
// RegionToTextInteractionFilterBase implementation
|
||||
|
||||
template <class OutputType, class TextType>
|
||||
region_to_text_interaction_filter_base<OutputType, TextType>::region_to_text_interaction_filter_base (bool inverse)
|
||||
: m_inverse (inverse)
|
||||
region_to_text_interaction_filter_base<OutputType, TextType>::region_to_text_interaction_filter_base (bool inverse, bool get_all)
|
||||
: m_inverse (inverse), m_get_all (get_all)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -448,7 +450,7 @@ region_to_text_interaction_filter_base<OutputType, TextType>::add (const db::Pol
|
|||
const OutputType *o = 0;
|
||||
tl::select (o, p, t);
|
||||
|
||||
if ((m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
if (m_get_all || (m_seen.find (o) == m_seen.end ()) != m_inverse) {
|
||||
|
||||
// A polygon and an text interact if the text is either inside completely
|
||||
// of at least one text of the polygon intersects with the text
|
||||
|
|
@ -457,7 +459,9 @@ region_to_text_interaction_filter_base<OutputType, TextType>::add (const db::Pol
|
|||
if (m_inverse) {
|
||||
m_seen.erase (o);
|
||||
} else {
|
||||
m_seen.insert (o);
|
||||
if (! m_get_all) {
|
||||
m_seen.insert (o);
|
||||
}
|
||||
put (*o);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -596,7 +596,7 @@ class DB_PUBLIC region_to_edge_interaction_filter_base
|
|||
: public db::box_scanner_receiver2<db::Polygon, size_t, db::Edge, size_t>
|
||||
{
|
||||
public:
|
||||
region_to_edge_interaction_filter_base (bool inverse);
|
||||
region_to_edge_interaction_filter_base (bool inverse, bool get_all);
|
||||
|
||||
void preset (const OutputType *s);
|
||||
void add (const db::Polygon *p, size_t, const db::Edge *e, size_t);
|
||||
|
|
@ -607,7 +607,7 @@ protected:
|
|||
|
||||
private:
|
||||
std::set<const OutputType *> m_seen;
|
||||
bool m_inverse;
|
||||
bool m_inverse, m_get_all;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -618,8 +618,8 @@ class DB_PUBLIC_TEMPLATE region_to_edge_interaction_filter
|
|||
: public region_to_edge_interaction_filter_base<OutputType>
|
||||
{
|
||||
public:
|
||||
region_to_edge_interaction_filter (OutputContainer &output, bool inverse)
|
||||
: region_to_edge_interaction_filter_base<OutputType> (inverse), mp_output (&output)
|
||||
region_to_edge_interaction_filter (OutputContainer &output, bool inverse, bool get_all = false)
|
||||
: region_to_edge_interaction_filter_base<OutputType> (inverse, get_all), mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -642,7 +642,7 @@ class DB_PUBLIC region_to_text_interaction_filter_base
|
|||
: public db::box_scanner_receiver2<db::Polygon, size_t, TextType, size_t>
|
||||
{
|
||||
public:
|
||||
region_to_text_interaction_filter_base (bool inverse);
|
||||
region_to_text_interaction_filter_base (bool inverse, bool get_all);
|
||||
|
||||
void preset (const OutputType *s);
|
||||
void add (const db::Polygon *p, size_t, const TextType *e, size_t);
|
||||
|
|
@ -653,7 +653,7 @@ protected:
|
|||
|
||||
private:
|
||||
std::set<const OutputType *> m_seen;
|
||||
bool m_inverse;
|
||||
bool m_inverse, m_get_all;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -664,8 +664,8 @@ class DB_PUBLIC_TEMPLATE region_to_text_interaction_filter
|
|||
: public region_to_text_interaction_filter_base<OutputType, TextType>
|
||||
{
|
||||
public:
|
||||
region_to_text_interaction_filter (OutputContainer &output, bool inverse)
|
||||
: region_to_text_interaction_filter_base<OutputType, TextType> (inverse), mp_output (&output)
|
||||
region_to_text_interaction_filter (OutputContainer &output, bool inverse, bool get_all = false)
|
||||
: region_to_text_interaction_filter_base<OutputType, TextType> (inverse, get_all), mp_output (&output)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1476,100 +1476,172 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
|
|||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_interacting, gsi::arg ("other"),
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with (different) polygons of the other region to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of polygons interacting with a polygon of this region is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Region &) const) &db::Region::selected_not_interacting, gsi::arg ("other"),
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Region &, size_t, size_t) const) &db::Region::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which do not overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with (different) polygons of the other region to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of polygons interacting with a polygon of this region is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching polygons from the other region\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_interacting, gsi::arg ("other"),
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with (different) polygons of the other region to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of polygons interacting with a polygon of this region is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Region &)) &db::Region::select_not_interacting, gsi::arg ("other"),
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Region &, size_t, size_t)) &db::Region::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which do not overlap or touch polygons from the other region\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with (different) polygons of the other region to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of polygons interacting with a polygon of this region is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_interacting, gsi::arg ("other"),
|
||||
"\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Edges &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with edges of the edge collection to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of edges interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"This method has been introduced in version 0.25.\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Edges &) const) &db::Region::selected_not_interacting, gsi::arg ("other"),
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Edges &, size_t, size_t) const) &db::Region::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which do not overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with edges of the edge collection to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of edges interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching edges from the edge collection\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_interacting, gsi::arg ("other"),
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with edges of the edge collection to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of edges interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Edges &)) &db::Region::select_not_interacting, gsi::arg ("other"),
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Edges &, size_t, size_t)) &db::Region::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons from this region which do not overlap or touch edges from the edge collection\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with edges of the edge collection to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of edges interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25\n"
|
||||
"The min_count and max_count arguments have been added in version 0.27.\n"
|
||||
) +
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Texts &) const) &db::Region::selected_interacting, gsi::arg ("other"),
|
||||
method ("interacting", (db::Region (db::Region::*) (const db::Texts &, size_t, size_t) const) &db::Region::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which overlap or touch texts\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with texts of the text collection to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons overlapping or touching texts\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Texts &) const) &db::Region::selected_not_interacting, gsi::arg ("other"),
|
||||
method ("not_interacting", (db::Region (db::Region::*) (const db::Texts &, size_t, size_t) const) &db::Region::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Returns the polygons of this region which do not overlap or touch texts\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with texts of the text collection to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return A new region containing the polygons not overlapping or touching texts\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &)) &db::Region::select_interacting, gsi::arg ("other"),
|
||||
method ("select_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons of this region which overlap or touch texts\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with texts of the text collection to make the polygon selected. A polygon is "
|
||||
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27\n"
|
||||
) +
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Texts &)) &db::Region::select_not_interacting, gsi::arg ("other"),
|
||||
method ("select_not_interacting", (db::Region &(db::Region::*) (const db::Texts &, size_t, size_t)) &db::Region::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
|
||||
"@brief Selects the polygons of this region which do not overlap or touch texts\n"
|
||||
"\n"
|
||||
"'min_count' and 'max_count' impose a constraint on the number of times a polygon of this region "
|
||||
"has to interact with texts of the text collection to make the polygon not selected. A polygon is not "
|
||||
"selected by this method if the number of texts interacting with the polygon is between min_count and max_count "
|
||||
"(including max_count).\n"
|
||||
"\n"
|
||||
"@return The region after the polygons have been selected (self)\n"
|
||||
"\n"
|
||||
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
|
||||
|
|
|
|||
|
|
@ -1689,6 +1689,278 @@ TEST(29_InteractionsWithTexts)
|
|||
db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_region_au29.gds");
|
||||
}
|
||||
|
||||
TEST(30a_interact_with_count_region)
|
||||
{
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Layout ly;
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||
db::cell_index_type ci1 = ly.add_cell ("C1");
|
||||
db::Cell &c1 = ly.cell (ci1);
|
||||
db::cell_index_type ci2 = ly.add_cell ("C2");
|
||||
db::Cell &c2 = ly.cell (ci2);
|
||||
top.insert (db::CellInstArray (db::CellInst (ci1), db::Trans ()));
|
||||
top.insert (db::CellInstArray (db::CellInst (ci2), db::Trans ()));
|
||||
|
||||
c1.shapes (l1).insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
c1.shapes (l1).insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
|
||||
c2.shapes (l2).insert (db::Box (db::Point (-10, -10), db::Point (10, 0)));
|
||||
c2.shapes (l2).insert (db::Box (db::Point (-10, 0), db::Point (10, 10)));
|
||||
c2.shapes (l2).insert (db::Box (db::Point (-110, -10), db::Point (-90, 10)));
|
||||
c2.shapes (l2).insert (db::Box (db::Point (-110, -210), db::Point (-90, -190)));
|
||||
|
||||
ly.copy_layer (l2, l3);
|
||||
top.shapes (l2).insert (db::Box (db::Point (90, -10), db::Point (110, 10)));
|
||||
top.shapes (l2).insert (db::Box (db::Point (-110, -110), db::Point (-90, -90)));
|
||||
|
||||
db::Region r (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Region rr (db::RecursiveShapeIterator (ly, top, l2), dss);
|
||||
db::Region rr2 (db::RecursiveShapeIterator (ly, top, l3), dss);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(30b_interact_with_count_edge)
|
||||
{
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Layout ly;
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||
db::cell_index_type ci1 = ly.add_cell ("C1");
|
||||
db::Cell &c1 = ly.cell (ci1);
|
||||
db::cell_index_type ci2 = ly.add_cell ("C2");
|
||||
db::Cell &c2 = ly.cell (ci2);
|
||||
top.insert (db::CellInstArray (db::CellInst (ci1), db::Trans ()));
|
||||
top.insert (db::CellInstArray (db::CellInst (ci2), db::Trans ()));
|
||||
|
||||
c1.shapes (l1).insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
c1.shapes (l1).insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
|
||||
c2.shapes (l2).insert (db::Edge (db::Point (-10, -10), db::Point (0, 0)));
|
||||
c2.shapes (l2).insert (db::Edge (db::Point (0, 0), db::Point (10, 10)));
|
||||
c2.shapes (l2).insert (db::Edge (db::Point (-110, -10), db::Point (-90, 10)));
|
||||
c2.shapes (l2).insert (db::Edge (db::Point (-110, -210), db::Point (-90, -190)));
|
||||
|
||||
ly.copy_layer (l2, l3);
|
||||
top.shapes (l2).insert (db::Edge (db::Point (90, -10), db::Point (110, 10)));
|
||||
top.shapes (l2).insert (db::Edge (db::Point (-110, -110), db::Point (-90, -90)));
|
||||
|
||||
db::Region r (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Edges rr (db::RecursiveShapeIterator (ly, top, l2), dss);
|
||||
db::Edges rr2 (db::RecursiveShapeIterator (ly, top, l3), dss);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(30c_interact_with_count_text)
|
||||
{
|
||||
db::DeepShapeStore dss;
|
||||
|
||||
db::Layout ly;
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
db::Cell &top = ly.cell (ly.add_cell ("TOP"));
|
||||
db::cell_index_type ci1 = ly.add_cell ("C1");
|
||||
db::Cell &c1 = ly.cell (ci1);
|
||||
db::cell_index_type ci2 = ly.add_cell ("C2");
|
||||
db::Cell &c2 = ly.cell (ci2);
|
||||
top.insert (db::CellInstArray (db::CellInst (ci1), db::Trans ()));
|
||||
top.insert (db::CellInstArray (db::CellInst (ci2), db::Trans ()));
|
||||
|
||||
c1.shapes (l1).insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
c1.shapes (l1).insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
|
||||
c2.shapes (l2).insert (db::Text ("a", db::Trans (db::Vector (0, 0))));
|
||||
c2.shapes (l2).insert (db::Text ("b", db::Trans (db::Vector (-100, 0))));
|
||||
c2.shapes (l2).insert (db::Text ("c", db::Trans (db::Vector (-100, -200))));
|
||||
|
||||
ly.copy_layer (l2, l3);
|
||||
top.shapes (l2).insert (db::Text ("x", db::Trans (db::Vector (100, 0))));
|
||||
top.shapes (l2).insert (db::Text ("y", db::Trans (db::Vector (-100, -100))));
|
||||
|
||||
db::Region r (db::RecursiveShapeIterator (ly, top, l1), dss);
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Texts rr (db::RecursiveShapeIterator (ly, top, l2), dss);
|
||||
db::Texts rr2 (db::RecursiveShapeIterator (ly, top, l3), dss);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(100_Integration)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
|
|
@ -1336,7 +1336,7 @@ TEST(30a)
|
|||
r.set_merged_semantics (false);
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_not_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
db::Region rr = r;
|
||||
r.select_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (-10, -10))));
|
||||
|
|
@ -1365,7 +1365,7 @@ TEST(30b)
|
|||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (true);
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (20, 20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (30, 30)))).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Edges (db::Edge (db::Point (-200, -200), db::Point (-190, -190)))).to_string (), "");
|
||||
r.select_interacting (db::Edges (db::Edge (db::Point (-20, -20), db::Point (-10, -10))));
|
||||
EXPECT_EQ (r.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
|
@ -1522,7 +1522,7 @@ TEST(34a)
|
|||
db::Texts tt;
|
||||
tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30))));
|
||||
tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0))));
|
||||
EXPECT_EQ (r.selected_interacting (tt).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (tt).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (300, 30))))).to_string (), "");
|
||||
db::Region rr = r;
|
||||
r.select_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (-10, -10)))));
|
||||
|
|
@ -1554,7 +1554,7 @@ TEST(34b)
|
|||
db::Texts tt;
|
||||
tt.insert (db::Text ("abc", db::Trans (db::Vector (30, 30))));
|
||||
tt.insert (db::Text ("xyz", db::Trans (db::Vector (-100, 0))));
|
||||
EXPECT_EQ (r.selected_interacting (tt).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (tt).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (-190, -190))))).to_string (), "");
|
||||
r.select_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (-10, -10)))));
|
||||
EXPECT_EQ (r.to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
|
@ -1588,6 +1588,221 @@ TEST(34d)
|
|||
EXPECT_EQ (r.pull_interacting (db::Texts (db::Text ("abc", db::Trans (db::Vector (-190, -190))))).to_string (), "");
|
||||
}
|
||||
|
||||
TEST(35a_interact_with_count_region)
|
||||
{
|
||||
db::Region r;
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
r.insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Region rr;
|
||||
rr.insert (db::Box (db::Point (-10, -10), db::Point (10, 0)));
|
||||
rr.insert (db::Box (db::Point (-10, 0), db::Point (10, 10)));
|
||||
rr.insert (db::Box (db::Point (-110, -10), db::Point (-90, 10)));
|
||||
rr.insert (db::Box (db::Point (-110, -210), db::Point (-90, -190)));
|
||||
db::Region rr2 = rr;
|
||||
rr.insert (db::Box (db::Point (90, -10), db::Point (110, 10)));
|
||||
rr.insert (db::Box (db::Point (-110, -110), db::Point (-90, -90)));
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(35b_interact_with_count_edge)
|
||||
{
|
||||
db::Region r;
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
r.insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Edges rr;
|
||||
rr.insert (db::Edge (db::Point (-10, -10), db::Point (0, 0)));
|
||||
rr.insert (db::Edge (db::Point (0, 0), db::Point (10, 10)));
|
||||
rr.insert (db::Edge (db::Point (-110, -10), db::Point (-90, 10)));
|
||||
rr.insert (db::Edge (db::Point (-110, -210), db::Point (-90, -190)));
|
||||
db::Edges rr2 = rr;
|
||||
rr.insert (db::Edge (db::Point (90, -10), db::Point (110, 10)));
|
||||
rr.insert (db::Edge (db::Point (-110, -110), db::Point (-90, -90)));
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(35c_interact_with_count_text)
|
||||
{
|
||||
db::Region r;
|
||||
r.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
r.insert (db::Box (db::Point (-100, -100), db::Point (0, 0)));
|
||||
r.set_merged_semantics (true);
|
||||
r.set_min_coherence (false);
|
||||
|
||||
db::Region empty;
|
||||
|
||||
db::Texts rr;
|
||||
rr.insert (db::Text ("a", db::Trans (db::Vector (0, 0))));
|
||||
rr.insert (db::Text ("b", db::Trans (db::Vector (-100, 0))));
|
||||
rr.insert (db::Text ("c", db::Trans (db::Vector (-100, -200))));
|
||||
db::Texts rr2 = rr;
|
||||
rr.insert (db::Text ("x", db::Trans (db::Vector (100, 0))));
|
||||
rr.insert (db::Text ("y", db::Trans (db::Vector (-100, -100))));
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 5, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 2, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_interacting (rr2, 4, 5).to_string (), "");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 4, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 5, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 2).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 2, 5).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr2, 4, 5).to_string (), "(-100,-100;-100,0;0,0;0,200;100,200;100,0;0,0;0,-100)");
|
||||
|
||||
r.set_merged_semantics (false);
|
||||
|
||||
EXPECT_EQ (r.selected_interacting (empty).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 0, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 2).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 1, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100);(0,0;0,200;100,200;100,0)");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 2, 1).to_string (), "");
|
||||
EXPECT_EQ (r.selected_interacting (rr, 3, 4).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
|
||||
EXPECT_EQ (r.selected_not_interacting (empty).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 0, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 2).to_string (), "(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 1, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 4).to_string (), "");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 2, 1).to_string (), "(0,0;0,200;100,200;100,0);(-100,-100;-100,0;0,0;0,-100)");
|
||||
EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)");
|
||||
}
|
||||
|
||||
TEST(100_Processors)
|
||||
{
|
||||
db::Region r;
|
||||
|
|
|
|||
|
|
@ -1673,6 +1673,9 @@ CODE
|
|||
# @name interacting
|
||||
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
|
||||
# @synopsis layer.interacting(other)
|
||||
# @synopsis layer.interacting(other, count)
|
||||
# @synopsis layer.interacting(other, min_count, max_count)
|
||||
# @synopsis layer.interacting(other, min_count .. max_count)
|
||||
# This method selects all shapes or regions from self which touch or overlap shapes from the other
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
|
|
@ -1690,11 +1693,25 @@ CODE
|
|||
# @td @img(/images/drc_interacting.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# If a single count is given, shapes from self are selected only if they do interact with the given
|
||||
# number of (different) shapes from the other layer. If a min and max count is given, shapes from
|
||||
# self are selected only if they interact with min_count or more, but a maximum of max_count different shapes
|
||||
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
|
||||
#
|
||||
# @table
|
||||
# @tr
|
||||
# @td @img(/images/drc_interacting2.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name not_interacting
|
||||
# @brief Selects shapes or regions of self which do not touch or overlap shapes from the other region
|
||||
# @synopsis layer.not_interacting(other)
|
||||
# @synopsis layer.not_interacting(other, count)
|
||||
# @synopsis layer.not_interacting(other, min_count, max_count)
|
||||
# @synopsis layer.not_interacting(other, min_count .. max_count)
|
||||
# This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
|
|
@ -1712,13 +1729,27 @@ CODE
|
|||
# @td @img(/images/drc_not_interacting.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# If a single count is given, shapes from self are selected only if they do not interact with the given
|
||||
# number of (different) shapes from the other layer. If a min and max count is given, shapes from
|
||||
# self are selected only if they interact with less than min_count or more than max_count different shapes
|
||||
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
|
||||
#
|
||||
# @table
|
||||
# @tr
|
||||
# @td @img(/images/drc_not_interacting2.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
|
||||
# %DRC%
|
||||
# @name select_interacting
|
||||
# @brief Selects shapes or regions of self which touch or overlap shapes from the other region
|
||||
# @synopsis layer.select_interacting(other)
|
||||
# @synopsis layer.select_interacting(other, count)
|
||||
# @synopsis layer.select_interacting(other, min_count, max_count)
|
||||
# @synopsis layer.select_interacting(other, min_count .. max_count)
|
||||
# This method selects all shapes or regions from self which touch or overlap shapes from the other
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# layer. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \interacting.
|
||||
|
|
@ -1726,13 +1757,21 @@ CODE
|
|||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
# If a single count is given, shapes from self are selected only if they do interact with the given
|
||||
# number of (different) shapes from the other layer. If a min and max count is given, shapes from
|
||||
# self are selected only if they interact with min_count or more, but a maximum of max_count different shapes
|
||||
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
|
||||
|
||||
# %DRC%
|
||||
# @name select_not_interacting
|
||||
# @brief Selects shapes or regions of self which do not touch or overlap shapes from the other region
|
||||
# @synopsis layer.select_interacting(other)
|
||||
# @synopsis layer.select_not_interacting(other)
|
||||
# @synopsis layer.select_not_interacting(other, count)
|
||||
# @synopsis layer.select_not_interacting(other, min_count, max_count)
|
||||
# @synopsis layer.select_not_interacting(other, min_count .. max_count)
|
||||
# This method selects all shapes or regions from self which do not touch or overlap shapes from the other
|
||||
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# layer. Unless self is in raw mode (see \raw), coherent regions are selected from self,
|
||||
# otherwise individual shapes are selected.
|
||||
# It modifies self to contain the selected shapes. A version which does not modify self
|
||||
# is \not_interacting.
|
||||
|
|
@ -1740,6 +1779,11 @@ CODE
|
|||
# This method is available for polygon, text and edge layers. Edges can be selected
|
||||
# with respect to other edges or polygons. Texts can be selected with respect to
|
||||
# polygons. Polygons can be selected with respect to edges, texts and other polygons.
|
||||
#
|
||||
# If a single count is given, shapes from self are selected only if they do not interact with the given
|
||||
# number of (different) shapes from the other layer. If a min and max count is given, shapes from
|
||||
# self are selected only if they interact with less than min_count or more than max_count different shapes
|
||||
# from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions.
|
||||
|
||||
# %DRC%
|
||||
# @name intersections
|
||||
|
|
@ -1883,7 +1927,7 @@ CODE
|
|||
|
||||
%w(interacting not_interacting).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(other)
|
||||
def #{f}(other, *args)
|
||||
other.requires_edges_texts_or_region("#{f}")
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region("#{f}")
|
||||
|
|
@ -1892,12 +1936,40 @@ CODE
|
|||
else
|
||||
other.requires_edges_or_region("#{f}")
|
||||
end
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data))
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(:#{f}, *args)))
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(interacting not_interacting overlapping not_overlapping inside not_inside outside not_outside).each do |fi|
|
||||
%w(interacting not_interacting).each do |fi|
|
||||
f = "select_" + fi
|
||||
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
|
||||
eval <<"CODE"
|
||||
def #{f}(other, *args)
|
||||
if :#{fi} != :interacting && :#{fi} != :not_interacting
|
||||
requires_edges_or_region("#{f}")
|
||||
requires_same_type(other, "#{f}")
|
||||
else
|
||||
requires_edges_texts_or_region("#{f}")
|
||||
if self.data.is_a?(RBA::Text)
|
||||
other.requires_region("#{f}")
|
||||
elsif self.data.is_a?(RBA::Region)
|
||||
other.requires_edges_texts_or_region("#{f}")
|
||||
else
|
||||
other.requires_edges_or_region("#{f}")
|
||||
end
|
||||
end
|
||||
if @engine.is_tiled?
|
||||
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(:#{f}, *args))
|
||||
DRCLayer::new(@engine, self.data)
|
||||
else
|
||||
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(:#{f}, *args)))
|
||||
end
|
||||
end
|
||||
CODE
|
||||
end
|
||||
|
||||
%w(overlapping not_overlapping inside not_inside outside not_outside).each do |fi|
|
||||
f = "select_" + fi
|
||||
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
|
||||
eval <<"CODE"
|
||||
|
|
@ -3238,6 +3310,42 @@ CODE
|
|||
def requires_same_type(other, f)
|
||||
self.data.class == other.data.class || raise("#{f}: Requires input of the same kind")
|
||||
end
|
||||
|
||||
def minmax_count(f, *args)
|
||||
if args.size == 0
|
||||
return []
|
||||
elsif args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
if a.min.to_i <= 0
|
||||
raise("#{f}: min_count argument must be a positive, non-zero number")
|
||||
end
|
||||
return [a.min.to_i, a.max.to_i]
|
||||
elsif !a.is_a?(1.class)
|
||||
raise("#{f}: count argument must be an integer number")
|
||||
elsif a <= 0
|
||||
raise("#{f}: count argument must be a positive, non-zero number")
|
||||
else
|
||||
return [a, a]
|
||||
end
|
||||
elsif args.size == 2
|
||||
amin = args[0]
|
||||
amax = args[1]
|
||||
if !amin.is_a?(1.class)
|
||||
raise("#{f}: min_count argument must be an integer number")
|
||||
elsif !amax.is_a?(1.class)
|
||||
raise("#{f}: max_count argument must be an integer number")
|
||||
elsif amin <= 0
|
||||
raise("#{f}: min_count argument must be a positive, non-zero number")
|
||||
elsif amax < amin
|
||||
raise("#{f}: max_count argument must be larger or equal to min_count")
|
||||
else
|
||||
return [amin, amax]
|
||||
end
|
||||
else
|
||||
raise("#{f}: too many arguments")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue