Unify most special-case processing to the clearance if-then-else.

This also allows us to support hole-to-hole clearance when dragging
a via near another via on the same net.

Fixes https://gitlab.com/kicad/code/kicad/issues/12781

(cherry picked from commit 8a0c225efa)
This commit is contained in:
Jeff Young 2023-04-06 15:33:49 +01:00
parent 2b6d2fc117
commit 4c04233a20
2 changed files with 44 additions and 34 deletions

View File

@ -103,20 +103,6 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
if( aHead->m_kind == LINE_T )
lineWidthH = static_cast<const LINE*>( aHead )->Width() / 2;
// same nets? no collision!
if( aCtx && aCtx->options.m_differentNetsOnly
&& m_net == aHead->m_net && m_net >= 0 && aHead->m_net >= 0 )
{
return false;
}
// a pad associated with a "free" pin (NIC) doesn't have a net until it has been used
if( aCtx && aCtx->options.m_differentNetsOnly
&& ( IsFreePad() || aHead->IsFreePad() ) )
{
return false;
}
// check if we are not on completely different layers first
if( !m_layers.Overlaps( aHead->m_layers ) )
return false;
@ -128,34 +114,56 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
collisionsFound |= holeI->collideSimple( aHead, aNode, aCtx );
if( holeH && holeI )
collisionsFound |= holeI->collideSimple( holeH, aNode, aCtx );
int clearance;
if( aCtx && aCtx->options.m_overrideClearance >= 0 )
{
clearance = aCtx->options.m_overrideClearance;
}
else if( aNode->GetRuleResolver()->IsKeepout( this, aHead ) )
if( aCtx )
{
clearance = 0; // keepouts are exact boundary; no clearance
// Hole to hole collsions are never net-specific
COLLISION_SEARCH_OPTIONS holeToHoleOptions( aCtx->options );
holeToHoleOptions.m_differentNetsOnly = false;
COLLISION_SEARCH_CONTEXT holeToHoleCtx( aCtx->obstacles, holeToHoleOptions );
collisionsFound |= holeI->collideSimple( holeH, aNode, &holeToHoleCtx );
}
else
{
clearance = aNode->GetClearance( this, aHead );
collisionsFound |= holeI->collideSimple( holeH, aNode, nullptr );
}
}
// fixme: this f***ing singleton must go...
ROUTER* router = ROUTER::GetInstance();
ROUTER_IFACE* iface = router ? router->GetInterface() : nullptr;
bool differentNetsOnly = aCtx && aCtx->options.m_differentNetsOnly;
int clearance;
if( iface )
if( differentNetsOnly && m_net == aHead->m_net && m_net >= 0 && aHead->m_net >= 0 )
{
if( !iface->IsFlashedOnLayer( this, aHead->Layer() ) )
return collisionsFound;
if( !iface->IsFlashedOnLayer( aHead, Layer() ) )
return collisionsFound;
// same nets? no clearance!
clearance = -1;
}
else if( differentNetsOnly && ( IsFreePad() || aHead->IsFreePad() ) )
{
// a pad associated with a "free" pin (NIC) doesn't have a net until it has been used
clearance = -1;
}
else if( aNode->GetRuleResolver()->IsKeepout( this, aHead ) )
{
clearance = 0; // keepouts are exact boundary; no clearance
}
else if( iface && !iface->IsFlashedOnLayer( this, aHead->Layer() ) )
{
clearance = -1;
}
else if( iface && !iface->IsFlashedOnLayer( aHead, Layer() ) )
{
clearance = -1;
}
else if( aCtx && aCtx->options.m_overrideClearance >= 0 )
{
clearance = aCtx->options.m_overrideClearance;
}
else
{
clearance = aNode->GetClearance( this, aHead );
}
if( clearance >= 0 )

View File

@ -340,6 +340,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
case PNS::ITEM::VIA_T: parentA = &m_dummyVias[0]; break;
case PNS::ITEM::SEGMENT_T: parentA = &m_dummyTracks[0]; break;
case PNS::ITEM::LINE_T: parentA = &m_dummyTracks[0]; break;
case PNS::ITEM::HOLE_T: parentB = &m_dummyVias[0]; break;
default: break;
}
@ -358,6 +359,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
case PNS::ITEM::VIA_T: parentB = &m_dummyVias[1]; break;
case PNS::ITEM::SEGMENT_T: parentB = &m_dummyTracks[1]; break;
case PNS::ITEM::LINE_T: parentB = &m_dummyTracks[1]; break;
case PNS::ITEM::HOLE_T: parentB = &m_dummyVias[1]; break;
default: break;
}