WIP: DRC 'enclosing' feature

This commit is contained in:
Matthias Koefferlein 2020-12-07 22:48:03 +01:00
parent ca388150bb
commit 5934bd529f
14 changed files with 411 additions and 71 deletions

View File

@ -545,7 +545,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
return clone ();
} 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 inside, enclosing or interacting and inverse is false ("inside" or "interacting")
// * mode is outside and inverse is true ("not outside")
if ((mode <= 0) != inverse) {
return new EmptyRegion ();
@ -586,7 +586,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
if (mode < 0) {
// NOTE: on "inside", the other region must be merged
// NOTE: on "inside" or "enclosing", 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);
@ -609,8 +609,8 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
// 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);
// cannot only have min_count/max_count in outside mode
tl_assert (mode <= 0);
for (RegionIterator p = other.begin_merged (); ! p.at_end (); ++p) {
if (p->box ().touches (bbox ())) {
@ -621,6 +621,9 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
}
// there should be at least one element to look at for primary
tl_assert (nstart > 0);
size_t n = nstart;
for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p, ++n) {
if (mode > 0 || p->box ().touches (other.bbox ())) {
@ -628,7 +631,7 @@ AsIfFlatRegion::selected_interacting_generic (const Region &other, int mode, boo
}
}
db::InteractionDetector id (mode, 0);
db::InteractionDetector id (mode, nstart - 1);
id.set_include_touching (touching);
db::EdgeSink es;
ep.process (es, id);

View File

@ -188,6 +188,16 @@ public:
return selected_interacting_generic (other, -1, true, true);
}
virtual RegionDelegate *selected_enclosing (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, -2, true, false, min_count, max_count);
}
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, -2, true, true, min_count, max_count);
}
virtual RegionDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, 0, true, false, min_count, max_count);
@ -218,14 +228,14 @@ public:
return selected_interacting_generic (other, true, min_count, max_count);
}
virtual RegionDelegate *selected_overlapping (const Region &other) const
virtual RegionDelegate *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, 0, false, false);
return selected_interacting_generic (other, 0, false, false, min_count, max_count);
}
virtual RegionDelegate *selected_not_overlapping (const Region &other) const
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const
{
return selected_interacting_generic (other, 0, false, true);
return selected_interacting_generic (other, 0, false, true, min_count, max_count);
}
virtual RegionDelegate *pull_inside (const Region &other) const

View File

@ -628,8 +628,8 @@ bool EdgePolygonOp::selects_edges () const
// -------------------------------------------------------------------------------
// InteractionDetector implementation
InteractionDetector::InteractionDetector (int mode, property_type container_id)
: m_mode (mode), m_include_touching (true), m_container_id (container_id)
InteractionDetector::InteractionDetector (int mode, property_type primary_id)
: m_mode (mode), m_include_touching (true), m_last_primary_id (primary_id)
{
// .. nothing yet ..
}
@ -675,39 +675,64 @@ InteractionDetector::edge (bool north, bool enter, property_type p)
inside->erase (p);
if (m_mode != 0) {
// the container objects are delivered last of all coincident edges
// (due to prefer_touch == true and the sorting of coincident edges by property id)
// hence every remaining parts count as non-interacting (outside)
if (p == m_container_id) {
if (m_mode < -1) {
// in enclosing mode report primaries open after a secondary ended as non-interactions: these only partially
// overlap and the outside part qualifies this secondary as non-closing (see "finish")
if (p > m_last_primary_id) {
for (std::set <property_type>::const_iterator i = inside->begin (); i != inside->end (); ++i) {
if (*i != m_container_id) {
if (*i <= m_last_primary_id) {
m_non_interactions.insert (*i);
}
}
}
} else if (m_mode != 0) {
// the primary objects are delivered last of all coincident edges
// (due to prefer_touch == true and the sorting of coincident edges by property id)
// hence every remaining parts count as non-interacting (outside)
if (p <= m_last_primary_id) {
for (std::set <property_type>::const_iterator i = inside->begin (); i != inside->end (); ++i) {
if (*i > m_last_primary_id) {
m_non_interactions.insert (*i);
}
}
}
}
} else if (inside_after > inside_before) {
if (m_mode != 0) {
// in inside/outside mode we are only interested in interactions with the container_id property
if (p != m_container_id) {
// note that the container parts will be delivered first of all coincident
// edges hence we can check whether the container is present even for coincident
// edges
if (inside->find (m_container_id) != inside->end ()) {
m_interactions.insert (std::make_pair (m_container_id, p));
} else {
m_non_interactions.insert (p);
// in enclosing/inside/outside mode we are only interested in interactions with a primary
if (p > m_last_primary_id) {
if (m_mode < -1) {
// enclosing mode: report primaries open when a secondary starts as non-interactions: these only partially
// overlap and the outside part qualifies this secondary as non-closing (see "finish")
for (std::set <property_type>::const_iterator i = inside->begin (); i != inside->end (); ++i) {
if (*i <= m_last_primary_id) {
m_non_interactions.insert (*i);
}
}
} else {
// note that the primary parts will be delivered first of all coincident
// edges hence we can check whether the primary is present even for coincident
// edges
bool any = false;
for (std::set <property_type>::const_iterator i = inside->begin (); i != inside->end (); ++i) {
if (*i != m_container_id) {
m_interactions.insert (std::make_pair (m_container_id, *i));
if (*i <= m_last_primary_id) {
any = true;
m_interactions.insert (std::make_pair (*i, p));
}
}
if (! any) {
m_non_interactions.insert (p);
}
}
} else {
for (std::set <property_type>::const_iterator i = inside->begin (); i != inside->end (); ++i) {
if (*i > m_last_primary_id) {
m_interactions.insert (std::make_pair (p, *i));
}
}
}
@ -750,14 +775,36 @@ InteractionDetector::compare_ns () const
void
InteractionDetector::finish ()
{
if (m_mode < 0) {
if (m_mode < -1) {
// In inside mode remove those objects which have a non-interaction with the container_id property
for (std::set<property_type>::const_iterator p = m_non_interactions.begin (); p != m_non_interactions.end (); ++p) {
m_interactions.erase (std::make_pair (m_container_id, *p));
// In enclosing mode remove those objects which have an interaction with a primary having a non-interaction
std::set<property_type> secondaries_to_delete;
for (std::set<std::pair<property_type, property_type> >::iterator i = m_interactions.begin (); i != m_interactions.end (); ++i) {
if (i->first <= m_last_primary_id && m_non_interactions.find (i->first) != m_non_interactions.end ()) {
secondaries_to_delete.insert (i->second);
}
}
m_non_interactions.clear ();
for (std::set<std::pair<property_type, property_type> >::iterator i = m_interactions.begin (); i != m_interactions.end (); ) {
std::set<std::pair<property_type, property_type> >::iterator ii = i;
++ii;
if (i->first <= m_last_primary_id && secondaries_to_delete.find (i->second) != secondaries_to_delete.end ()) {
m_interactions.erase (i);
}
i = ii;
}
} else if (m_mode == -1) {
// In inside mode remove those objects which have a non-interaction with a primary
for (std::set<std::pair<property_type, property_type> >::iterator i = m_interactions.begin (); i != m_interactions.end (); ) {
std::set<std::pair<property_type, property_type> >::iterator ii = i;
++ii;
if (i->first <= m_last_primary_id && m_non_interactions.find (i->second) != m_non_interactions.end ()) {
m_interactions.erase (i);
}
i = ii;
}
} else if (m_mode > 0) {
@ -768,13 +815,12 @@ InteractionDetector::finish ()
m_interactions.clear ();
for (std::set<property_type>::const_iterator p = m_non_interactions.begin (); p != m_non_interactions.end (); ++p) {
m_interactions.insert (m_interactions.end (), std::make_pair (m_container_id, *p));
m_interactions.insert (m_interactions.end (), std::make_pair (m_last_primary_id, *p));
}
}
m_non_interactions.clear ();
}
}
// -------------------------------------------------------------------------------

View File

@ -234,6 +234,7 @@ public:
* The mode parameter selects the interaction check mode.
* 0 is "overlapping".
* -1 will select all polygons inside polygons from the other layer.
* -2 will select all polygons enclosing polygons from the other layer.
* +1 will select all polygons outside polygons from the other layer.
*
* In mode -1 and +1, finish () needs to be called before the interactions
@ -242,16 +243,19 @@ public:
* input polygons (property != reference property). In mode +1 these are
* pseudo-interactions, because "outside" by definition means non-interacting.
*
* 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 objects must have higher property id's.
* The reported interactions will be (container_id,polygon_id) even for outside mode.
* Mode -1 (inside) and +1 (outside) requires a property value for the containing (primary) region.
* Property IDs from 0 to the given last primary ID value are considered to belong to
* the primary region.
* This last property ID must be specified in the last_primary_id parameter.
* For correct operation, the secondary input must use property IDs bigger than
* last_primary_id.
* The reported interactions will be (primary_id,polygon_id) even for outside mode.
* For outside mode, the primary_id is always last_primary_id.
*
* For mode 0, property ids <= container_id are considered to belong to the first
* For mode 0, property ids <= last_primary_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);
InteractionDetector (int mode = 0, property_type primary_id = 0);
/**
* @brief Sets the "touching" flag
@ -308,7 +312,7 @@ public:
private:
int m_mode;
bool m_include_touching;
property_type m_container_id;
property_type m_last_primary_id;
std::vector <int> m_wcv_n, m_wcv_s;
std::set <property_type> m_inside_n, m_inside_s;
std::set<std::pair<property_type, property_type> > m_interactions;

View File

@ -110,14 +110,16 @@ 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_enclosing (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_enclosing (const Region &, size_t, size_t) 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 *selected_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *selected_not_overlapping (const Region &, size_t, size_t) const { return new EmptyRegion (); }
virtual RegionDelegate *pull_inside (const Region &) const { return new EmptyRegion (); }
virtual RegionDelegate *pull_interacting (const Region &) const { return new EmptyRegion (); }
virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); }

View File

@ -1178,6 +1178,52 @@ public:
return Region (mp_delegate->selected_not_inside (other));
}
/**
* @brief Returns all polygons of this which are enclosing polygons from the other region
*
* Merged semantics applies.
*/
Region &select_enclosing (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
{
set_delegate (mp_delegate->selected_enclosing (other, min_count, max_count));
return *this;
}
/**
* @brief Returns all polygons of this which are not enclosing polygons from the other region
*
* Merged semantics applies.
*/
Region &select_not_enclosing (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
{
set_delegate (mp_delegate->selected_not_enclosing (other, min_count, max_count));
return *this;
}
/**
* @brief Returns all polygons of this which are enclosing polygons from the other region
*
* This method is an out-of-place version of select_enclosing.
*
* Merged semantics applies.
*/
Region selected_enclosing (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
return Region (mp_delegate->selected_enclosing (other, min_count, max_count));
}
/**
* @brief Returns all polygons of this which are not enclosing polygons from the other region
*
* This method is an out-of-place version of select_not_enclosing.
*
* Merged semantics applies.
*/
Region selected_not_enclosing (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_enclosing (other, min_count, max_count));
}
/**
* @brief Selects all polygons of this region which overlap or touch polygons from the other region
*
@ -1329,9 +1375,9 @@ public:
*
* Merged semantics applies.
*/
Region &select_overlapping (const Region &other)
Region &select_overlapping (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
{
set_delegate (mp_delegate->selected_overlapping (other));
set_delegate (mp_delegate->selected_overlapping (other, min_count, max_count));
return *this;
}
@ -1340,9 +1386,9 @@ public:
*
* Merged semantics applies.
*/
Region &select_not_overlapping (const Region &other)
Region &select_not_overlapping (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ())
{
set_delegate (mp_delegate->selected_not_overlapping (other));
set_delegate (mp_delegate->selected_not_overlapping (other, min_count, max_count));
return *this;
}
@ -1353,9 +1399,9 @@ public:
*
* Merged semantics applies.
*/
Region selected_overlapping (const Region &other) const
Region selected_overlapping (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits<size_t>::max ()) const
{
return Region (mp_delegate->selected_overlapping (other));
return Region (mp_delegate->selected_overlapping (other, min_count, max_count));
}
/**
@ -1365,9 +1411,9 @@ public:
*
* Merged semantics applies.
*/
Region selected_not_overlapping (const Region &other) const
Region selected_not_overlapping (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_overlapping (other));
return Region (mp_delegate->selected_not_overlapping (other, min_count, max_count));
}
/**

View File

@ -351,14 +351,16 @@ 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_enclosing (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_enclosing (const Region &other, size_t min_count, size_t max_count) 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 *selected_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *selected_not_overlapping (const Region &other, size_t min_count, size_t max_count) const = 0;
virtual RegionDelegate *pull_inside (const Region &other) const = 0;
virtual RegionDelegate *pull_interacting (const Region &other) const = 0;
virtual EdgesDelegate *pull_interacting (const Edges &other) const = 0;

View File

@ -466,7 +466,9 @@ void interacting_local_operation<TS, TI, TR>::compute_local (db::Layout * /*layo
ep.insert (subject, n);
}
db::InteractionDetector id (m_mode, 0);
tl_assert (nstart > 0);
db::InteractionDetector id (m_mode, nstart - 1);
id.set_include_touching (m_touching);
db::EdgeSink es;
ep.process (es, id);

View File

@ -83,6 +83,19 @@ static db::CompoundRegionOperationNode *new_overlapping (db::CompoundRegionOpera
}
}
static db::CompoundRegionOperationNode *new_enclosing (db::CompoundRegionOperationNode *a, db::CompoundRegionOperationNode *b, bool inverse, size_t min_count, size_t max_count)
{
// TODO: is this correct?
if (a->result_type () != db::CompoundRegionOperationNode::Region) {
throw tl::Exception ("Primary input for interaction compound operation must be of Region type");
}
if (b->result_type () == db::CompoundRegionOperationNode::Region) {
return new db::CompoundRegionInteractOperationNode (a, b, -2, false, inverse, min_count, max_count);
} else {
throw tl::Exception ("Secondary input for enclosing compound operation must be of Region type");
}
}
static db::CompoundRegionOperationNode *new_inside (db::CompoundRegionOperationNode *a, db::CompoundRegionOperationNode *b, bool inverse)
{
// TODO: is this correct?
@ -281,6 +294,9 @@ Class<db::CompoundRegionOperationNode> decl_CompoundRegionOperationNode ("db", "
gsi::constructor ("new_overlapping", &new_overlapping, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("inverse", false), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", std::numeric_limits<size_t>::max (), "unlimited"),
"@brief Creates a node representing an overlapping selection operation between the inputs.\n"
) +
gsi::constructor ("new_enclosing", &new_enclosing, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("inverse", false), gsi::arg ("min_count", size_t (0)), gsi::arg ("max_count", std::numeric_limits<size_t>::max (), "unlimited"),
"@brief Creates a node representing an inside selection operation between the inputs.\n"
) +
gsi::constructor ("new_inside", &new_inside, gsi::arg ("a"), gsi::arg ("b"), gsi::arg ("inverse", false),
"@brief Creates a node representing an inside selection operation between the inputs.\n"
) +

View File

@ -1406,6 +1406,42 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"This operator adds the polygons of the other region to self. "
"This usually creates unmerged regions and polygons may overlap. Use \\merge if you want to ensure the result region is merged.\n"
) +
method ("enclosing", &db::Region::selected_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are completely enclosing polygons from the other region\n"
"\n"
"@return A new region containing the polygons which are enclosing polygons from the other region\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."
) +
method ("not_enclosing", &db::Region::selected_not_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which are not completely enclosing polygons from the other region\n"
"\n"
"@return A new region containing the polygons which are not enclosing polygons from the other region\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."
) +
method ("select_enclosing", &db::Region::select_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons of this region which are completely enclosing polygons from the other region\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.27."
) +
method ("select_not_enclosing", &db::Region::select_not_enclosing, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons of this region which are not completely enclosing polygons from the other region\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.27."
) +
method ("inside", &db::Region::selected_inside, gsi::arg ("other"),
"@brief Returns the polygons of this region which are completely inside polygons from the other region\n"
"\n"
@ -1634,33 +1670,41 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"This method has been introduced in version 0.27\n"
) +
method ("overlapping", &db::Region::selected_overlapping, gsi::arg ("other"),
method ("overlapping", &db::Region::selected_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which overlap polygons from the other region\n"
"\n"
"@return A new region containing the polygons overlapping polygons from the other region\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
"\n"
"The count options have been introduced in version 0.27."
) +
method ("not_overlapping", &db::Region::selected_not_overlapping, gsi::arg ("other"),
method ("not_overlapping", &db::Region::selected_not_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Returns the polygons of this region which do not overlap polygons from the other region\n"
"\n"
"@return A new region containing the polygons not overlapping polygons from the other region\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
"\n"
"The count options have been introduced in version 0.27."
) +
method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"),
method ("select_overlapping", &db::Region::select_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons from this region which overlap polygons from the other region\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"
"The count options have been introduced in version 0.27."
) +
method ("select_not_overlapping", &db::Region::select_not_overlapping, gsi::arg ("other"),
method ("select_not_overlapping", &db::Region::select_not_overlapping, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits<size_t>::max ()), "unlimited"),
"@brief Selects the polygons from this region which do not overlap polygons from the other region\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"
"The count options have been introduced in version 0.27."
) +
method ("pull_inside", &db::Region::pull_inside, gsi::arg ("other"),
"@brief Returns all polygons of \"other\" which are inside polygons of this region\n"

View File

@ -1418,10 +1418,90 @@ CODE
# This method is available for polygon, edge and edge pair layers. An alias
# is "\join". See there for a description of the function.
# %DRC%
# @name enclosing
# @brief Selects shapes or regions of self which completely enclose one or more shapes from the other region
# @synopsis layer.enclosing(other)
# @synopsis layer.enclosing(other, min_count)
# @synopsis layer.enclosing(other, min_count, max_count)
# @synopsis layer.enclosing(other, min_count .. max_count)
# This method selects all shapes or regions from self which enclose shapes from the other
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
# otherwise individual shapes are selected.
# It returns a new layer containing the selected shapes. A version which modifies self
# is \select_enclosing.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
#
# The following image shows the effect of the "enclosing" method:
#
# @table
# @tr
# @td @img(/images/drc_enclosing.png) @/td
# @/tr
# @/table
#
# A range of counts can be specified. If so, the shape from the primary layer is
# only selected when enclosing a given number of shapes from the other layer.
# For the interpretation of the count see \interacting.
# %DRC%
# @name not_enclosing
# @brief Selects shapes or regions of self which do not enclose one or more shapes from the other region
# @synopsis layer.not_enclosing(other)
# @synopsis layer.not_enclosing(other, min_count)
# @synopsis layer.not_enclosing(other, min_count, max_count)
# @synopsis layer.not_enclosing(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not enclose shapes from the other
# region. Unless self is in raw mode (see \raw), coherent regions are selected from self,
# otherwise individual shapes are selected. This method returns the inverse of \enclosing
# and provides the same options.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
# It returns a new layer containing the selected shapes. A version which modifies self
# is \select_not_enclosing.
# %DRC%
# @name select_enclosing
# @brief Selects shapes or regions of self which completely enclose one or more shapes from the other region
# @synopsis layer.select_enclosing(other)
# @synopsis layer.select_enclosing(other, min_count)
# @synopsis layer.select_enclosing(other, min_count, max_count)
# @synopsis layer.select_enclosing(other, min_count .. max_count)
# This method selects all shapes or regions from self which 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.
# It modifies self to contain the selected shapes. A version which does not modify self
# is \enclosing.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
# %DRC%
# @name select_not_enclosing
# @brief Selects shapes or regions of self which do not enclose one or more shapes from the other region
# @synopsis layer.select_not_enclosing(other)
# @synopsis layer.select_not_enclosing(other, min_count)
# @synopsis layer.select_not_enclosing(other, min_count, max_count)
# @synopsis layer.select_not_enclosing(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not enclose shapes from the other
# region. 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_enclosing.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
# %DRC%
# @name overlapping
# @brief Selects shapes or regions of self which overlap shapes from the other region
# @synopsis layer.overlapping(other)
# @synopsis layer.overlapping(other, min_count)
# @synopsis layer.overlapping(other, min_count, max_count)
# @synopsis layer.overlapping(other, min_count .. max_count)
# This method selects all shapes or regions from self which 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.
@ -1438,17 +1518,25 @@ CODE
# @td @img(/images/drc_overlapping.png) @/td
# @/tr
# @/table
#
# A range of counts can be specified. If so, the shape from the primary layer is
# only selected when overlapping a given number of shapes from the other layer.
# For the interpretation of the count see \interacting.
# %DRC%
# @name not_overlapping
# @brief Selects shapes or regions of self which do not overlap shapes from the other region
# @synopsis layer.not_overlapping(other)
# @synopsis layer.not_overlapping(other, min_count)
# @synopsis layer.not_overlapping(other, min_count, max_count)
# @synopsis layer.not_overlapping(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not 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.
# otherwise individual shapes are selected. This method will return the inverse of \overlapping
# and provides the same options.
#
# The "not_overlapping" method is equivalent to the \outside method. It is provided
# as an alias for consistency.
# The "not_overlapping" method is similar to the \outside method. However, "outside" does
# not provide the option to specify counts.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
@ -1459,6 +1547,9 @@ CODE
# @name select_overlapping
# @brief Selects shapes or regions of self which overlap shapes from the other region
# @synopsis layer.select_overlapping(other)
# @synopsis layer.select_overlapping(other, min_count)
# @synopsis layer.select_overlapping(other, min_count, max_count)
# @synopsis layer.select_overlapping(other, min_count .. max_count)
# This method selects all shapes or regions from self which 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.
@ -1472,6 +1563,9 @@ CODE
# @name select_not_overlapping
# @brief Selects shapes or regions of self which do not overlap shapes from the other region
# @synopsis layer.select_not_overlapping(other)
# @synopsis layer.select_not_overlapping(other, min_count)
# @synopsis layer.select_not_overlapping(other, min_count, max_count)
# @synopsis layer.select_not_overlapping(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not 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.
@ -1902,7 +1996,7 @@ CODE
CODE
end
%w(| ^ overlapping not_overlapping inside not_inside outside not_outside in not_in).each do |f|
%w(| ^ inside not_inside outside not_outside in not_in).each do |f|
eval <<"CODE"
def #{f}(other)
requires_same_type(other, "#{f}")
@ -1974,7 +2068,34 @@ CODE
CODE
end
%w(overlapping not_overlapping inside not_inside outside not_outside).each do |fi|
%w(overlapping not_overlapping enclosing not_enclosing).each do |f|
eval <<"CODE"
def #{f}(other, *args)
requires_same_type(other, "#{f}")
requires_edges_or_region("#{f}")
DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(:#{f}, *args)))
end
CODE
end
%w(overlapping not_overlapping enclosing not_enclosing).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)
requires_edges_or_region("#{f}")
requires_same_type(other, "#{f}")
if @engine.is_tiled?
self.data = @engine._tcmd(self.data, 0, self.data.class, :#{fi}, other.data, *minmax_count(:#{fi}, *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(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"

View File

@ -16,6 +16,12 @@ l1.interacting(l2, 1..2).output(102, 0)
l1.interacting(l2, 2..).output(103, 0)
l1.interacting(l2, 1, 2).output(104, 0)
l1.overlapping(l2, 1).output(110, 0)
l1.overlapping(l2, 2).output(111, 0)
l1.overlapping(l2, 1..2).output(112, 0)
l1.overlapping(l2, 2..).output(113, 0)
l1.overlapping(l2, 1, 2).output(114, 0)
l = l1.dup
l.select_interacting(l2, 1)
l.output(200, 0)
@ -32,12 +38,34 @@ l = l1.dup
l.select_interacting(l2, 1, 2)
l.output(204, 0)
l = l1.dup
l.select_overlapping(l2, 1)
l.output(210, 0)
l = l1.dup
l.select_overlapping(l2, 2)
l.output(211, 0)
l = l1.dup
l.select_overlapping(l2, 1..2)
l.output(212, 0)
l = l1.dup
l.select_overlapping(l2, 2..)
l.output(213, 0)
l = l1.dup
l.select_overlapping(l2, 1, 2)
l.output(214, 0)
l1.not_interacting(l2, 1).output(300, 0)
l1.not_interacting(l2, 2).output(301, 0)
l1.not_interacting(l2, 1..2).output(302, 0)
l1.not_interacting(l2, 2..).output(303, 0)
l1.not_interacting(l2, 1, 2).output(304, 0)
l1.not_overlapping(l2, 1).output(310, 0)
l1.not_overlapping(l2, 2).output(311, 0)
l1.not_overlapping(l2, 1..2).output(312, 0)
l1.not_overlapping(l2, 2..).output(313, 0)
l1.not_overlapping(l2, 1, 2).output(314, 0)
l = l1.dup
l.select_not_interacting(l2, 1)
l.output(400, 0)
@ -54,3 +82,19 @@ l = l1.dup
l.select_not_interacting(l2, 1, 2)
l.output(404, 0)
l = l1.dup
l.select_not_overlapping(l2, 1)
l.output(410, 0)
l = l1.dup
l.select_not_overlapping(l2, 2)
l.output(411, 0)
l = l1.dup
l.select_not_overlapping(l2, 1..2)
l.output(412, 0)
l = l1.dup
l.select_not_overlapping(l2, 2..)
l.output(413, 0)
l = l1.dup
l.select_not_overlapping(l2, 1, 2)
l.output(414, 0)

Binary file not shown.

Binary file not shown.