Calculate inside polygon using points

Minor improvement in polygon calculation to use consecutive points
rather than casting to a full segment.  Avoids division except when it
will not create a denormal.
This commit is contained in:
Seth Hillbrand 2018-05-10 08:26:40 -07:00
parent d67821d771
commit f2aea97807
1 changed files with 34 additions and 7 deletions

View File

@ -24,6 +24,7 @@
#include <algorithm>
#include <common.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_circle.h>
@ -331,7 +332,7 @@ int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
{
if( !m_closed || SegmentCount() < 3 || !BBox().Contains( aP ) )
if( !m_closed || PointCount() < 3 || !BBox().Contains( aP ) )
return false;
bool inside = false;
@ -344,12 +345,14 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
* Note: slope might be denormal here in the case of a horizontal line but we require our
* y to move from above to below the point (or vice versa)
*/
for( int i = 0; i < SegmentCount(); i++ )
for( int i = 0; i < PointCount(); i++ )
{
const SEG s = CSegment( i );
double inv_slope = ( ( double ) s.B.x - s.A.x ) / (s.B.y - s.A.y );
if( ( ( s.A.y > aP.y ) != ( s.B.y > aP.y ) ) &&
( aP.x - s.A.x < inv_slope * ( aP.y - s.A.y ) ) )
const VECTOR2D p1 = CPoint( i );
const VECTOR2D p2 = CPoint( i + 1 ); // CPoint wraps, so ignore counts
const VECTOR2D diff = p2 - p1;
if( ( ( p1.y > aP.y ) != ( p2.y > aP.y ) ) &&
( aP.x - p1.x < ( diff.x / diff.y ) * ( aP.y - p1.y ) ) )
inside = !inside;
}
@ -359,7 +362,31 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
{
return CheckClearance( aP, 1 );
if( !PointCount() )
return false;
else if( PointCount() == 1 )
return m_points[0] == aP;
for( int i = 0; i < PointCount(); i++ )
{
const VECTOR2I& p1 = CPoint( i );
const VECTOR2I& p2 = CPoint( i + 1 );
if( aP == p1 )
return true;
if( p1.x == p2.x && p1.x == aP.x && ( p1.y > aP.y ) != ( p2.y > aP.y ) )
return true;
const VECTOR2D diff = p2 - p1;
if( aP.x >= p1.x && aP.x <= p2.x )
{
if( KiROUND( p1.y + ( diff.y / diff.x ) * ( aP.x - p1.x ) ) == aP.y )
return true;
}
}
return false;
}