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_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;
}
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;
}
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;
}