diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index f38d94228..8d1abf149 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -1550,13 +1550,6 @@ DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const return res.release (); } -RegionDelegate * -DeepRegion::in (const Region &other, bool invert) const -{ - // TODO: this can be optimized maybe ... - return db::AsIfFlatRegion::in (other, invert); -} - template static Output *region_cop_impl (DeepRegion *region, db::CompoundRegionOperationNode &node) @@ -1796,6 +1789,43 @@ 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 +{ + std::unique_ptr dr_holder; + const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); + if (! other_deep) { + // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization + dr_holder.reset (new db::DeepRegion (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &polygons = merged_deep_layer (); + const db::DeepLayer &other_polygons = other_deep->merged_deep_layer (); + + db::ContainedLocalOperation op (output_mode); + + db::local_processor proc (const_cast (&polygons.layout ()), const_cast (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ()); + proc.set_description (progress_desc ()); + proc.set_report_progress (report_progress ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (polygons.store ()->threads ()); + + InteractingResultHolder orh (output_mode, merged_semantics (), polygons); + + proc.run (&op, polygons.layer (), other_polygons.layer (), orh.layers ()); + + return orh.result_pair (); +} + std::pair DeepRegion::selected_interacting_generic (const Region &other, int mode, bool touching, InteractingOutputMode output_mode, size_t min_count, size_t max_count) const { diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 75ea1961d..aec863284 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -155,6 +155,7 @@ 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; diff --git a/src/db/db/dbRegionLocalOperations.cc b/src/db/db/dbRegionLocalOperations.cc index d6aa19b9e..9f42af6c6 100644 --- a/src/db/db/dbRegionLocalOperations.cc +++ b/src/db/db/dbRegionLocalOperations.cc @@ -915,6 +915,83 @@ template class DB_PUBLIC interacting_local_operation +contained_local_operation::contained_local_operation (InteractingOutputMode output_mode) + : m_output_mode (output_mode) +{ + // .. nothing yet .. +} + +template +db::Coord contained_local_operation::dist () const +{ + return 0; +} + +template +void contained_local_operation::do_compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const +{ + if (m_output_mode == None) { + return; + } else if (m_output_mode == Positive || m_output_mode == Negative) { + tl_assert (results.size () == 1); + } else { + tl_assert (results.size () == 2); + } + + db::EdgeProcessor ep; + ep.set_base_verbosity (50); + + std::set others; + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (typename shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j).second); + } + } + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const TS &subject = interactions.subject_shape (i->first); + if (others.find (subject) != others.end ()) { + if (m_output_mode == Positive || m_output_mode == PositiveAndNegative) { + results [0].insert (subject); + } + } else { + if (m_output_mode == Negative) { + results [0].insert (subject); + } else if (m_output_mode == PositiveAndNegative) { + results [1].insert (subject); + } + } + } +} + +template +OnEmptyIntruderHint +contained_local_operation::on_empty_intruder_hint () const +{ + if (m_output_mode == Positive) { + return OnEmptyIntruderHint::Drop; + } else if (m_output_mode == Negative) { + return OnEmptyIntruderHint::Copy; + } else if (m_output_mode == PositiveAndNegative) { + return OnEmptyIntruderHint::CopyToSecond; + } else { + return OnEmptyIntruderHint::Ignore; + } +} + +template +std::string contained_local_operation::description () const +{ + return tl::to_string (tr ("Select polygons contained in other region")); +} + +// explicit instantiations +template class DB_PUBLIC contained_local_operation; +template class DB_PUBLIC contained_local_operation; + +// --------------------------------------------------------------------------------------------------------------- + template pull_local_operation::pull_local_operation (int mode, bool touching) : m_mode (mode), m_touching (touching) diff --git a/src/db/db/dbRegionLocalOperations.h b/src/db/db/dbRegionLocalOperations.h index 6d81c2b0d..7a457e413 100644 --- a/src/db/db/dbRegionLocalOperations.h +++ b/src/db/db/dbRegionLocalOperations.h @@ -351,6 +351,24 @@ public: typedef pull_with_text_local_operation PullWithTextLocalOperation; +template +class contained_local_operation + : public local_operation +{ +public: + contained_local_operation (InteractingOutputMode output_mode); + + virtual db::Coord dist () const; + virtual void do_compute_local (db::Layout * /*layout*/, const shape_interactions &interactions, std::vector > &results, size_t /*max_vertex_count*/, double /*area_ratio*/) const; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; + +private: + InteractingOutputMode m_output_mode; +}; + +typedef contained_local_operation ContainedLocalOperation; + } // namespace db #endif diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index fb1dfffbc..052a2ccea 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -2018,6 +2018,55 @@ TEST(30c_interact_with_count_text) EXPECT_EQ (r.selected_not_interacting (rr, 3, 4).to_string (), "(0,0;0,200;100,200;100,0)"); } +TEST(31_in) +{ + 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)); + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), 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 (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 (20, 0)), r2r.in (r1)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (21, 0)), r2r.in (r1, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (30, 0)), r2.in (r1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (31, 0)), r2.in (r1r, true)); + + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (40, 0)), r2r.in (r1r)); + target.insert (target_top_cell_index, target.get_layer (db::LayerProperties (41, 0)), r2r.in (r1r, true)); + + CHECKPOINT(); + db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_region_au31.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/testdata/algo/deep_region_au31.gds b/testdata/algo/deep_region_au31.gds new file mode 100644 index 000000000..f079981bf Binary files /dev/null and b/testdata/algo/deep_region_au31.gds differ diff --git a/testdata/algo/deep_region_l31.gds b/testdata/algo/deep_region_l31.gds new file mode 100644 index 000000000..1c6661453 Binary files /dev/null and b/testdata/algo/deep_region_l31.gds differ