WIP: bug fixes, renamed "enclosing" to "covering" in Region/DRC.

Reasoning: "enclosing" was reserved for the DRC function.
This commit is contained in:
Matthias Koefferlein 2020-12-07 23:55:35 +01:00
parent 5934bd529f
commit 0670e83d77
5 changed files with 161 additions and 308 deletions

View File

@ -232,30 +232,27 @@ public:
* @brief Constructor
*
* 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.
* 0 is "overlapping" or "touching".
* -1 will select all secondary polygons inside polygons from the primary.
* -2 will select all secondary polygons enclosing polygons from the primary.
* +1 will select all secondary polygons outside polygons from the primary.
*
* In mode -1 and +1, finish () needs to be called before the interactions
* can be used. In mode -1 and +1, the interactions delivered will contain
* interactions of the reference property vs. the property of the respective
* input polygons (property != reference property). In mode +1 these are
* pseudo-interactions, because "outside" by definition means non-interacting.
* Use set_include_touching(f) to specify whether to include or not include the touching
* case as interacting for mode 0.
*
* Mode -1 (inside) and +1 (outside) requires a property value for the containing (primary) region.
* In modes -2, -1 and +1, finish () needs to be called before the interactions
* can be used.
*
* All modes require property IDs to differentiate both inputs into primary and secondary.
* Property IDs from 0 to the given last primary ID value are considered to belong to
* the primary region.
* the primary region. Property IDs above the last primary ID are considered to belong to
* the secondary 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 <= last_primary_id are considered to belong to the first
* container and property ids > container_id to the second container.
* The reported interactions will be (primary_id,secondary_id) even for outside mode.
* For outside mode, the primary_id is always last_primary_id. In outside mode, the
* interactions are pseudo-interactions as by definition outside polygons don't interact.
*/
InteractionDetector (int mode = 0, property_type primary_id = 0);
InteractionDetector (int mode = 0, property_type last_primary_id = 0);
/**
* @brief Sets the "touching" flag

View File

@ -22,6 +22,7 @@
#include "gsiDecl.h"
#include "gsiEnums.h"
#include "dbDeepShapeStore.h"
#include "dbEdges.h"
@ -211,90 +212,60 @@ static db::Edges with_angle2 (const db::Edges *r, double amin, double amax, bool
return r->filtered (f);
}
static db::EdgePairs width1 (const db::Edges *r, db::Edges::coord_type d)
{
return r->width_check (d);
}
static db::EdgePairs width2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs width2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->width_check (d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
);
}
static db::EdgePairs space1 (const db::Edges *r, db::Edges::coord_type d)
{
return r->space_check (d);
}
static db::EdgePairs space2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs space2 (const db::Edges *r, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->space_check (d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
);
}
static db::EdgePairs inside1 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d)
{
return r->inside_check (other, d);
}
static db::EdgePairs inside2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs inside2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->inside_check (other, d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
);
}
static db::EdgePairs overlap1 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d)
{
return r->overlap_check (other, d);
}
static db::EdgePairs overlap2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs overlap2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->overlap_check (other, d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
);
}
static db::EdgePairs enclosing1 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d)
{
return r->enclosing_check (other, d);
}
static db::EdgePairs enclosing2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs enclosing2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->enclosing_check (other, d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
);
}
static db::EdgePairs separation1 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d)
{
return r->separation_check (other, d);
}
static db::EdgePairs separation2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, const tl::Variant &metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
static db::EdgePairs separation2 (const db::Edges *r, const db::Edges &other, db::Edges::coord_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection)
{
return r->separation_check (other, d, db::EdgesCheckOptions (whole_edges,
metrics.is_nil () ? db::Euclidian : db::metrics_type (metrics.to_int ()),
metrics,
ignore_angle.is_nil () ? 90 : ignore_angle.to_double (),
min_projection.is_nil () ? db::Edges::distance_type (0) : min_projection.to<db::Edges::distance_type> (),
max_projection.is_nil () ? std::numeric_limits<db::Edges::distance_type>::max () : max_projection.to<db::Edges::distance_type> ())
@ -346,21 +317,6 @@ static db::Region extents0 (const db::Edges *r)
return extents2 (r, 0, 0);
}
static int euclidian_metrics ()
{
return db::Euclidian;
}
static int square_metrics ()
{
return db::Square;
}
static int projection_metrics ()
{
return db::Projection;
}
static void insert_r (db::Edges *e, const db::Region &a)
{
for (db::Region::const_iterator p = a.begin (); ! p.at_end (); ++p) {
@ -1097,24 +1053,7 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"\n"
"@return The transformed edge collection.\n"
) +
method_ext ("width_check", &width1, gsi::arg ("d"),
"@brief Performs a width check between edges\n"
"@param d The minimum width for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"To understand the overlap check for edges, one has to be familiar with the concept of the inside and outside "
"interpretation of an edge. An edge is considered a boundary between \"inside\" and \"outside\" where \"inside\" "
"is right to the edge. Although there is not necessarily a contiguous region for edges, the definition of the "
"inside part allows one to specify edge relations which are denoted by \"space\", \"width\", \"inside\" and \"enclosing\". "
"In that sense, width means that another edge is anti-parallel and left to the edge under test with a distance of less than the given "
"threshold."
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\space_check, \\inside_check, \\overlap_check, \\separation_check and \\enclosing_check.\n"
) +
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs a width check with options\n"
"@param d The minimum width for which the edges are checked\n"
"@param whole_edges If true, deliver the whole edges\n"
@ -1123,9 +1062,6 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
"\n"
@ -1143,23 +1079,7 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("space_check", &space1, gsi::arg ("d"),
"@brief Performs a space check between edges\n"
"@param d The minimum distance for which the edges are checked\n"
"To understand the space check for edges, one has to be familiar with the concept of the inside and outside "
"interpretation of an edge. An edge is considered a boundary between \"inside\" and \"outside\" where \"inside\" "
"is right to the edge. Although there is not necessarily a contiguous region for edges, the definition of the "
"inside part allows one to specify edge relations which are denoted by \"space\", \"width\", \"inside\" and \"enclosing\". "
"In that sense, space means that another edge is anti-parallel and right to the edge under test with a distance of less than the given "
"threshold."
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\width_check, \\inside_check, \\overlap_check, \\separation_check and \\enclosing_check.\n"
) +
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs a space check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param whole_edges If true, deliver the whole edges\n"
@ -1168,9 +1088,6 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the space check.\n"
"\n"
@ -1188,24 +1105,7 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("inside_check", &inside1, gsi::arg ("other"), gsi::arg ("d"),
"@brief Performs an inside check between edges\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"To understand the inside check for edges, one has to be familiar with the concept of the inside and outside "
"interpretation of an edge. An edge is considered a boundary between \"inside\" and \"outside\" where \"inside\" "
"is right to the edge. Although there is not necessarily a contiguous region for edges, the definition of the "
"inside part allows one to specify edge relations which are denoted by \"space\", \"width\", \"inside\" and \"enclosing\". "
"In that sense, inside means that another edge is parallel and right to the edge under test with a distance of less than the given "
"threshold."
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\width_check, \\space_check, \\overlap_check, \\separation_check and \\enclosing_check.\n"
) +
method_ext ("inside_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
method_ext ("inside_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs an inside check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
@ -1215,9 +1115,6 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
"\n"
@ -1235,24 +1132,7 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("enclosing_check", &enclosing1, gsi::arg ("other"), gsi::arg ("d"),
"@brief Performs an enclosing check between edges\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"To understand the enclosing check for edges, one has to be familiar with the concept of the inside and outside "
"interpretation of an edge. An edge is considered a boundary between \"inside\" and \"outside\" where \"inside\" "
"is right to the edge. Although there is not necessarily a contiguous region for edges, the definition of the "
"inside part allows one to specify edge relations which are denoted by \"space\", \"width\", \"inside\" and \"enclosing\". "
"In that sense, enclosing means that another edge is parallel and left to the edge under test with a distance of less than the given "
"threshold."
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\width_check, \\space_check, \\overlap_check, \\separation_check and \\inside_check.\n"
) +
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs an enclosing check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
@ -1262,8 +1142,32 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle threshold of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
"Setting this value to 90 (the default) will exclude edges with an angle of 90 degree or more from the check.\n"
"Use nil for this value to select the default.\n"
"\n"
"\"min_projection\" and \"max_projection\" allow selecting edges by their projected value upon each other. "
"It is sufficient if the projection of one edge on the other matches the specified condition. "
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs an overlap check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"@param whole_edges If true, deliver the whole edges\n"
"@param metrics Specify the metrics type\n"
"@param ignore_angle The threshold angle above which no check is performed\n"
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
@ -1282,22 +1186,7 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("overlap_check", &overlap1, gsi::arg ("other"), gsi::arg ("d"),
"@brief Performs an overlap check between edges\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"Technically, the overlap check is a width check between edges from different collections. "
"The check is performed where the edges are orientation towards each other with their 'inside' side "
"and they are orientation anti-parallel. This situation is found where two polygons overlap. Hence the "
"check is an 'overlap' check.\n"
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\width_check, \\space_check, \\enclosing_check, \\separation_check and \\inside_check.\n"
) +
method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"),
"@brief Performs an overlap check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
@ -1307,54 +1196,6 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
"Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle threshold of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
"Setting this value to 90 (the default) will exclude edges with an angle of 90 degree or more from the check.\n"
"Use nil for this value to select the default.\n"
"\n"
"\"min_projection\" and \"max_projection\" allow selecting edges by their projected value upon each other. "
"It is sufficient if the projection of one edge on the other matches the specified condition. "
"The projected length must be larger or equal to \"min_projection\" and less than \"max_projection\". "
"If you don't want to specify one threshold, pass nil to the respective value.\n"
) +
method_ext ("separation_check", &separation1, gsi::arg ("other"), gsi::arg ("d"),
"@brief Performs an separation check between edges\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"Technically, the separation check is a space check between edges from different collections. "
"The check is performed where the edges are orientation towards each other with their 'outside' side "
"and they are orientation anti-parallel. This situation is found where two polygons have a space. Hence the "
"check is a 'separation' check.\n"
"\n"
"This method returns an \\EdgePairs collection which contains the parts of the edges violating the check "
"criterion.\n"
"\n"
"A version of this method is available with more options (i.e. the option the deliver whole edges). "
"Other checks with different edge relations are \\width_check, \\space_check, \\enclosing_check, \\overlap_check and \\inside_check.\n"
) +
method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges"), gsi::arg ("metrics"), gsi::arg ("ignore_angle"), gsi::arg ("min_projection"), gsi::arg ("max_projection"),
"@brief Performs an overlap check with options\n"
"@param d The minimum distance for which the edges are checked\n"
"@param other The other edge collection against which to check\n"
"@param whole_edges If true, deliver the whole edges\n"
"@param metrics Specify the metrics type\n"
"@param ignore_angle The threshold angle above which no check is performed\n"
"@param min_projection The lower threshold of the projected length of one edge onto another\n"
"@param max_projection The upper threshold of the projected length of one edge onto another\n"
"\n"
"This version is similar to the simple version with one parameter. In addition, it allows "
"to specify many more options.\n"
"\n"
"If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole "
"edges which contribute in the width check.\n"
"\n"
@ -1601,35 +1442,6 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
method ("disable_progress", &db::Edges::disable_progress,
"@brief Disable progress reporting\n"
"Calling this method will disable progress reporting. See \\enable_progress.\n"
) +
method ("Euclidian", &euclidian_metrics,
"@brief Specifies Euclidian metrics for the check functions\n"
"This value can be used for the metrics parameter in the check functions, i.e. \\width_check. "
"This value specifies Euclidian metrics, i.e. the distance between two points is measured by:\n"
"\n"
"@code\n"
"d = sqrt(dx^2 + dy^2)\n"
"@/code\n"
"\n"
"All points within a circle with radius d around one point are considered to have a smaller distance than d."
) +
method ("Square", &square_metrics,
"@brief Specifies square metrics for the check functions\n"
"This value can be used for the metrics parameter in the check functions, i.e. \\width_check. "
"This value specifies sqaure metrics, i.e. the distance between two points is measured by:\n"
"\n"
"@code\n"
"d = max(abs(dx), abs(dy))\n"
"@/code\n"
"\n"
"All points within a square with length 2*d around one point are considered to have a smaller distance than d in this metrics."
) +
method ("Projection", &projection_metrics,
"@brief Specifies projected distance metrics for the check functions\n"
"This value can be used for the metrics parameter in the check functions, i.e. \\width_check. "
"This value specifies projected metrics, i.e. the distance is defined as the minimum distance "
"measured perpendicular to one edge. That implies that the distance is defined only where two "
"edges have a non-vanishing projection onto each other."
),
"@brief A collection of edges (Not necessarily describing closed contours)\n"
"\n\n"
@ -1659,5 +1471,9 @@ Class<db::Edges> dec_Edges (decl_dbShapeCollection, "db", "Edges",
"This class has been introduced in version 0.23.\n"
);
// borrow the Metrics constants from Region:
extern gsi::EnumIn<db::Region, db::metrics_type> decl_Region_Metrics;
gsi::ClassExt<db::Edges> inject_Metrics_from_Region_in_Edges (decl_Region_Metrics.defs ());
}

View File

@ -1406,40 +1406,48 @@ 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"
method ("covering", &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 covering polygons from the other region\n"
"\n"
"@return A new region containing the polygons which are enclosing polygons from the other region\n"
"@return A new region containing the polygons which are covering polygons from the other region\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
"\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\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"
method ("not_covering", &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 covering polygons from the other region\n"
"\n"
"@return A new region containing the polygons which are not enclosing polygons from the other region\n"
"@return A new region containing the polygons which are not covering polygons from the other region\n"
"\n"
"Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n"
"\n"
"This attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\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"
method ("select_covering", &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 covering 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 attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\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"
method ("select_not_covering", &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 covering 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 attribute is sometimes called 'enclosing' instead of 'covering', but this term is reserved for the respective DRC function.\n"
"\n"
"This method has been introduced in version 0.27."
) +
method ("inside", &db::Region::selected_inside, gsi::arg ("other"),

View File

@ -1680,14 +1680,15 @@ TEST(26b)
TEST(26c)
{
db::EdgeProcessor ep;
ep.insert (db::Polygon (db::Box (db::Point (0, 0), db::Point (100, 100))), 0);
ep.insert (db::Polygon (db::Box (db::Point (40, 0), db::Point (140, 100))), 1);
ep.insert (db::Polygon (db::Box (db::Point (60, 20), db::Point (160, 120))), 2);
ep.insert (db::Polygon (db::Box (db::Point (110, 50), db::Point (210, 150))), 3);
ep.insert (db::Polygon (db::Box (db::Point (-100, -100), db::Point (1000, 1000))), 4);
ep.insert (db::Polygon (db::Box (db::Point (1000, 1100), db::Point (1100, 1200))), 5);
ep.insert (db::Polygon (db::Box (db::Point (-100, -100), db::Point (1000, 1000))), 0);
ep.insert (db::Polygon (db::Box (db::Point (1000, 1100), db::Point (1100, 1200))), 1);
ep.insert (db::Polygon (db::Box (db::Point (0, 0), db::Point (100, 100))), 2);
ep.insert (db::Polygon (db::Box (db::Point (40, 0), db::Point (140, 100))), 3);
ep.insert (db::Polygon (db::Box (db::Point (60, 20), db::Point (160, 120))), 4);
ep.insert (db::Polygon (db::Box (db::Point (110, 50), db::Point (210, 150))), 5);
ep.insert (db::Polygon (db::Box (db::Point (1000, 1100), db::Point (1010, 1110))), 6);
db::InteractionDetector id (-1, 4); // inside with background #4
db::InteractionDetector id (-1, 0); // inside with background #0
db::EdgeSink es;
ep.process (es, id);
id.finish ();
@ -1701,7 +1702,35 @@ TEST(26c)
}
// does not work yet!
EXPECT_EQ (s, "4:0,4:1,4:2,4:3");
EXPECT_EQ (s, "0:2,0:3,0:4,0:5");
}
TEST(26d)
{
db::EdgeProcessor ep;
ep.insert (db::Polygon (db::Box (db::Point (-100, -100), db::Point (1000, 1000))), 0);
ep.insert (db::Polygon (db::Box (db::Point (1000, 1100), db::Point (1100, 1200))), 1);
ep.insert (db::Polygon (db::Box (db::Point (0, 0), db::Point (100, 100))), 2);
ep.insert (db::Polygon (db::Box (db::Point (40, 0), db::Point (140, 100))), 3);
ep.insert (db::Polygon (db::Box (db::Point (60, 20), db::Point (160, 120))), 4);
ep.insert (db::Polygon (db::Box (db::Point (110, 50), db::Point (210, 150))), 5);
ep.insert (db::Polygon (db::Box (db::Point (1000, 1100), db::Point (1010, 1110))), 6);
db::InteractionDetector id (-1, 1); // inside with background #0 and #1
db::EdgeSink es;
ep.process (es, id);
id.finish ();
std::string s;
for (db::InteractionDetector::iterator i = id.begin (); i != id.end (); ++i) {
if (! s.empty ()) {
s += ",";
}
s += tl::to_string (i->first) + ":" + tl::to_string (i->second);
}
// does not work yet!
EXPECT_EQ (s, "0:2,0:3,0:4,0:5,1:6");
}
TEST(27)

View File

@ -1419,78 +1419,81 @@ CODE
# 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
# @name covering
# @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region
# @synopsis layer.covering(other)
# @synopsis layer.covering(other, min_count)
# @synopsis layer.covering(other, min_count, max_count)
# @synopsis layer.covering(other, min_count .. max_count)
# This method selects all shapes or regions from self which completly cover 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.
# is \select_covering.
#
# 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:
# The following image shows the effect of the "covering" method:
#
# @table
# @tr
# @td @img(/images/drc_enclosing.png) @/td
# @td @img(/images/drc_covering.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.
# only selected when covering a given number of shapes from the other layer.
# For the interpretation of the count see \interacting.
#
# The "covering" attribute is sometimes called "enclosing", but this name is
# used for the respective DRC function (see \enclosing).
# %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
# @name not_covering
# @brief Selects shapes or regions of self which do not cover (enclose) one or more shapes from the other region
# @synopsis layer.not_covering(other)
# @synopsis layer.not_covering(other, min_count)
# @synopsis layer.not_covering(other, min_count, max_count)
# @synopsis layer.not_covering(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not cover 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
# otherwise individual shapes are selected. This method returns the inverse of \covering
# 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.
# is \select_not_covering.
# %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
# @name select_covering
# @brief Selects shapes or regions of self which completely cover (enclose) one or more shapes from the other region
# @synopsis layer.select_covering(other)
# @synopsis layer.select_covering(other, min_count)
# @synopsis layer.select_covering(other, min_count, max_count)
# @synopsis layer.select_covering(other, min_count .. max_count)
# This method selects all shapes or regions from self which cover 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.
# is \covering.
#
# 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
# @name select_not_covering
# @brief Selects shapes or regions of self which do not cover (enclose) one or more shapes from the other region
# @synopsis layer.select_not_covering(other)
# @synopsis layer.select_not_covering(other, min_count)
# @synopsis layer.select_not_covering(other, min_count, max_count)
# @synopsis layer.select_not_covering(other, min_count .. max_count)
# This method selects all shapes or regions from self which do not cover 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.
# is \not_covering.
#
# This method is available for polygon and edge layers. Edges can be selected
# with respect to other edges or polygons.
@ -2068,7 +2071,7 @@ CODE
CODE
end
%w(overlapping not_overlapping enclosing not_enclosing).each do |f|
%w(overlapping not_overlapping covering not_covering).each do |f|
eval <<"CODE"
def #{f}(other, *args)
requires_same_type(other, "#{f}")
@ -2078,7 +2081,7 @@ CODE
CODE
end
%w(overlapping not_overlapping enclosing not_enclosing).each do |fi|
%w(overlapping not_overlapping covering not_covering).each do |fi|
f = "select_" + fi
# In tiled mode, there are no modifying versions. Emulate using the non-modifying one.
eval <<"CODE"
@ -3010,7 +3013,7 @@ CODE
args = [ value, whole_edges, metrics, alim, minp, maxp ]
if self.data.is_a?(RBA::Region)
args << shielded
args << (shielded == nil ? true : shielded)
if :#{f} != :width && :#{f} != :notch
args << opposite_filter
args << rect_filter