From f85dc57642d7c032c92418309931165dbca18c72 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Thu, 23 Aug 2018 13:36:19 +0200 Subject: [PATCH] POLY_GRID_PARTITION: fixed incorrect point-in-polygon test in some corner cases Fixes: lp:1787236 * https://bugs.launchpad.net/kicad/+bug/1787236 --- include/geometry/poly_grid_partition.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/geometry/poly_grid_partition.h b/include/geometry/poly_grid_partition.h index 75ed0c42e8..e08d30ffa9 100644 --- a/include/geometry/poly_grid_partition.h +++ b/include/geometry/poly_grid_partition.h @@ -43,7 +43,7 @@ class POLY_GRID_PARTITION { private: - enum HASH_FLAG +enum HASH_FLAG { LEAD_H = 1, LEAD_V = 2, @@ -195,7 +195,12 @@ private: auto dir = edge.B - edge.A; int flags = 0; - if( edgeSet[edge] == 1 ) + + if ( dir.y == 0 ) + { + flags = 0; + } + else if( edgeSet[edge] == 1 ) { if( dir.Dot( ref_h ) < 0 ) { @@ -210,6 +215,9 @@ private: m_flags.push_back( flags ); + if( edge.A.y == edge.B.y ) + continue; + std::set indices; indices.insert( m_gridSize * poly2gridY( edge.A.y ) + poly2gridX( edge.A.x ) ); @@ -374,12 +382,12 @@ public: build( aPolyOutline, gridSize ); } - int containsPoint( const VECTOR2I& aP ) // const + int containsPoint( const VECTOR2I& aP, bool debug = false ) const { const auto gridPoint = poly2grid( aP ); if( !m_bbox.Contains( aP ) ) - return false; + return 0; SCAN_STATE state; const EDGE_LIST& cell = m_grid[ m_gridSize * gridPoint.y + gridPoint.x ]; @@ -414,13 +422,14 @@ public: } } } - + if( state.nearest < 0 ) return 0; if( state.dist_max == 0 ) return 1; + // special case for diagonal 'slits', e.g. two segments that partially overlap each other. if( state.nearest_prev >= 0 && state.dist_max == state.dist_prev ) { int d = std::abs( state.nearest_prev - state.nearest ); @@ -429,12 +438,8 @@ public: { return 0; } - else if( d > 1 ) - { - return 1; - } } - + if( state.dist_max > 0 ) { return m_flags[state.nearest] & LEAD_H ? 1 : 0;