router: allow for insertion of a via without leading trace (e.g. in the middle of already existing trace)

This commit is contained in:
Tomasz Wlostowski 2015-07-02 16:09:24 +02:00 committed by Maciej Suminski
parent a3edd9706f
commit f96c65254c
5 changed files with 82 additions and 70 deletions

View File

@ -707,10 +707,7 @@ void PNS_LINE::Reverse()
void PNS_LINE::AppendVia( const PNS_VIA& aVia ) void PNS_LINE::AppendVia( const PNS_VIA& aVia )
{ {
if( m_line.PointCount() == 0 ) if( m_line.PointCount() > 1 && aVia.Pos() == m_line.CPoint( 0 ) )
return;
if( aVia.Pos() == m_line.CPoint( 0 ) )
{ {
Reverse(); Reverse();
} }

View File

@ -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 ) bool PNS_LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, PNS_LINE& aNewHead )
{ {
SHAPE_LINE_CHAIN line = buildInitialLine( aP ); PNS_LINE initTrack( m_head );
PNS_LINE initTrack( m_head, line ), walkFull; PNS_LINE walkFull;
int effort = 0; int effort = 0;
bool viaOk = handleViaPlacement( initTrack ); bool rv = true, viaOk;
bool rv = true;
viaOk = buildInitialLine ( aP, initTrack );
PNS_WALKAROUND walkaround( m_currentNode, Router() ); 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 ); PNS_OPTIMIZER::Optimize( &walkFull, effort, m_currentNode );
if( m_currentNode->CheckColliding( &walkFull ) ) if ( m_currentNode->CheckColliding( &walkFull ) )
{ return false;
TRACEn(0, "strange, walk line colliding\n");
}
m_head = walkFull; m_head = walkFull;
aNewHead = 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 ) bool PNS_LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, PNS_LINE& aNewHead )
{ {
m_head.SetShape( buildInitialLine( aP ) ); buildInitialLine( aP, m_head );
if( m_placingVia )
{
m_head.AppendVia( makeVia ( m_head.CPoint( -1 ) ) );
}
aNewHead = m_head; aNewHead = m_head;
return m_currentNode->CheckColliding( &m_head ); return m_currentNode->CheckColliding( &m_head );
} }
bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead ) bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
{ {
SHAPE_LINE_CHAIN line = buildInitialLine( aP ); PNS_LINE initTrack( m_head );
PNS_LINE initTrack( m_head, line );
PNS_LINE walkSolids, l2; PNS_LINE walkSolids, l2;
handleViaPlacement( initTrack ); bool viaOk = buildInitialLine( aP, initTrack );
m_currentNode = m_shove->CurrentNode(); m_currentNode = m_shove->CurrentNode();
PNS_OPTIMIZER optimizer( m_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().Append( l2.CLine() );
l.Line().Simplify(); l.Line().Simplify();
if( m_placingVia ) if( m_placingVia && viaOk )
{ {
PNS_VIA v1( makeVia ( l.CPoint( -1 ) ) ); PNS_VIA v1( makeVia ( l.CPoint( -1 ) ) );
PNS_VIA v2( makeVia ( l2.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(); const SHAPE_LINE_CHAIN& l = pl.CLine();
if( !l.SegmentCount() ) if( !l.SegmentCount() )
{
if( pl.EndsWithVia() )
{
m_lastNode->Add( pl.Via().Clone() );
Router()->CommitRouting( m_lastNode );
m_idle = true;
}
return true; return true;
}
VECTOR2I p_pre_last = l.CPoint( -1 ); VECTOR2I p_pre_last = l.CPoint( -1 );
const VECTOR2I p_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() ) if( !aLatest->SegmentCount() )
return; return;
if (aLatest->CLine().CPoint(0) == aLatest->CLine().CPoint(-1))
return;
aNode->Add( aLatest, true ); aNode->Add( aLatest, true );
for( int s = 0; s < aLatest->SegmentCount(); s++ ) for( int s = 0; s < aLatest->SegmentCount(); s++ )
@ -1046,22 +1021,56 @@ void PNS_LINE_PLACER::SetOrthoMode( bool aOrthoMode )
Move( m_currentEnd, NULL ); 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 ) if(m_p_start == aP)
return l;
if( m_orthoMode )
{ {
VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) ); l.Clear();
} else {
l = m_direction.BuildInitialTrace( m_p_start, aP );
l.Remove( -1, -1 ); if( l.SegmentCount() > 1 && m_orthoMode )
l.Point( 1 ) = newLast; {
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
} }

View File

@ -253,13 +253,6 @@ private:
*/ */
void simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest ); 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() * Function checkObtusity()
* *
@ -347,7 +340,7 @@ private:
const PNS_VIA makeVia ( const VECTOR2I& aP ); 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 ///> current routing direction
DIRECTION_45 m_direction; DIRECTION_45 m_direction;

View File

@ -986,7 +986,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
m_multiLineMode = false; m_multiLineMode = false;
// empty head? nothing to shove... // empty head? nothing to shove...
if( !aCurrentHead.SegmentCount() ) if( !aCurrentHead.SegmentCount() && !aCurrentHead.EndsWithVia() )
return SH_INCOMPLETE; return SH_INCOMPLETE;
PNS_LINE* head = clone( &aCurrentHead ); 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 ) void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead )
{ {
if(!aHead->SegmentCount())
return;
PNS_OPTIMIZER optimizer( aNode ); PNS_OPTIMIZER optimizer( aNode );
int optFlags = 0, n_passes = 0; int optFlags = 0, n_passes = 0;

View File

@ -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; WALKAROUND_STATUS s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
SHAPE_LINE_CHAIN best_path; 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 ); start( aInitialPath );
m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath ); m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath );