Rewrite broken collision routine SHAPE_ARC::Collide( SEG& aSeg )
This commit is contained in:
parent
9b43689a76
commit
d47bd3a04d
|
@ -231,67 +231,24 @@ bool SHAPE_ARC::Collide( const SEG& aSeg, int aClearance, int* aActual, VECTOR2I
|
|||
if( aSeg.A == aSeg.B )
|
||||
return Collide( aSeg.A, aClearance, aActual, aLocation );
|
||||
|
||||
int minDist = aClearance + m_width / 2;
|
||||
VECTOR2I center = GetCenter();
|
||||
ecoord dist_sq;
|
||||
ecoord closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
VECTOR2I nearest;
|
||||
CIRCLE circle( center, GetRadius() );
|
||||
|
||||
VECTOR2I ab = ( aSeg.B - aSeg.A );
|
||||
VECTOR2I ac = ( center - aSeg.A );
|
||||
// Possible points of the collision are:
|
||||
// 1. Intersetion of the segment with the full circle
|
||||
// 2. Closest point on the segment to the center of the circle
|
||||
// 3. End points of the segment
|
||||
|
||||
ecoord lenAbSq = ab.SquaredEuclideanNorm();
|
||||
double lambda = (double) ac.Dot( ab ) / (double) lenAbSq;
|
||||
std::vector<VECTOR2I> candidatePts = circle.Intersect( aSeg );
|
||||
|
||||
if( lambda >= 0.0 && lambda <= 1.0 )
|
||||
candidatePts.push_back( aSeg.NearestPoint( center ) );
|
||||
candidatePts.push_back( aSeg.A );
|
||||
candidatePts.push_back( aSeg.B );
|
||||
|
||||
for( const VECTOR2I& candidate : candidatePts )
|
||||
{
|
||||
VECTOR2I p;
|
||||
|
||||
p.x = (double) aSeg.A.x * lambda + (double) aSeg.B.x * (1.0 - lambda);
|
||||
p.y = (double) aSeg.A.y * lambda + (double) aSeg.B.y * (1.0 - lambda);
|
||||
|
||||
dist_sq = ( m_start - p ).SquaredEuclideanNorm();
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
nearest = p;
|
||||
}
|
||||
|
||||
dist_sq = ( m_end - p ).SquaredEuclideanNorm();
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
nearest = p;
|
||||
}
|
||||
}
|
||||
|
||||
dist_sq = aSeg.SquaredDistance( m_start );
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
nearest = m_start;
|
||||
}
|
||||
|
||||
dist_sq = aSeg.SquaredDistance( m_end );
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
nearest = m_end;
|
||||
}
|
||||
|
||||
if( closest_dist_sq == 0 || closest_dist_sq < SEG::Square( minDist ) )
|
||||
{
|
||||
if( aLocation )
|
||||
*aLocation = nearest;
|
||||
|
||||
if( aActual )
|
||||
*aActual = std::max( 0, (int) sqrt( closest_dist_sq ) - m_width / 2 );
|
||||
|
||||
return true;
|
||||
if( Collide( candidate, aClearance, aActual, aLocation ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -844,6 +844,31 @@ BOOST_AUTO_TEST_CASE( CollideArc )
|
|||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( CollideArcToShapeLineChain )
|
||||
{
|
||||
SHAPE_ARC arc( VECTOR2I( 206000000, 140110000 ), VECTOR2I( 201574617, 139229737 ),
|
||||
VECTOR2I( 197822958, 136722959 ), 250000 );
|
||||
|
||||
SHAPE_LINE_CHAIN lc( { VECTOR2I( 159600000, 142500000 ), VECTOR2I( 159600000, 142600000 ),
|
||||
VECTOR2I( 166400000, 135800000 ), VECTOR2I( 166400000, 111600000 ),
|
||||
VECTOR2I( 190576804, 111600000 ), VECTOR2I( 192242284, 113265480 ),
|
||||
VECTOR2I( 192255720, 113265480 ), VECTOR2I( 203682188, 124691948 ),
|
||||
VECTOR2I( 203682188, 140332188 ), VECTOR2I( 206000000, 142650000 ) },
|
||||
false );
|
||||
|
||||
|
||||
|
||||
SHAPE* arc_sh = &arc;
|
||||
SHAPE* lc_sh = &lc;
|
||||
|
||||
BOOST_CHECK_EQUAL( arc_sh->Collide( &lc, 100000 ), true );
|
||||
BOOST_CHECK_EQUAL( lc_sh->Collide( &arc, 100000 ), true );
|
||||
|
||||
SEG seg( VECTOR2I( 203682188, 124691948 ), VECTOR2I( 203682188, 140332188 ) );
|
||||
BOOST_CHECK_EQUAL( arc.Collide( seg, 0 ), true );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( CollideArcToPolygonApproximation )
|
||||
{
|
||||
SHAPE_ARC arc( VECTOR2I( 73843527, 74355869 ), VECTOR2I( 71713528, 72965869 ), -76.36664803,
|
||||
|
|
|
@ -225,8 +225,70 @@ int playground_main_func( int argc, char* argv[] )
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int drawShapes( int argc, char* argv[] )
|
||||
{
|
||||
SHAPE_ARC arc( VECTOR2I( 206000000, 140110000 ), VECTOR2I( 201574617, 139229737 ),
|
||||
VECTOR2I( 197822958, 136722959 ), 250000 );
|
||||
|
||||
SHAPE_LINE_CHAIN lc( { /* VECTOR2I( 159600000, 142500000 ), VECTOR2I( 159600000, 142600000 ),
|
||||
VECTOR2I( 166400000, 135800000 ), VECTOR2I( 166400000, 111600000 ),
|
||||
VECTOR2I( 190576804, 111600000 ), VECTOR2I( 192242284, 113265480 ),
|
||||
VECTOR2I( 192255720, 113265480 ),*/
|
||||
VECTOR2I( 203682188, 124691948 ), VECTOR2I( 203682188, 140332188 ),
|
||||
/* VECTOR2I( 206000000, 142650000 ) */ },
|
||||
false );
|
||||
|
||||
auto frame = new PNS_LOG_VIEWER_FRAME( nullptr );
|
||||
Pgm().App().SetTopWindow( frame ); // wxApp gets a face.
|
||||
frame->Show();
|
||||
|
||||
overlay = frame->GetOverlay();
|
||||
|
||||
|
||||
overlay->SetIsFill( false );
|
||||
overlay->SetLineWidth( arc.GetWidth() );
|
||||
overlay->SetStrokeColor( RED );
|
||||
overlay->Arc( arc );
|
||||
overlay->SetLineWidth( arc.GetWidth() / 20 );
|
||||
overlay->SetStrokeColor( GREEN );
|
||||
overlay->Polyline( lc );
|
||||
|
||||
overlay->SetLineWidth( 80000.0 );
|
||||
overlay->SetStrokeColor( CYAN );
|
||||
|
||||
for( int i = 0; i < lc.PointCount(); ++i )
|
||||
{
|
||||
int mult = ( i % 2 ) ? 1 : -1;
|
||||
overlay->AnnotatedPoint( lc.GetPoint( i ), arc.GetWidth() * 2 );
|
||||
overlay->SetGlyphSize( { 800000.0, 800000.0 } );
|
||||
overlay->BitmapText( wxString::Format( "x=%d, y=%d", lc.GetPoint( i ).x, lc.GetPoint( i ).y ),
|
||||
lc.GetPoint( i ) + VECTOR2I( 0, mult*arc.GetWidth() * 4 ), 0 );
|
||||
}
|
||||
|
||||
arc.Collide( &lc, 100000 );
|
||||
|
||||
BOX2I vp = arc.BBox();
|
||||
vp.Merge( lc.BBox() );
|
||||
vp.Inflate( (800000 + arc.GetWidth() * 4 )*2);
|
||||
frame->GetPanel()->GetView()->SetViewport( BOX2D( vp.GetOrigin(), vp.GetSize() ) );
|
||||
|
||||
overlay = nullptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool registered = UTILITY_REGISTRY::Register( {
|
||||
"playground",
|
||||
"Geometry/drawing playground",
|
||||
playground_main_func,
|
||||
} );
|
||||
|
||||
|
||||
static bool registered1 = UTILITY_REGISTRY::Register( {
|
||||
"drawShapes",
|
||||
"drawing shapes",
|
||||
drawShapes,
|
||||
} );
|
||||
|
|
Loading…
Reference in New Issue