P&S: memory mgr & disappearing trace fixes. Still a bit buggy, though...

This commit is contained in:
Maciej Suminski 2015-08-03 21:11:51 +02:00
parent 07f5516e59
commit 0fbf31ef38
20 changed files with 594 additions and 435 deletions

View File

@ -212,7 +212,7 @@ bool PNS_DIFF_PAIR_PLACER::attemptWalk ( PNS_NODE* aNode, PNS_DIFF_PAIR* aCurren
PNS_SHOVE::SHOVE_STATUS sh1;
sh1 = shove.ProcessSingleLine( &postWalk, &preShove, &postShove );
sh1 = shove.ProcessSingleLine( postWalk, preShove, postShove );
if( sh1 != PNS_SHOVE::SH_OK )
return false;

View File

@ -30,7 +30,6 @@ PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) :
m_world = NULL;
m_lastNode = NULL;
m_mode = SEGMENT;
m_draggedLine = NULL;
m_draggedVia = NULL;
m_shove = NULL;
m_draggedSegmentIndex = 0;
@ -59,7 +58,7 @@ bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT* aSeg )
m_draggedLine = m_world->AssembleLine( aSeg, &m_draggedSegmentIndex );
m_shove->SetInitialLine( m_draggedLine );
m_lastValidDraggedLine = *m_draggedLine;
m_lastValidDraggedLine = m_draggedLine;
m_lastValidDraggedLine.ClearSegmentLinks();
if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 )
@ -90,12 +89,12 @@ bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA* aVia )
{
int segIndex;
PNS_SEGMENT* seg = ( PNS_SEGMENT*) item;
std::auto_ptr<PNS_LINE> l( m_world->AssembleLine( seg, &segIndex ) );
PNS_LINE l = m_world->AssembleLine( seg, &segIndex );
if( segIndex != 0 )
l->Reverse();
l.Reverse();
m_origViaConnections.push_back( *l );
m_origViaConnections.Add( l );
}
}
@ -139,8 +138,8 @@ bool PNS_DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
case SEGMENT:
case CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
PNS_LINE tmp( *m_draggedLine );
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
PNS_LINE tmp( m_draggedLine );
if( m_mode == SEGMENT )
tmp.DragSegment( aP, m_draggedSegmentIndex, thresh );
@ -188,18 +187,21 @@ void PNS_DRAGGER::dumbDragVia( PNS_VIA* aVia, PNS_NODE* aNode, const VECTOR2I& a
m_lastNode->Remove( aVia );
m_lastNode->Add( m_draggedVia );
BOOST_FOREACH( PNS_LINE &l, m_origViaConnections )
BOOST_FOREACH( PNS_ITEM* item, m_origViaConnections.Items() )
{
PNS_LINE origLine( l );
PNS_LINE* draggedLine = l.Clone();
if ( const PNS_LINE* l = dyn_cast<const PNS_LINE*>( item ) )
{
PNS_LINE origLine( *l );
PNS_LINE draggedLine( *l );
draggedLine->DragCorner( aP, 0 );
draggedLine->ClearSegmentLinks();
draggedLine.DragCorner( aP, 0 );
draggedLine.ClearSegmentLinks();
m_draggedItems.Add( draggedLine ); // FIXME: mem leak
m_draggedItems.Add( draggedLine );
m_lastNode->Remove( &origLine );
m_lastNode->Add( draggedLine );
m_lastNode->Add( &draggedLine );
}
}
}
@ -219,8 +221,8 @@ bool PNS_DRAGGER::dragShove( const VECTOR2I& aP )
case SEGMENT:
case CORNER:
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
PNS_LINE tmp( *m_draggedLine );
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
PNS_LINE tmp( m_draggedLine );
if( m_mode == SEGMENT )
tmp.DragSegment( aP, m_draggedSegmentIndex, thresh );

View File

@ -114,15 +114,15 @@ private:
PNS_NODE* m_world;
PNS_NODE* m_lastNode;
DragMode m_mode;
PNS_LINE* m_draggedLine;
PNS_LINE m_draggedLine;
PNS_VIA* m_draggedVia;
PNS_LINE m_lastValidDraggedLine;
PNS_SHOVE* m_shove;
int m_draggedSegmentIndex;
bool m_dragStatus;
PNS_MODE m_currentMode;
std::vector<PNS_LINE> m_origViaConnections;
std::vector<PNS_LINE> m_draggedViaConnections;
PNS_ITEMSET m_origViaConnections;
PNS_ITEMSET m_draggedViaConnections;
PNS_VIA* m_initialVia;
PNS_ITEMSET m_draggedItems;
};

View File

@ -40,13 +40,60 @@ enum LineMarker {
MK_DP_COUPLED = ( 1 << 5 )
};
/**
* Class PNS_OBJECT
*
* Abstract base class to hold ownership information about items/nodes
* used by the router.
*/
class PNS_OBJECT
{
public:
PNS_OBJECT ():
m_owner(NULL) {};
~PNS_OBJECT() {};
/**
* Functon SetOwner()
*
* Sets the node that owns this item. An item can belong to a single
* PNS_OBJECT or stay unowned.
*/
void SetOwner( PNS_OBJECT* aOwner )
{
m_owner = aOwner;
}
/**
* Function BelongsTo()
*
* @return true if the item is owned by aObj
*/
bool BelongsTo( const PNS_OBJECT* aObj ) const
{
return m_owner == aObj;
}
/**
* Function Owner()
*
* Returns the owner of this item, or NULL if there's none.
*/
PNS_OBJECT* Owner() const { return m_owner; }
protected:
PNS_OBJECT *m_owner;
};
/**
* Class PNS_ITEM
*
* Base class for PNS router board items. Implements the shared properties of all PCB items -
* net, spanned layers, geometric shape & refererence to owning model.
*/
class PNS_ITEM
class PNS_ITEM : public PNS_OBJECT
{
public:
static const int UnusedNet = INT_MAX;
@ -226,34 +273,6 @@ public:
return Layers().Overlaps( aOther->Layers() );
}
/**
* Functon SetOwner()
*
* Sets the node that owns this item. An item can belong to a single
* PNS_NODE or stay unowned.
*/
void SetOwner( PNS_NODE* aOwner )
{
m_owner = aOwner;
}
/**
* Function BelongsTo()
*
* @return true if the item is owned by the node aNode.
*/
bool BelongsTo( PNS_NODE* aNode ) const
{
return m_owner == aNode;
}
/**
* Function Owner()
*
* Returns the owner of this item, or NULL if there's none.
*/
PNS_NODE* Owner() const { return m_owner; }
/**
* Function Collide()
*
@ -337,7 +356,6 @@ protected:
PnsKind m_kind;
BOARD_CONNECTED_ITEM* m_parent;
PNS_NODE* m_owner;
PNS_LAYERSET m_layers;
bool m_movable;

View File

@ -21,22 +21,40 @@
#include <boost/foreach.hpp>
#include "pns_itemset.h"
#include "pns_line.h"
PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM* aInitialItem ) :
m_owner( false )
void PNS_ITEMSET::release()
{
if( aInitialItem )
m_items.push_back( aInitialItem );
BOOST_FOREACH( PNS_ITEM* item, m_items )
{
if( item->BelongsTo( this ) )
delete item;
}
m_items.clear();
}
PNS_ITEMSET::~PNS_ITEMSET()
{
if( m_owner )
{
BOOST_FOREACH( PNS_ITEM* item, m_items )
delete item;
release();
}
void PNS_ITEMSET::Add( const PNS_LINE& aLine )
{
PNS_LINE* copy = aLine.Clone();
copy->SetOwner( this );
m_items.push_back( copy );
}
void PNS_ITEMSET::Prepend( const PNS_LINE& aLine )
{
PNS_LINE* copy = aLine.Clone();
copy->SetOwner( this );
m_items.push_front( copy );
}

View File

@ -32,44 +32,55 @@
* Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/
class PNS_LINE;
class PNS_ITEMSET
class PNS_ITEMSET : public PNS_OBJECT
{
public:
typedef std::deque<PNS_ITEM*> ITEMS;
PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL );
PNS_ITEMSET( const PNS_ITEMSET& aOther ):
m_owner( false )
PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL, bool aBecomeOwner = false )
{
m_items = aOther.m_items;
if( aInitialItem )
{
if( aBecomeOwner )
aInitialItem->SetOwner( this );
m_items.push_back( aInitialItem );
}
}
PNS_ITEMSET( const PNS_ITEMSET& aOther )
{
copyFrom( aOther );
}
~PNS_ITEMSET();
void MakeOwner()
{
m_owner = true;
}
const PNS_ITEMSET& operator=( const PNS_ITEMSET& aOther )
{
m_items = aOther.m_items;
copyFrom( aOther );
return *this;
}
int Count( int aKindMask = -1 ) const
{
int n = 0;
BOOST_FOREACH( PNS_ITEM* item, m_items )
{
if( item->Kind() & aKindMask )
n++;
}
return n;
}
bool Empty() const
{
return m_items.empty();
}
ITEMS& Items() { return m_items; }
const ITEMS& CItems() const { return m_items; }
@ -100,13 +111,22 @@ public:
return m_items.size();
}
void Add( PNS_ITEM* aItem )
void Add( const PNS_LINE& aLine );
void Prepend( const PNS_LINE& aLine );
void Add( PNS_ITEM* aItem, bool aBecomeOwner = false )
{
if( aBecomeOwner )
aItem->SetOwner( this );
m_items.push_back( aItem );
}
void Prepend( PNS_ITEM* aItem )
void Prepend( PNS_ITEM* aItem, bool aBecomeOwner = false )
{
if( aBecomeOwner )
aItem->SetOwner( this );
m_items.push_front( aItem );
}
@ -122,6 +142,12 @@ public:
void Clear()
{
BOOST_FOREACH( PNS_ITEM *item, m_items )
{
if( item->BelongsTo( this ) )
delete item;
}
m_items.clear();
}
@ -130,17 +156,53 @@ public:
return std::find( m_items.begin(), m_items.end(), aItem ) != m_items.end();
}
void Erase( const PNS_ITEM* aItem )
void Erase( PNS_ITEM* aItem )
{
ITEMS::iterator f = std::find( m_items.begin(), m_items.end(), aItem );
if( f != m_items.end() )
m_items.erase( f );
if( aItem->BelongsTo( this ) )
delete aItem;
}
template<class T>
T* FindByKind( PNS_ITEM::PnsKind kind, int index = 0 )
{
int n = 0;
BOOST_FOREACH( PNS_ITEM* item, m_items )
{
if( item->OfKind (kind) )
{
if( index == n )
return static_cast<T*>( item );
else
n++;
}
}
return NULL;
}
private:
void release();
void copyFrom( const PNS_ITEMSET& aOther )
{
release();
BOOST_FOREACH( PNS_ITEM *item, aOther.m_items )
{
if( item->BelongsTo( &aOther ) )
m_items.push_back( item->Clone() );
else
m_items.push_back( item );
}
}
ITEMS m_items;
bool m_owner;
};
#endif

View File

@ -52,7 +52,7 @@ public:
};
PNS_JOINT() :
PNS_ITEM( JOINT ) {}
PNS_ITEM( JOINT ), m_locked( false ) {}
PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1 ) :
PNS_ITEM( JOINT )
@ -60,6 +60,7 @@ public:
m_tag.pos = aPos;
m_tag.net = aNet;
m_layers = aLayers;
m_locked = false;
}
PNS_JOINT( const PNS_JOINT& aB ) :
@ -70,6 +71,7 @@ public:
m_tag.net = aB.m_tag.net;
m_linkedItems = aB.m_linkedItems;
m_layers = aB.m_layers;
m_locked = false;
}
PNS_ITEM* Clone( ) const
@ -82,6 +84,9 @@ public:
/// segments of the same net, on the same layer.
bool IsLineCorner() const
{
if( m_locked )
return false;
if( m_linkedItems.Size() != 2 )
return false;
@ -138,6 +143,17 @@ public:
return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
}
PNS_VIA* Via()
{
BOOST_FOREACH( PNS_ITEM* item, m_linkedItems.Items() )
{
if( item->OfKind( VIA ) )
return static_cast<PNS_VIA*>( item );
}
return NULL;
}
/// trivial accessors
const HASH_TAG& Tag() const
@ -201,12 +217,25 @@ public:
m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
}
void Lock( bool aLock = true )
{
m_locked = aLock;
}
bool IsLocked() const
{
return m_locked;
}
private:
///> hash tag for unordered_multimap
HASH_TAG m_tag;
///> list of items linked to this joint
PNS_ITEMSET m_linkedItems;
///> locked (non-movable) flag
bool m_locked;
};
inline bool operator==( PNS_JOINT::HASH_TAG const& aP1, PNS_JOINT::HASH_TAG const& aP2 )

View File

@ -115,8 +115,10 @@ int PNS_LINE::Marker() const
if( m_segmentRefs )
{
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
{
marker |= s->Marker();
}
}
return marker;
}
@ -293,6 +295,9 @@ bool PNS_LINE::Is45Degree()
{
const SEG& s = m_line.CSegment( i );
if( s.Length() < 10 )
continue;
double angle = 180.0 / M_PI *
atan2( (double) s.B.y - (double) s.A.y,
(double) s.B.x - (double) s.A.x );

View File

@ -690,7 +690,6 @@ void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, co
return;
PNS_SEGMENT* s_old = static_cast<PNS_SEGMENT*>( aSeg );
PNS_SEGMENT* s_new[2];
s_new[0] = s_old->Clone();
@ -814,7 +813,7 @@ bool PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem )
int eiDepth = -1;
if( aEndItem && aEndItem->Owner() )
eiDepth = aEndItem->Owner()->Depth();
eiDepth = static_cast<PNS_NODE*>( aEndItem->Owner() )->Depth();
if( m_lastNode )
{
@ -839,7 +838,7 @@ bool PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem )
splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
if( Settings().RemoveLoops() )
removeLoops( m_lastNode, &current );
removeLoops( m_lastNode, current );
}
updateLeadingRatLine();
@ -929,22 +928,22 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
}
void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE& aLatest )
{
if( !aLatest->SegmentCount() )
if( !aLatest.SegmentCount() )
return;
if ( aLatest->CLine().CPoint( 0 ) == aLatest->CLine().CPoint( -1 ) )
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++ )
{
PNS_SEGMENT* seg = ( *aLatest->LinkedSegments() )[s];
PNS_LINE* ourLine = aNode->AssembleLine( seg );
PNS_SEGMENT* seg = ( *aLatest.LinkedSegments() )[s];
PNS_LINE ourLine = aNode->AssembleLine( seg );
PNS_JOINT a, b;
std::vector<PNS_LINE*> lines;
std::vector<PNS_LINE> lines;
aNode->FindLineEnds( ourLine, a, b );
@ -958,42 +957,38 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
int removedCount = 0;
int total = 0;
BOOST_FOREACH( PNS_LINE* line, lines )
BOOST_FOREACH( PNS_LINE& line, lines )
{
total++;
if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() )
if( !( line.ContainsSegment( seg ) ) && line.SegmentCount() )
{
aNode->Remove( line );
aNode->Remove( &line );
removedCount++;
}
}
TRACE( 0, "total segs removed: %d/%d\n", removedCount % total );
delete ourLine;
}
aNode->Remove( aLatest );
aNode->Remove( &aLatest );
}
void PNS_LINE_PLACER::simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest )
{
PNS_LINE* l = aNode->AssembleLine( aLatest );
SHAPE_LINE_CHAIN simplified ( l->CLine() );
PNS_LINE l = aNode->AssembleLine( aLatest );
SHAPE_LINE_CHAIN simplified( l.CLine() );
simplified.Simplify();
if( simplified.PointCount() != l->PointCount() )
if( simplified.PointCount() != l.PointCount() )
{
std::auto_ptr<PNS_LINE> lnew( l->Clone() );
aNode->Remove( l );
lnew->SetShape( simplified );
aNode->Add( lnew.get() );
PNS_LINE lnew( l );
aNode->Remove( &l );
lnew.SetShape( simplified );
aNode->Add( &lnew );
}
delete l;
}

View File

@ -242,7 +242,7 @@ private:
* Searches aNode for traces concurrent to aLatest and removes them. Updated
* topology is stored in aNode.
*/
void removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest );
void removeLoops( PNS_NODE* aNode, PNS_LINE& aLatest );
/**
* Function simplifyNewLine()

View File

@ -37,7 +37,6 @@ PNS_MEANDER_PLACER::PNS_MEANDER_PLACER( PNS_ROUTER* aRouter ) :
{
m_world = NULL;
m_currentNode = NULL;
m_originLine = NULL;
// Init temporary variables (do not leave uninitialized members)
m_initialSegment = NULL;
@ -74,7 +73,6 @@ bool PNS_MEANDER_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
p = m_initialSegment->Seg().NearestPoint( aP );
m_originLine = NULL;
m_currentNode = NULL;
m_currentStart = p;
@ -84,9 +82,9 @@ bool PNS_MEANDER_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
PNS_TOPOLOGY topo( m_world );
m_tunedPath = topo.AssembleTrivialPath( m_initialSegment );
m_world->Remove( m_originLine );
m_world->Remove( &m_originLine );
m_currentWidth = m_originLine->Width();
m_currentWidth = m_originLine.Width();
m_currentEnd = VECTOR2I( 0, 0 );
return true;
@ -123,10 +121,10 @@ bool PNS_MEANDER_PLACER::doMove( const VECTOR2I& aP, PNS_ITEM* aEndItem, int aTa
m_currentNode = m_world->Branch();
cutTunedLine( m_originLine->CLine(), m_currentStart, aP, pre, tuned, post );
cutTunedLine( m_originLine.CLine(), m_currentStart, aP, pre, tuned, post );
m_result = PNS_MEANDERED_LINE( this, false );
m_result.SetWidth( m_originLine->Width() );
m_result.SetWidth( m_originLine.Width() );
m_result.SetBaselineOffset( 0 );
for( int i = 0; i < tuned.SegmentCount(); i++ )
@ -197,7 +195,7 @@ bool PNS_MEANDER_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
if( !m_currentNode )
return false;
m_currentTrace = PNS_LINE( *m_originLine, m_finalShape );
m_currentTrace = PNS_LINE( m_originLine, m_finalShape );
m_currentNode->Add( &m_currentTrace );
Router()->CommitRouting( m_currentNode );
@ -207,7 +205,7 @@ bool PNS_MEANDER_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
bool PNS_MEANDER_PLACER::CheckFit( PNS_MEANDER_SHAPE* aShape )
{
PNS_LINE l( *m_originLine, aShape->CLine( 0 ) );
PNS_LINE l( m_originLine, aShape->CLine( 0 ) );
if( m_currentNode->CheckColliding( &l ) )
return false;
@ -221,7 +219,7 @@ bool PNS_MEANDER_PLACER::CheckFit( PNS_MEANDER_SHAPE* aShape )
const PNS_ITEMSET PNS_MEANDER_PLACER::Traces()
{
m_currentTrace = PNS_LINE( *m_originLine, m_finalShape );
m_currentTrace = PNS_LINE( m_originLine, m_finalShape );
return PNS_ITEMSET( &m_currentTrace );
}

View File

@ -100,7 +100,7 @@ protected:
///> Current world state
PNS_NODE* m_currentNode;
PNS_LINE* m_originLine;
PNS_LINE m_originLine;
PNS_LINE m_currentTrace;
PNS_ITEMSET m_tunedPath;

View File

@ -60,7 +60,6 @@ bool PNS_MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
p = m_initialSegment->Seg().NearestPoint( aP );
m_originLine = NULL;
m_currentNode = NULL;
m_currentStart = p;
@ -88,12 +87,12 @@ bool PNS_MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
m_tunedPathP = topo.AssembleTrivialPath( m_originPair.PLine().GetLink( 0 ) );
m_tunedPathN = topo.AssembleTrivialPath( m_originPair.NLine().GetLink( 0 ) );
m_world->Remove( m_originLine );
m_world->Remove( &m_originLine );
m_currentWidth = m_originLine->Width( );
m_currentWidth = m_originLine.Width();
m_currentEnd = VECTOR2I( 0, 0 );
if ( m_originPair.PLine().Net () == m_originLine->Net() )
if ( m_originPair.PLine().Net() == m_originLine.Net() )
m_coupledLength = itemsetLength( m_tunedPathN );
else
m_coupledLength = itemsetLength( m_tunedPathP );

View File

@ -88,13 +88,18 @@ PNS_NODE::~PNS_NODE()
delete *i;
}
releaseGarbage();
unlinkParent();
delete m_index;
}
int PNS_NODE::GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const
{
if( !m_clearanceFunctor )
return 100000;
return (*m_clearanceFunctor)( aA, aB );
}
@ -595,8 +600,6 @@ void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant )
void PNS_NODE::doRemove( PNS_ITEM* aItem )
{
// assert(m_root->m_index->Contains(aItem) || m_index->Contains(aItem));
// case 1: removing an item that is stored in the root node from any branch:
// mark it as overridden, but do not remove
if( aItem->BelongsTo( m_root ) && !isRoot() )
@ -609,7 +612,10 @@ void PNS_NODE::doRemove( PNS_ITEM* aItem )
// the item belongs to this particular branch: un-reference it
if( aItem->BelongsTo( this ) )
{
aItem->SetOwner( NULL );
m_root->m_garbageItems.insert( aItem );
}
}
@ -626,9 +632,6 @@ void PNS_NODE::removeLine( PNS_LINE* aLine )
{
std::vector<PNS_SEGMENT*>* segRefs = aLine->LinkedSegments();
if( !aLine->SegmentCount() )
return;
assert( segRefs != NULL );
assert( aLine->Owner() );
@ -636,9 +639,6 @@ void PNS_NODE::removeLine( PNS_LINE* aLine )
{
removeSegment( seg );
}
aLine->SetOwner( NULL );
aLine->ClearSegmentLinks();
}
@ -769,22 +769,22 @@ void PNS_NODE::followLine( PNS_SEGMENT* aCurrent, bool aScanDirection, int& aPos
}
PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex)
const PNS_LINE PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex )
{
const int MaxVerts = 1024 * 16;
VECTOR2I corners[MaxVerts + 1];
PNS_SEGMENT* segs[MaxVerts + 1];
PNS_LINE* pl = new PNS_LINE;
PNS_LINE pl;
bool guardHit = false;
int i_start = MaxVerts / 2, i_end = i_start + 1;
pl->SetWidth( aSeg->Width() );
pl->SetLayers( aSeg->Layers() );
pl->SetNet( aSeg->Net() );
pl->SetOwner( this );
pl.SetWidth( aSeg->Width() );
pl.SetLayers( aSeg->Layers() );
pl.SetNet( aSeg->Net() );
pl.SetOwner( this );
followLine( aSeg, false, i_start, MaxVerts, corners, segs, guardHit );
@ -800,11 +800,11 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex)
{
const VECTOR2I& p = corners[i];
pl->Line().Append( p );
pl.Line().Append( p );
if( segs[i] && prev_seg != segs[i] )
{
pl->LinkSegment( segs[i] );
pl.LinkSegment( segs[i] );
// latter condition to avoid loops
if( segs[i] == aSeg && aOriginSegmentIndex && !originSet )
@ -818,16 +818,16 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex)
prev_seg = segs[i];
}
assert( pl->SegmentCount() != 0 );
assert( pl.SegmentCount() != 0 );
return pl;
}
void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB )
void PNS_NODE::FindLineEnds( const PNS_LINE& aLine, PNS_JOINT& aA, PNS_JOINT& aB )
{
aA = *FindJoint( aLine->CPoint( 0 ), aLine );
aB = *FindJoint( aLine->CPoint( -1 ), aLine );
aA = *FindJoint( aLine.CPoint( 0 ), &aLine );
aB = *FindJoint( aLine.CPoint( -1 ), &aLine );
}
@ -869,32 +869,30 @@ void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector<PNS_JOINT*>& aFo
#endif
int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector<PNS_LINE*>& aLines )
int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector<PNS_LINE>& aLines )
{
BOOST_FOREACH( PNS_ITEM* item, aA.LinkList() )
{
if( item->Kind() == PNS_ITEM::SEGMENT )
{
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
PNS_LINE* line = AssembleLine( seg );
PNS_LINE line = AssembleLine( seg );
PNS_JOINT j_start, j_end;
FindLineEnds( line, j_start, j_end );
int id_start = line->CLine().Find( aA.Pos() );
int id_end = line->CLine().Find( aB.Pos() );
int id_start = line.CLine().Find( aA.Pos() );
int id_end = line.CLine().Find( aB.Pos() );
if( id_end < id_start )
std::swap( id_end, id_start );
if( id_start >= 0 && id_end >= 0 )
{
line->ClipVertexRange ( id_start, id_end );
line.ClipVertexRange( id_start, id_end );
aLines.push_back( line );
}
else
delete line;
}
}
@ -932,6 +930,13 @@ PNS_JOINT* PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
}
void PNS_NODE::LockJoint( const VECTOR2I& aPos, const PNS_ITEM* aItem, bool aLock )
{
PNS_JOINT& jt = touchJoint( aPos, aItem->Layers(), aItem->Net() );
jt.Lock( aLock );
}
PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet )
{
PNS_JOINT::HASH_TAG tag;
@ -1119,6 +1124,21 @@ void PNS_NODE::releaseChildren()
}
void PNS_NODE::releaseGarbage()
{
if( !isRoot( ) )
return;
BOOST_FOREACH( PNS_ITEM* item, m_garbageItems )
{
if( !item->BelongsTo( this ) )
delete item;
}
m_garbageItems.clear();
}
void PNS_NODE::Commit( PNS_NODE* aNode )
{
if( aNode->isRoot() )
@ -1136,6 +1156,7 @@ void PNS_NODE::Commit( PNS_NODE* aNode )
}
releaseChildren();
releaseGarbage();
}

View File

@ -128,7 +128,7 @@ struct PNS_COLLISION_FILTER {
* - lightweight cloning/branching (for recursive optimization and shove
* springback)
**/
class PNS_NODE
class PNS_NODE : public PNS_OBJECT
{
public:
typedef boost::optional<PNS_OBSTACLE> OPT_OBSTACLE;
@ -303,7 +303,7 @@ public:
* @param aOriginSegmentIndex index of aSeg in the resulting line
* @return the line
*/
PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex = NULL );
const PNS_LINE AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex = NULL );
///> Prints the contents and joints structure
void Dump( bool aLong = false );
@ -335,6 +335,8 @@ public:
*/
PNS_JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
void LockJoint( const VECTOR2I& aPos, const PNS_ITEM* aItem, bool aLock );
/**
* Function FindJoint()
*
@ -357,10 +359,10 @@ public:
///> finds all lines between a pair of joints. Used by the loop removal procedure.
int FindLinesBetweenJoints( PNS_JOINT& aA,
PNS_JOINT& aB,
std::vector<PNS_LINE*>& aLines );
std::vector<PNS_LINE>& aLines );
///> finds the joints corresponding to the ends of line aLine
void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB );
void FindLineEnds( const PNS_LINE& aLine, PNS_JOINT& aA, PNS_JOINT& aB );
///> Destroys all child nodes. Applicable only to the root node.
void KillChildren();
@ -410,6 +412,7 @@ private:
void doRemove( PNS_ITEM* aItem );
void unlinkParent();
void releaseChildren();
void releaseGarbage();
bool isRoot() const
{
@ -464,6 +467,8 @@ private:
///> optional collision filtering object
PNS_COLLISION_FILTER *m_collisionFilter;
boost::unordered_set<PNS_ITEM*> m_garbageItems;
};
#endif

View File

@ -57,7 +57,7 @@ void PNS_SHOVE::replaceItems( PNS_ITEM* aOld, PNS_ITEM* aNew )
}
int PNS_SHOVE::getClearance( PNS_ITEM *aA, PNS_ITEM *aB ) const
int PNS_SHOVE::getClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const
{
if( m_forceClearance >= 0 )
return m_forceClearance;
@ -66,7 +66,7 @@ int PNS_SHOVE::getClearance( PNS_ITEM *aA, PNS_ITEM *aB ) const
}
static void sanityCheck( PNS_LINE* aOld, PNS_LINE* aNew )
void PNS_SHOVE::sanityCheck( PNS_LINE* aOld, PNS_LINE* aNew )
{
assert( aOld->CPoint( 0 ) == aNew->CPoint( 0 ) );
assert( aOld->CPoint( -1 ) == aNew->CPoint( -1 ) );
@ -78,9 +78,9 @@ PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) :
{
m_forceClearance = -1;
m_root = aWorld;
m_currentNode = aWorld;
// Initialize other temporary variables:
m_currentNode = NULL;
m_draggedVia = NULL;
m_iter = 0;
m_multiLineMode = false;
@ -89,76 +89,68 @@ PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) :
PNS_SHOVE::~PNS_SHOVE()
{
// free all the stuff we've created during routing/dragging operation.
BOOST_FOREACH( PNS_ITEM* item, m_gcItems )
delete item;
}
// garbage-collected line assembling
PNS_LINE* PNS_SHOVE::assembleLine( const PNS_SEGMENT* aSeg, int* aIndex )
PNS_LINE PNS_SHOVE::assembleLine( const PNS_SEGMENT* aSeg, int* aIndex )
{
PNS_LINE* l = m_currentNode->AssembleLine( const_cast<PNS_SEGMENT*>( aSeg ), aIndex );
m_gcItems.push_back( l );
return l;
return m_currentNode->AssembleLine( const_cast<PNS_SEGMENT*>( aSeg ), aIndex );
}
// A dumb function that checks if the shoved line is shoved the right way, e.g.
// visually "outwards" of the line/via applying pressure on it. Unfortunately there's no
// mathematical concept of orientation of an open curve, so we use some primitive heuristics:
// if the shoved line wraps around the start of the "pusher", it's likely shoved in wrong direction.
bool PNS_SHOVE::checkBumpDirection( PNS_LINE* aCurrent, PNS_LINE* aShoved ) const
bool PNS_SHOVE::checkBumpDirection( const PNS_LINE& aCurrent, const PNS_LINE& aShoved ) const
{
const SEG ss = aCurrent->CSegment( 0 );
const SEG& ss = aCurrent.CSegment( 0 );
int dist = getClearance( aCurrent, aShoved ) + PNS_HULL_MARGIN;
int dist = getClearance( &aCurrent, &aShoved ) + PNS_HULL_MARGIN;
dist += aCurrent->Width() / 2;
dist += aShoved->Width() / 2;
dist += aCurrent.Width() / 2;
dist += aShoved.Width() / 2;
const VECTOR2I ps = ss.A - ( ss.B - ss.A ).Resize( dist );
return !aShoved->CLine().PointOnEdge( ps );
return !aShoved.CLine().PointOnEdge( ps );
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_LINE* aShoved )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::walkaroundLoneVia( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE& aShoved )
{
int clearance = getClearance( aCurrent, aObstacle );
const SHAPE_LINE_CHAIN hull = aCurrent->Via().Hull( clearance, aObstacle->Width() );
int clearance = getClearance( &aCurrent, &aObstacle );
const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width() );
SHAPE_LINE_CHAIN path_cw, path_ccw;
aObstacle->Walkaround( hull, path_cw, true );
aObstacle->Walkaround( hull, path_ccw, false );
aObstacle.Walkaround( hull, path_cw, true );
aObstacle.Walkaround( hull, path_ccw, false );
const SHAPE_LINE_CHAIN& shortest = path_ccw.Length() < path_cw.Length() ? path_ccw : path_cw;
if( shortest.PointCount() < 2 )
return SH_INCOMPLETE;
if( aObstacle->CPoint( -1 ) != shortest.CPoint( -1 ) )
if( aObstacle.CPoint( -1 ) != shortest.CPoint( -1 ) )
return SH_INCOMPLETE;
if( aObstacle->CPoint( 0 ) != shortest.CPoint( 0 ) )
if( aObstacle.CPoint( 0 ) != shortest.CPoint( 0 ) )
return SH_INCOMPLETE;
aShoved->SetShape( shortest );
aShoved.SetShape( shortest );
if( m_currentNode->CheckColliding( aShoved, aCurrent ) )
if( m_currentNode->CheckColliding( &aShoved, &aCurrent ) )
return SH_INCOMPLETE;
return SH_OK;
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_LINE* aShoved, const HULL_SET& aHulls )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE& aShoved, const HULL_SET& aHulls )
{
const SHAPE_LINE_CHAIN& obs = aObstacle->CLine();
const SHAPE_LINE_CHAIN& obs = aObstacle.CLine();
bool failingDirCheck = false;
int attempt;
@ -169,7 +161,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
int vFirst = -1, vLast = -1;
SHAPE_LINE_CHAIN path;
PNS_LINE l( *aObstacle );
PNS_LINE l( aObstacle );
for( int i = 0; i < (int) aHulls.size(); i++ )
{
@ -199,7 +191,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
}
}
if( ( vFirst < 0 || vLast < 0 ) && !path.CompareGeometry( aObstacle->CLine() ) )
if( ( vFirst < 0 || vLast < 0 ) && !path.CompareGeometry( aObstacle.CLine() ) )
{
TRACE( 100, "attempt %d fail vfirst-last", attempt );
continue;
@ -211,11 +203,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue;
}
if( !checkBumpDirection( aCurrent, &l ) )
if( !checkBumpDirection( aCurrent, l ) )
{
TRACE( 100, "attempt %d fail direction-check", attempt );
failingDirCheck = true;
aShoved->SetShape( l.CLine() );
aShoved.SetShape( l.CLine() );
continue;
}
@ -226,11 +218,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue;
}
bool colliding = m_currentNode->CheckColliding( &l, aCurrent, PNS_ITEM::ANY, m_forceClearance );
bool colliding = m_currentNode->CheckColliding( &l, &aCurrent, PNS_ITEM::ANY, m_forceClearance );
if( ( aCurrent->Marker() & MK_HEAD ) && !colliding )
if( ( aCurrent.Marker() & MK_HEAD ) && !colliding )
{
PNS_JOINT* jtStart = m_currentNode->FindJoint( aCurrent->CPoint( 0 ), aCurrent );
PNS_JOINT* jtStart = m_currentNode->FindJoint( aCurrent.CPoint( 0 ), &aCurrent );
BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() )
{
@ -245,7 +237,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue;
}
aShoved->SetShape( l.CLine() );
aShoved.SetShape( l.CLine() );
return SH_OK;
}
@ -254,16 +246,16 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_LINE* aShoved )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE& aShoved )
{
aShoved->ClearSegmentLinks();
aShoved.ClearSegmentLinks();
bool obstacleIsHead = false;
if( aObstacle->LinkedSegments() )
if( aObstacle.LinkedSegments() )
{
BOOST_FOREACH( PNS_SEGMENT* s, *aObstacle->LinkedSegments() )
BOOST_FOREACH( PNS_SEGMENT* s, *aObstacle.LinkedSegments() )
if( s->Marker() & MK_HEAD )
{
@ -274,18 +266,18 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE* aCurrent, PNS_LI
SHOVE_STATUS rv;
bool viaOnEnd = aCurrent->EndsWithVia();
bool viaOnEnd = aCurrent.EndsWithVia();
if( viaOnEnd && ( !aCurrent->LayersOverlap( aObstacle ) || aCurrent->SegmentCount() == 0 ) )
if( viaOnEnd && ( !aCurrent.LayersOverlap( &aObstacle ) || aCurrent.SegmentCount() == 0 ) )
{
rv = walkaroundLoneVia( aCurrent, aObstacle, aShoved );
}
else
{
int w = aObstacle->Width();
int n_segs = aCurrent->SegmentCount();
int w = aObstacle.Width();
int n_segs = aCurrent.SegmentCount();
int clearance = getClearance( aCurrent, aObstacle );
int clearance = getClearance( &aCurrent, &aObstacle );
HULL_SET hulls;
@ -293,114 +285,119 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE* aCurrent, PNS_LI
for( int i = 0; i < n_segs; i++ )
{
PNS_SEGMENT seg( *aCurrent, aCurrent->CSegment( i ) );
hulls.push_back( seg.Hull( clearance, w ) );
PNS_SEGMENT seg( aCurrent, aCurrent.CSegment( i ) );
SHAPE_LINE_CHAIN hull = seg.Hull( clearance, w );
hulls.push_back( hull );
}
if( viaOnEnd )
hulls.push_back ( aCurrent->Via().Hull( clearance, w ) );
hulls.push_back ( aCurrent.Via().Hull( clearance, w ) );
rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls );
}
if( obstacleIsHead )
aShoved->Mark( aShoved->Marker() | MK_HEAD );
aShoved.Mark( aShoved.Marker() | MK_HEAD );
return rv;
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE& aCurrent, PNS_SEGMENT* aObstacleSeg )
{
int segIndex;
PNS_LINE* obstacleLine = assembleLine( aObstacleSeg, &segIndex );
PNS_LINE* shovedLine = clone( obstacleLine );
PNS_LINE obstacleLine = assembleLine( aObstacleSeg, &segIndex );
PNS_LINE shovedLine( obstacleLine );
PNS_SEGMENT tmp( *aObstacleSeg );
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, obstacleLine, shovedLine );
assert( obstacleLine->LayersOverlap( shovedLine ) );
if( rv == SH_OK )
{
if( shovedLine->Marker() & MK_HEAD )
{
if( m_multiLineMode )
return SH_INCOMPLETE;
m_newHead = *shovedLine;
}
sanityCheck( obstacleLine, shovedLine );
replaceItems ( obstacleLine, shovedLine );
sanityCheck( obstacleLine, shovedLine );
int rank = aCurrent->Rank();
shovedLine->SetRank( rank - 1 );
if( !pushLine( shovedLine ) )
rv = SH_INCOMPLETE;
}
assert( obstacleLine.LayersOverlap( &shovedLine ) );
#ifdef DEBUG
m_logger.NewGroup( "on-colliding-segment", m_iter );
m_logger.Log( aObstacleSeg, 0, "obstacle-segment" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( obstacleLine, 2, "obstacle-line" );
m_logger.Log( shovedLine, 3, "shoved-line" );
m_logger.Log( &tmp, 0, "obstacle-segment" );
m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( &obstacleLine, 2, "obstacle-line" );
m_logger.Log( &shovedLine, 3, "shoved-line" );
#endif
return rv;
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle )
{
PNS_LINE* shovedLine = clone( aObstacle );
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, aObstacle, shovedLine );
if( rv == SH_OK )
{
if( shovedLine->Marker() & MK_HEAD )
if( shovedLine.Marker() & MK_HEAD )
{
if( m_multiLineMode )
return SH_INCOMPLETE;
m_newHead = *shovedLine;
m_newHead = shovedLine;
}
sanityCheck( aObstacle, shovedLine );
replaceItems( aObstacle, shovedLine );
sanityCheck( aObstacle, shovedLine );
sanityCheck( &obstacleLine, &shovedLine );
replaceItems( &obstacleLine, &shovedLine );
int rank = aObstacle->Rank();
shovedLine->SetRank ( rank );
int rank = aCurrent.Rank();
shovedLine.SetRank( rank - 1 );
if( !pushLine( shovedLine ) )
rv = SH_INCOMPLETE;
#ifdef DEBUG
m_logger.NewGroup( "on-colliding-line", m_iter );
m_logger.Log( aObstacle, 0, "obstacle-line" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( shovedLine, 3, "shoved-line" );
#endif
}
return rv;
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle )
{
PNS_LINE shovedLine( aObstacle );
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, aObstacle, shovedLine );
#ifdef DEBUG
m_logger.NewGroup( "on-colliding-line", m_iter );
m_logger.Log( &aObstacle, 0, "obstacle-line" );
m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( &shovedLine, 3, "shoved-line" );
#endif
if( rv == SH_OK )
{
if( shovedLine.Marker() & MK_HEAD )
{
if( m_multiLineMode )
return SH_INCOMPLETE;
m_newHead = shovedLine;
}
sanityCheck( &aObstacle, &shovedLine );
replaceItems( &aObstacle, &shovedLine );
int rank = aObstacle.Rank();
shovedLine.SetRank( rank - 1 );
if( !pushLine( shovedLine ) )
{
rv = SH_INCOMPLETE;
//printf( "pushLine failed\n" );
}
}
return rv;
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid )
{
PNS_WALKAROUND walkaround( m_currentNode, Router() );
PNS_LINE* walkaroundLine = clone( aCurrent );
PNS_LINE walkaroundLine( aCurrent );
if( aCurrent->EndsWithVia() )
if( aCurrent.EndsWithVia() )
{
PNS_VIA vh = aCurrent->Via();
PNS_VIA vh = aCurrent.Via();
PNS_VIA* via = NULL;
PNS_JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), aCurrent );
PNS_JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent );
if( !jtStart )
return SH_INCOMPLETE;
@ -421,7 +418,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOL
walkaround.SetSolidsOnly( true );
walkaround.SetIterationLimit ( 8 ); // fixme: make configurable
int currentRank = aCurrent->Rank();
int currentRank = aCurrent.Rank();
int nextRank;
if( !Settings().JumpOverObstacles() )
@ -435,34 +432,35 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOL
walkaround.SetSingleDirection( true );
}
if( walkaround.Route( *aCurrent, *walkaroundLine, false ) != PNS_WALKAROUND::DONE )
if( walkaround.Route( aCurrent, walkaroundLine, false ) != PNS_WALKAROUND::DONE )
return SH_INCOMPLETE;
walkaroundLine->ClearSegmentLinks();
walkaroundLine->Unmark();
walkaroundLine->Line().Simplify();
walkaroundLine.ClearSegmentLinks();
walkaroundLine.Unmark();
walkaroundLine.Line().Simplify();
if( walkaroundLine->HasLoops() )
if( walkaroundLine.HasLoops() )
return SH_INCOMPLETE;
if( aCurrent->Marker() & MK_HEAD )
if( aCurrent.Marker() & MK_HEAD )
{
walkaroundLine->Mark( MK_HEAD );
walkaroundLine.Mark( MK_HEAD );
if( m_multiLineMode )
return SH_INCOMPLETE;
m_newHead = *walkaroundLine;
m_newHead = walkaroundLine;
}
replaceItems ( aCurrent, walkaroundLine );
walkaroundLine->SetRank( nextRank );
sanityCheck( &aCurrent, &walkaroundLine );
replaceItems( &aCurrent, &walkaroundLine );
walkaroundLine.SetRank( nextRank );
#ifdef DEBUG
m_logger.NewGroup( "on-colliding-solid", m_iter );
m_logger.Log( aObstacleSolid, 0, "obstacle-solid" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( walkaroundLine, 3, "walk-line" );
m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( &walkaroundLine, 3, "walk-line" );
#endif
popLine();
@ -532,6 +530,9 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
PNS_JOINT* jt = m_currentNode->FindJoint( p0, aVia );
VECTOR2I p0_pushed( p0 + aForce );
if( jt->IsLocked() )
return SH_INCOMPLETE;
while( aForce.x != 0 || aForce.y != 0 )
{
PNS_JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia );
@ -542,6 +543,12 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
p0_pushed += aForce.Resize( 2 ); // make sure pushed via does not overlap with any existing joint
}
if( !jt )
{
TRACEn( 1, "weird, can't find the center-of-via joint\n" );
return SH_INCOMPLETE;
}
PNS_VIA* pushedVia = aVia->Clone();
pushedVia->SetPos( p0_pushed );
pushedVia->Mark( aVia->Marker() );
@ -552,12 +559,6 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
m_draggedViaHeadSet.Clear();
}
if( !jt )
{
TRACEn( 1, "weird, can't find the center-of-via joint\n" );
return SH_INCOMPLETE;
}
BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() )
{
if( PNS_SEGMENT* seg = dyn_cast<PNS_SEGMENT*>( item ) )
@ -567,19 +568,19 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
lp.first = assembleLine( seg, &segIndex );
assert( segIndex == 0 || ( segIndex == ( lp.first->SegmentCount() - 1 ) ) );
assert( segIndex == 0 || ( segIndex == ( lp.first.SegmentCount() - 1 ) ) );
if( segIndex == 0 )
lp.first->Reverse();
lp.first.Reverse();
lp.second = clone( lp.first );
lp.second->ClearSegmentLinks();
lp.second->DragCorner( p0_pushed, lp.second->CLine().Find( p0 ) );
lp.second->AppendVia( *pushedVia );
lp.second = lp.first;
lp.second.ClearSegmentLinks();
lp.second.DragCorner( p0_pushed, lp.second.CLine().Find( p0 ) );
lp.second.AppendVia( *pushedVia );
draggedLines.push_back( lp );
if( aVia->Marker() & MK_HEAD )
m_draggedViaHeadSet.Add( clone ( lp.second ) );
m_draggedViaHeadSet.Add( lp.second );
}
}
@ -594,9 +595,6 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
m_logger.Log( aVia, 0, "obstacle-via" );
#endif
if( aVia->BelongsTo( m_currentNode ) )
delete aVia;
pushedVia->SetRank( aCurrentRank - 1 );
#ifdef DEBUG
@ -605,32 +603,34 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
BOOST_FOREACH( LINE_PAIR lp, draggedLines )
{
if( lp.first->Marker() & MK_HEAD )
if( lp.first.Marker() & MK_HEAD )
{
lp.second->Mark( MK_HEAD );
lp.second.Mark( MK_HEAD );
if ( m_multiLineMode )
return SH_INCOMPLETE;
m_newHead = *lp.second;
m_newHead = lp.second;
}
unwindStack( lp.first );
unwindStack( &lp.first );
if( lp.second->SegmentCount() )
if( lp.second.SegmentCount() )
{
replaceItems( lp.first, lp.second );
lp.second->SetRank( aCurrentRank - 1 );
replaceItems( &lp.first, &lp.second );
lp.second.SetRank( aCurrentRank - 1 );
if( !pushLine( lp.second ) )
return SH_INCOMPLETE;
}
else
m_currentNode->Remove( lp.first );
{
m_currentNode->Remove( &lp.first );
}
#ifdef DEBUG
m_logger.Log( lp.first, 2, "fan-pre" );
m_logger.Log( lp.second, 3, "fan-post" );
m_logger.Log( &lp.first, 2, "fan-pre" );
m_logger.Log( &lp.second, 3, "fan-post" );
#endif
}
@ -687,28 +687,27 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA*
}
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PNS_VIA* aObstacleVia )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE& aCurrent, PNS_VIA* aObstacleVia )
{
std::vector<PNS_LINE*> steps;
int n = 0;
PNS_LINE* cur = clone( aCurrent );
cur->ClearSegmentLinks();
PNS_LINE cur( aCurrent );
cur.ClearSegmentLinks();
PNS_JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia );
PNS_LINE* shoved = clone( aCurrent );
shoved->ClearSegmentLinks();
PNS_LINE shoved( aCurrent );
shoved.ClearSegmentLinks();
cur->RemoveVia();
unwindStack( aCurrent );
cur.RemoveVia();
unwindStack( &aCurrent );
BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() )
{
if( item->OfKind( PNS_ITEM::SEGMENT ) && item->LayersOverlap( aCurrent ) )
if( item->OfKind( PNS_ITEM::SEGMENT ) && item->LayersOverlap( &aCurrent ) )
{
PNS_SEGMENT* seg = (PNS_SEGMENT*) item;
PNS_LINE* head = assembleLine( seg );
PNS_LINE head = assembleLine( seg );
head->AppendVia( *aObstacleVia );
head.AppendVia( *aObstacleVia );
SHOVE_STATUS st = ProcessSingleLine( head, cur, shoved );
@ -717,14 +716,14 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PN
#ifdef DEBUG
m_logger.NewGroup( "on-reverse-via-fail-shove", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( shoved, 3, "shoved-line" );
m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( &shoved, 3, "shoved-line" );
#endif
return st;
}
cur->SetShape( shoved->CLine() );
cur.SetShape( shoved.CLine() );
n++;
}
}
@ -734,38 +733,38 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PN
#ifdef DEBUG
m_logger.NewGroup( "on-reverse-via-fail-lonevia", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( &aCurrent, 1, "current-line" );
#endif
PNS_LINE head( *aCurrent );
PNS_LINE head( aCurrent );
head.Line().Clear();
head.AppendVia( *aObstacleVia );
head.ClearSegmentLinks();
SHOVE_STATUS st = ProcessSingleLine( &head, aCurrent, shoved );
SHOVE_STATUS st = ProcessSingleLine( head, aCurrent, shoved );
if( st != SH_OK )
return st;
cur->SetShape( shoved->CLine() );
cur.SetShape( shoved.CLine() );
}
if( aCurrent->EndsWithVia() )
shoved->AppendVia( aCurrent->Via() );
if( aCurrent.EndsWithVia() )
shoved.AppendVia( aCurrent.Via() );
#ifdef DEBUG
m_logger.NewGroup( "on-reverse-via", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" );
m_logger.Log( shoved, 3, "shoved-line" );
m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( &shoved, 3, "shoved-line" );
#endif
int currentRank = aCurrent->Rank();
replaceItems( aCurrent, shoved );
int currentRank = aCurrent.Rank();
replaceItems( &aCurrent, &shoved );
if ( !pushLine( shoved ) )
return SH_INCOMPLETE;
shoved->SetRank( currentRank );
shoved.SetRank( currentRank );
return SH_OK;
}
@ -773,17 +772,17 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PN
void PNS_SHOVE::unwindStack( PNS_SEGMENT *aSeg )
{
for( std::vector<PNS_LINE*>::iterator i = m_lineStack.begin(); i != m_lineStack.end(); )
for( std::vector<PNS_LINE>::iterator i = m_lineStack.begin(); i != m_lineStack.end() ; )
{
if( (*i)->ContainsSegment( aSeg ) )
if( i->ContainsSegment( aSeg ) )
i = m_lineStack.erase( i );
else
i++;
}
for( std::vector<PNS_LINE*>::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); )
for( std::vector<PNS_LINE>::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end() ; )
{
if( (*i)->ContainsSegment( aSeg ) )
if( i->ContainsSegment( aSeg ) )
i = m_optimizerQueue.erase( i );
else
i++;
@ -808,9 +807,9 @@ void PNS_SHOVE::unwindStack( PNS_ITEM* aItem )
}
bool PNS_SHOVE::pushLine( PNS_LINE* aL )
bool PNS_SHOVE::pushLine( const PNS_LINE& aL )
{
if( aL->LinkCount() >= 0 && ( aL->LinkCount() != aL->SegmentCount() ) )
if( aL.LinkCount() >= 0 && ( aL.LinkCount() != aL.SegmentCount() ) )
return false;
m_lineStack.push_back( aL );
@ -819,18 +818,28 @@ bool PNS_SHOVE::pushLine( PNS_LINE* aL )
return true;
}
void PNS_SHOVE::popLine( )
{
PNS_LINE* l = m_lineStack.back();
PNS_LINE& l = m_lineStack.back();
for( std::vector<PNS_LINE*>::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); )
for( std::vector<PNS_LINE>::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); )
{
if( ( *i ) == l )
bool found = false;
if( !l.LinkedSegments() )
continue;
BOOST_FOREACH( PNS_SEGMENT *s, *l.LinkedSegments() )
{
if( i->ContainsSegment( s ) )
{
i = m_optimizerQueue.erase( i );
found = true;
break;
}
else
}
if( !found )
i++;
}
@ -840,7 +849,7 @@ void PNS_SHOVE::popLine( )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
{
PNS_LINE* currentLine = m_lineStack.back();
PNS_LINE currentLine = m_lineStack.back();
PNS_NODE::OPT_OBSTACLE nearest;
SHOVE_STATUS st = SH_NULL;
@ -848,7 +857,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
for( int i = 0; i < 3; i++ )
{
nearest = m_currentNode->NearestObstacle( currentLine, search_order[i] );
nearest = m_currentNode->NearestObstacle( &currentLine, search_order[i] );
if( nearest )
break;
@ -864,7 +873,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
unwindStack( ni );
if( !ni->OfKind( PNS_ITEM::SOLID ) && ni->Rank() >= 0 && ni->Rank() > currentLine->Rank() )
if( !ni->OfKind( PNS_ITEM::SOLID ) && ni->Rank() >= 0 && ni->Rank() > currentLine.Rank() )
{
switch( ni->Kind() )
{
@ -873,7 +882,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
PNS_VIA* revVia = (PNS_VIA*) ni;
TRACE( 2, "iter %d: reverse-collide-via", aIter );
if( currentLine->EndsWithVia() && m_currentNode->CheckColliding( &currentLine->Via(), revVia ) )
if( currentLine.EndsWithVia() && m_currentNode->CheckColliding( &currentLine.Via(), revVia ) )
{
st = SH_INCOMPLETE;
}
@ -889,7 +898,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
{
PNS_SEGMENT* seg = (PNS_SEGMENT*) ni;
TRACE( 2, "iter %d: reverse-collide-segment ", aIter );
PNS_LINE* revLine = assembleLine( seg );
PNS_LINE revLine = assembleLine( seg );
popLine();
st = onCollidingLine( revLine, currentLine );
@ -914,7 +923,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
case PNS_ITEM::VIA:
TRACE( 2, "iter %d: shove-via ", aIter );
st = onCollidingVia( currentLine, (PNS_VIA*) ni );
st = onCollidingVia( &currentLine, (PNS_VIA*) ni );
break;
case PNS_ITEM::SOLID:
@ -988,22 +997,20 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
m_multiLineMode = false;
// empty head? nothing to shove...
if( !aCurrentHead.SegmentCount() && !aCurrentHead.EndsWithVia() )
return SH_INCOMPLETE;
PNS_LINE* head = clone( &aCurrentHead );
if( !head )
return SH_INCOMPLETE;
head->ClearSegmentLinks();
PNS_LINE head( aCurrentHead );
head.ClearSegmentLinks();
m_lineStack.clear();
m_optimizerQueue.clear();
m_newHead = OPT_LINE();
m_logger.Clear();
PNS_ITEMSET headSet( clone( &aCurrentHead ) );
PNS_ITEMSET headSet;
headSet.Add( aCurrentHead );
reduceSpringback( headSet );
@ -1011,19 +1018,24 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
m_currentNode = parent->Branch();
m_currentNode->ClearRanks();
m_currentNode->Add( head );
m_currentNode->Add( &head );
head->Mark( MK_HEAD );
head->SetRank( 100000 );
m_currentNode->LockJoint( head.CPoint(0), &head, true );
if( !head.EndsWithVia() )
m_currentNode->LockJoint( head.CPoint( -1 ), &head, true );
head.Mark( MK_HEAD );
head.SetRank( 100000 );
m_logger.NewGroup( "initial", 0 );
m_logger.Log( head, 0, "head" );
m_logger.Log( &head, 0, "head" );
PNS_VIA* headVia = NULL;
if( head->EndsWithVia() )
if( head.EndsWithVia() )
{
headVia = head->Via().Clone();
headVia = head.Via().Clone();
m_currentNode->Add( headVia );
headVia->Mark( MK_HEAD );
headVia->SetRank( 100000 );
@ -1037,7 +1049,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
if( ( st == SH_OK || st == SH_HEAD_MODIFIED ) )
runOptimizer( m_currentNode, head );
runOptimizer( m_currentNode );
if( m_newHead && st == SH_OK )
{
@ -1081,7 +1093,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
if( !headOrig->SegmentCount() )
return SH_INCOMPLETE;
headSet.Add( clone( headOrig ) );
headSet.Add( *headOrig );
}
m_lineStack.clear();
@ -1095,25 +1107,26 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
m_currentNode = parent->Branch();
m_currentNode->ClearRanks();
int n = 0;
BOOST_FOREACH ( const PNS_ITEM* item, aHeadSet.CItems() )
{
const PNS_LINE* headOrig = static_cast<const PNS_LINE*>( item );
PNS_LINE* head = clone( headOrig );
head->ClearSegmentLinks();
PNS_LINE head( *headOrig );
head.ClearSegmentLinks();
m_currentNode->Add( head );
m_currentNode->Add( &head );
head->Mark( MK_HEAD );
head->SetRank( 100000 );
head.Mark( MK_HEAD );
head.SetRank( 100000 );
n++;
if ( !pushLine( head ) )
return SH_INCOMPLETE;
PNS_VIA* headVia = NULL;
if( head->EndsWithVia() )
if( head.EndsWithVia() )
{
headVia = head->Via().Clone(); // fixme: leak
headVia = head.Via().Clone(); // fixme: leak
m_currentNode->Add( headVia );
headVia->Mark( MK_HEAD );
headVia->SetRank( 100000 );
@ -1127,7 +1140,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
st = shoveMainLoop();
if( st == SH_OK )
runOptimizer( m_currentNode, NULL );
runOptimizer( m_currentNode );
m_currentNode->RemoveByMarker( MK_HEAD );
@ -1162,8 +1175,6 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveDraggingVia( PNS_VIA* aVia, const VECTOR
PNS_NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node;
m_currentNode = parent;
//st = pushVia( aVia, ( aWhere - aVia->Pos() ), 0, true );
//reduceSpringback( m_draggedViaHeadSet );
parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node;
@ -1176,7 +1187,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveDraggingVia( PNS_VIA* aVia, const VECTOR
st = shoveMainLoop();
if( st == SH_OK )
runOptimizer( m_currentNode, NULL );
runOptimizer( m_currentNode );
if( st == SH_OK || st == SH_HEAD_MODIFIED )
{
@ -1196,7 +1207,7 @@ 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_OPTIMIZER optimizer( aNode );
int optFlags = 0, n_passes = 0;
@ -1207,10 +1218,10 @@ void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead )
int maxWidth = 0;
for( std::vector<PNS_LINE*>::iterator i = m_optimizerQueue.begin();
for( std::vector<PNS_LINE>::iterator i = m_optimizerQueue.begin();
i != m_optimizerQueue.end(); ++i )
{
maxWidth = std::max( (*i)->Width(), maxWidth );
maxWidth = std::max( i->Width(), maxWidth );
}
if( area )
@ -1253,20 +1264,20 @@ void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead )
{
std::reverse( m_optimizerQueue.begin(), m_optimizerQueue.end() );
for( std::vector<PNS_LINE*>::iterator i = m_optimizerQueue.begin();
for( std::vector<PNS_LINE>::iterator i = m_optimizerQueue.begin();
i != m_optimizerQueue.end(); ++i )
{
PNS_LINE* line = *i;
PNS_LINE& line = *i;
if( !( line -> Marker() & MK_HEAD ) )
if( !( line.Marker() & MK_HEAD ) )
{
PNS_LINE optimized;
if( optimizer.Optimize( line, &optimized ) )
if( optimizer.Optimize( &line, &optimized ) )
{
aNode->Remove( line );
line->SetShape( optimized.CLine() );
aNode->Add( line );
aNode->Remove( &line );
line.SetShape( optimized.CLine() );
aNode->Add( &line );
}
}
}
@ -1288,8 +1299,8 @@ const PNS_LINE PNS_SHOVE::NewHead() const
}
void PNS_SHOVE::SetInitialLine( PNS_LINE* aInitial )
void PNS_SHOVE::SetInitialLine( PNS_LINE& aInitial )
{
m_root = m_root->Branch();
m_root->Remove( aInitial );
m_root->Remove( &aInitial );
}

View File

@ -64,8 +64,8 @@ public:
SHOVE_STATUS ShoveMultiLines( const PNS_ITEMSET& aHeadSet );
SHOVE_STATUS ShoveDraggingVia( PNS_VIA* aVia, const VECTOR2I& aWhere, PNS_VIA** aNewVia );
SHOVE_STATUS ProcessSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_LINE* aShoved );
SHOVE_STATUS ProcessSingleLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE& aShoved );
void ForceClearance ( bool aEnabled, int aClearance )
{
@ -79,12 +79,12 @@ public:
const PNS_LINE NewHead() const;
void SetInitialLine( PNS_LINE* aInitial );
void SetInitialLine( PNS_LINE& aInitial );
private:
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
typedef boost::optional<PNS_LINE> OPT_LINE;
typedef std::pair <PNS_LINE*, PNS_LINE*> LINE_PAIR;
typedef std::pair<PNS_LINE, PNS_LINE> LINE_PAIR;
typedef std::vector<LINE_PAIR> LINE_PAIR_VEC;
struct SPRINGBACK_TAG
@ -98,21 +98,21 @@ private:
OPT_BOX2I m_affectedArea;
};
SHOVE_STATUS processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_LINE* aShoved, const HULL_SET& hulls );
SHOVE_STATUS processHullSet( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE& aShoved, const HULL_SET& hulls );
bool reduceSpringback( const PNS_ITEMSET& aHeadItems );
bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems,
const PNS_COST_ESTIMATOR& aCost, const OPT_BOX2I& aAffectedArea );
SHOVE_STATUS walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved );
bool checkBumpDirection( PNS_LINE* aCurrent, PNS_LINE* aShoved ) const;
SHOVE_STATUS walkaroundLoneVia( PNS_LINE& aCurrent, PNS_LINE& aObstacle, PNS_LINE& aShoved );
bool checkBumpDirection( const PNS_LINE& aCurrent, const PNS_LINE& aShoved ) const;
SHOVE_STATUS onCollidingLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle );
SHOVE_STATUS onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg );
SHOVE_STATUS onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid );
SHOVE_STATUS onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle );
SHOVE_STATUS onCollidingSegment( PNS_LINE& aCurrent, PNS_SEGMENT* aObstacleSeg );
SHOVE_STATUS onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid );
SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia );
SHOVE_STATUS onReverseCollidingVia( PNS_LINE* aCurrent, PNS_VIA* aObstacleVia );
SHOVE_STATUS onReverseCollidingVia( PNS_LINE& aCurrent, PNS_VIA* aObstacleVia );
SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank, bool aDryRun = false );
OPT_BOX2I totalAffectedArea() const;
@ -120,34 +120,25 @@ private:
void unwindStack( PNS_SEGMENT* aSeg );
void unwindStack( PNS_ITEM* aItem );
void runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead );
void runOptimizer( PNS_NODE* aNode );
bool pushLine( PNS_LINE* aL );
bool pushLine( const PNS_LINE& aL );
void popLine();
PNS_LINE* assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL );
PNS_LINE assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL );
void replaceItems( PNS_ITEM* aOld, PNS_ITEM* aNew );
template<class T> T* clone( const T* aItem )
{
T *cloned = aItem->Clone();
m_gcItems.push_back( cloned );
return cloned;
}
OPT_BOX2I m_affectedAreaSum;
SHOVE_STATUS shoveIteration( int aIter );
SHOVE_STATUS shoveMainLoop();
int getClearance( PNS_ITEM* aA, PNS_ITEM* aB ) const;
int getClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const;
std::vector<SPRINGBACK_TAG> m_nodeStack;
std::vector<PNS_LINE*> m_lineStack;
std::vector<PNS_LINE*> m_optimizerQueue;
std::vector<PNS_ITEM*> m_gcItems;
std::vector<PNS_LINE> m_lineStack;
std::vector<PNS_LINE> m_optimizerQueue;
PNS_NODE* m_root;
PNS_NODE* m_currentNode;
@ -161,6 +152,7 @@ private:
int m_iter;
int m_forceClearance;
bool m_multiLineMode;
void sanityCheck( PNS_LINE* aOld, PNS_LINE* aNew );
};
#endif // __PNS_SHOVE_H

View File

@ -49,7 +49,7 @@ int PNS_SIZES_SETTINGS::inheritTrackWidth( PNS_ITEM* aItem )
return 0;
}
PNS_JOINT* jt = aItem->Owner()->FindJoint( p, aItem );
PNS_JOINT* jt = static_cast<PNS_NODE*>( aItem->Owner() )->FindJoint( p, aItem );
assert( jt != NULL );

View File

@ -37,17 +37,17 @@ bool PNS_TOPOLOGY::SimplifyLine( PNS_LINE* aLine )
return false;
PNS_SEGMENT* root = ( *aLine->LinkedSegments() )[0];
std::auto_ptr<PNS_LINE> l( m_world->AssembleLine( root ) );
SHAPE_LINE_CHAIN simplified( l->CLine() );
PNS_LINE l = m_world->AssembleLine( root );
SHAPE_LINE_CHAIN simplified( l.CLine() );
simplified.Simplify();
if( simplified.PointCount() != l->PointCount() )
if( simplified.PointCount() != l.PointCount() )
{
std::auto_ptr<PNS_LINE> lnew( l->Clone() );
m_world->Remove( l.get() );
lnew->SetShape( simplified );
m_world->Add( lnew.get() );
PNS_LINE lnew( l );
m_world->Remove( &l );
lnew.SetShape( simplified );
m_world->Add( &lnew );
return true;
}
@ -199,13 +199,13 @@ bool PNS_TOPOLOGY::followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET&
if( !next_seg )
return false;
PNS_LINE* l = m_world->AssembleLine( next_seg );
PNS_LINE l = m_world->AssembleLine( next_seg );
VECTOR2I nextAnchor = ( aLeft ? l->CLine().CPoint( -1 ) : l->CLine().CPoint( 0 ) );
VECTOR2I nextAnchor = ( aLeft ? l.CLine().CPoint( -1 ) : l.CLine().CPoint( 0 ) );
if( nextAnchor != anchor )
{
l->Reverse();
l.Reverse();
}
if( aLeft )
@ -219,7 +219,7 @@ bool PNS_TOPOLOGY::followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET&
aSet.Add( l );
}
return followTrivialPath( l, aLeft, aSet, aVisited );
return followTrivialPath( &l, aLeft, aSet, aVisited );
}
return false;
@ -231,12 +231,12 @@ const PNS_ITEMSET PNS_TOPOLOGY::AssembleTrivialPath( PNS_SEGMENT* aStart )
PNS_ITEMSET path;
std::set<PNS_ITEM*> visited;
PNS_LINE* l = m_world->AssembleLine( aStart );
PNS_LINE l = m_world->AssembleLine( aStart );
path.Add( l );
followTrivialPath( l, false, path, visited );
followTrivialPath( l, true, path, visited );
followTrivialPath( &l, false, path, visited );
followTrivialPath( &l, true, path, visited );
return path;
}
@ -362,14 +362,17 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair )
}
}
}
} else
}
else
{
return false;
}
if( !coupledSeg )
return false;
std::auto_ptr<PNS_LINE> lp( m_world->AssembleLine( refSeg ) );
std::auto_ptr<PNS_LINE> ln( m_world->AssembleLine( coupledSeg ) );
PNS_LINE lp = m_world->AssembleLine( refSeg );
PNS_LINE ln = m_world->AssembleLine( coupledSeg );
if( DpNetPolarity( refNet ) < 0 )
{
@ -377,17 +380,18 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair )
}
int gap = -1;
if( refSeg->Seg().ApproxParallel( coupledSeg->Seg() ) )
{
// Segments are parallel -> compute pair gap
const VECTOR2I refDir = refSeg->Anchor( 1 ) - refSeg->Anchor( 0 );
const VECTOR2I displacement = refSeg->Anchor( 1 ) - coupledSeg->Anchor( 1 );
gap = (int) std::abs( refDir.Cross( displacement ) / refDir.EuclideanNorm() ) - lp->Width();
gap = (int) std::abs( refDir.Cross( displacement ) / refDir.EuclideanNorm() ) - lp.Width();
}
aPair = PNS_DIFF_PAIR( *lp, *ln );
aPair.SetWidth( lp->Width() );
aPair.SetLayers( lp->Layers() );
aPair = PNS_DIFF_PAIR( lp, ln );
aPair.SetWidth( lp.Width() );
aPair.SetLayers( lp.Layers() );
aPair.SetGap( gap );
return true;

View File

@ -292,7 +292,7 @@ void ROUTER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
switch( aEvent.KeyCode() )
{
case 'S':
case '0':
TRACEn( 2, "saving drag/route log...\n" );
m_router->DumpLog();
break;