From 7510728a712cfa2b847f37bf3f73c38953ff8ce3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 3 Aug 2024 23:18:57 +0200 Subject: [PATCH 1/7] First API steps --- src/db/db/dbAsIfFlatEdgePairs.cc | 84 +++++++++++++ src/db/db/dbAsIfFlatEdgePairs.h | 16 +++ src/db/db/dbDeepEdgePairs.cc | 84 +++++++++++++ src/db/db/dbDeepEdgePairs.h | 16 +++ src/db/db/dbEdgePairs.cc | 10 ++ src/db/db/dbEdgePairs.h | 208 +++++++++++++++++++++++++++++++ src/db/db/dbEdgePairsDelegate.h | 16 +++ src/db/db/dbEmptyEdgePairs.cc | 12 ++ src/db/db/dbEmptyEdgePairs.h | 16 +++ 9 files changed, 462 insertions(+) diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc index d0f098e27..789322e69 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.cc +++ b/src/db/db/dbAsIfFlatEdgePairs.cc @@ -241,6 +241,90 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const return new_edge_pairs.release (); } +RegionDelegate * +AsIfFlatEdgePairs::pull_interacting (const Region &) const +{ + // @@@ +} + +EdgesDelegate * +AsIfFlatEdgePairs::pull_interacting (const Edges &) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_interacting (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +std::pair +AsIfFlatEdgePairs::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +std::pair +AsIfFlatEdgePairs::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_outside (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_not_outside (const Region &other) const +{ + // @@@ +} + +std::pair +AsIfFlatEdgePairs::selected_outside_pair (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_inside (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_not_inside (const Region &other) const +{ + // @@@ +} + +std::pair +AsIfFlatEdgePairs::selected_inside_pair (const Region &other) const +{ + // @@@ +} + RegionDelegate * AsIfFlatEdgePairs::polygons (db::Coord e) const { diff --git a/src/db/db/dbAsIfFlatEdgePairs.h b/src/db/db/dbAsIfFlatEdgePairs.h index 2a69bb035..9387aa03c 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.h +++ b/src/db/db/dbAsIfFlatEdgePairs.h @@ -62,6 +62,22 @@ public: virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &proc) const; virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &proc) const; + virtual RegionDelegate *pull_interacting (const Region &) const; + virtual EdgesDelegate *pull_interacting (const Edges &) const; + virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_not_interacting (const Edges &other, 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 EdgePairsDelegate *selected_outside (const Region &other) const; + virtual EdgePairsDelegate *selected_not_outside (const Region &other) const; + virtual std::pair selected_outside_pair (const Region &other) const; + virtual EdgePairsDelegate *selected_inside (const Region &other) const; + virtual EdgePairsDelegate *selected_not_inside (const Region &other) const; + virtual std::pair selected_inside_pair (const Region &other) const; + virtual EdgePairsDelegate *add_in_place (const EdgePairs &other) { return add (other); diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index 090644265..4900d5e0e 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -497,6 +497,90 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const return new db::DeepRegion (new_layer); } +RegionDelegate * +DeepEdgePairs::pull_interacting (const Region &) const +{ + // @@@ +} + +EdgesDelegate * +DeepEdgePairs::pull_interacting (const Edges &) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_interacting (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +std::pair +DeepEdgePairs::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +std::pair +DeepEdgePairs::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_outside (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_not_outside (const Region &other) const +{ + // @@@ +} + +std::pair +DeepEdgePairs::selected_outside_pair (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_inside (const Region &other) const +{ + // @@@ +} + +EdgePairsDelegate * +DeepEdgePairs::selected_not_inside (const Region &other) const +{ + // @@@ +} + +std::pair +DeepEdgePairs::selected_inside_pair (const Region &other) const +{ + // @@@ +} + EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const { db::DeepLayer new_layer = deep_layer ().derived (); diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h index 8ec686da0..ae0e7a5e5 100644 --- a/src/db/db/dbDeepEdgePairs.h +++ b/src/db/db/dbDeepEdgePairs.h @@ -83,6 +83,22 @@ public: virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const; + virtual RegionDelegate *pull_interacting (const Region &) const; + virtual EdgesDelegate *pull_interacting (const Edges &) const; + virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_not_interacting (const Edges &other, 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 EdgePairsDelegate *selected_outside (const Region &other) const; + virtual EdgePairsDelegate *selected_not_outside (const Region &other) const; + virtual std::pair selected_outside_pair (const Region &other) const; + virtual EdgePairsDelegate *selected_inside (const Region &other) const; + virtual EdgePairsDelegate *selected_not_inside (const Region &other) const; + virtual std::pair selected_inside_pair (const Region &other) const; + virtual EdgePairsDelegate *add_in_place (const EdgePairs &other); virtual EdgePairsDelegate *add (const EdgePairs &other) const; diff --git a/src/db/db/dbEdgePairs.cc b/src/db/db/dbEdgePairs.cc index 6e0d9059e..600d5c709 100644 --- a/src/db/db/dbEdgePairs.cc +++ b/src/db/db/dbEdgePairs.cc @@ -224,6 +224,16 @@ void EdgePairs::second_edges (Edges &output) const output.set_delegate (mp_delegate->second_edges ()); } +void EdgePairs::pull_interacting (Region &output, const Region &other) const +{ + // @@@ +} + +void EdgePairs::pull_interacting (Edges &output, const Edges &other) const +{ + // @@@ +} + void EdgePairs::set_delegate (EdgePairsDelegate *delegate) { if (delegate != mp_delegate) { diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index 53a499689..dd5211a1c 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -370,6 +370,214 @@ public: */ void processed (Edges &output, const EdgePairToEdgeProcessorBase &proc) const; + /** + * @brief Selects all polygons of the region set which overlap or touch edges from this edge pair set + * + * Merged semantics applies for the other region. Merged polygons will be selected from the other region + * if merged semantics is enabled. + */ + void pull_interacting (Region &output, const Region &other) const; + + /** + * @brief Selects all edges of the other edge set which overlap or touch edges from this edge pair set + * + * Merged semantics applies. If merged semantics is chosen, the connected edge parts will be + * selected as a whole from other. + */ + void pull_interacting (Edges &output, const Edges &other) const; + + /** + * @brief Selects all edge pairs of this set which overlap or touch with polygons from the region + */ + EdgePairs &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, min_count, max_count)); + return *this; + } + + /** + * @brief Returns all edge pairs of this set which overlap or touch with polygons from the region + * + * This method is an out-of-place version of select_interacting. + */ + EdgePairs selected_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + return EdgePairs (mp_delegate->selected_interacting (other, min_count, max_count)); + } + + /** + * @brief Selects all edge pairs of this set which do not overlap or touch with polygons from the region + */ + EdgePairs &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, min_count, max_count)); + return *this; + } + + /** + * @brief Returns all edge pairs of this set which do not overlap or touch with polygons from the region + * + * This method is an out-of-place version of select_not_interacting. + */ + EdgePairs selected_not_interacting (const Region &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + return EdgePairs (mp_delegate->selected_not_interacting (other, min_count, max_count)); + } + + /** + * @brief Returns all edge pairs of this 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, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); + return std::pair (EdgePairs (p.first), EdgePairs (p.second)); + } + + /** + * @brief Selects all edge pairs of this collection which are completely outside polygons from the region + */ + EdgePairs &select_outside (const Region &other) + { + set_delegate (mp_delegate->selected_outside (other)); + return *this; + } + + /** + * @brief Selects all edge pairs of this collection which are not completely outside polygons from the region + */ + EdgePairs &select_not_outside (const Region &other) + { + set_delegate (mp_delegate->selected_not_outside (other)); + return *this; + } + + /** + * @brief Returns all edge pairs of this collection which are completely outside polygons from the region + * + * This method is an out-of-place version of select_outside. + */ + EdgePairs selected_outside (const Region &other) const + { + return EdgePairs (mp_delegate->selected_outside (other)); + } + + /** + * @brief Returns all edge pairs of this collection which are not completely outside polygons from the region + * + * This method is an out-of-place version of select_not_outside. + */ + EdgePairs selected_not_outside (const Region &other) const + { + return EdgePairs (mp_delegate->selected_not_outside (other)); + } + + /** + * @brief Returns all edge pairs of this which are completely outside polygons from the region and the opposite ones at the same time + * + * This method is equivalent to calling selected_outside and selected_not_outside, but faster. + */ + std::pair selected_outside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_outside_pair (other); + return std::pair (EdgePairs (p.first), EdgePairs (p.second)); + } + + /** + * @brief Selects all edge pairs of this collection which are completely inside polygons from the region + */ + EdgePairs &select_inside (const Region &other) + { + set_delegate (mp_delegate->selected_inside (other)); + return *this; + } + + /** + * @brief Selects all edge pairs of this collection which are not completely inside polygons from the region + */ + EdgePairs &select_not_inside (const Region &other) + { + set_delegate (mp_delegate->selected_not_inside (other)); + return *this; + } + + /** + * @brief Returns all edge pairs of this which are completely inside polygons from the region + * + * This method is an out-of-place version of select_inside. + */ + EdgePairs selected_inside (const Region &other) const + { + return EdgePairs (mp_delegate->selected_inside (other)); + } + + /** + * @brief Returns all edge pairs of this which are not completely inside polygons from the region + * + * This method is an out-of-place version of select_not_inside. + */ + EdgePairs selected_not_inside (const Region &other) const + { + return EdgePairs (mp_delegate->selected_not_inside (other)); + } + + /** + * @brief Returns all edge pairs of this which are completely inside polygons from the region and the opposite ones at the same time + * + * This method is equivalent to calling selected_inside and selected_not_inside, but faster. + */ + std::pair selected_inside_differential (const Region &other) const + { + std::pair p = mp_delegate->selected_inside_pair (other); + return std::pair (EdgePairs (p.first), EdgePairs (p.second)); + } + + /** + * @brief Selects all edge pairs of this edge pairs set which overlap or touch with edges from the edge set + */ + EdgePairs &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, min_count, max_count)); + return *this; + } + + /** + * @brief Returns all edge pairs of this edge pairs set which overlap or touch with edges from the edge set + * + * This method is an out-of-place version of select_interacting. + */ + EdgePairs selected_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + return EdgePairs (mp_delegate->selected_interacting (other, min_count, max_count)); + } + + /** + * @brief Returns all edge pairs 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, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + std::pair p = mp_delegate->selected_interacting_pair (other, min_count, max_count); + return std::pair (EdgePairs (p.first), EdgePairs (p.second)); + } + + /** + * @brief Selects all edge pairs of this edge pairs set which do not overlap or touch with edges from the edge set + */ + EdgePairs &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, min_count, max_count)); + return *this; + } + + /** + * @brief Returns all edge pairs of this edge pairs set which do not overlap or touch with edges from the edge set + * + * This method is an out-of-place version of select_not_interacting. + */ + EdgePairs selected_not_interacting (const Edges &other, size_t min_count = 1, size_t max_count = std::numeric_limits::max ()) const + { + return EdgePairs (mp_delegate->selected_not_interacting (other, min_count, max_count)); + } + /** * @brief Transforms the edge pair set */ diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index 189ff293e..c786838fa 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -200,6 +200,22 @@ public: virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &proc) const = 0; virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &proc) const = 0; + virtual RegionDelegate *pull_interacting (const Region &) const = 0; + virtual EdgesDelegate *pull_interacting (const Edges &) const = 0; + virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const = 0; + virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const = 0; + virtual EdgePairsDelegate *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 EdgePairsDelegate *selected_outside (const Region &other) const = 0; + virtual EdgePairsDelegate *selected_not_outside (const Region &other) const = 0; + virtual std::pair selected_outside_pair (const Region &other) const = 0; + virtual EdgePairsDelegate *selected_inside (const Region &other) const = 0; + virtual EdgePairsDelegate *selected_not_inside (const Region &other) const = 0; + virtual std::pair selected_inside_pair (const Region &other) const = 0; + virtual RegionDelegate *polygons (db::Coord e) const = 0; virtual EdgesDelegate *edges () const = 0; virtual EdgesDelegate *first_edges () const = 0; diff --git a/src/db/db/dbEmptyEdgePairs.cc b/src/db/db/dbEmptyEdgePairs.cc index d9468ef93..e9f2aa2a1 100644 --- a/src/db/db/dbEmptyEdgePairs.cc +++ b/src/db/db/dbEmptyEdgePairs.cc @@ -65,6 +65,18 @@ EmptyEdgePairs::processed_to_edges (const EdgePairToEdgeProcessorBase &) const return new EmptyEdges (); } +RegionDelegate * +EmptyEdgePairs::pull_interacting (const Region &) const +{ + return new EmptyRegion (); +} + +EdgesDelegate * +EmptyEdgePairs::pull_interacting (const Edges &) const +{ + return new EmptyEdges (); +} + EdgesDelegate * EmptyEdgePairs::edges () const { diff --git a/src/db/db/dbEmptyEdgePairs.h b/src/db/db/dbEmptyEdgePairs.h index 16be5fa99..d74697533 100644 --- a/src/db/db/dbEmptyEdgePairs.h +++ b/src/db/db/dbEmptyEdgePairs.h @@ -61,6 +61,22 @@ public: virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const; + virtual RegionDelegate *pull_interacting (const Region &) const; + virtual EdgesDelegate *pull_interacting (const Edges &) const; + virtual EdgePairsDelegate *selected_interacting (const Region &, size_t, size_t) const { return new EmptyEdgePairs (); } + virtual EdgePairsDelegate *selected_not_interacting (const Region &, size_t, size_t) const { return new EmptyEdgePairs (); } + virtual EdgePairsDelegate *selected_interacting (const Edges &, size_t, size_t) const { return new EmptyEdgePairs (); } + virtual EdgePairsDelegate *selected_not_interacting (const Edges &, size_t, size_t) const { return new EmptyEdgePairs (); } + virtual std::pair selected_interacting_pair (const Region &, size_t, size_t) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); } + virtual std::pair selected_interacting_pair (const Edges &, size_t, size_t) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); } + + virtual EdgePairsDelegate *selected_outside (const Region &) const { return new EmptyEdgePairs (); } + virtual EdgePairsDelegate *selected_not_outside (const Region &) const { return new EmptyEdgePairs (); } + virtual std::pair selected_outside_pair (const Region &) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); } + virtual EdgePairsDelegate *selected_inside (const Region &) const { return new EmptyEdgePairs (); } + virtual EdgePairsDelegate *selected_not_inside (const Region &) const { return new EmptyEdgePairs (); } + virtual std::pair selected_inside_pair (const Region &) const { return std::make_pair (new EmptyEdgePairs (), new EmptyEdgePairs ()); } + virtual RegionDelegate *polygons (db::Coord e) const; virtual EdgesDelegate *edges () const; virtual EdgesDelegate *first_edges () const; From c23c4045ba53f212c9f12d58a9c499d328c49f3b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Aug 2024 17:57:50 +0200 Subject: [PATCH 2/7] Basic implementation --- src/db/db/db.pro | 4 + src/db/db/dbAsIfFlatEdgePairs.cc | 255 +++++++++++++++- src/db/db/dbAsIfFlatEdgePairs.h | 7 + src/db/db/dbDeepEdgePairs.cc | 217 ++++++++++---- src/db/db/dbDeepEdgePairs.h | 24 +- src/db/db/dbEdgePairs.cc | 4 +- src/db/db/dbEdgePairs.h | 20 ++ src/db/db/dbEdgePairsDelegate.cc | 7 + src/db/db/dbEdgePairsDelegate.h | 7 + src/db/db/dbEdgePairsLocalOperations.cc | 377 ++++++++++++++++++++++++ src/db/db/dbEdgePairsLocalOperations.h | 111 +++++++ src/db/db/dbEdgePairsUtils.cc | 92 ++++++ src/db/db/dbEdgePairsUtils.h | 261 ++++++++++++++++ src/db/db/dbEdgesLocalOperations.cc | 2 +- 14 files changed, 1297 insertions(+), 91 deletions(-) create mode 100644 src/db/db/dbEdgePairsLocalOperations.cc create mode 100644 src/db/db/dbEdgePairsLocalOperations.h create mode 100644 src/db/db/dbEdgePairsUtils.cc create mode 100644 src/db/db/dbEdgePairsUtils.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index b6aac64f3..d0fa394b3 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -27,6 +27,8 @@ SOURCES = \ dbEdgePairFilters.cc \ dbEdgePairRelations.cc \ dbEdgePairs.cc \ + dbEdgePairsLocalOperations.cc \ + dbEdgePairsUtils.cc \ dbEdgeProcessor.cc \ dbEdges.cc \ dbEdgesLocalOperations.cc \ @@ -250,6 +252,8 @@ HEADERS = \ dbEdgePairFilters.h \ dbEdgePairRelations.h \ dbEdgePairs.h \ + dbEdgePairsLocalOperations.h \ + dbEdgePairsUtils.h \ dbEdgeProcessor.h \ dbEdges.h \ dbEdgesLocalOperations.h \ diff --git a/src/db/db/dbAsIfFlatEdgePairs.cc b/src/db/db/dbAsIfFlatEdgePairs.cc index 789322e69..70c853734 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.cc +++ b/src/db/db/dbAsIfFlatEdgePairs.cc @@ -26,8 +26,13 @@ #include "dbFlatRegion.h" #include "dbFlatEdges.h" #include "dbEmptyEdgePairs.h" +#include "dbEmptyEdges.h" +#include "dbEmptyRegion.h" #include "dbEdgePairs.h" +#include "dbEdgePairsLocalOperations.h" #include "dbBoxConvert.h" +#include "dbRegion.h" +#include "dbHierProcessor.h" #include @@ -242,87 +247,305 @@ AsIfFlatEdgePairs::filtered (const EdgePairFilterBase &filter) const } RegionDelegate * -AsIfFlatEdgePairs::pull_interacting (const Region &) const +AsIfFlatEdgePairs::pull_interacting (const Region &other) const { - // @@@ + return pull_generic (other); } EdgesDelegate * -AsIfFlatEdgePairs::pull_interacting (const Edges &) const +AsIfFlatEdgePairs::pull_interacting (const Edges &other) const { - // @@@ + return pull_generic (other); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_interacting (const Region &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_generic (other, EdgePairsInteract, false, min_count, max_count); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_generic (other, EdgePairsInteract, true, min_count, max_count); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_generic (other, false, min_count, max_count); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_generic (other, true, min_count, max_count); } std::pair AsIfFlatEdgePairs::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_pair_generic (other, EdgePairsInteract, min_count, max_count); } std::pair AsIfFlatEdgePairs::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const { - // @@@ + return selected_interacting_pair_generic (other, min_count, max_count); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_outside (const Region &other) const { - // @@@ + return selected_interacting_generic (other, EdgePairsOutside, false, size_t (1), std::numeric_limits::max ()); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_not_outside (const Region &other) const { - // @@@ + return selected_interacting_generic (other, EdgePairsOutside, true, size_t (1), std::numeric_limits::max ()); } std::pair AsIfFlatEdgePairs::selected_outside_pair (const Region &other) const { - // @@@ + return selected_interacting_pair_generic (other, EdgePairsOutside, size_t (1), std::numeric_limits::max ()); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_inside (const Region &other) const { - // @@@ + return selected_interacting_generic (other, EdgePairsInside, false, size_t (1), std::numeric_limits::max ()); } EdgePairsDelegate * AsIfFlatEdgePairs::selected_not_inside (const Region &other) const { - // @@@ + return selected_interacting_generic (other, EdgePairsInside, true, size_t (1), std::numeric_limits::max ()); } std::pair AsIfFlatEdgePairs::selected_inside_pair (const Region &other) const { - // @@@ + return selected_interacting_pair_generic (other, EdgePairsInside, size_t (1), std::numeric_limits::max ()); +} + +namespace { + +class OutputPairHolder +{ +public: + OutputPairHolder (int inverse, bool merged_semantics) + { + m_e1.reset (new FlatEdgePairs (merged_semantics)); + m_results.push_back (& m_e1->raw_edge_pairs ()); + + if (inverse == 0) { + m_e2.reset (new FlatEdgePairs (merged_semantics)); + m_results.push_back (& m_e2->raw_edge_pairs ()); + } + } + + 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 * +AsIfFlatEdgePairs::pull_generic (const Edges &other) const +{ + // shortcuts + if (other.empty () || empty ()) { + return new EmptyEdges (); + } + + db::box_scanner2 scanner (report_progress (), progress_desc ()); + + AddressableEdgePairDelivery e (begin ()); + + for ( ; ! e.at_end (); ++e) { + scanner.insert1 (e.operator-> (), 0); + } + + AddressableEdgeDelivery p = other.addressable_merged_edges (); + + for ( ; ! p.at_end (); ++p) { + scanner.insert2 (p.operator-> (), 1); + } + + std::unique_ptr output (new FlatEdges (true)); + + edge_pair_to_edge_interaction_filter filter (output.get (), size_t (1), std::numeric_limits::max ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + return output.release (); +} + +RegionDelegate * +AsIfFlatEdgePairs::pull_generic (const Region &other) const +{ + // shortcuts + if (other.empty () || empty ()) { + return new EmptyRegion (); + } + + db::box_scanner2 scanner (report_progress (), progress_desc ()); + + AddressableEdgePairDelivery e (begin ()); + + for ( ; ! e.at_end (); ++e) { + scanner.insert1 (e.operator-> (), 0); + } + + AddressablePolygonDelivery p = other.addressable_merged_polygons (); + + for ( ; ! p.at_end (); ++p) { + scanner.insert2 (p.operator-> (), 1); + } + + std::unique_ptr output (new FlatRegion (true)); + + edge_pair_to_polygon_interaction_filter filter (output.get (), EdgePairsInteract, size_t (1), std::numeric_limits::max ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + return output.release (); +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_interacting_generic (const Edges &other, 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 inverse ? clone () : new EmptyEdgePairs (); + } + + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ()); + + db::EdgePairsIterator edges (begin ()); + + db::EdgePair2EdgeInteractingLocalOperation op (inverse ? db::EdgePair2EdgeInteractingLocalOperation::Inverse : db::EdgePair2EdgeInteractingLocalOperation::Normal, min_count, max_count); + + 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 edge collection 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; +} + +EdgePairsDelegate * +AsIfFlatEdgePairs::selected_interacting_generic (const Region &other, EdgePairInteractionMode 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 == EdgePairsOutside) == inverse) ? new EmptyEdgePairs () : clone (); + } + + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (inverse ? 1 : -1, merged_semantics () || is_merged ()); + + db::EdgePairsIterator edges (begin ()); + + db::edge_pair_to_polygon_interacting_local_operation op (mode, inverse ? db::edge_pair_to_polygon_interacting_local_operation::Inverse : db::edge_pair_to_polygon_interacting_local_operation::Normal, min_count, max_count); + + 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 || mode != EdgePairsInteract ? other.begin_merged () : other.begin ()); + + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); + + return oph.region_pair ().first; +} + +std::pair +AsIfFlatEdgePairs::selected_interacting_pair_generic (const Edges &other, 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 std::make_pair (new EmptyEdgePairs (), clone ()); + } + + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (0, merged_semantics () || is_merged ()); + + db::EdgePairsIterator edges (begin ()); + + db::EdgePair2EdgeInteractingLocalOperation op (db::EdgePair2EdgeInteractingLocalOperation::Both, min_count, max_count); + + 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 (); +} + +std::pair +AsIfFlatEdgePairs::selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, 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 ()) { + if (mode != EdgePairsOutside) { + return std::make_pair (new EmptyEdgePairs (), clone ()); + } else { + return std::make_pair (clone (), new EmptyEdgePairs ()); + } + } + + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + OutputPairHolder oph (0, merged_semantics () || is_merged ()); + + db::EdgePairsIterator edges (begin ()); + + db::edge_pair_to_polygon_interacting_local_operation op (mode, db::edge_pair_to_polygon_interacting_local_operation::Both, min_count, max_count); + + 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 || mode != EdgePairsInteract ? other.begin_merged () : other.begin ()); + + proc.run_flat (edges, others, std::vector (), &op, oph.results ()); + + return oph.region_pair (); } RegionDelegate * diff --git a/src/db/db/dbAsIfFlatEdgePairs.h b/src/db/db/dbAsIfFlatEdgePairs.h index 9387aa03c..fe6152419 100644 --- a/src/db/db/dbAsIfFlatEdgePairs.h +++ b/src/db/db/dbAsIfFlatEdgePairs.h @@ -27,6 +27,7 @@ #include "dbCommon.h" #include "dbEdgePairsDelegate.h" +#include "dbEdgePairsUtils.h" namespace db { @@ -101,6 +102,12 @@ public: protected: void update_bbox (const db::Box &box); void invalidate_bbox (); + virtual EdgesDelegate *pull_generic (const Edges &other) const; + virtual RegionDelegate *pull_generic (const Region &other) const; + virtual EdgePairsDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const; private: friend class DeepEdgePairs; diff --git a/src/db/db/dbDeepEdgePairs.cc b/src/db/db/dbDeepEdgePairs.cc index 4900d5e0e..bc4be7bb5 100644 --- a/src/db/db/dbDeepEdgePairs.cc +++ b/src/db/db/dbDeepEdgePairs.cc @@ -27,6 +27,9 @@ #include "dbDeepRegion.h" #include "dbCellMapping.h" #include "dbLayoutUtils.h" +#include "dbEdgePairsLocalOperations.h" +#include "dbHierProcessor.h" +#include "dbRegion.h" #include @@ -497,88 +500,190 @@ RegionDelegate *DeepEdgePairs::polygons (db::Coord e) const return new db::DeepRegion (new_layer); } -RegionDelegate * -DeepEdgePairs::pull_interacting (const Region &) const -{ - // @@@ -} - EdgesDelegate * -DeepEdgePairs::pull_interacting (const Edges &) const +DeepEdgePairs::pull_generic (const Edges &other) const { - // @@@ + std::unique_ptr dr_holder; + const db::DeepEdges *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::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + const db::DeepLayer &edge_pairs = deep_layer (); + const db::DeepLayer &other_edges = other_deep->merged_deep_layer (); + + DeepLayer dl_out (other_edges.derived ()); + + db::EdgePair2EdgePullLocalOperation op; + + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), edge_pairs.breakout_cells (), other_edges.breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + proc.run (&op, edge_pairs.layer (), other_edges.layer (), dl_out.layer ()); + + return new db::DeepEdges (dl_out); +} + +RegionDelegate * +DeepEdgePairs::pull_generic (const Region &other) 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 &edge_pairs = deep_layer (); + const db::DeepLayer &other_polygons = other_deep->merged_deep_layer (); + + DeepLayer dl_out (other_polygons.derived ()); + + db::EdgePair2PolygonPullLocalOperation op; + + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), edge_pairs.breakout_cells (), other_polygons.breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + proc.run (&op, edge_pairs.layer (), other_polygons.layer (), dl_out.layer ()); + + return new db::DeepRegion (dl_out); } EdgePairsDelegate * -DeepEdgePairs::selected_interacting (const Region &other, size_t min_count, size_t max_count) const +DeepEdgePairs::selected_interacting_generic (const Edges &other, 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) { + // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + min_count = std::max (size_t (1), min_count); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + + const db::DeepLayer &edge_pairs = deep_layer (); + + DeepLayer dl_out (edge_pairs.derived ()); + + db::EdgePair2EdgeInteractingLocalOperation op (inverse ? db::EdgePair2EdgeInteractingLocalOperation::Inverse : db::EdgePair2EdgeInteractingLocalOperation::Normal, min_count, max_count); + + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + // NOTE: with counting the other region needs to be merged + proc.run (&op, edge_pairs.layer (), (counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ()); + + return new db::DeepEdgePairs (dl_out); } EdgePairsDelegate * -DeepEdgePairs::selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const +DeepEdgePairs::selected_interacting_generic (const Region &other, EdgePairInteractionMode 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) { + // 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 (); + } -EdgePairsDelegate * -DeepEdgePairs::selected_interacting (const Edges &other, size_t min_count, size_t max_count) const -{ - // @@@ -} + min_count = std::max (size_t (1), min_count); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); -EdgePairsDelegate * -DeepEdgePairs::selected_not_interacting (const Edges &other, size_t min_count, size_t max_count) const -{ - // @@@ + const db::DeepLayer &edge_pairs = deep_layer (); + + DeepLayer dl_out (edge_pairs.derived ()); + + db::edge_pair_to_polygon_interacting_local_operation op (mode, inverse ? db::edge_pair_to_polygon_interacting_local_operation::Inverse : db::edge_pair_to_polygon_interacting_local_operation::Normal, min_count, max_count); + + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + // NOTE: with counting the other region needs to be merged + proc.run (&op, edge_pairs.layer (), (counting || mode != EdgePairsInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), dl_out.layer ()); + + return new db::DeepEdgePairs (dl_out); } std::pair -DeepEdgePairs::selected_interacting_pair (const Region &other, size_t min_count, size_t max_count) const +DeepEdgePairs::selected_interacting_pair_generic (const Edges &other, 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) { + // if the other region isn't deep, turn into a top-level only deep region to facilitate re-hierarchization + dr_holder.reset (new db::DeepEdges (other, const_cast (*deep_layer ().store ()))); + other_deep = dr_holder.get (); + } + + min_count = std::max (size_t (1), min_count); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + + const db::DeepLayer &edge_pairs = deep_layer (); + + DeepLayer dl_out (edge_pairs.derived ()); + DeepLayer dl_out2 (edge_pairs.derived ()); + + std::vector output_layers; + output_layers.reserve (2); + output_layers.push_back (dl_out.layer ()); + output_layers.push_back (dl_out2.layer ()); + + db::EdgePair2EdgeInteractingLocalOperation op (db::EdgePair2EdgeInteractingLocalOperation::Both, min_count, max_count); + + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + // NOTE: with counting the other region needs to be merged + proc.run (&op, edge_pairs.layer (), (counting ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers); + + return std::make_pair (new db::DeepEdgePairs (dl_out), new db::DeepEdgePairs (dl_out2)); } std::pair -DeepEdgePairs::selected_interacting_pair (const Edges &other, size_t min_count, size_t max_count) const +DeepEdgePairs::selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode 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) { + // 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 (); + } -EdgePairsDelegate * -DeepEdgePairs::selected_outside (const Region &other) const -{ - // @@@ -} + min_count = std::max (size_t (1), min_count); + bool counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); -EdgePairsDelegate * -DeepEdgePairs::selected_not_outside (const Region &other) const -{ - // @@@ -} + const db::DeepLayer &edge_pairs = deep_layer (); -std::pair -DeepEdgePairs::selected_outside_pair (const Region &other) const -{ - // @@@ -} + DeepLayer dl_out (edge_pairs.derived ()); + DeepLayer dl_out2 (edge_pairs.derived ()); -EdgePairsDelegate * -DeepEdgePairs::selected_inside (const Region &other) const -{ - // @@@ -} + std::vector output_layers; + output_layers.reserve (2); + output_layers.push_back (dl_out.layer ()); + output_layers.push_back (dl_out2.layer ()); -EdgePairsDelegate * -DeepEdgePairs::selected_not_inside (const Region &other) const -{ - // @@@ -} + db::edge_pair_to_polygon_interacting_local_operation op (mode, db::edge_pair_to_polygon_interacting_local_operation::Both, min_count, max_count); -std::pair -DeepEdgePairs::selected_inside_pair (const Region &other) const -{ - // @@@ + db::local_processor proc (const_cast (&edge_pairs.layout ()), const_cast (&edge_pairs.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edge_pairs.breakout_cells (), other_deep->deep_layer ().breakout_cells ()); + proc.set_base_verbosity (base_verbosity ()); + proc.set_threads (edge_pairs.store ()->threads ()); + + // NOTE: with counting the other region needs to be merged + proc.run (&op, edge_pairs.layer (), (counting || mode != EdgePairsInteract ? other_deep->merged_deep_layer () : other_deep->deep_layer ()).layer (), output_layers); + + return std::make_pair (new db::DeepEdgePairs (dl_out), new db::DeepEdgePairs (dl_out2)); } EdgesDelegate *DeepEdgePairs::generic_edges (bool first, bool second) const diff --git a/src/db/db/dbDeepEdgePairs.h b/src/db/db/dbDeepEdgePairs.h index ae0e7a5e5..c9417dfe0 100644 --- a/src/db/db/dbDeepEdgePairs.h +++ b/src/db/db/dbDeepEdgePairs.h @@ -83,22 +83,6 @@ public: virtual RegionDelegate *processed_to_polygons (const EdgePairToPolygonProcessorBase &filter) const; virtual EdgesDelegate *processed_to_edges (const EdgePairToEdgeProcessorBase &filter) const; - virtual RegionDelegate *pull_interacting (const Region &) const; - virtual EdgesDelegate *pull_interacting (const Edges &) const; - virtual EdgePairsDelegate *selected_interacting (const Region &other, size_t min_count, size_t max_count) const; - virtual EdgePairsDelegate *selected_not_interacting (const Region &other, size_t min_count, size_t max_count) const; - virtual EdgePairsDelegate *selected_interacting (const Edges &other, size_t min_count, size_t max_count) const; - virtual EdgePairsDelegate *selected_not_interacting (const Edges &other, 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 EdgePairsDelegate *selected_outside (const Region &other) const; - virtual EdgePairsDelegate *selected_not_outside (const Region &other) const; - virtual std::pair selected_outside_pair (const Region &other) const; - virtual EdgePairsDelegate *selected_inside (const Region &other) const; - virtual EdgePairsDelegate *selected_not_inside (const Region &other) const; - virtual std::pair selected_inside_pair (const Region &other) const; - virtual EdgePairsDelegate *add_in_place (const EdgePairs &other); virtual EdgePairsDelegate *add (const EdgePairs &other) const; @@ -120,6 +104,14 @@ public: return this; } +protected: + virtual EdgesDelegate *pull_generic (const Edges &other) const; + virtual RegionDelegate *pull_generic (const Region &other) const; + virtual EdgePairsDelegate *selected_interacting_generic (const Edges &other, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Edges &other, size_t min_count, size_t max_count) const; + virtual EdgePairsDelegate *selected_interacting_generic (const Region &other, EdgePairInteractionMode mode, bool inverse, size_t min_count, size_t max_count) const; + virtual std::pair selected_interacting_pair_generic (const Region &other, EdgePairInteractionMode mode, size_t min_count, size_t max_count) const; + private: DeepEdgePairs &operator= (const DeepEdgePairs &other); diff --git a/src/db/db/dbEdgePairs.cc b/src/db/db/dbEdgePairs.cc index 600d5c709..61e6f9bf6 100644 --- a/src/db/db/dbEdgePairs.cc +++ b/src/db/db/dbEdgePairs.cc @@ -226,12 +226,12 @@ void EdgePairs::second_edges (Edges &output) const void EdgePairs::pull_interacting (Region &output, const Region &other) const { - // @@@ + output = Region (mp_delegate->pull_interacting (other)); } void EdgePairs::pull_interacting (Edges &output, const Edges &other) const { - // @@@ + output = Edges (mp_delegate->pull_interacting (other)); } void EdgePairs::set_delegate (EdgePairsDelegate *delegate) diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index dd5211a1c..24d305359 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -767,6 +767,26 @@ public: */ void second_edges (Edges &output) const; + /** + * @brief Sets the base verbosity + * + * Setting this value will make timing measurements appear at least at + * the given verbosity level and more detailed timing at the given level + * plus 10. The default level is 30. + */ + void set_base_verbosity (int vb) + { + mp_delegate->set_base_verbosity (vb); + } + + /** + * @brief Gets the base verbosity + */ + unsigned int base_verbosity () const + { + return mp_delegate->base_verbosity (); + } + /** * @brief Enable progress reporting * diff --git a/src/db/db/dbEdgePairsDelegate.cc b/src/db/db/dbEdgePairsDelegate.cc index b34ba9c19..710ea4bf5 100644 --- a/src/db/db/dbEdgePairsDelegate.cc +++ b/src/db/db/dbEdgePairsDelegate.cc @@ -30,6 +30,7 @@ namespace db EdgePairsDelegate::EdgePairsDelegate () { + m_base_verbosity = 30; m_report_progress = false; } @@ -43,6 +44,7 @@ EdgePairsDelegate & EdgePairsDelegate::operator= (const EdgePairsDelegate &other) { if (this != &other) { + m_base_verbosity = other.m_base_verbosity; m_report_progress = other.m_report_progress; } return *this; @@ -53,6 +55,11 @@ EdgePairsDelegate::~EdgePairsDelegate () // .. nothing yet .. } +void EdgePairsDelegate::set_base_verbosity (int vb) +{ + m_base_verbosity = vb; +} + void EdgePairsDelegate::enable_progress (const std::string &progress_desc) { m_report_progress = true; diff --git a/src/db/db/dbEdgePairsDelegate.h b/src/db/db/dbEdgePairsDelegate.h index c786838fa..d58ba7661 100644 --- a/src/db/db/dbEdgePairsDelegate.h +++ b/src/db/db/dbEdgePairsDelegate.h @@ -173,6 +173,12 @@ public: return this; } + void set_base_verbosity (int vb); + int base_verbosity () const + { + return m_base_verbosity; + } + void enable_progress (const std::string &progress_desc); void disable_progress (); @@ -254,6 +260,7 @@ protected: private: bool m_report_progress; std::string m_progress_desc; + int m_base_verbosity; }; } diff --git a/src/db/db/dbEdgePairsLocalOperations.cc b/src/db/db/dbEdgePairsLocalOperations.cc new file mode 100644 index 000000000..dc9899f55 --- /dev/null +++ b/src/db/db/dbEdgePairsLocalOperations.cc @@ -0,0 +1,377 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbEdgePairsLocalOperations.h" +#include "dbHierProcessor.h" +#include "dbLocalOperationUtils.h" + +namespace db +{ + +// --------------------------------------------------------------------------------------------- +// EdgePair2EdgeInteractingLocalOperation implementation + +EdgePair2EdgeInteractingLocalOperation::EdgePair2EdgeInteractingLocalOperation (output_mode_t output_mode, size_t min_count, size_t max_count) + : m_output_mode (output_mode), m_min_count (min_count), m_max_count (max_count) +{ + // .. nothing yet .. +} + +db::Coord EdgePair2EdgeInteractingLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void EdgePair2EdgeInteractingLocalOperation::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::EdgePair &subject = interactions.subject_shape (i->first); + scanner.insert1 (&subject, 0); + } + + for (typename std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert2 (o.operator-> (), 1); + } + + if (m_output_mode == Inverse || m_output_mode == Both) { + + std::unordered_set interacting; + edge_pair_to_edge_interaction_filter > filter (&interacting, m_min_count, m_max_count); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + const db::EdgePair &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_pair_to_edge_interaction_filter > filter (&result, m_min_count, m_max_count); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + } +} + +OnEmptyIntruderHint EdgePair2EdgeInteractingLocalOperation::on_empty_intruder_hint () const +{ + return m_output_mode == Both ? CopyToSecond : (m_output_mode == Inverse ? Copy : Drop); +} + +std::string EdgePair2EdgeInteractingLocalOperation::description () const +{ + return tl::to_string (tr ("Select edge pairs interacting edges")); +} + +// --------------------------------------------------------------------------------------------- +// Edge2EdgePullLocalOperation implementation + +EdgePair2EdgePullLocalOperation::EdgePair2EdgePullLocalOperation () +{ + // .. nothing yet .. +} + +db::Coord EdgePair2EdgePullLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void EdgePair2EdgePullLocalOperation::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::EdgePair &subject = interactions.subject_shape (i->first); + scanner.insert1 (&subject, 1); + } + + for (std::set::const_iterator o = others.begin (); o != others.end (); ++o) { + scanner.insert2 (o.operator-> (), 0); + } + + edge_pair_to_edge_interaction_filter > filter (&result, size_t (1), std::numeric_limits::max ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); +} + +OnEmptyIntruderHint EdgePair2EdgePullLocalOperation::on_empty_intruder_hint () const +{ + return Drop; +} + +std::string EdgePair2EdgePullLocalOperation::description () const +{ + return tl::to_string (tr ("Select interacting edges from other")); +} + +// --------------------------------------------------------------------------------------------- +// edge_to_polygon_interacting_local_operation implementation + +template +edge_pair_to_polygon_interacting_local_operation::edge_pair_to_polygon_interacting_local_operation (EdgePairInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count) + : m_mode (mode), m_output_mode (output_mode), m_min_count (min_count), m_max_count (max_count) +{ + // .. nothing yet .. +} + +template +db::Coord edge_pair_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_pair_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::EdgePair &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_pair_to_polygon_interaction_filter > filter (&interacting, m_mode, m_min_count, m_max_count); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + for (typename shape_interactions::iterator i = interactions.begin (); i != interactions.end (); ++i) { + + const db::EdgePair &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_pair_to_polygon_interaction_filter > filter (&result, m_mode, m_min_count, m_max_count); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); + + } +} + +template +OnEmptyIntruderHint edge_pair_to_polygon_interacting_local_operation::on_empty_intruder_hint () const +{ + if (m_mode == EdgePairsOutside) { + 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_pair_to_polygon_interacting_local_operation::description () const +{ + if (m_mode == EdgePairsInteract) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-interacting edge pairs")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select interacting edge pairs")); + } else { + return tl::to_string (tr ("Select interacting and non-interacting edge pairs")); + } + } else if (m_mode == EdgePairsInside) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-inside edge pairs")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select inside edge pairs")); + } else { + return tl::to_string (tr ("Select inside and non-inside edge pairs")); + } + } else if (m_mode == EdgePairsOutside) { + if (m_output_mode == Inverse) { + return tl::to_string (tr ("Select non-outside edge pairs")); + } else if (m_output_mode == Normal) { + return tl::to_string (tr ("Select outside edge pairs")); + } else { + return tl::to_string (tr ("Select outside and non-outside edge pairs")); + } + } + return std::string (); +} + +template class edge_pair_to_polygon_interacting_local_operation; +template class edge_pair_to_polygon_interacting_local_operation; + +// --------------------------------------------------------------------------------------------- +// EdgePair2PolygonPullLocalOperation 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; +}; + +} + +EdgePair2PolygonPullLocalOperation::EdgePair2PolygonPullLocalOperation () +{ + // .. nothing yet .. +} + +db::Coord EdgePair2PolygonPullLocalOperation::dist () const +{ + // touching is sufficient + return 1; +} + +void EdgePair2PolygonPullLocalOperation::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::EdgePair &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_pair_to_polygon_interaction_filter filter (&inserter, EdgePairsInteract, size_t (1), std::numeric_limits::max ()); + scanner.process (filter, 1, db::box_convert (), db::box_convert ()); +} + +OnEmptyIntruderHint EdgePair2PolygonPullLocalOperation::on_empty_intruder_hint () const +{ + return Drop; +} + +std::string EdgePair2PolygonPullLocalOperation::description () const +{ + return tl::to_string (tr ("Select interacting polygons")); +} + +} + diff --git a/src/db/db/dbEdgePairsLocalOperations.h b/src/db/db/dbEdgePairsLocalOperations.h new file mode 100644 index 000000000..a7f6679e5 --- /dev/null +++ b/src/db/db/dbEdgePairsLocalOperations.h @@ -0,0 +1,111 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_dbEdgePairsLocalOperation +#define HDR_dbEdgePairsLocalOperation + +#include "dbCommon.h" + +#include "dbLayout.h" +#include "dbLocalOperation.h" +#include "dbEdgePairsUtils.h" + +namespace db +{ + +/** + * @brief Implements edge pair-to-edge interactions + */ +class DB_PUBLIC EdgePair2EdgeInteractingLocalOperation + : public local_operation +{ +public: + enum output_mode_t { Normal, Inverse, Both }; + + EdgePair2EdgeInteractingLocalOperation (output_mode_t output_mode, size_t min_count, size_t max_count); + + 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: + output_mode_t m_output_mode; + size_t m_min_count, m_max_count; +}; + +/** + * @brief Implements edge pair-to-edge interactions (pull mode) + */ +class DB_PUBLIC EdgePair2EdgePullLocalOperation + : public local_operation +{ +public: + EdgePair2EdgePullLocalOperation (); + + 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 edge_pair_to_polygon_interacting_local_operation + : public local_operation +{ +public: + enum output_mode_t { Normal, Inverse, Both }; + + edge_pair_to_polygon_interacting_local_operation (EdgePairInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count); + + 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: + EdgePairInteractionMode m_mode; + output_mode_t m_output_mode; + size_t m_min_count, m_max_count; +}; + +/** + * @brief Implements edge-to-polygon interactions (pull mode) + */ +class DB_PUBLIC EdgePair2PolygonPullLocalOperation + : public local_operation +{ +public: + EdgePair2PolygonPullLocalOperation (); + + 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/dbEdgePairsUtils.cc b/src/db/db/dbEdgePairsUtils.cc new file mode 100644 index 000000000..a9bf089a9 --- /dev/null +++ b/src/db/db/dbEdgePairsUtils.cc @@ -0,0 +1,92 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbEdgePairsUtils.h" +#include "dbEdgesUtils.h" +#include "dbEdgeProcessor.h" + +namespace db +{ + +static void insert_into_ep (const db::EdgePair &ep, db::EdgeProcessor &proc, size_t prop_id) +{ + proc.insert (db::Edge (ep.first ().p1 (), ep.first ().p2 ()), prop_id); + proc.insert (db::Edge (ep.first ().p2 (), ep.second ().p1 ()), prop_id); + proc.insert (db::Edge (ep.second ().p1 (), ep.second ().p2 ()), prop_id); + proc.insert (db::Edge (ep.second ().p2 (), ep.first ().p1 ()), prop_id); +} + +// NOTE: these predicates are based on the "polygon" interpretation of edge pairs. +// Edge pairs are considered connected and filled. +// This is different from the interpretation of edge pairs as two edges. + +bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b) +{ + db::EdgeProcessor ep; + insert_into_ep (a, ep, 1); + ep.insert (b, 0); + + db::InteractionDetector id (0, 0); + id.set_include_touching (true); + db::EdgeSink es; + ep.process (es, id); + id.finish (); + + return id.begin () != id.end (); +} + +bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b) +{ + db::EdgeProcessor ep; + insert_into_ep (a, ep, 1); + ep.insert (b, 0); + + db::InteractionDetector id (-1, 0); + id.set_include_touching (true); + db::EdgeSink es; + ep.process (es, id); + id.finish (); + + return id.begin () != id.end (); +} + +bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b) +{ + db::EdgeProcessor ep; + insert_into_ep (a, ep, 1); + ep.insert (b, 0); + + db::InteractionDetector id (1, 0); + id.set_include_touching (false); + db::EdgeSink es; + ep.process (es, id); + id.finish (); + + return id.begin () != id.end (); +} + +bool edge_pair_interacts (const db::EdgePair &a, const db::Edge &b) +{ + return edge_interacts (a.first (), b) || edge_interacts (a.second (), b); +} + +} diff --git a/src/db/db/dbEdgePairsUtils.h b/src/db/db/dbEdgePairsUtils.h new file mode 100644 index 000000000..1c4ffe9a0 --- /dev/null +++ b/src/db/db/dbEdgePairsUtils.h @@ -0,0 +1,261 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2024 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_dbEdgePairsUtils +#define HDR_dbEdgePairsUtils + +#include "dbCommon.h" +#include "dbHash.h" +#include "dbEdgePairs.h" +#include "dbBoxScanner.h" +#include "tlSelect.h" + +#include + +namespace db { + +/** + * @brief The operation mode for the interaction filters + */ +enum EdgePairInteractionMode { EdgePairsInteract, EdgePairsInside, EdgePairsOutside }; + +/** + * @brief A predicate defining edge pair a interacts with polygon b + */ +DB_PUBLIC bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b); + +/** + * @brief A predicate defining edge pair a is "inside" polygon b + */ +DB_PUBLIC bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b); + +/** + * @brief A predicate defining edge pair a is "outside" polygon b + */ +DB_PUBLIC bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b); + +/** + * @brief A helper class for the edge pair to region interaction functionality which acts as an edge pair receiver + * + * Note: This special scanner uses pointers to two different objects: edge pairs and polygons. + * It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate + * pointers to edge pairs. + * + * There is a special box converter which is able to sort that out as well. + */ +template +class edge_pair_to_polygon_interaction_filter + : public db::box_scanner_receiver2 +{ +public: + edge_pair_to_polygon_interaction_filter (OutputContainer *output, EdgePairInteractionMode mode, size_t min_count, size_t max_count) + : mp_output (output), m_mode (mode), m_min_count (min_count), m_max_count (max_count) + { + // NOTE: "counting" does not really make much sense in Outside mode ... + m_counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + tl_assert (!m_counting || mode != EdgePairsOutside); + } + + void finish (const OutputType *o) + { + if (m_counting) { + + size_t count = 0; + auto i = m_counts.find (o); + if (i != m_counts.end ()) { + count = i->second; + } + + bool match = (count >= m_min_count && count <= m_max_count); + if (match == (m_mode != EdgePairsOutside)) { + mp_output->insert (*o); + } + + } else { + + if (m_mode == EdgePairsOutside && m_seen.find (o) == m_seen.end ()) { + mp_output->insert (*o); + } + + } + } + + void finish1 (const db::EdgePair *o, size_t /*p*/) + { + const OutputType *ep = 0; + tl::select (ep, o, (const db::Polygon *) 0); + if (ep) { + finish (ep); + } + } + + void finish2 (const db::Polygon *o, size_t /*p*/) + { + const OutputType *ep = 0; + tl::select (ep, (const db::EdgePair *) 0, o); + if (ep) { + finish (ep); + } + } + + void add (const db::EdgePair *e, size_t, const db::Polygon *p, size_t) + { + const OutputType *ep = 0; + tl::select (ep, e, p); + + if (m_counting) { + + if ((m_mode == EdgePairsInteract && db::edge_pair_interacts (*e, *p)) || + (m_mode == EdgePairsInside && db::edge_pair_is_inside (*e, *p)) || + (m_mode == EdgePairsOutside && ! db::edge_pair_is_outside (*e, *p))) { + + // we report the result on "finish" here. + m_counts[ep] += 1; + + } + + } else if (m_seen.find (ep) == m_seen.end ()) { + + if ((m_mode == EdgePairsInteract && db::edge_pair_interacts (*e, *p)) || + (m_mode == EdgePairsInside && db::edge_pair_is_inside (*e, *p))) { + + m_seen.insert (ep); + mp_output->insert (*ep); + + } else if (m_mode == EdgePairsOutside && ! db::edge_pair_is_outside (*e, *p)) { + + // In this case we need to collect edges which are outside always - we report those on "finished". + m_seen.insert (ep); + + } + + } + } + +private: + OutputContainer *mp_output; + std::map m_counts; + std::set m_seen; + EdgePairInteractionMode m_mode; + size_t m_min_count, m_max_count; + bool m_counting; +}; + +/** + * @brief A predicate defining edge pair a interacts with edge b + */ +DB_PUBLIC bool edge_pair_interacts (const db::EdgePair &a, const db::Edge &b); + +/** + * @brief A helper class for the edge pair to region interaction functionality which acts as an edge pair receiver + * + * Note: This special scanner uses pointers to two different objects: edge pairs and polygons. + * It uses odd value pointers to indicate pointers to polygons and even value pointers to indicate + * pointers to edge pairs. + * + * There is a special box converter which is able to sort that out as well. + */ +template +class edge_pair_to_edge_interaction_filter + : public db::box_scanner_receiver2 +{ +public: + edge_pair_to_edge_interaction_filter (OutputContainer *output, size_t min_count, size_t max_count) + : mp_output (output), m_min_count (min_count), m_max_count (max_count) + { + m_counting = !(min_count == 1 && max_count == std::numeric_limits::max ()); + } + + void finish (const OutputType *o) + { + if (m_counting) { + + size_t count = 0; + auto i = m_counts.find (o); + if (i != m_counts.end ()) { + count = i->second; + } + + bool match = (count >= m_min_count && count <= m_max_count); + if (match) { + mp_output->insert (*o); + } + + } + } + + void finish1 (const db::EdgePair *o, size_t /*p*/) + { + const OutputType *ep = 0; + tl::select (ep, o, (const db::Edge *) 0); + if (ep) { + finish (ep); + } + } + + void finish2 (const db::Edge *o, size_t /*p*/) + { + const OutputType *ep = 0; + tl::select (ep, (const db::EdgePair *) 0, o); + if (ep) { + finish (ep); + } + } + + void add (const db::EdgePair *e, size_t, const db::Edge *p, size_t) + { + const OutputType *ep = 0; + tl::select (ep, e, p); + + if (m_counting) { + + if (db::edge_pair_interacts (*e, *p)) { + + // we report the result on "finish" here. + m_counts[ep] += 1; + + } + + } else if (m_seen.find (ep) == m_seen.end ()) { + + if (db::edge_pair_interacts (*e, *p)) { + + m_seen.insert (ep); + mp_output->insert (*ep); + + } + + } + } + +private: + OutputContainer *mp_output; + std::map m_counts; + std::set m_seen; + EdgePairInteractionMode m_mode; + size_t m_min_count, m_max_count; + bool m_counting; +}; + +} // namespace db + +#endif diff --git a/src/db/db/dbEdgesLocalOperations.cc b/src/db/db/dbEdgesLocalOperations.cc index 3572b131c..544758948 100644 --- a/src/db/db/dbEdgesLocalOperations.cc +++ b/src/db/db/dbEdgesLocalOperations.cc @@ -344,7 +344,7 @@ std::string Edge2EdgePullLocalOperation::description () const // --------------------------------------------------------------------------------------------- -// Edge2EdgePullLocalOperation implementation +// edge_to_polygon_interacting_local_operation implementation template edge_to_polygon_interacting_local_operation::edge_to_polygon_interacting_local_operation (EdgeInteractionMode mode, output_mode_t output_mode, size_t min_count, size_t max_count) From c63e41e73249692e67639599ddc63fef2bd9c8c4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Aug 2024 18:37:31 +0200 Subject: [PATCH 3/7] GSI binding --- src/db/db/dbEdgePairs.h | 10 ++ src/db/db/gsiDeclDbEdgePairs.cc | 284 ++++++++++++++++++++++++++++++++ src/db/db/gsiDeclDbEdges.cc | 36 ++-- 3 files changed, 312 insertions(+), 18 deletions(-) diff --git a/src/db/db/dbEdgePairs.h b/src/db/db/dbEdgePairs.h index 24d305359..cc9ddcd3b 100644 --- a/src/db/db/dbEdgePairs.h +++ b/src/db/db/dbEdgePairs.h @@ -217,6 +217,16 @@ public: return mp_delegate; } + /** + * @brief Takes the underlying delegate object + */ + EdgePairsDelegate *take_delegate () + { + EdgePairsDelegate *delegate = mp_delegate; + mp_delegate = 0; + return delegate; + } + /** * @brief Iterator of the edge pair set * diff --git a/src/db/db/gsiDeclDbEdgePairs.cc b/src/db/db/gsiDeclDbEdgePairs.cc index d5edc7cec..780b95442 100644 --- a/src/db/db/gsiDeclDbEdgePairs.cc +++ b/src/db/db/gsiDeclDbEdgePairs.cc @@ -211,6 +211,15 @@ Class > decl_EdgePairToEdg // --------------------------------------------------------------------------------- // EdgePairs binding +static inline std::vector as_2edge_pairs_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::EdgePairs (const_cast (rp.first).take_delegate ())); + res.push_back (db::EdgePairs (const_cast (rp.second).take_delegate ())); + return res; +} + static db::EdgePairs *new_v () { return new db::EdgePairs (); @@ -287,6 +296,40 @@ static db::EdgePairs moved_xy (const db::EdgePairs *r, db::Coord x, db::Coord y) return r->transformed (db::Disp (db::Vector (x, y))); } +static db::Region pull_interacting_polygons (const db::EdgePairs *r, const db::Region &other) +{ + db::Region out; + r->pull_interacting (out, other); + return out; +} + +static db::Edges pull_interacting_edges (const db::EdgePairs *r, const db::Edges &other) +{ + db::Edges out; + r->pull_interacting (out, other); + return out; +} + +static std::vector split_inside_with_region (const db::EdgePairs *r, const db::Region &other) +{ + return as_2edge_pairs_vector (r->selected_inside_differential (other)); +} + +static std::vector split_outside_with_region (const db::EdgePairs *r, const db::Region &other) +{ + return as_2edge_pairs_vector (r->selected_outside_differential (other)); +} + +static std::vector split_interacting_with_edges (const db::EdgePairs *r, const db::Edges &other, size_t min_count, size_t max_count) +{ + return as_2edge_pairs_vector (r->selected_interacting_differential (other, min_count, max_count)); +} + +static std::vector split_interacting_with_region (const db::EdgePairs *r, const db::Region &other, size_t min_count, size_t max_count) +{ + return as_2edge_pairs_vector (r->selected_interacting_differential (other, min_count, max_count)); +} + static db::Region polygons1 (const db::EdgePairs *e) { db::Region r; @@ -1158,6 +1201,247 @@ Class decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs", "enlargement it is possible to give edge pairs an area which otherwise would not have one (coincident edges, " "two point-like edges)." ) + + method ("interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Edges &, size_t, size_t) const) &db::EdgePairs::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 edge pairs from this edge pair collection which overlap or touch edges from the other edge collection\n" + "\n" + "@return A new edge pair collection containing the edge pairs 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 pair of this collection " + "has to interact with (different) edges of the other collection to make the edge pair selected. An edge pair is " + "not selected by this method if the number of edges interacting with an edge pair of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("not_interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Edges &, size_t, size_t) const) &db::EdgePairs::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 edge pairs from this edge pair collection which do not overlap or touch edges from the other edge collection\n" + "\n" + "@return A new edge pair collection containing the edge pairs not 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 pair of this collection " + "has to interact with (different) edges of the other collection to make the edge pair selected. An edge pair is " + "not selected by this method if the number of edges interacting with an edge pair of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Edges &, size_t, size_t)) &db::EdgePairs::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 edge pairs from this edge pair collection which overlap or touch edges from the other edge collection\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_not_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Edges &, size_t, size_t)) &db::EdgePairs::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 edge pairs from this edge pair collection which do not overlap or touch edges from the other edge collection\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + 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 edge pairs from this edge pair collection which do and do not interact with edges from the other collection\n" + "\n" + "@return A two-element list of edge pair 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.29.6.\n" + ) + + method ("interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Region &, size_t, size_t) const) &db::EdgePairs::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 edge pairs from this edge pair collection which overlap or touch polygons from the region\n" + "\n" + "@return A new edge pair collection containing the edge pairs overlapping or touching polygons from the region\n" + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection " + "has to interact with (different) polygons of the other region to make the edge pair selected. An edge pair is " + "not selected by this method if the number of polygons interacting with an edge pair of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("not_interacting", (db::EdgePairs (db::EdgePairs::*) (const db::Region &, size_t, size_t) const) &db::EdgePairs::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 edge pairs from this edge pair collection which do not overlap or touch polygons from the region\n" + "\n" + "@return A new edge pair collection containing the edge pairs not overlapping or touching polygons from the region\n" + "\n" + "'min_count' and 'max_count' impose a constraint on the number of times an edge pair of this collection " + "has to interact with (different) polygons of the other region to make the edge pair selected. An edge pair is " + "not selected by this method if the number of polygons interacting with an edge pair of this collection is between min_count and max_count " + "(including max_count).\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &, size_t, size_t)) &db::EdgePairs::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 edge pairs from this edge pair collection which overlap or touch polygons from the region\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "This is the in-place version of \\interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_not_interacting", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &, size_t, size_t)) &db::EdgePairs::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 edge pairs from this edge pair collection which do not overlap or touch polygons from the region\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "This is the in-place version of \\not_interacting - i.e. self is modified rather than a new collection is returned.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + 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 edge pairs from this edge pair collection which do and do not interact with polygons from the other region\n" + "\n" + "@return A two-element list of edge pair 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.29.6.\n" + ) + + method ("inside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_inside, gsi::arg ("other"), + "@brief Returns the edge pairs from this edge pair collection which are inside (completely covered by) polygons from the region\n" + "\n" + "@return A new edge pair collection containing the edge pairs completely inside polygons from the region\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("not_inside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_not_inside, gsi::arg ("other"), + "@brief Returns the edge pairs from this edge pair collection which are not inside (not completely covered by) polygons from the region\n" + "\n" + "@return A new edge pair collection containing the edge pairs not completely inside polygons from the region\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_inside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_inside, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are inside (completely covered by) polygons from the region\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_not_inside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_not_inside, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are not inside (completely covered by) polygons from the region\n" + "\n" + "@return The edge pair collection after the edge pairs have been selected (self)\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method_ext ("split_inside", &split_inside_with_region, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are and are not inside (completely covered by) polygons from the other region\n" + "\n" + "@return A two-element list of edge pair collections (first: inside, second: non-inside)\n" + "\n" + "This method provides a faster way to compute both inside and non-inside edge pairs compared to using separate methods. " + "It has been introduced in version 0.29.6." + ) + + method ("outside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_outside, gsi::arg ("other"), + "@brief Returns the edge pairs from this edge pair collection which are outside (not overlapped by) polygons from the other region\n" + "\n" + "@return A new edge pair collection containing the the selected edges\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("not_outside", (db::EdgePairs (db::EdgePairs::*) (const db::Region &) const) &db::EdgePairs::selected_not_outside, gsi::arg ("other"), + "@brief Returns the edge pairs from this edge pair collection which are not outside (partially overlapped by) polygons from the other region\n" + "\n" + "@return A new edge pair collection containing the the selected edges\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_outside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_outside, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are outside (not overlapped by) polygons from the other region\n" + "\n" + "@return The edge pair collection after the edges have been selected (self)\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method ("select_not_outside", (db::EdgePairs &(db::EdgePairs::*) (const db::Region &)) &db::EdgePairs::select_not_outside, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are not outside (partially overlapped by) polygons from the other region\n" + "\n" + "@return The edge pair collection after the edges have been selected (self)\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method_ext ("split_outside", &split_outside_with_region, gsi::arg ("other"), + "@brief Selects the edge pairs from this edge pair collection which are and are not outside (not overlapped by) polygons from the other region\n" + "\n" + "@return A two-element list of edge pair collections (first: outside, second: non-outside)\n" + "\n" + "This method provides a faster way to compute both outside and non-outside edges compared to using separate methods. " + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method_ext ("pull_interacting", &pull_interacting_edges, gsi::arg ("other"), + "@brief Returns all edges of \"other\" which are interacting with (overlapping, touching) edge pairs of this set\n" + "The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they " + "select shapes from the argument region rather than self. In a deep (hierarchical) context " + "the output region will be hierarchically aligned with self, so the \"pull_...\" methods " + "provide a way for re-hierarchization.\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "@return The edge collection after the edges have been selected (from other)\n" + "\n" + "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + + method_ext ("pull_interacting", &pull_interacting_polygons, gsi::arg ("other"), + "@brief Returns all polygons of \"other\" which are interacting with (overlapping, touching) edge pairs of this set\n" + "The \"pull_...\" methods are similar to \"select_...\" but work the opposite way: they " + "select shapes from the argument region rather than self. In a deep (hierarchical) context " + "the output region will be hierarchically aligned with self, so the \"pull_...\" methods " + "provide a way for re-hierarchization.\n" + "\n" + "Edge pairs are considered 'filled' in the context of this operation - i.e. the area between the edges belongs to " + "the edge pair, hence participates in the check.\n" + "\n" + "@return The region after the polygons have been selected (from other)\n" + "\n" + "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" + "\n" + "This method has been introduced in version 0.29.6\n" + ) + method ("clear", &db::EdgePairs::clear, "@brief Clears the edge pair collection\n" ) + diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index 8e983164a..6d86681e5 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -1366,14 +1366,14 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", 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" "\n" - "@return A new edge collection containing the edges overlapping or touching edges from the other edge collection\n" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("not_inside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_not_inside, gsi::arg ("other"), "@brief Returns the edges of this edge collection which are not inside (completely covered by) 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" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + @@ -1402,14 +1402,14 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", method ("inside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_inside, gsi::arg ("other"), "@brief Returns the edges from this edge collection which are inside (completely covered by) polygons from the region\n" "\n" - "@return A new edge collection containing the edges overlapping or touching polygons from the region\n" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("not_inside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_not_inside, gsi::arg ("other"), "@brief Returns the edges from this edge collection which are not inside (completely covered by) polygons from the region\n" "\n" - "@return A new edge collection containing the edges not overlapping or touching polygons from the region\n" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + @@ -1436,35 +1436,35 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "It has been introduced in version 0.28." ) + method ("outside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_outside, gsi::arg ("other"), - "@brief Returns the edges of this edge collection which are outside (completely covered by) edges from the other edge collection\n" + "@brief Returns the edges of this edge collection which are outside (not overlapped by) 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" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("not_outside", (db::Edges (db::Edges::*) (const db::Edges &) const) &db::Edges::selected_not_outside, gsi::arg ("other"), - "@brief Returns the edges of this edge collection which are not outside (completely covered by) edges from the other edge collection\n" + "@brief Returns the edges of this edge collection which are not outside (partially overlapped by) 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" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("select_outside", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_outside, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are outside (completely covered by) edges from the other edge collection\n" + "@brief Selects the edges from this edge collection which are outside (not overlapped by) edges from the other edge collection\n" "\n" "@return The edge collection after the edges have been selected (self)\n" "\n" "This method has been introduced in version 0.28." ) + method ("select_not_outside", (db::Edges &(db::Edges::*) (const db::Edges &)) &db::Edges::select_not_outside, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are not outside (completely covered by) edges from the other edge collection\n" + "@brief Selects the edges from this edge collection which are not outside (partially overlapped by) edges from the other edge collection\n" "\n" "@return The edge collection after the edges have been selected (self)\n" "\n" "This method has been introduced in version 0.28." ) + method_ext ("split_outside", &split_outside_with_edges, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are and are not outside (completely covered by) edges from the other collection\n" + "@brief Selects the edges from this edge collection which are and are not outside (not overlapped by) edges from the other collection\n" "\n" "@return A two-element list of edge collections (first: outside, second: non-outside)\n" "\n" @@ -1472,35 +1472,35 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "It has been introduced in version 0.28." ) + method ("outside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_outside, gsi::arg ("other"), - "@brief Returns the edges from this edge collection which are outside (completely covered by) polygons from the region\n" + "@brief Returns the edges from this edge collection which are outside (not overlapped by) polygons from the region\n" "\n" - "@return A new edge collection containing the edges overlapping or touching polygons from the region\n" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("not_outside", (db::Edges (db::Edges::*) (const db::Region &) const) &db::Edges::selected_not_outside, gsi::arg ("other"), - "@brief Returns the edges from this edge collection which are not outside (completely covered by) polygons from the region\n" + "@brief Returns the edges from this edge collection which are not outside (partially overlapped by) polygons from the region\n" "\n" - "@return A new edge collection containing the edges not overlapping or touching polygons from the region\n" + "@return A new edge collection containing the the selected edges\n" "\n" "This method has been introduced in version 0.28." ) + method ("select_outside", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_outside, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are outside (completely covered by) polygons from the region\n" + "@brief Selects the edges from this edge collection which are outside (not overlapped by) polygons from the region\n" "\n" "@return The edge collection after the edges have been selected (self)\n" "\n" "This method has been introduced in version 0.28." ) + method ("select_not_outside", (db::Edges &(db::Edges::*) (const db::Region &)) &db::Edges::select_not_outside, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are not outside (completely covered by) polygons from the region\n" + "@brief Selects the edges from this edge collection which are not outside (partially overlapped by) polygons from the region\n" "\n" "@return The edge collection after the edges have been selected (self)\n" "\n" "This method has been introduced in version 0.28." ) + method_ext ("split_outside", &split_outside_with_region, gsi::arg ("other"), - "@brief Selects the edges from this edge collection which are and are not outside (completely covered by) polygons from the other region\n" + "@brief Selects the edges from this edge collection which are and are not outside (not overlapped by) polygons from the other region\n" "\n" "@return A two-element list of edge collections (first: outside, second: non-outside)\n" "\n" From 29f82854fbd790003b94377758f83d5979328887 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Aug 2024 19:23:31 +0200 Subject: [PATCH 4/7] Fixed DRC update --- src/db/db/dbHierProcessor.cc | 33 ++++++++++++++++ src/db/db/dbLocalOperation.cc | 6 +++ src/drc/drc/built-in-macros/_drc_layer.rb | 47 ++++++++++++++--------- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index c5d123d7c..a6d42449b 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -2558,6 +2558,12 @@ template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; +template class DB_PUBLIC local_processor_cell_context; // explicit instantiations template class DB_PUBLIC local_processor_cell_contexts; @@ -2581,6 +2587,12 @@ template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; +template class DB_PUBLIC local_processor_cell_contexts; // explicit instantiations template class DB_PUBLIC shape_interactions; @@ -2598,6 +2610,9 @@ template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; +template class DB_PUBLIC shape_interactions; // explicit instantiations template class DB_PUBLIC local_processor_context_computation_task; @@ -2629,6 +2644,12 @@ template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; +template class DB_PUBLIC local_processor_context_computation_task; // explicit instantiations template class DB_PUBLIC local_processor_result_computation_task; @@ -2652,6 +2673,12 @@ template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; +template class DB_PUBLIC local_processor_result_computation_task; // explicit instantiations template class DB_PUBLIC local_processor; @@ -2683,6 +2710,12 @@ template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; +template class DB_PUBLIC local_processor; } diff --git a/src/db/db/dbLocalOperation.cc b/src/db/db/dbLocalOperation.cc index 24b7f4786..bec8d0cd1 100644 --- a/src/db/db/dbLocalOperation.cc +++ b/src/db/db/dbLocalOperation.cc @@ -106,6 +106,12 @@ template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; +template class DB_PUBLIC local_operation; } diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index b06b04e77..f14d74b7a 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -2813,13 +2813,14 @@ CODE requires_region other.requires_region else - requires_edges_texts_or_region - if self.data.is_a?(RBA::Text) + if self.data.is_a?(RBA::Texts) other.requires_region elsif self.data.is_a?(RBA::Region) other.requires_edges_texts_or_region - else + elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) other.requires_edges_or_region + else + raise("Invalid data type of primary layer") end end @@ -2837,11 +2838,13 @@ CODE @engine._context("#{f}") do - requires_edges_or_region + check_is_layer(other) if self.data.is_a?(RBA::Edges) other.requires_edges_or_region - else + elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) other.requires_region + else + raise("Invalid data type of primary layer") end DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data)) @@ -2913,12 +2916,14 @@ CODE @engine._context("#{f}") do check_is_layer(other) - if self.data.is_a?(RBA::Text) + if self.data.is_a?(RBA::Texts) other.requires_region elsif self.data.is_a?(RBA::Region) other.requires_edges_texts_or_region - else + elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) other.requires_edges_or_region + else + raise("Invalid data type of primary layer") end DRCLayer::new(@engine, @engine._tcmd(self.data, 0, self.data.class, :#{f}, other.data, *minmax_count(*args))) @@ -2938,13 +2943,14 @@ CODE @engine._context("#{f}") do check_is_layer(other) - requires_edges_texts_or_region - if self.data.is_a?(RBA::Text) + if self.data.is_a?(RBA::Texts) other.requires_region elsif self.data.is_a?(RBA::Region) other.requires_edges_texts_or_region - else + elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) other.requires_edges_or_region + else + raise("Invalid data type of primary layer") end if @engine.is_tiled? @@ -2985,11 +2991,13 @@ CODE @engine._context("#{f}") do check_is_layer(other) - requires_edges_or_region - if self.data.is_a?(RBA::Edges) - other.requires_edges_or_region - elsif self.data.is_a?(RBA::Region) + if self.data.is_a?(RBA::Region) other.requires_edges_texts_or_region + elsif self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) + other.requires_edges_or_region + else + # Note: there is no "split" for Texts yet. + raise("Invalid data type of primary layer") end res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args)) @@ -3088,11 +3096,13 @@ CODE @engine._context("#{f}") do - requires_edges_or_region + check_is_layer(other) if self.data.is_a?(RBA::Edges) other.requires_edges_or_region - else + elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) other.requires_region + else + raise("Invalid data type of primary layer") end if @engine.is_tiled? @@ -3115,11 +3125,12 @@ CODE @engine._context("#{f}") do check_is_layer(other) - requires_edges_or_region if self.data.is_a?(RBA::Edges) other.requires_edges_or_region - elsif self.data.is_a?(RBA::Region) + elsif self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) other.requires_region + else + raise("Invalid data type of primary layer") end res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data, *minmax_count(*args)) From 35219469d6987246602c4db2d935e27f1fd4d10d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Aug 2024 21:03:19 +0200 Subject: [PATCH 5/7] Debugging and first tests for DRC --- src/db/db/dbEdgePairsUtils.cc | 21 +++- src/drc/unit_tests/drcSimpleTests.cc | 10 ++ testdata/drc/drcSimpleTests_131.drc | 146 +++++++++++++++++++++++++ testdata/drc/drcSimpleTests_131.gds | Bin 0 -> 3278 bytes testdata/drc/drcSimpleTests_au131.gds | Bin 0 -> 60682 bytes testdata/drc/drcSimpleTests_au131d.gds | Bin 0 -> 30926 bytes 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 testdata/drc/drcSimpleTests_131.drc create mode 100644 testdata/drc/drcSimpleTests_131.gds create mode 100644 testdata/drc/drcSimpleTests_au131.gds create mode 100644 testdata/drc/drcSimpleTests_au131d.gds diff --git a/src/db/db/dbEdgePairsUtils.cc b/src/db/db/dbEdgePairsUtils.cc index a9bf089a9..de7ec803d 100644 --- a/src/db/db/dbEdgePairsUtils.cc +++ b/src/db/db/dbEdgePairsUtils.cc @@ -41,6 +41,12 @@ static void insert_into_ep (const db::EdgePair &ep, db::EdgeProcessor &proc, siz bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b) { + // fall back to edge-only checks for degenerate edge pairs + if (a.area () == 0) { + return edge_interacts (a.first (), b) || edge_interacts (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) || + edge_interacts (a.second (), b) || edge_interacts (db::Edge (a.second ().p2 (), a.first ().p1 ()), b); + } + db::EdgeProcessor ep; insert_into_ep (a, ep, 1); ep.insert (b, 0); @@ -56,6 +62,12 @@ bool edge_pair_interacts (const db::EdgePair &a, const db::Polygon &b) bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b) { + // fall back to edge-only checks for degenerate edge pairs + if (a.area () == 0) { + return edge_is_inside (a.first (), b) && edge_is_inside (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) && + edge_is_inside (a.second (), b) && edge_is_inside (db::Edge (a.second ().p2 (), a.first ().p1 ()), b); + } + db::EdgeProcessor ep; insert_into_ep (a, ep, 1); ep.insert (b, 0); @@ -71,6 +83,12 @@ bool edge_pair_is_inside (const db::EdgePair &a, const db::Polygon &b) bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b) { + // fall back to edge-only checks for degenerate edge pairs + if (a.area () == 0) { + return edge_is_outside (a.first (), b) && edge_is_outside (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) && + edge_is_outside (a.second (), b) && edge_is_outside (db::Edge (a.second ().p2 (), a.first ().p1 ()), b); + } + db::EdgeProcessor ep; insert_into_ep (a, ep, 1); ep.insert (b, 0); @@ -86,7 +104,8 @@ bool edge_pair_is_outside (const db::EdgePair &a, const db::Polygon &b) bool edge_pair_interacts (const db::EdgePair &a, const db::Edge &b) { - return edge_interacts (a.first (), b) || edge_interacts (a.second (), b); + return edge_interacts (a.first (), b) || edge_interacts (db::Edge (a.first ().p2 (), a.second ().p1 ()), b) || + edge_interacts (a.second (), b) || edge_interacts (db::Edge (a.second ().p2 (), a.first ().p1 ()), b); } } diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index a561ad241..902e12200 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1953,3 +1953,13 @@ TEST(130d_size_inside_outside) { run_test (_this, "130", true); } + +TEST(131_edge_pair_interactions) +{ + run_test (_this, "131", false); +} + +TEST(131d_edge_pair_interactions) +{ + run_test (_this, "131", true); +} diff --git a/testdata/drc/drcSimpleTests_131.drc b/testdata/drc/drcSimpleTests_131.drc new file mode 100644 index 000000000..bf487b5ff --- /dev/null +++ b/testdata/drc/drcSimpleTests_131.drc @@ -0,0 +1,146 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l2 = input(2, 0) +l3 = input(3, 0) +l4 = input(4, 0) +l5 = input(5, 0) +l6 = input(6, 0) + +l1.output(1, 0) +l2.output(2, 0) +l3.output(3, 0) +l4.output(4, 0) +l5.output(5, 0) +l6.output(6, 0) + +eps = l1.sep(l2, 200.nm) + +eps.output(10, 0) + +l = 100 +eps.interacting(l3).output(l + 0, 0) +eps.interacting(l4).output(l + 1, 0) +eps.interacting(l5).output(l + 2, 0) +eps.interacting(l6).output(l + 3, 0) + +l = 110 +eps.interacting(l3, 1..1).output(l + 0, 0) +eps.interacting(l4, 1..1).output(l + 1, 0) +eps.interacting(l5, 1..1).output(l + 2, 0) +eps.interacting(l6, 1..1).output(l + 3, 0) + +l = 120 +eps.interacting(l3, 2).output(l + 0, 0) +eps.interacting(l4, 2).output(l + 1, 0) +eps.interacting(l5, 2).output(l + 2, 0) +eps.interacting(l6, 2).output(l + 3, 0) + +l = 130 +eps.not_interacting(l3).output(l + 0, 0) +eps.not_interacting(l4).output(l + 1, 0) +eps.not_interacting(l5).output(l + 2, 0) +eps.not_interacting(l6).output(l + 3, 0) + +l = 140 +eps.interacting(l3.edges).output(l + 0, 0) +eps.interacting(l4.edges).output(l + 1, 0) +eps.interacting(l5.edges).output(l + 2, 0) +eps.interacting(l6.edges).output(l + 3, 0) + +l = 150 +eps.interacting(l3.edges, 1 .. 1).output(l + 0, 0) +eps.interacting(l4.edges, 1 .. 1).output(l + 1, 0) +eps.interacting(l5.edges, 1 .. 1).output(l + 2, 0) +eps.interacting(l6.edges, 1 .. 1).output(l + 3, 0) + +l = 160 +eps.interacting(l3.edges, 2).output(l + 0, 0) +eps.interacting(l4.edges, 2).output(l + 1, 0) +eps.interacting(l5.edges, 2).output(l + 2, 0) +eps.interacting(l6.edges, 2).output(l + 3, 0) + +l = 170 +eps.not_interacting(l3.edges).output(l + 0, 0) +eps.not_interacting(l4.edges).output(l + 1, 0) +eps.not_interacting(l5.edges).output(l + 2, 0) +eps.not_interacting(l6.edges).output(l + 3, 0) + +l = 180 +eps.split_interacting(l3, 1..1)[0].output(l + 0, 0) +eps.split_interacting(l4, 1..1)[0].output(l + 1, 0) +eps.split_interacting(l5, 1..1)[0].output(l + 2, 0) +eps.split_interacting(l6, 1..1)[0].output(l + 3, 0) + +l = 190 +eps.split_interacting(l3, 1..1)[1].output(l + 0, 0) +eps.split_interacting(l4, 1..1)[1].output(l + 1, 0) +eps.split_interacting(l5, 1..1)[1].output(l + 2, 0) +eps.split_interacting(l6, 1..1)[1].output(l + 3, 0) + +l = 200 +eps.split_interacting(l3.edges, 1..1)[0].output(l + 0, 0) +eps.split_interacting(l4.edges, 1..1)[0].output(l + 1, 0) +eps.split_interacting(l5.edges, 1..1)[0].output(l + 2, 0) +eps.split_interacting(l6.edges, 1..1)[0].output(l + 3, 0) + +l = 210 +eps.split_interacting(l3.edges, 1..1)[1].output(l + 0, 0) +eps.split_interacting(l4.edges, 1..1)[1].output(l + 1, 0) +eps.split_interacting(l5.edges, 1..1)[1].output(l + 2, 0) +eps.split_interacting(l6.edges, 1..1)[1].output(l + 3, 0) + +l = 300 +eps.inside(l3).output(l + 0, 0) +eps.inside(l4).output(l + 1, 0) +eps.inside(l5).output(l + 2, 0) +eps.inside(l6).output(l + 3, 0) + +l = 310 +eps.not_inside(l3).output(l + 0, 0) +eps.not_inside(l4).output(l + 1, 0) +eps.not_inside(l5).output(l + 2, 0) +eps.not_inside(l6).output(l + 3, 0) + +l = 320 +eps.split_inside(l3)[0].output(l + 0, 0) +eps.split_inside(l4)[0].output(l + 1, 0) +eps.split_inside(l5)[0].output(l + 2, 0) +eps.split_inside(l6)[0].output(l + 3, 0) + +l = 330 +eps.split_inside(l3)[1].output(l + 0, 0) +eps.split_inside(l4)[1].output(l + 1, 0) +eps.split_inside(l5)[1].output(l + 2, 0) +eps.split_inside(l6)[1].output(l + 3, 0) + +l = 400 +eps.outside(l3).output(l + 0, 0) +eps.outside(l4).output(l + 1, 0) +eps.outside(l5).output(l + 2, 0) +eps.outside(l6).output(l + 3, 0) + +l = 410 +eps.not_outside(l3).output(l + 0, 0) +eps.not_outside(l4).output(l + 1, 0) +eps.not_outside(l5).output(l + 2, 0) +eps.not_outside(l6).output(l + 3, 0) + +l = 420 +eps.split_outside(l3)[0].output(l + 0, 0) +eps.split_outside(l4)[0].output(l + 1, 0) +eps.split_outside(l5)[0].output(l + 2, 0) +eps.split_outside(l6)[0].output(l + 3, 0) + +l = 430 +eps.split_outside(l3)[1].output(l + 0, 0) +eps.split_outside(l4)[1].output(l + 1, 0) +eps.split_outside(l5)[1].output(l + 2, 0) +eps.split_outside(l6)[1].output(l + 3, 0) + diff --git a/testdata/drc/drcSimpleTests_131.gds b/testdata/drc/drcSimpleTests_131.gds new file mode 100644 index 0000000000000000000000000000000000000000..3b5f8d0c601b67d5240a0f817495bbdb7245d541 GIT binary patch literal 3278 zcma);PiPcp7{=e7ot>Q|n>DRwt#v^ULZw}zNKg}sBrz0=q9Qp+C|Y{xsYj6Gf z%Au5EMRE`o4@Eqb97++9Af8GIQi6CWJ>(>U|HWi{o_XiZH#6jm>fyKh%=hg3e$V&L zWF(RxI4%|~#6fiE>oJiH)!M$%^Lq}?U3)S#KD%S)x5)`<*ZjUH zir@-kk*GJ2szl8|L^^%dBzf_rNTs6;{!EgWp@`A+N=L$vJpQHY>L=-2o_C~QulxKW z^Eize4?`ar%)HSUrZlOgoxh^4DDdBHe$%|BEtsEYjOz|4P%r zw0>RQHzlL)lq*@4ZGBao&fn`P>&zqD`cGo|TR@PVhYA1iw>Vjo91pLl&B75s1WTzY0Tj}p`0RR_lUgB|agk2s1Z zjvQU-1zkm-R_V%ZNyc zIY&8x(n@pY9OW9#QzEj#k? zcoMYEW>nqp!+qFw6609@Y zBmLQRuRlbZUEiWU*fW742pmlZy?#FBxQ?X1Z?~iACBNO@nm2OZK7+iF?-#c<@ASLs z`MO0Pa;{BbJ@Soz)x6X1s;}l-$(wgUn)^1*yOYs$(CcTOoTn_;G;ik2+)W3)e&$@q z;F0lL&D&@?==C$_IUZ(Cg=Ha~(-v?*T{C z*YfxO4*!Tq$}2dx>-cUoeZ*fsLT%O|SwDKu-(2e;@k>y9Puy?sGI9^!oXh!#X7E^URH=m+I%EYTlYHaryXZ)Nc0KPeyd`ehh5b*7kj#Da1xM3CzyBWU W;~BjP@daX#;5)Sj zu{DUASfn4)BCUc(5z}fkYK%lFK|w^M#rU#HG>E!VBv=tY_$B$!>w3<)a?Wq?e#rlS zKFB|FKj%01Ip;a|@4B9QX4Y=KTUmKkcWB4TuHSYW-DBb-UtxD{DNm$#2GW<#CzG?fK!DHNK2r z{dK%AuaEg7&%L3Ghi1$gk8IArb)e@nliz!C%;bmHoBSoi+?hG|vEdvt^PGm)m-0DB z9+z_`S6SncO@8%D@tk}$=8DW`X4ivb)_7!--;8H6kIPJc@9LN}zKmbHC7!n{yDszS zrEw49d9SST$maZ8clUf|a(n-K%;bmHoBZmv@!b9-u0QhX@5S}MdCVG*Z1S78_IzgY zd+r=F`Qh~`zXG4ce3u53UU~XABjfulzV64{T)ajeJUC{JM>gkAk6aMzpuCbkNsnaKcx02$HE{96 z{aQF2bLZNqtntVupT2nNbK@E#(;xYaSJrrBlTVMFjAw7*m3Q{<<*6ZSJhI7e#`-@Q z?^9;_BYjd?HNI^AwHNm9dFDBn_TQ&6pM~M|_Vvg5&*Rbq z$!+~&%o>ku^69IM@Acl=eMR{0IkA3+tntVuzaIB0=gG|ZbIn)Q__Fzrex$#~%)E!` z`O3WZ;q~VH`FdV^W?p;pl{FsON`1zZvT;kIPIxJy2QWkxl-<1>viU;~r$bKdyaqk~MyD zn_qutKYwP@XN}7~D)aKFKWm>Gv&JKv^KZVq=QESv zde4~253e`*{l5(UkMW*Go_J+{A1Z4+vdOPMx1T>V=g*#@GUp#&pYp3y|L^=-*IgCw zedg&0gOC4J)_7!--~Z&``@{t~>vkW7haGe&=sv{r_{U z-^k0~ALqX^W{pQS=imR5;9nE>Jo3cv;{LyV%o>ku^5;I%^O=|bZ`}WrVZ$jdA}ki}@q-{Xh6$ zW7c@&ls{*B|1W$;JbyRG`~J3gZsR>zN`d(WpPS>tEg{OU{N_*mv}Y;m^kXzBl;Hxc__CCRyY6w)tHDdG48c?#I49W{pQS&wp!wTyOlG zXOVIJd#~!Re~~r*x;CHlCYzZ|{=BEM#v`Zm-#GQZ;Scf;#r10b0-xudjuZR|-tag0 ztT$r)AfI(gt6$`wAL~u?7kS;E*zI!6;i%%P->Ckh z`jKt@2YADu;0=F+H|huYx$EEXC+1&xt336@`~^PGzdZQ_{Rw{I?RzDEgJ0CGqf-4M zAMUR@^#tn|dA{+qn+fAYG&$?N_mulpOk;cxP~zrh>z8@%Cv@P>cE8~z1v_!qq4Pw<9+ z-Zs-eW!vc%%OWZ}gww z4gY~R{0H9fANV|fasL6l;ZN{J|4Cl&KgsL;CwRmEw@m$S{QLpD@%(}}?mzkbxlR3? z=DsKN^BeN|`v=~5em^k1|Hl45dAMwb{{*u@0FL}NGlGp1mdAMwYs{(?9B1>UH?;EnnV-l)Ie=laX2znI_fKY88XKAz9_kYOizyCvC_cwXHevsGe7kRyYf}gv741Z&O zqke!l>KAyU|0b{h{ttQGpWu!9MgFY(`#<1~`UT#opWu!9|BH+kKE z1fH&#~dENiy z_4)(es2}9@`T^dkAK;Dt<)c&o8=s%R8_zHJx#w>@|Crx+|H;2Eet+|f^!wL$PVc`_ zf598|m%Lto$?Nr#yk5V_>-CqsUVq8!^%uNRKgsL$6a3=uEb8|k>hC3fy7ccaz#H`! zyitF_8}*mGzW+jAuV3W#`UT#oAD^H4$JqZTudjdb#`6Q-@F#d<|DU|R|4&}`7kRyZ zC$Ia9yzWo%#{NHfeg7Z4(f@)s`~%+bA9$nx0&ny`;EnzZ{9Jz-{VV1-_W#N2{wJ^3 zAMi&1eD_TMlh^$Z-ta$o!~ft7|C87KPhR&wdENiyb^nvs{SV&oKY88%;0^zSH~bIY z@IQFN|KJV(gE#yS-ta$o!~ft7|C87KPhR&wc*Fl+nEK!N{7GK_{0ZLJzaX#gUw}92 z2Y91?fj55sOJ3hUA+P(Jyk0-Z>-CGgUO&OlT|b7uF~3niz#H`oys>{zUf;hUulp0c zQNPHam4E&V-l$*Tjrs}RsQ+J``rp|9A+PuU;0=F*H~bCW`1>#NdjC&e_aAxPzvOlQ zgE#tj@_PRc-uV0m-tZ^*x$DpH7v?wo0p94J!5j7SzM1|ZulonQ;UDmZf502hFL~WR zcD8~r1Aqkjc&_z%3{Kk$bCz~}jkfByyE@F#d< z|AD;TKa-CqsUVq8!^_RR}f643h7raq_$?NqOyitF_8}%2w;V2I@_PLuuh&oTbJvgIZ_IDh5Aa6)0&n!+mPaj z^TUs3`iH#kAMl2Mz#Hoiyz%^!*Zo6Y?_bI5{v@yakG%f*0lcyQLtfwi0dMp_;0=F) zH~a(M=s&<4{WEx@e*$m#8@$m!f;aq4UiUZonf^BV?;p?fKY88%;0^zSH~bIY@IQIo z|KxT5lh^%EUiUwF-T&YX|C87K58m)Uc*FnT4gZ5T{14vnKX}9c;0^zSH~bIY@IQIo z|KxT5gE#ztX6k?A^CNlv^CNg;|DU|R{}0}%AK;Dp1>V^IC$I1Slh^%CUaueI_4-9# zub<%Ot{=nSnBS-$;EnnP-q`;qukZhp*Zm3Js9)su{eSRA{Q_^)Pw;yE-*NfW|N8#( zHeT-k$?N_kult+4-v4jo<^F#gFZ*j7FZ**FFZ+8NFV_$9djG$Tm-~P6x;5ON`=7k-fAYHj$?N_HZ}^|Q?tk!x|G^vn2XFWvyy1WFhX27E{s(XPAH3mz@P_}% z>;5ON`yagF|5G#lPhR&wc*FnT4gZ5T{7+u@KY88%kjH}>y1zwU4Hdi@};*DvyV{RBUE{TTkn{6_r%Z`3dF`u;zk zKf|A#U-u_?qkfS;tN!~xynds8VSb~2f;Z~_^QQhc{6Svt|G^vn1aJ5oywU%Y*ZY6+ zy1&Tl{v@yao4j5>z#IKPdA;4CC_#eFCfAEI?!5jVuZ}=a);eYUk|G^vn2XFYF zyzYPUy8po&{(srj|Hl45d42yMys`gJUf=%*Z`2R)M*RYB?EjOOfB%06dEMXS_4+|x zuV3W#`U!sS`Z4^C`HlJk-l$*Tjs1V}^6&ri`OANMb>q?g-(cPShWPKDT~}G-k*nv& zAsbz{zO_Q$s9!jLqke!l>KAyUeu6jZ{~c5R8~gv{_5L5c;ZN{}zrh>*KY6|XC$Ia9 zyzWo(y1&Wm^#i=o|C87IfAEGs!5jVtZ`2R)bJxG&Pt0%l3%ub^@P@y^8~s0dy?&9` z`+x98|MD+W{~P^3dA-7`- z-1TGl8}l3W1H4hcz#IKPdAsQU5xS$?N_muh$RoM*mM<@BhIY{seFM8@y3Jz|UR(hCeaC z;VIZnEet|dk z|HVISZpS<4xgE#yM-taegqyHzb_y6Q|f05VyNnZCidA)vsH~N3_ zdjAjJ@F#e~-{6h<0eg3{~voqhJ4y{5cfY;9^__EX?mctEAauLm4hx;`(Z{8IaCfd2dV6Z)e{xF2WOxGTDFxw3wTt3$eVe*X-I;TyK*d1Or zJy~m9?|U_K%_%7`G zNW4$Ae`6<4*1yN~yl&#^eUCU|q;`+U>xyUFyArvIw-OuhbvmD}5S=MtappZN56o7(D|?>`&=NUdkg|A+Q_(zO0a zJAZDy-T$=tceT15+rx^c_0z!LUg#fr-hakR{(%?#-%;ovdES4z? z#@BP3=5%fIdw1dfk>~fH@lt-k3;FG7{7d!kZTOY*8*~0cp6_4Am+oJhpZf~^BhUNK zc*#HT!u&j3=pT9Bf5uDxffxMmZTw5~v)u5~@q;|yzl@jq_v^y_BhT+Y<4gB1<@Z9N zf8=@p887(4KX?|ZV+&}XC{xe?64|pNJgN=Ww z{-K7K&fm!M{mb~${Y&$6xX?fHy#I`s`~xq{&(X%e)W2g5FU=3~eE%|D>fiCg{Ugus zKjTaHFXeZl&_D9L|BRRX124?~TZR6S=ly5A4K$v^Od{~HSZBhUNKc*#HTg8#<~{Ugu&&v?l{@Phxx z3;iR{`_FjEKk$P8eTDv!=ly5A~wqyyPEv!T)oG{*mYXXT0Pec)|bk zh5nJ}{b#)7A9%t4{zCuA^Zqkl@(;Y=|D{6z$n*X)Uh)q-<9{+-=&CHcmMdMA)oZ#m z8vXk#c2&({)b8&_qYwHaBu(pf#Z-Qk5bz)WGV-p@ojcK}^YQjJ-ri;0X8i72Uk_pU zW&1s8THoEq+kW@O`mSF8>~|aW`tf$)`?>!!)|l{-rDfWEZ#4SwmPXTh_^6E!VeqW+ zN2A&`bz%4i<7-Xprg{IM{>M9AHk#JQ_=#r!Axs@Kes9$7dm+rs`~IV* zbp{I z_F}t&NA6u3!tC3&AJl9wMhq_LSZAgeCa%5N)c?U_Z2DsC^O$CjG2Vd<%OQO3nh?fx z6=L?D5H|nA_KKPj<2@UD>{M$NV)nTZHa%fAP%C0+U9hV#v*XoT`f>B`HlOHw=Py{$IiT+H?}5C>({i`A6N~qunHzZoW;Yu85D5G_9Mq?tl8Xk#}`&=5LKUU*F!!&)aeC=LpwzSB7x$)s3cg z(^lTkH(tlp>rZ~K(X>9c|LlBYGyhr$TmBk#=?&xUf6}yWn%4(@!?xgkUR=dCL*^lx0cWaI7=i{nRA^JbD zdJkG&rdR&R=I!Z5)4FLZ@5hth&(--2#~MxRtMPq1|E~Lv)i+(gEA}pFS~qR2@6V@x zKUe4GHaD8q$M|#=c!z)|_t~FMQs2Gb-e=deZraLwpC^a0-^2gLekV=qrmej9+0SXI z@7{0kvuj#6&H1VP_0arZtma2<;yUq2wvzkazluP?m*L!O^M~SA zp3fh7K7Zha{E_GL2VTe@cp?9X3-d>w&mVa{f8_c6ffw>ep3fin()@(^*_-Dt)CXRu zzns?>o_~<%=MQ;){*dSA4|rkzkmu(w`>Q*9e}#Yl2YJ5#$n*V2p6@^KLjRF3?7wjQ zKz-r(eWCF9L!Qqcc|L#S`TT(w@<*P}A9x{u;D!8OEX*HyK7Zu-{E_GL2VTe@c|L#O zh5UgR@_(f;f8_c6k>~SAp3fh6q5r@O{eQKv|H$+GN1pFL@_he+7mh#V`Qs0GA%Eb7 z{IkDWu0MB5pEIrP^C#qa|Az|a4|#t6kmu(Qd4B$Y7v>N7!u|{M2la*dJ6xDQ@_hct z^Z6ss=MTJ)Kk|J3zzg{UFXW&7)qDN9bNZZlZJ$2_FVsI)IDg3V^M^b?f5`Lm2fQ$U z$n*1eys-bs^ZiGj??3W<|A80!k9=YOh2tOU3&-Dy!u*lv^GBY~A9+51;D!8==ko_% z$RBti|F;VBN1o3gc|L#S`TT(w@<*P}A9x{u;Q9RXZ;epi{~hD${Kt4Y|1qAtt_tI=krIN&mVa{f8d4uk>~RVUdSJKA^)9)$3OCX z{>bzBBhTj#ypTWgeEz@-`2#QHe?wvZ$n*Il&*zUkpFi+I{>bzB125zcypaE6h4~}T z=Z`#}Kk|J3zzg{!&*u-kkU#K3{*M>tk3640@_hct^Z5fW Date: Sun, 4 Aug 2024 21:18:23 +0200 Subject: [PATCH 6/7] Update DRC documentation for #1816 implementation --- src/drc/drc/built-in-macros/_drc_layer.rb | 42 ++++++++++++++--------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index f14d74b7a..4e1437b61 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -2283,13 +2283,17 @@ CODE # %DRC% # @name inside - # @brief Selects edges or polygons of self which are inside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are inside edges or polygons from the other layer # @synopsis layer.inside(other) # # If layer is a polygon layer, the other layer needs to be a polygon layer too. # In this case, this method selects all polygons which are completely inside # polygons from the other layer. # + # If layer is an edge pair layer, the other layer needs to be a polygon layer. + # In this case, this method selects all edge pairs which are completely inside + # polygons from the other layer. + # # If layer is an edge layer, the other layer can be polygon or edge layer. In the # first case, all edges completely inside the polygons from the other layer are # selected. If the other layer is an edge layer, all edges completely contained @@ -2329,10 +2333,10 @@ CODE # %DRC% # @name not_inside - # @brief Selects edges or polygons of self which are not inside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are not inside edges or polygons from the other layer # @synopsis layer.not_inside(other) # - # This method computes the inverse of \inside - i.e. edges or polygons from the layer + # This method computes the inverse of \inside - i.e. edge, edge pairs or polygons from the layer # not being inside polygons or edges from the other layer. # # This method returns a new layer containing the selected shapes. A version which modifies self @@ -2370,7 +2374,7 @@ CODE # @brief Returns the results of \inside and \not_inside at the same time # @synopsis (a, b) = layer.split_inside(other) # - # This method returns the polygons or edges inside of polygons or edges from the other layer in + # This method returns the polygons, edge pairs or edges inside of polygons or edges from the other layer in # one layer and all others in a second layer. This method is equivalent to calling # \inside and \not_inside, but is faster than doing this in separate steps: # @@ -2380,7 +2384,7 @@ CODE # %DRC% # @name select_inside - # @brief Selects edges or polygons of self which are inside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are inside edges or polygons from the other layer # @synopsis layer.select_inside(other) # # This method is the in-place version of \inside - i.e. it modifies the layer instead @@ -2388,7 +2392,7 @@ CODE # %DRC% # @name select_not_inside - # @brief Selects edges or polygons of self which are not inside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are not inside edges or polygons from the other layer # @synopsis layer.select_not_inside(other) # # This method is the in-place version of \inside - i.e. it modifies the layer instead @@ -2396,13 +2400,17 @@ CODE # %DRC% # @name outside - # @brief Selects edges or polygons of self which are outside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are outside edges or polygons from the other layer # @synopsis layer.outside(other) # # If layer is a polygon layer, the other layer needs to be a polygon layer too. # In this case, this method selects all polygons which are entirely outside # polygons from the other layer. # + # If layer is an edge pair layer, the other layer needs to be a polygon layer. + # In this case, this method selects all edge pairs which are entirely outside + # polygons from the other layer. + # # If layer is an edge layer, the other layer can be polygon or edge layer. In the # first case, all edges entirely outside the polygons from the other layer are # selected. If the other layer is an edge layer, all edges entirely outside @@ -2442,10 +2450,10 @@ CODE # %DRC% # @name not_outside - # @brief Selects edges or polygons of self which are not outside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are not outside edges or polygons from the other layer # @synopsis layer.not_outside(other) # - # This method computes the inverse of \outside - i.e. edges or polygons from the layer + # This method computes the inverse of \outside - i.e. edges, edge pairs or polygons from the layer # not being outside polygons or edges from the other layer. # # This method returns a new layer containing the selected shapes. A version which modifies self @@ -2483,7 +2491,7 @@ CODE # @brief Returns the results of \outside and \not_outside at the same time # @synopsis (a, b) = layer.split_outside(other) # - # This method returns the polygons or edges outside of polygons or edges from the other layer in + # This method returns the polygons, edge pairs or edges outside of polygons or edges from the other layer in # one layer and all others in a second layer. This method is equivalent to calling # \outside and \not_outside, but is faster than doing this in separate steps: # @@ -2493,7 +2501,7 @@ CODE # %DRC% # @name select_outside - # @brief Selects edges or polygons of self which are outside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are outside edges or polygons from the other layer # @synopsis layer.select_outside(other) # # This method is the in-place version of \outside - i.e. it modifies the layer instead @@ -2501,7 +2509,7 @@ CODE # %DRC% # @name select_not_outside - # @brief Selects edges or polygons of self which are not outside edges or polygons from the other layer + # @brief Selects edges, edge pairs or polygons of self which are not outside edges or polygons from the other layer # @synopsis layer.select_not_outside(other) # # This method is the in-place version of \outside - i.e. it modifies the layer instead @@ -2571,7 +2579,7 @@ CODE # It returns a new layer containing the selected shapes. A version which modifies self # is \select_interacting. # - # This method is available for polygon, text and edge layers. Edges can be selected + # This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected # with respect to other edges or polygons. Texts can be selected with respect to # polygons. Polygons can be selected with respect to edges, texts and other polygons. # @@ -2612,7 +2620,7 @@ CODE # It returns a new layer containing the selected shapes. A version which modifies self # is \select_not_interacting. # - # This method is available for polygon, text and edge layers. Edges can be selected + # This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected # with respect to other edges or polygons. Texts can be selected with respect to # polygons. Polygons can be selected with respect to edges, texts and other polygons. # @@ -2668,7 +2676,7 @@ CODE # It modifies self to contain the selected shapes. A version which does not modify self # is \interacting. # - # This method is available for polygon, text and edge layers. Edges can be selected + # This method is available for polygon, text, edge and edge pair layers. Edges and edge pairs can be selected # with respect to other edges or polygons. Texts can be selected with respect to # polygons. Polygons can be selected with respect to edges, texts and other polygons. # @@ -2690,7 +2698,7 @@ CODE # It modifies self to contain the selected shapes. A version which does not modify self # is \not_interacting. # - # This method is available for polygon, text and edge layers. Edges can be selected + # This method is available for polygon, text, edge and edge pair layers. Edges or edge pairs can be selected # with respect to other edges or polygons. Texts can be selected with respect to # polygons. Polygons can be selected with respect to edges, texts and other polygons. # @@ -2772,7 +2780,7 @@ CODE # # This method will neither modify self nor other. # - # This method is available for polygon, edge and text layers, similar to interacting. + # This method is available for polygon, edge, edge pair and text layers, similar to interacting. # %DRC% # @name pull_overlapping From b27bcd5c1610a088a83d73465863aa594e2bf8f9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Aug 2024 22:26:21 +0200 Subject: [PATCH 7/7] Added tests for GSI bindings of new EdgePairs functions --- testdata/ruby/dbEdgePairsTest.rb | 94 ++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/testdata/ruby/dbEdgePairsTest.rb b/testdata/ruby/dbEdgePairsTest.rb index c5bf4c4fe..99e4caac2 100644 --- a/testdata/ruby/dbEdgePairsTest.rb +++ b/testdata/ruby/dbEdgePairsTest.rb @@ -480,6 +480,100 @@ class DBEdgePairs_TestClass < TestBase end + # Interactions + def test_interactions + + edge_pairs = RBA::EdgePairs::new + edge_pairs.insert(RBA::EdgePair::new(RBA::Edge::new(0, 0, 100, 100), RBA::Edge::new(200, 300, 200, 500))) + edge_pairs.insert(RBA::EdgePair::new(RBA::Edge::new(0, 1000, 100, 1000), RBA::Edge::new(100, 1000, 0, 1000))) + + e = RBA::Edges::new + e.insert(RBA::Edge::new(0, 200, 200, 200)) + + assert_equal(edge_pairs.interacting(e).to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.interacting(e, 1, 1).to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.interacting(e, 2, 2).to_s, "") + assert_equal(edge_pairs.not_interacting(e).to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.not_interacting(e, 2, 2).to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_interacting(e) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_interacting(e, 1, 1) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_interacting(e, 2, 2) + assert_equal(ep.to_s, "") + ep = edge_pairs.dup + ep.select_not_interacting(e) + assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_not_interacting(e, 2, 2) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(e)[0].to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_interacting(e)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(e, 1, 1)[0].to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_interacting(e, 1, 1)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(e, 2, 2)[0].to_s, "") + assert_equal(edge_pairs.split_interacting(e, 2, 2)[1].to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + + r = RBA::Region::new + r.insert(RBA::Box::new(0, 190, 200, 210)) + + assert_equal(edge_pairs.interacting(r).to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.interacting(r, 1, 1).to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.interacting(r, 2, 2).to_s, "") + assert_equal(edge_pairs.not_interacting(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.not_interacting(r, 2, 2).to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_interacting(r) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_interacting(r, 1, 1) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_interacting(r, 2, 2) + assert_equal(ep.to_s, "") + ep = edge_pairs.dup + ep.select_not_interacting(r) + assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_not_interacting(r, 2, 2) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(r)[0].to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_interacting(r)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(r, 1, 1)[0].to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_interacting(r, 1, 1)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_interacting(r, 2, 2)[0].to_s, "") + assert_equal(edge_pairs.split_interacting(r, 2, 2)[1].to_s, "(0,0;100,100)/(200,300;200,500);(0,1000;100,1000)/(100,1000;0,1000)") + + r = RBA::Region::new + r.insert(RBA::Box::new(0, 0, 200, 500)) + + assert_equal(edge_pairs.inside(r).to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.not_inside(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_inside(r) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_not_inside(r) + assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_inside(r)[0].to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_inside(r)[1].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + + assert_equal(edge_pairs.outside(r).to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.not_outside(r).to_s, "(0,0;100,100)/(200,300;200,500)") + ep = edge_pairs.dup + ep.select_outside(r) + assert_equal(ep.to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + ep = edge_pairs.dup + ep.select_not_outside(r) + assert_equal(ep.to_s, "(0,0;100,100)/(200,300;200,500)") + assert_equal(edge_pairs.split_outside(r)[0].to_s, "(0,1000;100,1000)/(100,1000;0,1000)") + assert_equal(edge_pairs.split_outside(r)[1].to_s, "(0,0;100,100)/(200,300;200,500)") + + end + end