bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { bool realEnd = false; int lastV; PNS_LINE pl = Trace(); if( m_currentMode == RM_MarkObstacles && !Settings().CanViolateDRC() && m_world->CheckColliding( &pl ) ) return false; const SHAPE_LINE_CHAIN& l = pl.CLine(); if( !l.SegmentCount() ) { if( pl.EndsWithVia() ) { m_lastNode->Add( pl.Via().Clone() ); Router()->CommitRouting( m_lastNode ); m_lastNode = NULL; m_currentNode = NULL; m_idle = true; } return true; } VECTOR2I p_pre_last = l.CPoint( -1 ); const VECTOR2I p_last = l.CPoint( -1 ); DIRECTION_45 d_last( l.CSegment( -1 ) ); if( l.PointCount() > 2 ) p_pre_last = l.CPoint( -2 ); if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() ) realEnd = true; if( realEnd || m_placingVia ) lastV = l.SegmentCount(); else lastV = std::max( 1, l.SegmentCount() - 1 ); PNS_SEGMENT* lastSeg = NULL; for( int i = 0; i < lastV; i++ ) { const SEG& s = pl.CSegment( i ); PNS_SEGMENT* seg = new PNS_SEGMENT( s, m_currentNet ); seg->SetWidth( pl.Width() ); seg->SetLayer( m_currentLayer ); m_lastNode->Add( seg ); lastSeg = seg; } if( pl.EndsWithVia() ) m_lastNode->Add( pl.Via().Clone() ); if( realEnd ) simplifyNewLine( m_lastNode, lastSeg ); Router()->CommitRouting( m_lastNode ); m_lastNode = NULL; m_currentNode = NULL; if( !realEnd ) { setInitialDirection( d_last ); m_currentStart = m_placingVia ? p_last : p_pre_last; m_startItem = NULL; m_placingVia = false; m_chainedPlacement = !pl.EndsWithVia(); m_splitSeg = false; initPlacement(); } else { m_idle = true; } return realEnd; }
bool PNS_LINE_PLACER::optimizeTailHeadTransition() { PNS_LINE tmp = Trace(); if( PNS_OPTIMIZER::Optimize( &tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode ) ) { if( tmp.SegmentCount() < 1 ) return false; m_head = tmp; m_p_start = tmp.CLine().CPoint( 0 ); m_direction = DIRECTION_45( tmp.CSegment( 0 ) ); m_tail.Line().Clear(); return true; } SHAPE_LINE_CHAIN& head = m_head.Line(); SHAPE_LINE_CHAIN& tail = m_tail.Line(); int tailLookbackSegments = 3; //if(m_currentMode() == RM_Walkaround) // tailLookbackSegments = 10000; int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 ); if( tail.SegmentCount() < 3 ) return false; // assemble TailLookbackSegments tail segments with the current head SHAPE_LINE_CHAIN opt_line = tail.Slice( -threshold, -1 ); int end = std::min(2, head.PointCount() - 1 ); opt_line.Append( head.Slice( 0, end ) ); PNS_LINE new_head( m_tail, opt_line ); // and see if it could be made simpler by merging obtuse/collnear segments. // If so, replace the (threshold) last tail points and the head with // the optimized line if( PNS_OPTIMIZER::Optimize( &new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode ) ) { PNS_LINE tmp( m_tail, opt_line ); TRACE( 0, "Placer: optimize tail-head [%d]", threshold ); head.Clear(); tail.Replace( -threshold, -1, new_head.CLine() ); tail.Simplify(); m_p_start = new_head.CLine().CPoint( -1 ); m_direction = DIRECTION_45( new_head.CSegment( -1 ) ); return true; } return false; }