const PNS_DIFF_PAIR PNS_DP_GATEWAY::Entry() const { return PNS_DIFF_PAIR( m_entryP, m_entryN, 0 ); }
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; }
bool PNS_DIFF_PAIR_PLACER::routeHead( const VECTOR2I& aP ) { m_fitOk = false; PNS_DP_GATEWAYS gwsEntry( gap() ); PNS_DP_GATEWAYS gwsTarget( gap() ); if( !m_prevPair ) m_prevPair = m_start; gwsEntry.BuildFromPrimitivePair( *m_prevPair, m_startDiagonal ); PNS_DP_PRIMITIVE_PAIR target; if( findDpPrimitivePair( aP, m_currentEndItem, target ) ) { gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal ); m_snapOnTarget = true; } else { VECTOR2I fp; if( !propagateDpHeadForces( aP, fp ) ) return false; VECTOR2I midp, dirV; m_prevPair->CursorOrientation( fp, midp, dirV ); VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp ); int lead_dist = ( fpProj - fp ).EuclideanNorm(); gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() ); if( lead_dist > m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) { gwsTarget.BuildForCursor( fp ); } else { gwsTarget.BuildForCursor( fpProj ); gwsTarget.FilterByOrientation( DIRECTION_45::ANG_STRAIGHT | DIRECTION_45::ANG_HALF_FULL, DIRECTION_45( dirV ) ); } m_snapOnTarget = false; } m_currentTrace = PNS_DIFF_PAIR(); m_currentTrace.SetGap( gap() ); m_currentTrace.SetLayer( m_currentLayer ); bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace ); if( result ) { m_currentTrace.SetNets( m_netP, m_netN ); m_currentTrace.SetWidth( m_sizes.DiffPairWidth() ); m_currentTrace.SetGap( m_sizes.DiffPairGap() ); if( m_placingVia ) { m_currentTrace.AppendVias ( makeVia( m_currentTrace.CP().CPoint( -1 ), m_netP ), makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) ); } return true; } return false; }