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