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 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. /// point of intersection between our and their.
VECTOR2I p; 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. * sorted with increasing path lengths from the starting point of aChain.
* @return number of intersections found * @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() * Function PathLength()

View File

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