geometry: rework SHAPE_LINE_CHAIN::Intersect() to explicitly indicate touching vertices and remove references to SEGs from INTERSECTION structure

This commit is contained in:
Tomasz Wlostowski 2021-05-27 23:36:12 +02:00
parent e2785b117b
commit e7fe8c4ddb
2 changed files with 50 additions and 37 deletions

View File

@ -57,12 +57,20 @@ public:
*/
struct INTERSECTION
{
/// segment belonging from the (this) argument of Intersect()
SEG our;
/// segment belonging from the aOther argument of Intersect()
SEG their;
/// point of intersection between our and their.
VECTOR2I p;
/// index of the intersecting corner/segment in the 'our' (== this) line
int index_our;
/// index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line
int index_their;
/// when true, the corner [index_our] of the 'our' line lies exactly on 'their' line
bool is_corner_our;
/// when true, the corner [index_their] of the 'their' line lies exactly on 'our' line.
/// Note that when both is_corner_our and is_corner_their are set, the line chains touch with with corners
bool is_corner_their;
/// auxillary flag to avoid copying intersection info to intersection refining code, used by the refining
/// code (e.g. hull handling stuff in the P&S) to reject false intersection points.
bool valid;
};
@ -593,7 +601,7 @@ public:
* sorted with increasing path lengths from the starting point of aChain.
* @return number of intersections found
*/
int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp ) const;
int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp, bool aExcludeColinearAndTouching = false ) const;
/**
* Function PathLength()

View File

@ -749,8 +749,9 @@ int SHAPE_LINE_CHAIN::Intersect( const SEG& aSeg, INTERSECTIONS& aIp ) const
if( p )
{
INTERSECTION is;
is.our = CSegment( s );
is.their = aSeg;
is.valid = true;
is.index_our = s;
is.is_corner_our = is.is_corner_their = false;
is.p = *p;
aIp.push_back( is );
}
@ -772,16 +773,10 @@ static inline void addIntersection( SHAPE_LINE_CHAIN::INTERSECTIONS& aIps, int a
const auto& last = aIps.back();
if( ( (last.our.Index() + 1) % aPc) == aP.our.Index() && last.p == aP.p )
return;
if( last.our.Index() == aP.our.Index() && last.p == aP.p )
return;
aIps.push_back( aP );
}
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp ) const
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp, bool aExcludeColinearAndTouching ) const
{
BOX2I bb_other = aChain.BBox();
@ -798,27 +793,37 @@ int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS&
const SEG& b = aChain.CSegment( s2 );
INTERSECTION is;
if( a.Collinear( b ) )
{
is.our = a;
is.their = b;
is.index_our = s1;
is.index_their = s2;
is.is_corner_our = false;
is.is_corner_their = false;
is.valid = true;
if( a.Contains( b.A ) ) { is.p = b.A; addIntersection(aIp, PointCount(), is); }
if( a.Contains( b.B ) ) { is.p = b.B; addIntersection(aIp, PointCount(), is); }
if( b.Contains( a.A ) ) { is.p = a.A; addIntersection(aIp, PointCount(), is); }
if( b.Contains( a.B ) ) { is.p = a.B; addIntersection(aIp, PointCount(), is); }
OPT_VECTOR2I p = a.Intersect( b );
bool coll = a.Collinear( b );
if( coll && ! aExcludeColinearAndTouching )
{
if( a.Contains( b.A ) ) { is.p = b.A; is.is_corner_their = true; addIntersection(aIp, PointCount(), is); }
if( a.Contains( b.B ) ) { is.p = b.B; is.index_their++; is.is_corner_their = true; addIntersection(aIp, PointCount(), is); }
if( b.Contains( a.A ) ) { is.p = a.A; is.is_corner_our = true; addIntersection(aIp, PointCount(), is); }
if( b.Contains( a.B ) ) { is.p = a.B; is.index_our++; is.is_corner_our = true; addIntersection(aIp, PointCount(), is); }
}
else
else if( p )
{
OPT_VECTOR2I p = a.Intersect( b );
is.p = *p;
is.is_corner_our = false;
is.is_corner_their = false;
if( p )
{
is.p = *p;
is.our = a;
is.their = b;
addIntersection(aIp, PointCount(), is);
}
int distA = ( b.A - *p ).EuclideanNorm();
int distB = ( b.B - *p ).EuclideanNorm();
if ( p == a.A ) { is.is_corner_our = true; }
if ( p == a.B ) { is.is_corner_our = true; is.index_our++; }
if ( p == b.A ) { is.is_corner_their = true; }
if ( p == b.B ) { is.is_corner_their = true; is.index_their++; }
addIntersection(aIp, PointCount(), is);
}
}
}
@ -968,8 +973,8 @@ const OPT<SHAPE_LINE_CHAIN::INTERSECTION> SHAPE_LINE_CHAIN::SelfIntersecting() c
if( s1 + 1 != s2 && CSegment( s1 ).Contains( s2a ) )
{
INTERSECTION is;
is.our = CSegment( s1 );
is.their = CSegment( s2 );
is.index_our = s1;
is.index_their = s2;
is.p = s2a;
return is;
}
@ -980,8 +985,8 @@ const OPT<SHAPE_LINE_CHAIN::INTERSECTION> SHAPE_LINE_CHAIN::SelfIntersecting() c
!( IsClosed() && s1 == 0 && s2 == SegmentCount()-1 ) )
{
INTERSECTION is;
is.our = CSegment( s1 );
is.their = CSegment( s2 );
is.index_our = s1;
is.index_their = s2;
is.p = s2b;
return is;
}
@ -992,8 +997,8 @@ const OPT<SHAPE_LINE_CHAIN::INTERSECTION> SHAPE_LINE_CHAIN::SelfIntersecting() c
if( p )
{
INTERSECTION is;
is.our = CSegment( s1 );
is.their = CSegment( s2 );
is.index_our = s1;
is.index_their = s2;
is.p = *p;
return is;
}