mirror of https://github.com/KLayout/klayout.git
Merge pull request #847 from KLayout/more-edge-pair-filters
More edge pair filters
This commit is contained in:
commit
fb9c0077eb
|
|
@ -78,4 +78,51 @@ bool EdgePairFilterByDistance::selected (const db::EdgePair &edge_pair) const
|
||||||
return m_inverted ? !sel : sel;
|
return m_inverted ? !sel : sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------
|
||||||
|
// EdgePairFilterByArea implementation
|
||||||
|
|
||||||
|
EdgePairFilterByArea::EdgePairFilterByArea (area_type min_area, area_type max_area, bool inverted)
|
||||||
|
: m_min_area (min_area), m_max_area (max_area), m_inverted (inverted)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EdgePairFilterByArea::selected (const db::EdgePair &edge_pair) const
|
||||||
|
{
|
||||||
|
area_type dist = edge_pair.to_simple_polygon (0).area ();
|
||||||
|
bool sel = (dist >= m_min_area && dist < m_max_area);
|
||||||
|
return m_inverted ? !sel : sel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------
|
||||||
|
// EdgePairFilterByArea implementation
|
||||||
|
|
||||||
|
InternalAngleEdgePairFilter::InternalAngleEdgePairFilter (double a, bool inverted)
|
||||||
|
: m_inverted (inverted), m_checker (a, true, a, true)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalAngleEdgePairFilter::InternalAngleEdgePairFilter (double amin, bool include_amin, double amax, bool include_amax, bool inverted)
|
||||||
|
: m_inverted (inverted), m_checker (amin, include_amin, amax, include_amax)
|
||||||
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
InternalAngleEdgePairFilter::selected (const db::EdgePair &edge_pair) const
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#define HDR_dbEdgePairFilters
|
#define HDR_dbEdgePairFilters
|
||||||
|
|
||||||
#include "dbEdgePairs.h"
|
#include "dbEdgePairs.h"
|
||||||
|
#include "dbEdgesUtils.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -69,12 +70,57 @@ public:
|
||||||
EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, bool inverted);
|
EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, bool inverted);
|
||||||
|
|
||||||
virtual bool selected (const db::EdgePair &edge_pair) const;
|
virtual bool selected (const db::EdgePair &edge_pair) const;
|
||||||
virtual const TransformationReducer *vars () const { return 0; }
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
||||||
virtual bool wants_variants () const { return false; }
|
virtual bool wants_variants () const { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
distance_type m_min_distance, m_max_distance;
|
distance_type m_min_distance, m_max_distance;
|
||||||
bool m_inverted;
|
bool m_inverted;
|
||||||
|
db::MagnificationReducer m_vars;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Filters edge pairs based on the distance of the edges.
|
||||||
|
*
|
||||||
|
* The distance is measured as the smallest distance between each of the points of the two edges.
|
||||||
|
*/
|
||||||
|
class DB_PUBLIC EdgePairFilterByArea
|
||||||
|
: public EdgePairFilterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef db::coord_traits<db::Coord>::area_type area_type;
|
||||||
|
|
||||||
|
EdgePairFilterByArea (area_type min_area, area_type max_area, bool inverted);
|
||||||
|
|
||||||
|
virtual bool selected (const db::EdgePair &edge_pair) const;
|
||||||
|
virtual const TransformationReducer *vars () const { return &m_vars; }
|
||||||
|
virtual bool wants_variants () const { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
area_type m_min_area, m_max_area;
|
||||||
|
bool m_inverted;
|
||||||
|
db::MagnificationReducer m_vars;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Filters edge pairs based on the distance of the edges.
|
||||||
|
*
|
||||||
|
* The distance is measured as the smallest distance between each of the points of the two edges.
|
||||||
|
*/
|
||||||
|
class DB_PUBLIC InternalAngleEdgePairFilter
|
||||||
|
: public EdgePairFilterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InternalAngleEdgePairFilter (double a, bool inverted);
|
||||||
|
InternalAngleEdgePairFilter (double amin, bool include_amin, double amax, bool include_amax, bool inverted);
|
||||||
|
|
||||||
|
virtual bool selected (const db::EdgePair &edge_pair) const;
|
||||||
|
virtual const TransformationReducer *vars () const { return 0; }
|
||||||
|
virtual bool wants_variants () const { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_inverted;
|
||||||
|
db::EdgeAngleChecker m_checker;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,6 @@ struct DB_PUBLIC EdgeOrientationFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
db::DVector m_emin, m_emax;
|
|
||||||
bool m_inverse;
|
bool m_inverse;
|
||||||
db::MagnificationAndOrientationReducer m_vars;
|
db::MagnificationAndOrientationReducer m_vars;
|
||||||
EdgeAngleChecker m_checker;
|
EdgeAngleChecker m_checker;
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,30 @@ static db::EdgePairs with_angle_both2 (const db::EdgePairs *r, double amin, doub
|
||||||
return r->filtered (ef);
|
return r->filtered (ef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static db::EdgePairs with_internal_angle1 (const db::EdgePairs *r, double a, bool inverse)
|
||||||
|
{
|
||||||
|
db::InternalAngleEdgePairFilter f (a, inverse);
|
||||||
|
return r->filtered (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static db::EdgePairs with_internal_angle2 (const db::EdgePairs *r, double amin, double amax, bool inverse, bool include_amin, bool include_amax)
|
||||||
|
{
|
||||||
|
db::InternalAngleEdgePairFilter f (amin, include_amin, amax, include_amax, inverse);
|
||||||
|
return r->filtered (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static db::EdgePairs with_area1 (const db::EdgePairs *r, db::EdgePair::area_type a, bool inverse)
|
||||||
|
{
|
||||||
|
db::EdgePairFilterByArea f (a, a + 1, inverse);
|
||||||
|
return r->filtered (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static db::EdgePairs with_area2 (const db::EdgePairs *r, db::EdgePair::area_type amin, db::EdgePair::area_type amax, bool inverse)
|
||||||
|
{
|
||||||
|
db::EdgePairFilterByArea f (amin, amax, inverse);
|
||||||
|
return r->filtered (f);
|
||||||
|
}
|
||||||
|
|
||||||
extern Class<db::ShapeCollection> decl_dbShapeCollection;
|
extern Class<db::ShapeCollection> decl_dbShapeCollection;
|
||||||
|
|
||||||
Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
||||||
|
|
@ -621,7 +645,7 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
||||||
method_ext ("with_distance", with_distance2, gsi::arg ("min_distance"), gsi::arg ("max_distance"), gsi::arg ("inverse"),
|
method_ext ("with_distance", with_distance2, gsi::arg ("min_distance"), gsi::arg ("max_distance"), gsi::arg ("inverse"),
|
||||||
"@brief Filters the edge pairs by the distance of the edges\n"
|
"@brief Filters the edge pairs by the distance of the edges\n"
|
||||||
"Filters the edge pairs in the edge pair collection by distance of the edges. If \"inverse\" is false, only "
|
"Filters the edge pairs in the edge pair collection by distance of the edges. If \"inverse\" is false, only "
|
||||||
"edge pairs where both edges have a distance between min_distance and max_distance (max_distance itself is excluded). If \"inverse\" is true, "
|
"edge pairs where both edges have a distance between min_distance and max_distance (max_distance itself is excluded) are returned. If \"inverse\" is true, "
|
||||||
"edge pairs not fulfilling this criterion are returned.\n"
|
"edge pairs not fulfilling this criterion are returned.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Distance is measured as the shortest distance between any of the points on the edges.\n"
|
"Distance is measured as the shortest distance between any of the points on the edges.\n"
|
||||||
|
|
@ -678,6 +702,45 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.27.1.\n"
|
"This method has been added in version 0.27.1.\n"
|
||||||
) +
|
) +
|
||||||
|
method_ext ("with_area", with_area1, gsi::arg ("area"), gsi::arg ("inverse"),
|
||||||
|
"@brief Filters the edge pairs by the enclosed area\n"
|
||||||
|
"Filters the edge pairs in the edge pair collection by enclosed area. If \"inverse\" is false, only "
|
||||||
|
"edge pairs with the given area are returned. If \"inverse\" is true, "
|
||||||
|
"edge pairs not with the given area are returned.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been added in version 0.27.2.\n"
|
||||||
|
) +
|
||||||
|
method_ext ("with_area", with_area2, gsi::arg ("min_area"), gsi::arg ("max_area"), gsi::arg ("inverse"),
|
||||||
|
"@brief Filters the edge pairs by the enclosed area\n"
|
||||||
|
"Filters the edge pairs in the edge pair collection by enclosed area. If \"inverse\" is false, only "
|
||||||
|
"edge pairs with an area between min_area and max_area (max_area itself is excluded) are returned. If \"inverse\" is true, "
|
||||||
|
"edge pairs not fulfilling this criterion are returned.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been added in version 0.27.2.\n"
|
||||||
|
) +
|
||||||
|
method_ext ("with_internal_angle", with_internal_angle1, gsi::arg ("angle"), gsi::arg ("inverse"),
|
||||||
|
"@brief Filters the edge pairs by the angle between their edges\n"
|
||||||
|
"Filters the edge pairs in the edge pair collection by the angle between their edges. If \"inverse\" is false, only "
|
||||||
|
"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. 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"
|
||||||
|
) +
|
||||||
|
method_ext ("with_internal_angle", with_internal_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 Filters the edge pairs by the angle between their edges\n"
|
||||||
|
"Filters the edge pairs in the edge pair collection by the angle between their edges. If \"inverse\" is false, only "
|
||||||
|
"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. 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"
|
||||||
|
"\n"
|
||||||
|
"This method has been added in version 0.27.2.\n"
|
||||||
|
) +
|
||||||
method_ext ("polygons", &polygons1,
|
method_ext ("polygons", &polygons1,
|
||||||
"@brief Converts the edge pairs to polygons\n"
|
"@brief Converts the edge pairs to polygons\n"
|
||||||
"This method creates polygons from the edge pairs. Each polygon will be a triangle or quadrangle "
|
"This method creates polygons from the edge pairs. Each polygon will be a triangle or quadrangle "
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
|
|
||||||
#include "dbEdgePairs.h"
|
#include "dbEdgePairs.h"
|
||||||
|
#include "dbEdgePairFilters.h"
|
||||||
#include "dbEdges.h"
|
#include "dbEdges.h"
|
||||||
#include "dbRegion.h"
|
#include "dbRegion.h"
|
||||||
#include "dbTestSupport.h"
|
#include "dbTestSupport.h"
|
||||||
|
|
@ -160,3 +161,42 @@ TEST(4)
|
||||||
db::Region r (db::RecursiveShapeIterator (ly, ly.cell (top_cell), l1));
|
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);
|
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%
|
# %DRC%
|
||||||
# @name with_area
|
# @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(min .. max)
|
||||||
# @synopsis layer.with_area(value)
|
# @synopsis layer.with_area(value)
|
||||||
# @synopsis layer.with_area(min, max)
|
# @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
|
# 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
|
# The third form basically is equivalent to the first form, but
|
||||||
# allows specification of nil for min or max indicating no lower or
|
# allows specification of nil for min or max indicating no lower or
|
||||||
# upper limit.
|
# upper limit.
|
||||||
|
#
|
||||||
|
# This method is available for polygon or edge pair layers.
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name without_area
|
# @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(min .. max)
|
||||||
# @synopsis layer.without_area(value)
|
# @synopsis layer.without_area(value)
|
||||||
# @synopsis layer.without_area(min, max)
|
# @synopsis layer.without_area(min, max)
|
||||||
# This method is the inverse of "with_area". It will select
|
# 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.
|
# 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|
|
%w(area).each do |f|
|
||||||
[true, false].each do |inv|
|
[true, false].each do |inv|
|
||||||
|
|
@ -361,7 +363,8 @@ module DRC
|
||||||
|
|
||||||
@engine._context("#{mn}") do
|
@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
|
if args.size == 1
|
||||||
a = args[0]
|
a = args[0]
|
||||||
if a.is_a?(Range)
|
if a.is_a?(Range)
|
||||||
|
|
@ -857,7 +860,7 @@ CODE
|
||||||
# @synopsis layer.with_angle(min .. max)
|
# @synopsis layer.with_angle(min .. max)
|
||||||
# @synopsis layer.with_angle(value)
|
# @synopsis layer.with_angle(value)
|
||||||
# @synopsis layer.with_angle(min, max)
|
# @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,
|
# When called on an edge layer, the method selects edges by their angle,
|
||||||
# measured against the horizontal axis in the mathematical sense.
|
# 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
|
# The second version selects edges with exactly the given angle. The third
|
||||||
# version is identical to the first one.
|
# 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
|
# 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
|
# 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.
|
# 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
|
# @td @img(/images/drc_with_angle4.png) @/td
|
||||||
# @/tr
|
# @/tr
|
||||||
# @/table
|
# @/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%
|
# %DRC%
|
||||||
# @name without_angle
|
# @name without_angle
|
||||||
|
|
@ -910,11 +912,12 @@ CODE
|
||||||
# @synopsis layer.without_angle(min .. max)
|
# @synopsis layer.without_angle(min .. max)
|
||||||
# @synopsis layer.without_angle(value)
|
# @synopsis layer.without_angle(value)
|
||||||
# @synopsis layer.without_angle(min, max)
|
# @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
|
# 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
|
# 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
|
# A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||||
# both edges need to be "without_angle". For example
|
# both edges need to be "without_angle". For example
|
||||||
|
|
@ -925,8 +928,41 @@ CODE
|
||||||
# ep = edge_pairs.without_angle(0, both)
|
# ep = edge_pairs.without_angle(0, both)
|
||||||
# @/code
|
# @/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|
|
[true, false].each do |inv|
|
||||||
mn = (inv ? "without" : "with") + "_" + f
|
mn = (inv ? "without" : "with") + "_" + f
|
||||||
eval <<"CODE"
|
eval <<"CODE"
|
||||||
|
|
@ -935,16 +971,22 @@ CODE
|
||||||
@engine._context("#{mn}") do
|
@engine._context("#{mn}") do
|
||||||
|
|
||||||
f = :with_#{f}
|
f = :with_#{f}
|
||||||
args = args.select do |a|
|
|
||||||
if a.is_a?(DRCBothEdges)
|
if "#{f}" == "angle"
|
||||||
if !self.data.is_a?(RBA::EdgePairs)
|
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")
|
||||||
raise("'both' keyword only available for edge pair layers")
|
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
|
end
|
||||||
f = :with_#{f}_both
|
|
||||||
false
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
requires_edge_pairs
|
||||||
end
|
end
|
||||||
|
|
||||||
result_class = self.data.is_a?(RBA::Edges) ? RBA::Edges : RBA::EdgePairs
|
result_class = self.data.is_a?(RBA::Edges) ? RBA::Edges : RBA::EdgePairs
|
||||||
|
|
|
||||||
|
|
@ -1283,12 +1283,12 @@ TEST(48d_drcWithFragments)
|
||||||
run_test (_this, "48", true);
|
run_test (_this, "48", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(49_drcWithFragments)
|
TEST(49_epAngle)
|
||||||
{
|
{
|
||||||
run_test (_this, "49", false);
|
run_test (_this, "49", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(49d_drcWithFragments)
|
TEST(49d_epAngle)
|
||||||
{
|
{
|
||||||
run_test (_this, "49", true);
|
run_test (_this, "49", true);
|
||||||
}
|
}
|
||||||
|
|
@ -1298,3 +1298,8 @@ TEST(50_issue826)
|
||||||
run_test (_this, "50", false);
|
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(min .. max)</tt></li>
|
||||||
<li><tt>layer.with_angle(value)</tt></li>
|
<li><tt>layer.with_angle(value)</tt></li>
|
||||||
<li><tt>layer.with_angle(min, max)</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>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
When called on an edge layer, the method selects edges by their angle,
|
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
|
The second version selects edges with exactly the given angle. The third
|
||||||
version is identical to the first one.
|
version is identical to the first one.
|
||||||
</p><p>
|
</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
|
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
|
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.
|
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>
|
<td><img src="/images/drc_with_angle4.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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>
|
</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"/>
|
<keyword name="with_area"/>
|
||||||
<p>Usage:</p>
|
<p>Usage:</p>
|
||||||
<ul>
|
<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>
|
<li><tt>layer.with_area(min, max)</tt></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<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
|
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
|
The third form basically is equivalent to the first form, but
|
||||||
allows specification of nil for min or max indicating no lower or
|
allows specification of nil for min or max indicating no lower or
|
||||||
upper limit.
|
upper limit.
|
||||||
|
</p><p>
|
||||||
|
This method is available for polygon or edge pair layers.
|
||||||
</p>
|
</p>
|
||||||
<a name="with_area_ratio"/><h2>"with_area_ratio" - Selects polygons by the ratio of the bounding box area vs. polygon area</h2>
|
<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"/>
|
<keyword name="with_area_ratio"/>
|
||||||
|
|
@ -3334,7 +3335,7 @@ The tile size must be specified with the "tile_size" option:
|
||||||
</p><p>
|
</p><p>
|
||||||
<pre>
|
<pre>
|
||||||
# reports areas where layer 1/0 density is below 10% on 20x20 um tiles
|
# 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>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
Anisotropic tiles can be specified by giving two values, like "tile_size(10.um, 20.um)".
|
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>
|
<pre>
|
||||||
# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
|
# reports areas where layer 1/0 density is below 10% on 30x30 um tiles
|
||||||
# with a tile step of 20x20 um:
|
# 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>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
For "tile_step", anisotropic values can be given as well by using two values: the first for the
|
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
|
# reports density of layer 1/0 below 10% on 20x20 um tiles. The layout's boundary is taken from
|
||||||
# layer 0/0:
|
# layer 0/0:
|
||||||
cell_frame = input(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>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
Note that the layer given in "tile_boundary" adds to the input layer for computing the bounding box.
|
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>
|
<pre>
|
||||||
# reports density of layer 1/0 below 10% on 20x20 um tiles in the region 0,0 .. 2000,3000
|
# 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):
|
# (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>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
The "padding mode" indicates how the area outside the layout's bounding box is considered.
|
The "padding mode" indicates how the area outside the layout's bounding box is considered.
|
||||||
|
|
@ -3392,7 +3393,7 @@ There are two modes:
|
||||||
Example:
|
Example:
|
||||||
</p><p>
|
</p><p>
|
||||||
<pre>
|
<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>
|
</pre>
|
||||||
</p><p>
|
</p><p>
|
||||||
The complementary version of "with_density" is <a href="#without_density">without_density</a>.
|
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
|
This method is available for polygon layers. It will select all polygons from the input layer
|
||||||
which have the specified number of holes.
|
which have the specified number of holes.
|
||||||
</p>
|
</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>
|
<a name="with_length"/><h2>"with_length" - Selects edges by their length</h2>
|
||||||
<keyword name="with_length"/>
|
<keyword name="with_length"/>
|
||||||
<p>Usage:</p>
|
<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(min .. max)</tt></li>
|
||||||
<li><tt>layer.without_angle(value)</tt></li>
|
<li><tt>layer.without_angle(value)</tt></li>
|
||||||
<li><tt>layer.without_angle(min, max)</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>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
The method basically is the inverse of <a href="#with_angle">with_angle</a>. It selects all edges
|
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
|
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>
|
</p><p>
|
||||||
A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
A note on the "both" modifier (without_angle called on edge pairs): "both" means that
|
||||||
both edges need to be "without_angle". For example
|
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
|
# the edge pair is skipped if one edge is horizontal
|
||||||
ep = edge_pairs.without_angle(0, both)
|
ep = edge_pairs.without_angle(0, both)
|
||||||
</pre>
|
</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>
|
</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"/>
|
<keyword name="without_area"/>
|
||||||
<p>Usage:</p>
|
<p>Usage:</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -3531,10 +3559,10 @@ ep = edge_pairs.without_angle(0, both)
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
This method is the inverse of "with_area". It will select
|
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.
|
the given interval.
|
||||||
</p><p>
|
</p><p>
|
||||||
This method is available for polygon layers only.
|
This method is available for polygon or edge pair layers.
|
||||||
</p>
|
</p>
|
||||||
<a name="without_area_ratio"/><h2>"without_area_ratio" - Selects polygons by the aspect ratio of their bounding box</h2>
|
<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"/>
|
<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
|
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.
|
which do not have the specified number of holes.
|
||||||
</p>
|
</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>
|
<a name="without_length"/><h2>"without_length" - Selects edges by the their length</h2>
|
||||||
<keyword name="without_length"/>
|
<keyword name="without_length"/>
|
||||||
<p>Usage:</p>
|
<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.
|
|
@ -225,6 +225,86 @@ class DBEdgePairs_TestClass < TestBase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_5
|
||||||
|
|
||||||
|
# filters
|
||||||
|
|
||||||
|
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(10, 0, 10, 20))
|
||||||
|
ep3 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 20), RBA::Edge::new(10, 20, 10, 0))
|
||||||
|
ep4 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(10, 0, 10, 10))
|
||||||
|
|
||||||
|
r1 = RBA::EdgePairs::new([ ep1, ep2, ep3, ep4 ])
|
||||||
|
|
||||||
|
assert_equal(r1.with_distance(10, 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_distance(5, 20, 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_distance(15, 20, false).to_s, "")
|
||||||
|
assert_equal(r1.with_distance(15, 20, 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_length(10, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)")
|
||||||
|
assert_equal(r1.with_length(10, 20, false).to_s, "(0,0;0,10)/(10,20;10,0);(0,0;0,10)/(10,0;10,20);(0,0;0,10)/(10,0;10,10)")
|
||||||
|
assert_equal(r1.with_length(10, 21, 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_length(10, 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)")
|
||||||
|
assert_equal(r1.with_length_both(10, false).to_s, "(0,0;0,10)/(10,0;10,10)")
|
||||||
|
assert_equal(r1.with_length_both(10, 20, false).to_s, "(0,0;0,10)/(10,0;10,10)")
|
||||||
|
assert_equal(r1.with_length_both(10, 21, 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_length_both(10, true).to_s, "(0,0;0,20)/(10,20;10,0)")
|
||||||
|
|
||||||
|
assert_equal(r1.with_angle(0, false).to_s, "")
|
||||||
|
assert_equal(r1.with_angle(0, 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_angle(90, 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_angle(0, 90, false).to_s, "")
|
||||||
|
assert_equal(r1.with_angle(0, 90, 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_angle_both(0, false).to_s, "")
|
||||||
|
assert_equal(r1.with_angle_both(0, 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_angle_both(90, 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_angle_both(0, 90, false).to_s, "")
|
||||||
|
assert_equal(r1.with_angle_both(0, 90, 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_area(0, false).to_s, "(0,0;0,10)/(10,0;10,10)")
|
||||||
|
assert_equal(r1.with_area(150, false).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||||
|
assert_equal(r1.with_area(0, 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)")
|
||||||
|
assert_equal(r1.with_area(150, 151, false).to_s, "(0,0;0,10)/(10,20;10,0)")
|
||||||
|
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,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, 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))
|
||||||
|
ep3 = RBA::EdgePair::new(RBA::Edge::new(0, 0, 0, 10), RBA::Edge::new(-20, 0, -30, 0))
|
||||||
|
|
||||||
|
r1 = RBA::EdgePairs::new([ ep1, ep2, ep3 ])
|
||||||
|
|
||||||
|
assert_equal(r1.with_distance(20, false).to_s, "(0,0;0,10)/(20,0;30,0);(0,0;0,10)/(-20,0;-30,0)")
|
||||||
|
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);(0,0;0,10)/(-20,0;-30,0)")
|
||||||
|
assert_equal(r1.with_internal_angle(-90, false).to_s, "")
|
||||||
|
|
||||||
|
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)")
|
||||||
|
assert_equal(r1.with_angle(0, 90, false, true, true).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_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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue