diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 2a6d8efa49..ce3f845a60 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -707,10 +707,7 @@ void PNS_LINE::Reverse() void PNS_LINE::AppendVia( const PNS_VIA& aVia ) { - if( m_line.PointCount() == 0 ) - return; - - if( aVia.Pos() == m_line.CPoint( 0 ) ) + if( m_line.PointCount() > 1 && aVia.Pos() == m_line.CPoint( 0 ) ) { Reverse(); } diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index b31b5ed6a4..892fa05a10 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -357,42 +357,16 @@ bool PNS_LINE_PLACER::mergeHead() } -bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) -{ - if( !m_placingVia ) - return true; - - PNS_VIA v ( makeVia ( aHead.CPoint( -1 ) ) ); - v.SetNet ( aHead.Net() ); - - - VECTOR2I force; - VECTOR2I lead = aHead.CPoint( -1 ) - aHead.CPoint( 0 ); - - bool solidsOnly = ( m_currentMode != RM_Walkaround ); - - if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) ) - { - SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( - aHead.CPoint( 0 ), - aHead.CPoint( -1 ) + force ); - aHead = PNS_LINE( aHead, line ); - - v.SetPos( v.Pos() + force ); - return true; - } - - return false; -} bool PNS_LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, PNS_LINE& aNewHead ) { - SHAPE_LINE_CHAIN line = buildInitialLine( aP ); - PNS_LINE initTrack( m_head, line ), walkFull; + PNS_LINE initTrack( m_head ); + PNS_LINE walkFull; int effort = 0; - bool viaOk = handleViaPlacement( initTrack ); - bool rv = true; + bool rv = true, viaOk; + + viaOk = buildInitialLine ( aP, initTrack ); PNS_WALKAROUND walkaround( m_currentNode, Router() ); @@ -428,10 +402,8 @@ bool PNS_LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, PNS_LINE& aNewHead ) PNS_OPTIMIZER::Optimize( &walkFull, effort, m_currentNode ); - if( m_currentNode->CheckColliding( &walkFull ) ) - { - TRACEn(0, "strange, walk line colliding\n"); - } + if ( m_currentNode->CheckColliding( &walkFull ) ) + return false; m_head = walkFull; aNewHead = walkFull; @@ -442,26 +414,18 @@ bool PNS_LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, PNS_LINE& aNewHead ) bool PNS_LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, PNS_LINE& aNewHead ) { - m_head.SetShape( buildInitialLine( aP ) ); - - if( m_placingVia ) - { - m_head.AppendVia( makeVia ( m_head.CPoint( -1 ) ) ); - } - + buildInitialLine( aP, m_head ); aNewHead = m_head; - return m_currentNode->CheckColliding( &m_head ); } bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) { - SHAPE_LINE_CHAIN line = buildInitialLine( aP ); - PNS_LINE initTrack( m_head, line ); + PNS_LINE initTrack( m_head ); PNS_LINE walkSolids, l2; - handleViaPlacement( initTrack ); + bool viaOk = buildInitialLine( aP, initTrack ); m_currentNode = m_shove->CurrentNode(); PNS_OPTIMIZER optimizer( m_currentNode ); @@ -485,7 +449,7 @@ bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) l.Line().Append( l2.CLine() ); l.Line().Simplify(); - if( m_placingVia ) + if( m_placingVia && viaOk ) { PNS_VIA v1( makeVia ( l.CPoint( -1 ) ) ); PNS_VIA v2( makeVia ( l2.CPoint( -1 ) ) ); @@ -892,7 +856,15 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) const SHAPE_LINE_CHAIN& l = pl.CLine(); if( !l.SegmentCount() ) + { + if( pl.EndsWithVia() ) + { + m_lastNode->Add( pl.Via().Clone() ); + Router()->CommitRouting( m_lastNode ); + m_idle = true; + } return true; + } VECTOR2I p_pre_last = l.CPoint( -1 ); const VECTOR2I p_last = l.CPoint( -1 ); @@ -955,6 +927,9 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest ) if( !aLatest->SegmentCount() ) return; + if (aLatest->CLine().CPoint(0) == aLatest->CLine().CPoint(-1)) + return; + aNode->Add( aLatest, true ); for( int s = 0; s < aLatest->SegmentCount(); s++ ) @@ -1046,22 +1021,56 @@ void PNS_LINE_PLACER::SetOrthoMode( bool aOrthoMode ) Move( m_currentEnd, NULL ); } -const SHAPE_LINE_CHAIN PNS_LINE_PLACER::buildInitialLine( const VECTOR2I& aP ) +bool PNS_LINE_PLACER::buildInitialLine( const VECTOR2I& aP, PNS_LINE& aHead ) { - SHAPE_LINE_CHAIN l( m_direction.BuildInitialTrace( m_p_start, aP ) ); + SHAPE_LINE_CHAIN l; - if( l.SegmentCount() <= 1 ) - return l; - - if( m_orthoMode ) + if(m_p_start == aP) { - VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) ); + l.Clear(); + } else { + l = m_direction.BuildInitialTrace( m_p_start, aP ); - l.Remove( -1, -1 ); - l.Point( 1 ) = newLast; + if( l.SegmentCount() > 1 && m_orthoMode ) + { + VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) ); + + l.Remove( -1, -1 ); + l.Point( 1 ) = newLast; + } } - return l; + aHead.SetShape( l ); + + if( !m_placingVia ) + return true; + + PNS_VIA v ( makeVia ( aP ) ); + v.SetNet ( aHead.Net() ); + + if ( m_currentMode == RM_MarkObstacles ) + { + aHead.AppendVia ( v ); + return true; + } + + VECTOR2I force; + VECTOR2I lead = aP - m_p_start; + + bool solidsOnly = ( m_currentMode != RM_Walkaround ); + + if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) ) + { + SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( + m_p_start, + aP + force ); + aHead = PNS_LINE( aHead, line ); + + v.SetPos( v.Pos() + force ); + return true; + } + + return false; // via placement unsuccessful } diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 2b8743a2cd..285a21338a 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -253,13 +253,6 @@ private: */ void simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest ); - /** - * Function handleViaPlacement() - * - * Attempts to find a spot to place the via at the end of line aHead. - */ - bool handleViaPlacement( PNS_LINE& aHead ); - /** * Function checkObtusity() * @@ -347,7 +340,7 @@ private: const PNS_VIA makeVia ( const VECTOR2I& aP ); - const SHAPE_LINE_CHAIN buildInitialLine( const VECTOR2I& aP ); + bool buildInitialLine( const VECTOR2I& aP, PNS_LINE& aHead ); ///> current routing direction DIRECTION_45 m_direction; diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 762f4bcbf9..c6373b78f5 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -986,7 +986,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead ) m_multiLineMode = false; // empty head? nothing to shove... - if( !aCurrentHead.SegmentCount() ) + if( !aCurrentHead.SegmentCount() && !aCurrentHead.EndsWithVia() ) return SH_INCOMPLETE; PNS_LINE* head = clone( &aCurrentHead ); @@ -1183,6 +1183,9 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveDraggingVia( PNS_VIA* aVia, const VECTOR void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead ) { + if(!aHead->SegmentCount()) + return; + PNS_OPTIMIZER optimizer( aNode ); int optFlags = 0, n_passes = 0; diff --git a/pcbnew/router/pns_walkaround.cpp b/pcbnew/router/pns_walkaround.cpp index b3edf34a9f..2578304259 100644 --- a/pcbnew/router/pns_walkaround.cpp +++ b/pcbnew/router/pns_walkaround.cpp @@ -139,6 +139,16 @@ PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::Route( const PNS_LINE& aInitia WALKAROUND_STATUS s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; SHAPE_LINE_CHAIN best_path; + // special case for via-in-the-middle-of-track placement + if( aInitialPath.PointCount() <= 1 ) + { + if(aInitialPath.EndsWithVia() && m_world->CheckColliding( &aInitialPath.Via(), m_itemMask ) ) + return STUCK; + + aWalkPath = aInitialPath; + return DONE; + } + start( aInitialPath ); m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath );