PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER* aRouter ) : m_router( aRouter ), m_board( aBoard ) { PNS::NODE* world = m_router->GetWorld(); PNS::TOPOLOGY topo( world ); m_netClearanceCache.resize( m_board->GetNetCount() ); // Build clearance cache for net classes for( unsigned int i = 0; i < m_board->GetNetCount(); i++ ) { NETINFO_ITEM* ni = m_board->FindNet( i ); if( ni == NULL ) continue; CLEARANCE_ENT ent; ent.coupledNet = DpCoupledNet( i ); wxString netClassName = ni->GetClassName(); NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName ); int clearance = nc->GetClearance(); ent.clearance = clearance; m_netClearanceCache[i] = ent; wxLogTrace( "PNS", "Add net %u netclass %s clearance %d", i, netClassName.mb_str(), clearance ); } // Build clearance cache for pads for( MODULE* mod = m_board->m_Modules; mod ; mod = mod->Next() ) { auto moduleClearance = mod->GetLocalClearance(); for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() ) { int padClearance = pad->GetLocalClearance(); if( padClearance > 0 ) m_localClearanceCache[ pad ] = padClearance; else if( moduleClearance > 0 ) m_localClearanceCache[ pad ] = moduleClearance; } } //printf("DefaultCL : %d\n", m_board->GetDesignSettings().m_NetClasses.Find ("Default clearance")->GetClearance()); m_overrideEnabled = false; m_defaultClearance = Millimeter2iu( 0.254 ); // m_board->m_NetClasses.Find ("Default clearance")->GetClearance(); m_overrideNetA = 0; m_overrideNetB = 0; m_overrideClearance = 0; m_useDpGap = false; }
bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ) { int refNet = aStart->Net(); int coupledNet = DpCoupledNet( refNet ); if( coupledNet < 0 ) return false; std::set<PNS_ITEM*> coupledItems; m_world->AllItemsInNet( coupledNet, coupledItems ); PNS_SEGMENT* coupledSeg = NULL, *refSeg; int minDist = std::numeric_limits<int>::max(); if( ( refSeg = dyn_cast<PNS_SEGMENT*>( aStart ) ) != NULL ) { for( PNS_ITEM* item : coupledItems ) { if( PNS_SEGMENT* s = dyn_cast<PNS_SEGMENT*>( item ) ) { if( s->Layers().Start() == refSeg->Layers().Start() && s->Width() == refSeg->Width() ) { int dist = s->Seg().Distance( refSeg->Seg() ); bool isParallel = refSeg->Seg().ApproxParallel( s->Seg() ); SEG p_clip, n_clip; bool isCoupled = commonParallelProjection( refSeg->Seg(), s->Seg(), p_clip, n_clip ); if( isParallel && isCoupled && dist < minDist ) { minDist = dist; coupledSeg = s; } } } } } else { return false; } if( !coupledSeg ) return false; PNS_LINE lp = m_world->AssembleLine( refSeg ); PNS_LINE ln = m_world->AssembleLine( coupledSeg ); if( DpNetPolarity( refNet ) < 0 ) { std::swap( lp, ln ); } int gap = -1; if( refSeg->Seg().ApproxParallel( coupledSeg->Seg() ) ) { // Segments are parallel -> compute pair gap const VECTOR2I refDir = refSeg->Anchor( 1 ) - refSeg->Anchor( 0 ); const VECTOR2I displacement = refSeg->Anchor( 1 ) - coupledSeg->Anchor( 1 ); gap = (int) std::abs( refDir.Cross( displacement ) / refDir.EuclideanNorm() ) - lp.Width(); } aPair = PNS_DIFF_PAIR( lp, ln ); aPair.SetWidth( lp.Width() ); aPair.SetLayers( lp.Layers() ); aPair.SetGap( gap ); return true; }