mirror of https://github.com/KLayout/klayout.git
Added more filters for edge pairs: with_area, with_internal_angle. Added tests
This commit is contained in:
parent
ea27a85a0f
commit
5251520876
|
|
@ -78,4 +78,41 @@ bool EdgePairFilterByDistance::selected (const db::EdgePair &edge_pair) const
|
|||
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
|
||||
{
|
||||
return m_checker (edge_pair.first ().d (), -edge_pair.second ().d ()) != m_inverted;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#define HDR_dbEdgePairFilters
|
||||
|
||||
#include "dbEdgePairs.h"
|
||||
#include "dbEdgesUtils.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -69,12 +70,57 @@ public:
|
|||
EdgePairFilterByDistance (distance_type min_distance, distance_type max_distance, 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; }
|
||||
virtual const TransformationReducer *vars () const { return &m_vars; }
|
||||
virtual bool wants_variants () const { return true; }
|
||||
|
||||
private:
|
||||
distance_type m_min_distance, m_max_distance;
|
||||
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:
|
||||
db::DVector m_emin, m_emax;
|
||||
bool m_inverse;
|
||||
db::MagnificationAndOrientationReducer m_vars;
|
||||
EdgeAngleChecker m_checker;
|
||||
|
|
|
|||
|
|
@ -246,6 +246,30 @@ static db::EdgePairs with_angle_both2 (const db::EdgePairs *r, double amin, doub
|
|||
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;
|
||||
|
||||
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"),
|
||||
"@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 "
|
||||
"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"
|
||||
"\n"
|
||||
"Distance is measured as the shortest distance between any of the points on the edges.\n"
|
||||
|
|
@ -678,6 +702,51 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"\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. 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"
|
||||
"\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. 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"
|
||||
"\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,
|
||||
"@brief Converts the edge pairs to polygons\n"
|
||||
"This method creates polygons from the edge pairs. Each polygon will be a triangle or quadrangle "
|
||||
|
|
|
|||
|
|
@ -225,6 +225,78 @@ class DBEdgePairs_TestClass < TestBase
|
|||
|
||||
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,20)/(10,20;10,0)")
|
||||
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)")
|
||||
|
||||
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)")
|
||||
assert_equal(r1.with_internal_angle(-90, false).to_s, "(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)")
|
||||
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, "")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue