47 ecoord min_dist_sq = min_dist * min_dist;
52 if( dist_sq == 0 || dist_sq < min_dist_sq )
61 *aMTV =
delta.Resize( min_dist - sqrt( dist_sq ) + 3 );
75 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_RECT to SHAPE_CIRCLE collisions when rect "
76 "has rounded corners" ) );
79 return outline.SHAPE::Collide( &aB, aClearance, aActual, aLocation );
86 const int min_dist = aClearance + r;
101 bool inside = c.
x >= p0.
x && c.
x <= ( p0.
x + size.
x )
102 && c.
y >= p0.
y && c.
y <= ( p0.
y + size.
y );
105 if( inside && !aActual && !aLocation && !aMTV )
108 for(
int i = 0; i < 4; i++ )
110 const SEG side( vts[i], vts[ i + 1] );
113 ecoord side_dist_sq = ( pn - c ).SquaredEuclideanNorm();
115 if( side_dist_sq < nearest_side_dist_sq )
118 nearest_side_dist_sq = side_dist_sq;
123 if( nearest_side_dist_sq == 0 )
127 if( nearest_side_dist_sq < min_dist_sq && !aActual )
132 if( inside || nearest_side_dist_sq == 0 || nearest_side_dist_sq < min_dist_sq )
135 *aLocation = nearest;
138 *aActual = std::max( 0, (
int) sqrt( nearest_side_dist_sq ) - r );
145 *aMTV = -
delta.Resize( abs( min_dist + 1 + sqrt( nearest_side_dist_sq ) ) + 1 );
147 *aMTV =
delta.Resize( abs( min_dist + 1 - sqrt( nearest_side_dist_sq ) ) + 1 );
166 int dist = ( nearest - c ).EuclideanNorm();
167 int min_dist = aClearance + r;
169 if( dist < min_dist )
171 for(
int corr = 0; corr < 5; corr++ )
175 if( aB.
Distance( c + f ) >= min_dist )
187 int closest_dist = std::numeric_limits<int>::max();
188 int closest_mtv_dist = std::numeric_limits<int>::max();
190 int closest_mtv_seg = -1;
203 if( dist < closest_mtv_dist )
205 closest_mtv_dist = dist;
216 int collision_dist = 0;
220 aActual || aLocation ? &collision_dist :
nullptr,
221 aLocation ? &pn :
nullptr ) )
223 if( collision_dist < closest_dist )
226 closest_dist = collision_dist;
229 if( closest_dist == 0 )
239 if( closest_dist == 0 || closest_dist < aClearance )
242 *aLocation = nearest;
245 *aActual = closest_dist;
254 if (closest_mtv_seg >= 0)
290 *aActual = std::max( 0, *aActual - aSeg.
GetWidth() / 2 );
302 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
306 int closest_dist = std::numeric_limits<int>::max();
321 std::vector<SEG> a_segs;
322 std::vector<SEG> b_segs;
342 auto seg_sort = [](
const SEG& a,
const SEG& b )
344 return a.
A.
x < b.A.x || ( a.
A.
x == b.A.x && a.
A.
y < b.A.y );
347 std::sort( a_segs.begin(), a_segs.end(), seg_sort );
348 std::sort( b_segs.begin(), b_segs.end(), seg_sort );
350 for(
const SEG& a_seg : a_segs )
352 for(
const SEG& b_seg : b_segs )
356 if( a_seg.Collide( b_seg, aClearance, aActual || aLocation ? &dist :
nullptr ) )
358 if( dist < closest_dist )
360 nearest = a_seg.NearestPoint( b_seg );
364 if( closest_dist == 0 )
375 if( (!aActual && !aLocation ) || closest_dist > 0 )
377 std::vector<const SHAPE_LINE_CHAIN*> chains = {
382 std::vector<const SHAPE*> shapes = { &aA, &aB };
384 for(
int ii = 0; ii < 2; ii++ )
387 const SHAPE* other = shapes[( ii + 1 ) % 2];
392 for(
size_t jj = 0; jj <
chain->ArcCount(); jj++ )
396 if( arc.
Collide( other, aClearance, aActual, aLocation ) )
402 if( closest_dist == 0 || closest_dist < aClearance )
405 *aLocation = nearest;
408 *aActual = closest_dist;
421 return Collide( aA.
Outline(), aB, aClearance, aActual, aLocation, aMTV );
423 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
427 int closest_dist = std::numeric_limits<int>::max();
439 int collision_dist = 0;
443 aActual || aLocation ? &collision_dist :
nullptr,
444 aLocation ? &pn :
nullptr ) )
446 if( collision_dist < closest_dist )
449 closest_dist = collision_dist;
452 if( closest_dist == 0 )
462 if( closest_dist == 0 || closest_dist < aClearance )
465 *aLocation = nearest;
468 *aActual = closest_dist;
480 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
487 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
496 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
503 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
513 return Collide( aA.
Outline(), aB, aClearance, aActual, aLocation, aMTV );
515 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
522 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
531 if( aClearance || aActual || aLocation || aMTV || aA.
GetRadius() > 0 || aB.
GetRadius() > 0 )
551 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
560 int64_t dist_sq = std::numeric_limits<int64_t>::max();
563 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
566 *aLocation = ( ptA + ptB ) / 2;
569 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
574 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
587 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
591 int closest_dist = std::numeric_limits<int>::max();
597 nearest = aA.
GetP0();
601 int collision_dist = 0;
611 aActual || aLocation ? &collision_dist :
nullptr,
612 aLocation ? &pn :
nullptr ) )
614 if( collision_dist < closest_dist )
617 closest_dist = collision_dist;
620 if( closest_dist == 0 )
629 for(
size_t i = 0; i < aB.
ArcCount(); i++ )
634 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
636 if( aA.
Collide( &arc, aClearance, aActual || aLocation ? &collision_dist :
nullptr,
637 aLocation ? &pn :
nullptr ) )
639 if( collision_dist < closest_dist )
642 closest_dist = collision_dist;
645 if( closest_dist == 0 )
654 if( closest_dist == 0 || closest_dist < aClearance )
657 *aLocation = nearest;
660 *aActual = closest_dist;
673 return Collide( aA, aB.
Outline(), aClearance, aActual, aLocation, aMTV );
678 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
687 int64_t dist_sq = std::numeric_limits<int64_t>::max();
690 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
693 *aLocation = ( ptA + ptB ) / 2;
696 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
701 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
714 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
722 return Collide( tmp, aB, aClearance, aActual, aLocation, aMTV );
728 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
741 return Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
744 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
748 int closest_dist = std::numeric_limits<int>::max();
754 nearest = aA.
GetP0();
760 int collision_dist = 0;
764 aActual || aLocation ? &collision_dist :
nullptr,
765 aLocation ? &pn :
nullptr ) )
767 if( collision_dist < closest_dist )
770 closest_dist = collision_dist;
773 if( closest_dist == 0 )
783 if( closest_dist == 0 || closest_dist < aClearance )
786 *aLocation = nearest;
789 *aActual = closest_dist;
804 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
815 return Collide( aA, tmp, aClearance, aActual, aLocation, aMTV );
819 int64_t dist_sq = std::numeric_limits<int64_t>::max();
822 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
825 *aLocation = ( ptA + ptB ) / 2;
828 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
833 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
843template<
class T_a,
class T_b>
848 return Collide( *
static_cast<const T_a*
>( aA ), *
static_cast<const T_b*
>( aB ),
849 aClearance, aActual, aLocation, aMTV);
853template<
class T_a,
class T_b>
857 bool rv =
Collide( *
static_cast<const T_b*
>( aB ), *
static_cast<const T_a*
>( aA ),
858 aClearance, aActual, aLocation, aMTV);
875 return polySetA->
Collide( aB, aClearance, aActual, aLocation );
882 return polySetB->
Collide( aA, aClearance, aActual, aLocation );
1012 switch( aB->
Type() )
1042 switch( aB->
Type() )
1075 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported collision: %s with %s" ),
1085 int currentActual = std::numeric_limits<int>::max();
1088 bool colliding =
false;
1096 if( aActual && currentActual > 0 )
1105 auto collideCompoundSubshapes =
1113 aActual || aLocation ? &
actual :
nullptr,
1115 aMTV ? &mtv :
nullptr ) )
1117 if(
actual < currentActual )
1143 if( collideCompoundSubshapes( elemA, elemB, aClearance ) )
1162 if( collideCompoundSubshapes( elemA, aB, aClearance ) )
1177 if( collideCompoundSubshapes( aA, elemB, aClearance ) )
1194 *aLocation = currentLocation;
1197 *aActual = currentActual;
1209 return collideShapes(
this, aShape, aClearance,
nullptr,
nullptr, aMTV );
1215 return collideShapes(
this, aShape, aClearance, aActual, aLocation,
nullptr );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr bool Intersects(const BOX2< Vec > &aRect) const
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
static SEG::ecoord Square(int a)
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
int GetWidth() const override
const VECTOR2I & GetP1() const
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
bool IsEffectiveLine() const
bool NearestPoints(const SHAPE_ARC &aArc, VECTOR2I &aPtA, VECTOR2I &aPtB, int64_t &aDistSq) const
Compute closest points between this arc and aArc.
const VECTOR2I & GetP0() const
wxString TypeName() const
SHAPE_TYPE Type() const
Return the type of the shape.
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
const VECTOR2I GetCenter() const
void SetCenter(const VECTOR2I &aCenter)
const std::vector< SHAPE * > & Shapes() const
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
virtual size_t GetPointCount() const =0
virtual size_t GetSegmentCount() const =0
virtual const VECTOR2I GetPoint(int aIndex) const =0
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
virtual bool IsClosed() const =0
virtual const SEG GetSegment(int aIndex) const =0
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
bool IsClosed() const override
virtual const SEG GetSegment(int aIndex) const override
virtual size_t GetSegmentCount() const override
bool IsArcSegment(size_t aSegment) const
Represent a set of closed polygons.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
bool Collide(const SHAPE *aShape, int aClearance, VECTOR2I *aMTV) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
const SHAPE_LINE_CHAIN Outline() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const VECTOR2I & GetPosition() const
const VECTOR2I GetSize() const
const SEG & GetSeg() const
int GetWidth() const override
bool Collide(const SHAPE *aShape, int aClearance, VECTOR2I *aMTV) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
An abstract shape on 2D plane.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
SHAPE(SHAPE_TYPE aType)
Create an empty shape of type aType.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
static constexpr extended_type ECOORD_MAX
VECTOR2_TRAITS< int32_t >::extended_type extended_type
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
@ SH_POLY_SET
set of polygons (with holes, etc.)
@ SH_RECT
axis-aligned rectangle
@ SH_SIMPLE
simple polygon
@ SH_NULL
empty shape (no shape...),
@ SH_POLY_SET_TRIANGLE
a single triangle belonging to a POLY_SET triangulation
@ SH_LINE_CHAIN
line chain (polyline)
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
static bool collideSingleShapes(const SHAPE *aA, const SHAPE *aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
static bool Collide(const SHAPE_CIRCLE &aA, const SHAPE_CIRCLE &aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
bool CollCaseReversed(const SHAPE *aA, const SHAPE *aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
static VECTOR2I pushoutForce(const SHAPE_CIRCLE &aA, const SEG &aB, int aClearance)
bool CollCase(const SHAPE *aA, const SHAPE *aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
static bool collideShapes(const SHAPE *aA, const SHAPE *aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
VECTOR2I::extended_type ecoord
const SHAPE_LINE_CHAIN chain
VECTOR2< int32_t > VECTOR2I