GSI enabling of Edges#in_and_out, Region#in_and_out and corresponding DRC feature

This commit is contained in:
Matthias Koefferlein 2022-11-27 15:59:18 +01:00
parent f6f4dbeb67
commit d76eef10af
9 changed files with 149 additions and 67 deletions

View File

@ -35,7 +35,16 @@
namespace gsi
{
static db::Edges *new_v ()
static inline std::vector<db::Edges> as_2edges_vector (const std::pair<db::Edges, db::Edges> &rp)
{
std::vector<db::Edges> res;
res.reserve (2);
res.push_back (db::Edges (const_cast<db::Edges &> (rp.first).take_delegate ()));
res.push_back (db::Edges (const_cast<db::Edges &> (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<db::Edges> 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<db::Edges> as_2edges_vector (const std::pair<db::Edges, db::Edges> &rp)
{
std::vector<db::Edges> res;
res.reserve (2);
res.push_back (db::Edges (const_cast<db::Edges &> (rp.first).take_delegate ()));
res.push_back (db::Edges (const_cast<db::Edges &> (rp.second).take_delegate ()));
return res;
}
static std::vector<db::Edges> andnot_with_edges (const db::Edges *r, const db::Edges &other)
{
return as_2edges_vector (r->andnot (other));
@ -1633,16 +1638,24 @@ Class<db::Edges> 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", &not_in, gsi::arg ("other"),
method_ext ("not_members_of|not_in", &not_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"

View File

@ -44,6 +44,15 @@
namespace gsi
{
static inline std::vector<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
{
std::vector<db::Region> res;
res.reserve (2);
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
res.push_back (db::Region (const_cast<db::Region &> (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<db::Region> 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<db::Region> as_2region_vector (const std::pair<db::Region, db::Region> &rp)
{
std::vector<db::Region> res;
res.reserve (2);
res.push_back (db::Region (const_cast<db::Region &> (rp.first).take_delegate ()));
res.push_back (db::Region (const_cast<db::Region &> (rp.second).take_delegate ()));
return res;
}
static std::vector<db::Region> andnot (const db::Region *r, const db::Region &other)
{
return as_2region_vector (r->andnot (other));
@ -2186,16 +2191,24 @@ Class<db::Region> 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", &not_in, gsi::arg ("other"),
method_ext ("not_members_of|not_in", &not_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."

View File

@ -1342,6 +1342,44 @@ The following image shows the effect of the "in" method (input1: red, input2: bl
</tr>
</table>
</p>
<a name="in_and_out"/><h2>"in_and_out" - Selects shapes or regions of self which are and which are not contained in the other layer</h2>
<keyword name="in_and_out"/>
<p>Usage:</p>
<ul>
<li><tt>(in, not_in) = layer.in_and_out(other)</tt></li>
</ul>
<p>
This method is equivalent to calling <a href="#in">in</a> and <a href="#not_in">not_in</a>, but more
efficient as it delivers both results in a single call.
</p><p>
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.
</p><p>
The following image shows the effect of the "interacting" method (input1: red, input2: blue):
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting.png"/></td>
</tr>
</table>
</p><p>
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.
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting2.png"/></td>
<td><img src="/images/drc_interacting3.png"/></td>
</tr>
<tr>
<td><img src="/images/drc_interacting4.png"/></td>
<td><img src="/images/drc_interacting5.png"/></td>
</tr>
</table>
</p>
<a name="insert"/><h2>"insert" - Inserts one or many objects into the layer</h2>
<keyword name="insert"/>
<p>Usage:</p>
@ -1448,50 +1486,6 @@ method computing both inside and outside part in a single call.
</tr>
</table>
</p>
<a name="interacting"/><h2>"interacting" - Selects shapes or regions of self which touch or overlap shapes from the other region</h2>
<keyword name="interacting"/>
<p>Usage:</p>
<ul>
<li><tt>layer.interacting(other)</tt></li>
<li><tt>layer.interacting(other, min_count)</tt></li>
<li><tt>layer.interacting(other, min_count, max_count)</tt></li>
<li><tt>layer.interacting(other, min_count .. max_count)</tt></li>
</ul>
<p>
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 <a href="#raw">raw</a>), 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 <a href="#select_interacting">select_interacting</a>.
</p><p>
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.
</p><p>
The following image shows the effect of the "interacting" method (input1: red, input2: blue):
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting.png"/></td>
</tr>
</table>
</p><p>
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.
</p><p>
<table>
<tr>
<td><img src="/images/drc_interacting2.png"/></td>
<td><img src="/images/drc_interacting3.png"/></td>
</tr>
<tr>
<td><img src="/images/drc_interacting4.png"/></td>
<td><img src="/images/drc_interacting5.png"/></td>
</tr>
</table>
</p>
<a name="intersections"/><h2>"intersections" - Returns the intersection points of intersecting edge segments for two edge collections</h2>
<keyword name="intersections"/>
<p>Usage:</p>

View File

@ -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)

View File

@ -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);
}

27
testdata/drc/drcSimpleTests_58.drc vendored Normal file
View File

@ -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)

BIN
testdata/drc/drcSimpleTests_58.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au58.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcSimpleTests_au58d.gds vendored Normal file

Binary file not shown.