Added more filters for edge pairs: with_area, with_internal_angle. Added tests

This commit is contained in:
Matthias Koefferlein 2021-06-21 23:44:48 +02:00
parent ea27a85a0f
commit 5251520876
5 changed files with 227 additions and 4 deletions

View File

@ -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;
}
}

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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 "

View File

@ -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