Revert "geometry: revert SHAPE_LINE_CHAIN::PointInside/PointOnEdge() optimizations so that it's consistent with other collision checking methods (i.e. SEG::Distance() )"
This reverts commit 4a0fba309a
.
This commit is contained in:
parent
05483a06c6
commit
93ecd44f5a
|
@ -350,46 +350,58 @@ int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
|
||||||
|
|
||||||
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
|
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
|
||||||
{
|
{
|
||||||
if( !m_closed || SegmentCount() < 3 )
|
if( !m_closed || PointCount() < 3 || !BBox().Contains( aP ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int cur = CSegment( 0 ).Side( aP );
|
bool inside = false;
|
||||||
|
|
||||||
if( cur == 0 )
|
/**
|
||||||
return false;
|
* To check for interior points, we draw a line in the positive x direction from
|
||||||
|
* the point. If it intersects an even number of segments, the point is outside the
|
||||||
for( int i = 1; i < SegmentCount(); i++ )
|
* line chain (it had to first enter and then exit). Otherwise, it is inside the chain.
|
||||||
|
*
|
||||||
|
* 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 < PointCount(); i++ )
|
||||||
{
|
{
|
||||||
const SEG s = CSegment( i );
|
const VECTOR2D p1 = CPoint( i );
|
||||||
|
const VECTOR2D p2 = CPoint( i + 1 ); // CPoint wraps, so ignore counts
|
||||||
|
const VECTOR2D diff = p2 - p1;
|
||||||
|
|
||||||
// if( aP == s.A || aP == s.B ) // edge does not belong to the interior!
|
if( ( ( p1.y > aP.y ) != ( p2.y > aP.y ) ) &&
|
||||||
// return false;
|
( aP.x - p1.x < ( diff.x / diff.y ) * ( aP.y - p1.y ) ) )
|
||||||
|
inside = !inside;
|
||||||
if( s.Side( aP ) != cur )
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
|
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
|
||||||
{
|
{
|
||||||
if( !PointCount() )
|
if( !PointCount() )
|
||||||
return false;
|
return false;
|
||||||
|
else if( PointCount() == 1 )
|
||||||
else if( PointCount() == 1 )
|
|
||||||
return m_points[0] == aP;
|
return m_points[0] == aP;
|
||||||
|
|
||||||
for( int i = 0; i < SegmentCount(); i++ )
|
for( int i = 0; i < PointCount(); i++ )
|
||||||
{
|
{
|
||||||
const SEG s = CSegment( i );
|
const VECTOR2I& p1 = CPoint( i );
|
||||||
|
const VECTOR2I& p2 = CPoint( i + 1 );
|
||||||
|
|
||||||
if( s.A == aP || s.B == aP )
|
if( aP == p1 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( s.Distance( aP ) <= 1 )
|
if( p1.x == p2.x && p1.x == aP.x && ( p1.y > aP.y ) != ( p2.y > aP.y ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
const VECTOR2D diff = p2 - p1;
|
||||||
|
if( aP.x >= p1.x && aP.x <= p2.x )
|
||||||
|
{
|
||||||
|
if( round_nearest( p1.y + ( diff.y / diff.x ) * ( aP.x - p1.x ) ) == aP.y )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue