From 1e323a0421d86704df16b9990742cf0796dce0c2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 1 Mar 2024 23:32:22 +0100 Subject: [PATCH] WIP --- src/db/db/dbAsIfFlatEdges.cc | 274 ++++++++++---------- src/db/db/dbAsIfFlatEdges.h | 20 +- src/db/db/dbDeepEdges.cc | 370 +--------------------------- src/db/db/dbDeepEdges.h | 8 +- src/db/db/dbEdges.h | 40 +-- src/db/db/dbEdgesDelegate.h | 12 +- src/db/db/dbEdgesLocalOperations.cc | 352 ++++++++++++++++++++++++++ src/db/db/dbEdgesLocalOperations.h | 74 ++++++ src/db/db/dbEmptyEdges.h | 12 +- src/db/db/gsiDeclDbEdges.cc | 92 +++++-- 10 files changed, 681 insertions(+), 573 deletions(-) diff --git a/src/db/db/dbAsIfFlatEdges.cc b/src/db/db/dbAsIfFlatEdges.cc index e4a482fe2..d48fbb0c3 100644 --- a/src/db/db/dbAsIfFlatEdges.cc +++ b/src/db/db/dbAsIfFlatEdges.cc @@ -28,6 +28,7 @@ #include "dbEmptyEdges.h" #include "dbEdges.h" #include "dbEdgesUtils.h" +#include "dbEdgesLocalOperations.h" #include "dbEdgeBoolean.h" #include "dbBoxConvert.h" #include "dbRegion.h" @@ -39,6 +40,7 @@ #include "dbPolygonGenerators.h" #include "dbPolygon.h" #include "dbPath.h" +#include "dbHierProcessor.h" #include @@ -94,104 +96,107 @@ AsIfFlatEdges::to_string (size_t nmax) const return os.str (); } -EdgesDelegate * -AsIfFlatEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse) const +namespace { + +class OutputPairHolder { - // shortcuts - if (other.empty () || empty ()) { - return ((mode == EdgesOutside) == inverse) ? new EmptyEdges () : clone (); - } +public: + OutputPairHolder (int inverse, bool merged_semantics) + { + m_e1.reset (new FlatEdges (merged_semantics)); + m_results.push_back (& m_e1->raw_edges ()); - db::box_scanner2 scanner (report_progress (), progress_desc ()); - - AddressableEdgeDelivery e (begin_merged ()); - - for ( ; ! e.at_end (); ++e) { - scanner.insert1 (e.operator-> (), 0); - } - - AddressablePolygonDelivery p = (mode == EdgesInside ? other.addressable_merged_polygons () : other.addressable_polygons ()); - - for ( ; ! p.at_end (); ++p) { - scanner.insert2 (p.operator-> (), 1); - } - - std::unique_ptr output (new FlatEdges (true)); - - if (! inverse) { - - edge_to_region_interaction_filter filter (output.get (), mode); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - } else { - - std::set result; - edge_to_region_interaction_filter > filter (&result, mode); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (result.find (*o) == result.end ()) { - output->insert (*o); - } + if (inverse == 0) { + m_e2.reset (new FlatEdges (merged_semantics)); + m_results.push_back (& m_e2->raw_edges ()); } - } - return output.release (); + std::pair region_pair () + { + return std::make_pair (m_e1.release (), m_e2.release ()); + } + + const std::vector &results () { return m_results; } + +private: + std::unique_ptr m_e1, m_e2; + std::vector m_results; +}; + } EdgesDelegate * -AsIfFlatEdges::selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const +AsIfFlatEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const { + min_count = std::max (size_t (1), min_count); + // shortcuts - if (edges.empty () || empty ()) { + if (max_count < min_count || other.empty () || empty ()) { return ((mode == EdgesOutside) == inverse) ? new EmptyEdges () : clone (); } - db::box_scanner scanner (report_progress (), progress_desc ()); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ()); - AddressableEdgeDelivery e (begin_merged ()); + db::EdgesIterator edges (begin_merged ()); - for ( ; ! e.at_end (); ++e) { - scanner.insert (e.operator-> (), 0); + db::edge_to_polygon_interacting_local_operation op (mode, inverse ? db::edge_to_polygon_interacting_local_operation::Inverse : db::edge_to_polygon_interacting_local_operation::Normal); + + db::local_processor proc; + proc.set_base_verbosity (base_verbosity ()); + proc.set_description (progress_desc ()); + proc.set_report_progress (report_progress ()); + + std::vector > others; + // NOTE: with counting the other region needs to be merged + others.push_back (counting ? other.begin_merged () : other.begin ()); + + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); + + return oph.region_pair ().first; +} + +EdgesDelegate * +AsIfFlatEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const +{ + min_count = std::max (size_t (1), min_count); + + // @@@ + // shortcuts + if (max_count < min_count || other.empty () || empty ()) { + return ((mode == EdgesOutside) == inverse) ? new EmptyEdges () : clone (); } - // NOTE: "inside" needs merged edges for the other edges as the algorithm works edge by edge - AddressableEdgeDelivery ee = (mode == EdgesInside ? edges.addressable_merged_edges () : edges.addressable_edges ()); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ()); - for ( ; ! ee.at_end (); ++ee) { - scanner.insert (ee.operator-> (), 1); - } + db::EdgesIterator edges (begin_merged ()); - std::unique_ptr output (new FlatEdges (true)); + db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal); - if (! inverse) { + db::local_processor proc; + proc.set_base_verbosity (base_verbosity ()); + proc.set_description (progress_desc ()); + proc.set_report_progress (report_progress ()); - edge_interaction_filter filter (*output, mode); - scanner.process (filter, 1, db::box_convert ()); + std::vector > others; + // NOTE: with counting the other edge collection needs to be merged + others.push_back (counting ? other.begin_merged () : other.begin ()); - } else { + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); - std::set result; - edge_interaction_filter > filter (result, mode); - scanner.process (filter, 1, db::box_convert ()); - - for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (result.find (*o) == result.end ()) { - output->insert (*o); - } - } - - } - - return output.release (); + return oph.region_pair ().first; } std::pair -AsIfFlatEdges::selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const +AsIfFlatEdges::selected_interacting_pair_generic (const Region &other, EdgeInteractionMode mode, size_t min_count, size_t max_count) const { + min_count = std::max (size_t (1), min_count); + + // @@@ // shortcuts - if (region.empty () || empty ()) { + if (max_count < min_count || other.empty () || empty ()) { if (mode != EdgesOutside) { return std::make_pair (new EmptyEdges (), clone ()); } else { @@ -199,43 +204,35 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Region ®ion, EdgeInte } } - db::box_scanner2 scanner (report_progress (), progress_desc ()); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (0, merged_semantics () || is_merged ()); - AddressableEdgeDelivery e (begin_merged ()); + db::EdgesIterator edges (begin_merged ()); - for ( ; ! e.at_end (); ++e) { - scanner.insert1 (e.operator-> (), 0); - } + db::edge_to_polygon_interacting_local_operation op (mode, db::edge_to_polygon_interacting_local_operation::Both); - AddressablePolygonDelivery p = region.addressable_merged_polygons (); + db::local_processor proc; + proc.set_base_verbosity (base_verbosity ()); + proc.set_description (progress_desc ()); + proc.set_report_progress (report_progress ()); - for ( ; ! p.at_end (); ++p) { - scanner.insert2 (p.operator-> (), 1); - } + std::vector > others; + // NOTE: with counting the other region needs to be merged + others.push_back (counting ? other.begin_merged () : other.begin ()); - std::unique_ptr output (new FlatEdges (true)); - std::unique_ptr output2 (new FlatEdges (true)); + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); - std::set result; - edge_to_region_interaction_filter > filter (&result, mode); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (result.find (*o) == result.end ()) { - output2->insert (*o); - } else { - output->insert (*o); - } - } - - return std::make_pair (output.release (), output2.release ()); + return oph.region_pair (); } std::pair -AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractionMode mode) const +AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractionMode mode, size_t min_count, size_t max_count) const { + min_count = std::max (size_t (1), min_count); + + // @@@ // shortcuts - if (other.empty () || empty ()) { + if (max_count < min_count || other.empty () || empty ()) { if (mode != EdgesOutside) { return std::make_pair (new EmptyEdges (), clone ()); } else { @@ -243,36 +240,25 @@ AsIfFlatEdges::selected_interacting_pair_generic (const Edges &other, EdgeIntera } } - db::box_scanner scanner (report_progress (), progress_desc ()); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (0, merged_semantics () || is_merged ()); - AddressableEdgeDelivery e (begin_merged ()); + db::EdgesIterator edges (begin_merged ()); - for ( ; ! e.at_end (); ++e) { - scanner.insert (e.operator-> (), 0); - } + db::Edge2EdgeInteractingLocalOperation op (mode, db::Edge2EdgeInteractingLocalOperation::Both); - AddressableEdgeDelivery ee = other.addressable_merged_edges (); + db::local_processor proc; + proc.set_base_verbosity (base_verbosity ()); + proc.set_description (progress_desc ()); + proc.set_report_progress (report_progress ()); - for ( ; ! ee.at_end (); ++ee) { - scanner.insert (ee.operator-> (), 1); - } + std::vector > others; + // NOTE: with counting the other edge collection needs to be merged + others.push_back (counting ? other.begin_merged () : other.begin ()); - std::unique_ptr output (new FlatEdges (true)); - std::unique_ptr output2 (new FlatEdges (true)); + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); - std::set results; - edge_interaction_filter > filter (results, mode); - scanner.process (filter, 1, db::box_convert ()); - - for (EdgesIterator o (begin_merged ()); ! o.at_end (); ++o) { - if (results.find (*o) == results.end ()) { - output2->insert (*o); - } else { - output->insert (*o); - } - } - - return std::make_pair (output.release (), output2.release ()); + return oph.region_pair (); } @@ -343,111 +329,111 @@ AsIfFlatEdges::pull_interacting (const Region &other) const } EdgesDelegate * -AsIfFlatEdges::selected_interacting (const Edges &other) const +AsIfFlatEdges::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, EdgesInteract, false); + return selected_interacting_generic (other, EdgesInteract, false, min_count, max_count); } EdgesDelegate * -AsIfFlatEdges::selected_not_interacting (const Edges &other) const +AsIfFlatEdges::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, EdgesInteract, true); + return selected_interacting_generic (other, EdgesInteract, true, min_count, max_count); } EdgesDelegate * -AsIfFlatEdges::selected_interacting (const Region &other) const +AsIfFlatEdges::selected_interacting (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, EdgesInteract, false); + return selected_interacting_generic (other, EdgesInteract, false, min_count, max_count); } EdgesDelegate * -AsIfFlatEdges::selected_not_interacting (const Region &other) const +AsIfFlatEdges::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_generic (other, EdgesInteract, true); + return selected_interacting_generic (other, EdgesInteract, true, min_count, max_count); } std::pair -AsIfFlatEdges::selected_interacting_pair (const Region &other) const +AsIfFlatEdges::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const { - return selected_interacting_pair_generic (other, EdgesInteract); + return selected_interacting_pair_generic (other, EdgesInteract, min_count, max_count); } std::pair -AsIfFlatEdges::selected_interacting_pair (const Edges &other) const +AsIfFlatEdges::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const { - return selected_interacting_pair_generic (other, EdgesInteract); + return selected_interacting_pair_generic (other, EdgesInteract, min_count, max_count); } EdgesDelegate * AsIfFlatEdges::selected_outside (const Region &other) const { - return selected_interacting_generic (other, EdgesOutside, false); + return selected_interacting_generic (other, EdgesOutside, false, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_not_outside (const Region &other) const { - return selected_interacting_generic (other, EdgesOutside, true); + return selected_interacting_generic (other, EdgesOutside, true, size_t (0), std::numeric_limits::max ()); } std::pair AsIfFlatEdges::selected_outside_pair (const Region &other) const { - return selected_interacting_pair_generic (other, EdgesOutside); + return selected_interacting_pair_generic (other, EdgesOutside, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_inside (const Region &other) const { - return selected_interacting_generic (other, EdgesInside, false); + return selected_interacting_generic (other, EdgesInside, false, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_not_inside (const Region &other) const { - return selected_interacting_generic (other, EdgesInside, true); + return selected_interacting_generic (other, EdgesInside, true, size_t (0), std::numeric_limits::max ()); } std::pair AsIfFlatEdges::selected_inside_pair (const Region &other) const { - return selected_interacting_pair_generic (other, EdgesInside); + return selected_interacting_pair_generic (other, EdgesInside, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_outside (const Edges &other) const { - return selected_interacting_generic (other, EdgesOutside, false); + return selected_interacting_generic (other, EdgesOutside, false, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_not_outside (const Edges &other) const { - return selected_interacting_generic (other, EdgesOutside, true); + return selected_interacting_generic (other, EdgesOutside, true, size_t (0), std::numeric_limits::max ()); } std::pair AsIfFlatEdges::selected_outside_pair (const Edges &other) const { - return selected_interacting_pair_generic (other, EdgesOutside); + return selected_interacting_pair_generic (other, EdgesOutside, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_inside (const Edges &other) const { - return selected_interacting_generic (other, EdgesInside, false); + return selected_interacting_generic (other, EdgesInside, false, size_t (0), std::numeric_limits::max ()); } EdgesDelegate * AsIfFlatEdges::selected_not_inside (const Edges &other) const { - return selected_interacting_generic (other, EdgesInside, true); + return selected_interacting_generic (other, EdgesInside, true, size_t (0), std::numeric_limits::max ()); } std::pair AsIfFlatEdges::selected_inside_pair (const Edges &other) const { - return selected_interacting_pair_generic (other, EdgesInside); + return selected_interacting_pair_generic (other, EdgesInside, size_t (0), std::numeric_limits::max ()); } diff --git a/src/db/db/dbAsIfFlatEdges.h b/src/db/db/dbAsIfFlatEdges.h index b1f9a07d4..fbdd7064e 100644 --- a/src/db/db/dbAsIfFlatEdges.h +++ b/src/db/db/dbAsIfFlatEdges.h @@ -183,12 +183,12 @@ public: virtual EdgesDelegate *pull_interacting (const Edges &) const; virtual RegionDelegate *pull_interacting (const Region &) const; - virtual EdgesDelegate *selected_interacting (const Edges &) const; - virtual EdgesDelegate *selected_not_interacting (const Edges &) const; - virtual EdgesDelegate *selected_interacting (const Region &) const; - virtual EdgesDelegate *selected_not_interacting (const Region &) const; - virtual std::pair selected_interacting_pair (const Region &other) const; - virtual std::pair selected_interacting_pair (const Edges &other) const; + virtual EdgesDelegate *selected_interacting (const Edges &, size_t min_count, size_t max_count) const; + virtual EdgesDelegate *selected_not_interacting (const Edges &, size_t min_count, size_t max_count) const; + virtual EdgesDelegate *selected_interacting (const Region &, size_t min_count, size_t max_count) const; + virtual EdgesDelegate *selected_not_interacting (const Region &, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const; virtual EdgesDelegate *selected_outside (const Edges &other) const; virtual EdgesDelegate *selected_not_outside (const Edges &other) const; @@ -217,10 +217,10 @@ protected: EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const EdgesCheckOptions &options) const; virtual EdgesDelegate *pull_generic (const Edges &edges) const; virtual RegionDelegate *pull_generic (const Region ®ion) const; - virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const; - virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode) const; - virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse) const; - virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const; + virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; + virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; AsIfFlatEdges &operator= (const AsIfFlatEdges &other); AsIfFlatEdges (const AsIfFlatEdges &other); diff --git a/src/db/db/dbDeepEdges.cc b/src/db/db/dbDeepEdges.cc index 5a2812207..39d406d1b 100644 --- a/src/db/db/dbDeepEdges.cc +++ b/src/db/db/dbDeepEdges.cc @@ -1354,363 +1354,10 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t return res.release (); } -namespace -{ - -class Edge2EdgeInteractingLocalOperation - : public local_operation -{ -public: - enum output_mode_t { Normal, Inverse, Both }; - - Edge2EdgeInteractingLocalOperation (EdgeInteractionMode mode, output_mode_t output_mode) - : m_mode (mode), m_output_mode (output_mode) - { - // .. nothing yet .. - } - - virtual db::Coord dist () const - { - // touching is sufficient - return 1; - } - - virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const - { - tl_assert (results.size () == (m_output_mode == Both ? 2 : 1)); - - std::unordered_set &result = results.front (); - - std::unordered_set *result2 = 0; - if (m_output_mode == Both) { - result2 = &results[1]; - } - - db::box_scanner scanner; - - std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.intruder_shape (*j).second); - } - } - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Edge &subject = interactions.subject_shape (i->first); - scanner.insert (&subject, 0); - } - - for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { - scanner.insert (o.operator-> (), 1); - } - - if (m_output_mode == Inverse || m_output_mode == Both) { - - std::unordered_set interacting; - edge_interaction_filter > filter (interacting, m_mode); - scanner.process (filter, 1, db::box_convert ()); - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - - const db::Edge &subject = interactions.subject_shape (i->first); - if (interacting.find (subject) == interacting.end ()) { - if (m_output_mode != Both) { - result.insert (subject); - } else { - result2->insert (subject); - } - } else if (m_output_mode == Both) { - result.insert (subject); - } - - } - - } else { - - edge_interaction_filter > filter (result, m_mode); - scanner.process (filter, 1, db::box_convert ()); - - } - - } - - virtual OnEmptyIntruderHint on_empty_intruder_hint () const - { - if (m_mode == EdgesOutside) { - return m_output_mode == Both ? Copy : (m_output_mode == Inverse ? Drop : Copy); - } else { - return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop); - } - } - - virtual std::string description () const - { - return tl::to_string (tr ("Select interacting edges")); - } - -private: - EdgeInteractionMode m_mode; - output_mode_t m_output_mode; -}; - -class Edge2EdgePullLocalOperation - : public local_operation -{ -public: - Edge2EdgePullLocalOperation () - { - // .. nothing yet .. - } - - virtual db::Coord dist () const - { - // touching is sufficient - return 1; - } - - virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const - { - tl_assert (results.size () == 1); - std::unordered_set &result = results.front (); - - db::box_scanner scanner; - - std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.intruder_shape (*j).second); - } - } - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Edge &subject = interactions.subject_shape (i->first); - scanner.insert (&subject, 1); - } - - for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { - scanner.insert (o.operator-> (), 0); - } - - edge_interaction_filter > filter (result, EdgesInteract); - scanner.process (filter, 1, db::box_convert ()); - - } - - virtual OnEmptyIntruderHint on_empty_intruder_hint () const - { - return Drop; - } - - virtual std::string description () const - { - return tl::to_string (tr ("Select interacting edges from other")); - } -}; - -class Edge2PolygonInteractingLocalOperation - : public local_operation -{ -public: - enum output_mode_t { Normal, Inverse, Both }; - - Edge2PolygonInteractingLocalOperation (EdgeInteractionMode mode, output_mode_t output_mode) - : m_mode (mode), m_output_mode (output_mode) - { - // .. nothing yet .. - } - - virtual db::Coord dist () const - { - // touching is sufficient - return 1; - } - - virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const - { - tl_assert (results.size () == size_t (m_output_mode == Both ? 2 : 1)); - - std::unordered_set &result = results.front (); - - std::unordered_set *result2 = 0; - if (m_output_mode == Both) { - result2 = &results[1]; - } - - db::box_scanner2 scanner; - - std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.intruder_shape (*j).second); - } - } - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Edge &subject = interactions.subject_shape (i->first); - scanner.insert1 (&subject, 0); - } - - std::list heap; - for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { - heap.push_back (o->obj ().transformed (o->trans ())); - scanner.insert2 (& heap.back (), 1); - } - - if (m_output_mode == Inverse || m_output_mode == Both) { - - std::unordered_set interacting; - edge_to_region_interaction_filter > filter (&interacting, m_mode); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - - const db::Edge &subject = interactions.subject_shape (i->first); - - if (interacting.find (subject) == interacting.end ()) { - if (m_output_mode != Both) { - result.insert (subject); - } else { - result2->insert (subject); - } - } else if (m_output_mode == Both) { - result.insert (subject); - } - - } - - } else { - - edge_to_region_interaction_filter > filter (&result, m_mode); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - - } - } - - virtual OnEmptyIntruderHint on_empty_intruder_hint () const - { - if (m_mode == EdgesOutside) { - return m_output_mode == Both ? Copy : (m_output_mode == Inverse ? Drop : Copy); - } else { - return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop); - } - } - - virtual std::string description () const - { - if (m_mode == EdgesInteract) { - if (m_output_mode == Inverse) { - return tl::to_string (tr ("Select non-interacting edges")); - } else if (m_output_mode == Normal) { - return tl::to_string (tr ("Select interacting edges")); - } else { - return tl::to_string (tr ("Select interacting and non-interacting edges")); - } - } else if (m_mode == EdgesInside) { - if (m_output_mode == Inverse) { - return tl::to_string (tr ("Select non-inside edges")); - } else if (m_output_mode == Normal) { - return tl::to_string (tr ("Select inside edges")); - } else { - return tl::to_string (tr ("Select inside and non-inside edges")); - } - } else if (m_mode == EdgesOutside) { - if (m_output_mode == Inverse) { - return tl::to_string (tr ("Select non-outside edges")); - } else if (m_output_mode == Normal) { - return tl::to_string (tr ("Select outside edges")); - } else { - return tl::to_string (tr ("Select outside and non-outside edges")); - } - } - return std::string (); - } - -private: - EdgeInteractionMode m_mode; - output_mode_t m_output_mode; -}; - -struct ResultInserter -{ - typedef db::Polygon value_type; - - ResultInserter (db::Layout *layout, std::unordered_set &result) - : mp_layout (layout), mp_result (&result) - { - // .. nothing yet .. - } - - void insert (const db::Polygon &p) - { - (*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ())); - } - -private: - db::Layout *mp_layout; - std::unordered_set *mp_result; -}; - -class Edge2PolygonPullLocalOperation - : public local_operation -{ -public: - Edge2PolygonPullLocalOperation () - { - // .. nothing yet .. - } - - virtual db::Coord dist () const - { - // touching is sufficient - return 1; - } - - virtual void do_compute_local (db::Layout *layout, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const - { - tl_assert (results.size () == 1); - std::unordered_set &result = results.front (); - - db::box_scanner2 scanner; - - std::set others; - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { - others.insert (interactions.intruder_shape (*j).second); - } - } - - for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { - const db::Edge &subject = interactions.subject_shape (i->first); - scanner.insert1 (&subject, 1); - } - - std::list heap; - for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { - heap.push_back (o->obj ().transformed (o->trans ())); - scanner.insert2 (& heap.back (), 0); - } - - ResultInserter inserter (layout, result); - edge_to_region_interaction_filter filter (&inserter, EdgesInteract); - scanner.process (filter, 1, db::box_convert (), db::box_convert ()); - } - - virtual OnEmptyIntruderHint on_empty_intruder_hint () const - { - return Drop; - } - - virtual std::string description () const - { - return tl::to_string (tr ("Select interacting regions")); - } -}; - -} - EdgesDelegate * -DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse) const +DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const { + // @@@ std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -1723,7 +1370,7 @@ DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMod DeepLayer dl_out (edges.derived ()); - db::Edge2PolygonInteractingLocalOperation op (mode, inverse ? db::Edge2PolygonInteractingLocalOperation::Inverse : db::Edge2PolygonInteractingLocalOperation::Normal); + db::edge_to_polygon_interacting_local_operation op (mode, inverse ? db::edge_to_polygon_interacting_local_operation::Inverse : db::edge_to_polygon_interacting_local_operation::Normal); db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); proc.set_base_verbosity (base_verbosity ()); @@ -1735,8 +1382,9 @@ DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMod } std::pair -DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteractionMode mode) const +DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteractionMode mode, size_t min_count, size_t max_count) const { + // @@@ std::unique_ptr dr_holder; const db::DeepRegion *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -1755,7 +1403,7 @@ DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteracti output_layers.push_back (dl_out.layer ()); output_layers.push_back (dl_out2.layer ()); - db::Edge2PolygonInteractingLocalOperation op (mode, db::Edge2PolygonInteractingLocalOperation::Both); + db::edge_to_polygon_interacting_local_operation op (mode, db::edge_to_polygon_interacting_local_operation::Both); db::local_processor proc (const_cast (&edges.layout ()), const_cast (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); proc.set_base_verbosity (base_verbosity ()); @@ -1767,8 +1415,9 @@ DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteracti } EdgesDelegate * -DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode mode, bool inverse) const +DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const { + // @@@ std::unique_ptr dr_holder; const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { @@ -1793,8 +1442,9 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode } std::pair -DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractionMode mode) const +DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractionMode mode, size_t min_count, size_t max_count) const { + // @@@ std::unique_ptr dr_holder; const db::DeepEdges *other_deep = dynamic_cast (other.delegate ()); if (! other_deep) { diff --git a/src/db/db/dbDeepEdges.h b/src/db/db/dbDeepEdges.h index 0578d704b..7309f93da 100644 --- a/src/db/db/dbDeepEdges.h +++ b/src/db/db/dbDeepEdges.h @@ -193,10 +193,10 @@ private: 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; virtual RegionDelegate *pull_generic (const Region ®ion) const; - virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse) const; - virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode) const; - virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse) const; - virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode) const; + virtual EdgesDelegate *selected_interacting_generic (const Edges &edges, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Edges &edges, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; + virtual EdgesDelegate *selected_interacting_generic (const Region ®ion, EdgeInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Region ®ion, EdgeInteractionMode mode, size_t min_count, size_t max_count) const; DeepEdges *apply_filter (const EdgeFilterBase &filter) const; template OutputContainer *processed_impl (const edge_processor &filter) const; diff --git a/src/db/db/dbEdges.h b/src/db/db/dbEdges.h index e5317f20d..28decbbb6 100644 --- a/src/db/db/dbEdges.h +++ b/src/db/db/dbEdges.h @@ -991,9 +991,9 @@ public: * Merged semantics applies. If merged semantics is chosen, the connected edge parts will be * selected as a whole. */ - Edges &select_interacting (const Region &other) + Edges &select_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) { - set_delegate (mp_delegate->selected_interacting (other)); + set_delegate (mp_delegate->selected_interacting (other, min_count, max_count)); return *this; } @@ -1002,9 +1002,9 @@ public: * * This method is an out-of-place version of select_interacting. */ - Edges selected_interacting (const Region &other) const + Edges selected_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - return Edges (mp_delegate->selected_interacting (other)); + return Edges (mp_delegate->selected_interacting (other, min_count, max_count)); } /** @@ -1013,9 +1013,9 @@ public: * Merged semantics applies. If merged semantics is chosen, the connected edge parts will be * selected as a whole. */ - Edges &select_not_interacting (const Region &other) + Edges &select_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) { - set_delegate (mp_delegate->selected_not_interacting (other)); + set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count)); return *this; } @@ -1024,17 +1024,17 @@ public: * * This method is an out-of-place version of select_not_interacting. */ - Edges selected_not_interacting (const Region &other) const + Edges selected_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - return Edges (mp_delegate->selected_not_interacting (other)); + return Edges (mp_delegate->selected_not_interacting (other, min_count, max_count)); } /** * @brief Returns all edges of this edge set which do not overlap or touch with polygons from the region together with the ones that do not */ - std::pair selected_interacting_differential (const Region &other) const + std::pair selected_interacting_differential (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - std::pair p = mp_delegate->selected_interacting_pair (other); + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); return std::pair (Edges (p.first), Edges (p.second)); } @@ -1280,9 +1280,9 @@ public: * Merged semantics applies. If merged semantics is chosen, the connected edge parts will be * selected as a whole. */ - Edges &select_interacting (const Edges &other) + Edges &select_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) { - set_delegate (mp_delegate->selected_interacting (other)); + set_delegate (mp_delegate->selected_interacting (other, min_count, max_count)); return *this; } @@ -1291,17 +1291,17 @@ public: * * This method is an out-of-place version of select_interacting. */ - Edges selected_interacting (const Edges &other) const + Edges selected_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - return Edges (mp_delegate->selected_interacting (other)); + return Edges (mp_delegate->selected_interacting (other, min_count, max_count)); } /** * @brief Returns all edges of this edge set which do not overlap or touch with edges from the other edge set together with the ones that do not */ - std::pair selected_interacting_differential (const Edges &other) const + std::pair selected_interacting_differential (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - std::pair p = mp_delegate->selected_interacting_pair (other); + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); return std::pair (Edges (p.first), Edges (p.second)); } @@ -1311,9 +1311,9 @@ public: * Merged semantics applies. If merged semantics is chosen, the connected edge parts will be * selected as a whole. */ - Edges &select_not_interacting (const Edges &other) + Edges &select_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) { - set_delegate (mp_delegate->selected_not_interacting (other)); + set_delegate (mp_delegate->selected_not_interacting (other, min_count, max_count)); return *this; } @@ -1322,9 +1322,9 @@ public: * * This method is an out-of-place version of select_not_interacting. */ - Edges selected_not_interacting (const Edges &other) const + Edges selected_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const { - return Edges (mp_delegate->selected_not_interacting (other)); + return Edges (mp_delegate->selected_not_interacting (other, min_count, max_count)); } /** diff --git a/src/db/db/dbEdgesDelegate.h b/src/db/db/dbEdgesDelegate.h index 919ba5b8a..e5210c24f 100644 --- a/src/db/db/dbEdgesDelegate.h +++ b/src/db/db/dbEdgesDelegate.h @@ -318,12 +318,12 @@ public: virtual std::pair inside_outside_part_pair (const Region &other) const = 0; virtual RegionDelegate *pull_interacting (const Region &) const = 0; virtual EdgesDelegate *pull_interacting (const Edges &) const = 0; - virtual EdgesDelegate *selected_interacting (const Region &other) const = 0; - virtual EdgesDelegate *selected_not_interacting (const Region &other) const = 0; - virtual EdgesDelegate *selected_interacting (const Edges &other) const = 0; - virtual EdgesDelegate *selected_not_interacting (const Edges &other) const = 0; - virtual std::pair selected_interacting_pair (const Region &other) const = 0; - virtual std::pair selected_interacting_pair (const Edges &other) const = 0; + virtual EdgesDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual EdgesDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual EdgesDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; + virtual EdgesDelegate *selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual std::pair selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const = 0; virtual EdgesDelegate *selected_outside (const Region &other) const = 0; virtual EdgesDelegate *selected_not_outside (const Region &other) const = 0; diff --git a/src/db/db/dbEdgesLocalOperations.cc b/src/db/db/dbEdgesLocalOperations.cc index e201df8b5..28bc77979 100644 --- a/src/db/db/dbEdgesLocalOperations.cc +++ b/src/db/db/dbEdgesLocalOperations.cc @@ -199,5 +199,357 @@ EdgeToPolygonLocalOperation::do_compute_local (db::Layout * /*layout*/, db::Cell } } +// --------------------------------------------------------------------------------------------- +// Edge2EdgeInteractingLocalOperation implementation + +Edge2EdgeInteractingLocalOperation::Edge2EdgeInteractingLocalOperation (EdgeInteractionMode mode, output_mode_t output_mode) + : m_mode (mode), m_output_mode (output_mode) +{ + // .. nothing yet .. +} + +db::Coord Edge2EdgeInteractingLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void Edge2EdgeInteractingLocalOperation::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const +{ + tl_assert (results.size () == (m_output_mode == Both ? 2 : 1)); + + std::unordered_set &result = results.front (); + + std::unordered_set *result2 = 0; + if (m_output_mode == Both) { + result2 = &results[1]; + } + + db::box_scanner scanner; + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j).second); + } + } + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert (&subject, 0); + } + + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert (o.operator-> (), 1); + } + + if (m_output_mode == Inverse || m_output_mode == Both) { + + std::unordered_set interacting; + edge_interaction_filter > filter (interacting, m_mode); + scanner.process (filter, 1, db::box_convert ()); + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + const db::Edge &subject = interactions.subject_shape (i->first); + if (interacting.find (subject) == interacting.end ()) { + if (m_output_mode != Both) { + result.insert (subject); + } else { + result2->insert (subject); + } + } else if (m_output_mode == Both) { + result.insert (subject); + } + + } + + } else { + + edge_interaction_filter > filter (result, m_mode); + scanner.process (filter, 1, db::box_convert ()); + + } + +} + +OnEmptyIntruderHint Edge2EdgeInteractingLocalOperation::on_empty_intruder_hint () const +{ + if (m_mode == EdgesOutside) { + return m_output_mode == Both ? Copy : (m_output_mode == Inverse ? Drop : Copy); + } else { + return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop); + } +} + +std::string Edge2EdgeInteractingLocalOperation::description () const +{ + return tl::to_string (tr ("Select interacting edges")); +} + +// --------------------------------------------------------------------------------------------- +// Edge2EdgePullLocalOperation implementation + +Edge2EdgePullLocalOperation::Edge2EdgePullLocalOperation () +{ + // .. nothing yet .. +} + +db::Coord Edge2EdgePullLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void Edge2EdgePullLocalOperation::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const +{ + tl_assert (results.size () == 1); + std::unordered_set &result = results.front (); + + db::box_scanner scanner; + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j).second); + } + } + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert (&subject, 1); + } + + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert (o.operator-> (), 0); + } + + edge_interaction_filter > filter (result, EdgesInteract); + scanner.process (filter, 1, db::box_convert ()); + +} + +OnEmptyIntruderHint Edge2EdgePullLocalOperation::on_empty_intruder_hint () const +{ + return Drop; +} + +std::string Edge2EdgePullLocalOperation::description () const +{ + return tl::to_string (tr ("Select interacting edges from other")); +} + + +// --------------------------------------------------------------------------------------------- +// Edge2EdgePullLocalOperation implementation + +template +edge_to_polygon_interacting_local_operation::edge_to_polygon_interacting_local_operation (EdgeInteractionMode mode, output_mode_t output_mode) + : m_mode (mode), m_output_mode (output_mode) +{ + // .. nothing yet .. +} + +template +db::Coord edge_to_polygon_interacting_local_operation::dist () const +{ + // touching is sufficient + return 1; +} + +static const db::Polygon *deref (const db::Polygon &poly, std::list &) +{ + return &poly; +} + +static const db::Polygon *deref (const db::PolygonRef &pref, std::list &heap) +{ + heap.push_back (pref.obj ().transformed (pref.trans ())); + return & heap.back (); +} + +template +void edge_to_polygon_interacting_local_operation::do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const +{ + tl_assert (results.size () == size_t (m_output_mode == Both ? 2 : 1)); + + std::unordered_set &result = results.front (); + + std::unordered_set *result2 = 0; + if (m_output_mode == Both) { + result2 = &results[1]; + } + + db::box_scanner2 scanner; + + 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 db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert1 (&subject, 0); + } + + std::list heap; + for (typename std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert2 (deref (*o, heap), 1); + } + + if (m_output_mode == Inverse || m_output_mode == Both) { + + std::unordered_set interacting; + edge_to_region_interaction_filter > filter (&interacting, m_mode); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + const db::Edge &subject = interactions.subject_shape (i->first); + + if (interacting.find (subject) == interacting.end ()) { + if (m_output_mode != Both) { + result.insert (subject); + } else { + result2->insert (subject); + } + } else if (m_output_mode == Both) { + result.insert (subject); + } + + } + + } else { + + edge_to_region_interaction_filter > filter (&result, m_mode); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + } +} + +template +OnEmptyIntruderHint edge_to_polygon_interacting_local_operation::on_empty_intruder_hint () const +{ + if (m_mode == EdgesOutside) { + return m_output_mode == Both ? Copy : (m_output_mode == Inverse ? Drop : Copy); + } else { + return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop); + } +} + +template +std::string edge_to_polygon_interacting_local_operation::description () const +{ + if (m_mode == EdgesInteract) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-interacting edges")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select interacting edges")); + } else { + return tl::to_string (tr ("Select interacting and non-interacting edges")); + } + } else if (m_mode == EdgesInside) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-inside edges")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select inside edges")); + } else { + return tl::to_string (tr ("Select inside and non-inside edges")); + } + } else if (m_mode == EdgesOutside) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-outside edges")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select outside edges")); + } else { + return tl::to_string (tr ("Select outside and non-outside edges")); + } + } + return std::string (); +} + +template class edge_to_polygon_interacting_local_operation; +template class edge_to_polygon_interacting_local_operation; + +// --------------------------------------------------------------------------------------------- +// Edge2EdgePullLocalOperation implementation + +namespace { + +struct ResultInserter +{ + typedef db::Polygon value_type; + + ResultInserter (db::Layout *layout, std::unordered_set &result) + : mp_layout (layout), mp_result (&result) + { + // .. nothing yet .. + } + + void insert (const db::Polygon &p) + { + (*mp_result).insert (db::PolygonRef (p, mp_layout->shape_repository ())); + } + +private: + db::Layout *mp_layout; + std::unordered_set *mp_result; +}; + +} + +Edge2PolygonPullLocalOperation::Edge2PolygonPullLocalOperation () +{ + // .. nothing yet .. +} + +db::Coord Edge2PolygonPullLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void Edge2PolygonPullLocalOperation::do_compute_local (db::Layout *layout, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const +{ + tl_assert (results.size () == 1); + std::unordered_set &result = results.front (); + + db::box_scanner2 scanner; + + std::set others; + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (shape_interactions::iterator2 j = i->second.begin (); j != i->second.end (); ++j) { + others.insert (interactions.intruder_shape (*j).second); + } + } + + for (shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + const db::Edge &subject = interactions.subject_shape (i->first); + scanner.insert1 (&subject, 1); + } + + std::list heap; + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + heap.push_back (o->obj ().transformed (o->trans ())); + scanner.insert2 (& heap.back (), 0); + } + + ResultInserter inserter (layout, result); + edge_to_region_interaction_filter filter (&inserter, EdgesInteract); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); +} + +OnEmptyIntruderHint Edge2PolygonPullLocalOperation::on_empty_intruder_hint () const +{ + return Drop; +} + +std::string Edge2PolygonPullLocalOperation::description () const +{ + return tl::to_string (tr ("Select interacting regions")); +} + } diff --git a/src/db/db/dbEdgesLocalOperations.h b/src/db/db/dbEdgesLocalOperations.h index 9a5f9bdc4..eea3f1006 100644 --- a/src/db/db/dbEdgesLocalOperations.h +++ b/src/db/db/dbEdgesLocalOperations.h @@ -31,6 +31,7 @@ #include "dbEdgeBoolean.h" #include "dbEdgeProcessor.h" #include "dbLocalOperation.h" +#include "dbEdgesUtils.h" namespace db { @@ -79,6 +80,79 @@ private: bool m_include_borders; }; +/** + * @brief Implements edge-to-edge interactions + */ +class DB_PUBLIC Edge2EdgeInteractingLocalOperation + : public local_operation +{ +public: + enum output_mode_t { Normal, Inverse, Both }; + + Edge2EdgeInteractingLocalOperation (EdgeInteractionMode mode, output_mode_t output_mode); + + virtual db::Coord dist () const; + virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; + +private: + EdgeInteractionMode m_mode; + output_mode_t m_output_mode; +}; + +/** + * @brief Implements edge-to-edge interactions (pull mode) + */ +class DB_PUBLIC Edge2EdgePullLocalOperation + : public local_operation +{ +public: + Edge2EdgePullLocalOperation (); + + virtual db::Coord dist () const; + virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; +}; + +/** + * @brief Implements edge-to-polygon interactions + */ +template +class DB_PUBLIC_TEMPLATE edge_to_polygon_interacting_local_operation + : public local_operation +{ +public: + enum output_mode_t { Normal, Inverse, Both }; + + edge_to_polygon_interacting_local_operation (EdgeInteractionMode mode, output_mode_t output_mode); + + virtual db::Coord dist () const; + virtual void do_compute_local (db::Layout * /*layout*/, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; + +private: + EdgeInteractionMode m_mode; + output_mode_t m_output_mode; +}; + +/** + * @brief Implements edge-to-polygon interactions (pull mode) + */ +class DB_PUBLIC Edge2PolygonPullLocalOperation + : public local_operation +{ +public: + Edge2PolygonPullLocalOperation (); + + virtual db::Coord dist () const; + virtual void do_compute_local (db::Layout *layout, db::Cell * /*cell*/, const shape_interactions &interactions, std::vector > &results, const db::LocalProcessorBase * /*proc*/) const; + virtual OnEmptyIntruderHint on_empty_intruder_hint () const; + virtual std::string description () const; +}; + } #endif diff --git a/src/db/db/dbEmptyEdges.h b/src/db/db/dbEmptyEdges.h index 92bab3379..ec265156e 100644 --- a/src/db/db/dbEmptyEdges.h +++ b/src/db/db/dbEmptyEdges.h @@ -94,12 +94,12 @@ public: virtual RegionDelegate *pull_interacting (const Region &) const; virtual EdgesDelegate *pull_interacting (const Edges &) const { return new EmptyEdges (); } - virtual EdgesDelegate *selected_interacting (const Edges &) const { return new EmptyEdges (); } - virtual EdgesDelegate *selected_not_interacting (const Edges &) const { return new EmptyEdges (); } - virtual EdgesDelegate *selected_interacting (const Region &) const { return new EmptyEdges (); } - virtual EdgesDelegate *selected_not_interacting (const Region &) const { return new EmptyEdges (); } - virtual std::pair selected_interacting_pair (const Region &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } - virtual std::pair selected_interacting_pair (const Edges &) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual EdgesDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyEdges (); } + virtual EdgesDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyEdges (); } + virtual std::pair selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } + virtual std::pair selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyEdges (), new EmptyEdges ()); } virtual EdgesDelegate *selected_outside (const Region &) const { return new EmptyEdges (); } virtual EdgesDelegate *selected_not_outside (const Region &) const { return new EmptyEdges (); } diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 718b6d16b..6c648ee86 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -428,14 +428,14 @@ static std::vector split_outside_with_region (const db::Edges *r, con return as_2edges_vector (r->selected_outside_differential (other)); } -static std::vector split_interacting_with_edges (const db::Edges *r, const db::Edges &other) +static std::vector split_interacting_with_edges (const db::Edges *r, const db::Edges &other, size_t min_count, size_t max_count) { - return as_2edges_vector (r->selected_interacting_differential (other)); + return as_2edges_vector (r->selected_interacting_differential (other, min_count, max_count)); } -static std::vector split_interacting_with_region (const db::Edges *r, const db::Region &other) +static std::vector split_interacting_with_region (const db::Edges *r, const db::Region &other, size_t min_count, size_t max_count) { - return as_2edges_vector (r->selected_interacting_differential (other)); + return as_2edges_vector (r->selected_interacting_differential (other, min_count, max_count)); } @@ -969,61 +969,107 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "The 'join_with' alias has been introduced in version 0.28.12." ) + - method ("interacting", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_interacting, gsi::arg ("other"), + method ("interacting", (db::Edges (db::Edges::*) (const db::Edges &, size_t, size_t) const) &db::Edges::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Returns the edges of this edge collection which overlap or touch edges from the other edge collection\n" "\n" "@return A new edge collection containing the edges overlapping or touching edges from the other edge collection\n" + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge of this collection " + "has to interact with (different) edges of the other collection to make the edge selected. An edge is " + "selected by this method if the number of edges interacting with an edge of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." ) + - method ("not_interacting", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_not_interacting, gsi::arg ("other"), + method ("not_interacting", (db::Edges (db::Edges::*) (const db::Edges &, size_t, size_t) const) &db::Edges::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Returns the edges of this edge collection which do not overlap or touch edges from the other edge collection\n" "\n" "@return A new edge collection containing the edges not overlapping or touching edges from the other edge collection\n" - ) + - method ("select_interacting", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_interacting, gsi::arg ("other"), + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge of this collection " + "has to interact with (different) edges of the other collection to make the edge selected. An edge is " + "not selected by this method if the number of edges interacting with an edge of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method ("select_interacting", (db::Edges &(db::Edges::*) (const db::Edges &, size_t, size_t)) &db::Edges::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which overlap or touch edges from the other edge collection\n" "\n" "@return The edge collection after the edges have been selected (self)\n" - ) + - method ("select_not_interacting", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_not_interacting, gsi::arg ("other"), + "\n" + "This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method ("select_not_interacting", (db::Edges &(db::Edges::*) (const db::Edges &, size_t, size_t)) &db::Edges::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which do not overlap or touch edges from the other edge collection\n" "\n" "@return The edge collection after the edges have been selected (self)\n" - ) + - method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), + "\n" + "This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method_ext ("split_interacting", &split_interacting_with_edges, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which do and do not interact with edges from the other collection\n" "\n" "@return A two-element list of edge collections (first: interacting, second: non-interacting)\n" "\n" "This method provides a faster way to compute both interacting and non-interacting edges compared to using separate methods. " - "It has been introduced in version 0.28." + "It has been introduced in version 0.28.\n" + "'min_count' and 'max_count' have been introduced in version 0.29." ) + - method ("interacting", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_interacting, gsi::arg ("other"), + method ("interacting", (db::Edges (db::Edges::*) (const db::Region &, size_t, size_t) const) &db::Edges::selected_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Returns the edges from this edge collection which overlap or touch polygons from the region\n" "\n" "@return A new edge collection containing the edges overlapping or touching polygons from the region\n" - ) + - method ("not_interacting", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_not_interacting, gsi::arg ("other"), + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge of this collection " + "has to interact with (different) polygons of the other region to make the edge selected. An edge is " + "selected by this method if the number of polygons interacting with an edge of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method ("not_interacting", (db::Edges (db::Edges::*) (const db::Region &, size_t, size_t) const) &db::Edges::selected_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Returns the edges from this edge collection which do not overlap or touch polygons from the region\n" "\n" "@return A new edge collection containing the edges not overlapping or touching polygons from the region\n" - ) + - method ("select_interacting", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_interacting, gsi::arg ("other"), + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge of this collection " + "has to interact with (different) polygons of the other region to make the edge selected. An edge is " + "not selected by this method if the number of polygons interacting with an edge of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method ("select_interacting", (db::Edges &(db::Edges::*) (const db::Region &, size_t, size_t)) &db::Edges::select_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which overlap or touch polygons from the region\n" "\n" "@return The edge collection after the edges have been selected (self)\n" - ) + - method ("select_not_interacting", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_not_interacting, gsi::arg ("other"), + "\n" + "This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method ("select_not_interacting", (db::Edges &(db::Edges::*) (const db::Region &, size_t, size_t)) &db::Edges::select_not_interacting, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which do not overlap or touch polygons from the region\n" "\n" "@return The edge collection after the edges have been selected (self)\n" - ) + - method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), + "\n" + "This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "'min_count' and 'max_count' have been introduced in version 0.29." + ) + + method_ext ("split_interacting", &split_interacting_with_region, gsi::arg ("other"), gsi::arg ("min_count", size_t (1)), gsi::arg ("max_count", size_t (std::numeric_limits::max ()), "unlimited"), "@brief Selects the edges from this edge collection which do and do not interact with polygons from the other region\n" "\n" "@return A two-element list of edge collections (first: interacting, second: non-interacting)\n" "\n" "This method provides a faster way to compute both interacting and non-interacting edges compared to using separate methods. " - "It has been introduced in version 0.28." + "It has been introduced in version 0.28.\n" + "'min_count' and 'max_count' have been introduced in version 0.29." ) + method ("inside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_inside, gsi::arg ("other"), "@brief Returns the edges of this edge collection which are inside (completely covered by) edges from the other edge collection\n"