mirror of https://github.com/KLayout/klayout.git
Implemented with(out)_angle, with(out)_area on edge pairs (DRC, GSI). Deprecated 'with(out)_angle' on polygon layers (DRC) as this is now redundant with 'corners'
This commit is contained in:
parent
4982d63597
commit
881e0010d5
|
|
@ -112,7 +112,17 @@ InternalAngleEdgePairFilter::InternalAngleEdgePairFilter (double amin, bool incl
|
|||
bool
|
||||
InternalAngleEdgePairFilter::selected (const db::EdgePair &edge_pair) const
|
||||
{
|
||||
return m_checker (edge_pair.first ().d (), -edge_pair.second ().d ()) != m_inverted;
|
||||
db::Vector d1 = edge_pair.first ().d ();
|
||||
db::Vector d2 = edge_pair.second ().d ();
|
||||
|
||||
if (db::sprod_sign (d1, d2) < 0) {
|
||||
d1 = -d1;
|
||||
}
|
||||
if (db::vprod_sign (d1, d2) < 0) {
|
||||
std::swap (d1, d2);
|
||||
}
|
||||
|
||||
return m_checker (d1, d2) != m_inverted;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -724,10 +724,7 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"edge pairs with the given angle are returned. If \"inverse\" is true, "
|
||||
"edge pairs not with the given angle are returned.\n"
|
||||
"\n"
|
||||
"The angle is measured between the two edges. Antiparallel edges have an angle of 0, parallel ones an angle of 180 or -180 degree (whichever fits). "
|
||||
"For other configurations, the angle is determined by thinking of the edges as emerging from the same point: if the second edge is rotated clockwise "
|
||||
"against the first one, the angle is positive. If the second edge is rotated counterclockwise, the angle is negative. This way, the same angle "
|
||||
"definition applies to edges at a corner of a polygon and the same edges appearing in an edge pair.\n"
|
||||
"The angle is measured between the two edges. It is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.2.\n"
|
||||
) +
|
||||
|
|
@ -737,10 +734,7 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"edge pairs with an angle between min_angle and max_angle (max_angle itself is excluded) are returned. If \"inverse\" is true, "
|
||||
"edge pairs not fulfilling this criterion are returned.\n"
|
||||
"\n"
|
||||
"The angle is measured between the two edges. Antiparallel edges have an angle of 0, parallel ones an angle of 180 or -180 degree (whichever fits). "
|
||||
"For other configurations, the angle is determined by thinking of the edges as emerging from the same point: if the second edge is rotated clockwise "
|
||||
"against the first one, the angle is positive. If the second edge is rotated counterclockwise, the angle is negative. This way, the same angle "
|
||||
"definition applies to edges at a corner of a polygon and the same edges appearing in an edge pair.\n"
|
||||
"The angle is measured between the two edges. It is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).\n"
|
||||
"\n"
|
||||
"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_angle\" where the default is false, meaning the maximum angle is not included in the range.\n"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "tlUnitTest.h"
|
||||
|
||||
#include "dbEdgePairs.h"
|
||||
#include "dbEdgePairFilters.h"
|
||||
#include "dbEdges.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbTestSupport.h"
|
||||
|
|
@ -160,3 +161,42 @@ TEST(4)
|
|||
db::Region r (db::RecursiveShapeIterator (ly, ly.cell (top_cell), l1));
|
||||
EXPECT_EQ (db::compare (r, "(-10,-21;9,20;50,51;91,80);(-10,-21;9,20;110,121;91,80)"), true);
|
||||
}
|
||||
|
||||
TEST(5_InternalAngleFilter)
|
||||
{
|
||||
db::EdgePair ep0 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (100, 0), db::Point (0, 0)));
|
||||
db::EdgePair ep45 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, 100)));
|
||||
db::EdgePair ep180 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (100, 0)));
|
||||
db::EdgePair ep90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 0), db::Point (0, 100)));
|
||||
db::EdgePair epm90 (db::Edge (db::Point (0, 0), db::Point (100, 0)), db::Edge (db::Point (0, 100), db::Point (0, 0)));
|
||||
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep0), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep180), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (epm90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, false).selected (ep45), false);
|
||||
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep0), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep180), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep90), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (epm90), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (90.0, false).selected (ep45), false);
|
||||
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep0), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep180), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (epm90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (45.0, false).selected (ep45), true);
|
||||
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep0), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep180), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep90), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (epm90), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true).selected (ep45), true);
|
||||
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep0), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep180), true);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (epm90), false);
|
||||
EXPECT_EQ (db::InternalAngleEdgePairFilter (0.0, true, 45.0, true, false).selected (ep45), true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,28 +330,30 @@ module DRC
|
|||
|
||||
# %DRC%
|
||||
# @name with_area
|
||||
# @brief Selects polygons by area
|
||||
# @brief Selects polygons or edge pairs by area
|
||||
# @synopsis layer.with_area(min .. max)
|
||||
# @synopsis layer.with_area(value)
|
||||
# @synopsis layer.with_area(min, max)
|
||||
# The first form will select all polygons with an area larger or
|
||||
# The first form will select all polygons or edge pairs with an area larger or
|
||||
# equal to min and less (but not equal to) max. The second form
|
||||
# will select the polygons with exactly the given area.
|
||||
# will select the polygons or edge pairs with exactly the given area.
|
||||
# The third form basically is equivalent to the first form, but
|
||||
# allows specification of nil for min or max indicating no lower or
|
||||
# upper limit.
|
||||
#
|
||||
# This method is available for polygon or edge pair layers.
|
||||
|
||||
# %DRC%
|
||||
# @name without_area
|
||||
# @brief Selects polygons by area
|
||||
# @brief Selects polygons or edge pairs by area
|
||||
# @synopsis layer.without_area(min .. max)
|
||||
# @synopsis layer.without_area(value)
|
||||
# @synopsis layer.without_area(min, max)
|
||||
# This method is the inverse of "with_area". It will select
|
||||
# polygons without an area equal to the given one or outside
|
||||
# polygons or edge pairs without an area equal to the given one or outside
|
||||
# the given interval.
|
||||
#
|
||||
# This method is available for polygon layers only.
|
||||
# This method is available for polygon or edge pair layers.
|
||||
|
||||
%w(area).each do |f|
|
||||
[true, false].each do |inv|
|
||||
|
|
@ -361,7 +363,8 @@ module DRC
|
|||
|
||||
@engine._context("#{mn}") do
|
||||
|
||||
requires_region
|
||||
self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge pair or polygon layer")
|
||||
|
||||
if args.size == 1
|
||||
a = args[0]
|
||||
if a.is_a?(Range)
|
||||
|
|
@ -857,7 +860,7 @@ CODE
|
|||
# @synopsis layer.with_angle(min .. max)
|
||||
# @synopsis layer.with_angle(value)
|
||||
# @synopsis layer.with_angle(min, max)
|
||||
# @synopsis edge_pairlayer.with_angle(min, max [, both])
|
||||
# @synopsis edge_pair_layer.with_angle(min, max [, both])
|
||||
#
|
||||
# When called on an edge layer, the method selects edges by their angle,
|
||||
# measured against the horizontal axis in the mathematical sense.
|
||||
|
|
@ -871,10 +874,6 @@ CODE
|
|||
# The second version selects edges with exactly the given angle. The third
|
||||
# version is identical to the first one.
|
||||
#
|
||||
# When called on a polygon layer, this method selects corners which match the
|
||||
# given angle or is within the given angle interval. The angle is measured between the edges forming the corner.
|
||||
# For each corner, an edge pair containing the edges forming in the angle is returned.
|
||||
#
|
||||
# When called on an edge pair layer, this method selects edge pairs with one or both edges
|
||||
# meeting the angle criterion. In this case an additional argument is accepted which can be
|
||||
# either "both" (plain word) to indicate that both edges have to be within the given interval.
|
||||
|
|
@ -903,6 +902,9 @@ CODE
|
|||
# @td @img(/images/drc_with_angle4.png) @/td
|
||||
# @/tr
|
||||
# @/table
|
||||
#
|
||||
# Note that in former versions, with_angle could be used on polygon layers selecting corners with specific angles.
|
||||
# This feature has been deprecated. Use \corners instead.
|
||||
|
||||
# %DRC%
|
||||
# @name without_angle
|
||||
|
|
@ -910,11 +912,12 @@ CODE
|
|||
# @synopsis layer.without_angle(min .. max)
|
||||
# @synopsis layer.without_angle(value)
|
||||
# @synopsis layer.without_angle(min, max)
|
||||
# @synopsis edge_pairlayer.without_angle(min, max [, both])
|
||||
# @synopsis edge_pair_layer.without_angle(min, max [, both])
|
||||
#
|
||||
# The method basically is the inverse of \with_angle. It selects all edges
|
||||
# of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle
|
||||
# is not inside the given interval (first and third form).
|
||||
# is not inside the given interval (first and third form). When called on edge pairs, it selects
|
||||
# edge pairs by the angles of their edges.
|
||||
#
|
||||
# A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||
# both edges need to be "without_angle". For example
|
||||
|
|
@ -925,8 +928,41 @@ CODE
|
|||
# ep = edge_pairs.without_angle(0, both)
|
||||
# @/code
|
||||
#
|
||||
# See \with_internal_angle and \without_internal_angle to select edge pairs by the
|
||||
# angle between the edges.
|
||||
|
||||
%w(angle).each do |f|
|
||||
# %DRC%
|
||||
# @name with_internal_angle
|
||||
# @brief Selects edge pairs by their internal angle
|
||||
# @synopsis edge_pair_layer.with_internal_angle(min .. max)
|
||||
# @synopsis edge_pair_layer.with_internal_angle(value)
|
||||
# @synopsis edge_pair_layer.with_internal_angle(min, max)
|
||||
#
|
||||
# This method selects edge pairs by the angle enclosed by their edges.
|
||||
# The angle is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).
|
||||
# If an interval or two values are given, the angle is checked to be within the given
|
||||
# range.
|
||||
#
|
||||
# Here are examples for "with_internal_angle" on edge pair layers:
|
||||
#
|
||||
# @code
|
||||
# # selects edge pairs with parallel edges
|
||||
# ep1 = edge_pairs.with_internal_angle(0)
|
||||
# # selects edge pairs with perpendicular edges
|
||||
# ep2 = edge_pairs.with_internal_angle(90)
|
||||
# @/code
|
||||
|
||||
# %DRC%
|
||||
# @name without_internal_angle
|
||||
# @brief Selects edge pairs by their internal angle
|
||||
# @synopsis edge_pair_layer.without_internal_angle(min .. max)
|
||||
# @synopsis edge_pair_layer.without_internal_angle(value)
|
||||
# @synopsis edge_pair_layer.without_internal_angle(min, max)
|
||||
#
|
||||
# The method basically is the inverse of \with_internal_angle. It selects all
|
||||
# edge pairs by the angle enclosed by their edges, applying the opposite criterion than \with_internal_angle.
|
||||
|
||||
%w(angle internal_angle).each do |f|
|
||||
[true, false].each do |inv|
|
||||
mn = (inv ? "without" : "with") + "_" + f
|
||||
eval <<"CODE"
|
||||
|
|
@ -935,16 +971,22 @@ CODE
|
|||
@engine._context("#{mn}") do
|
||||
|
||||
f = :with_#{f}
|
||||
args = args.select do |a|
|
||||
if a.is_a?(DRCBothEdges)
|
||||
if !self.data.is_a?(RBA::EdgePairs)
|
||||
raise("'both' keyword only available for edge pair layers")
|
||||
|
||||
if "#{f}" == "angle"
|
||||
self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::EdgePairs) || raise("Requires an edge, edge pair or polygon layer")
|
||||
args = args.select do |a|
|
||||
if a.is_a?(DRCBothEdges)
|
||||
if !self.data.is_a?(RBA::EdgePairs)
|
||||
raise("'both' keyword only available for edge pair layers")
|
||||
end
|
||||
f = :with_#{f}_both
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
f = :with_#{f}_both
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
else
|
||||
requires_edge_pairs
|
||||
end
|
||||
|
||||
result_class = self.data.is_a?(RBA::Edges) ? RBA::Edges : RBA::EdgePairs
|
||||
|
|
|
|||
|
|
@ -1283,12 +1283,12 @@ TEST(48d_drcWithFragments)
|
|||
run_test (_this, "48", true);
|
||||
}
|
||||
|
||||
TEST(49_drcWithFragments)
|
||||
TEST(49_epAngle)
|
||||
{
|
||||
run_test (_this, "49", false);
|
||||
}
|
||||
|
||||
TEST(49d_drcWithFragments)
|
||||
TEST(49d_epAngle)
|
||||
{
|
||||
run_test (_this, "49", true);
|
||||
}
|
||||
|
|
@ -1298,3 +1298,8 @@ TEST(50_issue826)
|
|||
run_test (_this, "50", false);
|
||||
}
|
||||
|
||||
TEST(51_epInternalAngle)
|
||||
{
|
||||
run_test (_this, "51", false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3157,7 +3157,7 @@ Shielding is enabled by default, but can be switched off with the "transparent"
|
|||
<li><tt>layer.with_angle(min .. max)</tt></li>
|
||||
<li><tt>layer.with_angle(value)</tt></li>
|
||||
<li><tt>layer.with_angle(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.with_angle(min, max [, both])</tt></li>
|
||||
<li><tt>edge_pair_layer.with_angle(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
When called on an edge layer, the method selects edges by their angle,
|
||||
|
|
@ -3172,10 +3172,6 @@ edges with a angle larger or equal to min and less than max (but not equal).
|
|||
The second version selects edges with exactly the given angle. The third
|
||||
version is identical to the first one.
|
||||
</p><p>
|
||||
When called on a polygon layer, this method selects corners which match the
|
||||
given angle or is within the given angle interval. The angle is measured between the edges forming the corner.
|
||||
For each corner, an edge pair containing the edges forming in the angle is returned.
|
||||
</p><p>
|
||||
When called on an edge pair layer, this method selects edge pairs with one or both edges
|
||||
meeting the angle criterion. In this case an additional argument is accepted which can be
|
||||
either "both" (plain word) to indicate that both edges have to be within the given interval.
|
||||
|
|
@ -3204,8 +3200,11 @@ The following images demonstrate some use cases of <a href="#with_angle">with_an
|
|||
<td><img src="/images/drc_with_angle4.png"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p><p>
|
||||
Note that in former versions, with_angle could be used on polygon layers selecting corners with specific angles.
|
||||
This feature has been deprecated. Use <a href="#corners">corners</a> instead.
|
||||
</p>
|
||||
<a name="with_area"/><h2>"with_area" - Selects polygons by area</h2>
|
||||
<a name="with_area"/><h2>"with_area" - Selects polygons or edge pairs by area</h2>
|
||||
<keyword name="with_area"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
|
|
@ -3214,12 +3213,14 @@ The following images demonstrate some use cases of <a href="#with_angle">with_an
|
|||
<li><tt>layer.with_area(min, max)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The first form will select all polygons with an area larger or
|
||||
The first form will select all polygons or edge pairs with an area larger or
|
||||
equal to min and less (but not equal to) max. The second form
|
||||
will select the polygons with exactly the given area.
|
||||
will select the polygons or edge pairs with exactly the given area.
|
||||
The third form basically is equivalent to the first form, but
|
||||
allows specification of nil for min or max indicating no lower or
|
||||
upper limit.
|
||||
</p><p>
|
||||
This method is available for polygon or edge pair layers.
|
||||
</p>
|
||||
<a name="with_area_ratio"/><h2>"with_area_ratio" - Selects polygons by the ratio of the bounding box area vs. polygon area</h2>
|
||||
<keyword name="with_area_ratio"/>
|
||||
|
|
@ -3334,7 +3335,7 @@ The tile size must be specified with the "tile_size" option:
|
|||
</p><p>
|
||||
<pre>
|
||||
# reports areas where layer 1/0 density is below 10% on 20x20 um tiles
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um))
|
||||
low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um))
|
||||
</pre>
|
||||
</p><p>
|
||||
Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
|
||||
|
|
@ -3348,7 +3349,7 @@ in increments of the tile step:
|
|||
<pre>
|
||||
# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
|
||||
# with a tile step of 20x20 um:
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
|
||||
low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(30.um), tile_step(20.um))
|
||||
</pre>
|
||||
</p><p>
|
||||
For "tile_step", anisotropic values can be given as well by using two values: the first for the
|
||||
|
|
@ -3366,7 +3367,7 @@ drawn boundary layer. To specify a separate, additional layer included in the bo
|
|||
# reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
|
||||
# layer 0/0:
|
||||
cell_frame = input(0, 0)
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
|
||||
low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), tile_boundary(cell_frame))
|
||||
</pre>
|
||||
</p><p>
|
||||
Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
|
||||
|
|
@ -3378,7 +3379,7 @@ direction. With the "tile_origin" option this allows full control over the area
|
|||
<pre>
|
||||
# reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
|
||||
# (100 and 150 tiles of 20 um each are used in horizontal and vertical direction):
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
|
||||
low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), tile_origin(0.0, 0.0), tile_count(100, 150))
|
||||
</pre>
|
||||
</p><p>
|
||||
The "padding mode" indicates how the area outside the layout's bounding box is considered.
|
||||
|
|
@ -3392,7 +3393,7 @@ There are two modes:
|
|||
Example:
|
||||
</p><p>
|
||||
<pre>
|
||||
low_density = input(1, 0).density(0.0 .. 0.1, tile_size(20.um), padding_ignore)
|
||||
low_density = input(1, 0).with_density(0.0 .. 0.1, tile_size(20.um), padding_ignore)
|
||||
</pre>
|
||||
</p><p>
|
||||
The complementary version of "with_density" is <a href="#without_density">without_density</a>.
|
||||
|
|
@ -3430,6 +3431,29 @@ This method is available for edge pair layers only.
|
|||
This method is available for polygon layers. It will select all polygons from the input layer
|
||||
which have the specified number of holes.
|
||||
</p>
|
||||
<a name="with_internal_angle"/><h2>"with_internal_angle" - Selects edge pairs by their internal angle</h2>
|
||||
<keyword name="with_internal_angle"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>edge_pair_layer.with_internal_angle(min .. max)</tt></li>
|
||||
<li><tt>edge_pair_layer.with_internal_angle(value)</tt></li>
|
||||
<li><tt>edge_pair_layer.with_internal_angle(min, max)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
This method selects edge pairs by the angle enclosed by their edges.
|
||||
The angle is between 0 (parallel or anti-parallel edges) and 90 degree (perpendicular edges).
|
||||
If an interval or two values are given, the angle is checked to be within the given
|
||||
range.
|
||||
</p><p>
|
||||
Here are examples for "with_internal_angle" on edge pair layers:
|
||||
</p><p>
|
||||
<pre>
|
||||
# selects edge pairs with parallel edges
|
||||
ep1 = edge_pairs.with_internal_angle(0)
|
||||
# selects edge pairs with perpendicular edges
|
||||
ep2 = edge_pairs.with_internal_angle(90)
|
||||
</pre>
|
||||
</p>
|
||||
<a name="with_length"/><h2>"with_length" - Selects edges by their length</h2>
|
||||
<keyword name="with_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
@ -3505,12 +3529,13 @@ This method is available for polygon layers only.
|
|||
<li><tt>layer.without_angle(min .. max)</tt></li>
|
||||
<li><tt>layer.without_angle(value)</tt></li>
|
||||
<li><tt>layer.without_angle(min, max)</tt></li>
|
||||
<li><tt>edge_pairlayer.without_angle(min, max [, both])</tt></li>
|
||||
<li><tt>edge_pair_layer.without_angle(min, max [, both])</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method basically is the inverse of <a href="#with_angle">with_angle</a>. It selects all edges
|
||||
of the edge layer or corners of the polygons which do not have the given angle (second form) or whose angle
|
||||
is not inside the given interval (first and third form).
|
||||
is not inside the given interval (first and third form). When called on edge pairs, it selects
|
||||
edge pairs by the angles of their edges.
|
||||
</p><p>
|
||||
A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||
both edges need to be "without_angle". For example
|
||||
|
|
@ -3520,8 +3545,11 @@ both edges need to be "without_angle". For example
|
|||
# the edge pair is skipped if one edge is horizontal
|
||||
ep = edge_pairs.without_angle(0, both)
|
||||
</pre>
|
||||
</p><p>
|
||||
See <a href="#with_internal_angle">with_internal_angle</a> and <a href="#without_internal_angle">without_internal_angle</a> to select edge pairs by the
|
||||
angle between the edges.
|
||||
</p>
|
||||
<a name="without_area"/><h2>"without_area" - Selects polygons by area</h2>
|
||||
<a name="without_area"/><h2>"without_area" - Selects polygons or edge pairs by area</h2>
|
||||
<keyword name="without_area"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
|
|
@ -3531,10 +3559,10 @@ ep = edge_pairs.without_angle(0, both)
|
|||
</ul>
|
||||
<p>
|
||||
This method is the inverse of "with_area". It will select
|
||||
polygons without an area equal to the given one or outside
|
||||
polygons or edge pairs without an area equal to the given one or outside
|
||||
the given interval.
|
||||
</p><p>
|
||||
This method is available for polygon layers only.
|
||||
This method is available for polygon or edge pair layers.
|
||||
</p>
|
||||
<a name="without_area_ratio"/><h2>"without_area_ratio" - Selects polygons by the aspect ratio of their bounding box</h2>
|
||||
<keyword name="without_area_ratio"/>
|
||||
|
|
@ -3647,6 +3675,18 @@ This method is available for edge pair layers only.
|
|||
This method is available for polygon layers. It will select all polygons from the input layer
|
||||
which do not have the specified number of holes.
|
||||
</p>
|
||||
<a name="without_internal_angle"/><h2>"without_internal_angle" - Selects edge pairs by their internal angle</h2>
|
||||
<keyword name="without_internal_angle"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>edge_pair_layer.without_internal_angle(min .. max)</tt></li>
|
||||
<li><tt>edge_pair_layer.without_internal_angle(value)</tt></li>
|
||||
<li><tt>edge_pair_layer.without_internal_angle(min, max)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The method basically is the inverse of <a href="#with_internal_angle">with_internal_angle</a>. It selects all
|
||||
edge pairs by the angle enclosed by their edges, applying the opposite criterion than <a href="#with_internal_angle">with_internal_angle</a>.
|
||||
</p>
|
||||
<a name="without_length"/><h2>"without_length" - Selects edges by the their length</h2>
|
||||
<keyword name="without_length"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
source $drc_test_source
|
||||
target $drc_test_target
|
||||
|
||||
if $drc_test_deep
|
||||
deep
|
||||
end
|
||||
|
||||
ep = input(1, 0).drc(sep(input(2, 0), angle_limit(91)) < 0.5)
|
||||
|
||||
input(1, 0).output(1, 0)
|
||||
input(2, 0).output(2, 0)
|
||||
|
||||
ep.polygons(0).output(100, 0)
|
||||
|
||||
ep.with_internal_angle(45.0).polygons(0).output(200, 0)
|
||||
ep.with_internal_angle(0.0).polygons(0).output(201, 0)
|
||||
ep.with_internal_angle(45.0..91.0).polygons(0).output(202, 0)
|
||||
|
||||
ep.without_internal_angle(45.0).polygons(0).output(220, 0)
|
||||
ep.without_internal_angle(0.0).polygons(0).output(221, 0)
|
||||
ep.without_internal_angle(45.0..91.0).polygons(0).output(222, 0)
|
||||
|
||||
ep.with_area(0 .. 0.1).polygons(0).output(300, 0)
|
||||
ep.without_area(0 .. 0.1).polygons(0).output(301, 0)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -268,13 +268,9 @@ class DBEdgePairs_TestClass < TestBase
|
|||
assert_equal(r1.with_area(150, 150, false).to_s, "")
|
||||
assert_equal(r1.with_area(150, 151, true).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)")
|
||||
|
||||
assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,20)/(10,20;10,0)")
|
||||
assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)")
|
||||
assert_equal(r1.with_internal_angle(0, 0, false).to_s, "")
|
||||
assert_equal(r1.with_internal_angle(0, 180, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,20)/(10,20;10,0)")
|
||||
assert_equal(r1.with_internal_angle(0, 180, false, true, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,20)/(10,20;10,0);(0,0;0,10)/(10,0;10,10)")
|
||||
assert_equal(r1.with_internal_angle(180, false).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)")
|
||||
assert_equal(r1.with_internal_angle(-180, false).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)")
|
||||
assert_equal(r1.with_internal_angle(0, true).to_s, "(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)")
|
||||
assert_equal(r1.with_internal_angle(0, true).to_s, "")
|
||||
|
||||
ep1 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(10, 20, 10, 0))
|
||||
ep2 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(20, 0, 30, 0))
|
||||
|
|
@ -286,8 +282,8 @@ class DBEdgePairs_TestClass < TestBase
|
|||
assert_equal(r1.with_distance(20, true).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||
|
||||
assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||
assert_equal(r1.with_internal_angle(90, false).to_s, "(0,0;0,10)/(20,0;30,0)")
|
||||
assert_equal(r1.with_internal_angle(-90, false).to_s, "(0,0;0,10)/(-20,0;-30,0)")
|
||||
assert_equal(r1.with_internal_angle(90, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)")
|
||||
assert_equal(r1.with_internal_angle(-90, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)")
|
||||
|
||||
assert_equal(r1.with_angle(90, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)")
|
||||
assert_equal(r1.with_angle(0, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)")
|
||||
|
|
@ -295,6 +291,18 @@ class DBEdgePairs_TestClass < TestBase
|
|||
assert_equal(r1.with_angle_both(90, false).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||
assert_equal(r1.with_angle_both(0, false).to_s, "")
|
||||
|
||||
ep1 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(10, 20, 10, 0))
|
||||
ep2 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(20, 10, 30, 0))
|
||||
|
||||
r1 = RBA::EdgePairs::new([ ep1, ep2 ])
|
||||
|
||||
assert_equal(r1.with_internal_angle(0, false).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||
assert_equal(r1.with_internal_angle(90, false).to_s, "")
|
||||
assert_equal(r1.with_internal_angle(90, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,10;30,0)")
|
||||
assert_equal(r1.with_internal_angle(45, false).to_s, "(0,0;0,10)/(20,10;30,0)")
|
||||
assert_equal(r1.with_internal_angle(0, 45, false, true, true).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(20,10;30,0)")
|
||||
assert_equal(r1.with_internal_angle(0, 45, true, true, true).to_s, "")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue