diff --git a/src/db/db/dbEdgePairRelations.cc b/src/db/db/dbEdgePairRelations.cc index a1309898e..5d32bcc27 100644 --- a/src/db/db/dbEdgePairRelations.cc +++ b/src/db/db/dbEdgePairRelations.cc @@ -93,15 +93,21 @@ static bool include_zero_flag (zero_distance_mode zd_mode, const db::Edge &a, co */ 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; - } - db::Edge g (other); - int s1 = e.side_of (g.p1 ()); - int s2 = e.side_of (g.p2 ()); + + // s1 = side of g.p1 wrt e + // s2 = side of g.p2 wrt e + int s1, s2; + if (e.is_degenerate ()) { + if (g.contains (e.p1 ())) { + s1 = s2 = 0; + } else { + s1 = s2 = -1; + } + } else { + s1 = e.side_of (g.p1 ()); + s2 = e.side_of (g.p2 ()); + } bool include_zero = include_zero_flag (zd_mode, e, g); int thr = include_zero ? 0 : -1; @@ -115,33 +121,49 @@ bool euclidian_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits thr) { - return false; - } - - double a = e.double_sq_length (); - 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 - 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) { + // point vs. point + if (e.p1 ().distance (g.p1 ()) < double (d)) { if (output) { *output = g; } return true; } - } - return false; + return false; + + } else { + + db::Point o = g.p1 (); + + 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 ()) / a; + double c = (e.p1 ().sq_double_distance (o) - double (d) * double (d)) / 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; + } + return true; + } + } + + return false; + + } } @@ -150,10 +172,13 @@ bool euclidian_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits::max (), l2 = -std::numeric_limits::max (); // handle the parallel case + // NOTE: a point is "parallel" to an edge. if (e.parallel (g)) { + if (std::abs (double (e.distance (g.p1 ()))) >= double (d)) { return false; } + } else { double ef = 1.0 / e.double_length (); @@ -233,16 +258,21 @@ bool euclidian_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 - - if (e.is_degenerate ()) { - return false; - } - db::Edge g (other); - int s1 = e.side_of (g.p1 ()); - int s2 = e.side_of (g.p2 ()); + + // s1 = side of g.p1 wrt e + // s2 = side of g.p2 wrt e + int s1, s2; + if (e.is_degenerate ()) { + if (g.contains (e.p1 ())) { + s1 = s2 = 0; + } else { + s1 = s2 = -1; + } + } else { + s1 = e.side_of (g.p1 ()); + s2 = e.side_of (g.p2 ()); + } bool include_zero = include_zero_flag (zd_mode, e, g); int thr = include_zero ? 0 : -1; @@ -259,37 +289,53 @@ static bool var_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits< // Handle the case of point vs. edge if (g.is_degenerate ()) { - 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 ())) { - return false; - } - if (db::sprod (db::Vector (e.p2 () - g.p1 ()), e.d ()) < -(dd * e.double_length ())) { - return false; + + if (! e.is_degenerate ()) { + if (e.side_of (g.p1 ()) > thr) { + return false; + } + if (db::sprod (db::Vector (g.p1 () - e.p1 ()), e.d ()) < -(dd * e.double_length ())) { + return false; + } + if (db::sprod (db::Vector (e.p2 () - g.p1 ()), e.d ()) < -(dd * e.double_length ())) { + return false; + } + if (double (e.distance (g.p1 ())) <= -double (d)) { + return false; + } + } else { + // point to point + if (e.p1 ().distance (g.p1 ()) >= double (d)) { + return false; + } } + if (output) { *output = g; } return true; + } // Determine body interactions (projected mode) - double l1 = std::numeric_limits::min (), l2 = std::numeric_limits::max (); + double l1 = std::numeric_limits::lowest (), l2 = std::numeric_limits::max (); - double ef = 1.0 / e.double_length (); - db::DVector ep = db::DVector (ef * e.dx (), ef * e.dy ()); - db::DVector en = db::DVector (ef * e.dy (), -ef * e.dx ()); + db::DVector ep, en; + double ef = 0.0; + if (! e.is_degenerate ()) { + ef = 1.0 / e.double_length (); + ep = db::DVector (ef * e.dx (), ef * e.dy ()); + en = db::DVector (ef * e.dy (), -ef * e.dx ()); + } // handle the parallel case if (e.parallel (g)) { + if (std::abs (double (e.distance (g.p1 ()))) >= double (d)) { return false; } + } else { db::DPoint e1d = db::DPoint (e.p1 ()) + en * double (d); @@ -307,10 +353,21 @@ static bool var_near_part_of_edge (zero_distance_mode zd_mode, db::coord_traits< } if (db::sprod_sign (e, g) == 0) { - if (db::sprod (db::Vector (g.p1 () - e.p1 ()), e.d ()) < -(dd * e.double_length ()) || - db::sprod (db::Vector (e.p2 () - g.p1 ()), e.d ()) < -(dd * e.double_length ())) { - return false; + + if (! g.is_degenerate ()) { + + if (db::sprod (db::Vector (g.p1 () - e.p1 ()), e.d ()) < -(dd * e.double_length ()) || + db::sprod (db::Vector (e.p2 () - g.p1 ()), e.d ()) < -(dd * e.double_length ())) { + return false; + } + + double l = db::sprod (db::DVector (e.p1 () - g.p1 ()), db::DVector (g.d ())) / g.double_sq_length (); + double dl = double (dd) / g.double_length (); + l1 = l - dl; + l2 = l + dl; + } + } else { double det = db::vprod (db::DVector (g.d ()), en); @@ -410,7 +467,9 @@ EdgeRelationFilter::check (const db::Edge &a, const db::Edge &b, db::EdgePair *o // Check whether the edges have an angle less than the ignore_angle parameter - if (m_ignore_angle == 90.0) { + if (a.is_degenerate () || b.is_degenerate ()) { + // accept dots as "always good" + } else if (m_ignore_angle == 90.0) { if (db::sprod_sign (aa, b) >= 0) { return false; } diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 85547ab6b..258c5969d 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -2055,3 +2055,14 @@ TEST(145d_edges_merge) run_test (_this, "145", true); } +// issue 2141 +TEST(146_edges_and_corners) +{ + run_test (_this, "146", false); +} + +TEST(146d_edges_and_corners) +{ + run_test (_this, "146", true); +} + diff --git a/testdata/drc/drcSimpleTests_146.drc b/testdata/drc/drcSimpleTests_146.drc new file mode 100644 index 000000000..b52cb8548 --- /dev/null +++ b/testdata/drc/drcSimpleTests_146.drc @@ -0,0 +1,51 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l2 = input(2, 0) + +l1.output(1, 0) +l2.output(2, 0) +l1e = l1.edges +l2e = l2.edges +l1c = l1.corners(as_dots) +l2c = l2.corners(as_dots) + +l1e.sep(l2c, 0.6).output(100, 0) +l1c.sep(l2e, 0.6).output(101, 0) +l1c.sep(l2c, 0.6).output(102, 0) +l1e.enc(l2c, 0.6).output(103, 0) +l1c.enc(l2e, 0.6).output(104, 0) +l1c.enc(l2c, 0.6).output(105, 0) +l2e.width(1.0).output(106, 0) +l2c.width(1.0).output(107, 0) +l2e.space(2.0).output(108, 0) +l2c.space(2.0).output(109, 0) + +l1e.sep(l2c, 0.6, square).output(110, 0) +l1c.sep(l2e, 0.6, square).output(111, 0) +l1c.sep(l2c, 0.6, square).output(112, 0) +l1e.enc(l2c, 0.6, square).output(113, 0) +l1c.enc(l2e, 0.6, square).output(114, 0) +l1c.enc(l2c, 0.6, square).output(115, 0) +l2e.width(1.0, square).output(116, 0) +l2c.width(1.0, square).output(117, 0) +l2e.space(2.0, square).output(118, 0) +l2c.space(2.0, square).output(119, 0) + +l1e.sep(l2c, 0.6, projection).output(120, 0) +l1c.sep(l2e, 0.6, projection).output(121, 0) +l1c.sep(l2c, 0.6, projection).output(122, 0) +l1e.enc(l2c, 0.6, projection).output(123, 0) +l1c.enc(l2e, 0.6, projection).output(124, 0) +l1c.enc(l2c, 0.6, projection).output(125, 0) +l2e.width(1.0, projection).output(126, 0) +l2c.width(1.0, projection).output(127, 0) +l2e.space(2.0, projection).output(128, 0) +l2c.space(2.0, projection).output(129, 0) + diff --git a/testdata/drc/drcSimpleTests_146.gds b/testdata/drc/drcSimpleTests_146.gds new file mode 100644 index 000000000..bb2a9b3f9 Binary files /dev/null and b/testdata/drc/drcSimpleTests_146.gds differ diff --git a/testdata/drc/drcSimpleTests_au146.gds b/testdata/drc/drcSimpleTests_au146.gds new file mode 100644 index 000000000..66262fc23 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au146.gds differ diff --git a/testdata/drc/drcSimpleTests_au146d.gds b/testdata/drc/drcSimpleTests_au146d.gds new file mode 100644 index 000000000..8621421d6 Binary files /dev/null and b/testdata/drc/drcSimpleTests_au146d.gds differ