diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index 797ca73d2..57b3fc2a7 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -757,9 +757,123 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co return result.release (); } +EdgesDelegate * +AsIfFlatEdges::merged () const +{ + if (empty ()) { + return new db::EmptyEdges (); + } else { + return boolean (0, EdgeOr); + } +} + +EdgesDelegate * +AsIfFlatEdges::and_with (const Edges &other) const +{ + if (empty () || other.empty ()) { + return new db::EmptyEdges (); + } else { + return boolean (&other, EdgeAnd); + } +} + +EdgesDelegate * +AsIfFlatEdges::not_with (const Edges &other) const +{ + if (empty ()) { + return new db::EmptyEdges (); + } else if (other.empty ()) { + return clone (); + } else { + return boolean (&other, EdgeNot); + } +} + +std::pair +AsIfFlatEdges::andnot_with (const Edges &other) const +{ + if (empty ()) { + return std::make_pair (new db::EmptyEdges (), new db::EmptyEdges ()); + } else if (other.empty ()) { + return std::make_pair (new db::EmptyEdges (), clone ()); + } else { + return boolean_andnot (&other); + } +} + +EdgesDelegate * +AsIfFlatEdges::and_with (const Region &other) const +{ + if (empty () || other.empty ()) { + return new db::EmptyEdges (); + } else { + return edge_region_op (other, db::EdgePolygonOp::Inside, true /*include borders*/).first; + } +} + +EdgesDelegate * +AsIfFlatEdges::not_with (const Region &other) const +{ + if (empty ()) { + return new db::EmptyEdges (); + } else if (other.empty ()) { + return clone (); + } else { + return edge_region_op (other, db::EdgePolygonOp::Outside, true /*include borders*/).first; + } +} + +std::pair +AsIfFlatEdges::andnot_with (const Region &other) const +{ + if (empty ()) { + return std::make_pair (new db::EmptyEdges (), new db::EmptyEdges ()); + } else if (other.empty ()) { + return std::make_pair (new db::EmptyEdges (), clone ()); + } else { + return edge_region_op (other, db::EdgePolygonOp::Both, true /*include borders*/); + } +} + +EdgesDelegate * +AsIfFlatEdges::xor_with (const Edges &other) const +{ + if (empty ()) { + return other.delegate ()->clone (); + } else if (other.empty ()) { + return clone (); + } else { + return boolean (&other, EdgeXor); + } +} + +EdgesDelegate * +AsIfFlatEdges::or_with (const Edges &other) const +{ + if (empty ()) { + return other.delegate ()->clone (); + } else if (other.empty ()) { + return clone (); + } else { + return boolean (&other, EdgeOr); + } +} + +EdgesDelegate * +AsIfFlatEdges::intersections (const Edges &other) const +{ + if (empty () || other.empty ()) { + return new db::EmptyEdges (); + } else { + return boolean (&other, EdgeIntersections); + } +} + 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); @@ -769,8 +883,10 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const AddressableEdgeDelivery e (begin ()); for ( ; ! e.at_end (); ++e) { - if (! e->is_degenerate ()) { + if (op == EdgeIntersections || ! e->is_degenerate ()) { scanner.insert (e.operator-> (), 0); + } else if (op != EdgeOr) { + dots.insert (*e); } } @@ -779,20 +895,58 @@ AsIfFlatEdges::boolean (const Edges *other, EdgeBoolOp op) const if (other) { ee = other->addressable_edges (); for ( ; ! ee.at_end (); ++ee) { - if (! ee->is_degenerate ()) { + if (op == EdgeIntersections || ! ee->is_degenerate ()) { scanner.insert (ee.operator-> (), 1); + } else if (op != EdgeOr) { + other_dots.insert (*ee); } } } 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 ()); @@ -805,6 +959,8 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const for ( ; ! e.at_end (); ++e) { if (! e->is_degenerate ()) { scanner.insert (e.operator-> (), 0); + } else { + dots.insert (*e); } } @@ -815,12 +971,24 @@ AsIfFlatEdges::boolean_andnot (const Edges *other) const for ( ; ! ee.at_end (); ++ee) { if (! ee->is_degenerate ()) { scanner.insert (ee.operator-> (), 1); + } else { + other_dots.insert (*ee); } } } 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/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index fbdd7064e..fd07227ef 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -107,55 +107,25 @@ public: return merged (); } - virtual EdgesDelegate *merged () const - { - return boolean (0, EdgeOr); - } + virtual EdgesDelegate *merged () const; - virtual EdgesDelegate *and_with (const Edges &other) const - { - return boolean (&other, EdgeAnd); - } + virtual EdgesDelegate *and_with (const Edges &other) const; - virtual EdgesDelegate *not_with (const Edges &other) const - { - return boolean (&other, EdgeNot); - } + virtual EdgesDelegate *not_with (const Edges &other) const; - virtual std::pair andnot_with (const Edges &other) const - { - return boolean_andnot (&other); - } + virtual std::pair andnot_with (const Edges &other) const; - virtual EdgesDelegate *and_with (const Region &other) const - { - return edge_region_op (other, db::EdgePolygonOp::Inside, true /*include borders*/).first; - } + virtual EdgesDelegate *and_with (const Region &other) const; - virtual EdgesDelegate *not_with (const Region &other) const - { - return edge_region_op (other, db::EdgePolygonOp::Outside, true /*include borders*/).first; - } + virtual EdgesDelegate *not_with (const Region &other) const; - virtual std::pair andnot_with (const Region &other) const - { - return edge_region_op (other, db::EdgePolygonOp::Both, true /*include borders*/); - } + virtual std::pair andnot_with (const Region &other) const; - virtual EdgesDelegate *xor_with (const Edges &other) const - { - return boolean (&other, EdgeXor); - } + virtual EdgesDelegate *xor_with (const Edges &other) const; - virtual EdgesDelegate *or_with (const Edges &other) const - { - return boolean (&other, EdgeOr); - } + virtual EdgesDelegate *or_with (const Edges &other) const; - virtual EdgesDelegate *intersections (const Edges &other) const - { - return boolean (&other, EdgeIntersections); - } + virtual EdgesDelegate *intersections (const Edges &other) const; virtual EdgesDelegate *add_in_place (const Edges &other) { diff --git a/src/db/db/dbEdgeBoolean.h b/src/db/db/dbEdgeBoolean.h index 0c35670c4..1a7050c07 100644 --- a/src/db/db/dbEdgeBoolean.h +++ b/src/db/db/dbEdgeBoolean.h @@ -272,13 +272,6 @@ struct EdgeBooleanClusterCollector // .. nothing yet .. } - EdgeBooleanClusterCollector (OutputContainer *output, OutputContainer *intersections, EdgeBoolOp op) - : db::cluster_collector > (EdgeBooleanCluster (output, op), op != EdgeAnd /*report single*/), - mp_output (output), mp_intersections (intersections) - { - // .. nothing yet .. - } - void add (const db::Edge *o1, size_t p1, const db::Edge *o2, size_t p2) { // Select edges which are: diff --git a/src/db/unit_tests/dbEdgesTests.cc b/src/db/unit_tests/dbEdgesTests.cc index 8b6d5e509..c5e0754cf 100644 --- a/src/db/unit_tests/dbEdgesTests.cc +++ b/src/db/unit_tests/dbEdgesTests.cc @@ -22,12 +22,14 @@ #include "tlUnitTest.h" +#include "tlStream.h" #include "dbEdges.h" #include "dbEdgesUtils.h" #include "dbPolygonTools.h" #include "dbRegion.h" #include "dbTestSupport.h" +#include "dbReader.h" #include @@ -1255,6 +1257,101 @@ TEST(30) EXPECT_EQ (e.selected_interacting_differential (r2, size_t (2), size_t(3)).second.to_string (), "(0,0;200,0)"); } +// borrowed from deep edges tests +TEST(31) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l1.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + 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 r3 (db::RecursiveShapeIterator (ly, top_cell, l3)); + db::Region r2and3 = r2 & r3; + + db::Edges e2 = r2.edges (); + db::Edges e3 = r3.edges (); + db::Edges e3copy = r3.edges (); + db::Edges e2and3 = r2and3.edges (); + db::Edges eempty (db::RecursiveShapeIterator (ly, top_cell, lempty)); + db::Edges edots = e2and3.processed (db::EdgeSegmentSelector (-1, 0, 0)); + db::Edges edotscopy = e2and3.processed (db::EdgeSegmentSelector (-1, 0, 0)); + + db::Layout target; + unsigned int target_top_cell_index = target.add_cell (ly.cell_name (top_cell_index)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (2, 0)), r2); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (3, 0)), r3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), e3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), e2and3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), edots.merged ()); + + 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 & edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (22, 0)), e3 & eempty); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (23, 0)), e3 & e3copy); + 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 (30, 0)), e3 - e2and3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), e3 - edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (32, 0)), e3 - eempty); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (33, 0)), e3 - e3copy); + 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 (40, 0)), e3 ^ e2and3); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), e3 ^ edots); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (42, 0)), e3 ^ eempty); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (43, 0)), e3 ^ e3copy); + 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 (50, 0)), e3.andnot(e2and3).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (51, 0)), e3.andnot(edots).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (52, 0)), e3.andnot(eempty).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (53, 0)), e3.andnot(e3copy).first); + 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 (60, 0)), e3.andnot(e2and3).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (61, 0)), e3.andnot(edots).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (62, 0)), e3.andnot(eempty).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (63, 0)), e3.andnot(e3copy).second); + 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 (70, 0)), e3.intersections(e2and3)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (71, 0)), e3.intersections(edots)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (72, 0)), e3.intersections(eempty)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (73, 0)), e3.intersections(e3copy)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (74, 0)), eempty.intersections(e2and3)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (75, 0)), edots.intersections(edotscopy)); + 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)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au3_flat.gds"); +} + // GitHub issue #72 (Edges/Region NOT issue) TEST(100) { diff --git a/testdata/algo/deep_edges_au3_flat.gds b/testdata/algo/deep_edges_au3_flat.gds new file mode 100644 index 000000000..b2e385c13 Binary files /dev/null and b/testdata/algo/deep_edges_au3_flat.gds differ