diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index 57b3fc2a7..dce0cb71a 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -872,8 +872,6 @@ AsIfFlatEdges::intersections (const Edges &other) const EdgesDelegate * AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const { - std::set dots, other_dots; - std::unique_ptr output (new FlatEdges (true)); EdgeBooleanClusterCollectorToShapes cluster_collector (&output->raw_edges (), op); @@ -883,11 +881,7 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const AddressableEdgeDelivery e (begin ()); for ( ; ! e.at_end (); ++e) { - if (op == EdgeIntersections || ! e->is_degenerate ()) { - scanner.insert (e.operator-> (), 0); - } else if (op != EdgeOr) { - dots.insert (*e); - } + scanner.insert (e.operator-> (), 0); } AddressableEdgeDelivery ee; @@ -895,58 +889,18 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const if (other) { ee = other->addressable_edges (); for ( ; ! ee.at_end (); ++ee) { - if (op == EdgeIntersections || ! ee->is_degenerate ()) { - scanner.insert (ee.operator-> (), 1); - } else if (op != EdgeOr) { - other_dots.insert (*ee); - } + scanner.insert (ee.operator-> (), 1); } } scanner.process (cluster_collector, 1, db::box_convert ()); - // process dots - // NOTE: currently, dots vs. dots is supported, but not dots vs. edges - if (op == EdgeOr) { - for (auto i = dots.begin (); i != dots.end (); ++i) { - output->insert (*i); - } - for (auto i = other_dots.begin (); i != other_dots.end (); ++i) { - output->insert (*i); - } - } else if (op == EdgeNot) { - for (auto i = dots.begin (); i != dots.end (); ++i) { - if (other_dots.find (*i) == other_dots.end ()) { - output->insert (*i); - } - } - } else if (op == EdgeXor) { - for (auto i = dots.begin (); i != dots.end (); ++i) { - if (other_dots.find (*i) == other_dots.end ()) { - output->insert (*i); - } - } - for (auto i = other_dots.begin (); i != other_dots.end (); ++i) { - if (dots.find (*i) == dots.end ()) { - output->insert (*i); - } - } - } else if (op == EdgeAnd) { - for (auto i = dots.begin (); i != dots.end (); ++i) { - if (other_dots.find (*i) != other_dots.end ()) { - output->insert (*i); - } - } - } - return output.release (); } std::pair AsIfFlatEdges::boolean_andnot (const Edges *other) const { - std::set dots, other_dots; - std::unique_ptr output (new FlatEdges (true)); std::unique_ptr output2 (new FlatEdges (true)); EdgeBooleanClusterCollectorToShapes cluster_collector (&output->raw_edges (), EdgeAndNot, &output2->raw_edges ()); @@ -957,11 +911,7 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const AddressableEdgeDelivery e (begin ()); for ( ; ! e.at_end (); ++e) { - if (! e->is_degenerate ()) { - scanner.insert (e.operator-> (), 0); - } else { - dots.insert (*e); - } + scanner.insert (e.operator-> (), 0); } AddressableEdgeDelivery ee; @@ -969,26 +919,12 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const if (other) { ee = other->addressable_edges (); for ( ; ! ee.at_end (); ++ee) { - if (! ee->is_degenerate ()) { - scanner.insert (ee.operator-> (), 1); - } else { - other_dots.insert (*ee); - } + scanner.insert (ee.operator-> (), 1); } } scanner.process (cluster_collector, 1, db::box_convert ()); - // process dots - // NOTE: currently, dots vs. dots is supported, but not dots vs. edges - for (auto i = dots.begin (); i != dots.end (); ++i) { - if (other_dots.find (*i) == other_dots.end ()) { - output2->insert (*i); - } else { - output->insert (*i); - } - } - return std::make_pair (output.release (), output2.release ()); } diff --git a/src/db/db/dbBoxScanner.h b/src/db/db/dbBoxScanner.h index bcdb9fd02..2b2b06185 100644 --- a/src/db/db/dbBoxScanner.h +++ b/src/db/db/dbBoxScanner.h @@ -1079,7 +1079,7 @@ public: m_cl.erase (cli); } - } else if (m_report_single) { + } else if (m_report_single && m_ignore_single.find (obj) == m_ignore_single.end ()) { // single-object entry: create a cluster and feed it a single-object signature Cluster cl (m_cl_template); @@ -1089,6 +1089,13 @@ public: } } + void ignore_single (const Obj *o) + { + if (m_report_single) { + m_ignore_single.insert (o); + } + } + void add_asymm (const Obj *o1, const Prop &p1, const Obj *o2, const Prop &p2) { om_iterator_type om1 = m_om.find (om_key_type (o1, p1)); @@ -1166,6 +1173,7 @@ private: bool m_report_single; cl_type m_cl; om_type m_om; + std::set m_ignore_single; }; } diff --git a/src/db/db/dbEdgeBoolean.h b/src/db/db/dbEdgeBoolean.h index 1a7050c07..d9600f551 100644 --- a/src/db/db/dbEdgeBoolean.h +++ b/src/db/db/dbEdgeBoolean.h @@ -86,14 +86,14 @@ struct EdgeBooleanCluster { typedef db::Edge::coord_type coord_type; - EdgeBooleanCluster (OutputContainer *output, EdgeBoolOp op) - : mp_output (output), mp_output2 (0), m_op (op) + EdgeBooleanCluster (OutputContainer *output, std::set *dots, EdgeBoolOp op) + : mp_output (output), mp_output2 (0), mp_dots (dots), mp_dots2 (0), m_op (op) { // .. nothing yet .. } - EdgeBooleanCluster (OutputContainer *output, OutputContainer *output2, EdgeBoolOp op) - : mp_output (output), mp_output2 (output2), m_op (op) + EdgeBooleanCluster (OutputContainer *output, OutputContainer *output2, std::set *dots, std::set *dots2, EdgeBoolOp op) + : mp_output (output), mp_output2 (output2), mp_dots (dots), mp_dots2 (dots2), m_op (op) { // .. nothing yet .. } @@ -106,13 +106,31 @@ struct EdgeBooleanCluster if (begin () + 1 == end ()) { if (begin ()->second == 0) { if (m_op == EdgeAndNot) { - mp_output2->insert (*(begin ()->first)); + if (begin ()->first->is_degenerate ()) { + if (mp_dots) { + mp_dots2->insert (begin ()->first->p1 ()); + } + } else if (mp_output2) { + mp_output2->insert (*(begin ()->first)); + } } else if (m_op != EdgeAnd) { - mp_output->insert (*(begin ()->first)); + if (begin ()->first->is_degenerate ()) { + if (mp_dots) { + mp_dots->insert (begin ()->first->p1 ()); + } + } else if (mp_output) { + mp_output->insert (*(begin ()->first)); + } } } else { if (m_op != EdgeAnd && m_op != EdgeNot && m_op != EdgeAndNot) { - mp_output->insert (*(begin ()->first)); + if (begin ()->first->is_degenerate ()) { + if (mp_dots) { + mp_dots->insert (begin ()->first->p1 ()); + } + } else if (mp_output) { + mp_output->insert (*(begin ()->first)); + } } } return; @@ -258,6 +276,7 @@ struct EdgeBooleanCluster private: OutputContainer *mp_output, *mp_output2; + std::set *mp_dots, *mp_dots2; db::EdgeBoolOp m_op; }; @@ -266,8 +285,8 @@ struct EdgeBooleanClusterCollector : public db::cluster_collector > { EdgeBooleanClusterCollector (OutputContainer *output, EdgeBoolOp op, OutputContainer *output2 = 0) - : db::cluster_collector > (EdgeBooleanCluster (output, output2, op == EdgeIntersections ? EdgeAnd : op), op != EdgeAnd && op != EdgeIntersections /*report single*/), - mp_output (output), mp_intersections (op == EdgeIntersections ? output : 0) + : db::cluster_collector > (EdgeBooleanCluster (output, output2, &m_dots, &m_dots2, op == EdgeIntersections ? EdgeAnd : op), op != EdgeAnd && op != EdgeIntersections /*report single*/), + mp_output (output), mp_output2 (output2), m_op (op) { // .. nothing yet .. } @@ -289,11 +308,76 @@ struct EdgeBooleanClusterCollector } else { - if (mp_intersections && p1 != p2) { - std::pair ip = o1->intersect_point (*o2); - if (ip.first) { - m_intersections.insert (ip.second); + // dots vs. edge or dot is handled here, no need to copy dots + if (o1->is_degenerate ()) { + this->ignore_single (o1); + } + if (o2->is_degenerate ()) { + this->ignore_single (o2); + } + + if (m_op == EdgeIntersections) { + + if (p1 != p2) { + std::pair ip = o1->intersect_point (*o2); + if (ip.first) { + m_dots.insert (ip.second); + } } + + } else if (m_op == EdgeAndNot) { + + // handle case of dot vs. edge or dot + if (p1 != p2 && (o1->is_degenerate () || o2->is_degenerate ())) { + std::pair ip = o1->intersect_point (*o2); + if (ip.first) { + m_dots.insert (ip.second); + } + if (o1->is_degenerate () && ! ip.first) { + m_dots2.insert (o1->p1 ()); + } + } + + } else if (m_op == EdgeAnd) { + + // handle case of dot vs. edge or dot + if (p1 != p2 && (o1->is_degenerate () || o2->is_degenerate ())) { + std::pair ip = o1->intersect_point (*o2); + if (ip.first) { + m_dots.insert (ip.second); + } + } + + } else if (m_op == EdgeNot) { + + // handle case of dot vs. edge or dot + if (p1 != p2 && o1->is_degenerate ()) { + std::pair ip = o1->intersect_point (*o2); + if (! ip.first) { + m_dots.insert (o1->p1 ()); + } + } + + } else if (m_op == EdgeOr) { + + // forward dots + if (o1->is_degenerate ()) { + m_dots.insert (o1->p1 ()); + } + if (o2->is_degenerate ()) { + m_dots.insert (o2->p1 ()); + } + + } else if (m_op == EdgeXor) { + + // handle case of dot vs. edge or dot + if (p1 != p2 && o1->is_degenerate () && o2->is_degenerate ()) { + if (o1->p1 () != o2->p1 ()) { + m_dots.insert (o1->p1 ()); + m_dots.insert (o2->p1 ()); + } + } + } } @@ -348,35 +432,44 @@ struct EdgeBooleanClusterCollector }; /** - * @brief Finalizes the implementation for "EdgeIntersections" + * @brief Finalizes the implementation for "sections" * This method pushes those points which don't interact with the edges to the output container * as degenerate edges. It needs to be called after the pass has been made. */ void finalize (bool) { - if (m_intersections.empty ()) { + add_orphan_dots (m_dots, mp_output); + if (mp_output2) { + add_orphan_dots (m_dots2, mp_output2); + } + } + +private: + OutputContainer *mp_output, *mp_output2; + EdgeBoolOp m_op; + std::set m_dots, m_dots2; + + static void add_orphan_dots (const std::set &dots, OutputContainer *output) + { + if (dots.empty ()) { return; } - db::box_scanner2 intersections_to_edge_scanner; - for (typename OutputContainer::const_iterator e = mp_output->begin (); e != mp_output->end (); ++e) { - intersections_to_edge_scanner.insert1 (e.operator-> (), 0); + db::box_scanner2 dots_to_edge_scanner; + for (typename OutputContainer::const_iterator e = output->begin (); e != output->end (); ++e) { + dots_to_edge_scanner.insert1 (e.operator-> (), 0); } - for (std::set::const_iterator p = m_intersections.begin (); p != m_intersections.end (); ++p) { - intersections_to_edge_scanner.insert2 (p.operator-> (), 0); + for (std::set::const_iterator p = dots.begin (); p != dots.end (); ++p) { + dots_to_edge_scanner.insert2 (p.operator-> (), 0); } std::set points_to_remove; RemovePointsOnEdges rpoe (points_to_remove); - intersections_to_edge_scanner.process (rpoe, 1, db::box_convert (), db::box_convert ()); + dots_to_edge_scanner.process (rpoe, 1, db::box_convert (), db::box_convert ()); + + std::set_difference (dots.begin (), dots.end (), points_to_remove.begin (), points_to_remove.end (), PointInserter (output)); - std::set_difference (m_intersections.begin (), m_intersections.end (), points_to_remove.begin (), points_to_remove.end (), PointInserter (mp_intersections)); } - -private: - OutputContainer *mp_output; - OutputContainer *mp_intersections; - std::set m_intersections; }; /** diff --git a/src/db/db/dbRegionCheckUtils.cc b/src/db/db/dbRegionCheckUtils.cc index 8b7dbf249..9ace8d834 100644 --- a/src/db/db/dbRegionCheckUtils.cc +++ b/src/db/db/dbRegionCheckUtils.cc @@ -133,7 +133,7 @@ Edge2EdgeCheckBase::finish (const Edge *o, size_t p) std::set partial_edges; - db::EdgeBooleanCluster > ec (&partial_edges, db::EdgeNot); + db::EdgeBooleanCluster > ec (&partial_edges, 0, db::EdgeNot); ec.add (o, 0); for (std::multimap, size_t>::const_iterator i = i0; i != m_e2ep.end () && i->first == k; ++i) { diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index f214f42a4..3d4c7c5a0 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -133,7 +133,7 @@ TEST(3_Edge2EdgeBooleans) db::Layout ly; { std::string fn (tl::testdata ()); - fn += "/algo/deep_region_l1.gds"; + fn += "/algo/deep_edges_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); @@ -145,14 +145,17 @@ TEST(3_Edge2EdgeBooleans) db::DeepShapeStore dss; unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l21 = ly.get_layer (db::LayerProperties (2, 1)); unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); unsigned int lempty = ly.insert_layer (); db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r21 (db::RecursiveShapeIterator (ly, top_cell, l21), dss); db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); db::Region r2and3 = r2 & r3; db::Edges e2 = r2.edges (); + db::Edges e21 = r21.edges (); db::Edges e3 = r3.edges (); db::Edges e3copy = r3.edges (); db::Edges e2and3 = r2and3.edges (); @@ -177,6 +180,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), eempty & e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), edots & edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), edots & e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), e21 & edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (28, 0)), edots & e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e3 - e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e3 - edots); @@ -185,6 +190,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (34, 0)), eempty - e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (35, 0)), edots - edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (36, 0)), edots - e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (37, 0)), e21 - edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (38, 0)), edots - e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e3 ^ e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e3 ^ edots); @@ -193,6 +200,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (44, 0)), eempty ^ e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (45, 0)), edots ^ edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (46, 0)), edots ^ e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (47, 0)), e21 ^ edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (48, 0)), edots ^ e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), e3.andnot(e2and3).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), e3.andnot(edots).first); @@ -201,6 +210,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (54, 0)), eempty.andnot(e2and3).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (55, 0)), edots.andnot(edotscopy).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (56, 0)), edots.andnot(e2).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (57, 0)), e21.andnot(edots).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (58, 0)), edots.andnot(e21).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), e3.andnot(e2and3).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), e3.andnot(edots).second); @@ -209,6 +220,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (64, 0)), eempty.andnot(e2and3).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (65, 0)), edots.andnot(edotscopy).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (66, 0)), edots.andnot(e2).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (67, 0)), e21.andnot(edots).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (68, 0)), edots.andnot(e21).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (70, 0)), e3.intersections(e2and3)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (71, 0)), e3.intersections(edots)); @@ -219,6 +232,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (76, 0)), edots.intersections(e2)); // test, whether dots are not merged target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (77, 0)), edots.intersections(e2).select_interacting(e2)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (78, 0)), e21.intersections(edots)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (79, 0)), edots.intersections(e21)); CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au3.gds"); diff --git a/src/db/unit_tests/dbEdgesTests.cc b/src/db/unit_tests/dbEdgesTests.cc index c5e0754cf..727405280 100644 --- a/src/db/unit_tests/dbEdgesTests.cc +++ b/src/db/unit_tests/dbEdgesTests.cc @@ -1165,7 +1165,7 @@ TEST(29) db::Edges e; e.insert (db::Edge (db::Point(0, 0), db::Point (100, 0))); e.insert (db::Edge (db::Point(110, 0), db::Point (110, 0))); - EXPECT_EQ (e.merged ().to_string (), "(0,0;100,0)"); + EXPECT_EQ (e.merged ().to_string (), "(0,0;100,0);(110,0;110,0)"); e.insert (db::Edge (db::Point(100, 0), db::Point (110, 0))); // dots do not participate in merge @@ -1175,7 +1175,7 @@ TEST(29) e.insert (db::Edge (db::Point(110, 0), db::Point (110, 0))); e.insert (db::Edge (db::Point(110, 0), db::Point (110, 0))); // dots do not participate in merge - EXPECT_EQ (e.merged ().to_string (), ""); + EXPECT_EQ (e.merged ().to_string (), "(110,0;110,0)"); } // interacting with count @@ -1263,7 +1263,7 @@ TEST(31) db::Layout ly; { std::string fn (tl::testdata ()); - fn += "/algo/deep_region_l1.gds"; + fn += "/algo/deep_edges_l1.gds"; tl::InputStream stream (fn); db::Reader reader (stream); reader.read (ly); @@ -1273,14 +1273,17 @@ TEST(31) db::Cell &top_cell = ly.cell (top_cell_index); unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l21 = ly.get_layer (db::LayerProperties (2, 1)); unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); unsigned int lempty = ly.insert_layer (); db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2)); + db::Region r21 (db::RecursiveShapeIterator (ly, top_cell, l21)); db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3)); db::Region r2and3 = r2 & r3; db::Edges e2 = r2.edges (); + db::Edges e21 = r21.edges (); db::Edges e3 = r3.edges (); db::Edges e3copy = r3.edges (); db::Edges e2and3 = r2and3.edges (); @@ -1305,6 +1308,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), eempty & e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (25, 0)), edots & edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (26, 0)), edots & e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (27, 0)), e21 & edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (28, 0)), edots & e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), e3 - e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e3 - edots); @@ -1313,6 +1318,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (34, 0)), eempty - e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (35, 0)), edots - edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (36, 0)), edots - e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (37, 0)), e21 - edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (38, 0)), edots - e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), e3 ^ e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e3 ^ edots); @@ -1321,6 +1328,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (44, 0)), eempty ^ e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (45, 0)), edots ^ edotscopy); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (46, 0)), edots ^ e2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (47, 0)), e21 ^ edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (48, 0)), edots ^ e21); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (50, 0)), e3.andnot(e2and3).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), e3.andnot(edots).first); @@ -1329,6 +1338,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (54, 0)), eempty.andnot(e2and3).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (55, 0)), edots.andnot(edotscopy).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (56, 0)), edots.andnot(e2).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (57, 0)), e21.andnot(edots).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (58, 0)), edots.andnot(e21).first); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (60, 0)), e3.andnot(e2and3).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), e3.andnot(edots).second); @@ -1337,6 +1348,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (64, 0)), eempty.andnot(e2and3).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (65, 0)), edots.andnot(edotscopy).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (66, 0)), edots.andnot(e2).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (67, 0)), e21.andnot(edots).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (68, 0)), edots.andnot(e21).second); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (70, 0)), e3.intersections(e2and3)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (71, 0)), e3.intersections(edots)); @@ -1347,6 +1360,8 @@ TEST(31) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (76, 0)), edots.intersections(e2)); // test, whether dots are not merged target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (77, 0)), edots.intersections(e2).select_interacting(e2)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (78, 0)), e21.intersections(edots)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (79, 0)), edots.intersections(e21)); CHECKPOINT(); db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au3_flat.gds"); diff --git a/testdata/algo/deep_edges_au3.gds b/testdata/algo/deep_edges_au3.gds index b6d89fd5e..b5a143c79 100644 Binary files a/testdata/algo/deep_edges_au3.gds and b/testdata/algo/deep_edges_au3.gds differ diff --git a/testdata/algo/deep_edges_au3_flat.gds b/testdata/algo/deep_edges_au3_flat.gds index b2e385c13..ca8d210ec 100644 Binary files a/testdata/algo/deep_edges_au3_flat.gds and b/testdata/algo/deep_edges_au3_flat.gds differ diff --git a/testdata/algo/deep_edges_l1.gds b/testdata/algo/deep_edges_l1.gds new file mode 100644 index 000000000..7a9bada7e Binary files /dev/null and b/testdata/algo/deep_edges_l1.gds differ diff --git a/testdata/drc/drcSuiteTests_au3.oas b/testdata/drc/drcSuiteTests_au3.oas index 3430b083c..9bffec16f 100644 Binary files a/testdata/drc/drcSuiteTests_au3.oas and b/testdata/drc/drcSuiteTests_au3.oas differ