diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 9343ae457..e266660fc 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -916,10 +916,19 @@ EdgesDelegate *DeepEdges::merged () const return res.release (); } -DeepLayer +std::pair DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const { + std::vector output_layers; + DeepLayer dl_out (deep_layer ().derived ()); + output_layers.push_back (dl_out.layer ()); + + DeepLayer dl_out2; + if (op == EdgeAndNot) { + dl_out2 = DeepLayer (deep_layer ().derived ()); + output_layers.push_back (dl_out2.layer ()); + } db::EdgeBoolAndOrNotLocalOperation local_op (op); @@ -929,9 +938,9 @@ DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ()); proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ()); - proc.run (&local_op, deep_layer ().layer (), other->deep_layer ().layer (), dl_out.layer ()); + proc.run (&local_op, deep_layer ().layer (), other->deep_layer ().layer (), output_layers); - return dl_out; + return std::make_pair (dl_out, dl_out2); } std::pair @@ -965,17 +974,25 @@ EdgesDelegate *DeepEdges::intersections (const Edges &other) const { const DeepEdges *other_deep = dynamic_cast (other.delegate ()); - if (empty () || other.empty ()) { + if (empty ()) { return clone (); + } else if (other.empty ()) { + + // NOTE: we do not use "EmptyEdges" as we want to maintain + return new DeepEdges (deep_layer ().derived ()); + } else if (! other_deep) { return AsIfFlatEdges::intersections (other); } else { - return new DeepEdges (and_or_not_with (other_deep, EdgeIntersections)); + db::DeepEdges *res = new DeepEdges (and_or_not_with (other_deep, EdgeIntersections).first); + // this is to preserve dots in later steps + res->set_merged_semantics (false); + return res; } } @@ -999,7 +1016,7 @@ EdgesDelegate *DeepEdges::and_with (const Edges &other) const } else { - return new DeepEdges (and_or_not_with (other_deep, EdgeAnd)); + return new DeepEdges (and_or_not_with (other_deep, EdgeAnd).first); } } @@ -1018,7 +1035,7 @@ EdgesDelegate *DeepEdges::not_with (const Edges &other) const } else { - return new DeepEdges (and_or_not_with (other_deep, EdgeNot)); + return new DeepEdges (and_or_not_with (other_deep, EdgeNot).first); } } @@ -1094,7 +1111,7 @@ EdgesDelegate *DeepEdges::not_with (const Region &other) const std::pair DeepEdges::andnot_with (const Edges &other) const { - const DeepRegion *other_deep = dynamic_cast (other.delegate ()); + const DeepEdges *other_deep = dynamic_cast (other.delegate ()); if (empty ()) { @@ -1111,7 +1128,7 @@ DeepEdges::andnot_with (const Edges &other) const } else { - auto res = edge_region_op (other_deep, EdgePolygonOp::Both, true /*include borders*/); + auto res = and_or_not_with (other_deep, EdgeAndNot); return std::make_pair (new DeepEdges (res.first), new DeepEdges (res.second)); } @@ -1137,8 +1154,8 @@ EdgesDelegate *DeepEdges::xor_with (const Edges &other) const // Implement XOR as (A-B)+(B-A) - only this implementation // is compatible with the local processor scheme - DeepLayer n1 (and_or_not_with (other_deep, EdgeNot)); - DeepLayer n2 (other_deep->and_or_not_with (this, EdgeNot)); + DeepLayer n1 (and_or_not_with (other_deep, EdgeNot).first); + DeepLayer n2 (other_deep->and_or_not_with (this, EdgeNot).first); n1.add_from (n2); return new DeepEdges (n1); diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 7309f93da..ac91001e5 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -188,7 +188,7 @@ private: void init (); void ensure_merged_edges_valid () const; - DeepLayer and_or_not_with(const DeepEdges *other, EdgeBoolOp op) const; + std::pair and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const; std::pair edge_region_op (const DeepRegion *other, EdgePolygonOp::mode_t op, bool include_borders) const; EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const db::EdgesCheckOptions &options) const; virtual EdgesDelegate *pull_generic (const Edges &edges) const; diff --git a/src/db/db/dbEdgesLocalOperations.cc b/src/db/db/dbEdgesLocalOperations.cc index a27183282..3572b131c 100644 --- a/src/db/db/dbEdgesLocalOperations.cc +++ b/src/db/db/dbEdgesLocalOperations.cc @@ -94,6 +94,9 @@ EdgeBoolAndOrNotLocalOperation::do_compute_local (db::Layout * /*layout*/, db::C if (! is_and) { result.insert (subject); } + if (result2) { + result2->insert (subject); + } } else { scanner.insert (&subject, 0); any_subject = true; diff --git a/src/db/unit_tests/dbDeepEdgesTests.cc b/src/db/unit_tests/dbDeepEdgesTests.cc index dfa2c7bad..f214f42a4 100644 --- a/src/db/unit_tests/dbDeepEdgesTests.cc +++ b/src/db/unit_tests/dbDeepEdgesTests.cc @@ -146,6 +146,7 @@ TEST(3_Edge2EdgeBooleans) 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), dss); db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); @@ -153,7 +154,11 @@ TEST(3_Edge2EdgeBooleans) 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), dss); + 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)); @@ -162,11 +167,58 @@ TEST(3_Edge2EdgeBooleans) 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 - 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)); + 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.gds"); diff --git a/testdata/algo/deep_edges_au3.gds b/testdata/algo/deep_edges_au3.gds index 4bb15fdec..b6d89fd5e 100644 Binary files a/testdata/algo/deep_edges_au3.gds and b/testdata/algo/deep_edges_au3.gds differ