router: 'root line' tracking in the SHOVE algorithm. See comments for detailed explanation.

This commit is contained in:
Tomasz Wlostowski 2021-04-27 00:27:30 +02:00
parent 3a8744d054
commit a433451bd8
2 changed files with 94 additions and 13 deletions

View File

@ -56,21 +56,70 @@ void SHOVE::replaceItems( ITEM* aOld, std::unique_ptr< ITEM > aNew )
m_currentNode->Replace( aOld, std::move( aNew ) ); m_currentNode->Replace( aOld, std::move( aNew ) );
} }
void SHOVE::replaceLine( LINE& aOld, LINE& aNew ) void SHOVE::replaceLine( LINE& aOld, LINE& aNew, bool aIncludeInChangedArea, NODE* aNode )
{ {
OPT_BOX2I changed_area = ChangedArea( aOld, aNew ); if( aIncludeInChangedArea )
if( changed_area )
{ {
if( Dbg() ) OPT_BOX2I changed_area = ChangedArea( aOld, aNew );
if( changed_area )
{ {
Dbg()->AddBox( *changed_area, 3, "shove-changed-area" ); if( Dbg() )
} {
Dbg()->AddBox( *changed_area, 3, "shove-changed-area" );
}
m_affectedArea = m_affectedArea ? m_affectedArea->Merge( *changed_area ) : *changed_area; m_affectedArea = m_affectedArea ? m_affectedArea->Merge( *changed_area ) : *changed_area;
}
} }
m_currentNode->Replace( aOld, aNew ); bool foundPredecessor = false;
LINE* rootLine = nullptr;
// Keep track of the 'root lines', i.e. the unmodified (pre-shove) versions
// of the affected tracks in a map. The optimizer can then query the pre-shove shape
// for each shoved line and perform additional constraint checks (i.e. prevent overzealous optimizations)
// Check if the shoved line already has an ancestor (e.g. line from a previous shove iteration/cursor movement)
for( auto link : aOld.Links() )
{
auto oldLineIter = m_rootLineHistory.find( link );
if( oldLineIter != m_rootLineHistory.end() )
{
rootLine = oldLineIter->second;
foundPredecessor = true;
break;
}
}
// If found, use it, otherwise, create new entry in the map (we have a genuine new 'root' line)
if( !foundPredecessor )
{
for( auto link : aOld.Links() )
{
if( ! rootLine )
{
rootLine = aOld.Clone();
}
m_rootLineHistory[link] = rootLine;
}
}
// Now update the NODE (calling Replace invalidates the Links() in a LINE)
if( aNode )
{
aNode->Replace( aOld, aNew );
}
else
{
m_currentNode->Replace( aOld, aNew );
}
// point the Links() of the new line to its oldest ancestor
for( auto link : aNew.Links() )
{
m_rootLineHistory[ link ] = rootLine;
}
} }
int SHOVE::getClearance( const ITEM* aA, const ITEM* aB ) const int SHOVE::getClearance( const ITEM* aA, const ITEM* aB ) const
@ -115,6 +164,16 @@ SHOVE::SHOVE( NODE* aWorld, ROUTER* aRouter ) :
SHOVE::~SHOVE() SHOVE::~SHOVE()
{ {
std::unordered_set<LINE*> alreadyDeleted;
for( auto it : m_rootLineHistory )
{
auto it2 = alreadyDeleted.find( it.second );
if( it2 == alreadyDeleted.end() )
{
alreadyDeleted.insert( it.second );
delete it.second;
}
}
} }
@ -1577,6 +1636,23 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( const VIA_HANDLE aOldVia, const VEC
} }
LINE* SHOVE::findRootLine( LINE *aLine )
{
for( auto link : aLine->Links() )
{
if( auto seg = dyn_cast<SEGMENT*>( link ) )
{
auto it = m_rootLineHistory.find( seg );
if( it != m_rootLineHistory.end() )
return it->second;
}
}
return nullptr;
}
void SHOVE::runOptimizer( NODE* aNode ) void SHOVE::runOptimizer( NODE* aNode )
{ {
OPTIMIZER optimizer( aNode ); OPTIMIZER optimizer( aNode );
@ -1620,6 +1696,8 @@ void SHOVE::runOptimizer( NODE* aNode )
break; break;
} }
optFlags |= OPTIMIZER::LIMIT_CORNER_COUNT;
if( area ) if( area )
{ {
if( Dbg() ) if( Dbg() )
@ -1646,12 +1724,12 @@ void SHOVE::runOptimizer( NODE* aNode )
if( !( line.Marker() & MK_HEAD ) ) if( !( line.Marker() & MK_HEAD ) )
{ {
LINE optimized; LINE optimized;
LINE* root = findRootLine( &line );
if( optimizer.Optimize( &line, &optimized ) ) if( optimizer.Optimize( &line, &optimized, root ) )
{ {
aNode->Remove( line ); replaceLine( line, optimized, false, aNode );
line.SetShape( optimized.CLine() ); line = optimized; // keep links in the lines in the queue up to date
aNode->Add( line );
} }
} }
} }

View File

@ -147,7 +147,9 @@ private:
LINE assembleLine( const LINKED_ITEM* aSeg, int* aIndex = NULL ); LINE assembleLine( const LINKED_ITEM* aSeg, int* aIndex = NULL );
void replaceItems( ITEM* aOld, std::unique_ptr< ITEM > aNew ); void replaceItems( ITEM* aOld, std::unique_ptr< ITEM > aNew );
void replaceLine( LINE& aOld, LINE& aNew ); void replaceLine( LINE& aOld, LINE& aNew, bool aIncludeInChangedArea = true, NODE *aNode = nullptr );
LINE* findRootLine( LINE *aLine );
OPT_BOX2I m_affectedArea; OPT_BOX2I m_affectedArea;
@ -160,6 +162,7 @@ private:
std::vector<SPRINGBACK_TAG> m_nodeStack; std::vector<SPRINGBACK_TAG> m_nodeStack;
std::vector<LINE> m_lineStack; std::vector<LINE> m_lineStack;
std::vector<LINE> m_optimizerQueue; std::vector<LINE> m_optimizerQueue;
std::unordered_map<const LINKED_ITEM*, LINE*> m_rootLineHistory;
NODE* m_root; NODE* m_root;
NODE* m_currentNode; NODE* m_currentNode;