const PNS_ITEMSET PNS_DIFF_PAIR_PLACER::Traces() { PNS_ITEMSET t; t.Add( const_cast<PNS_LINE*>( &m_currentTrace.PLine() ) ); t.Add( const_cast<PNS_LINE*>( &m_currentTrace.NLine() ) ); return t; }
bool PNS_TOPOLOGY::followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET& aSet, std::set<PNS_ITEM*>& aVisited ) { VECTOR2I anchor = aLeft ? aLine->CPoint( 0 ) : aLine->CPoint( -1 ); PNS_SEGMENT* last = aLeft ? aLine->LinkedSegments()->front() : aLine->LinkedSegments()->back(); PNS_JOINT* jt = m_world->FindJoint( anchor, aLine ); assert( jt != NULL ); aVisited.insert( last ); if( jt->IsNonFanoutVia() || jt->IsTraceWidthChange() ) { PNS_ITEM* via = NULL; PNS_SEGMENT* next_seg = NULL; for( PNS_ITEM* link : jt->Links().Items() ) { if( link->OfKind( PNS_ITEM::VIA ) ) via = link; else if( aVisited.find( link ) == aVisited.end() ) next_seg = static_cast<PNS_SEGMENT*>( link ); } if( !next_seg ) return false; PNS_LINE l = m_world->AssembleLine( next_seg ); VECTOR2I nextAnchor = ( aLeft ? l.CLine().CPoint( -1 ) : l.CLine().CPoint( 0 ) ); if( nextAnchor != anchor ) { l.Reverse(); } if( aLeft ) { if( via ) aSet.Prepend( via ); aSet.Prepend( l ); } else { if( via ) aSet.Add( via ); aSet.Add( l ); } return followTrivialPath( &l, aLeft, aSet, aVisited ); } return false; }
const PNS_ITEMSET PNS_TOPOLOGY::AssembleTrivialPath( PNS_SEGMENT* aStart ) { PNS_ITEMSET path; std::set<PNS_ITEM*> visited; PNS_LINE l = m_world->AssembleLine( aStart ); path.Add( l ); followTrivialPath( &l, false, path, visited ); followTrivialPath( &l, true, path, visited ); return path; }
void PNS_ROUTER::markViolations( PNS_NODE* aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ITEM_VECTOR& aRemoved ) { for( PNS_ITEM* item : aCurrent.Items() ) { PNS_NODE::OBSTACLES obstacles; aNode->QueryColliding( item, obstacles, PNS_ITEM::ANY ); if( item->OfKind( PNS_ITEM::LINE ) ) { PNS_LINE* l = static_cast<PNS_LINE*>( item ); if( l->EndsWithVia() ) { PNS_VIA v( l->Via() ); aNode->QueryColliding( &v, obstacles, PNS_ITEM::ANY ); } } for( PNS_OBSTACLE& obs : obstacles ) { int clearance = aNode->GetClearance( item, obs.m_item ); std::unique_ptr<PNS_ITEM> tmp( obs.m_item->Clone() ); tmp->Mark( MK_VIOLATION ); m_iface->DisplayItem( tmp.get(), -1, clearance ); aRemoved.push_back( obs.m_item ); } } }
void PNS_TOOL_BASE::deleteTraces( PNS_ITEM* aStartItem, bool aWholeTrack ) { PNS_NODE *node = m_router->GetWorld()->Branch(); if( !aStartItem ) return; if( !aWholeTrack ) { node->Remove( aStartItem ); } else { PNS_TOPOLOGY topo( node ); PNS_ITEMSET path = topo.AssembleTrivialPath( aStartItem ); for( auto ent : path.Items() ) node->Remove( ent.item ); } m_router->CommitRouting( node ); }
int PNS_MEANDER_SKEW_PLACER::itemsetLength( const PNS_ITEMSET& aSet ) const { int total = 0; BOOST_FOREACH( const PNS_ITEM* item, aSet.CItems() ) { if( const PNS_LINE* l = dyn_cast<const PNS_LINE*>( item ) ) { total += l->CLine().Length(); } } return total; }
bool PNS_DIFF_PAIR_PLACER::rhShoveOnly( const VECTOR2I& aP ) { m_currentNode = m_shove->CurrentNode(); bool ok = routeHead( aP ); m_fitOk = false; if( !ok ) return false; if( !tryWalkDp( m_currentNode, m_currentTrace, true ) ) return false; PNS_LINE pLine( m_currentTrace.PLine() ); PNS_LINE nLine( m_currentTrace.NLine() ); PNS_ITEMSET head; head.Add( &pLine ); head.Add( &nLine ); PNS_SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head ); m_currentNode = m_shove->CurrentNode(); if( status == PNS_SHOVE::SH_OK ) { m_currentNode = m_shove->CurrentNode(); if( !m_currentNode->CheckColliding( &m_currentTrace.PLine() ) && !m_currentNode->CheckColliding( &m_currentTrace.NLine() ) ) { m_fitOk = true; } } return m_fitOk; }
void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { m_iface->EraseView(); m_placer->Move( aP, aEndItem ); PNS_ITEMSET current = m_placer->Traces(); for( const PNS_ITEM* item : current.CItems() ) { if( !item->OfKind( PNS_ITEM::LINE ) ) continue; const PNS_LINE* l = static_cast<const PNS_LINE*>( item ); m_iface->DisplayItem( l ); if( l->EndsWithVia() ) m_iface->DisplayItem( &l->Via() ); } //PNS_ITEMSET tmp( ¤t ); updateView( m_placer->CurrentNode( true ), current ); }
void PNS_ROUTER::DisplayItems( const PNS_ITEMSET& aItems ) { for( const PNS_ITEM* item : aItems.CItems() ) m_iface->DisplayItem( item ); }
PNS_ITEM* PNS_TOOL_BASE::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer ) { int tl = getView()->GetTopLayer(); if( aLayer > 0 ) tl = aLayer; PNS_ITEM* prioritized[4]; for( int i = 0; i < 4; i++ ) prioritized[i] = 0; PNS_ITEMSET candidates = m_router->QueryHoverItems( aWhere ); for( PNS_ITEM* item : candidates.Items() ) { if( !IsCopperLayer( item->Layers().Start() ) ) continue; // fixme: this causes flicker with live loop removal... //if( item->Parent() && !item->Parent()->ViewIsVisible() ) // continue; if( aNet < 0 || item->Net() == aNet ) { if( item->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ) ) { if( !prioritized[2] ) prioritized[2] = item; if( item->Layers().Overlaps( tl ) ) prioritized[0] = item; } else { if( !prioritized[3] ) prioritized[3] = item; if( item->Layers().Overlaps( tl ) ) prioritized[1] = item; } } } PNS_ITEM* rv = NULL; PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)frame->GetDisplayOptions(); for( int i = 0; i < 4; i++ ) { PNS_ITEM* item = prioritized[i]; if( displ_opts->m_ContrastModeDisplay ) if( item && !item->Layers().Overlaps( tl ) ) item = NULL; if( item ) { rv = item; break; } } if( rv && aLayer >= 0 && !rv->Layers().Overlaps( aLayer ) ) rv = NULL; if( rv ) { wxLogTrace( "PNS", "%s, layer : %d, tl: %d", rv->KindStr().c_str(), rv->Layers().Start(), tl ); } return rv; }