diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index 203a89e9f..209c303ae 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -533,7 +533,7 @@ EdgesDelegate * AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const { std::auto_ptr output (new FlatEdges (true)); - EdgeBooleanClusterCollector cluster_collector (&output->raw_edges (), op); + EdgeBooleanClusterCollectorToShapes cluster_collector (&output->raw_edges (), op); db::box_scanner scanner (report_progress (), progress_desc ()); scanner.reserve (size () + (other ? other->size () : 0)); diff --git a/src/db/db/dbBoxScanner.h b/src/db/db/dbBoxScanner.h index 868ecc709..eefd7df5a 100644 --- a/src/db/db/dbBoxScanner.h +++ b/src/db/db/dbBoxScanner.h @@ -137,6 +137,21 @@ struct box_scanner_receiver * terminate the scan process early if the outcome is known. */ bool stop () const { return false; } + + /** + * @brief Pre-scanning operations + * + * This method is called before the scanning starts. + */ + void initialize () { } + + /** + * @brief Post-scanning operations + * + * This method is called after the scan has finished (without exception). The argument is the + * return value (false if "stop" stopped the process). + */ + void finalize (bool) { } }; /** @@ -265,6 +280,22 @@ public: */ template bool process (Rec &rec, typename BoxConvert::box_type::coord_type enl, const BoxConvert &bc = BoxConvert ()) + { + rec.initialize (); + bool ret = do_process (rec, enl, bc); + rec.finalize (ret); + return ret; + } + +private: + container_type m_pp; + double m_fill_factor; + size_t m_scanner_thr; + bool m_report_progress; + std::string m_progress_desc; + + template + bool do_process (Rec &rec, typename BoxConvert::box_type::coord_type enl, const BoxConvert &bc = BoxConvert ()) { typedef typename BoxConvert::box_type box_type; typedef typename box_type::coord_type coord_type; @@ -420,13 +451,6 @@ public: return true; } - -private: - container_type m_pp; - double m_fill_factor; - size_t m_scanner_thr; - bool m_report_progress; - std::string m_progress_desc; }; /** @@ -469,6 +493,21 @@ struct box_scanner_receiver2 * terminate the scan process early if the outcome is known. */ bool stop () const { return false; } + + /** + * @brief Pre-scanning operations + * + * This method is called before the scanning starts. + */ + void initialize () { } + + /** + * @brief Post-scanning operations + * + * This method is called after the scan has finished (without exception). The argument is the + * return value (false if "stop" stopped the process). + */ + void finalize (bool) { } }; /** @@ -613,6 +652,23 @@ public: */ template bool process (Rec &rec, typename BoxConvert1::box_type::coord_type enl, const BoxConvert1 &bc1 = BoxConvert1 (), const BoxConvert2 &bc2 = BoxConvert2 ()) + { + rec.initialize (); + bool ret = do_process (rec, enl, bc1, bc2); + rec.finalize (ret); + return ret; + } + +private: + container_type1 m_pp1; + container_type2 m_pp2; + double m_fill_factor; + size_t m_scanner_thr; + bool m_report_progress; + std::string m_progress_desc; + + template + bool do_process (Rec &rec, typename BoxConvert1::box_type::coord_type enl, const BoxConvert1 &bc1 = BoxConvert1 (), const BoxConvert2 &bc2 = BoxConvert2 ()) { typedef typename BoxConvert1::box_type box_type; // must be same as BoxConvert2::box_type typedef typename box_type::coord_type coord_type; @@ -845,14 +901,6 @@ public: return true; } - -private: - container_type1 m_pp1; - container_type2 m_pp2; - double m_fill_factor; - size_t m_scanner_thr; - bool m_report_progress; - std::string m_progress_desc; }; /** diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index e0e11a055..e8929c7bf 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -349,7 +349,7 @@ public: // .. and run the merge operation s->second.clear (); - EdgeBooleanClusterCollector cluster_collector (&s->second, EdgeOr); + EdgeBooleanClusterCollectorToShapes cluster_collector (&s->second, EdgeOr); m_scanner.process (cluster_collector, 1, db::box_convert ()); return s->second; diff --git a/src/db/db/dbEdgeBoolean.h b/src/db/db/dbEdgeBoolean.h index 449d3f8f1..a85fb6e40 100644 --- a/src/db/db/dbEdgeBoolean.h +++ b/src/db/db/dbEdgeBoolean.h @@ -26,6 +26,7 @@ #include "dbEdge.h" #include "dbHash.h" #include "dbBoxScanner.h" +#include "dbShapes.h" #include "tlIntervalMap.h" @@ -222,14 +223,14 @@ struct EdgeBooleanClusterCollector { EdgeBooleanClusterCollector (OutputContainer *output, EdgeBoolOp op) : db::cluster_collector > (EdgeBooleanCluster (output, op == EdgeIntersections ? EdgeAnd : op), op != EdgeAnd && op != EdgeIntersections /*report single*/), - mp_intersections (op == EdgeIntersections ? output : 0) + mp_output (output), mp_intersections (op == EdgeIntersections ? output : 0) { // .. nothing yet .. } EdgeBooleanClusterCollector (OutputContainer *output, OutputContainer *intersections, EdgeBoolOp op) : db::cluster_collector > (EdgeBooleanCluster (output, op), op != EdgeAnd /*report single*/), - mp_intersections (intersections) + mp_output (output), mp_intersections (intersections) { // .. nothing yet .. } @@ -252,16 +253,168 @@ struct EdgeBooleanClusterCollector } else if (mp_intersections && p1 != p2) { std::pair ip = o1->intersect_point (*o2); - if (ip.first && m_seen_intersections.insert (ip.second).second) { - mp_intersections->insert (db::Edge (ip.second, ip.second)); + if (ip.first) { + m_intersections.insert (ip.second); } } } + /** + * @brief A receiver for the reducer which removes points that are on the edges + */ + struct RemovePointsOnEdges + : public db::box_scanner_receiver2 + { + public: + RemovePointsOnEdges (std::set &points_to_remove) + : mp_points_to_remove (&points_to_remove) + { } + + void add (const db::Edge *e, const size_t &, const db::Point *pt, const size_t &) + { + if (e->contains (*pt)) { + mp_points_to_remove->insert (*pt); + } + } + + private: + std::set *mp_points_to_remove; + }; + + /** + * @brief An inserter to produce degenerated edges from points + */ + struct PointInserter + : public std::iterator + { + typedef db::Point value_type; + + PointInserter (OutputContainer *output) + : mp_output (output) + { } + + PointInserter &operator= (const db::Point &pt) + { + mp_output->insert (db::Edge (pt, pt)); + return *this; + } + + PointInserter &operator* () { return *this; } + PointInserter &operator++ () { return *this; } + PointInserter &operator++ (int) { return *this; } + + private: + OutputContainer *mp_output; + }; + + /** + * @brief Finalizes the implementation for "EdgeIntersections" + * 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 ()) { + 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); + } + for (std::set::const_iterator p = m_intersections.begin (); p != m_intersections.end (); ++p) { + intersections_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 ()); + + 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::unordered_set m_seen_intersections; + std::set m_intersections; +}; + +/** + * @brief A helper class to use db::Shapes as container for EdgeBooleanClusterCollector + */ +struct DB_PUBLIC ShapesToOutputContainerAdaptor +{ +public: + struct Iterator + : public db::Shapes::shape_iterator + { + Iterator (const db::Shapes::shape_iterator &iter) + : db::Shapes::shape_iterator (iter) + { } + + Iterator () + : db::Shapes::shape_iterator () + { } + + const db::Edge *operator-> () const + { + return (db::Shapes::shape_iterator::operator* ()).basic_ptr (db::Edge::tag ()); + } + + bool operator!= (const Iterator &other) const + { + // only for testing whether at end: + return at_end () != other.at_end (); + } + + bool operator== (const Iterator &other) const + { + // only for testing whether at end: + return at_end () == other.at_end (); + } + }; + + typedef Iterator const_iterator; + + ShapesToOutputContainerAdaptor (db::Shapes &shapes) + : mp_shapes (&shapes) + { + // .. nothing yet .. + } + + const_iterator begin () + { + return Iterator (mp_shapes->begin (db::ShapeIterator::Edges)); + } + + const_iterator end () + { + return Iterator (); + } + + void insert (const db::Edge &edge) + { + mp_shapes->insert (edge); + } + +private: + db::Shapes *mp_shapes; +}; + +/** + * @brief A specialization of the EdgeBooleanClusterCollector for a Shapes output container + */ +struct DB_PUBLIC EdgeBooleanClusterCollectorToShapes + : EdgeBooleanClusterCollector +{ + EdgeBooleanClusterCollectorToShapes (db::Shapes *output, EdgeBoolOp op) + : EdgeBooleanClusterCollector (&m_adaptor, op), m_adaptor (*output) + { + } + +private: + ShapesToOutputContainerAdaptor m_adaptor; }; } diff --git a/src/db/db/dbFlatEdges.cc b/src/db/db/dbFlatEdges.cc index 75c977bee..75d80f539 100644 --- a/src/db/db/dbFlatEdges.cc +++ b/src/db/db/dbFlatEdges.cc @@ -112,7 +112,7 @@ FlatEdges::ensure_merged_edges_valid () const m_merged_edges.clear (); db::Shapes tmp (false); - EdgeBooleanClusterCollector cluster_collector (&tmp, EdgeOr); + EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr); db::box_scanner scanner (report_progress (), progress_desc ()); scanner.reserve (m_edges.size ()); diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 3c85dc9be..1728f32d6 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1228,11 +1228,6 @@ public: add_pair (*c1, *i2, p, t); } - bool stop () const - { - return false; - } - /** * @brief Finally join the clusters in the join set * @@ -1275,6 +1270,11 @@ public: } } + // needs explicit implementation because we have two base classes: + bool stop () const { return false; } + void initialize () { } + void finalize (bool) { } + private: struct InteractionKeyForClustersType : public InstanceToInstanceInteraction diff --git a/src/db/db/dbOriginalLayerEdges.cc b/src/db/db/dbOriginalLayerEdges.cc index ee47f5771..631652f8b 100644 --- a/src/db/db/dbOriginalLayerEdges.cc +++ b/src/db/db/dbOriginalLayerEdges.cc @@ -253,7 +253,7 @@ OriginalLayerEdges::ensure_merged_edges_valid () const m_merged_edges.clear (); db::Shapes tmp (false); - EdgeBooleanClusterCollector cluster_collector (&tmp, EdgeOr); + EdgeBooleanClusterCollectorToShapes cluster_collector (&tmp, EdgeOr); db::box_scanner scanner (report_progress (), progress_desc ()); scanner.reserve (size ()); diff --git a/src/db/unit_tests/dbBoxScanner.cc b/src/db/unit_tests/dbBoxScanner.cc index 8d396e3b7..48369cb64 100644 --- a/src/db/unit_tests/dbBoxScanner.cc +++ b/src/db/unit_tests/dbBoxScanner.cc @@ -36,6 +36,8 @@ struct BoxScannerTestRecorder } bool stop () const { return false; } + void initialize () { str += "[i]"; } + void finalize (bool) { str += "[f]"; } void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2) { @@ -54,6 +56,8 @@ struct BoxScannerTestRecorderStopping } bool stop () const { return do_stop; } + void initialize () { str += "[i]"; } + void finalize (bool s) { str += s ? "[f+]" : "[f-]"; } void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2) { @@ -70,6 +74,8 @@ struct BoxScannerTestRecorder2 void finish (const db::Box *, size_t) { } bool stop () const { return false; } + void initialize () { } + void finalize (bool) { } void add (const db::Box * /*b1*/, size_t p1, const db::Box * /*b2*/, size_t p2) { @@ -91,6 +97,8 @@ struct BoxScannerTestRecorderTwo } bool stop () const { return false; } + void initialize () { str += "[i]"; } + void finalize (bool) { str += "[f]"; } void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2) { @@ -113,6 +121,8 @@ struct BoxScannerTestRecorderTwoStopping } bool stop () const { return do_stop; } + void initialize () { str += "[i]"; } + void finalize (bool s) { str += s ? "[f+]" : "[f-]"; } void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2) { @@ -130,6 +140,8 @@ struct BoxScannerTestRecorder2Two void finish2 (const db::SimplePolygon *, int) { } bool stop () const { return false; } + void initialize () { } + void finalize (bool) { } void add (const db::Box * /*b1*/, size_t p1, const db::SimplePolygon * /*b2*/, int p2) { @@ -159,11 +171,11 @@ TEST(1) db::box_convert bc; bs.set_scanner_threshold (0); EXPECT_EQ (bs.process (tr, 1, bc), true); - EXPECT_EQ (tr.str, "(4-2)(5-2)(5-4)(3-2)(3-4)(5-3)<2><5><4><3>(1-0)<0><1>"); + EXPECT_EQ (tr.str, "[i](4-2)(5-2)(5-4)(3-2)(3-4)(5-3)<2><5><4><3>(1-0)<0><1>[f]"); BoxScannerTestRecorderStopping trstop; EXPECT_EQ (bs.process (trstop, 1, bc), false); - EXPECT_EQ (trstop.str, "(4-2)"); + EXPECT_EQ (trstop.str, "[i](4-2)[f-]"); } TEST(1a) @@ -182,7 +194,7 @@ TEST(1a) db::box_convert bc; bs.set_scanner_threshold (0); bs.process (tr, 1, bc); - EXPECT_EQ (tr.str, "(1-0)<0><1>"); + EXPECT_EQ (tr.str, "[i](1-0)<0><1>[f]"); } TEST(1b) @@ -204,7 +216,7 @@ TEST(1b) db::box_convert bc; bs.set_scanner_threshold (0); bs.process (tr, 1, bc); - EXPECT_EQ (tr.str, "(3-0)(1-3)(4-1)(2-4)<0><3><1><4><2>"); + EXPECT_EQ (tr.str, "[i](3-0)(1-3)(4-1)(2-4)<0><3><1><4><2>[f]"); } TEST(1c) @@ -226,7 +238,7 @@ TEST(1c) db::box_convert bc; bs.set_scanner_threshold (0); bs.process (tr, 1, bc); - EXPECT_EQ (tr.str, "(3-0)(1-3)<0>(4-1)<3>(2-4)<1><4><2>"); + EXPECT_EQ (tr.str, "[i](3-0)(1-3)<0>(4-1)<3>(2-4)<1><4><2>[f]"); } TEST(1d) @@ -248,7 +260,7 @@ TEST(1d) db::box_convert bc; bs.set_scanner_threshold (0); bs.process (tr, 0, bc); - EXPECT_EQ (tr.str, "(3-0)<0><3><1><4><2>"); + EXPECT_EQ (tr.str, "[i](3-0)<0><3><1><4><2>[f]"); } TEST(1e) @@ -269,7 +281,7 @@ TEST(1e) bs.set_fill_factor (0.0); db::box_convert bc; bs.process (tr, 0, bc); - EXPECT_EQ (tr.str, "(0-3)<0><1><2><3><4>"); + EXPECT_EQ (tr.str, "[i](0-3)<0><1><2><3><4>[f]"); } TEST(1f) @@ -280,7 +292,7 @@ TEST(1f) bs.set_fill_factor (0.0); db::box_convert bc; bs.process (tr, 0, bc); - EXPECT_EQ (tr.str, ""); + EXPECT_EQ (tr.str, "[i][f]"); } TEST(1g) @@ -302,7 +314,7 @@ TEST(1g) bs.set_fill_factor (0.0); db::box_convert bc; bs.process (tr, 0, bc); - EXPECT_EQ (tr.str, "<2><4>(0-3)<0><1><3>"); + EXPECT_EQ (tr.str, "[i]<2><4>(0-3)<0><1><3>[f]"); } void run_test2 (tl::TestBase *_this, size_t n, double ff, db::Coord spread, bool touch = true) @@ -927,7 +939,7 @@ TEST(two_1) db::box_convert bc2; bs.set_scanner_threshold (0); bs.process (tr, 1, bc1, bc2); - EXPECT_EQ (tr.str, "(2-12)(2-14)(4-12)(4-14)(2-15)(4-15)(5-12)(5-14)(5-15)(2-13)(4-13)(3-12)(3-14)(3-13)(3-15)(5-13)(0-10)<2><5><4><3><12><15><14><13>(0-11)(1-10)(1-11)<0><1><10><11>"); + EXPECT_EQ (tr.str, "[i](2-12)(2-14)(4-12)(4-14)(2-15)(4-15)(5-12)(5-14)(5-15)(2-13)(4-13)(3-12)(3-14)(3-13)(3-15)(5-13)(0-10)<2><5><4><3><12><15><14><13>(0-11)(1-10)(1-11)<0><1><10><11>[f]"); } TEST(two_1a) @@ -963,7 +975,7 @@ TEST(two_1a) db::box_convert bc2; bs.set_scanner_threshold (0); bs.process (tr, 1, bc1, bc2); - EXPECT_EQ (tr.str, "(2-11)(2-12)(1-11)(1-12)<1><2><11><12>(0-10)<0><10>"); + EXPECT_EQ (tr.str, "[i](2-11)(2-12)(1-11)(1-12)<1><2><11><12>(0-10)<0><10>[f]"); } TEST(two_1b) @@ -999,12 +1011,12 @@ TEST(two_1b) db::box_convert bc2; bs.set_scanner_threshold (0); EXPECT_EQ (bs.process (tr, 1, bc1, bc2), true); - EXPECT_EQ (tr.str, "(1-12)(2-12)(1-11)(2-11)<1><2><11><12>(0-10)<0><10>"); + EXPECT_EQ (tr.str, "[i](1-12)(2-12)(1-11)(2-11)<1><2><11><12>(0-10)<0><10>[f]"); BoxScannerTestRecorderTwoStopping trstop; EXPECT_EQ (bs.process (trstop, 1, bc1, bc2), false); - EXPECT_EQ (trstop.str, "(1-12)"); + EXPECT_EQ (trstop.str, "[i](1-12)[f-]"); } TEST(two_1c) @@ -1035,7 +1047,7 @@ TEST(two_1c) db::box_convert bc2; bs.set_scanner_threshold (0); EXPECT_EQ (bs.process (tr, 1, bc1, bc2), true); - EXPECT_EQ (tr.str, "<0><10>(1-12)(2-12)(1-11)(2-11)<1><2><12><11>"); + EXPECT_EQ (tr.str, "[i]<0><10>(1-12)(2-12)(1-11)(2-11)<1><2><12><11>[f]"); } void run_test2_two (tl::TestBase *_this, size_t n, double ff, db::Coord spread, bool touch = true) diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index 2fa7f90d2..33ff2c563 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -131,6 +131,7 @@ TEST(3_Edge2EdgeBooleans) db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); db::Region r2and3 = r2 & r3; + db::Edges e2 = r2.edges (); db::Edges e3 = r3.edges (); db::Edges e2and3 = r2and3.edges (); @@ -144,6 +145,8 @@ TEST(3_Edge2EdgeBooleans) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), e3 & e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), e3 - e2and3); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), e3 ^ e2and3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), e3.intersections(e2and3)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (24, 0)), e3.intersections(e2)); CHECKPOINT(); db::compare_layouts (_this, target, tl::testsrc () + "/testdata/algo/deep_edges_au3.gds"); diff --git a/src/db/unit_tests/dbEdges.cc b/src/db/unit_tests/dbEdges.cc index ace673825..eff26ff66 100644 --- a/src/db/unit_tests/dbEdges.cc +++ b/src/db/unit_tests/dbEdges.cc @@ -852,9 +852,37 @@ TEST(22) ee.insert (db::Edge (4000,-2000,-2000,-2000)); EXPECT_EQ ((e & ee).to_string (), "(400,0;-2000,0);(500,-174;400,0);(1000,0;900,-173);(4000,0;1000,0)"); - EXPECT_EQ (e.intersections (ee).to_string (), "(400,0;400,0);(-2000,0;-2000,0);(1000,0;1000,0);(4000,0;4000,0);(400,0;-2000,0);(500,-174;400,0);(1000,0;900,-173);(4000,0;1000,0)"); - // no particular new points with intersections - just endpoints of original edges - EXPECT_EQ (e.intersections (ee).merged ().to_string (), "(400,0;-2000,0);(500,-174;400,0);(1000,0;900,-173);(4000,0;1000,0)"); + EXPECT_EQ (e.intersections (ee).to_string (), "(400,0;-2000,0);(500,-174;400,0);(1000,0;900,-173);(4000,0;1000,0)"); + + // Edge/edge intersections + ee.clear (); + e.clear (); + e.insert (db::Edge (0, -100, 0, 150)); + ee.insert (db::Edge (-50, 50, 50, 50)); + ee.insert (db::Edge (-50, 100, 50, 100)); + EXPECT_EQ ((e & ee).to_string (), ""); // AND does not report intersection points + EXPECT_EQ (e.intersections (ee).to_string (), "(0,50;0,50);(0,100;0,100)"); + + // Edge is intersected by pair with connection point on this line + ee.clear (); + e.clear (); + e.insert (db::Edge (0, -100, 0, 150)); + ee.insert (db::Edge (-50, 50, 0, 50)); + ee.insert (db::Edge (0, 60, 50, 60)); + ee.insert (db::Edge (-50, 100, 0, 100)); + ee.insert (db::Edge (0, 100, 50, 100)); + EXPECT_EQ ((e & ee).to_string (), ""); // AND does not report intersection points + EXPECT_EQ (e.intersections (ee).to_string (), "(0,50;0,50);(0,60;0,60);(0,100;0,100)"); + + // Coincident edges are crossed by another one + ee.clear (); + e.clear (); + e.insert (db::Edge (0, -100, 0, 250)); + ee.insert (db::Edge (0, 0, 0, 150)); + ee.insert (db::Edge (-50, 100, 50, 100)); + ee.insert (db::Edge (-50, 200, 50, 200)); + EXPECT_EQ ((e & ee).to_string (), "(0,0;0,150)"); + EXPECT_EQ (e.intersections (ee).to_string (), "(0,0;0,150);(0,200;0,200)"); } TEST(23) diff --git a/testdata/algo/deep_edges_au3.gds b/testdata/algo/deep_edges_au3.gds index ae59b5807..62914f828 100644 Binary files a/testdata/algo/deep_edges_au3.gds and b/testdata/algo/deep_edges_au3.gds differ diff --git a/testdata/drc/drcSuiteTests.drc b/testdata/drc/drcSuiteTests.drc index b3164b5cd..be4c43ed6 100644 --- a/testdata/drc/drcSuiteTests.drc +++ b/testdata/drc/drcSuiteTests.drc @@ -589,6 +589,22 @@ def run_testsuite(dm, ic, tiled = false, hier = false) p = c.edges.pull_interacting(b.edges) p.output(lb + 5, dm) + lb += 10 #440 + message "--- edge booleans, intersections #{lb}" + + p = c.edges - b.edges + p.output(lb, dm) + p = b.edges - c.edges + p.output(lb + 1, dm) + p = c.edges & b.edges + p.output(lb + 2, dm) + p = c.edges ^ b.edges + p.output(lb + 3, dm) + p = c.edges.intersections(b.edges) + p.output(lb + 4, dm) + p = b.edges.intersections(c.edges) + p.output(lb + 5, dm) + end if $drc_test_mode == 1