7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 00:21:31 +00:00

Handle more arc degeneracies

This commit is contained in:
Seth Hillbrand 2025-01-14 12:51:44 -08:00
parent bfb3875a68
commit 5cd9e319d3

View File

@ -530,24 +530,58 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_RECT& aB, int aCle
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_RECT& aB, int aClearance,
int* aActual, VECTOR2I* aLocation, VECTOR2I* aMTV )
{
wxASSERT_MSG( !aMTV, wxString::Format( wxT( "MTV not implemented for %s : %s collisions" ),
aA.TypeName(),
aB.TypeName() ) );
if( aA.IsEffectiveLine() )
{
SHAPE_SEGMENT tmp( aA.GetP0(), aA.GetP1(), aA.GetWidth() );
bool retval = Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
const SHAPE_LINE_CHAIN lc( aA );
if( retval && aMTV )
*aMTV = - *aMTV;
bool rv = Collide( lc, aB.Outline(), aClearance + aA.GetWidth() / 2, aActual, aLocation, aMTV );
return retval;
}
if( rv && aActual )
*aActual = std::max( 0, *aActual - aA.GetWidth() / 2 );
VECTOR2I ptA, ptB;
int64_t dist_sq = std::numeric_limits<int64_t>::max();
aA.NearestPoints( aB, ptA, ptB, dist_sq );
int half_width = ( aA.GetWidth() + 1 ) / 2;
int min_dist = aClearance + half_width;
return rv;
if( dist_sq < SEG::Square( min_dist ) )
{
if( aLocation )
*aLocation = ( ptA + ptB ) / 2;
if( aActual )
*aActual = std::max( 0, KiROUND( std::sqrt( dist_sq ) - half_width ) );
if( aMTV )
{
const VECTOR2I delta = ptB - ptA;
*aMTV = delta.Resize( min_dist - std::sqrt( dist_sq ) + 3 );
}
return true;
}
return false;
}
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_CIRCLE& aB, int aClearance,
int* aActual, VECTOR2I* aLocation, VECTOR2I* aMTV )
{
if( aA.IsEffectiveLine() )
{
SHAPE_SEGMENT tmp( aA.GetP0(), aA.GetP1(), aA.GetWidth() );
bool retval = Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
if( retval && aMTV )
*aMTV = - *aMTV;
return retval;
}
VECTOR2I ptA, ptB;
int64_t dist_sq = std::numeric_limits<int64_t>::max();
aA.NearestPoints( aB, ptA, ptB, dist_sq );
@ -750,6 +784,23 @@ static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_LINE_CHAIN_BASE& aB
static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_ARC& aB, int aClearance,
int* aActual, VECTOR2I* aLocation, VECTOR2I* aMTV )
{
if( aA.IsEffectiveLine() )
{
SHAPE_SEGMENT tmp( aA.GetP0(), aA.GetP1(), aA.GetWidth() );
bool retval = Collide( aB, tmp, aClearance, aActual, aLocation, aMTV );
if( retval && aMTV )
*aMTV = - *aMTV;
return retval;
}
if( aB.IsEffectiveLine() )
{
SHAPE_SEGMENT tmp( aB.GetP0(), aB.GetP1(), aB.GetWidth() );
return Collide( aA, tmp, aClearance, aActual, aLocation, aMTV );
}
VECTOR2I ptA, ptB;
int64_t dist_sq = std::numeric_limits<int64_t>::max();
aA.NearestPoints( aB, ptA, ptB, dist_sq );