mirror of https://github.com/KLayout/klayout.git
GSI enabling of Edges#in_and_out, Region#in_and_out and corresponding DRC feature
This commit is contained in:
parent
f6f4dbeb67
commit
d76eef10af
|
|
@ -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", ¬_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"
|
||||
|
|
|
|||
|
|
@ -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", ¬_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."
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue