When dragging a via, we need to get all obstacles

The clearance epsilon should not be used to limit which force elements
we return in the query.  Otherwise, we can drag elements into a
DRC-violating space

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16293

(cherry picked from commit 5e850911c5)
This commit is contained in:
Seth Hillbrand 2024-03-29 09:49:43 -07:00
parent 892c5726f5
commit 6b5acdea1f
4 changed files with 30 additions and 7 deletions

View File

@ -191,6 +191,9 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
}
else
{
if( aCtx && !aCtx->options.m_useClearanceEpsilon )
clearanceEpsilon = 0;
clearance = aNode->GetClearance( this, aHead, aCtx ? aCtx->options.m_useClearanceEpsilon
: false );
}

View File

@ -409,12 +409,18 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM_SET& aSet, int aKindMask )
NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
{
OBSTACLES obs;
COLLISION_SEARCH_OPTIONS opts;
opts.m_kindMask = aKindMask;
opts.m_limitCount = 1;
return CheckColliding( aItemA, opts );
}
NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, const COLLISION_SEARCH_OPTIONS& aOpts )
{
OBSTACLES obs;
if( aItemA->Kind() == ITEM::LINE_T )
{
int n = 0;
@ -428,7 +434,7 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
// Disabling the cache will lead to slowness.
const SEGMENT s( *line, l.CSegment( i ) );
n += QueryColliding( &s, obs, opts );
n += QueryColliding( &s, obs, aOpts );
if( n )
return OPT_OBSTACLE( *obs.begin() );
@ -436,13 +442,13 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
if( line->EndsWithVia() )
{
n += QueryColliding( &line->Via(), obs, opts );
n += QueryColliding( &line->Via(), obs, aOpts );
if( n )
return OPT_OBSTACLE( *obs.begin() );
}
}
else if( QueryColliding( aItemA, obs, opts ) > 0 )
else if( QueryColliding( aItemA, obs, aOpts ) > 0 )
{
return OPT_OBSTACLE( *obs.begin() );
}

View File

@ -279,8 +279,7 @@ public:
* starting point.
*
* @param aLine the item to find collisions with
* @param aKindMask mask of obstacle types to take into account
* @param aRestrictedSet is an optional set of items that should be considered as obstacles
* @param aOpts options for the search
* @return the obstacle, if found, otherwise empty.
*/
OPT_OBSTACLE NearestObstacle( const LINE* aLine,
@ -307,6 +306,16 @@ public:
*/
OPT_OBSTACLE CheckColliding( const ITEM_SET& aSet, int aKindMask = ITEM::ANY_T );
/**
* Check if the item collides with anything else in the world, and if found, returns the
* obstacle.
*
* @param aItem the item to find collisions with
* @param aOpts options for the search
* @return the obstacle, if found, otherwise empty.
*/
OPT_OBSTACLE CheckColliding( const ITEM* aItem, const COLLISION_SEARCH_OPTIONS& aOpts );
/**
* Find all items that contain the point \a aPoint.
*

View File

@ -61,7 +61,12 @@ bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForc
while( iter < aMaxIterations )
{
NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, aCollisionMask );
COLLISION_SEARCH_OPTIONS opt;
opt.m_limitCount = 1;
opt.m_kindMask = aCollisionMask;
opt.m_useClearanceEpsilon = false;
NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, opt );
if( !obs )
break;