Added missing files, tests for angle and length (universal DRC), some clarifications and bug fixes.

This commit is contained in:
Matthias Koefferlein 2021-01-10 20:18:06 +01:00
parent 0a7ca69da2
commit 383f72eb09
7 changed files with 720 additions and 14 deletions

View File

@ -581,15 +581,15 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
"horizontal = edges.with_orientation(0, true)\n" "horizontal = edges.with_orientation(0, true)\n"
"@/code\n" "@/code\n"
) + ) +
method_ext ("with_angle", with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_amin", true), gsi::arg ("include_amax", true), method_ext ("with_angle", with_angle2, gsi::arg ("min_angle"), gsi::arg ("max_angle"), gsi::arg ("inverse"), gsi::arg ("include_min_angle", true), gsi::arg ("include_max_angle", false),
"@brief Filter the edges by orientation\n" "@brief Filter the edges by orientation\n"
"Filters the edges in the edge collection by orientation. If \"inverse\" is false, only " "Filters the edges in the edge collection by orientation. If \"inverse\" is false, only "
"edges which have an angle to the x-axis larger or equal to \"min_angle\" and less than \"max_angle\" are " "edges which have an angle to the x-axis larger or equal to \"min_angle\" (depending on \"include_min_angle\") and equal or less than \"max_angle\" (depending on \"include_max_angle\") are "
"returned. If \"inverse\" is true, " "returned. If \"inverse\" is true, "
"edges which do not conform to this criterion are returned.\n" "edges which do not conform to this criterion are returned.\n"
"\n" "\n"
"With \"include_min\" set to true (the default), the minimum angle is included in the criterion while with false, the " "With \"include_min_angle\" set to true (the default), the minimum angle is included in the criterion while with false, the "
"minimum angle itself is not included. Same for \"include_max\".\n" "minimum angle itself is not included. Same for \"include_max_angle\" where the default is false, meaning the maximum angle is not included in the range.\n"
"\n" "\n"
"The two \"include..\" arguments have been added in version 0.27." "The two \"include..\" arguments have been added in version 0.27."
) + ) +

View File

@ -200,23 +200,35 @@ TEST(4)
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
} }
{ {
db::EdgeOrientationFilter f1 (50.0, true, 80.0, true, false); db::EdgeOrientationFilter f1 (50.0, true, 80.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(200,0;250,200);(250,-200;300,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(200,0;250,200);(250,-200;300,0)");
} }
{ {
db::EdgeOrientationFilter f1 (50.0, true, 80.0, true, true); db::EdgeOrientationFilter f1 (50.0, true, 80.0, false, true);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(0,200;100,200);(100,200;100,0);(100,0;0,0);(250,200;300,0);(300,0;200,0);(200,0;250,-200)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(0,200;100,200);(100,200;100,0);(100,0;0,0);(250,200;300,0);(300,0;200,0);(200,0;250,-200)");
} }
{
db::EdgeOrientationFilter f1 (0.0, true, 1.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
}
{
db::EdgeOrientationFilter f1 (-1.0, true, 1.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
}
{
db::EdgeOrientationFilter f1 (-1.0, true, 0.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "");
}
{
db::EdgeOrientationFilter f1 (-1.0, true, 0.0, true, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
}
{ {
db::EdgeOrientationFilter f1 (0.0, true, 1.0, true, false); db::EdgeOrientationFilter f1 (0.0, true, 1.0, true, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
} }
{ {
db::EdgeOrientationFilter f1 (-1.0, true, 1.0, true, false); db::EdgeOrientationFilter f1 (0.0, false, 1.0, true, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,200;100,200);(100,0;0,0);(300,0;200,0)");
}
{
db::EdgeOrientationFilter f1 (-1.0, true, 0.0, true, false);
EXPECT_EQ (r.filtered (f1).to_string (), ""); EXPECT_EQ (r.filtered (f1).to_string (), "");
} }
{ {
@ -224,15 +236,15 @@ TEST(4)
EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)");
} }
{ {
db::EdgeOrientationFilter f1 (90.0, true, 91.0, true, false); db::EdgeOrientationFilter f1 (90.0, true, 91.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)");
} }
{ {
db::EdgeOrientationFilter f1 (89.0, true, 91.0, true, false); db::EdgeOrientationFilter f1 (89.0, true, 91.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)"); EXPECT_EQ (r.filtered (f1).to_string (), "(0,0;0,200);(100,200;100,0)");
} }
{ {
db::EdgeOrientationFilter f1 (89.0, true, 90.0, true, false); db::EdgeOrientationFilter f1 (89.0, true, 90.0, false, false);
EXPECT_EQ (r.filtered (f1).to_string (), ""); EXPECT_EQ (r.filtered (f1).to_string (), "");
} }
} }

View File

@ -0,0 +1,664 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by /home/matthias/klayout/master/scripts/extract_doc.rb -->
<!-- DO NOT EDIT! -->
<doc>
<title>DRC Reference: DRC expressions</title>
<keyword name="Expressions"/>
<p>
DRC expression objects represent abstract recipes for the <a href="/about/drc_ref_layer.xml#drc">Layer#drc</a> universal DRC function.
For example, when using a universal DRC expression like this:
</p><p>
<pre>
out = in.drc(width &lt; 2.0)
</pre>
</p><p>
"width &lt; 2.0" forms a DRC expression object. DRC expression objects have methods which
manipulate or evaluate the results of this expression. In addition, DRC expressions have a
result type, which is either polygon, edge or edge pair. The result type is defined by the
expression generating it. In the example above, "width &lt; 2.0" is a DRC width check which
renders edge pairs. To obtain polygons from these edge pairs, use the "polygons" method:
</p><p>
<pre>
out = in.drc((width &lt; 2.0).polygons)
</pre>
</p><p>
The following documentation will list the methods available for DRC expression objects.
</p>
<h2-index/>
<a name="!"/><h2>"!" - Logical not</h2>
<keyword name="!"/>
<p>Usage:</p>
<ul>
<li><tt>! expression</tt></li>
</ul>
<p>
This operator will evaluate the expression after. If this expression renders
an empty result, the operator will return the primary shape. Otherwise it will
return an empty result.
</p><p>
This operator can be used together with predicates such a "rectangles" to
invert their meaning. For example, this code selects all primary shapes which
are not rectangles:
</p><p>
<pre>
out = in.drc(! rectangles)
out = in.drc(! primary.rectangles) # equivalent
</pre>
</p>
<a name="&amp;"/><h2>"&amp;" - Boolean AND between the results of two expressions</h2>
<keyword name="&amp;"/>
<p>Usage:</p>
<ul>
<li><tt>expression &amp; expression</tt></li>
</ul>
<p>
The &amp; operator will compute the boolean AND between the results
of two expressions. The expression types need to be edge or polygon.
</p><p>
The following example computes the partial edges where width is less than
0.3 micrometers and space is less than 0.2 micrometers:
</p><p>
<pre>
out = in.drc((width &lt; 0.3).edges &amp; (space &lt; 0.2).edges)
</pre>
</p>
<a name="+"/><h2>"+" - Boolean OR between the results of two expressions</h2>
<keyword name="+"/>
<p>Usage:</p>
<ul>
<li><tt>expression + expression</tt></li>
</ul>
<p>
The + operator will join the results of two expressions.
</p>
<a name="-"/><h2>"-" - Boolean NOT between the results of two expressions</h2>
<keyword name="-"/>
<p>Usage:</p>
<ul>
<li><tt>expression - expression</tt></li>
</ul>
<p>
The - operator will compute the difference between the results
of two expressions. The NOT operation is defined for polygons,
edges and polygons subtracted from edges (first argument edge,
second argument polygon).
</p><p>
The following example will produce edge markers where the
width of is less then 0.3 micron but not inside polygons on
the "waive" layer:
</p><p>
<pre>
out = in.drc((width &lt; 0.3).edges - secondary(waive))
</pre>
</p>
<a name="^"/><h2>"^" - Boolean XOR between the results of two expressions</h2>
<keyword name="^"/>
<p>Usage:</p>
<ul>
<li><tt>expression - expression</tt></li>
</ul>
<p>
The ^ operator will compute the XOR (symmetric difference) between the results
of two expressions. The XOR operation is defined for polygons and edges.
Both expressions must be of the same type.
</p>
<a name="angle"/><h2>"angle" - Selects edges based on their angle</h2>
<keyword name="angle"/>
<p>Usage:</p>
<ul>
<li><tt>expression.angle (in condition)</tt></li>
</ul>
<p>
This operation selects edges by their angle, measured against the horizontal
axis in the mathematical sense.
</p><p>
For this measurement edges are considered without their direction and straight lines.
A horizontal edge has an angle of zero degree. A vertical one has
an angle of 90 degee. The angle range is from -90 (exclusive) to 90 degree (inclusive).
</p><p>
If the input shapes are not polygons or edge pairs, they are converted to edges
before the angle test is made.
</p><p>
For example, the following code selects all edges from the primary shape which are 45 degree
(up) or 135 degree (down). The "+" will join the results:
</p><p>
<pre>
out = in.drc((angle == 45) + (angle == 135))
out = in.drc((primary.angle == 45) + (primary.angle == 135)) # equivalent
</pre>
</p><p>
Note that angle checks usually imply the need to rotation variant formation as cells which
are placed unrotated and rotated by 90 degree cannot be considered identical. This imposes
a performance penalty in hierarchical mode. If possible, consider using <a href="/about/drc_ref_drc.xml#rectilinear">DRC#rectilinear</a> for
example to detect shapes with non-manhattan geometry instead of using angle checks.
</p><p>
The "angle" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.angle".
</p>
<a name="area"/><h2>"area" - Selects the primary shape if the area is meeting the condition</h2>
<keyword name="area"/>
<p>Usage:</p>
<ul>
<li><tt>expression.area (in condition)</tt></li>
</ul>
<p>
This operation is used in conditions to select shapes based on their area.
It is applicable on polygon expressions. The result will be the input
polygons if the area condition is met.
</p><p>
See <a href="#drc">drc</a> for more details about comparison specs.
</p><p>
The following example will select all polygons with an area less than 2.0 square micrometers:
</p><p>
<pre>
out = in.drc(area &lt; 2.0)
out = in.drc(primary.area &lt; 2.0) # equivalent
</pre>
</p><p>
The area method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.area".
</p>
<a name="bbox_height"/><h2>"bbox_height" - Selects the primary shape if its bounding box height is meeting the condition</h2>
<keyword name="bbox_height"/>
<p>Usage:</p>
<ul>
<li><tt>expression.bbox_height (in condition)</tt></li>
</ul>
<p>
This operation acts similar to <a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a>, but takes the height of the shape's
bounding box. In general, it's more advisable to use <a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a> or <a href="/about/drc_ref_drc.xml#bbox_max">DRC#bbox_max</a>
because bbox_height implies a certain orientation. This can imply variant formation in
hierarchical contexts: cells rotated by 90 degree have to be treated differently from
ones not rotated. This usually results in a larger computation effort and larger result files.
</p><p>
The "bbox_height" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.bbox_height".
</p>
<a name="bbox_max"/><h2>"bbox_max" - Selects the primary shape if its bounding box larger dimension is meeting the condition</h2>
<keyword name="bbox_max"/>
<p>Usage:</p>
<ul>
<li><tt>expression.bbox_max (in condition)</tt></li>
</ul>
<p>
This operation acts similar to <a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a>, but takes the larger dimension of the shape's
bounding box.
</p><p>
The "bbox_max" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.bbox_max".
</p>
<a name="bbox_min"/><h2>"bbox_min" - Selects the primary shape if its bounding box smaller dimension is meeting the condition</h2>
<keyword name="bbox_min"/>
<p>Usage:</p>
<ul>
<li><tt>expression.bbox_min (in condition)</tt></li>
</ul>
<p>
This operation is used in conditions to select shapes based on smaller dimension of their bounding boxes.
It is applicable on polygon expressions. The result will be the input
polygons if the bounding box condition is met.
</p><p>
See <a href="#drc">drc</a> for more details about comparison specs.
</p><p>
The following example will select all polygons whose bounding box smaller dimension is larger
than 200 nm:
</p><p>
<pre>
out = in.drc(bbox_min &gt; 200.nm)
out = in.drc(primary.bbox_min &gt; 200.nm) # equivalent
</pre>
</p><p>
The "bbox_min" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.bbox_min".
</p>
<a name="bbox_width"/><h2>"bbox_width" - Selects the primary shape if its bounding box width is meeting the condition</h2>
<keyword name="bbox_width"/>
<p>Usage:</p>
<ul>
<li><tt>expression.bbox_width (in condition)</tt></li>
</ul>
<p>
This operation acts similar to <a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a>, but takes the width of the shape's
bounding box. In general, it's more advisable to use <a href="/about/drc_ref_drc.xml#bbox_min">DRC#bbox_min</a> or <a href="/about/drc_ref_drc.xml#bbox_max">DRC#bbox_max</a>
because bbox_width implies a certain orientation. This can imply variant formation in
hierarchical contexts: cells rotated by 90 degree have to be treated differently from
ones not rotated. This usually results in a larger computation effort and larger result files.
</p><p>
The "bbox_width" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.bbox_width".
</p>
<a name="centers"/><h2>"centers" - Returns the part at the center of each edge of the input</h2>
<keyword name="centers"/>
<p>Usage:</p>
<ul>
<li><tt>expression.centers(length)</tt></li>
<li><tt>expression.end_segments(length, fraction)</tt></li>
</ul>
<p>
This method acts on edge expressions and delivers a specific part of each edge.
See <a href="/about/drc_ref_layer.xml#centers">layer#centers</a> for details about this functionality.
</p>
<a name="corners (in condition)"/><h2>"corners (in condition)" - Applies smoothing</h2>
<keyword name="corners (in condition)"/>
<p>Usage:</p>
<ul>
<li><tt>expression.corners</tt></li>
<li><tt>expression.corners(as_dots)</tt></li>
<li><tt>expression.corners(as_boxes)</tt></li>
</ul>
<p>
This operation acts on polygons and selects the corners of the polygons.
It can be put into a condition to select corners by their angles. The angle of
a corner is positive for a turn to the left if walking a polygon counterclockwise
and negative for the turn to the right. Angles take values between -180 and 180 degree.
</p><p>
When using "as_dots" for the argument, the operation will return single-point edges at
the selected corners. With "as_boxes" (the default), small (2x2 DBU) rectangles will be
produced at each selected corner.
</p><p>
The following example selects all corners:
</p><p>
<pre>
out = in.drc(corners)
out = in.drc(primary.corners) # equivalent
</pre>
</p><p>
The following example selects all inner corners:
</p><p>
<pre>
out = in.drc(corners &lt; 0)
out = in.drc(primary.corners &lt; 0) # equivalent
</pre>
</p><p>
The "corners" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.corners".
</p>
<a name="count"/><h2>"count" - Selects a expression result based on the number of (local) shapes</h2>
<keyword name="count"/>
<p>Usage:</p>
<ul>
<li><tt>expression.count (in condition)</tt></li>
</ul>
<p>
This operation is used in conditions to select expression results based on their
count. "count" is used as a method on a expression. It will evaluate the expression locally
and return the original result if the shape count in the result is matching the condition.
</p><p>
See <a href="#drc">drc</a> for more details about comparison specs.
</p><p>
Note that the expression is evaluated locally: for each primary shape, the expression is
evaluated and the count of the resulting edge, edge pair or polygon set is taken.
As the primary input will always have a single item (the local shape), using "count" on
primary does not really make sense. It can be used on derived expressions however.
</p><p>
The following example selects triangles:
</p><p>
<pre>
out = in.drc(if_any(corners.count == 3))
</pre>
</p><p>
Note "if_any" which selects the primary shape if the argument evaluates to a non-empty
result. Without "if_any" three corners are returned for each triangle.
</p>
<a name="edges"/><h2>"edges" - Converts the input shapes into edges</h2>
<keyword name="edges"/>
<p>Usage:</p>
<ul>
<li><tt>expression.edges</tt></li>
</ul>
<p>
Polygons will be separated into edges forming their contours. Edge pairs will be
decomposed into individual edges.
</p><p>
Contrary most other operations, "edges" does not have a plain function equivalent
as this is reserved for the function generating an edges layer.
To generate the edges of the primary shapes, use "primary" explicit as the source
for the edges:
</p><p>
<pre>
out = in.drc(primary.edges)
</pre>
</p>
<a name="end_segments"/><h2>"end_segments" - Returns the part at the end of each edge of the input</h2>
<keyword name="end_segments"/>
<p>Usage:</p>
<ul>
<li><tt>expression.end_segments(length)</tt></li>
<li><tt>expression.end_segments(length, fraction)</tt></li>
</ul>
<p>
This method acts on edge expressions and delivers a specific part of each edge.
See <a href="/about/drc_ref_layer.xml#end_segments">layer#end_segments</a> for details about this functionality.
</p>
<a name="extended"/><h2>"extended" - Returns polygons describing an area along the edges of the input</h2>
<keyword name="extended"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extended([:begin =&gt; b,] [:end =&gt; e,] [:out =&gt; o,] [:in =&gt; i], [:joined =&gt; true])</tt></li>
<li><tt>expression.extended(b, e, o, i)</tt></li>
</ul>
<p>
This method acts on edge expressions.
It will create a polygon for each edge
tracing the edge with certain offsets to the edge. "o" is the offset applied to the
outer side of the edge, "i" is the offset applied to the inner side of the edge.
"b" is the offset applied at the beginning and "e" is the offset applied at the end.
</p>
<a name="extended_in"/><h2>"extended_in" - Returns polygons describing an area along the edges of the input</h2>
<keyword name="extended_in"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extended_in(d)</tt></li>
</ul>
<p>
This method acts on edge expressions. Polygons are generated for
each edge describing the edge drawn with a certain width extending into
the "inside" (the right side when looking from start to end).
This method is basically equivalent to the <a href="#extended">extended</a> method:
"extended(0, 0, 0, dist)".
A version extending to the outside is <a href="#extended_out">extended_out</a>.
</p>
<a name="extended_out"/><h2>"extended_out" - Returns polygons describing an area along the edges of the input</h2>
<keyword name="extended_out"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extended_out(d)</tt></li>
</ul>
<p>
This method acts on edge expressions. Polygons are generated for
each edge describing the edge drawn with a certain width extending into
the "outside" (the left side when looking from start to end).
This method is basically equivalent to the <a href="#extended">extended</a> method:
"extended(0, 0, dist, 0)".
A version extending to the inside is <a href="#extended_in">extended_in</a>.
</p>
<a name="extent_refs"/><h2>"extent_refs" - Returns partial references to the boundings boxes of the polygons</h2>
<keyword name="extent_refs"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extent_refs([ options ])</tt></li>
</ul>
<p>
The extent_refs operation acts on polygons and has the same effect than <a href="/about/drc_ref_layer.xml#extent_refs">Layer#extent_refs</a>.
It takes the same arguments. It is available as a method on <a href="#DRC">DRC</a> expressions or
as plain function, in which case it acts on the primary shapes.
</p>
<a name="extents"/><h2>"extents" - Returns the bounding box of each input object</h2>
<keyword name="extents"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extents([ enlargement ])</tt></li>
</ul>
<p>
This method provides the same functionality as <a href="/about/drc_ref_layer.xml#extents">Layer#extents</a> and takes the same
arguments. It returns the bounding boxes of the input objects. It acts on edge
edge pair and polygon expressions.
</p><p>
The "extents" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.extents".
</p>
<a name="first_edges"/><h2>"first_edges" - Returns the first edges of edge pairs</h2>
<keyword name="first_edges"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extents([ enlargement ])</tt></li>
</ul>
<p>
This method acts on edge pair expressions and returns the first edges of the
edge pairs delivered by the expression.
</p>
<a name="holes"/><h2>"holes" - Selects all holes from the input polygons</h2>
<keyword name="holes"/>
<p>Usage:</p>
<ul>
<li><tt>expression.holes</tt></li>
</ul>
<p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
The following example selects all holes with an area larger than 2 square micrometers:
</p><p>
<pre>
out = in.drc(holes.area &gt; 2.um)
out = in.drc(primary.holes.area &gt; 2.um) # equivalent
</pre>
</p>
<a name="hulls"/><h2>"hulls" - Selects all hulls from the input polygons</h2>
<keyword name="hulls"/>
<p>Usage:</p>
<ul>
<li><tt>expression.hulls</tt></li>
</ul>
<p>
The hulls are the outer contours of the input polygons. By selecting hulls only,
all holes will be closed.
</p><p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
The following example closes all holes:
</p><p>
<pre>
out = in.drc(hulls)
out = in.drc(primary.hulls) # equivalent
</pre>
</p>
<a name="length"/><h2>"length" - Selects edges based on their length</h2>
<keyword name="length"/>
<p>Usage:</p>
<ul>
<li><tt>expression.length (in condition)</tt></li>
</ul>
<p>
This operation will select those edges which are meeting the length
criterion. Non-edge shapes (polygons, edge pairs) will be converted to edges before.
</p><p>
For example, this code selects all edges from the primary shape which are longer or
equal than 1 micrometer:
</p><p>
<pre>
out = in.drc(length &gt;= 1.um)
out = in.drc(primary.length &gt;= 1.um) # equivalent
</pre>
</p><p>
The "length" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.length".
</p>
<a name="merged"/><h2>"merged" - Returns the merged input polygons, optionally selecting multi-overlap</h2>
<keyword name="merged"/>
<p>Usage:</p>
<ul>
<li><tt>expression.merged</tt></li>
<li><tt>expression.merged(min_count)</tt></li>
</ul>
<p>
This operation will act on polygons. Without a min_count argument, the merged
polygons will be returned.
</p><p>
With a min_count argument, the result will include only those parts where more
than the given number of polygons overlap. As the primary input is merged already,
it will always contribute as one.
</p><p>
The "merged" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.merged".
</p>
<a name="middle"/><h2>"middle" - Returns the centers of polygon bounding boxes</h2>
<keyword name="middle"/>
<p>Usage:</p>
<ul>
<li><tt>expression.middle([ options ])</tt></li>
</ul>
<p>
The middle operation acts on polygons and has the same effect than <a href="/about/drc_ref_layer.xml#middle">Layer#middle</a>.
It takes the same arguments. It is available as a method on <a href="#DRC">DRC</a> expressions or
as plain function, in which case it acts on the primary shapes.
</p>
<a name="odd_polygons"/><h2>"odd_polygons" - Selects all polygons which are non-orientable</h2>
<keyword name="odd_polygons"/>
<p>Usage:</p>
<ul>
<li><tt>expression.odd_polygons</tt></li>
</ul>
<p>
Non-orientable polygons are for example "8"-shape polygons. Such polygons are
usually considered harmful as their definition of covered area is depending on the
wrap count rule in place.
</p><p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
</p>
<a name="perimeter"/><h2>"perimeter" - Selects the primary shape if the perimeter is meeting the condition</h2>
<keyword name="perimeter"/>
<p>Usage:</p>
<ul>
<li><tt>expression.perimeter (in condition)</tt></li>
</ul>
<p>
This operation is used in conditions to select shapes based on their perimeter.
It is applicable on polygon expressions. The result will be the input
polygons if the perimeter condition is met.
</p><p>
See <a href="#drc">drc</a> for more details about comparison specs.
</p><p>
The following example will select all polygons with a perimeter less than 10 micrometers:
</p><p>
<pre>
out = in.drc(perimeter &lt; 10.0)
out = in.drc(primary.perimeter &lt; 10.0) # equivalent
</pre>
</p><p>
The perimeter method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.perimeter".
</p>
<a name="polygons"/><h2>"polygons" - Converts the input shapes into polygons</h2>
<keyword name="polygons"/>
<p>Usage:</p>
<ul>
<li><tt>expression.polygons([ enlargement ])</tt></li>
</ul>
<p>
Generates polygons from the input shapes. Polygons stay polygons. Edges and edge pairs
are converted to polygons. For this, the enlargement parameter will specify the
edge thickness or augmentation applied to edge pairs. With the default enlargement
of zero edges will not be converted to valid polygons and degenerated edge pairs
will not become valid polygons as well.
</p><p>
Contrary most other operations, "polygons" does not have a plain function equivalent
as this is reserved for the function generating a polygon layer.
</p><p>
This method is useful for generating polygons from DRC violation markers as shown in
the following example:
</p><p>
<pre>
out = in.drc((width &lt; 0.5.um).polygons)
</pre>
</p>
<a name="rectangles"/><h2>"rectangles" - Selects all polygons which are rectangles</h2>
<keyword name="rectangles"/>
<p>Usage:</p>
<ul>
<li><tt>expression.rectangles</tt></li>
</ul>
<p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
The following example selects all rectangles:
</p><p>
<pre>
out = in.drc(rectangles)
out = in.drc(primary.rectangles) # equivalent
</pre>
</p>
<a name="rectilinear"/><h2>"rectilinear" - Selects all polygons which are rectilinear</h2>
<keyword name="rectilinear"/>
<p>Usage:</p>
<ul>
<li><tt>expression.rectilinear</tt></li>
</ul>
<p>
Rectilinear polygons only have vertical and horizontal edges. Such polygons are also
called manhattan polygons.
</p><p>
This operation can be used as a plain function in which case it acts on primary
shapes or can be used as method on another DRC expression.
The following example selects all manhattan polygons:
</p><p>
<pre>
out = in.drc(rectilinear)
out = in.drc(primary.rectilinear) # equivalent
</pre>
</p>
<a name="rounded_corners"/><h2>"rounded_corners" - Applies corner rounding</h2>
<keyword name="rounded_corners"/>
<p>Usage:</p>
<ul>
<li><tt>expression.rounded_corners(inner, outer, n)</tt></li>
</ul>
<p>
This operation acts on polygons and applies corner rounding the the given inner
and outer corner radius and the number of points n per full circle. See <a href="/about/drc_ref_layer.xml#rounded_corners">Layer#rounded_corners</a> for more details.
</p><p>
The "rounded_corners" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.rounded_corners".
</p>
<a name="second_edges"/><h2>"second_edges" - Returns the second edges of edge pairs</h2>
<keyword name="second_edges"/>
<p>Usage:</p>
<ul>
<li><tt>expression.extents([ enlargement ])</tt></li>
</ul>
<p>
This method acts on edge pair expressions and returns the second edges of the
edge pairs delivered by the expression.
</p>
<a name="sized"/><h2>"sized" - Returns the sized version of the input</h2>
<keyword name="sized"/>
<p>Usage:</p>
<ul>
<li><tt>expression.sized(d [, mode])</tt></li>
<li><tt>expression.sized(dx, dy [, mode]))</tt></li>
</ul>
<p>
This method provides the same functionality as <a href="/about/drc_ref_layer.xml#sized">Layer#sized</a> and takes the same
arguments. It acts on polygon expressions.
</p><p>
The "sized" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.sized".
</p>
<a name="smoothed"/><h2>"smoothed" - Applies smoothing</h2>
<keyword name="smoothed"/>
<p>Usage:</p>
<ul>
<li><tt>expression.smoothed(d)</tt></li>
</ul>
<p>
This operation acts on polygons and applies polygon smoothing with the tolerance d. See <a href="/about/drc_ref_layer.xml#smoothed">Layer#smoothed</a> for more details.
</p><p>
The "smoothed" method is available as a plain function or as a method on <a href="#DRC">DRC</a> expressions.
The plain function is equivalent to "primary.smoothed".
</p>
<a name="start_segments"/><h2>"start_segments" - Returns the part at the beginning of each edge of the input</h2>
<keyword name="start_segments"/>
<p>Usage:</p>
<ul>
<li><tt>expression.start_segments(length)</tt></li>
<li><tt>expression.start_segments(length, fraction)</tt></li>
</ul>
<p>
This method acts on edge expressions and delivers a specific part of each edge.
See <a href="/about/drc_ref_layer.xml#start_segments">layer#start_segments</a> for details about this functionality.
</p>
<a name="|"/><h2>"|" - Boolean OR between the results of two expressions</h2>
<keyword name="|"/>
<p>Usage:</p>
<ul>
<li><tt>expression | expression</tt></li>
</ul>
<p>
The | operator will compute the boolean OR between the results of
two expressions. '+' is basically a synonym. Both expressions
must render the same type.
</p>
</doc>

30
testdata/drc/drcGenericTests_12.drc vendored Normal file
View File

@ -0,0 +1,30 @@
source $drc_test_source
target $drc_test_target
if $drc_test_deep
deep
threads(0) # easier to debug
end
l1 = input(1, 0)
l2 = input(2, 0)
l3 = input(3, 0)
l1.output(1, 0)
l2.output(2, 0)
l3.output(3, 0)
# edge predicates
l1.drc(length > 5.0).output(100, 0)
l1.drc(2.0 < length <= 5.0).output(101, 0)
l1.drc(length <= 2.0).output(102, 0)
l1.drc(length == 2.0).output(103, 0)
l1.drc(angle == 0.0).output(110, 0)
l1.drc(angle < 0.0).output(111, 0)
l1.drc(angle > 0.0).output(112, 0)
l1.drc(angle == 90).output(113, 0)
l1.drc((angle == 0.0) + (angle == 90)).output(114, 0)

BIN
testdata/drc/drcGenericTests_12.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcGenericTests_au12.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/drcGenericTests_au12d.gds vendored Normal file

Binary file not shown.