31 #include <math/vector2d.h>
32 #include <core/optional.h>
34 typedef OPT<VECTOR2I> OPT_VECTOR2I;
39 using ecoord = VECTOR2I::extended_type;
40 friend inline std::ostream& operator<<( std::ostream& aStream,
const SEG& aSeg );
59 SEG(
int aX1,
int aY1,
int aX2,
int aY2 ) :
90 SEG(
const SEG& aSeg ) : A( aSeg.A ), B( aSeg.B ), m_index( aSeg.m_index )
94 SEG& operator=(
const SEG& aSeg )
98 m_index = aSeg.m_index;
103 bool operator==(
const SEG& aSeg )
const
105 return (A == aSeg.A && B == aSeg.B) ;
108 bool operator!=(
const SEG& aSeg )
const
110 return (A != aSeg.A || B != aSeg.B);
132 const ecoord det = ( B - A ).Cross( aP - A );
134 return det < 0 ? -1 : ( det > 0 ? 1 : 0 );
173 OPT_VECTOR2I
Intersect(
const SEG& aSeg,
bool aIgnoreEndpoints =
false,
174 bool aLines =
false )
const;
188 bool Collide(
const SEG& aSeg,
int aClearance )
const;
190 ecoord SquaredDistance(
const SEG& aSeg )
const;
201 return sqrt( SquaredDistance( aSeg ) );
204 ecoord SquaredDistance(
const VECTOR2I& aP )
const
206 return (
NearestPoint( aP ) - aP ).SquaredEuclideanNorm();
218 return sqrt( SquaredDistance( aP ) );
221 void CanonicalCoefs( ecoord& qA, ecoord& qB, ecoord& qC )
const
225 qC = -qA * A.x - qB * A.y;
238 CanonicalCoefs( qa, qb, qc );
240 ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc );
241 ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc );
243 return ( d1 <= 1 && d2 <= 1 );
246 bool ApproxCollinear(
const SEG& aSeg )
const
249 CanonicalCoefs( p, q, r );
251 ecoord dist1 = ( p * aSeg.A.x + q * aSeg.A.y + r ) / sqrt( p * p + q * q );
252 ecoord dist2 = ( p * aSeg.B.x + q * aSeg.B.y + r ) / sqrt( p * p + q * q );
254 return std::abs( dist1 ) <= 1 && std::abs( dist2 ) <= 1;
257 bool ApproxParallel (
const SEG& aSeg )
const
260 CanonicalCoefs( p, q, r );
262 ecoord dist1 = ( p * aSeg.A.x + q * aSeg.A.y + r ) / sqrt( p * p + q * q );
263 ecoord dist2 = ( p * aSeg.B.x + q * aSeg.B.y + r ) / sqrt( p * p + q * q );
265 return std::abs( dist1 - dist2 ) <= 1;
269 bool Overlaps(
const SEG& aSeg )
const
271 if( aSeg.A == aSeg.B )
273 if( A == aSeg.A || B == aSeg.A )
276 return Contains( aSeg.A );
282 if( Contains( aSeg.A ) || Contains( aSeg.B ) )
284 if( aSeg.Contains( A ) || aSeg.Contains( B ) )
298 return ( A - B ).EuclideanNorm();
301 ecoord SquaredLength()
const
303 return ( A - B ).SquaredEuclideanNorm();
306 ecoord TCoef(
const VECTOR2I& aP )
const;
319 bool Contains(
const VECTOR2I& aP )
const;
321 bool PointCloserThan(
const VECTOR2I& aP,
int aDist )
const;
331 return A + ( B - A ) / 2;
344 ecoord l_squared = d.
Dot( d );
349 ecoord t = d.
Dot( aP - A );
351 int xp = rescale( t, (ecoord)d.x, l_squared );
352 int yp = rescale( t, (ecoord)d.y, l_squared );
359 ecoord p = A.y - B.y;
360 ecoord q = B.x - A.x;
361 ecoord r = -p * A.x - q * A.y;
363 ecoord dist = ( p * aP.x + q * aP.y + r ) / sqrt( p * p + q * q );
365 return aDetermineSide ? dist : std::abs( dist );
368 inline SEG::ecoord SEG::TCoef(
const VECTOR2I& aP )
const
371 return d.
Dot( aP - A);
377 ecoord l_squared = d.
Dot( d );
382 ecoord t = d.
Dot( aP - A );
386 else if( t > l_squared )
389 int xp = rescale( t, (ecoord)d.x, l_squared );
390 int yp = rescale( t, (ecoord)d.y, l_squared );
395 inline std::ostream& operator<<( std::ostream& aStream,
const SEG& aSeg )
397 aStream <<
"[ " << aSeg.A <<
" - " << aSeg.B <<
" ]";