Fix some fairly catastrophic bugs in shape collision optimization.

I did a little too much copy & paste last time around....
This commit is contained in:
Jeff Young 2020-10-05 22:22:01 +01:00
parent 6d50c9749c
commit 18a3c4c1db
3 changed files with 95 additions and 70 deletions

View File

@ -107,8 +107,14 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aC
nearest = pn;
nearest_side_dist_sq = side_dist_sq;
// If we're not looking for actual or MTV, short-circuit once we find any collision
if( ( nearest_side_dist_sq == 0 || !aActual ) && !aMTV )
if( aMTV )
continue;
if( nearest_side_dist_sq == 0 )
break;
// If we're not looking for aActual then any collision will do
if( nearest_side_dist_sq < min_dist_sq && !aActual )
break;
}
}
@ -171,32 +177,37 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN_BASE&
int closest_dist = INT_MAX;
VECTOR2I nearest;
for( int s = 0; s < aB.GetSegmentCount(); s++ )
{
int collision_dist = 0;
VECTOR2I pn;
if( aA.Collide( aB.GetSegment( s ), aClearance,
aActual || aLocation ? &collision_dist : nullptr,
aLocation ? &pn : nullptr ) )
{
if( collision_dist < closest_dist )
{
nearest = pn;
closest_dist = collision_dist;
if( closest_dist == 0 || !aActual )
break;
}
}
}
if( aB.IsClosed() && aB.PointInside( aA.GetCenter() ) )
{
closest_dist = 0;
nearest = aA.GetCenter();
}
else
{
for( int s = 0; s < aB.GetSegmentCount(); s++ )
{
int collision_dist = 0;
VECTOR2I pn;
if( aA.Collide( aB.GetSegment( s ), aClearance,
aActual || aLocation ? &collision_dist : nullptr,
aLocation ? &pn : nullptr ) )
{
if( collision_dist < closest_dist )
{
nearest = pn;
closest_dist = collision_dist;
}
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 )
{
@ -251,31 +262,37 @@ static inline bool Collide( const SHAPE_LINE_CHAIN_BASE& aA, const SHAPE_LINE_CH
int closest_dist = INT_MAX;
VECTOR2I nearest;
for( int i = 0; i < aB.GetSegmentCount(); i++ )
{
int collision_dist = 0;
VECTOR2I pn;
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;
if( closest_dist == 0 || !aActual )
break;
}
}
}
if( aB.IsClosed() && aA.GetPointCount() > 0 && aB.PointInside( aA.GetPoint( 0 ) ) )
{
closest_dist = 0;
nearest = aA.GetPoint( 0 );
}
else
{
for( int i = 0; i < aB.GetSegmentCount(); i++ )
{
int collision_dist = 0;
VECTOR2I pn;
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;
}
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 )
{
@ -300,31 +317,37 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN_BASE& a
int closest_dist = INT_MAX;
VECTOR2I nearest;
for( int s = 0; s < aB.GetSegmentCount(); s++ )
{
int collision_dist = 0;
VECTOR2I pn;
if( aA.Collide( aB.GetSegment( s ), aClearance,
aActual || aLocation ? &collision_dist : nullptr,
aLocation ? &pn : nullptr ) )
{
if( collision_dist < closest_dist )
{
nearest = pn;
closest_dist = collision_dist;
if( closest_dist == 0 || !aActual )
break;
}
}
}
if( aB.IsClosed() && aB.PointInside( aA.Centre() ) )
{
nearest = aA.Centre();
closest_dist = 0;
}
else
{
for( int s = 0; s < aB.GetSegmentCount(); s++ )
{
int collision_dist = 0;
VECTOR2I pn;
if( aA.Collide( aB.GetSegment( s ), aClearance,
aActual || aLocation ? &collision_dist : nullptr,
aLocation ? &pn : nullptr ) )
{
if( collision_dist < closest_dist )
{
nearest = pn;
closest_dist = collision_dist;
}
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 )
{

View File

@ -114,7 +114,11 @@ bool SHAPE_LINE_CHAIN_BASE::Collide( const VECTOR2I& aP, int aClearance, int* aA
nearest = pn;
closest_dist_sq = dist_sq;
if( closest_dist_sq == 0 || !aActual )
if( closest_dist_sq == 0 )
break;
// If we're not looking for aActual then any collision will do
if( closest_dist_sq < clearance_sq && !aActual )
break;
}
}
@ -178,7 +182,11 @@ bool SHAPE_LINE_CHAIN_BASE::Collide( const SEG& aSeg, int aClearance, int* aActu
closest_dist_sq = dist_sq;
if( closest_dist_sq == 0 || !aActual )
if( closest_dist_sq == 0)
break;
// If we're not looking for aActual then any collision will do
if( closest_dist_sq < clearance_sq && !aActual )
break;
}
}

View File

@ -24,10 +24,8 @@
#include <vector>
#include <view/view.h>
#include <view/view_item.h>
#include <view/view_group.h>
#include <gal/graphics_abstraction_layer.h>
#include <gal/color4d.h>
#include <pgm_base.h>
#include <settings/settings_manager.h>
@ -36,10 +34,6 @@
#include <pcbnew_settings.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_circle.h>
#include <geometry/convex_hull.h>
#include "pns_node.h"
#include "pns_line_placer.h"