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

View File

@ -674,18 +674,18 @@ public:
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;
l.Append( aP - VECTOR2I( -50000, -50000 ) );
l.Append( aP + VECTOR2I( -50000, -50000 ) );
l.Append( aP - VECTOR2I( -aSize, -aSize ) );
l.Append( aP + VECTOR2I( -aSize, -aSize ) );
AddLine( l, aColor, 10000 );
l.Clear();
l.Append( aP - VECTOR2I( 50000, -50000 ) );
l.Append( aP + VECTOR2I( 50000, -50000 ) );
l.Append( aP - VECTOR2I( aSize, -aSize ) );
l.Append( aP + VECTOR2I( aSize, -aSize ) );
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,
double aCornerTolerance ) const
double aCornerTolerance ) const
{
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
return true;
@ -195,7 +195,7 @@ void OPTIMIZER::CacheRemove( ITEM* aItem )
}
void OPTIMIZER::ClearCache( bool aStaticOnly )
void OPTIMIZER::ClearCache( bool 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 );
return p1_in || p2_in;
}
}
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 )
{
return true;
}
}
}
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) ) ) )
return true; // pt on polyground boundary
}
}
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,
const SHAPE_LINE_CHAIN& aCurrentPath,
const SHAPE_LINE_CHAIN& aReplacement )
{
{
SHAPE_LINE_CHAIN encPoly = aOriginLine->CLine().Slice( aVertex1, aVertex2 );
// 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;
for( JOINT* j : joints )
{
if( j->Net() == aOriginLine->Net() )
{
if ( j->Net() == aOriginLine->Net() )
continue;
if( pointInside2( encPoly, j->Pos() ) )
{
bool falsePositive = false;
for( int k = 0; k < encPoly.PointCount(); k++ )
if ( pointInside2( encPoly, j->Pos() ) )
{
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;
break;
}
}
}
if( !falsePositive )
@ -407,8 +407,8 @@ void OPTIMIZER::ClearConstraints()
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 )
{
if( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) )
if ( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) )
return false;
}
@ -588,13 +588,13 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
bool hasArcs = aLine->ArcCount();
bool rv = false;
if( m_effortLevel & PRESERVE_VERTEX )
if ( m_effortLevel & PRESERVE_VERTEX )
{
auto c = new PRESERVE_VERTEX_CONSTRAINT( m_world, m_preservedVertex );
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,
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 );
AddConstraint( c );
@ -670,7 +670,7 @@ bool OPTIMIZER::mergeStep( LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath, int step
bool ok = false;
if( !checkColliding( aLine, bypass ) )
if ( !checkColliding( aLine, 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 )
{
const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>( aShape );
SHAPE_LINE_CHAIN l;
VECTOR2I p0 = cir->GetCenter();
VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 );
SHAPE_LINE_CHAIN l;
VECTOR2I p0 = cir->GetCenter();
VECTOR2I v0( cir->GetRadius() * M_SQRT2, 0 );
l.Append( p0 );
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 ) );
if( !connect.SegmentCount() )
if(!connect.SegmentCount())
continue;
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;
for( int i = 0; i < aCoupled.SegmentCount(); i++ )
for ( int i = 0; i < aCoupled.SegmentCount(); i++ )
{
SEG s = aCoupled.CSegment( i );
VECTOR2I projOverCoupled = s.LineProject ( aVertex );
if( s.ApproxParallel( aOrigSeg ) )
if( s.ApproxParallel ( aOrigSeg ) )
{
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,
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 ),
aCoupled, aPair, vStartIdx );
DIRECTION_45 dir( aRefBypass.CSegment( 0 ) );
DIRECTION_45 dir( aRefBypass.CSegment( 0 ) );
int64_t bestLength = -1;
bool found = false;
int64_t bestLength = -1;
bool found = false;
SHAPE_LINE_CHAIN bestBypass;
int si, ei;
int si, ei;
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;
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;
@ -1250,7 +1250,7 @@ bool OPTIMIZER::mergeDpStep( DIFF_PAIR* aPair, bool aTryP, int step )
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();
coupledPath.Simplify();
@ -1386,7 +1386,7 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, const SHAPE_LINE_CH
int da = a.Length();
int db = b.Length();
if( da < db )
if ( da < db )
guide = a;
else
guide = b;
@ -1398,9 +1398,9 @@ bool tightenSegment( bool dir, NODE *aNode, const LINE& cur, const SHAPE_LINE_CH
int current = step;
SHAPE_LINE_CHAIN snew;
while( step > 1 )
while (step > 1)
{
LINE l( cur );
LINE l ( cur );
snew.Clear();
snew.Append( a.A );
@ -1441,27 +1441,27 @@ void Tighten( NODE *aNode, const SHAPE_LINE_CHAIN& aOldLine, const LINE& aNewLin
{
LINE tmp;
if( aNewLine.SegmentCount() < 3 )
if ( aNewLine.SegmentCount() < 3 )
return;
SHAPE_LINE_CHAIN current ( aNewLine.CLine() );
for( int step = 0; step < 3; step++)
for (int step = 0; step < 3; step++)
{
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;
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;
opt.Replace(i, i + 3, l_out);
opt.Replace(i, i+3, l_out);
auto optArea = std::abs(shovedArea( aOldLine, opt ));
auto prevArea = std::abs(shovedArea( aOldLine, current ));

View File

@ -249,7 +249,7 @@ public:
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:
int m_entryDirectionMask;