Further simplify PNS::ITEM::collideSimple().
Also brings text_pns_basic's mocks into line with their "real"
counterparts.
(cherry picked from commit 2f198bdcb2
)
This commit is contained in:
parent
3b05d03220
commit
eb492724c7
|
@ -48,8 +48,11 @@ static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
|
|||
bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
||||
COLLISION_SEARCH_CONTEXT* aCtx ) const
|
||||
{
|
||||
// Note: if 'this' is a pad or a via then its hole is a separate PNS::ITEM in the node's
|
||||
// index and we don't need to deal with holeI here. The same is *not* true of the routing
|
||||
// "head", so we do need to handle holeH.
|
||||
|
||||
const SHAPE* shapeI = Shape();
|
||||
const HOLE* holeI = Hole();
|
||||
int lineWidthI = 0;
|
||||
|
||||
const SHAPE* shapeH = aHead->Shape();
|
||||
|
@ -62,21 +65,7 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
|||
|
||||
//printf( "h %p n %p t %p ctx %p\n", aHead, aNode, this, aCtx );
|
||||
|
||||
if( aHead == this ) // we cannot be self-colliding
|
||||
return false;
|
||||
|
||||
// prevent bogus collisions between the item and its own hole.
|
||||
// FIXME: figure out a cleaner way of doing that
|
||||
if( holeI && aHead == holeI->ParentPadVia() )
|
||||
return false;
|
||||
|
||||
if( holeH && this == holeH->ParentPadVia() )
|
||||
return false;
|
||||
|
||||
if( holeH && this == holeH )
|
||||
return false;
|
||||
|
||||
if( holeI && aHead == holeI )
|
||||
if( this == aHead || this == holeH ) // we cannot be self-colliding
|
||||
return false;
|
||||
|
||||
// Special cases for "head" lines with vias attached at the end. Note that this does not
|
||||
|
@ -95,6 +84,11 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
|||
collisionsFound |= line->Via().collideSimple( this, aNode, aCtx );
|
||||
}
|
||||
|
||||
// And a special case for the "head" via's hole.
|
||||
|
||||
if( holeH )
|
||||
collisionsFound |= collideSimple( holeH, aNode, aCtx );
|
||||
|
||||
// Sadly collision routines ignore SHAPE_POLY_LINE widths so we have to pass them in as part
|
||||
// of the clearance value.
|
||||
if( m_kind == LINE_T )
|
||||
|
@ -107,34 +101,16 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
|||
if( !m_layers.Overlaps( aHead->m_layers ) )
|
||||
return false;
|
||||
|
||||
if( holeH )
|
||||
collisionsFound |= collideSimple( holeH, aNode, aCtx );
|
||||
|
||||
if( holeI )
|
||||
collisionsFound |= holeI->collideSimple( aHead, aNode, aCtx );
|
||||
|
||||
if( holeH && holeI )
|
||||
{
|
||||
if( aCtx )
|
||||
{
|
||||
// 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
|
||||
{
|
||||
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;
|
||||
|
||||
// Hole-to-hole collisions don't have anything to do with nets
|
||||
if( Kind() == HOLE_T && aHead->Kind() == HOLE_T )
|
||||
differentNetsOnly = false;
|
||||
|
||||
if( differentNetsOnly && m_net == aHead->m_net && m_net >= 0 && aHead->m_net >= 0 )
|
||||
{
|
||||
// same nets? no clearance!
|
||||
|
|
|
@ -440,8 +440,7 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
|
|||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
}
|
||||
|
||||
if( isHole( aA ) || isHole( aB ) )
|
||||
else if( isHole( aA ) || isHole( aB ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
|
||||
{
|
||||
|
|
|
@ -40,15 +40,26 @@ static bool isCopper( const PNS::ITEM* aItem )
|
|||
|
||||
BOARD_ITEM* parent = aItem->Parent();
|
||||
|
||||
if ( !parent )
|
||||
{
|
||||
return LSET::AllCuMask().Contains( (PCB_LAYER_ID) aItem->Layer() );
|
||||
}
|
||||
|
||||
if( parent && parent->Type() == PCB_PAD_T )
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( parent );
|
||||
return pad->IsOnCopperLayer() && pad->GetAttribute() != PAD_ATTRIB::NPTH;
|
||||
|
||||
if( !pad->IsOnCopperLayer() )
|
||||
return false;
|
||||
|
||||
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
|
||||
return true;
|
||||
|
||||
// round NPTH with a hole size >= pad size are not on a copper layer
|
||||
// All other NPTH are seen on copper layers
|
||||
// This is a basic criteria, but probably enough for a NPTH
|
||||
if( pad->GetShape() == PAD_SHAPE::CIRCLE )
|
||||
{
|
||||
if( pad->GetSize().x <= pad->GetDrillSize().x )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -69,12 +80,7 @@ static bool isEdge( const PNS::ITEM* aItem )
|
|||
if( !aItem )
|
||||
return false;
|
||||
|
||||
const BOARD_ITEM* parent = aItem->Parent();
|
||||
|
||||
if ( !parent )
|
||||
{
|
||||
return aItem->Layer() == Edge_Cuts;
|
||||
}
|
||||
const BOARD_ITEM *parent = aItem->BoardItem();
|
||||
|
||||
return parent && ( parent->IsOnLayer( Edge_Cuts ) || parent->IsOnLayer( Margin ) );
|
||||
}
|
||||
|
@ -93,51 +99,68 @@ public:
|
|||
bool aUseClearanceEpsilon = true ) override
|
||||
{
|
||||
PNS::CONSTRAINT constraint;
|
||||
int rv = -1;
|
||||
int layer;
|
||||
int rv = 0;
|
||||
LAYER_RANGE layers;
|
||||
|
||||
if( !aA->Layers().IsMultilayer() || !aB || aB->Layers().IsMultilayer() )
|
||||
layer = aA->Layer();
|
||||
if( !aB )
|
||||
layers = aA->Layers();
|
||||
else if( isEdge( aA ) )
|
||||
layers = aB->Layers();
|
||||
else if( isEdge( aB ) )
|
||||
layers = aA->Layers();
|
||||
else
|
||||
layer = aB->Layer();
|
||||
layers = aA->Layers().Intersection( aB->Layers() );
|
||||
|
||||
if( isHole( aA ) && isHole( aB ) )
|
||||
// Normalize layer range (no -1 magic numbers)
|
||||
layers = layers.Intersection( LAYER_RANGE( PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT - 1 ) );
|
||||
|
||||
for( int layer = layers.Start(); layer <= layers.End(); ++layer )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer,
|
||||
&constraint ) )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
else if( isHole( aA ) || isHole( aB ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer,
|
||||
&constraint ) )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
else if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
else if( isEdge( aA ) || ( aB && isEdge( aB ) ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer,
|
||||
&constraint ) )
|
||||
if( isHole( aA ) && isHole( aB) )
|
||||
{
|
||||
if( constraint.m_Value.Min() > rv )
|
||||
rv = constraint.m_Value.Min();
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE, aA, aB, layer, &constraint ) )
|
||||
{
|
||||
if( constraint.m_Value.Min() > rv )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
}
|
||||
else if( isHole( aA ) || isHole( aB ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE, aA, aB, layer, &constraint ) )
|
||||
{
|
||||
if( constraint.m_Value.Min() > rv )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
}
|
||||
else if( isCopper( aA ) && ( !aB || isCopper( aB ) ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, layer, &constraint ) )
|
||||
{
|
||||
if( constraint.m_Value.Min() > rv )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
}
|
||||
else if( isEdge( aA ) || ( aB && isEdge( aB ) ) )
|
||||
{
|
||||
if( QueryConstraint( PNS::CONSTRAINT_TYPE::CT_EDGE_CLEARANCE, aA, aB, layer, &constraint ) )
|
||||
{
|
||||
if( constraint.m_Value.Min() > rv )
|
||||
rv = constraint.m_Value.Min();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual int DpCoupledNet( int aNet ) override { return -1; }
|
||||
virtual int DpNetPolarity( int aNet ) override { return -1; }
|
||||
|
||||
virtual int DpCoupledNet( int aNet ) override { return -1; }
|
||||
virtual int DpNetPolarity( int aNet ) override { return -1; }
|
||||
virtual bool DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN ) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
|
||||
const PNS::ITEM* aItemB, int aLayer,
|
||||
PNS::CONSTRAINT* aConstraint ) override
|
||||
|
@ -149,13 +172,14 @@ public:
|
|||
key.type = aType;
|
||||
|
||||
auto it = m_ruleMap.find( key );
|
||||
|
||||
if( it == m_ruleMap.end() )
|
||||
{
|
||||
int cl;
|
||||
switch( aType )
|
||||
{
|
||||
case PNS::CONSTRAINT_TYPE::CT_CLEARANCE: cl = m_defaultClearance; break;
|
||||
case PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE: cl = m_defaultHole2Hole; break;
|
||||
case PNS::CONSTRAINT_TYPE::CT_CLEARANCE: cl = m_defaultClearance; break;
|
||||
case PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE: cl = m_defaultHole2Hole; break;
|
||||
case PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE: cl = m_defaultHole2Copper; break;
|
||||
default: return false;
|
||||
}
|
||||
|
@ -166,7 +190,9 @@ public:
|
|||
aConstraint->m_Value.SetMin( cl );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
*aConstraint = it->second;
|
||||
}
|
||||
|
||||
|
@ -294,8 +320,8 @@ static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
|
|||
|
||||
BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
|
||||
{
|
||||
PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
|
||||
PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 );
|
||||
PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
|
||||
PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 50000, 10000 );
|
||||
|
||||
std::unique_ptr<PNS::NODE> world ( new PNS::NODE );
|
||||
|
||||
|
@ -328,10 +354,28 @@ BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
|
|||
BOOST_CHECK_EQUAL( first.m_clearance, m_ruleResolver.m_defaultClearance );
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE( "via to via, forced copper to hole violation" );
|
||||
BOOST_TEST_MESSAGE( "via to via, forced hole to hole violation" );
|
||||
{
|
||||
PNS::NODE::OBSTACLES obstacles;
|
||||
m_ruleResolver.m_defaultClearance = 200000;
|
||||
m_ruleResolver.m_defaultHole2Hole = 1000000;
|
||||
|
||||
world->QueryColliding( v1, obstacles );
|
||||
dumpObstacles( obstacles );
|
||||
|
||||
BOOST_CHECK_EQUAL( obstacles.size(), 1 );
|
||||
auto iter = obstacles.begin();
|
||||
const auto first = *iter++;
|
||||
|
||||
BOOST_CHECK_EQUAL( first.m_head, v1->Hole() );
|
||||
BOOST_CHECK_EQUAL( first.m_item, v2->Hole() );
|
||||
BOOST_CHECK_EQUAL( first.m_clearance, m_ruleResolver.m_defaultHole2Hole );
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE( "via to via, forced copper to hole violation" );
|
||||
{
|
||||
PNS::NODE::OBSTACLES obstacles;
|
||||
m_ruleResolver.m_defaultHole2Hole = 220000;
|
||||
m_ruleResolver.m_defaultHole2Copper = 1000000;
|
||||
|
||||
world->QueryColliding( v1, obstacles );
|
||||
|
@ -340,13 +384,12 @@ BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE )
|
|||
BOOST_CHECK_EQUAL( obstacles.size(), 2 );
|
||||
auto iter = obstacles.begin();
|
||||
const auto first = *iter++;
|
||||
const auto second = *iter;
|
||||
|
||||
BOOST_CHECK_EQUAL( first.m_head, v1 );
|
||||
BOOST_CHECK_EQUAL( first.m_item, v2 );
|
||||
// There is no guarantee on what order the two collisions will be in...
|
||||
BOOST_CHECK( ( first.m_head == v1 && first.m_item == v2->Hole() )
|
||||
|| ( first.m_head == v1->Hole() && first.m_item == v2 ) );
|
||||
|
||||
BOOST_CHECK_EQUAL( first.m_clearance, m_ruleResolver.m_defaultHole2Copper );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue