router: make post-drag optimization less intrusive

Fixes: #5918
This commit is contained in:
Tomasz Wlostowski 2020-10-18 22:59:16 +02:00
parent 14ce7a0ad7
commit 0306d16748
5 changed files with 93 additions and 88 deletions

View File

@ -291,9 +291,20 @@ void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
{ {
return; return;
} }
for( ITEM* item : fanout.Items() ) for( ITEM* item : fanout.Items() )
{ {
if ( VIA *via = dyn_cast<VIA*>( item ) )
{
auto draggedVia = Clone( *via );
draggedVia->SetPos( aP );
m_draggedItems.Add( draggedVia.get() );
}
/*
if( const LINE* l = dyn_cast<const LINE*>( item ) ) if( const LINE* l = dyn_cast<const LINE*>( item ) )
{ {
LINE origLine( *l ); LINE origLine( *l );
@ -307,27 +318,18 @@ void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
m_lastNode->Remove( origLine ); m_lastNode->Remove( origLine );
m_lastNode->Add( draggedLine ); m_lastNode->Add( draggedLine );
} }
else if ( VIA *via = dyn_cast<VIA*>( item ) ) else */
{
auto nvia = Clone( *via );
nvia->SetPos( aP );
m_draggedItems.Add( nvia.get() );
m_lastNode->Remove( via );
m_lastNode->Add( std::move( nvia ) );
}
} }
} }
void DRAGGER::optimizeAndUpdateDraggedLine( LINE& dragged, SEG& aDraggedSeg, const VECTOR2I& aP ) void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, SEG& aDraggedSeg, const VECTOR2I& aP )
{ {
VECTOR2D lockV; VECTOR2D lockV;
dragged.ClearLinks(); aDragged.ClearLinks();
dragged.Unmark(); aDragged.Unmark();
lockV = dragged.CLine().NearestPoint( aP ); lockV = aDragged.CLine().NearestPoint( aP );
if( Settings().GetOptimizeDraggedTrack() ) if( Settings().GetOptimizeDraggedTrack() )
{ {
@ -335,25 +337,29 @@ void DRAGGER::optimizeAndUpdateDraggedLine( LINE& dragged, SEG& aDraggedSeg, con
optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS | OPTIMIZER::KEEP_TOPOLOGY ); optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS | OPTIMIZER::KEEP_TOPOLOGY );
int startV = dragged.CLine().Find( aDraggedSeg.A ); OPT_BOX2I affectedArea = *aDragged.ChangedArea( &aOrig );
int endV = dragged.CLine().Find( aDraggedSeg.B );
if ( endV > startV ) optimizer.SetPreserveVertex( aP );
{
std::swap(endV, startV);
}
if( startV >= 0 && endV >= 0) if( affectedArea )
{ {
optimizer.SetPreserveVertex( aP ); //Dbg()->AddBox( *affectedArea, 2 );
optimizer.SetRestrictVertexRange( startV, endV ); optimizer.SetRestrictArea( *affectedArea );
optimizer.Optimize( &dragged ); optimizer.Optimize( &aDragged );
OPT_BOX2I optArea = *aDragged.ChangedArea( &aOrig );
if( optArea )
Dbg()->AddBox( *optArea, 4 );
} }
} }
m_lastNode->Add( dragged ); m_lastNode->Add( aDragged );
m_draggedItems.Clear(); m_draggedItems.Clear();
m_draggedItems.Add( dragged ); m_draggedItems.Add( aDragged );
} }
@ -419,15 +425,14 @@ bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
ok = true; ok = true;
} }
if( ok ) if(ok)
{ {
m_lastNode->Remove( origLine ); m_lastNode->Remove( origLine );
SEG dummy; SEG dummy;
optimizeAndUpdateDraggedLine( dragged, dummy, aP ); optimizeAndUpdateDraggedLine( dragged, origLine, dummy, aP );
} }
break;
} }
break;
case DM_VIA: // fixme... case DM_VIA: // fixme...
{ {
dragViaWalkaround( m_initialVia, m_lastNode, aP ); dragViaWalkaround( m_initialVia, m_lastNode, aP );
@ -568,20 +573,20 @@ bool DRAGGER::Drag( const VECTOR2I& aP )
switch( m_currentMode ) switch( m_currentMode )
{ {
case RM_MarkObstacles: case RM_MarkObstacles:
ret = dragMarkObstacles( aP ); ret = dragMarkObstacles( aP );
break; break;
case RM_Shove: case RM_Shove:
case RM_Smart: case RM_Smart:
ret = dragShove( aP ); ret = dragShove( aP );
break; break;
case RM_Walkaround: case RM_Walkaround:
ret = dragWalkaround( aP ); ret = dragWalkaround( aP );
break; break;
default: default:
break; break;
} }
} }
@ -594,7 +599,7 @@ bool DRAGGER::Drag( const VECTOR2I& aP )
NODE* DRAGGER::CurrentNode() const NODE* DRAGGER::CurrentNode() const
{ {
return m_lastNode; return m_lastNode ? m_lastNode : m_world;
} }

View File

@ -123,7 +123,7 @@ private:
bool startDragVia( VIA* aVia ); bool startDragVia( VIA* aVia );
void dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP ); void dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
void dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP ); void dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
void optimizeAndUpdateDraggedLine( LINE& dragged, SEG& aDraggedSeg, const VECTOR2I& aP ); void optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, SEG& aDraggedSeg, const VECTOR2I& aP );
private: private:
VIA_HANDLE m_initialVia; VIA_HANDLE m_initialVia;

View File

@ -674,18 +674,18 @@ public:
m_view->Add( m_items ); m_view->Add( m_items );
} }
void AddPoint( VECTOR2I aP, int aColor, const std::string aName = "" ) override virtual void AddPoint( VECTOR2I aP, int aColor, int aSize, const std::string aName ) override
{ {
SHAPE_LINE_CHAIN l; SHAPE_LINE_CHAIN l;
l.Append( aP - VECTOR2I( -50000, -50000 ) ); l.Append( aP - VECTOR2I( -aSize, -aSize ) );
l.Append( aP + VECTOR2I( -50000, -50000 ) ); l.Append( aP + VECTOR2I( -aSize, -aSize ) );
AddLine( l, aColor, 10000 ); AddLine( l, aColor, 10000 );
l.Clear(); l.Clear();
l.Append( aP - VECTOR2I( 50000, -50000 ) ); l.Append( aP - VECTOR2I( aSize, -aSize ) );
l.Append( aP + VECTOR2I( 50000, -50000 ) ); l.Append( aP + VECTOR2I( aSize, -aSize ) );
AddLine( l, aColor, 10000 ); AddLine( l, aColor, 10000 );
} }

View File

@ -102,7 +102,7 @@ void COST_ESTIMATOR::Replace( const LINE& aOldLine, const LINE& aNewLine )
bool COST_ESTIMATOR::IsBetter( const COST_ESTIMATOR& aOther, double aLengthTolerance, bool COST_ESTIMATOR::IsBetter( const COST_ESTIMATOR& aOther, double aLengthTolerance,
double aCornerTolerance ) const double aCornerTolerance ) const
{ {
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost ) if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
return true; return true;
@ -195,7 +195,7 @@ void OPTIMIZER::CacheRemove( ITEM* aItem )
} }
void OPTIMIZER::ClearCache( bool aStaticOnly ) void OPTIMIZER::ClearCache( bool aStaticOnly )
{ {
if( !aStaticOnly ) if( !aStaticOnly )
{ {
@ -226,7 +226,7 @@ bool AREA_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine
bool p2_in = m_allowedArea.Contains( p2 ); bool p2_in = m_allowedArea.Contains( p2 );
return p1_in || p2_in; return p1_in || p2_in;
} }
bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
@ -255,7 +255,7 @@ bool PRESERVE_VERTEX_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE*
if ( dist <= 1 ) if ( dist <= 1 )
{ {
return true; return true;
} }
} }
return false; return false;
@ -297,7 +297,7 @@ static bool pointInside2( const SHAPE_LINE_CHAIN& aL, const VECTOR2I& aP )
{ {
if( (ipNext.x ==aP.x) || ( ip.y == aP.y && ( (ipNext.x >aP.x) == (ip.x <aP.x) ) ) ) if( (ipNext.x ==aP.x) || ( ip.y == aP.y && ( (ipNext.x >aP.x) == (ip.x <aP.x) ) ) )
return true; // pt on polyground boundary return true; // pt on polyground boundary
} }
if( (ip.y <aP.y) != (ipNext.y <aP.y) ) if( (ip.y <aP.y) != (ipNext.y <aP.y) )
{ {
@ -345,7 +345,7 @@ static bool pointInside2( const SHAPE_LINE_CHAIN& aL, const VECTOR2I& aP )
bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine, bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aOriginLine,
const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement ) const SHAPE_LINE_CHAIN& aReplacement )
{ {
SHAPE_LINE_CHAIN encPoly = aOriginLine->CLine().Slice( aVertex1, aVertex2 ); SHAPE_LINE_CHAIN encPoly = aOriginLine->CLine().Slice( aVertex1, aVertex2 );
// fixme: this is a remarkably shitty implementation... // fixme: this is a remarkably shitty implementation...
@ -361,20 +361,20 @@ bool KEEP_TOPOLOGY_CONSTRAINT::Check( int aVertex1, int aVertex2, const LINE* aO
return true; return true;
for( JOINT* j : joints ) for( JOINT* j : joints )
{ {
if( j->Net() == aOriginLine->Net() ) if ( j->Net() == aOriginLine->Net() )
continue; continue;
if( pointInside2( encPoly, j->Pos() ) ) if ( pointInside2( encPoly, j->Pos() ) )
{
bool falsePositive = false;
for( int k = 0; k < encPoly.PointCount(); k++ )
{ {
if( encPoly.CPoint(k) == j->Pos() ) bool falsePositive = false;
for( int k = 0; k < encPoly.PointCount(); k++)
{
if(encPoly.CPoint(k) == j->Pos() )
{ {
falsePositive = true; falsePositive = true;
break; break;
} }
} }
if( !falsePositive ) if( !falsePositive )
@ -407,8 +407,8 @@ void OPTIMIZER::ClearConstraints()
void OPTIMIZER::AddConstraint ( OPT_CONSTRAINT *aConstraint ) void OPTIMIZER::AddConstraint ( OPT_CONSTRAINT *aConstraint )
{ {
m_constraints.push_back( aConstraint ); m_constraints.push_back(aConstraint);
} }
@ -418,7 +418,7 @@ bool OPTIMIZER::checkConstraints( int aVertex1, int aVertex2, LINE* aOriginLine,
{ {
for( OPT_CONSTRAINT* c : m_constraints ) for( OPT_CONSTRAINT* c : m_constraints )
{ {
if( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) ) if ( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) )
return false; return false;
} }
@ -588,13 +588,13 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
bool hasArcs = aLine->ArcCount(); bool hasArcs = aLine->ArcCount();
bool rv = false; bool rv = false;
if( m_effortLevel & PRESERVE_VERTEX ) if ( m_effortLevel & PRESERVE_VERTEX )
{ {
auto c = new PRESERVE_VERTEX_CONSTRAINT( m_world, m_preservedVertex ); auto c = new PRESERVE_VERTEX_CONSTRAINT( m_world, m_preservedVertex );
AddConstraint( c ); AddConstraint( c );
} }
if( m_effortLevel & RESTRICT_VERTEX_RANGE ) if ( m_effortLevel & RESTRICT_VERTEX_RANGE )
{ {
auto c = new RESTRICT_VERTEX_RANGE_CONSTRAINT( m_world, m_restrictedVertexRange.first, auto c = new RESTRICT_VERTEX_RANGE_CONSTRAINT( m_world, m_restrictedVertexRange.first,
m_restrictedVertexRange.second ); m_restrictedVertexRange.second );
@ -608,7 +608,7 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
} }
if( m_effortLevel & KEEP_TOPOLOGY ) if ( m_effortLevel & KEEP_TOPOLOGY )
{ {
auto c = new KEEP_TOPOLOGY_CONSTRAINT( m_world ); auto c = new KEEP_TOPOLOGY_CONSTRAINT( m_world );
AddConstraint( c ); AddConstraint( c );
@ -670,7 +670,7 @@ bool OPTIMIZER::mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, int step
bool ok = false; bool ok = false;
if( !checkColliding( aLine, bypass ) ) if ( !checkColliding( aLine, bypass ) )
{ {
ok = checkConstraints ( n, n + step + 1, aLine, aCurrentPath, bypass ); ok = checkConstraints ( n, n + step + 1, aLine, aCurrentPath, bypass );
} }
@ -709,9 +709,9 @@ OPTIMIZER::BREAKOUT_LIST OPTIMIZER::circleBreakouts( int aWidth, const SHAPE* aS
for( int angle = 0; angle < 360; angle += 45 ) for( int angle = 0; angle < 360; angle += 45 )
{ {
const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>( aShape ); const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>( aShape );
SHAPE_LINE_CHAIN l; SHAPE_LINE_CHAIN l;
VECTOR2I p0 = cir->GetCenter(); VECTOR2I p0 = cir->GetCenter();
VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 ); VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 );
l.Append( p0 ); l.Append( p0 );
l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) ); l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) );
@ -929,7 +929,7 @@ int OPTIMIZER::smartPadsSingle( LINE* aLine, ITEM* aPad, bool aEnd, int aEndVert
DIRECTION_45 dir_bkout( breakout.CSegment( -1 ) ); DIRECTION_45 dir_bkout( breakout.CSegment( -1 ) );
if( !connect.SegmentCount() ) if(!connect.SegmentCount())
continue; continue;
int ang1 = dir_bkout.Angle( DIRECTION_45( connect.CSegment( 0 ) ) ); int ang1 = dir_bkout.Angle( DIRECTION_45( connect.CSegment( 0 ) ) );
@ -1100,12 +1100,12 @@ int findCoupledVertices( const VECTOR2I& aVertex, const SEG& aOrigSeg,
{ {
int count = 0; int count = 0;
for( int i = 0; i < aCoupled.SegmentCount(); i++ ) for ( int i = 0; i < aCoupled.SegmentCount(); i++ )
{ {
SEG s = aCoupled.CSegment( i ); SEG s = aCoupled.CSegment( i );
VECTOR2I projOverCoupled = s.LineProject ( aVertex ); VECTOR2I projOverCoupled = s.LineProject ( aVertex );
if( s.ApproxParallel( aOrigSeg ) ) if( s.ApproxParallel ( aOrigSeg ) )
{ {
int64_t dist = int64_t{(( projOverCoupled - aVertex ).EuclideanNorm())} - aPair->Width(); int64_t dist = int64_t{(( projOverCoupled - aVertex ).EuclideanNorm())} - aPair->Width();
@ -1144,15 +1144,15 @@ bool coupledBypass( NODE* aNode, DIFF_PAIR* aPair, bool aRefIsP, const SHAPE_LIN
const SHAPE_LINE_CHAIN& aRefBypass, const SHAPE_LINE_CHAIN& aCoupled, const SHAPE_LINE_CHAIN& aRefBypass, const SHAPE_LINE_CHAIN& aCoupled,
SHAPE_LINE_CHAIN& aNewCoupled ) SHAPE_LINE_CHAIN& aNewCoupled )
{ {
int vStartIdx[1024]; // fixme: possible overflow int vStartIdx[1024]; // fixme: possible overflow
int nStarts = findCoupledVertices( aRefBypass.CPoint( 0 ), aRefBypass.CSegment( 0 ), int nStarts = findCoupledVertices( aRefBypass.CPoint( 0 ), aRefBypass.CSegment( 0 ),
aCoupled, aPair, vStartIdx ); aCoupled, aPair, vStartIdx );
DIRECTION_45 dir( aRefBypass.CSegment( 0 ) ); DIRECTION_45 dir( aRefBypass.CSegment( 0 ) );
int64_t bestLength = -1; int64_t bestLength = -1;
bool found = false; bool found = false;
SHAPE_LINE_CHAIN bestBypass; SHAPE_LINE_CHAIN bestBypass;
int si, ei; int si, ei;
for( int i=0; i< nStarts; i++ ) for( int i=0; i< nStarts; i++ )
{ {
@ -1237,7 +1237,7 @@ bool OPTIMIZER::mergeDpStep( DIFF_PAIR* aPair, bool aTryP, int step )
deltaUni = aPair->CoupledLength ( newRef, coupledPath ) - clenPre + budget; deltaUni = aPair->CoupledLength ( newRef, coupledPath ) - clenPre + budget;
if( coupledBypass( m_world, aPair, aTryP, newRef, bypass, coupledPath, newCoup ) ) if ( coupledBypass( m_world, aPair, aTryP, newRef, bypass, coupledPath, newCoup ) )
{ {
deltaCoupled = aPair->CoupledLength( newRef, newCoup ) - clenPre + budget; deltaCoupled = aPair->CoupledLength( newRef, newCoup ) - clenPre + budget;
@ -1250,7 +1250,7 @@ bool OPTIMIZER::mergeDpStep( DIFF_PAIR* aPair, bool aTryP, int step )
return true; return true;
} }
} }
else if( deltaUni >= 0 && verifyDpBypass( m_world, aPair, aTryP, newRef, coupledPath ) ) else if( deltaUni >= 0 && verifyDpBypass ( m_world, aPair, aTryP, newRef, coupledPath ) )
{ {
newRef.Simplify(); newRef.Simplify();
coupledPath.Simplify(); coupledPath.Simplify();
@ -1386,7 +1386,7 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, const SHAPE_LINE_CH
int da = a.Length(); int da = a.Length();
int db = b.Length(); int db = b.Length();
if( da < db ) if ( da < db )
guide = a; guide = a;
else else
guide = b; guide = b;
@ -1398,9 +1398,9 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, const SHAPE_LINE_CH
int current = step; int current = step;
SHAPE_LINE_CHAIN snew; SHAPE_LINE_CHAIN snew;
while( step > 1 ) while (step > 1)
{ {
LINE l( cur ); LINE l ( cur );
snew.Clear(); snew.Clear();
snew.Append( a.A ); snew.Append( a.A );
@ -1441,27 +1441,27 @@ void Tighten( NODE *aNode, const SHAPE_LINE_CHAIN& aOldLine, const LINE& aNewLin
{ {
LINE tmp; LINE tmp;
if( aNewLine.SegmentCount() < 3 ) if ( aNewLine.SegmentCount() < 3 )
return; return;
SHAPE_LINE_CHAIN current ( aNewLine.CLine() ); SHAPE_LINE_CHAIN current ( aNewLine.CLine() );
for( int step = 0; step < 3; step++) for (int step = 0; step < 3; step++)
{ {
current.Simplify(); current.Simplify();
for( int i = 0; i <= current.SegmentCount() - 3; i++) for ( int i = 0; i <= current.SegmentCount() - 3; i++)
{ {
SHAPE_LINE_CHAIN l_in, l_out; SHAPE_LINE_CHAIN l_in, l_out;
l_in = current.Slice(i, i+3); l_in = current.Slice(i, i+3);
for( int dir = 0; dir < 1; dir++) for (int dir = 0; dir < 1; dir++)
{ {
if( tightenSegment( dir ? true : false, aNode, aNewLine, l_in, l_out ) ) if( tightenSegment( dir ? true : false, aNode, aNewLine, l_in, l_out ) )
{ {
SHAPE_LINE_CHAIN opt = current; SHAPE_LINE_CHAIN opt = current;
opt.Replace(i, i + 3, l_out); opt.Replace(i, i+3, l_out);
auto optArea = std::abs(shovedArea( aOldLine, opt )); auto optArea = std::abs(shovedArea( aOldLine, opt ));
auto prevArea = std::abs(shovedArea( aOldLine, current )); auto prevArea = std::abs(shovedArea( aOldLine, current ));

View File

@ -249,7 +249,7 @@ public:
virtual ~ANGLE_CONSTRAINT_45() {}; virtual ~ANGLE_CONSTRAINT_45() {};
virtual bool Check ( int aVertex1, int aVertex2, LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override; virtual bool Check ( int aVertex1, int aVertex2, const LINE* aOriginLine, const SHAPE_LINE_CHAIN& aCurrentPath, const SHAPE_LINE_CHAIN& aReplacement ) override;
private: private:
int m_entryDirectionMask; int m_entryDirectionMask;