46 ecoord min_dist_sq = min_dist * min_dist;
51 if( dist_sq == 0 || dist_sq < min_dist_sq )
60 *aMTV =
delta.Resize( min_dist - sqrt( dist_sq ) + 3 );
74 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_RECT to SHAPE_CIRCLE collisions when rect "
75 "has rounded corners" ) );
78 return outline.SHAPE::Collide( &aB, aClearance, aActual, aLocation );
85 const int min_dist = aClearance + r;
100 bool inside = c.
x >= p0.
x && c.
x <= ( p0.
x + size.
x )
101 && c.
y >= p0.
y && c.
y <= ( p0.
y + size.
y );
104 if( inside && !aActual && !aLocation && !aMTV )
107 for(
int i = 0; i < 4; i++ )
109 const SEG side( vts[i], vts[ i + 1] );
112 ecoord side_dist_sq = ( pn - c ).SquaredEuclideanNorm();
114 if( side_dist_sq < nearest_side_dist_sq )
117 nearest_side_dist_sq = side_dist_sq;
122 if( nearest_side_dist_sq == 0 )
126 if( nearest_side_dist_sq < min_dist_sq && !aActual )
131 if( inside || nearest_side_dist_sq == 0 || nearest_side_dist_sq < min_dist_sq )
134 *aLocation = nearest;
137 *aActual = std::max( 0, (
int) sqrt( nearest_side_dist_sq ) - r );
144 *aMTV = -
delta.Resize( abs( min_dist + 1 + sqrt( nearest_side_dist_sq ) ) + 1 );
146 *aMTV =
delta.Resize( abs( min_dist + 1 - sqrt( nearest_side_dist_sq ) ) + 1 );
165 int dist = ( nearest - c ).EuclideanNorm();
166 int min_dist = aClearance + r;
168 if( dist < min_dist )
170 for(
int corr = 0; corr < 5; corr++ )
174 if( aB.
Distance( c + f ) >= min_dist )
183template <
typename SegmentSource,
typename Containment>
185 int aHalfWidth, Containment aContainment,
int* aActual,
188 const int effClear = aClearance + aHalfWidth;
191 int bestActual = std::numeric_limits<int>::max();
194 const size_t nSegs = aSegSource.GetSegmentCount();
196 for(
size_t i = 0; i < nSegs; ++i )
198 const SEG seg = aSegSource.GetSegment(
static_cast<int>( i ) );
202 if( aA.
Collide( seg, effClear, aActual ? &localActual :
nullptr, aLocation ? &localLoc :
nullptr ) )
204 if( !aActual && !aLocation )
207 if( !found || localActual < bestActual )
209 bestActual = localActual;
210 bestLocation = localLoc;
219 *aActual = std::max( 0, bestActual - aHalfWidth );
221 *aLocation = bestLocation;
241 int closest_dist = std::numeric_limits<int>::max();
242 int closest_mtv_dist = std::numeric_limits<int>::max();
244 int closest_mtv_seg = -1;
257 if( dist < closest_mtv_dist )
259 closest_mtv_dist = dist;
270 int collision_dist = 0;
274 aActual || aLocation ? &collision_dist :
nullptr,
275 aLocation ? &pn :
nullptr ) )
277 if( collision_dist < closest_dist )
280 closest_dist = collision_dist;
283 if( closest_dist == 0 )
293 if( closest_dist == 0 || closest_dist < aClearance )
296 *aLocation = nearest;
299 *aActual = closest_dist;
308 if (closest_mtv_seg >= 0)
344 *aActual = std::max( 0, *aActual - aSeg.
GetWidth() / 2 );
356 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
360 int closest_dist = std::numeric_limits<int>::max();
375 std::vector<SEG> a_segs;
376 std::vector<SEG> b_segs;
398 const bool need_output = aActual || aLocation;
399 const int64_t pair_count =
static_cast<int64_t
>( a_segs.size() ) * b_segs.size();
400 auto dense_candidates = [&](
const std::vector<SEG>& aQueries,
401 const std::vector<SEG>& aIndexed )
403 int indexed_min_x = std::numeric_limits<int>::max();
404 int indexed_min_y = std::numeric_limits<int>::max();
405 int indexed_max_x = std::numeric_limits<int>::min();
406 int indexed_max_y = std::numeric_limits<int>::min();
408 for(
const SEG& segment : aIndexed )
410 indexed_min_x = std::min( { indexed_min_x, segment.A.x, segment.B.x } );
411 indexed_min_y = std::min( { indexed_min_y, segment.A.y, segment.B.y } );
412 indexed_max_x = std::max( { indexed_max_x, segment.A.x, segment.B.x } );
413 indexed_max_y = std::max( { indexed_max_y, segment.A.y, segment.B.y } );
416 const SEG& query = aQueries.front();
417 const int64_t min_x =
static_cast<int64_t
>( std::min( query.
A.
x, query.
B.
x ) ) - aClearance;
418 const int64_t min_y =
static_cast<int64_t
>( std::min( query.
A.
y, query.
B.
y ) ) - aClearance;
419 const int64_t max_x =
static_cast<int64_t
>( std::max( query.
A.
x, query.
B.
x ) ) + aClearance;
420 const int64_t max_y =
static_cast<int64_t
>( std::max( query.
A.
y, query.
B.
y ) ) + aClearance;
421 return min_x <= indexed_min_x && min_y <= indexed_min_y && max_x >= indexed_max_x
422 && max_y >= indexed_max_y;
427 bool use_index = aClearance >= 0 && std::min( a_segs.size(), b_segs.size() ) >= 64
428 && pair_count >= 4096;
432 const std::vector<SEG>& queries = b_segs.size() >= a_segs.size() ? a_segs : b_segs;
433 const std::vector<SEG>& indexed = b_segs.size() >= a_segs.size() ? b_segs : a_segs;
434 use_index = !dense_candidates( queries, indexed );
440 const size_t probe_a_count = std::min<size_t>( a_segs.size(), 4 );
441 const size_t probe_b_count = std::min<size_t>( b_segs.size(), 8 );
442 bool early_collision =
false;
444 for(
size_t i = 0; i < probe_a_count && !early_collision; ++i )
446 for(
size_t j = 0; j < probe_b_count; ++j )
448 if( a_segs[i].
Collide( b_segs[j], aClearance ) )
450 early_collision =
true;
456 if( early_collision )
460 else if( b_segs.size() >= a_segs.size() )
464 for(
const SEG& a_seg : a_segs )
467 auto visitor = [&](
int aIndex )
469 if( a_seg.Collide(
index.Segment( aIndex ), aClearance ) )
477 index.VisitCandidates( a_seg, aClearance, visitor );
487 for(
const SEG& b_seg : b_segs )
490 auto visitor = [&](
int aIndex )
492 if(
index.Segment( aIndex ).Collide( b_seg, aClearance ) )
500 index.VisitCandidates( b_seg, aClearance, visitor );
507 else if( aClearance >= 0 )
509 for(
const SEG& a_seg : a_segs )
511 for(
const SEG& b_seg : b_segs )
513 if( a_seg.Collide( b_seg, aClearance ) )
521 auto seg_sort = [](
const SEG& a,
const SEG& b )
523 return a.
A.
x < b.A.x || ( a.
A.
x == b.A.x && a.
A.
y < b.A.y );
526 std::sort( a_segs.begin(), a_segs.end(), seg_sort );
527 std::sort( b_segs.begin(), b_segs.end(), seg_sort );
529 const bool use_index = aClearance >= 0 && a_segs.size() >= 32 && b_segs.size() >= 64
530 && pair_count >= 4096 && !dense_candidates( a_segs, b_segs );
536 bool scan_direct =
false;
538 enum class COLLISION_RESULT
545 auto collide_pair = [&](
const SEG& aASeg,
const SEG& aBSeg )
549 if( !aASeg.
Collide( aBSeg, aClearance, &dist ) )
550 return COLLISION_RESULT::NONE;
552 if( dist < closest_dist )
558 return closest_dist == 0 ? COLLISION_RESULT::EXACT : COLLISION_RESULT::FOUND;
561 for(
const SEG& a_seg : a_segs )
566 auto visitor = [&](
int aIndex )
571 index.VisitCandidates( a_seg, aClearance, visitor );
580 const size_t candidate_count = scan_direct ?
index.size() :
candidates.size();
582 for(
size_t i = 0; i < candidate_count; ++i )
584 const int b_index = scan_direct ?
static_cast<int>( i ) :
candidates[i];
585 const COLLISION_RESULT
result = collide_pair( a_seg,
index.Segment( b_index ) );
587 if(
result == COLLISION_RESULT::EXACT )
590 *aLocation = nearest;
593 *aActual = closest_dist;
598 if(
result == COLLISION_RESULT::FOUND && !aActual )
603 else if( aClearance >= 0 )
605 for(
const SEG& a_seg : a_segs )
607 for(
const SEG& b_seg : b_segs )
611 if( a_seg.Collide( b_seg, aClearance, &dist ) )
613 if( dist < closest_dist )
615 nearest = a_seg.NearestPoint( b_seg );
619 if( closest_dist == 0 )
631 if( (!aActual && !aLocation ) || closest_dist > 0 )
633 std::vector<const SHAPE_LINE_CHAIN*> chains = {
638 std::vector<const SHAPE*> shapes = { &aA, &aB };
640 for(
int ii = 0; ii < 2; ii++ )
643 const SHAPE* other = shapes[( ii + 1 ) % 2];
648 for(
size_t jj = 0; jj <
chain->ArcCount(); jj++ )
652 if( arc.
Collide( other, aClearance, aActual, aLocation ) )
658 if( closest_dist == 0 || closest_dist < aClearance )
661 *aLocation = nearest;
664 *aActual = closest_dist;
677 return Collide( aA.
Outline(), aB, aClearance, aActual, aLocation, aMTV );
679 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
683 int closest_dist = std::numeric_limits<int>::max();
695 int collision_dist = 0;
699 aActual || aLocation ? &collision_dist :
nullptr,
700 aLocation ? &pn :
nullptr ) )
702 if( collision_dist < closest_dist )
705 closest_dist = collision_dist;
708 if( closest_dist == 0 )
718 if( closest_dist == 0 || closest_dist < aClearance )
721 *aLocation = nearest;
724 *aActual = closest_dist;
736 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
743 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
752 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
759 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
769 return Collide( aA.
Outline(), aB, aClearance, aActual, aLocation, aMTV );
771 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
778 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
787 if( aClearance || aActual || aLocation || aMTV || aA.
GetRadius() > 0 || aB.
GetRadius() > 0 )
807 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
816 int64_t dist_sq = std::numeric_limits<int64_t>::max();
819 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
822 *aLocation = ( ptA + ptB ) / 2;
825 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
830 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
843 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
847 int closest_dist = std::numeric_limits<int>::max();
853 nearest = aA.
GetP0();
857 int collision_dist = 0;
867 aActual || aLocation ? &collision_dist :
nullptr,
868 aLocation ? &pn :
nullptr ) )
870 if( collision_dist < closest_dist )
873 closest_dist = collision_dist;
876 if( closest_dist == 0 )
885 for(
size_t i = 0; i < aB.
ArcCount(); i++ )
890 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
892 if( aA.
Collide( &arc, aClearance, aActual || aLocation ? &collision_dist :
nullptr,
893 aLocation ? &pn :
nullptr ) )
895 if( collision_dist < closest_dist )
898 closest_dist = collision_dist;
901 if( closest_dist == 0 )
910 if( closest_dist == 0 || closest_dist < aClearance )
913 *aLocation = nearest;
916 *aActual = closest_dist;
929 return Collide( aA, aB.
Outline(), aClearance, aActual, aLocation, aMTV );
934 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
943 int64_t dist_sq = std::numeric_limits<int64_t>::max();
946 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
949 *aLocation = ( ptA + ptB ) / 2;
952 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
957 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
970 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
978 return Collide( tmp, aB, aClearance, aActual, aLocation, aMTV );
984 *aActual = std::max( 0, *aActual - aB.
GetWidth() / 2 );
997 return Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
1000 wxASSERT_MSG( !aMTV, wxString::Format( wxT(
"MTV not implemented for %s : %s collisions" ),
1004 int closest_dist = std::numeric_limits<int>::max();
1010 nearest = aA.
GetP0();
1014 const BOX2I arc_bbox = aA.
BBox( aClearance );
1015 const bool near_full_circle = ( aA.
GetP0() - aA.
GetP1() ).SquaredEuclideanNorm() <
SEG::Square( aClearance )
1023 if( !near_full_circle
1024 && ( std::max( segment.
A.
x, segment.
B.
x ) < arc_bbox.
GetLeft()
1025 || std::min( segment.
A.
x, segment.
B.
x ) > arc_bbox.
GetRight()
1026 || std::max( segment.
A.
y, segment.
B.
y ) < arc_bbox.
GetTop()
1027 || std::min( segment.
A.
y, segment.
B.
y ) > arc_bbox.
GetBottom() ) )
1032 int collision_dist = 0;
1035 if( aA.
Collide( segment, aClearance,
1036 aActual || aLocation ? &collision_dist :
nullptr,
1037 aLocation ? &pn :
nullptr ) )
1039 if( collision_dist < closest_dist )
1042 closest_dist = collision_dist;
1045 if( closest_dist == 0 )
1055 if( closest_dist == 0 || closest_dist < aClearance )
1058 *aLocation = nearest;
1061 *aActual = closest_dist;
1076 bool retval =
Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
1078 if( retval && aMTV )
1087 return Collide( aA, tmp, aClearance, aActual, aLocation, aMTV );
1091 int64_t dist_sq = std::numeric_limits<int64_t>::max();
1094 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
1097 *aLocation = ( ptA + ptB ) / 2;
1100 *aActual = std::max( 0,
KiROUND( std::sqrt( dist_sq ) ) );
1105 *aMTV =
delta.Resize( aClearance - std::sqrt( dist_sq ) + 3 );
1115template<
class T_a,
class T_b>
1120 return Collide( *
static_cast<const T_a*
>( aA ), *
static_cast<const T_b*
>( aB ),
1121 aClearance, aActual, aLocation, aMTV);
1125template<
class T_a,
class T_b>
1129 bool rv =
Collide( *
static_cast<const T_b*
>( aB ), *
static_cast<const T_a*
>( aA ),
1130 aClearance, aActual, aLocation, aMTV);
1142 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1144 const int halfWidth = aSeg.
GetWidth() / 2;
1145 const int effClear = aClearance + halfWidth;
1147 int localActual = 0;
1150 if( aA.
Collide( aSeg.
GetSeg(), effClear, aActual ? &localActual :
nullptr, aLocation ? &localLoc :
nullptr ) )
1153 *aActual = std::max( 0, localActual - halfWidth );
1155 *aLocation = localLoc;
1166 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1170 const int effClr = aClearance + r;
1174 if( dSq == 0 || dSq < effSq )
1178 const int d =
static_cast<int>( std::round( std::sqrt(
static_cast<double>( dSq ) ) ) );
1179 *aActual = std::max( 0, d - r );
1193 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1195 aA, aB.
Outline(), aClearance, 0,
1198 return aB.BBox().Contains( aA.GetCenter() );
1200 aActual, aLocation );
1207 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1209 aA, aB, aClearance, 0,
1214 aActual, aLocation );
1221 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1223 const int halfWidth = aB.
GetWidth() / 2;
1224 const int effClear = aClearance + halfWidth;
1225 const int tessError = std::max( 1, effClear / 4 );
1229 aA,
chain, aClearance, halfWidth,
1234 aActual, aLocation );
1241 wxASSERT_MSG( !aMTV, wxT(
"MTV not implemented for SHAPE_ELLIPSE collisions" ) );
1260 const int tessError = std::max( 1, aClearance / 4 );
1263 return Collide( aA, chainB, aClearance, aActual, aLocation, aMTV );
1275 return polySetA->
Collide( aB, aClearance, aActual, aLocation );
1282 return polySetB->
Collide( aA, aClearance, aActual, aLocation );
1285 switch( aA->
Type() )
1291 switch( aB->
Type() )
1324 switch( aB->
Type() )
1357 switch( aB->
Type() )
1390 switch( aB->
Type() )
1424 switch( aB->
Type() )
1458 switch( aB->
Type() )
1489 switch( aB->
Type() )
1520 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported collision: %s with %s" ),
1530 int currentActual = std::numeric_limits<int>::max();
1533 bool colliding =
false;
1541 if( aActual && currentActual > 0 )
1550 auto collideCompoundSubshapes =
1558 aActual || aLocation ? &
actual :
nullptr,
1560 aMTV ? &mtv :
nullptr ) )
1562 if(
actual < currentActual )
1588 if( collideCompoundSubshapes( elemA, elemB, aClearance ) )
1607 if( collideCompoundSubshapes( elemA, aB, aClearance ) )
1622 if( collideCompoundSubshapes( aA, elemB, aClearance ) )
1639 *aLocation = currentLocation;
1642 *aActual = currentActual;
1654 return collideShapes(
this, aShape, aClearance,
nullptr,
nullptr, aMTV );
1660 return collideShapes(
this, aShape, aClearance, aActual, aLocation,
nullptr );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
constexpr coord_type GetBottom() const
Immutable owning spatial snapshot of straight segments.
VECTOR2I::extended_type ecoord
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)
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
int GetWidth() const override
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
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
SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError) const
Build a polyline approximation of the ellipse or arc.
const VECTOR2I & GetCenter() const
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const override
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed 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,...
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
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
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,...
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
bool Collide(const SHAPE *aShape, int aClearance, VECTOR2I *aActual) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
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_ELLIPSE
ellipse or elliptical arc
@ 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 bool collideEllipseVsSegments(const SHAPE_ELLIPSE &aA, const SegmentSource &aSegSource, int aClearance, int aHalfWidth, Containment aContainment, int *aActual, VECTOR2I *aLocation)
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
static std::vector< int > candidates(const SEGMENT_INDEX &aIndex, const SEG &aQuery, int aPadding)
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I