From 0304930136abd3d3679d19cac18cc1a8ef931d89 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 14:53:30 +0100 Subject: [PATCH] WIP: introducing Region#in_and_out and Edges#in_and_out, support for hierachical Edges#in, Tests updated --- src/db/db/dbAsIfFlatEdges.cc | 22 ++++++++ src/db/db/dbAsIfFlatEdges.h | 1 + src/db/db/dbAsIfFlatRegion.cc | 69 ++++++++++++++++++------- src/db/db/dbAsIfFlatRegion.h | 11 +++- src/db/db/dbDeepEdges.cc | 59 ++++++++++++++++++++- src/db/db/dbDeepEdges.h | 1 + src/db/db/dbDeepRegion.cc | 10 +--- src/db/db/dbDeepRegion.h | 4 +- src/db/db/dbEdges.h | 13 +++++ src/db/db/dbEdgesDelegate.h | 1 + src/db/db/dbEmptyEdges.h | 1 + src/db/db/dbEmptyRegion.h | 1 + src/db/db/dbRegion.h | 13 +++++ src/db/db/dbRegionDelegate.h | 1 + src/db/db/dbRegionLocalOperations.cc | 1 + src/db/db/dbRegionLocalOperations.h | 2 + src/db/unit_tests/dbDeepRegionTests.cc | 62 +++++++++++++++++++++- src/db/unit_tests/dbRegionTests.cc | 10 ++++ testdata/algo/deep_region_au31.gds | Bin 7298 -> 8522 bytes 19 files changed, 247 insertions(+), 35 deletions(-) diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index e42d5c29b..fc505a457 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -530,6 +530,28 @@ AsIfFlatEdges::in (const Edges &other, bool invert) const return new_region.release (); } +std::pair +AsIfFlatEdges::in_and_out (const Edges &other) const +{ + std::set op; + for (EdgesIterator o (other.begin_merged ()); ! o.at_end (); ++o) { + op.insert (*o); + } + + std::unique_ptr in (new FlatEdges (false)); + std::unique_ptr out (new FlatEdges (false)); + + for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (op.find (*o) != op.end ()) { + in->insert (*o); + } else { + out->insert (*o); + } + } + + return std::make_pair (in.release (), out.release ()); +} + size_t AsIfFlatEdges::count () const { diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index 785b0a677..4a15a91a4 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -204,6 +204,7 @@ public: virtual std::pair selected_inside_pair (const Region &other) const; virtual EdgesDelegate *in (const Edges &, bool) const; + virtual std::pair in_and_out (const Edges &) const; virtual bool equals (const Edges &other) const; virtual bool less (const Edges &other) const; diff --git a/src/db/db/dbAsIfFlatRegion.cc b/src/db/db/dbAsIfFlatRegion.cc index e0bb9dd4e..c0a2896bc 100644 --- a/src/db/db/dbAsIfFlatRegion.cc +++ b/src/db/db/dbAsIfFlatRegion.cc @@ -148,25 +148,6 @@ AsIfFlatRegion::edges (const EdgeFilterBase *filter) const return result.release (); } -RegionDelegate * -AsIfFlatRegion::in (const Region &other, bool invert) const -{ - std::set op; - for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) { - op.insert (*o); - } - - std::unique_ptr new_region (new FlatRegion (false)); - - for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) { - if ((op.find (*o) == op.end ()) == invert) { - new_region->insert (*o); - } - } - - return new_region.release (); -} - bool AsIfFlatRegion::is_box () const { @@ -400,6 +381,56 @@ private: } +std::pair +AsIfFlatRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const +{ + OutputPairHolder oph (output_mode, merged_semantics ()); + + if (output_mode == None) { + return oph.region_pair (); + } + + // shortcut + if (empty ()) { + if (output_mode == Positive || output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (clone (), clone ()); + } + } else if (other.empty ()) { + if (output_mode == Positive) { + return std::make_pair (new EmptyRegion (), (RegionDelegate *) 0); + } else if (output_mode == Negative) { + return std::make_pair (clone (), (RegionDelegate *) 0); + } else { + return std::make_pair (new EmptyRegion (), clone ()); + } + } + + std::set op; + for (RegionIterator o (other.begin_merged ()); ! o.at_end (); ++o) { + op.insert (*o); + } + + std::unique_ptr new_region (new FlatRegion (false)); + + for (RegionIterator o (begin_merged ()); ! o.at_end (); ++o) { + if (op.find (*o) != op.end ()) { + if (output_mode == Positive || output_mode == PositiveAndNegative) { + oph.results () [0]->insert (*o); + } + } else { + if (output_mode == Negative) { + oph.results () [0]->insert (*o); + } else if (output_mode == PositiveAndNegative) { + oph.results () [1]->insert (*o); + } + } + } + + return oph.region_pair (); +} + std::pair AsIfFlatRegion::selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { diff --git a/src/db/db/dbAsIfFlatRegion.h b/src/db/db/dbAsIfFlatRegion.h index d6ec3366c..699431ce3 100644 --- a/src/db/db/dbAsIfFlatRegion.h +++ b/src/db/db/dbAsIfFlatRegion.h @@ -265,7 +265,15 @@ public: return pull_generic (other, 0, false); } - virtual RegionDelegate *in (const Region &other, bool invert) const; + virtual RegionDelegate *in (const Region &other, bool invert) const + { + return in_and_out_generic (other, invert ? Negative : Positive).first; + } + + virtual std::pair in_and_out (const Region &other) const + { + return in_and_out_generic (other, PositiveAndNegative); + } virtual bool equals (const Region &other) const; virtual bool less (const Region &other) const; @@ -284,6 +292,7 @@ protected: virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const; + virtual std::pair in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const; template static void produce_markers_for_grid_check (const db::Polygon &poly, const Trans &tr, db::Coord gx, db::Coord gy, db::Shapes &shapes); diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 93dd301d1..e3b40b063 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -34,6 +34,7 @@ #include "dbLayoutUtils.h" #include "dbLocalOperation.h" #include "dbLocalOperationUtils.h" +#include "dbRegionLocalOperations.h" // for db::ContainedEdgesLocalOperation #include "dbHierProcessor.h" #include "dbEmptyEdges.h" @@ -1741,8 +1742,62 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const { - // TODO: is there a cheaper way? - return AsIfFlatEdges::in (other, invert); + std::unique_ptr dr_holder; + const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &edges = merged_deep_layer (); + + DeepLayer dl_out (edges.derived ()); + + std::vector output_layers; + output_layers.reserve (1); + output_layers.push_back (dl_out.layer ()); + + db::ContainedEdgesLocalOperation op (invert ? Negative : Positive); + + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edges.store ()->threads ()); + + proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers); + + return new db::DeepEdges (dl_out); +} + +std::pair DeepEdges::in_and_out (const Edges &other) const +{ + std::unique_ptr dr_holder; + const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other edge collection isn't deep, turn into a top-level only deep edge collection to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &edges = merged_deep_layer (); + + DeepLayer dl_out (edges.derived ()); + DeepLayer dl_out2 (edges.derived ()); + + std::vector output_layers; + output_layers.reserve (2); + output_layers.push_back (dl_out.layer ()); + output_layers.push_back (dl_out2.layer ()); + + db::ContainedEdgesLocalOperation op (PositiveAndNegative); + + db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edges.store ()->threads ()); + + proc.run (&op, edges.layer (), other_deep->merged_deep_layer ().layer (), output_layers); + + return std::make_pair (new db::DeepEdges (dl_out), new db::DeepEdges (dl_out2)); } namespace diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 1bd84c16f..7fd8730aa 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -156,6 +156,7 @@ public: virtual RegionDelegate *extended (coord_type ext_b, coord_type ext_e, coord_type ext_o, coord_type ext_i, bool join) const; virtual EdgesDelegate *in (const Edges &, bool) const; + virtual std::pair in_and_out (const Edges &) const; virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index 8d1abf149..3aae6b595 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1789,16 +1789,8 @@ private: } -RegionDelegate * -DeepRegion::in (const Region &other, bool invert) const -{ - // TODO: we could offer in_and_not_it (both at once) - InteractingOutputMode output_mode = invert ? Negative : Positive; - return in_and_out (other, output_mode).first; -} - std::pair -DeepRegion::in_and_out (const Region &other, InteractingOutputMode output_mode) const +DeepRegion::in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const { std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index aec863284..e47cfae95 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -133,8 +133,6 @@ public: virtual RegionDelegate *sized (coord_type d, unsigned int mode) const; virtual RegionDelegate *sized (coord_type dx, coord_type dy, unsigned int mode) const; - virtual RegionDelegate *in (const Region &other, bool invert) const; - virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const; virtual DeepShapeCollectionDelegateBase *deep () @@ -155,10 +153,10 @@ protected: virtual std::pair selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; virtual std::pair selected_interacting_generic (const Edges &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; virtual std::pair selected_interacting_generic (const Texts &other, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const; - virtual std::pair in_and_out (const Region &other, InteractingOutputMode output_mode) const; virtual RegionDelegate *pull_generic (const Region &other, int mode, bool touching) const; virtual EdgesDelegate *pull_generic (const Edges &other) const; virtual TextsDelegate *pull_generic (const Texts &other) const; + virtual std::pair in_and_out_generic (const Region &other, InteractingOutputMode output_mode) const; private: friend class DeepEdges; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index 6f2114d41..1524581c8 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -1390,6 +1390,19 @@ public: return Edges (mp_delegate->in (other, invert)); } + /** + * @brief Returns all edges which are in the other edge set and which are not. + * + * This method is equivalent to calling in with invert = false and true, but more efficient. + * + * Merged semantics applies. + */ + std::pair in_and_out (const Edges &other) const + { + std::pair p = mp_delegate->in_and_out (other); + return std::pair (Edges (p.first), Edges (p.second)); + } + /** * @brief Returns the nth edge * diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 59a595f4b..db17aeda4 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -333,6 +333,7 @@ public: virtual std::pair selected_inside_pair (const Edges &other) const = 0; virtual EdgesDelegate *in (const Edges &other, bool invert) const = 0; + virtual std::pair in_and_out (const Edges &) const = 0; virtual const db::Edge *nth (size_t n) const = 0; virtual bool has_valid_edges () const = 0; diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 569eada56..4cefa2693 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -115,6 +115,7 @@ public: virtual std::pair selected_inside_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *in (const Edges &, bool) const { return new EmptyEdges (); } + virtual std::pair in_and_out (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual const db::Edge *nth (size_t) const { tl_assert (false); } virtual bool has_valid_edges () const { return true; } diff --git a/src/db/db/dbEmptyRegion.h b/src/db/db/dbEmptyRegion.h index e5537792d..60c5332d9 100644 --- a/src/db/db/dbEmptyRegion.h +++ b/src/db/db/dbEmptyRegion.h @@ -133,6 +133,7 @@ public: virtual TextsDelegate *pull_interacting (const Texts &) const { return new EmptyTexts (); } virtual RegionDelegate *pull_overlapping (const Region &) const { return new EmptyRegion (); } virtual RegionDelegate *in (const Region &, bool) const { return new EmptyRegion (); } + virtual std::pair in_and_out (const Region &) const { return std::make_pair (new EmptyRegion (), new EmptyRegion ()); } virtual bool has_valid_polygons () const { return true; } virtual bool has_valid_merged_polygons () const { return true; } diff --git a/src/db/db/dbRegion.h b/src/db/db/dbRegion.h index af8671d46..3030911e2 100644 --- a/src/db/db/dbRegion.h +++ b/src/db/db/dbRegion.h @@ -1602,6 +1602,19 @@ public: return Region (mp_delegate->in (other, invert)); } + /** + * @brief Returns all polygons which are in the other region plus the ones which are not + * + * This method is similar to calling in with inverse = false and true, but more efficient. + * + * Merged semantics applies. + */ + std::pair in_and_out (const Region &other) const + { + std::pair p = mp_delegate->in_and_out (other); + return std::pair (Region (p.first), Region (p.second)); + } + /** * @brief Round corners (in-place) * diff --git a/src/db/db/dbRegionDelegate.h b/src/db/db/dbRegionDelegate.h index 985ba48e1..e94737cad 100644 --- a/src/db/db/dbRegionDelegate.h +++ b/src/db/db/dbRegionDelegate.h @@ -308,6 +308,7 @@ public: virtual RegionDelegate *pull_overlapping (const Region &other) const = 0; virtual TextsDelegate *pull_interacting (const Texts &other) const = 0; virtual RegionDelegate *in (const Region &other, bool invert) const = 0; + virtual std::pair in_and_out (const Region &other) const = 0; virtual const db::Polygon *nth (size_t n) const = 0; virtual bool has_valid_polygons () const = 0; diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index 33fe39dd6..501d534f5 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -986,6 +986,7 @@ std::string contained_local_operation::description () const // explicit instantiations template class DB_PUBLIC contained_local_operation; template class DB_PUBLIC contained_local_operation; +template class DB_PUBLIC contained_local_operation; // --------------------------------------------------------------------------------------------------------------- diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 7a457e413..102076b79 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -368,6 +368,8 @@ private: }; typedef contained_local_operation ContainedLocalOperation; +// the implementation is type-agnostic and can be used for edges too +typedef contained_local_operation ContainedEdgesLocalOperation; } // namespace db diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index 052a2ccea..dfff18bf6 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2036,10 +2036,11 @@ TEST(31_in) unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); - unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); db::Region r1r = r1; r1r.set_merged_semantics (false); db::Region r2r = r2; @@ -2053,6 +2054,10 @@ TEST(31_in) target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (10, 0)), r2.in (r1)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in (r1, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in (r3, false)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in (r3, true)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in (r1, false)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in (r1, true)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in (r1)); target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true)); @@ -2067,6 +2072,61 @@ TEST(31_in) db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); } +TEST(31_in_and_out) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/deep_region_l31.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); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0)); // empty + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + db::Region r3 (db::RecursiveShapeIterator (ly, top_cell, l3), dss); + + db::Region r1r = r1; + r1r.set_merged_semantics (false); + db::Region r2r = r2; + r2r.set_merged_semantics (false); + + 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 (1, 0)), r1); + 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 (10, 0)), r2.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (11, 0)), r2.in_and_out (r1).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (12, 0)), r2.in_and_out (r3).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (13, 0)), r2.in_and_out (r3).second); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (14, 0)), r3.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (15, 0)), r3.in_and_out (r1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (20, 0)), r2r.in_and_out (r1).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in_and_out (r1).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in_and_out (r1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in_and_out (r1r).second); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in_and_out (r1r).first); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in_and_out (r1r).second); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/src/db/unit_tests/dbRegionTests.cc b/src/db/unit_tests/dbRegionTests.cc index adb905dc1..c29654f1c 100644 --- a/src/db/unit_tests/dbRegionTests.cc +++ b/src/db/unit_tests/dbRegionTests.cc @@ -1095,15 +1095,25 @@ TEST(19) r2.insert (db::Box (db::Point (0, 0), db::Point (20, 30))); EXPECT_EQ (r1.in (r2, false).to_string (), "(0,0;0,30;20,30;20,0)"); + EXPECT_EQ (r1.in_and_out (r2).first.to_string (), "(0,0;0,30;20,30;20,0)"); EXPECT_EQ (r1.in (r2, true).to_string (), ""); + EXPECT_EQ (r1.in (r1, false).to_string (), "(0,0;0,30;20,30;20,0)"); + EXPECT_EQ (r1.in (r1, true).to_string (), ""); + EXPECT_EQ (r1.in_and_out (r2).second.to_string (), ""); EXPECT_EQ (r2.in (r1, true).to_string (), ""); r1.set_merged_semantics (false); r2.set_merged_semantics (false); EXPECT_EQ (db::compare (r1.in (r2, false), "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); + EXPECT_EQ (db::compare (r1.in_and_out (r2).first, "(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); EXPECT_EQ (r1.in (r2, true).to_string (), "(0,0;0,20;10,20;10,0)"); + EXPECT_EQ (r1.in_and_out (r2).second.to_string (), "(0,0;0,20;10,20;10,0)"); EXPECT_EQ (r2.in (r1, true).to_string (), "(0,0;0,10;20,10;20,0)"); + EXPECT_EQ (r1.in (db::Region (), false).to_string (), ""); + EXPECT_EQ (db::compare (r1.in (db::Region (), true), "(0,0;0,20;10,20;10,0);(0,0;0,20;20,20;20,0);(0,0;0,30;20,30;20,0)"), true); + EXPECT_EQ (db::Region ().in (r1, false).to_string (), ""); + EXPECT_EQ (db::Region ().in (r1, true).to_string (), ""); } TEST(20) diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds index 4ff450d2f99e19b09ad2494ce62b2b1be6cdc473..786700549f5b3184698a2217c14080913edb63ff 100644 GIT binary patch delta 223 zcmZp&JmsXsz{bGD6u}_F$i)7Pftx{^fsetMK>(ROQAu48LvUl%c_v2QiCO-Pypy>Y z?Saf)Af^|Hx%m}SDhsBT%?a$^S%7K+xPfXW7qGhn$qQT{wg9*N=5U^Q%vkiW3BE?qp