Add true arc-to-polyline collisions

This commit is contained in:
Roberto Fernandez Bautista 2021-07-26 17:14:05 +01:00
parent dd65ce9523
commit eaf8eb284a
2 changed files with 47 additions and 7 deletions

View File

@ -534,14 +534,53 @@ static inline bool Collide( const SHAPE_ARC& aA, const SHAPE_LINE_CHAIN_BASE& aB
aA.Type(),
aB.Type() ) );
const SHAPE_LINE_CHAIN lc = aA.ConvertToPolyline();
int closest_dist = INT_MAX;
VECTOR2I nearest;
bool rv = Collide( lc, aB, aClearance + aA.GetWidth() / 2, aActual, aLocation, aMTV );
if( aB.IsClosed() && aB.PointInside( aA.GetP0() ) )
{
closest_dist = 0;
nearest = aA.GetP0();
}
else
{
for( size_t i = 0; i < aB.GetSegmentCount(); i++ )
{
int collision_dist = 0;
VECTOR2I pn;
if( rv && aActual )
*aActual = std::max( 0, *aActual - aA.GetWidth() / 2 );
if( aA.Collide( aB.GetSegment( i ), aClearance,
aActual || aLocation ? &collision_dist : nullptr,
aLocation ? &pn : nullptr ) )
{
if( collision_dist < closest_dist )
{
nearest = pn;
closest_dist = collision_dist;
}
return rv;
if( closest_dist == 0 )
break;
// If we're not looking for aActual then any collision will do
if( !aActual )
break;
}
}
}
if( closest_dist == 0 || closest_dist < aClearance )
{
if( aLocation )
*aLocation = nearest;
if( aActual )
*aActual = closest_dist;
return true;
}
return false;
}

View File

@ -761,10 +761,11 @@ BOOST_AUTO_TEST_CASE( CollideArcToPolygonApproximation )
// Create a polyset approximation from the arc - error outside (simulating the zone filler)
SHAPE_POLY_SET arcBuffer;
int clearance = ( arc.GetWidth() * 3 ) / 2;
int polygonApproximationError = SHAPE_ARC::DefaultAccuracyForPCB();
TransformArcToPolygon( arcBuffer, wxPoint( arc.GetP0() ), wxPoint( arc.GetArcMid() ),
wxPoint( arc.GetP1() ), arc.GetWidth() + 2 * clearance,
SHAPE_ARC::DefaultAccuracyForPCB(), ERROR_OUTSIDE );
polygonApproximationError, ERROR_OUTSIDE );
BOOST_REQUIRE_EQUAL( arcBuffer.OutlineCount(), 1 );
BOOST_CHECK_EQUAL( arcBuffer.HoleCount( 0 ), 0 );
@ -793,7 +794,7 @@ BOOST_AUTO_TEST_CASE( CollideArcToPolygonApproximation )
BOOST_CHECK_EQUAL( zoneFill.Collide( &arc, clearance * 2, &actual, &location ), true );
BOOST_CHECK( KI_TEST::IsWithin( actual, clearance, tol ) );
BOOST_CHECK( KI_TEST::IsWithin( actual, clearance, polygonApproximationError ) );
}