diff --git a/src/db/db/dbEdgeProcessor.h b/src/db/db/dbEdgeProcessor.h index 40ed4fcce..ea4a4cf2e 100644 --- a/src/db/db/dbEdgeProcessor.h +++ b/src/db/db/dbEdgeProcessor.h @@ -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 diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 4a6bd2955..a14190af9 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) ); } -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) ); } -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) ); } -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) ); } -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) ); } -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 (), max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to ()) @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 decl_Region_Metrics; +gsi::ClassExt inject_Metrics_from_Region_in_Edges (decl_Region_Metrics.defs ()); + } diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index a71f871f9..1794d6958 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -1406,40 +1406,48 @@ Class 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::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::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::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::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::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::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::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::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"), diff --git a/src/db/unit_tests/dbEdgeProcessorTests.cc b/src/db/unit_tests/dbEdgeProcessorTests.cc index e529edd48..2234b8d25 100644 --- a/src/db/unit_tests/dbEdgeProcessorTests.cc +++ b/src/db/unit_tests/dbEdgeProcessorTests.cc @@ -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) diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 14ca2ce0b..7a6c24446 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -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