diff --git a/scripts/drc_lvs_doc/create_drc_samples.rb b/scripts/drc_lvs_doc/create_drc_samples.rb index 5594555be4..bbc97987e9 100644 --- a/scripts/drc_lvs_doc/create_drc_samples.rb +++ b/scripts/drc_lvs_doc/create_drc_samples.rb @@ -177,6 +177,37 @@ def produce(s1, s2) run_demo gen, "input.width(1.2, square)", "drc_width3.png" run_demo gen, "input.width(1.2, whole_edges)", "drc_width4.png" +class Gen + def produce(s1, s2) + pts = [ + RBA::Point::new(0, 0), + RBA::Point::new(2000, 0), + RBA::Point::new(2000, 2000), + RBA::Point::new(0, 2000) + ]; + s1.insert(RBA::Polygon::new(pts)) + pts = [ + RBA::Point::new(2000, 2000), + RBA::Point::new(4000, 2000), + RBA::Point::new(4000, 4000), + RBA::Point::new(2000, 4000) + ]; + s1.insert(RBA::Polygon::new(pts)) + pts = [ + RBA::Point::new( 500, 4000), + RBA::Point::new(2500, 4000), + RBA::Point::new(2500, 6000), + RBA::Point::new( 500, 6000) + ]; + s1.insert(RBA::Polygon::new(pts)) + end +end + +gen = Gen::new + +run_demo gen, "input.width(1.0)", "drc_width5.png" +run_demo gen, "input.width(1.0, without_touching_corners)", "drc_width6.png" + class Gen def produce(s1, s2) pts = [ @@ -381,6 +412,45 @@ def produce(s1, s2) " one_side_allowed,\n" + " two_opposite_sides_allowed)", "drc_separation11.png" +class Gen + def produce(s1, s2) + pts = [ + RBA::Point::new(0, 0), + RBA::Point::new(2000, 0), + RBA::Point::new(2000, 1500), + RBA::Point::new(0, 1500) + ]; + s2.insert(RBA::Polygon::new(pts)) + pts = [ + RBA::Point::new(2000, 1500), + RBA::Point::new(3500, 1500), + RBA::Point::new(3500, 3500), + RBA::Point::new(2000, 3500) + ]; + s1.insert(RBA::Polygon::new(pts)) + pts = [ + RBA::Point::new(1000, 3500), + RBA::Point::new(3000, 3500), + RBA::Point::new(3000, 5000), + RBA::Point::new(1000, 5000) + ]; + s2.insert(RBA::Polygon::new(pts)) + pts = [ + RBA::Point::new(1000, 5500), + RBA::Point::new(3000, 5500), + RBA::Point::new(3000, 7000), + RBA::Point::new(1000, 7000) + ]; + s1.insert(RBA::Polygon::new(pts)) + end +end + +gen = Gen::new + +run_demo gen, "input1.sep(input2, 1.0)", "drc_separation12.png" +run_demo gen, "input1.sep(input2, 1.0, without_touching_corners)", "drc_separation13.png" +run_demo gen, "input1.sep(input2, 1.0, without_touching_edges)", "drc_separation14.png" + # ... class Gen diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index e4a482fe2d..4f38b882eb 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -761,12 +761,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co } } - EdgeRelationFilter check (rel, d, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d, options); edge2edge_check_for_edges edge_check (check, *result, other != 0); scanner.process (edge_check, d, db::box_convert ()); diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index 54f0b4f3b0..5a86535fdf 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -1139,12 +1139,7 @@ AsIfFlatRegion::run_check (db::edge_relation_type rel, bool different_polygons, db::RegionIterator polygons (needs_merged_primary ? begin_merged () : begin ()); bool primary_is_merged = ! merged_semantics () || needs_merged_primary || is_merged (); - EdgeRelationFilter check (rel, d, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d, options); std::vector others; std::vector foreign; @@ -1217,12 +1212,7 @@ AsIfFlatRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord std::unique_ptr result (new FlatEdgePairs ()); db::PropertyMapper pm (result->properties_repository (), properties_repository ()); - EdgeRelationFilter check (rel, d, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d, options); for (RegionIterator p (begin_merged ()); ! p.at_end (); ++p) { diff --git a/src/db/db/dbCompoundOperation.cc b/src/db/db/dbCompoundOperation.cc index 21e23c1c48..be321c4932 100644 --- a/src/db/db/dbCompoundOperation.cc +++ b/src/db/db/dbCompoundOperation.cc @@ -1625,19 +1625,13 @@ CompoundRegionEdgePairToEdgeProcessingOperationNode::do_compute_local (CompoundR // --------------------------------------------------------------------------------------------- CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) - : CompoundRegionMultiInputOperationNode (), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false) + : CompoundRegionMultiInputOperationNode (), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false) { set_description ("check"); - - m_check.set_include_zero (false); - m_check.set_whole_edges (options.whole_edges); - m_check.set_ignore_angle (options.ignore_angle); - m_check.set_min_projection (options.min_projection); - m_check.set_max_projection (options.max_projection); } CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) - : CompoundRegionMultiInputOperationNode (input), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false) + : CompoundRegionMultiInputOperationNode (input), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options), m_has_other (false), m_is_other_merged (false) { set_description ("check"); @@ -1645,16 +1639,10 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi if (pc_always_different (m_options.prop_constraint)) { m_different_polygons = true; } - - m_check.set_include_zero (false); - m_check.set_whole_edges (options.whole_edges); - m_check.set_ignore_angle (options.ignore_angle); - m_check.set_min_projection (options.min_projection); - m_check.set_max_projection (options.max_projection); } CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegionOperationNode *input, CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, const db::RegionCheckOptions &options) - : CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options.metrics), m_different_polygons (different_polygons), m_options (options) + : CompoundRegionMultiInputOperationNode (other), m_check (rel, d, options), m_different_polygons (different_polygons), m_options (options) { tl_assert (input == 0); // input is a dummy parameter @@ -1663,12 +1651,6 @@ CompoundRegionCheckOperationNode::CompoundRegionCheckOperationNode (CompoundRegi m_is_other_merged = other->is_merged (); set_description ("check"); - - m_check.set_include_zero (false); - m_check.set_whole_edges (options.whole_edges); - m_check.set_ignore_angle (options.ignore_angle); - m_check.set_min_projection (options.min_projection); - m_check.set_max_projection (options.max_projection); } db::OnEmptyIntruderHint diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 5a28122078..a9608af23a 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -2046,12 +2046,7 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord const db::DeepLayer &edges = merged_deep_layer (); - EdgeRelationFilter check (rel, d, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d, options); std::unique_ptr res (new db::DeepEdgePairs (edges.derived ())); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index ceb7cf0a96..f44f0fca73 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1940,12 +1940,7 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons const db::DeepLayer &polygons = needs_merged_primary ? merged_deep_layer () : deep_layer (); - EdgeRelationFilter check (rel, d, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d, options); std::unique_ptr res (new db::DeepEdgePairs (polygons.derived ())); @@ -2008,12 +2003,7 @@ DeepRegion::run_single_polygon_check (db::edge_relation_type rel, db::Coord d, c double mag = tr.mag (); db::Coord d_with_mag = db::coord_traits::rounded (d / mag); - EdgeRelationFilter check (rel, d_with_mag, options.metrics); - check.set_include_zero (false); - check.set_whole_edges (options.whole_edges); - check.set_ignore_angle (options.ignore_angle); - check.set_min_projection (options.min_projection); - check.set_max_projection (options.max_projection); + EdgeRelationFilter check (rel, d_with_mag, options); const db::Shapes &shapes = c->shapes (polygons.layer ()); db::Shapes &result = c->shapes (res->deep_layer ().layer ()); diff --git a/src/db/db/dbEdgePairRelations.cc b/src/db/db/dbEdgePairRelations.cc index 4875b29b4c..3e62bd3ca4 100644 --- a/src/db/db/dbEdgePairRelations.cc +++ b/src/db/db/dbEdgePairRelations.cc @@ -48,17 +48,53 @@ db::Edge::distance_type edge_projection (const db::Edge &a, const db::Edge &b) return db::coord_traits::rounded (a.double_length () * fabs (l2 - l1)); } +/** + * @brief Gets a flag indicating whether zero distance is included in the checks + */ +static bool include_zero_flag (zero_distance_mode zd_mode, const db::Edge &a, const db::Edge &b) +{ + if (zd_mode == AlwaysIncludeZeroDistance) { + + return true; + + } else if (zd_mode == NeverIncludeZeroDistance) { + + return false; + + } else { + + int s1 = a.side_of (b.p1 ()); + int s2 = a.side_of (b.p2 ()); + + if (s1 == 0 && s2 == 0) { + if (zd_mode == IncludeZeroDistanceWhenTouching || zd_mode == IncludeZeroDistanceWhenCollinearAndTouching) { + return a.intersect (b); + } else if (zd_mode == IncludeZeroDistanceWhenOverlapping) { + return a.coincident (b); + } + } else if ((s1 == 0 || s2 == 0) && a.p1 () != b.p2 () && a.p2 () != b.p1 ()) { + if (zd_mode == IncludeZeroDistanceWhenTouching) { + return a.intersect (b); + } + } + + return false; + + } +} + /** * @brief Returns the part of the "other" edge which is on the inside side of e and within distance d * * This function applies Euclidian metrics. * If no such part is found, this function returns false. + * + * The input edges are normalized to "width" orientation. */ -bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) +bool euclidian_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) { // Handle the case of point-like basic edge: cannot determine // orientation - if (e.is_degenerate ()) { return false; } @@ -67,11 +103,7 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits int s1 = e.side_of (g.p1 ()); int s2 = e.side_of (g.p2 ()); - // "kissing corner" issue: force include zero if the edges are collinear and overlap. - if (! include_zero && s1 == 0 && s2 == 0 && e.intersect (g)) { - include_zero = true; - } - + bool include_zero = include_zero_flag (zd_mode, e, g); int thr = include_zero ? 0 : -1; // keep only part of other which is on the "inside" side of e @@ -89,18 +121,18 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits db::Point o = g.p1 (); - if (e.side_of (o) >= 0) { + if (e.side_of (o) > thr) { return false; } double a = e.double_sq_length (); - double b = db::sprod (db::Vector (e.p1 () - o), e.d ()); - double c = e.p1 ().sq_double_distance (o) - d * d; + double b = db::sprod (db::Vector (e.p1 () - o), e.d ()) / a; + double c = (e.p1 ().sq_double_distance (o) - double (d) * double (d)) / a; - double s = b * b - a * c; - if (s >= 0) { - double l1 = std::max (0.0, (-b - sqrt (s)) / a); - double l2 = std::min (1.0, (-b + sqrt (s)) / a); + double s = b * b - c; + if (s >= -db::epsilon) { + double l1 = std::max (0.0, (-b - sqrt (s))); + double l2 = std::min (1.0, (-b + sqrt (s))); if (l1 <= l2) { if (output) { *output = g; @@ -167,13 +199,13 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits db::Point o = i ? e.p2 () : e.p1 (); double a = g.double_sq_length (); - double b = db::sprod (db::Vector (g.p1 () - o), g.d ()); - double c = g.p1 ().sq_double_distance (o) - double (d) * double (d); + double b = db::sprod (db::Vector (g.p1 () - o), g.d ()) / a; + double c = (g.p1 ().sq_double_distance (o) - double (d) * double (d)) / a; - double s = b * b - a * c; - if (s >= 0) { - l1 = std::min (l1, (-b - sqrt (s)) / a); - l2 = std::max (l2, (-b + sqrt (s)) / a); + double s = b * b - c; + if (s >= -db::epsilon) { + l1 = std::min (l1, -b - sqrt (s)); + l2 = std::max (l2, -b + sqrt (s)); } } @@ -181,7 +213,7 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits l1 = std::max (0.0, l1); l2 = std::min (1.0, l2); - if (l1 >= l2) { + if (l1 > l2 - db::epsilon) { return false; } else { if (output) { @@ -194,10 +226,12 @@ bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits /** * @brief Returns the part of the "other" edge which is on the inside side of e and within distance d * - * This function applies Square metrics. + * This function applies Projection or Square metrics. * If no such part is found, this function returns false. + * + * The input edges are normalized to "width" orientation. */ -static bool var_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, db::coord_traits::distance_type dd, const db::Edge &e, const db::Edge &other, db::Edge *output) +static bool var_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits::distance_type d, db::coord_traits::distance_type dd, const db::Edge &e, const db::Edge &other, db::Edge *output) { // Handle the case of point-like basic edge: cannot determine // orientation @@ -210,11 +244,7 @@ static bool var_near_part_of_edge (bool include_zero, db::coord_traits= 0) { + if (e.side_of (g.p1 ()) > thr) { + return false; + } + if (double (e.distance (g.p1 ())) <= -double (d)) { return false; } if (db::sprod (db::Vector (g.p1 () - e.p1 ()), e.d ()) < -(dd * e.double_length ())) { @@ -314,9 +346,9 @@ static bool var_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) +bool projected_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) { - return var_near_part_of_edge (include_zero, d, 0, e, other, output); + return var_near_part_of_edge (zd_mode, d, 0, e, other, output); } /** @@ -325,20 +357,26 @@ bool projected_near_part_of_edge (bool include_zero, db::coord_traits * This function applies Square metrics. * If no such part is found, this function returns false. */ -bool square_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) +bool square_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &other, db::Edge *output) { - return var_near_part_of_edge (include_zero, d, d, e, other, output); + return var_near_part_of_edge (zd_mode, d, d, e, other, output); } // --------------------------------------------------------------------------------- // Implementation of EdgeRelationFilter -EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection) - : m_whole_edges (false), m_include_zero (true), m_r (r), m_d (d), m_metrics (metrics), m_ignore_angle (0), m_min_projection (min_projection), m_max_projection (max_projection) +EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics, double ignore_angle, distance_type min_projection, distance_type max_projection, zero_distance_mode zd_mode) + : m_whole_edges (false), m_zero_distance_mode (zd_mode), m_r (r), m_d (d), m_metrics (metrics), m_ignore_angle (0), m_min_projection (min_projection), m_max_projection (max_projection) { set_ignore_angle (ignore_angle); } +EdgeRelationFilter::EdgeRelationFilter (edge_relation_type r, distance_type d, const EdgesCheckOptions &options) + : m_whole_edges (options.whole_edges), m_zero_distance_mode (options.zd_mode), m_r (r), m_d (d), m_metrics (options.metrics), m_ignore_angle (0), m_min_projection (options.min_projection), m_max_projection (options.max_projection) +{ + set_ignore_angle (options.ignore_angle); +} + void EdgeRelationFilter::set_ignore_angle (double a) { @@ -399,14 +437,14 @@ EdgeRelationFilter::check (const db::Edge &a, const db::Edge &b, db::EdgePair *o bool in1, in2; if (m_metrics == Euclidian) { - in2 = euclidian_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); - in1 = euclidian_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); + in2 = euclidian_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); + in1 = euclidian_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); } else if (m_metrics == Square) { - in2 = square_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); - in1 = square_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); + in2 = square_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); + in1 = square_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); } else { - in2 = projected_near_part_of_edge (m_include_zero, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); - in1 = projected_near_part_of_edge (m_include_zero, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); + in2 = projected_near_part_of_edge (m_zero_distance_mode, m_d, an, bn, ! m_whole_edges && output ? &output->second () : 0); + in1 = projected_near_part_of_edge (m_zero_distance_mode, m_d, bn, an, ! m_whole_edges && output ? &output->first () : 0); } if (in1 && in2) { diff --git a/src/db/db/dbEdgePairRelations.h b/src/db/db/dbEdgePairRelations.h index 99b5aec6cb..8345b26b13 100644 --- a/src/db/db/dbEdgePairRelations.h +++ b/src/db/db/dbEdgePairRelations.h @@ -98,6 +98,111 @@ enum edge_relation_type InsideRelation = 4 }; +/** + * @brief An enum specifying whether how edges with zero distance are handled in checks + */ +enum zero_distance_mode { + + /** + * @brief Never include zero-distance edges + */ + NeverIncludeZeroDistance = 0, + + /** + * @brief Include zero-distance edges when they share at least one common point + */ + IncludeZeroDistanceWhenTouching = 1, + + /** + * @brief Include zero-distance edges when they share at least one common point and are collinear + */ + IncludeZeroDistanceWhenCollinearAndTouching = 2, + + /** + * @brief Include zero-distance edges when they share more than a single common point (this implies that they are collinear) + */ + IncludeZeroDistanceWhenOverlapping = 3, + + /** + * @brief Always include zero-distance edges (hardly useful) + */ + AlwaysIncludeZeroDistance = 4 +}; + +/** + * @brief A structure holding the options for the region checks (space, width, ...) + */ +struct DB_PUBLIC EdgesCheckOptions +{ + typedef db::coord_traits::distance_type distance_type; + + /** + * @brief Constructor + */ + EdgesCheckOptions (bool _whole_edges = false, + metrics_type _metrics = db::Euclidian, + double _ignore_angle = 90, + distance_type _min_projection = 0, + distance_type _max_projection = std::numeric_limits::max (), + zero_distance_mode _zd_mode = IncludeZeroDistanceWhenTouching) + : whole_edges (_whole_edges), + metrics (_metrics), + ignore_angle (_ignore_angle), + min_projection (_min_projection), + max_projection (_max_projection), + zd_mode (_zd_mode) + { } + + /** + * @brief Specifies is whole edges are to be delivered + * + * Without "whole_edges", the parts of + * the edges are returned which violate the condition. If "whole_edges" is true, the + * result will contain the complete edges participating in the result. + */ + bool whole_edges; + + /** + * @brief Measurement metrics + * + * The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected" + * metrics are available. + */ + metrics_type metrics; + + /** + * @brief Specifies the obtuse angle threshold + * + * "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate + * in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked, + * but acute corners are for example. + */ + double ignore_angle; + + /** + * @brief Specifies the projection limit's minimum value + * + * With min_projection and max_projection it is possible to specify how edges must be related + * to each other. If the length of the projection of either edge on the other is >= min_projection + * or < max_projection, the edges are considered for the check. + */ + distance_type min_projection; + + /** + * @brief Specifies the projection limit's maximum value + */ + distance_type max_projection; + + /** + * @brief Specifies zero-distance edge handling + * + * This allows implementing the "kissing corners" case. When set to "IncludeZeroDistanceWhenTouching", kissing corners will + * be reported as errors, when set to "NeverIncludeZeroDistance", they won't. Note that with merged inputs, edges + * will not overlap except at the corners. + */ + zero_distance_mode zd_mode; +}; + /** * @brief A filter based on the edge pair relation * @@ -123,9 +228,14 @@ struct DB_PUBLIC EdgeRelationFilter * to each other. If the length of the projection of either edge on the other is >= min_projection * or < max_projection, the edges are considered for the check. */ - EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits::max ()); + EdgeRelationFilter (edge_relation_type r, distance_type d, metrics_type metrics = db::Euclidian, double ignore_angle = 90, distance_type min_projection = 0, distance_type max_projection = std::numeric_limits::max (), zero_distance_mode include_zero = AlwaysIncludeZeroDistance); - /** + /** + * Constructs an edge relation filter from a CheckOptions structure + */ + EdgeRelationFilter (edge_relation_type r, distance_type d, const EdgesCheckOptions &options); + + /** * @brief Tests whether two edges fulfil the check fail criterion * * If the output pointer is non-null, the object will receive the edge pair that @@ -150,19 +260,19 @@ struct DB_PUBLIC EdgeRelationFilter } /** - * @brief Sets a flag indicating whether zero distance shall be included in the check + * @brief Sets a value indicating whether zero-distance edges shall be included in the check */ - void set_include_zero (bool f) + void set_zero_distance_mode (zero_distance_mode f) { - m_include_zero = f; + m_zero_distance_mode = f; } /** - * @brief Gets a flag indicating whether zero distance shall be included in the check + * @brief Gets a value indicating whether zero-distance edges shall be included in the check */ - bool include_zero () const + zero_distance_mode get_zero_distance_mode () const { - return m_include_zero; + return m_zero_distance_mode; } /** @@ -262,7 +372,7 @@ struct DB_PUBLIC EdgeRelationFilter private: bool m_whole_edges; - bool m_include_zero; + zero_distance_mode m_zero_distance_mode; edge_relation_type m_r; distance_type m_d; metrics_type m_metrics; @@ -273,9 +383,9 @@ struct DB_PUBLIC EdgeRelationFilter // Internal methods exposed for testing purposes -DB_PUBLIC bool projected_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); -DB_PUBLIC bool square_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); -DB_PUBLIC bool euclidian_near_part_of_edge (bool include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); +DB_PUBLIC bool projected_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); +DB_PUBLIC bool square_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); +DB_PUBLIC bool euclidian_near_part_of_edge (zero_distance_mode include_zero, db::coord_traits::distance_type d, const db::Edge &e, const db::Edge &g, db::Edge *output); DB_PUBLIC db::Edge::distance_type edge_projection (const db::Edge &a, const db::Edge &b); } diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 919ba5b8a2..051d671eec 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -39,69 +39,6 @@ namespace db { -/** - * @brief A structure holding the options for the region checks (space, width, ...) - */ -struct DB_PUBLIC EdgesCheckOptions -{ - typedef db::coord_traits::distance_type distance_type; - - /** - * @brief Constructor - */ - EdgesCheckOptions (bool _whole_edges = false, - metrics_type _metrics = db::Euclidian, - double _ignore_angle = 90, - distance_type _min_projection = 0, - distance_type _max_projection = std::numeric_limits::max ()) - : whole_edges (_whole_edges), - metrics (_metrics), - ignore_angle (_ignore_angle), - min_projection (_min_projection), - max_projection (_max_projection) - { } - - /** - * @brief Specifies is whole edges are to be delivered - * - * Without "whole_edges", the parts of - * the edges are returned which violate the condition. If "whole_edges" is true, the - * result will contain the complete edges participating in the result. - */ - bool whole_edges; - - /** - * @brief Measurement metrics - * - * The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected" - * metrics are available. - */ - metrics_type metrics; - - /** - * @brief Specifies the obtuse angle threshold - * - * "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate - * in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked, - * but acute corners are for example. - */ - double ignore_angle; - - /** - * @brief Specifies the projection limit's minimum value - * - * With min_projection and max_projection it is possible to specify how edges must be related - * to each other. If the length of the projection of either edge on the other is >= min_projection - * or < max_projection, the edges are considered for the check. - */ - distance_type min_projection; - - /** - * @brief Specifies the projection limit's maximum value - */ - distance_type max_projection; -}; - /** * @brief A base class for edge filters */ diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 90e91053e4..27b09b187a 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -113,6 +113,7 @@ enum OppositeFilter * @brief A structure holding the options for the region checks (space, width, ...) */ struct DB_PUBLIC RegionCheckOptions + : public EdgesCheckOptions { typedef db::coord_traits::distance_type distance_type; @@ -128,12 +129,9 @@ struct DB_PUBLIC RegionCheckOptions OppositeFilter _opposite_filter = NoOppositeFilter, RectFilter _rect_filter = NoRectFilter, bool _negative = false, - PropertyConstraint _prop_constraint = IgnoreProperties) - : whole_edges (_whole_edges), - metrics (_metrics), - ignore_angle (_ignore_angle), - min_projection (_min_projection), - max_projection (_max_projection), + PropertyConstraint _prop_constraint = IgnoreProperties, + zero_distance_mode _zd_mode = IncludeZeroDistanceWhenTouching) + : EdgesCheckOptions (_whole_edges, _metrics, _ignore_angle, _min_projection, _max_projection, _zd_mode), shielded (_shielded), opposite_filter (_opposite_filter), rect_filter (_rect_filter), @@ -141,46 +139,6 @@ struct DB_PUBLIC RegionCheckOptions prop_constraint (_prop_constraint) { } - /** - * @brief Specifies is whole edges are to be delivered - * - * Without "whole_edges", the parts of - * the edges are returned which violate the condition. If "whole_edges" is true, the - * result will contain the complete edges participating in the result. - */ - bool whole_edges; - - /** - * @brief Measurement metrics - * - * The metrics parameter specifies which metrics to use. "Euclidian", "Square" and "Projected" - * metrics are available. - */ - metrics_type metrics; - - /** - * @brief Specifies the obtuse angle threshold - * - * "ignore_angle" allows specification of a maximum angle that connected edges can have to not participate - * in the check. By choosing 90 degree, edges with angles of 90 degree and larger are not checked, - * but acute corners are for example. - */ - double ignore_angle; - - /** - * @brief Specifies the projection limit's minimum value - * - * With min_projection and max_projection it is possible to specify how edges must be related - * to each other. If the length of the projection of either edge on the other is >= min_projection - * or < max_projection, the edges are considered for the check. - */ - distance_type min_projection; - - /** - * @brief Specifies the projection limit's maximum value - */ - distance_type max_projection; - /** * @brief Specifies shielding * diff --git a/src/db/db/dbRegionUtils.cc b/src/db/db/dbRegionUtils.cc index 5084c03328..15b7b8bc7a 100644 --- a/src/db/db/dbRegionUtils.cc +++ b/src/db/db/dbRegionUtils.cc @@ -359,12 +359,7 @@ SinglePolygonCheck::process (const db::Polygon &polygon, std::vector result; - EdgeRelationFilter check (m_relation, m_d, m_options.metrics); - check.set_include_zero (false); - check.set_whole_edges (m_options.whole_edges); - check.set_ignore_angle (m_options.ignore_angle); - check.set_min_projection (m_options.min_projection); - check.set_max_projection (m_options.max_projection); + EdgeRelationFilter check (m_relation, m_d, m_options); edge2edge_check_negative_or_positive > edge_check (check, result, m_options.negative, false /*=same polygons*/, false /*=same layers*/, m_options.shielded, true /*=symmetric*/); poly2poly_check poly_check (edge_check); diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index dd88ca6d25..7821515537 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -390,23 +390,27 @@ static db::CompoundRegionOperationNode *new_edge_pair_to_second_edges (db::Compo return new db::CompoundRegionEdgePairToEdgeProcessingOperationNode (new db::EdgePairToSecondEdgesProcessor (), input, true /*processor is owned*/); } -static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_check_node (db::CompoundRegionOperationNode *other, db::edge_relation_type rel, bool different_polygons, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { check_non_null (other, "other"); - return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, - db::RegionCheckOptions (whole_edges, - metrics, - ignore_angle.is_nil () ? 90 : ignore_angle.to_double (), - min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to (), - max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), - shielded, - opposite_filter, - rect_filter, - negative) - ); + + db::RegionCheckOptions options; + + options.whole_edges = whole_edges; + options.metrics = metrics; + options.ignore_angle = ignore_angle.is_nil () ? 90 : ignore_angle.to_double (); + options.min_projection = min_projection.is_nil () ? db::Region::distance_type (0) : min_projection.to (); + options.max_projection = max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (); + options.shielded = shielded; + options.opposite_filter = opposite_filter; + options.rect_filter = rect_filter; + options.negative = negative; + options.zd_mode = zd_mode; + + return new db::CompoundRegionCheckOperationNode (0, other, rel, different_polygons, d, options); } -static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative) +static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::zero_distance_mode zd_mode, bool negative) { db::RegionCheckOptions options (whole_edges, metrics, @@ -415,28 +419,29 @@ static db::CompoundRegionOperationNode *new_width_check (db::Coord d, bool whole max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), shielded); options.negative = negative; + options.zd_mode = zd_mode; return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::WidthRelation, d, options), new_primary (), true /*processor is owned*/); } -static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative, bool isolated) +static db::CompoundRegionOperationNode *new_space_or_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative, bool isolated) { // NOTE: we have to use the "foreign" scheme with a filter because only this scheme // guarantees that all subject shapes are visited and receive all intruders. Having all intruders is crucial for the // semantics of the "drc" feature - return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); + return new_check_node (new_foreign (), db::SpaceRelation, isolated, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative); } -static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_space_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, false); + return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative, false); } -static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_isolated_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative, true); + return new_space_or_isolated_check (d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative, true); } -static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative) +static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::zero_distance_mode zd_mode, bool negative) { db::RegionCheckOptions options (whole_edges, metrics, @@ -445,27 +450,28 @@ static db::CompoundRegionOperationNode *new_notch_check (db::Coord d, bool whole max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), shielded); options.negative = negative; + options.zd_mode = zd_mode; return new db::CompoundRegionToEdgePairProcessingOperationNode (new db::SinglePolygonCheck (db::SpaceRelation, d, options), new_primary (), true /*processor is owned*/); } -static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_separation_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); + return new_check_node (other, db::SpaceRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative); } -static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_overlap_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); + return new_check_node (other, db::WidthRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative); } -static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_enclosing_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); + return new_check_node (other, db::OverlapRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative); } -static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, bool negative) +static db::CompoundRegionOperationNode *new_enclosed_check (db::CompoundRegionOperationNode *other, db::Coord d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite_filter, db::RectFilter rect_filter, db::zero_distance_mode zd_mode, bool negative) { - return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, negative); + return new_check_node (other, db::InsideRelation, true, d, whole_edges, metrics, ignore_angle, min_projection, max_projection, shielded, opposite_filter, rect_filter, zd_mode, negative); } static db::CompoundRegionOperationNode *new_perimeter_filter (db::CompoundRegionOperationNode *input, bool inverse, db::coord_traits::perimeter_type pmin, db::coord_traits::perimeter_type pmax) @@ -660,31 +666,45 @@ Class decl_CompoundRegionOperationNode ("db", " gsi::constructor ("new_minkowski_sum|#new_minkowsky_sum", &new_minkowski_sum_node4, gsi::arg ("input"), gsi::arg ("p"), "@brief Creates a node providing a Minkowski sum with a point sequence forming a contour.\n" ) + - gsi::constructor ("new_width_check", &new_width_check, 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."), gsi::arg ("shielded", true), gsi::arg ("negative", false), + gsi::constructor ("new_width_check", &new_width_check, 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."), gsi::arg ("shielded", true), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing a width check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_space_check", &new_space_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_space_check", &new_space_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing a space check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_isolated_check", &new_isolated_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_isolated_check", &new_isolated_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing a isolated polygons (space between different polygons) check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_notch_check", &new_notch_check, 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."), gsi::arg ("shielded", true), gsi::arg ("negative", false), + gsi::constructor ("new_notch_check", &new_notch_check, 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."), gsi::arg ("shielded", true), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing a intra-polygon space check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_separation_check", &new_separation_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_separation_check", &new_separation_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing a separation check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_overlap_check", &new_overlap_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_overlap_check", &new_overlap_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing an overlap check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_enclosing_check", &new_enclosing_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_enclosing_check", &new_enclosing_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing an inside (enclosure) check.\n" + "\n" + "The zero_distance_mode argument has been inserted in version 0.29.\n" ) + - gsi::constructor ("new_enclosed_check", &new_enclosed_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), + gsi::constructor ("new_enclosed_check", &new_enclosed_check, 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."), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), gsi::arg ("negative", false), "@brief Creates a node providing an enclosed (secondary enclosing primary) check.\n" "\n" - "This method has been added in version 0.27.5.\n" + "This method has been added in version 0.27.5. The zero_distance_mode argument has been inserted in version 0.29.\n" ) + gsi::constructor ("new_perimeter_filter", &new_perimeter_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("pmin", 0), gsi::arg ("pmax", std::numeric_limits::perimeter_type>::max (), "max"), "@brief Creates a node filtering the input by perimeter.\n" @@ -803,9 +823,7 @@ Class decl_CompoundRegionOperationNode ("db", " "\n" "The search distance for intruder shapes is determined by the operation and computed from the operation's requirements.\n" "\n" - "NOTE: this feature is experimental and not deployed into the the DRC framework yet.\n" - "\n" - "This class has been introduced in version 0.27." + "This class has been introduced in version 0.27. The API is considered internal and will change without notice." ); gsi::EnumIn decl_dbCompoundRegionLogicalBoolOperationNode_LogicalOp ("db", "LogicalOp", diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 718b6d16b8..f74687b1be 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -234,63 +234,69 @@ static db::Edges with_angle3 (const db::Edges *r, db::SpecialEdgeOrientationFilt return r->filtered (f); } -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) +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, db::zero_distance_mode zd_mode) { return r->width_check (d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } -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) +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, db::zero_distance_mode zd_mode) { return r->space_check (d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } -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) +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, db::zero_distance_mode zd_mode) { return r->inside_check (other, d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } -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) +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, db::zero_distance_mode zd_mode) { return r->overlap_check (other, d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } -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) +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, db::zero_distance_mode zd_mode) { return r->enclosing_check (other, d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } -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) +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, db::zero_distance_mode zd_mode) { return r->separation_check (other, d, db::EdgesCheckOptions (whole_edges, 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 ()) + max_projection.is_nil () ? std::numeric_limits::max () : max_projection.to (), + zd_mode) ); } @@ -1399,7 +1405,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "This variant has been introduced in version 0.27." ) + - 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"), + 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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1407,6 +1413,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -1424,8 +1431,10 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "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" + "\n" + "'zero_distance_mode' has been added in version 0.29." ) + - 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"), + 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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1433,6 +1442,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the space check.\n" @@ -1450,8 +1460,10 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "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" + "\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("inside_check|enclosed_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"), + method_ext ("inside_check|enclosed_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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1460,6 +1472,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -1479,8 +1492,9 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "If you don't want to specify one threshold, pass nil to the respective value.\n" "\n" "The 'enclosed_check' alias was introduced in version 0.27.5.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - 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"), + 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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1489,6 +1503,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -1506,8 +1521,10 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "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" + "\n" + "'zero_distance_mode' has been added in version 0.29." ) + - 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"), + 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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1516,6 +1533,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -1533,8 +1551,10 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "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" + "\n" + "'zero_distance_mode' has been added in version 0.29." ) + - 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"), + 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"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@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" @@ -1543,6 +1563,7 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "@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" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -1560,6 +1581,8 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "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" + "\n" + "'zero_distance_mode' has been added in version 0.29." ) + method_ext ("extents", &extents0, "@brief Returns a region with the bounding boxes of the edges\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index a51a139256..8310e8e83d 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -510,7 +510,7 @@ static db::Region merged_ext2 (db::Region *r, bool min_coherence, int min_wc) return r->merged (min_coherence, std::max (0, min_wc - 1)); } -static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->width_check (d, db::RegionCheckOptions (whole_edges, metrics, @@ -521,11 +521,12 @@ static db::EdgePairs width2 (const db::Region *r, db::Region::distance_type d, b db::NoOppositeFilter, db::NoRectFilter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->notch_check (d, db::RegionCheckOptions (whole_edges, metrics, @@ -536,11 +537,12 @@ static db::EdgePairs notch2 (const db::Region *r, db::Region::distance_type d, b db::NoOppositeFilter, db::NoRectFilter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->isolated_check (d, db::RegionCheckOptions (whole_edges, metrics, @@ -551,11 +553,12 @@ static db::EdgePairs isolated2 (const db::Region *r, db::Region::distance_type d opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->space_check (d, db::RegionCheckOptions (whole_edges, metrics, @@ -566,11 +569,12 @@ static db::EdgePairs space2 (const db::Region *r, db::Region::distance_type d, b opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->inside_check (other, d, db::RegionCheckOptions (whole_edges, metrics, @@ -581,11 +585,12 @@ static db::EdgePairs inside2 (const db::Region *r, const db::Region &other, db:: opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->overlap_check (other, d, db::RegionCheckOptions (whole_edges, metrics, @@ -596,11 +601,12 @@ static db::EdgePairs overlap2 (const db::Region *r, const db::Region &other, db: opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->enclosing_check (other, d, db::RegionCheckOptions (whole_edges, metrics, @@ -611,11 +617,12 @@ static db::EdgePairs enclosing2 (const db::Region *r, const db::Region &other, d opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } -static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint) +static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, db::Region::distance_type d, bool whole_edges, db::metrics_type metrics, const tl::Variant &ignore_angle, const tl::Variant &min_projection, const tl::Variant &max_projection, bool shielded, db::OppositeFilter opposite, db::RectFilter rect_filter, bool negative, db::PropertyConstraint prop_constraint, db::zero_distance_mode zero_distance_mode) { return r->separation_check (other, d, db::RegionCheckOptions (whole_edges, metrics, @@ -626,7 +633,8 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, opposite, rect_filter, negative, - prop_constraint) + prop_constraint, + zero_distance_mode) ); } @@ -2542,7 +2550,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "This variant was introduced in version 0.27.\n" ) + - method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("width_check", &width2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs a width check with options\n" "@param d The minimum width for which the polygons are checked\n" "@param whole_edges If true, deliver the whole edges\n" @@ -2553,6 +2561,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param shielded Enables shielding\n" "@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n" "@param property_constraint Only \\IgnoreProperties and \\NoPropertyConstraint are allowed - in the last case, properties are copied from the original shapes to the output. " + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "Other than 'width' allow more options here.\n" "\n" "This version is similar to the simple version with one parameter. In addition, it allows " @@ -2583,9 +2592,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded' and 'negative' options have been introduced in version 0.27. " - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("space_check", &space2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs a space check with options\n" "@param d The minimum space for which the polygons are checked\n" "@param whole_edges If true, deliver the whole edges\n" @@ -2597,6 +2607,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2626,9 +2637,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("notch_check", ¬ch2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("notch_check", ¬ch2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs a space check between edges of the same polygon with options\n" "@param d The minimum space for which the polygons are checked\n" "@param whole_edges If true, deliver the whole edges\n" @@ -2640,6 +2652,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" "@param property_constraint Only \\IgnoreProperties and \\NoPropertyConstraint are allowed - in the last case, properties are copied from the original shapes to the output" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "This version is similar to the simple version with one parameter. In addition, it allows " "to specify many more options.\n" @@ -2669,9 +2682,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded' and 'negative' options have been introduced in version 0.27.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("isolated_check", &isolated2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("isolated_check", &isolated2, gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs a space check between edges of different polygons with options\n" "@param d The minimum space for which the polygons are checked\n" "@param whole_edges If true, deliver the whole edges\n" @@ -2683,6 +2697,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative If true, edges not violation the condition will be output as pseudo-edge pairs\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2712,9 +2727,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "Merged semantics applies for the input of this method (see \\merged_semantics= for a description of this concept)\n" "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("inside_check|enclosed_check", &inside2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs an inside check with options\n" "@param d The minimum distance for which the polygons are checked\n" "@param other The other region against which to check\n" @@ -2727,6 +2743,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative Negative output from the first input\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2763,9 +2780,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. " "The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n" "The 'enclosed_check' alias was introduced in version 0.27.5.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("overlap_check", &overlap2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs an overlap check with options\n" "@param d The minimum overlap for which the polygons are checked\n" "@param other The other region against which to check\n" @@ -2778,6 +2796,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative Negative output from the first input\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2813,9 +2832,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. " "The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("enclosing_check", &enclosing2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs an enclosing check with options\n" "@param d The minimum enclosing distance for which the polygons are checked\n" "@param other The other region against which to check\n" @@ -2828,6 +2848,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative Negative output from the first input\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2863,9 +2884,10 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. " "The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + - method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), + method_ext ("separation_check", &separation2, gsi::arg ("other"), gsi::arg ("d"), gsi::arg ("whole_edges", false), gsi::arg ("metrics", db::metrics_type::Euclidian, "Euclidian"), gsi::arg ("ignore_angle", tl::Variant (), "default"), gsi::arg ("min_projection", tl::Variant (), "0"), gsi::arg ("max_projection", tl::Variant (), "max"), gsi::arg ("shielded", true), gsi::arg ("opposite_filter", db::NoOppositeFilter, "NoOppositeFilter"), gsi::arg ("rect_filter", db::NoRectFilter, "NoRectFilter"), gsi::arg ("negative", false), gsi::arg ("property_constraint", db::IgnoreProperties, "IgnoreProperties"), gsi::arg ("zero_distance_mode", db::IncludeZeroDistanceWhenTouching, "IncludeZeroDistanceWhenTouching"), "@brief Performs a separation check with options\n" "@param d The minimum separation for which the polygons are checked\n" "@param other The other region against which to check\n" @@ -2878,6 +2900,7 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "@param rect_filter Specifies an error filter for rectangular input shapes\n" "@param negative Negative output from the first input\n" "@param property_constraint Specifies whether to consider only shapes with a certain property relation\n" + "@param zero_distance_mode Specifies how to handle edges with zero distance\n" "\n" "If \"whole_edges\" is true, the resulting \\EdgePairs collection will receive the whole " "edges which contribute in the width check.\n" @@ -2913,7 +2936,8 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "\n" "The 'shielded', 'negative', 'not_opposite' and 'rect_sides' options have been introduced in version 0.27. " "The interpretation of the 'negative' flag has been restriced to first-layout only output in 0.27.1.\n" - "'property_constraint' has been added in version 0.28.4." + "'property_constraint' has been added in version 0.28.4.\n" + "'zero_distance_mode' has been added in version 0.29." ) + method_ext ("area", &area1, "@brief The area of the region\n" @@ -3192,6 +3216,46 @@ gsi::Enum decl_Metrics ("db", "Metrics", gsi::ClassExt inject_Metrics_in_Region (decl_Metrics.defs ()); gsi::ClassExt inject_Metrics_in_Edges (decl_Metrics.defs ()); +gsi::Enum decl_ZeroDistanceMode ("db", "ZeroDistanceMode", + gsi::enum_const ("NeverIncludeZeroDistance", db::NeverIncludeZeroDistance, + "@brief Specifies that check functions should never include edges with zero distance.\n" + "With this specification, the check functions will ignore edges which are collinear or touch." + ) + + gsi::enum_const ("AlwaysIncludeZeroDistance", db::AlwaysIncludeZeroDistance, + "@hide\n" + "@brief Specifies that check functions should always include edges with zero distance\n" + "This mode has little practical value.\n" + ) + + gsi::enum_const ("IncludeZeroDistanceWhenTouching", db::IncludeZeroDistanceWhenTouching, + "@brief Specifies that check functions should include edges when they touch\n" + "With this specification, the check functions will also check edges if they share at least one common point. " + "This is the mode that includes checking the 'kissing corner' cases. This mode is default for version 0.29 and later. " + ) + + gsi::enum_const ("IncludeZeroDistanceWhenCollinearAndTouching", db::IncludeZeroDistanceWhenCollinearAndTouching, + "@brief Specifies that check functions should include edges when they are collinear and touch\n" + "With this specification, the check functions will also check edges if they share at least one common point and are collinear. " + "This is the mode that includes checking the 'kissing corner' cases when the kissing edges are collinear. This mode was default up to version 0.28. " + ) + + gsi::enum_const ("IncludeZeroDistanceWhenOverlapping", db::IncludeZeroDistanceWhenOverlapping, + "@brief Specifies that check functions should include edges when they overlap\n" + "With this specification, the check functions will also check edges which are collinear and share more than a single point. " + "This is the mode that excludes the 'kissing corner' cases." + ), + "@brief This class represents the zero_distance_mode type for \\Region#width and related checks.\n" + "This mode determines how edges with zero distance are treated in the DRC checks. Formally these edges do neither represent " + "a space other other relation as they do not face each other. There are three modes available to treat this boundary case: " + "Ignore such edges (\\NeverIncludeZeroDistance) or only include them " + "if they share at least one common point (\\IncludeZeroDistanceWhenTouching). The latter mode allows activating checks for " + "the 'kissing corner' case and is the default mode in most checks." + "\n" + "This enum has been introduced in version 0.29." +); + +// Inject the Region::ZeroDistanceMode declarations into Region and Edges: +// (Edges injection has to be done here because only here defs() is available) +gsi::ClassExt inject_ZeroDistanceMode_in_Region (decl_ZeroDistanceMode.defs ()); +gsi::ClassExt inject_ZeroDistanceMode_in_Edges (decl_ZeroDistanceMode.defs ()); + gsi::Enum decl_PropertyConstraint ("db", "PropertyConstraint", gsi::enum_const ("IgnoreProperties", db::IgnoreProperties, "@brief Specifies to ignore properties\n" diff --git a/src/db/unit_tests/dbEdgePairRelationsTests.cc b/src/db/unit_tests/dbEdgePairRelationsTests.cc index c0b3f918f0..4b3d7f8c0c 100644 --- a/src/db/unit_tests/dbEdgePairRelationsTests.cc +++ b/src/db/unit_tests/dbEdgePairRelationsTests.cc @@ -51,139 +51,139 @@ TEST(1) TEST(2) { db::Edge output; - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 10), db::Point (100, 200)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 10), db::Point (100, 200)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;187,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(100,-50;187,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(-87,-50;187,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true); EXPECT_EQ (output.to_string (), "(-87,-50;0,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); EXPECT_EQ (output.to_string (), "(-94,-34;164,-77)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(0,0;50,-100)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); EXPECT_EQ (output.to_string (), "(40,0;90,-100)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;145,-89)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;145,-89)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true); EXPECT_EQ (output.to_string (), "(120,0;120,-98)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;100,-100)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;80,-100)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true); EXPECT_EQ (output.to_string (), "(-80,0;-80,-60)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;-45,-89)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(100,-50;100,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); EXPECT_EQ (output.to_string (), "(50,-50;50,-50)"); - EXPECT_EQ (euclidian_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false); + EXPECT_EQ (euclidian_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false); } TEST(3) { db::Edge output; - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;200,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(100,-50;200,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(-100,-50;200,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), true); EXPECT_EQ (output.to_string (), "(-100,-50;0,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); EXPECT_EQ (output.to_string (), "(-100,-33;200,-83)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(0,0;50,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); EXPECT_EQ (output.to_string (), "(40,0;90,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;150,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;150,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), true); EXPECT_EQ (output.to_string (), "(120,0;120,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;100,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;80,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), true); EXPECT_EQ (output.to_string (), "(-80,0;-80,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;-60,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(-100,0;-100,-100)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(100,-50;100,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); EXPECT_EQ (output.to_string (), "(50,-50;50,-50)"); - EXPECT_EQ (square_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), true); + EXPECT_EQ (square_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), true); EXPECT_EQ (output.to_string (), "(190,-50;190,-50)"); } TEST(4) { db::Edge output; - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (100, 200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-50)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-50)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (300, -50)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (300, -50)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-50)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -50), db::Point (0, -50)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, -100), db::Point (300, -100)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-300, 0), db::Point (300, -100)), &output), true); EXPECT_EQ (output.to_string (), "(0,-50;100,-67)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(0,0;50,-100)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (40, 0), db::Point (140, -200)), &output), true); EXPECT_EQ (output.to_string (), "(40,0;90,-100)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (200, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, -200), db::Point (200, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 200), db::Point (200, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (120, 200), db::Point (120, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 200), db::Point (100, -200)), &output), true); EXPECT_EQ (output.to_string (), "(100,0;100,-100)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 200), db::Point (80, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;80,-100)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-80, 200), db::Point (-80, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (80, 0), db::Point (-200, -200)), &output), true); EXPECT_EQ (output.to_string (), "(80,0;0,-57)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (), db::Edge (db::Point (-100, 200), db::Point (-100, -200)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 50), db::Point (100, 50)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, -50), db::Point (100, -50)), &output), true); EXPECT_EQ (output.to_string (), "(100,-50;100,-50)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (50, -50), db::Point (50, -50)), &output), true); EXPECT_EQ (output.to_string (), "(50,-50;50,-50)"); - EXPECT_EQ (projected_near_part_of_edge (true, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false); + EXPECT_EQ (projected_near_part_of_edge (db::AlwaysIncludeZeroDistance, 100, db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (190, -50), db::Point (190, -50)), &output), false); } TEST(5) @@ -291,7 +291,7 @@ TEST(7) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,30;1,20)"); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output); EXPECT_EQ (res, false); - f.set_include_zero (false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output); EXPECT_EQ (res, false); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, 20)), &output); @@ -300,7 +300,7 @@ TEST(7) res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output); EXPECT_EQ (res, false); - f.set_include_zero (true); + f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 300), db::Point (0, -200)), &output); EXPECT_EQ (res, true); EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,110;0,-100)"); @@ -309,7 +309,7 @@ TEST(7) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,110;1,-100)"); f.set_metrics (db::Square); - f.set_include_zero (true); + f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output); EXPECT_EQ (res, true); EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,30;0,20)"); @@ -318,7 +318,7 @@ TEST(7) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,30;1,20)"); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output); EXPECT_EQ (res, false); - f.set_include_zero (false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 20)), &output); EXPECT_EQ (res, false); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, 20)), &output); @@ -327,7 +327,7 @@ TEST(7) res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, 20)), &output); EXPECT_EQ (res, false); - f.set_include_zero (true); + f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 300), db::Point (0, -200)), &output); EXPECT_EQ (res, true); EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,110;0,-100)"); @@ -336,7 +336,7 @@ TEST(7) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,110;1,-100)"); f.set_metrics (db::Projection); - f.set_include_zero (true); + f.set_zero_distance_mode (db::AlwaysIncludeZeroDistance); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, -20)), &output); EXPECT_EQ (res, true); EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,10;0,0)"); @@ -345,7 +345,7 @@ TEST(7) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(1,10;1,0)"); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (-1, 30), db::Point (-1, -20)), &output); EXPECT_EQ (res, false); - f.set_include_zero (false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (0, 30), db::Point (0, 11)), &output); EXPECT_EQ (res, false); res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 10)), db::Edge (db::Point (1, 30), db::Point (1, -20)), &output); @@ -361,7 +361,7 @@ TEST(8_KissingCornerProblem) // if the projection is >0. db::EdgeRelationFilter f (db::WidthRelation, 10); - f.set_include_zero (false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); db::EdgePair output; bool res; @@ -382,8 +382,39 @@ TEST(8_KissingCornerProblem) res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); EXPECT_EQ (res, false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenOverlapping); + + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,40;0,100):(0,110;0,50)"); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + f = db::EdgeRelationFilter (db::SpaceRelation, 10); - f.set_include_zero (false); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); f.set_metrics (db::Euclidian); res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); @@ -401,4 +432,188 @@ TEST(8_KissingCornerProblem) EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,10;0,0):(0,-10;0,0)"); res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenOverlapping); + + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,40):(0,50;0,110)"); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + f.set_metrics (db::Euclidian); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); +} + +TEST(9_KissingCornerProblemSquareMetrics) +{ + // The kissing corner problem is solved by allowing distance-0 width and space relations and checking them + // if the projection is >0. + + db::EdgeRelationFilter f (db::WidthRelation, 10); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); + db::EdgePair output; + bool res; + + f.set_metrics (db::Square); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,90;0,100):(0,110;0,100)"); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,40;0,100):(0,110;0,50)"); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,0;0,10):(0,0;0,-10)"); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + + f = db::EdgeRelationFilter (db::SpaceRelation, 10); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); + + f.set_metrics (db::Square); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,90):(0,100;0,110)"); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,40):(0,50;0,110)"); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,10;0,0):(0,-10;0,0)"); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); +} + +TEST(10_KissingCornerProblemProjectionMetrics) +{ + // The kissing corner problem is solved by allowing distance-0 width and space relations and checking them + // if the projection is >0. It is not effective in projection metrics as there is no overlap. + + db::EdgeRelationFilter f (db::WidthRelation, 10); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); + db::EdgePair output; + bool res; + + f.set_metrics (db::Projection); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,50;0,100):(0,100;0,50)"); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 201), db::Point (0, 101)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 0), db::Point (1, 100)), db::Edge (db::Point (0, 201), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 200), db::Point (0, 50)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, 0), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 0), db::Point (0, 100)), db::Edge (db::Point (0, -1), db::Point (0, -100)), &output); + EXPECT_EQ (res, false); + + f = db::EdgeRelationFilter (db::SpaceRelation, 10); + f.set_zero_distance_mode (db::IncludeZeroDistanceWhenTouching); + + f.set_metrics (db::Projection); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, true); + EXPECT_EQ (output.first ().to_string () + ":" + output.second ().to_string (), "(0,100;0,50):(0,50;0,100)"); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); + + f.set_zero_distance_mode (db::NeverIncludeZeroDistance); + + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 101), db::Point (0, 201)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (1, 100), db::Point (1, 0)), db::Edge (db::Point (0, 0), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 100), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, 50), db::Point (0, 200)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, 0)), &output); + EXPECT_EQ (res, false); + res = f.check (db::Edge (db::Point (0, 100), db::Point (0, 0)), db::Edge (db::Point (0, -100), db::Point (0, -1)), &output); + EXPECT_EQ (res, false); } diff --git a/src/doc/doc/about/drc_ref_layer.xml b/src/doc/doc/about/drc_ref_layer.xml index 2e5e6b2b93..c8f124c5ca 100644 --- a/src/doc/doc/about/drc_ref_layer.xml +++ b/src/doc/doc/about/drc_ref_layer.xml @@ -2894,7 +2894,45 @@ The following image shows the effect of the separation check (input1: red, input

-

opposite and rectangle error filtering

+

Touching shapes

+

+Like width and space, the separation check also supports the "without_touching_corners" option. +

+This option will turn off errors that arise due to +edges touching in one corner (the "kissing corners" configuration). +By default, such edges will yield an error, as they +form a zero-distance situation. With this option in place, no errors will be reported. +

+The following images illustrate the effect of the "without_touching_corners" option. +The white line at the top of the bottom red shape is actually an edge pair indicating +the zero-distance violation of the separation check: +

+ + + + + +
+

+Another option is "without_touching_edges" which turns off errors that arise +at coincident edges. Formally such edges represent a zero-distance situation, hence +are flagged by default. Turning off the check in this case can be helpful when +separating a layer into two parts (e.g. thin/wide metal separation) and an error +between touching regions is not desired. +

+The "without_touching_edges" option is a stronger version of "without_touching_corners" and +makes sense only for two-layer checks. +

+The following images illustrate the effect of the "without_touching_edges" option: +

+ + + + + +
+

+

Opposite and rectangle error filtering

The options for the separation check are those available for the width or space method plus opposite and rectangle error filtering. @@ -3405,10 +3443,15 @@ each other is more or equal than min and less than max but is more intuitive, as "projecting" is written with a condition, like "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=". Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". -

  • transparent : performs the check without shielding (polygon layers only)
  • -
  • shielded : performs the check with shielding (polygon layers only)
  • +
  • without_touching_corners : With this option present, touching corners (aka "kissing +corners") will not yield errors. The default is to produce errors in these cases.
  • +
  • without_touching_edges : With this option present, coincident edges will not yield errors. +This is a stronger version of "without_touching_corners" and makes sense only for two-layer checks +or raw-mode input layers. It is listed here for completeness.
  • +
  • transparent : Performs the check without shielding (polygon layers only)
  • +
  • shielded : Performs the check with shielding (polygon layers only)
  • props_eq , props_ne , props_copy : (only props_copy applies to width check) - -see "Properties constraints" below.
  • +See "Properties constraints" below.

    Note that without the angle_limit, acute corners will always be reported, since two @@ -3509,6 +3552,22 @@ shape's properties to the output too: space_not_connected = metal1_nets.space(0.4.um, props_ne + props_copy) space_connected = metal1_nets.space(0.4.um, props_eq + props_copy) +

    +

    Touching shapes

    +

    +The "without_touching_corners" option will turn off errors that arise due to +the "kissing corner" configuration (or "checkerboard pattern"). Formally +this is a width violation across the diagonal, but when considering this +configuration as disconnected boxes, no error should be reported. +

    +The following images illustrate the effect of the "without_touching_corners" option: +

    + + + + + +

    "with_angle" - Selects edges by their angle

    diff --git a/src/doc/doc/images/drc_separation12.png b/src/doc/doc/images/drc_separation12.png new file mode 100644 index 0000000000..70847f7910 Binary files /dev/null and b/src/doc/doc/images/drc_separation12.png differ diff --git a/src/doc/doc/images/drc_separation13.png b/src/doc/doc/images/drc_separation13.png new file mode 100644 index 0000000000..00de3a91ca Binary files /dev/null and b/src/doc/doc/images/drc_separation13.png differ diff --git a/src/doc/doc/images/drc_separation14.png b/src/doc/doc/images/drc_separation14.png new file mode 100644 index 0000000000..e9a4cca311 Binary files /dev/null and b/src/doc/doc/images/drc_separation14.png differ diff --git a/src/doc/doc/images/drc_width5.png b/src/doc/doc/images/drc_width5.png new file mode 100644 index 0000000000..9bb7818143 Binary files /dev/null and b/src/doc/doc/images/drc_width5.png differ diff --git a/src/doc/doc/images/drc_width6.png b/src/doc/doc/images/drc_width6.png new file mode 100644 index 0000000000..50c558bfe3 Binary files /dev/null and b/src/doc/doc/images/drc_width6.png differ diff --git a/src/doc/docDRCLVSResources.qrc b/src/doc/docDRCLVSResources.qrc index e91766fe56..e4449b7ed5 100644 --- a/src/doc/docDRCLVSResources.qrc +++ b/src/doc/docDRCLVSResources.qrc @@ -4,6 +4,8 @@ doc/images/drc_width2.png doc/images/drc_width3.png doc/images/drc_width4.png + doc/images/drc_width5.png + doc/images/drc_width6.png doc/images/drc_width1u.png doc/images/drc_width2u.png doc/images/drc_width3u.png @@ -29,6 +31,9 @@ doc/images/drc_separation9.png doc/images/drc_separation10.png doc/images/drc_separation11.png + doc/images/drc_separation12.png + doc/images/drc_separation13.png + doc/images/drc_separation14.png doc/images/drc_raw1.png doc/images/drc_raw2.png doc/images/drc_raw3.png diff --git a/src/drc/drc/built-in-macros/_drc_cop_integration.rb b/src/drc/drc/built-in-macros/_drc_cop_integration.rb index 7b617aab07..8bf358bf0a 100644 --- a/src/drc/drc/built-in-macros/_drc_cop_integration.rb +++ b/src/drc/drc/built-in-macros/_drc_cop_integration.rb @@ -1485,6 +1485,7 @@ def _cop_#{f}(*args) shielded = nil opposite_filter = RBA::Region::NoOppositeFilter rect_filter = RBA::Region::NoRectFilter + zd_mode = RBA::Region::IncludeZeroDistanceWhenTouching n = 1 args.each do |a| @@ -1492,6 +1493,10 @@ def _cop_#{f}(*args) metrics = a.value elsif a.is_a?(DRCWholeEdges) whole_edges = a.value + elsif a.is_a?(DRCPropertiesConstraint) + prop_constraint = a.value + elsif a.is_a?(DRCZeroDistanceMode) + zd_mode = a.value elsif a.is_a?(DRCOppositeErrorFilter) opposite_filter = a.value elsif a.is_a?(DRCRectangleErrorFilter) @@ -1523,6 +1528,8 @@ def _cop_#{f}(*args) elsif rect_filter != RBA::Region::NoRectFilter raise("A rectangle error filter cannot be used with this check") end + + args << zd_mode if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated other && raise("No other layer must be specified for a single-layer check") diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 6cb79e63f1..14eb0c842d 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -322,6 +322,18 @@ def whole_edges(f = true) end end + def without_touching_corners(f = true) + self._context("without_touching_corners") do + DRCZeroDistanceMode::new(f ? RBA::Region::IncludeZeroDistanceWhenOverlapping : RBA::Region::IncludeZeroDistanceWhenTouching) + end + end + + def without_touching_edges(f = true) + self._context("without_touching_edges") do + DRCZeroDistanceMode::new(f ? RBA::Region::NeverIncludeZeroDistance : RBA::Region::IncludeZeroDistanceWhenTouching) + end + end + def euclidian DRCMetrics::new(RBA::Region::Euclidian) end diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index ee4ef6803d..ffa80b9433 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -3687,10 +3687,15 @@ def sep(*args) # but is more intuitive, as "projecting" is written with a condition, like # "projecting < 2.um". Available operators are: "==", "<", "<=", ">" and ">=". # Double-bounded ranges are also available, like: "0.5 <= projecting < 2.0". @/li - # @li @b transparent @/b: performs the check without shielding (polygon layers only) @/li - # @li @b shielded @/b: performs the check with shielding (polygon layers only) @/li + # @li @b without_touching_corners @/b: With this option present, touching corners (aka "kissing + # corners") will not yield errors. The default is to produce errors in these cases. @/li + # @li @b without_touching_edges @/b: With this option present, coincident edges will not yield errors. + # This is a stronger version of "without_touching_corners" and makes sense only for two-layer checks + # or raw-mode input layers. It is listed here for completeness. @/li + # @li @b transparent @/b: Performs the check without shielding (polygon layers only) @/li + # @li @b shielded @/b: Performs the check with shielding (polygon layers only) @/li # @li @b props_eq @/b, @b props_ne @/b, @b props_copy @/b: (only props_copy applies to width check) - - # see "Properties constraints" below. @/li + # See "Properties constraints" below. @/li # @/ul # # Note that without the angle_limit, acute corners will always be reported, since two @@ -3792,6 +3797,21 @@ def sep(*args) # space_connected = metal1_nets.space(0.4.um, props_eq + props_copy) # @/code # + # @h3 Touching shapes @/h3 + # + # The "without_touching_corners" option will turn off errors that arise due to + # the "kissing corner" configuration (or "checkerboard pattern"). Formally + # this is a width violation across the diagonal, but when considering this + # configuration as disconnected boxes, no error should be reported. + # + # The following images illustrate the effect of the "without_touching_corners" option: + # + # @table + # @tr + # @td @img(/images/drc_width5.png) @/td + # @td @img(/images/drc_width6.png) @/td + # @/tr + # @/table # %DRC% # @name space @@ -3912,7 +3932,45 @@ def sep(*args) # @/tr # @/table # - # @h3 opposite and rectangle error filtering @/h3 + # @h3 Touching shapes @/h3 + # + # Like \width and \space, the separation check also supports the "without_touching_corners" option. + # + # This option will turn off errors that arise due to + # edges touching in one corner (the "kissing corners" configuration). + # By default, such edges will yield an error, as they + # form a zero-distance situation. With this option in place, no errors will be reported. + # + # The following images illustrate the effect of the "without_touching_corners" option. + # The white line at the top of the bottom red shape is actually an edge pair indicating + # the zero-distance violation of the separation check: + # + # @table + # @tr + # @td @img(/images/drc_separation12.png) @/td + # @td @img(/images/drc_separation13.png) @/td + # @/tr + # @/table + # + # Another option is "without_touching_edges" which turns off errors that arise + # at coincident edges. Formally such edges represent a zero-distance situation, hence + # are flagged by default. Turning off the check in this case can be helpful when + # separating a layer into two parts (e.g. thin/wide metal separation) and an error + # between touching regions is not desired. + # + # The "without_touching_edges" option is a stronger version of "without_touching_corners" and + # makes sense only for two-layer checks. + # + # The following images illustrate the effect of the "without_touching_edges" option: + # + # @table + # @tr + # @td @img(/images/drc_separation12.png) @/td + # @td @img(/images/drc_separation14.png) @/td + # @/tr + # @/table + # + # @h3 Opposite and rectangle error filtering @/h3 # # The options for the separation check are those available for the \width or \space # method plus opposite and rectangle error filtering. @@ -4121,6 +4179,7 @@ def #{f}(*args) opposite_filter = RBA::Region::NoOppositeFilter rect_filter = RBA::Region::NoRectFilter prop_constraint = RBA::Region::IgnoreProperties + zd_mode = RBA::Region::IncludeZeroDistanceWhenTouching n = 1 args.each do |a| @@ -4132,6 +4191,8 @@ def #{f}(*args) negative = true elsif a.is_a?(DRCPropertiesConstraint) prop_constraint = a.value + elsif a.is_a?(DRCZeroDistanceMode) + zd_mode = a.value elsif a.is_a?(DRCOppositeErrorFilter) opposite_filter = a.value elsif a.is_a?(DRCRectangleErrorFilter) @@ -4185,6 +4246,8 @@ def #{f}(*args) raise("A rectangle error filter can only be used for polygon layers") end + args << zd_mode + border = (metrics == RBA::Region::Square ? value * 1.5 : value) if :#{f} == :width || :#{f} == :space || :#{f} == :notch || :#{f} == :isolated diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index 495f458d1f..fd774ebd68 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -95,6 +95,16 @@ def initialize(v) end end + # A wrapper for the "zero distance mode" for + # the DRC functions. The purpose of this class + # is to identify the value by the class. + class DRCZeroDistanceMode + attr_accessor :value + def initialize(v) + self.value = v + end + end + # A wrapper for the "as_dots" or "as_boxes" flag for # some DRC functions. The purpose of this class # is to identify the value by the class. diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 4fcba65e64..1362acee0d 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1617,7 +1617,27 @@ TEST(89_deep_with_mag_cop_size_aniso) run_test (_this, "89", true); } -TEST(90_issue1594_dual_top) +TEST(90_zero_distance_mode) +{ + run_test (_this, "90", false); +} + +TEST(90d_zero_distance_mode) +{ + run_test (_this, "90", true); +} + +TEST(91_zero_distance_mode) +{ + run_test (_this, "91", false); +} + +TEST(91d_zero_distance_mode) +{ + run_test (_this, "91", true); +} + +TEST(92_issue1594_dual_top) { std::string rs = tl::testdata (); rs += "/drc/issue_1594.drc"; @@ -1652,4 +1672,3 @@ TEST(90_issue1594_dual_top) CHECKPOINT (); compare_netlists (_this, output, au); } - diff --git a/testdata/drc/drcSimpleTests_90.drc b/testdata/drc/drcSimpleTests_90.drc new file mode 100644 index 0000000000..eb85f24ee1 --- /dev/null +++ b/testdata/drc/drcSimpleTests_90.drc @@ -0,0 +1,34 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l1_raw = input(1, 0).raw +l2 = input(2, 0) + +l1.output(1, 0) +l2.output(2, 0) + +l1.width(600.nm).output(100, 0) +l1.width(600.nm, without_touching_corners).output(101, 0) +l1.width(600.nm, without_touching_edges).output(102, 0) + +l1.space(600.nm).output(200, 0) +l1.space(600.nm, without_touching_corners).output(201, 0) +l1.space(600.nm, without_touching_edges).output(202, 0) +l1_raw.space(600.nm).output(210, 0) +l1_raw.space(600.nm, without_touching_corners).output(211, 0) +l1_raw.space(600.nm, without_touching_edges).output(212, 0) + +l1.sep(l2, 600.nm).output(300, 0) +l1.sep(l2, 600.nm, without_touching_corners).output(301, 0) +l1.sep(l2, 600.nm, without_touching_edges).output(302, 0) + +l1.drc(space < 600.nm).output(400, 0) +l1.drc(space(without_touching_corners) < 600.nm).output(401, 0) +l1.drc(space(without_touching_edges) < 600.nm).output(402, 0) + diff --git a/testdata/drc/drcSimpleTests_90.gds b/testdata/drc/drcSimpleTests_90.gds new file mode 100644 index 0000000000..1fedad706c Binary files /dev/null and b/testdata/drc/drcSimpleTests_90.gds differ diff --git a/testdata/drc/drcSimpleTests_91.drc b/testdata/drc/drcSimpleTests_91.drc new file mode 100644 index 0000000000..0b79b77730 --- /dev/null +++ b/testdata/drc/drcSimpleTests_91.drc @@ -0,0 +1,34 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) + +l1.output(1, 0) + +l1.space(600.nm).output(100, 0) +l1.space(600.nm, without_touching_corners).output(101, 0) +l1.space(600.nm, without_touching_edges).output(102, 0) +l1.space(600.nm, DRCZeroDistanceMode::new(RBA::ZeroDistanceMode::IncludeZeroDistanceWhenCollinearAndTouching)).output(103, 0) + +l1.space(600.nm, projection).output(110, 0) +l1.space(600.nm, projection, without_touching_corners).output(111, 0) +l1.space(600.nm, projection, without_touching_edges).output(112, 0) +l1.space(600.nm, projection, DRCZeroDistanceMode::new(RBA::ZeroDistanceMode::IncludeZeroDistanceWhenCollinearAndTouching)).output(113, 0) + +l1.space(600.nm, square).output(120, 0) +l1.space(600.nm, square, without_touching_corners).output(121, 0) +l1.space(600.nm, square, without_touching_edges).output(122, 0) +l1.space(600.nm, square, DRCZeroDistanceMode::new(RBA::ZeroDistanceMode::IncludeZeroDistanceWhenCollinearAndTouching)).output(123, 0) + +l1.data.min_coherence = true + +l1.space(600.nm).output(200, 0) +l1.space(600.nm, without_touching_corners).output(201, 0) +l1.space(600.nm, without_touching_edges).output(202, 0) +l1.space(600.nm, DRCZeroDistanceMode::new(RBA::ZeroDistanceMode::IncludeZeroDistanceWhenCollinearAndTouching)).output(203, 0) + diff --git a/testdata/drc/drcSimpleTests_91.gds b/testdata/drc/drcSimpleTests_91.gds new file mode 100644 index 0000000000..ab89a181dd Binary files /dev/null and b/testdata/drc/drcSimpleTests_91.gds differ diff --git a/testdata/drc/drcSimpleTests_au90.gds b/testdata/drc/drcSimpleTests_au90.gds new file mode 100644 index 0000000000..42058a4a86 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au90.gds differ diff --git a/testdata/drc/drcSimpleTests_au90d.gds b/testdata/drc/drcSimpleTests_au90d.gds new file mode 100644 index 0000000000..42058a4a86 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au90d.gds differ diff --git a/testdata/drc/drcSimpleTests_au91.gds b/testdata/drc/drcSimpleTests_au91.gds new file mode 100644 index 0000000000..ff5c26d23d Binary files /dev/null and b/testdata/drc/drcSimpleTests_au91.gds differ diff --git a/testdata/drc/drcSimpleTests_au91d.gds b/testdata/drc/drcSimpleTests_au91d.gds new file mode 100644 index 0000000000..ff5c26d23d Binary files /dev/null and b/testdata/drc/drcSimpleTests_au91d.gds differ diff --git a/testdata/ruby/dbEdgesTest.rb b/testdata/ruby/dbEdgesTest.rb index 1a0910a9df..f64dc910ec 100644 --- a/testdata/ruby/dbEdgesTest.rb +++ b/testdata/ruby/dbEdgesTest.rb @@ -476,6 +476,48 @@ def test_4 assert_equal((r2 | r1).width_check(60, true, RBA::Edges::Projection, nil, 50, nil).to_s, "(120,20;120,380)/(130,380;130,20)") assert_equal((r2 | r1).width_check(60, true, RBA::Edges::Projection, nil, nil, 50).to_s, "(50,200;50,220)/(100,400;100,0)") + # kissing corner/separation case + + r1 = RBA::Region::new + r1.insert(RBA::Box::new(0, 0, 100, 200)) + r1 = r1.edges + + r2 = RBA::Region::new + r2.insert(RBA::Box::new(100, 200, 200, 400)) + r2 = r2.edges + + r3a = RBA::Region::new + r3a.insert(RBA::Box::new(-10, 0, 110, 100)) + r3a = r3a.edges + + r3b = RBA::Region::new + r3b.insert(RBA::Box::new(10, 0, 90, 100)) + r3b = r3b.edges + + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(160,200;100,200)/(40,200;100,200)")) + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(160,200;100,200)/(40,200;100,200)")) + + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(160,200;100,200)/(40,200;100,200)")) + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(160,200;100,200)/(40,200;100,200)")) + + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,0;0,0)/(90,0;10,0)")) + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,0;0,0)/(90,0;10,0)")) + + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,0;0,0)/(110,0;-10,0)")) + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,0;0,0)/(110,0;-10,0)")) + + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, RBA::Edges::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + end # with.. diff --git a/testdata/ruby/dbRegionTest.rb b/testdata/ruby/dbRegionTest.rb index de204bc3d0..e0abb515bf 100644 --- a/testdata/ruby/dbRegionTest.rb +++ b/testdata/ruby/dbRegionTest.rb @@ -550,6 +550,44 @@ def test_5 assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, 50, nil).to_s, "(120,20;120,380)|(130,380;130,20)") assert_equal((r1 | r2).merged.width_check(60, true, RBA::Region::Projection, nil, nil, 50).to_s, "(50,200;50,220)|(100,400;100,0)") + # kissing corner/separation case + + r1 = RBA::Region::new + r1.insert(RBA::Box::new(0, 0, 100, 200)) + + r2 = RBA::Region::new + r2.insert(RBA::Box::new(100, 200, 200, 400)) + + r3a = RBA::Region::new + r3a.insert(RBA::Box::new(-10, 0, 110, 100)) + + r3b = RBA::Region::new + r3b.insert(RBA::Box::new(10, 0, 90, 100)) + + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)|(100,200;100,260);(40,200;100,200)|(160,200;100,200)")) + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, true, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort((r2 | r1).width_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, true, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)|(100,200;100,260);(40,200;100,200)|(160,200;100,200)")) + + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)|(100,200;100,260);(40,200;100,200)|(160,200;100,200)")) + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort((r2 | r1).space_check(60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)|(100,200;100,260);(40,200;100,200)|(160,200;100,200)")) + + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.separation_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,0;0,0)/(90,0;10,0)")) + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.inside_check(r3b, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,0;0,0)/(90,0;10,0)")) + + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,0;0,0)/(110,0;-10,0)")) + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.enclosing_check(r3a, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,0;0,0)/(110,0;-10,0)")) + + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::NeverIncludeZeroDistance).to_s), csort("")) + assert_equal(csort(r1.overlap_check(r2, 60, false, RBA::Edges::Euclidian, nil, nil, nil, true, RBA::Region::NoOppositeFilter, RBA::Region::NoRectFilter, false, RBA::Region::IgnoreProperties, RBA::Region::IncludeZeroDistanceWhenTouching).to_s), csort("(100,200;100,140)/(100,200;100,260);(40,200;100,200)/(160,200;100,200)")) + end # Others