From d76eef10afe1c8ed662e309f587f03542a9dcfcc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 27 Nov 2022 15:59:18 +0100 Subject: [PATCH] GSI enabling of Edges#in_and_out, Region#in_and_out and corresponding DRC feature --- src/db/db/gsiDeclDbEdges.cc | 37 ++++++---- src/db/db/gsiDeclDbRegion.cc | 35 ++++++--- src/doc/doc/about/drc_ref_layer.xml | 82 ++++++++++------------ src/drc/drc/built-in-macros/_drc_layer.rb | 25 +++++++ src/drc/unit_tests/drcSimpleTests.cc | 10 +++ testdata/drc/drcSimpleTests_58.drc | 27 +++++++ testdata/drc/drcSimpleTests_58.gds | Bin 0 -> 2274 bytes testdata/drc/drcSimpleTests_au58.gds | Bin 0 -> 19966 bytes testdata/drc/drcSimpleTests_au58d.gds | Bin 0 -> 13470 bytes 9 files changed, 149 insertions(+), 67 deletions(-) create mode 100644 testdata/drc/drcSimpleTests_58.drc create mode 100644 testdata/drc/drcSimpleTests_58.gds create mode 100644 testdata/drc/drcSimpleTests_au58.gds create mode 100644 testdata/drc/drcSimpleTests_au58d.gds diff --git a/src/db/db/gsiDeclDbEdges.cc b/src/db/db/gsiDeclDbEdges.cc index e2977296f..f1ce6d959 100644 --- a/src/db/db/gsiDeclDbEdges.cc +++ b/src/db/db/gsiDeclDbEdges.cc @@ -35,7 +35,16 @@ namespace gsi { -static db::Edges *new_v () +static inline std::vector as_2edges_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::Edges (const_cast (rp.first).take_delegate ())); + res.push_back (db::Edges (const_cast (rp.second).take_delegate ())); + return res; +} + +static db::Edges *new_v () { return new db::Edges (); } @@ -166,6 +175,11 @@ static db::Edges not_in (const db::Edges *r, const db::Edges &other) return r->in (other, true); } +static std::vector in_and_out (const db::Edges *r, const db::Edges &other) +{ + return as_2edges_vector (r->in_and_out (other)); +} + static db::Edges &move_p (db::Edges *r, const db::Vector &p) { r->transform (db::Disp (p)); @@ -377,15 +391,6 @@ static size_t id (const db::Edges *e) return tl::id_of (e->delegate ()); } -static inline std::vector as_2edges_vector (const std::pair &rp) -{ - std::vector res; - res.reserve (2); - res.push_back (db::Edges (const_cast (rp.first).take_delegate ())); - res.push_back (db::Edges (const_cast (rp.second).take_delegate ())); - return res; -} - static std::vector andnot_with_edges (const db::Edges *r, const db::Edges &other) { return as_2edges_vector (r->andnot (other)); @@ -1633,16 +1638,24 @@ Class decl_Edges (decl_dbShapeCollection, "db", "Edges", "\n" "Merged semantics applies for this method (see \\merged_semantics= of merged semantics)\n" ) + - method_ext ("members_of|#in", &in, gsi::arg ("other"), + method_ext ("members_of|in", &in, gsi::arg ("other"), "@brief Returns all edges which are members of the other edge collection\n" "This method returns all edges in self which can be found in the other edge collection as well with exactly the same " "geometry." ) + - method_ext ("not_members_of|#not_in", ¬_in, gsi::arg ("other"), + method_ext ("not_members_of|not_in", ¬_in, gsi::arg ("other"), "@brief Returns all edges which are not members of the other edge collection\n" "This method returns all edges in self which can not be found in the other edge collection with exactly the same " "geometry." ) + + method_ext ("in_and_out", &in_and_out, gsi::arg ("other"), + "@brief Returns all polygons which are members and not members of the other region\n" + "This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and " + "is more efficient than two separate calls. " + "The first element returned is the \\members_of part, the second is the \\not_members_of part.\n" + "\n" + "This method has been introduced in version 0.28.\n" + ) + method_ext ("is_deep?", &is_deep, "@brief Returns true if the edge collection is a deep (hierarchical) one\n" "\n" diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc index f7874686b..d3dafb24d 100644 --- a/src/db/db/gsiDeclDbRegion.cc +++ b/src/db/db/gsiDeclDbRegion.cc @@ -44,6 +44,15 @@ namespace gsi { +static inline std::vector as_2region_vector (const std::pair &rp) +{ + std::vector res; + res.reserve (2); + res.push_back (db::Region (const_cast (rp.first).take_delegate ())); + res.push_back (db::Region (const_cast (rp.second).take_delegate ())); + return res; +} + static db::Region *new_v () { return new db::Region (); @@ -430,6 +439,11 @@ static db::Region not_in (const db::Region *r, const db::Region &other) return r->in (other, true); } +static std::vector in_and_out (const db::Region *r, const db::Region &other) +{ + return as_2region_vector (r->in_and_out (other)); +} + static db::Region rectangles (const db::Region *r) { db::RectangleFilter f (false, false); @@ -605,15 +619,6 @@ static db::EdgePairs separation2 (const db::Region *r, const db::Region &other, ); } -static inline std::vector as_2region_vector (const std::pair &rp) -{ - std::vector res; - res.reserve (2); - res.push_back (db::Region (const_cast (rp.first).take_delegate ())); - res.push_back (db::Region (const_cast (rp.second).take_delegate ())); - return res; -} - static std::vector andnot (const db::Region *r, const db::Region &other) { return as_2region_vector (r->andnot (other)); @@ -2186,16 +2191,24 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region", "are taken from a hole-less representation (i.e. GDS2 file). Use explicit merge (\\merge method) " "in order to merge the polygons and detect holes.\n" ) + - method_ext ("members_of|#in", &in, gsi::arg ("other"), + method_ext ("members_of|in", &in, gsi::arg ("other"), "@brief Returns all polygons which are members of the other region\n" "This method returns all polygons in self which can be found in the other region as well with exactly the same " "geometry." ) + - method_ext ("not_members_of|#not_in", ¬_in, gsi::arg ("other"), + method_ext ("not_members_of|not_in", ¬_in, gsi::arg ("other"), "@brief Returns all polygons which are not members of the other region\n" "This method returns all polygons in self which can not be found in the other region with exactly the same " "geometry." ) + + method_ext ("in_and_out", &in_and_out, gsi::arg ("other"), + "@brief Returns all polygons which are members and not members of the other region\n" + "This method is equivalent to calling \\members_of and \\not_members_of, but delivers both results at the same time and " + "is more efficient than two separate calls. " + "The first element returned is the \\members_of part, the second is the \\not_members_of part.\n" + "\n" + "This method has been introduced in version 0.28.\n" + ) + method_ext ("rectangles", &rectangles, "@brief Returns all polygons which are rectangles\n" "This method returns all polygons in self which are rectangles." diff --git a/src/doc/doc/about/drc_ref_layer.xml b/src/doc/doc/about/drc_ref_layer.xml index 323b77638..10321b4c6 100644 --- a/src/doc/doc/about/drc_ref_layer.xml +++ b/src/doc/doc/about/drc_ref_layer.xml @@ -1342,6 +1342,44 @@ The following image shows the effect of the "in" method (input1: red, input2: bl

+

"in_and_out" - Selects shapes or regions of self which are and which are not contained in the other layer

+ +

Usage:

+
    +
  • (in, not_in) = layer.in_and_out(other)
  • +
+

+This method is equivalent to calling in and not_in, but more +efficient as it delivers both results in a single call. +

+This method is available for polygon, text and edge layers. Edges 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. +

+The following image shows the effect of the "interacting" method (input1: red, input2: blue): +

+ + + + +
+

+If a single count is given, shapes from self are selected only if they do interact at least with the given +number of (different) shapes from the other layer. If a min and max count is given, shapes from +self are selected only if they interact with min_count or more, but a maximum of max_count different shapes +from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. +

+ + + + + + + + + +
+

"insert" - Inserts one or many objects into the layer

Usage:

@@ -1448,50 +1486,6 @@ method computing both inside and outside part in a single call.

-

"interacting" - Selects shapes or regions of self which touch or overlap shapes from the other region

- -

Usage:

-
    -
  • layer.interacting(other)
  • -
  • layer.interacting(other, min_count)
  • -
  • layer.interacting(other, min_count, max_count)
  • -
  • layer.interacting(other, min_count .. max_count)
  • -
-

-This method selects all shapes or regions from self which touch or overlap shapes from the other -region. Unless self is in raw mode (see raw), coherent regions are selected from self, -otherwise individual shapes are selected. -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 -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. -

-The following image shows the effect of the "interacting" method (input1: red, input2: blue): -

- - - - -
-

-If a single count is given, shapes from self are selected only if they do interact at least with the given -number of (different) shapes from the other layer. If a min and max count is given, shapes from -self are selected only if they interact with min_count or more, but a maximum of max_count different shapes -from the other layer. Two polygons overlapping or touching at two locations are counted as single interactions. -

- - - - - - - - - -
-

"intersections" - Returns the intersection points of intersecting edge segments for two edge collections

Usage:

diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index abea2dd64..aef166151 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -2442,6 +2442,13 @@ CODE # @/tr # @/table + # %DRC% + # @name in_and_out + # @brief Selects shapes or regions of self which are and which are not contained in the other layer + # @synopsis (in, not_in) = layer.in_and_out(other) + # This method is equivalent to calling \in and \not_in, but more + # efficient as it delivers both results in a single call. + # %DRC% # @name interacting # @brief Selects shapes or regions of self which touch or overlap shapes from the other region @@ -2844,6 +2851,24 @@ CODE CODE end + %w(in_and_out).each do |f| + eval <<"CODE" + def #{f}(other, *args) + + @engine._context("#{f}") do + + requires_same_type(other) + requires_edges_or_region + + res = @engine._tcmd_a2(self.data, 0, self.data.class, self.data.class, :#{f}, other.data) + [ DRCLayer::new(@engine, res[0]), DRCLayer::new(@engine, res[1]) ] + + end + + end +CODE + end + %w(split_interacting).each do |f| eval <<"CODE" def #{f}(other, *args) diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 7ba20d07b..ab37a7f8a 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1376,3 +1376,13 @@ TEST(57d_issue_1190) { run_test (_this, "57", true); } + +TEST(58_in_and_out) +{ + run_test (_this, "58", false); +} + +TEST(58d_in_and_out) +{ + run_test (_this, "58", true); +} diff --git a/testdata/drc/drcSimpleTests_58.drc b/testdata/drc/drcSimpleTests_58.drc new file mode 100644 index 000000000..611071b3c --- /dev/null +++ b/testdata/drc/drcSimpleTests_58.drc @@ -0,0 +1,27 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) +l2 = input(2, 0) + +l1.output(1, 0) +l2.output(2, 0) + +l1e = l1.edges +l2e = l2.edges + +l2.in(l1).output(10, 0) +l2.not_in(l1).output(11, 0) +l2.in_and_out(l1).first.output(12, 0) +l2.in_and_out(l1).last.output(13, 0) + +l2e.in(l1e).output(20, 0) +l2e.not_in(l1e).output(21, 0) +l2e.in_and_out(l1e).first.output(22, 0) +l2e.in_and_out(l1e).last.output(23, 0) + diff --git a/testdata/drc/drcSimpleTests_58.gds b/testdata/drc/drcSimpleTests_58.gds new file mode 100644 index 0000000000000000000000000000000000000000..1c6661453820cac7cd0489128ead06045abd5c0f GIT binary patch literal 2274 zcmbuAF-#Oe6o&uXJN8aE;Q*rqFcLWenDfA(5fe0kG)59Ft{_wx8wz7AOiYX=1tu00 z7A9Iym}qHXL1|&EEi5c8jFkn2g{A+$dp~=U9Vy&o^KIVD|K`n`w{H+5iq)5|wMz1hFAvNyB)a=nGouCOkSW2#COAU+-;Lfjhx zSf~|&vCqKSk13~1z`zHn9pcCndr+n>J*l;tQFd) za8bMLqi01Wp8Ar0pXN@7e*vb)$&>&AuoZ4lyuQJwKz+??DJ&(-umt?=V z#S?r6h(q*MzL(K=NgL>sn zT2W`GwN2Z}PQAOs|JJ4b9Mn+~3)eqfN4ArBaUAGfZ{CY(`=L7gYkkdSZ_Ukv?PPF$ z>0NKGKht*C;SpV+634Aux7i1}*(3*Ic7%Ai05ztr<#kd|RXt&D2Po{MF&)fJMy~Er zw3s*YX#4QUa)79&xUb_BvC&O1FXOd1Riyq$YF|l-}_rhvtFGi;T9DLA`DQ%@d`saUZ7b|I#mh zO>YB{c|>a?qi%`zcyN7|VlZtdgZeuw>1`}Fhk(00 eQ&YEedpxM$WbSl_h`Q15^EGYv-NJvORKg!eQR&M7 literal 0 HcmV?d00001 diff --git a/testdata/drc/drcSimpleTests_au58.gds b/testdata/drc/drcSimpleTests_au58.gds new file mode 100644 index 0000000000000000000000000000000000000000..41d44f9a9202b06c217fb9ac0744326bff55aa5d GIT binary patch literal 19966 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 SgHWX2AXHnup}$!Shw>jq+V^Gv literal 0 HcmV?d00001