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; PNS_SHOVE::SHOVE_STATUS sh1;
sh1 = shove.ProcessSingleLine( &postWalk, &preShove, &postShove ); sh1 = shove.ProcessSingleLine( postWalk, preShove, postShove );
if( sh1 != PNS_SHOVE::SH_OK ) if( sh1 != PNS_SHOVE::SH_OK )
return false; return false;

View File

@ -30,7 +30,6 @@ PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) :
m_world = NULL; m_world = NULL;
m_lastNode = NULL; m_lastNode = NULL;
m_mode = SEGMENT; m_mode = SEGMENT;
m_draggedLine = NULL;
m_draggedVia = NULL; m_draggedVia = NULL;
m_shove = NULL; m_shove = NULL;
m_draggedSegmentIndex = 0; 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_draggedLine = m_world->AssembleLine( aSeg, &m_draggedSegmentIndex );
m_shove->SetInitialLine( m_draggedLine ); m_shove->SetInitialLine( m_draggedLine );
m_lastValidDraggedLine = *m_draggedLine; m_lastValidDraggedLine = m_draggedLine;
m_lastValidDraggedLine.ClearSegmentLinks(); m_lastValidDraggedLine.ClearSegmentLinks();
if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 ) if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 )
@ -90,12 +89,12 @@ bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA* aVia )
{ {
int segIndex; int segIndex;
PNS_SEGMENT* seg = ( PNS_SEGMENT*) item; 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 ) 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 SEGMENT:
case CORNER: case CORNER:
{ {
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
PNS_LINE tmp( *m_draggedLine ); PNS_LINE tmp( m_draggedLine );
if( m_mode == SEGMENT ) if( m_mode == SEGMENT )
tmp.DragSegment( aP, m_draggedSegmentIndex, thresh ); 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->Remove( aVia );
m_lastNode->Add( m_draggedVia ); m_lastNode->Add( m_draggedVia );
BOOST_FOREACH( PNS_LINE &l, m_origViaConnections ) BOOST_FOREACH( PNS_ITEM* item, m_origViaConnections.Items() )
{ {
PNS_LINE origLine( l ); if ( const PNS_LINE* l = dyn_cast<const PNS_LINE*>( item ) )
PNS_LINE* draggedLine = l.Clone(); {
PNS_LINE origLine( *l );
PNS_LINE draggedLine( *l );
draggedLine->DragCorner( aP, 0 ); draggedLine.DragCorner( aP, 0 );
draggedLine->ClearSegmentLinks(); draggedLine.ClearSegmentLinks();
m_draggedItems.Add( draggedLine ); // FIXME: mem leak m_draggedItems.Add( draggedLine );
m_lastNode->Remove( &origLine ); 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 SEGMENT:
case CORNER: case CORNER:
{ {
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0; int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
PNS_LINE tmp( *m_draggedLine ); PNS_LINE tmp( m_draggedLine );
if( m_mode == SEGMENT ) if( m_mode == SEGMENT )
tmp.DragSegment( aP, m_draggedSegmentIndex, thresh ); tmp.DragSegment( aP, m_draggedSegmentIndex, thresh );

View File

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

View File

@ -40,13 +40,60 @@ enum LineMarker {
MK_DP_COUPLED = ( 1 << 5 ) 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 * Class PNS_ITEM
* *
* Base class for PNS router board items. Implements the shared properties of all PCB items - * Base class for PNS router board items. Implements the shared properties of all PCB items -
* net, spanned layers, geometric shape & refererence to owning model. * net, spanned layers, geometric shape & refererence to owning model.
*/ */
class PNS_ITEM class PNS_ITEM : public PNS_OBJECT
{ {
public: public:
static const int UnusedNet = INT_MAX; static const int UnusedNet = INT_MAX;
@ -226,34 +273,6 @@ public:
return Layers().Overlaps( aOther->Layers() ); 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() * Function Collide()
* *
@ -337,7 +356,6 @@ protected:
PnsKind m_kind; PnsKind m_kind;
BOARD_CONNECTED_ITEM* m_parent; BOARD_CONNECTED_ITEM* m_parent;
PNS_NODE* m_owner;
PNS_LAYERSET m_layers; PNS_LAYERSET m_layers;
bool m_movable; bool m_movable;

View File

@ -21,22 +21,40 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include "pns_itemset.h" #include "pns_itemset.h"
#include "pns_line.h"
PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM* aInitialItem ) :
m_owner( false ) void PNS_ITEMSET::release()
{ {
if( aInitialItem ) BOOST_FOREACH( PNS_ITEM* item, m_items )
m_items.push_back( aInitialItem ); {
if( item->BelongsTo( this ) )
delete item;
}
m_items.clear();
} }
PNS_ITEMSET::~PNS_ITEMSET() PNS_ITEMSET::~PNS_ITEMSET()
{ {
if( m_owner ) release();
{ }
BOOST_FOREACH( PNS_ITEM* item, m_items )
delete item;
} 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, * Holds a list of board items, that can be filtered against net, kinds,
* layers, etc. * layers, etc.
**/ **/
class PNS_LINE;
class PNS_ITEMSET class PNS_ITEMSET : public PNS_OBJECT
{ {
public: public:
typedef std::deque<PNS_ITEM*> ITEMS; typedef std::deque<PNS_ITEM*> ITEMS;
PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL ); PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL, bool aBecomeOwner = false )
PNS_ITEMSET( const PNS_ITEMSET& aOther ):
m_owner( 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(); ~PNS_ITEMSET();
void MakeOwner()
{
m_owner = true;
}
const PNS_ITEMSET& operator=( const PNS_ITEMSET& aOther ) const PNS_ITEMSET& operator=( const PNS_ITEMSET& aOther )
{ {
m_items = aOther.m_items; copyFrom( aOther );
return *this; return *this;
} }
int Count( int aKindMask = -1 ) const int Count( int aKindMask = -1 ) const
{ {
int n = 0; int n = 0;
BOOST_FOREACH( PNS_ITEM* item, m_items ) BOOST_FOREACH( PNS_ITEM* item, m_items )
{ {
if( item->Kind() & aKindMask ) if( item->Kind() & aKindMask )
n++; n++;
} }
return n; return n;
} }
bool Empty() const
{
return m_items.empty();
}
ITEMS& Items() { return m_items; } ITEMS& Items() { return m_items; }
const ITEMS& CItems() const { return m_items; } const ITEMS& CItems() const { return m_items; }
@ -100,13 +111,22 @@ public:
return m_items.size(); 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 ); 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 ); m_items.push_front( aItem );
} }
@ -122,6 +142,12 @@ public:
void Clear() void Clear()
{ {
BOOST_FOREACH( PNS_ITEM *item, m_items )
{
if( item->BelongsTo( this ) )
delete item;
}
m_items.clear(); m_items.clear();
} }
@ -130,17 +156,53 @@ public:
return std::find( m_items.begin(), m_items.end(), aItem ) != m_items.end(); 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 ); ITEMS::iterator f = std::find( m_items.begin(), m_items.end(), aItem );
if( f != m_items.end() ) if( f != m_items.end() )
m_items.erase( f ); 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: 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; ITEMS m_items;
bool m_owner;
}; };
#endif #endif

View File

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

View File

@ -115,7 +115,9 @@ int PNS_LINE::Marker() const
if( m_segmentRefs ) if( m_segmentRefs )
{ {
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs ) BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
{
marker |= s->Marker(); marker |= s->Marker();
}
} }
return marker; return marker;
@ -293,6 +295,9 @@ bool PNS_LINE::Is45Degree()
{ {
const SEG& s = m_line.CSegment( i ); const SEG& s = m_line.CSegment( i );
if( s.Length() < 10 )
continue;
double angle = 180.0 / M_PI * double angle = 180.0 / M_PI *
atan2( (double) s.B.y - (double) s.A.y, atan2( (double) s.B.y - (double) s.A.y,
(double) s.B.x - (double) s.A.x ); (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; return;
PNS_SEGMENT* s_old = static_cast<PNS_SEGMENT*>( aSeg ); PNS_SEGMENT* s_old = static_cast<PNS_SEGMENT*>( aSeg );
PNS_SEGMENT* s_new[2]; PNS_SEGMENT* s_new[2];
s_new[0] = s_old->Clone(); s_new[0] = s_old->Clone();
@ -814,7 +813,7 @@ bool PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem )
int eiDepth = -1; int eiDepth = -1;
if( aEndItem && aEndItem->Owner() ) if( aEndItem && aEndItem->Owner() )
eiDepth = aEndItem->Owner()->Depth(); eiDepth = static_cast<PNS_NODE*>( aEndItem->Owner() )->Depth();
if( m_lastNode ) 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 ) ); splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
if( Settings().RemoveLoops() ) if( Settings().RemoveLoops() )
removeLoops( m_lastNode, &current ); removeLoops( m_lastNode, current );
} }
updateLeadingRatLine(); 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; return;
if ( aLatest->CLine().CPoint( 0 ) == aLatest->CLine().CPoint( -1 ) ) if ( aLatest.CLine().CPoint( 0 ) == aLatest.CLine().CPoint( -1 ) )
return; 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_SEGMENT* seg = ( *aLatest.LinkedSegments() )[s];
PNS_LINE* ourLine = aNode->AssembleLine( seg ); PNS_LINE ourLine = aNode->AssembleLine( seg );
PNS_JOINT a, b; PNS_JOINT a, b;
std::vector<PNS_LINE*> lines; std::vector<PNS_LINE> lines;
aNode->FindLineEnds( ourLine, a, b ); aNode->FindLineEnds( ourLine, a, b );
@ -958,42 +957,38 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
int removedCount = 0; int removedCount = 0;
int total = 0; int total = 0;
BOOST_FOREACH( PNS_LINE* line, lines ) BOOST_FOREACH( PNS_LINE& line, lines )
{ {
total++; total++;
if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() ) if( !( line.ContainsSegment( seg ) ) && line.SegmentCount() )
{ {
aNode->Remove( line ); aNode->Remove( &line );
removedCount++; removedCount++;
} }
} }
TRACE( 0, "total segs removed: %d/%d\n", removedCount % total ); 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 ) void PNS_LINE_PLACER::simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest )
{ {
PNS_LINE* l = aNode->AssembleLine( aLatest ); PNS_LINE l = aNode->AssembleLine( aLatest );
SHAPE_LINE_CHAIN simplified ( l->CLine() ); SHAPE_LINE_CHAIN simplified( l.CLine() );
simplified.Simplify(); simplified.Simplify();
if( simplified.PointCount() != l->PointCount() ) if( simplified.PointCount() != l.PointCount() )
{ {
std::auto_ptr<PNS_LINE> lnew( l->Clone() ); PNS_LINE lnew( l );
aNode->Remove( l ); aNode->Remove( &l );
lnew->SetShape( simplified ); lnew.SetShape( simplified );
aNode->Add( lnew.get() ); aNode->Add( &lnew );
} }
delete l;
} }

View File

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

View File

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

View File

@ -100,7 +100,7 @@ protected:
///> Current world state ///> Current world state
PNS_NODE* m_currentNode; PNS_NODE* m_currentNode;
PNS_LINE* m_originLine; PNS_LINE m_originLine;
PNS_LINE m_currentTrace; PNS_LINE m_currentTrace;
PNS_ITEMSET m_tunedPath; 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 ); p = m_initialSegment->Seg().NearestPoint( aP );
m_originLine = NULL;
m_currentNode = NULL; m_currentNode = NULL;
m_currentStart = p; 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_tunedPathP = topo.AssembleTrivialPath( m_originPair.PLine().GetLink( 0 ) );
m_tunedPathN = topo.AssembleTrivialPath( m_originPair.NLine().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 ); 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 ); m_coupledLength = itemsetLength( m_tunedPathN );
else else
m_coupledLength = itemsetLength( m_tunedPathP ); m_coupledLength = itemsetLength( m_tunedPathP );

View File

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

View File

@ -128,7 +128,7 @@ struct PNS_COLLISION_FILTER {
* - lightweight cloning/branching (for recursive optimization and shove * - lightweight cloning/branching (for recursive optimization and shove
* springback) * springback)
**/ **/
class PNS_NODE class PNS_NODE : public PNS_OBJECT
{ {
public: public:
typedef boost::optional<PNS_OBSTACLE> OPT_OBSTACLE; typedef boost::optional<PNS_OBSTACLE> OPT_OBSTACLE;
@ -303,7 +303,7 @@ public:
* @param aOriginSegmentIndex index of aSeg in the resulting line * @param aOriginSegmentIndex index of aSeg in the resulting line
* @return the 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 ///> Prints the contents and joints structure
void Dump( bool aLong = false ); void Dump( bool aLong = false );
@ -335,6 +335,8 @@ public:
*/ */
PNS_JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ); PNS_JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
void LockJoint( const VECTOR2I& aPos, const PNS_ITEM* aItem, bool aLock );
/** /**
* Function FindJoint() * Function FindJoint()
* *
@ -357,10 +359,10 @@ public:
///> finds all lines between a pair of joints. Used by the loop removal procedure. ///> finds all lines between a pair of joints. Used by the loop removal procedure.
int FindLinesBetweenJoints( PNS_JOINT& aA, int FindLinesBetweenJoints( PNS_JOINT& aA,
PNS_JOINT& aB, PNS_JOINT& aB,
std::vector<PNS_LINE*>& aLines ); std::vector<PNS_LINE>& aLines );
///> finds the joints corresponding to the ends of line aLine ///> 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. ///> Destroys all child nodes. Applicable only to the root node.
void KillChildren(); void KillChildren();
@ -410,6 +412,7 @@ private:
void doRemove( PNS_ITEM* aItem ); void doRemove( PNS_ITEM* aItem );
void unlinkParent(); void unlinkParent();
void releaseChildren(); void releaseChildren();
void releaseGarbage();
bool isRoot() const bool isRoot() const
{ {
@ -464,6 +467,8 @@ private:
///> optional collision filtering object ///> optional collision filtering object
PNS_COLLISION_FILTER *m_collisionFilter; PNS_COLLISION_FILTER *m_collisionFilter;
boost::unordered_set<PNS_ITEM*> m_garbageItems;
}; };
#endif #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 ) if( m_forceClearance >= 0 )
return m_forceClearance; 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( 0 ) == aNew->CPoint( 0 ) );
assert( aOld->CPoint( -1 ) == aNew->CPoint( -1 ) ); 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_forceClearance = -1;
m_root = aWorld; m_root = aWorld;
m_currentNode = aWorld;
// Initialize other temporary variables: // Initialize other temporary variables:
m_currentNode = NULL;
m_draggedVia = NULL; m_draggedVia = NULL;
m_iter = 0; m_iter = 0;
m_multiLineMode = false; m_multiLineMode = false;
@ -89,76 +89,68 @@ PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) :
PNS_SHOVE::~PNS_SHOVE() 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 ); return m_currentNode->AssembleLine( const_cast<PNS_SEGMENT*>( aSeg ), aIndex );
m_gcItems.push_back( l );
return l;
} }
// A dumb function that checks if the shoved line is shoved the right way, e.g. // 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 // 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: // 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. // 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 += aCurrent.Width() / 2;
dist += aShoved->Width() / 2; dist += aShoved.Width() / 2;
const VECTOR2I ps = ss.A - ( ss.B - ss.A ).Resize( dist ); 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_SHOVE::SHOVE_STATUS PNS_SHOVE::walkaroundLoneVia( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE* aShoved ) PNS_LINE& aShoved )
{ {
int clearance = getClearance( aCurrent, aObstacle ); int clearance = getClearance( &aCurrent, &aObstacle );
const SHAPE_LINE_CHAIN hull = aCurrent->Via().Hull( clearance, aObstacle->Width() ); const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width() );
SHAPE_LINE_CHAIN path_cw, path_ccw; SHAPE_LINE_CHAIN path_cw, path_ccw;
aObstacle->Walkaround( hull, path_cw, true ); aObstacle.Walkaround( hull, path_cw, true );
aObstacle->Walkaround( hull, path_ccw, false ); aObstacle.Walkaround( hull, path_ccw, false );
const SHAPE_LINE_CHAIN& shortest = path_ccw.Length() < path_cw.Length() ? path_ccw : path_cw; const SHAPE_LINE_CHAIN& shortest = path_ccw.Length() < path_cw.Length() ? path_ccw : path_cw;
if( shortest.PointCount() < 2 ) if( shortest.PointCount() < 2 )
return SH_INCOMPLETE; return SH_INCOMPLETE;
if( aObstacle->CPoint( -1 ) != shortest.CPoint( -1 ) ) if( aObstacle.CPoint( -1 ) != shortest.CPoint( -1 ) )
return SH_INCOMPLETE; return SH_INCOMPLETE;
if( aObstacle->CPoint( 0 ) != shortest.CPoint( 0 ) ) if( aObstacle.CPoint( 0 ) != shortest.CPoint( 0 ) )
return SH_INCOMPLETE; 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_INCOMPLETE;
return SH_OK; return SH_OK;
} }
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE* aShoved, const HULL_SET& aHulls ) PNS_LINE& aShoved, const HULL_SET& aHulls )
{ {
const SHAPE_LINE_CHAIN& obs = aObstacle->CLine(); const SHAPE_LINE_CHAIN& obs = aObstacle.CLine();
bool failingDirCheck = false; bool failingDirCheck = false;
int attempt; int attempt;
@ -169,7 +161,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
int vFirst = -1, vLast = -1; int vFirst = -1, vLast = -1;
SHAPE_LINE_CHAIN path; SHAPE_LINE_CHAIN path;
PNS_LINE l( *aObstacle ); PNS_LINE l( aObstacle );
for( int i = 0; i < (int) aHulls.size(); i++ ) 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 ); TRACE( 100, "attempt %d fail vfirst-last", attempt );
continue; continue;
@ -211,11 +203,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue; continue;
} }
if( !checkBumpDirection( aCurrent, &l ) ) if( !checkBumpDirection( aCurrent, l ) )
{ {
TRACE( 100, "attempt %d fail direction-check", attempt ); TRACE( 100, "attempt %d fail direction-check", attempt );
failingDirCheck = true; failingDirCheck = true;
aShoved->SetShape( l.CLine() ); aShoved.SetShape( l.CLine() );
continue; continue;
} }
@ -226,11 +218,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue; 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() ) BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() )
{ {
@ -245,7 +237,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE* aCurrent, PNS_LINE*
continue; continue;
} }
aShoved->SetShape( l.CLine() ); aShoved.SetShape( l.CLine() );
return SH_OK; 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_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE* aShoved ) PNS_LINE& aShoved )
{ {
aShoved->ClearSegmentLinks(); aShoved.ClearSegmentLinks();
bool obstacleIsHead = false; 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 ) if( s->Marker() & MK_HEAD )
{ {
@ -274,18 +266,18 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE* aCurrent, PNS_LI
SHOVE_STATUS rv; 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 ); rv = walkaroundLoneVia( aCurrent, aObstacle, aShoved );
} }
else else
{ {
int w = aObstacle->Width(); int w = aObstacle.Width();
int n_segs = aCurrent->SegmentCount(); int n_segs = aCurrent.SegmentCount();
int clearance = getClearance( aCurrent, aObstacle ); int clearance = getClearance( &aCurrent, &aObstacle );
HULL_SET hulls; 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++ ) for( int i = 0; i < n_segs; i++ )
{ {
PNS_SEGMENT seg( *aCurrent, aCurrent->CSegment( i ) ); PNS_SEGMENT seg( aCurrent, aCurrent.CSegment( i ) );
hulls.push_back( seg.Hull( clearance, w ) ); SHAPE_LINE_CHAIN hull = seg.Hull( clearance, w );
hulls.push_back( hull );
} }
if( viaOnEnd ) if( viaOnEnd )
hulls.push_back ( aCurrent->Via().Hull( clearance, w ) ); hulls.push_back ( aCurrent.Via().Hull( clearance, w ) );
rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls ); rv = processHullSet ( aCurrent, aObstacle, aShoved, hulls );
} }
if( obstacleIsHead ) if( obstacleIsHead )
aShoved->Mark( aShoved->Marker() | MK_HEAD ); aShoved.Mark( aShoved.Marker() | MK_HEAD );
return rv; 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; int segIndex;
PNS_LINE* obstacleLine = assembleLine( aObstacleSeg, &segIndex ); PNS_LINE obstacleLine = assembleLine( aObstacleSeg, &segIndex );
PNS_LINE* shovedLine = clone( obstacleLine ); PNS_LINE shovedLine( obstacleLine );
PNS_SEGMENT tmp( *aObstacleSeg );
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, obstacleLine, shovedLine ); SHOVE_STATUS rv = ProcessSingleLine( aCurrent, obstacleLine, shovedLine );
assert( obstacleLine->LayersOverlap( 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;
}
#ifdef DEBUG #ifdef DEBUG
m_logger.NewGroup( "on-colliding-segment", m_iter ); m_logger.NewGroup( "on-colliding-segment", m_iter );
m_logger.Log( aObstacleSeg, 0, "obstacle-segment" ); m_logger.Log( &tmp, 0, "obstacle-segment" );
m_logger.Log( aCurrent, 1, "current-line" ); m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( obstacleLine, 2, "obstacle-line" ); m_logger.Log( &obstacleLine, 2, "obstacle-line" );
m_logger.Log( shovedLine, 3, "shoved-line" ); m_logger.Log( &shovedLine, 3, "shoved-line" );
#endif #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( rv == SH_OK )
{ {
if( shovedLine->Marker() & MK_HEAD ) if( shovedLine.Marker() & MK_HEAD )
{ {
if( m_multiLineMode ) if( m_multiLineMode )
return SH_INCOMPLETE; return SH_INCOMPLETE;
m_newHead = *shovedLine; m_newHead = shovedLine;
} }
sanityCheck( aObstacle, shovedLine ); sanityCheck( &obstacleLine, &shovedLine );
replaceItems( aObstacle, shovedLine ); replaceItems( &obstacleLine, &shovedLine );
sanityCheck( aObstacle, shovedLine );
int rank = aObstacle->Rank(); int rank = aCurrent.Rank();
shovedLine->SetRank ( rank ); shovedLine.SetRank( rank - 1 );
if( !pushLine( shovedLine ) ) if( !pushLine( shovedLine ) )
rv = SH_INCOMPLETE; 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; 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_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_VIA* via = NULL;
PNS_JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), aCurrent ); PNS_JOINT* jtStart = m_currentNode->FindJoint( vh.Pos(), &aCurrent );
if( !jtStart ) if( !jtStart )
return SH_INCOMPLETE; return SH_INCOMPLETE;
@ -421,7 +418,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOL
walkaround.SetSolidsOnly( true ); walkaround.SetSolidsOnly( true );
walkaround.SetIterationLimit ( 8 ); // fixme: make configurable walkaround.SetIterationLimit ( 8 ); // fixme: make configurable
int currentRank = aCurrent->Rank(); int currentRank = aCurrent.Rank();
int nextRank; int nextRank;
if( !Settings().JumpOverObstacles() ) if( !Settings().JumpOverObstacles() )
@ -435,34 +432,35 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE* aCurrent, PNS_SOL
walkaround.SetSingleDirection( true ); walkaround.SetSingleDirection( true );
} }
if( walkaround.Route( *aCurrent, *walkaroundLine, false ) != PNS_WALKAROUND::DONE ) if( walkaround.Route( aCurrent, walkaroundLine, false ) != PNS_WALKAROUND::DONE )
return SH_INCOMPLETE; return SH_INCOMPLETE;
walkaroundLine->ClearSegmentLinks(); walkaroundLine.ClearSegmentLinks();
walkaroundLine->Unmark(); walkaroundLine.Unmark();
walkaroundLine->Line().Simplify(); walkaroundLine.Line().Simplify();
if( walkaroundLine->HasLoops() ) if( walkaroundLine.HasLoops() )
return SH_INCOMPLETE; return SH_INCOMPLETE;
if( aCurrent->Marker() & MK_HEAD ) if( aCurrent.Marker() & MK_HEAD )
{ {
walkaroundLine->Mark( MK_HEAD ); walkaroundLine.Mark( MK_HEAD );
if(m_multiLineMode) if( m_multiLineMode )
return SH_INCOMPLETE; return SH_INCOMPLETE;
m_newHead = *walkaroundLine; m_newHead = walkaroundLine;
} }
replaceItems ( aCurrent, walkaroundLine ); sanityCheck( &aCurrent, &walkaroundLine );
walkaroundLine->SetRank( nextRank ); replaceItems( &aCurrent, &walkaroundLine );
walkaroundLine.SetRank( nextRank );
#ifdef DEBUG #ifdef DEBUG
m_logger.NewGroup( "on-colliding-solid", m_iter ); m_logger.NewGroup( "on-colliding-solid", m_iter );
m_logger.Log( aObstacleSolid, 0, "obstacle-solid" ); m_logger.Log( aObstacleSolid, 0, "obstacle-solid" );
m_logger.Log( aCurrent, 1, "current-line" ); m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( walkaroundLine, 3, "walk-line" ); m_logger.Log( &walkaroundLine, 3, "walk-line" );
#endif #endif
popLine(); 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 ); PNS_JOINT* jt = m_currentNode->FindJoint( p0, aVia );
VECTOR2I p0_pushed( p0 + aForce ); VECTOR2I p0_pushed( p0 + aForce );
if( jt->IsLocked() )
return SH_INCOMPLETE;
while( aForce.x != 0 || aForce.y != 0 ) while( aForce.x != 0 || aForce.y != 0 )
{ {
PNS_JOINT* jt_next = m_currentNode->FindJoint( p0_pushed, aVia ); 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 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(); PNS_VIA* pushedVia = aVia->Clone();
pushedVia->SetPos( p0_pushed ); pushedVia->SetPos( p0_pushed );
pushedVia->Mark( aVia->Marker() ); pushedVia->Mark( aVia->Marker() );
@ -552,12 +559,6 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
m_draggedViaHeadSet.Clear(); 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() ) BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() )
{ {
if( PNS_SEGMENT* seg = dyn_cast<PNS_SEGMENT*>( item ) ) 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 ); lp.first = assembleLine( seg, &segIndex );
assert( segIndex == 0 || ( segIndex == ( lp.first->SegmentCount() - 1 ) ) ); assert( segIndex == 0 || ( segIndex == ( lp.first.SegmentCount() - 1 ) ) );
if( segIndex == 0 ) if( segIndex == 0 )
lp.first->Reverse(); lp.first.Reverse();
lp.second = clone( lp.first ); lp.second = lp.first;
lp.second->ClearSegmentLinks(); lp.second.ClearSegmentLinks();
lp.second->DragCorner( p0_pushed, lp.second->CLine().Find( p0 ) ); lp.second.DragCorner( p0_pushed, lp.second.CLine().Find( p0 ) );
lp.second->AppendVia( *pushedVia ); lp.second.AppendVia( *pushedVia );
draggedLines.push_back( lp ); draggedLines.push_back( lp );
if( aVia->Marker() & MK_HEAD ) 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" ); m_logger.Log( aVia, 0, "obstacle-via" );
#endif #endif
if( aVia->BelongsTo( m_currentNode ) )
delete aVia;
pushedVia->SetRank( aCurrentRank - 1 ); pushedVia->SetRank( aCurrentRank - 1 );
#ifdef DEBUG #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 ) 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 ) if ( m_multiLineMode )
return SH_INCOMPLETE; 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 ); replaceItems( &lp.first, &lp.second );
lp.second->SetRank( aCurrentRank - 1 ); lp.second.SetRank( aCurrentRank - 1 );
if( !pushLine( lp.second ) ) if( !pushLine( lp.second ) )
return SH_INCOMPLETE; return SH_INCOMPLETE;
} }
else else
m_currentNode->Remove( lp.first ); {
m_currentNode->Remove( &lp.first );
}
#ifdef DEBUG #ifdef DEBUG
m_logger.Log( lp.first, 2, "fan-pre" ); m_logger.Log( &lp.first, 2, "fan-pre" );
m_logger.Log( lp.second, 3, "fan-post" ); m_logger.Log( &lp.second, 3, "fan-post" );
#endif #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; int n = 0;
PNS_LINE* cur = clone( aCurrent ); PNS_LINE cur( aCurrent );
cur->ClearSegmentLinks(); cur.ClearSegmentLinks();
PNS_JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia ); PNS_JOINT* jt = m_currentNode->FindJoint( aObstacleVia->Pos(), aObstacleVia );
PNS_LINE* shoved = clone( aCurrent ); PNS_LINE shoved( aCurrent );
shoved->ClearSegmentLinks(); shoved.ClearSegmentLinks();
cur->RemoveVia(); cur.RemoveVia();
unwindStack( aCurrent ); unwindStack( &aCurrent );
BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() ) 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_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 ); SHOVE_STATUS st = ProcessSingleLine( head, cur, shoved );
@ -717,14 +716,14 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PN
#ifdef DEBUG #ifdef DEBUG
m_logger.NewGroup( "on-reverse-via-fail-shove", m_iter ); m_logger.NewGroup( "on-reverse-via-fail-shove", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" ); m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" ); m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( shoved, 3, "shoved-line" ); m_logger.Log( &shoved, 3, "shoved-line" );
#endif #endif
return st; return st;
} }
cur->SetShape( shoved->CLine() ); cur.SetShape( shoved.CLine() );
n++; n++;
} }
} }
@ -734,38 +733,38 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onReverseCollidingVia( PNS_LINE* aCurrent, PN
#ifdef DEBUG #ifdef DEBUG
m_logger.NewGroup( "on-reverse-via-fail-lonevia", m_iter ); m_logger.NewGroup( "on-reverse-via-fail-lonevia", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" ); m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" ); m_logger.Log( &aCurrent, 1, "current-line" );
#endif #endif
PNS_LINE head( *aCurrent ); PNS_LINE head( aCurrent );
head.Line().Clear(); head.Line().Clear();
head.AppendVia( *aObstacleVia ); head.AppendVia( *aObstacleVia );
head.ClearSegmentLinks(); head.ClearSegmentLinks();
SHOVE_STATUS st = ProcessSingleLine( &head, aCurrent, shoved ); SHOVE_STATUS st = ProcessSingleLine( head, aCurrent, shoved );
if( st != SH_OK ) if( st != SH_OK )
return st; return st;
cur->SetShape( shoved->CLine() ); cur.SetShape( shoved.CLine() );
} }
if( aCurrent->EndsWithVia() ) if( aCurrent.EndsWithVia() )
shoved->AppendVia( aCurrent->Via() ); shoved.AppendVia( aCurrent.Via() );
#ifdef DEBUG #ifdef DEBUG
m_logger.NewGroup( "on-reverse-via", m_iter ); m_logger.NewGroup( "on-reverse-via", m_iter );
m_logger.Log( aObstacleVia, 0, "the-via" ); m_logger.Log( aObstacleVia, 0, "the-via" );
m_logger.Log( aCurrent, 1, "current-line" ); m_logger.Log( &aCurrent, 1, "current-line" );
m_logger.Log( shoved, 3, "shoved-line" ); m_logger.Log( &shoved, 3, "shoved-line" );
#endif #endif
int currentRank = aCurrent->Rank(); int currentRank = aCurrent.Rank();
replaceItems( aCurrent, shoved ); replaceItems( &aCurrent, &shoved );
if ( !pushLine( shoved ) ) if ( !pushLine( shoved ) )
return SH_INCOMPLETE; return SH_INCOMPLETE;
shoved->SetRank( currentRank ); shoved.SetRank( currentRank );
return SH_OK; 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 ) 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 ); i = m_lineStack.erase( i );
else else
i++; 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 ); i = m_optimizerQueue.erase( i );
else else
i++; 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; return false;
m_lineStack.push_back( aL ); m_lineStack.push_back( aL );
@ -819,18 +818,28 @@ bool PNS_SHOVE::pushLine( PNS_LINE* aL )
return true; return true;
} }
void PNS_SHOVE::popLine( ) 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() )
{ {
i = m_optimizerQueue.erase( i ); if( i->ContainsSegment( s ) )
{
i = m_optimizerQueue.erase( i );
found = true;
break;
}
} }
else
if( !found )
i++; i++;
} }
@ -840,7 +849,7 @@ void PNS_SHOVE::popLine( )
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter ) 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; PNS_NODE::OPT_OBSTACLE nearest;
SHOVE_STATUS st = SH_NULL; 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++ ) 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 ) if( nearest )
break; break;
@ -864,7 +873,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
unwindStack( ni ); 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() ) switch( ni->Kind() )
{ {
@ -873,7 +882,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
PNS_VIA* revVia = (PNS_VIA*) ni; PNS_VIA* revVia = (PNS_VIA*) ni;
TRACE( 2, "iter %d: reverse-collide-via", aIter ); 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; st = SH_INCOMPLETE;
} }
@ -889,7 +898,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
{ {
PNS_SEGMENT* seg = (PNS_SEGMENT*) ni; PNS_SEGMENT* seg = (PNS_SEGMENT*) ni;
TRACE( 2, "iter %d: reverse-collide-segment ", aIter ); TRACE( 2, "iter %d: reverse-collide-segment ", aIter );
PNS_LINE* revLine = assembleLine( seg ); PNS_LINE revLine = assembleLine( seg );
popLine(); popLine();
st = onCollidingLine( revLine, currentLine ); st = onCollidingLine( revLine, currentLine );
@ -914,7 +923,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
TRACE( 2, "iter %d: shove-via ", aIter ); TRACE( 2, "iter %d: shove-via ", aIter );
st = onCollidingVia( currentLine, (PNS_VIA*) ni ); st = onCollidingVia( &currentLine, (PNS_VIA*) ni );
break; break;
case PNS_ITEM::SOLID: case PNS_ITEM::SOLID:
@ -988,22 +997,20 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
m_multiLineMode = false; m_multiLineMode = false;
// empty head? nothing to shove... // empty head? nothing to shove...
if( !aCurrentHead.SegmentCount() && !aCurrentHead.EndsWithVia() ) if( !aCurrentHead.SegmentCount() && !aCurrentHead.EndsWithVia() )
return SH_INCOMPLETE; return SH_INCOMPLETE;
PNS_LINE* head = clone( &aCurrentHead ); PNS_LINE head( aCurrentHead );
head.ClearSegmentLinks();
if( !head )
return SH_INCOMPLETE;
head->ClearSegmentLinks();
m_lineStack.clear(); m_lineStack.clear();
m_optimizerQueue.clear(); m_optimizerQueue.clear();
m_newHead = OPT_LINE(); m_newHead = OPT_LINE();
m_logger.Clear(); m_logger.Clear();
PNS_ITEMSET headSet( clone( &aCurrentHead ) ); PNS_ITEMSET headSet;
headSet.Add( aCurrentHead );
reduceSpringback( headSet ); reduceSpringback( headSet );
@ -1011,19 +1018,24 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveLines( const PNS_LINE& aCurrentHead )
m_currentNode = parent->Branch(); m_currentNode = parent->Branch();
m_currentNode->ClearRanks(); m_currentNode->ClearRanks();
m_currentNode->Add( head ); m_currentNode->Add( &head );
head->Mark( MK_HEAD ); m_currentNode->LockJoint( head.CPoint(0), &head, true );
head->SetRank( 100000 );
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.NewGroup( "initial", 0 );
m_logger.Log( head, 0, "head" ); m_logger.Log( &head, 0, "head" );
PNS_VIA* headVia = NULL; PNS_VIA* headVia = NULL;
if( head->EndsWithVia() ) if( head.EndsWithVia() )
{ {
headVia = head->Via().Clone(); headVia = head.Via().Clone();
m_currentNode->Add( headVia ); m_currentNode->Add( headVia );
headVia->Mark( MK_HEAD ); headVia->Mark( MK_HEAD );
headVia->SetRank( 100000 ); 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 ) ) if( ( st == SH_OK || st == SH_HEAD_MODIFIED ) )
runOptimizer( m_currentNode, head ); runOptimizer( m_currentNode );
if( m_newHead && st == SH_OK ) if( m_newHead && st == SH_OK )
{ {
@ -1081,7 +1093,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
if( !headOrig->SegmentCount() ) if( !headOrig->SegmentCount() )
return SH_INCOMPLETE; return SH_INCOMPLETE;
headSet.Add( clone( headOrig ) ); headSet.Add( *headOrig );
} }
m_lineStack.clear(); m_lineStack.clear();
@ -1095,25 +1107,26 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
m_currentNode = parent->Branch(); m_currentNode = parent->Branch();
m_currentNode->ClearRanks(); m_currentNode->ClearRanks();
int n = 0; int n = 0;
BOOST_FOREACH ( const PNS_ITEM* item, aHeadSet.CItems() ) BOOST_FOREACH ( const PNS_ITEM* item, aHeadSet.CItems() )
{ {
const PNS_LINE* headOrig = static_cast<const PNS_LINE*>( item ); const PNS_LINE* headOrig = static_cast<const PNS_LINE*>( item );
PNS_LINE* head = clone( headOrig ); PNS_LINE head( *headOrig );
head->ClearSegmentLinks(); head.ClearSegmentLinks();
m_currentNode->Add( head ); m_currentNode->Add( &head );
head->Mark( MK_HEAD ); head.Mark( MK_HEAD );
head->SetRank( 100000 ); head.SetRank( 100000 );
n++; n++;
if ( !pushLine( head ) ) if ( !pushLine( head ) )
return SH_INCOMPLETE; return SH_INCOMPLETE;
PNS_VIA* headVia = NULL; 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 ); m_currentNode->Add( headVia );
headVia->Mark( MK_HEAD ); headVia->Mark( MK_HEAD );
headVia->SetRank( 100000 ); headVia->SetRank( 100000 );
@ -1127,7 +1140,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ShoveMultiLines( const PNS_ITEMSET& aHeadSet
st = shoveMainLoop(); st = shoveMainLoop();
if( st == SH_OK ) if( st == SH_OK )
runOptimizer( m_currentNode, NULL ); runOptimizer( m_currentNode );
m_currentNode->RemoveByMarker( MK_HEAD ); 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; PNS_NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node;
m_currentNode = parent; 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; 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(); st = shoveMainLoop();
if( st == SH_OK ) if( st == SH_OK )
runOptimizer( m_currentNode, NULL ); runOptimizer( m_currentNode );
if( st == SH_OK || st == SH_HEAD_MODIFIED ) 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 ); PNS_OPTIMIZER optimizer( aNode );
int optFlags = 0, n_passes = 0; int optFlags = 0, n_passes = 0;
@ -1207,10 +1218,10 @@ void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead )
int maxWidth = 0; 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 ) i != m_optimizerQueue.end(); ++i )
{ {
maxWidth = std::max( (*i)->Width(), maxWidth ); maxWidth = std::max( i->Width(), maxWidth );
} }
if( area ) if( area )
@ -1253,20 +1264,20 @@ void PNS_SHOVE::runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead )
{ {
std::reverse( m_optimizerQueue.begin(), m_optimizerQueue.end() ); 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 ) 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; PNS_LINE optimized;
if( optimizer.Optimize( line, &optimized ) ) if( optimizer.Optimize( &line, &optimized ) )
{ {
aNode->Remove( line ); aNode->Remove( &line );
line->SetShape( optimized.CLine() ); line.SetShape( optimized.CLine() );
aNode->Add( line ); 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 = 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 ShoveMultiLines( const PNS_ITEMSET& aHeadSet );
SHOVE_STATUS ShoveDraggingVia( PNS_VIA* aVia, const VECTOR2I& aWhere, PNS_VIA** aNewVia ); SHOVE_STATUS ShoveDraggingVia( PNS_VIA* aVia, const VECTOR2I& aWhere, PNS_VIA** aNewVia );
SHOVE_STATUS ProcessSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle, SHOVE_STATUS ProcessSingleLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE* aShoved ); PNS_LINE& aShoved );
void ForceClearance ( bool aEnabled, int aClearance ) void ForceClearance ( bool aEnabled, int aClearance )
{ {
@ -79,12 +79,12 @@ public:
const PNS_LINE NewHead() const; const PNS_LINE NewHead() const;
void SetInitialLine( PNS_LINE* aInitial ); void SetInitialLine( PNS_LINE& aInitial );
private: private:
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET; typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
typedef boost::optional<PNS_LINE> OPT_LINE; 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; typedef std::vector<LINE_PAIR> LINE_PAIR_VEC;
struct SPRINGBACK_TAG struct SPRINGBACK_TAG
@ -98,21 +98,21 @@ private:
OPT_BOX2I m_affectedArea; OPT_BOX2I m_affectedArea;
}; };
SHOVE_STATUS processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle, SHOVE_STATUS processHullSet( PNS_LINE& aCurrent, PNS_LINE& aObstacle,
PNS_LINE* aShoved, const HULL_SET& hulls ); PNS_LINE& aShoved, const HULL_SET& hulls );
bool reduceSpringback( const PNS_ITEMSET& aHeadItems ); bool reduceSpringback( const PNS_ITEMSET& aHeadItems );
bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems, bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET& aHeadItems,
const PNS_COST_ESTIMATOR& aCost, const OPT_BOX2I& aAffectedArea ); const PNS_COST_ESTIMATOR& aCost, const OPT_BOX2I& aAffectedArea );
SHOVE_STATUS walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved ); SHOVE_STATUS walkaroundLoneVia( PNS_LINE& aCurrent, PNS_LINE& aObstacle, PNS_LINE& aShoved );
bool checkBumpDirection( PNS_LINE* aCurrent, PNS_LINE* aShoved ) const; bool checkBumpDirection( const PNS_LINE& aCurrent, const PNS_LINE& aShoved ) const;
SHOVE_STATUS onCollidingLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle ); SHOVE_STATUS onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle );
SHOVE_STATUS onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg ); SHOVE_STATUS onCollidingSegment( PNS_LINE& aCurrent, PNS_SEGMENT* aObstacleSeg );
SHOVE_STATUS onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid ); SHOVE_STATUS onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid );
SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia ); 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 ); SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank, bool aDryRun = false );
OPT_BOX2I totalAffectedArea() const; OPT_BOX2I totalAffectedArea() const;
@ -120,34 +120,25 @@ private:
void unwindStack( PNS_SEGMENT* aSeg ); void unwindStack( PNS_SEGMENT* aSeg );
void unwindStack( PNS_ITEM* aItem ); 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(); 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 ); 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; OPT_BOX2I m_affectedAreaSum;
SHOVE_STATUS shoveIteration( int aIter ); SHOVE_STATUS shoveIteration( int aIter );
SHOVE_STATUS shoveMainLoop(); 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<SPRINGBACK_TAG> m_nodeStack;
std::vector<PNS_LINE*> m_lineStack; std::vector<PNS_LINE> m_lineStack;
std::vector<PNS_LINE*> m_optimizerQueue; std::vector<PNS_LINE> m_optimizerQueue;
std::vector<PNS_ITEM*> m_gcItems;
PNS_NODE* m_root; PNS_NODE* m_root;
PNS_NODE* m_currentNode; PNS_NODE* m_currentNode;
@ -161,6 +152,7 @@ private:
int m_iter; int m_iter;
int m_forceClearance; int m_forceClearance;
bool m_multiLineMode; bool m_multiLineMode;
void sanityCheck( PNS_LINE* aOld, PNS_LINE* aNew );
}; };
#endif // __PNS_SHOVE_H #endif // __PNS_SHOVE_H

View File

@ -49,7 +49,7 @@ int PNS_SIZES_SETTINGS::inheritTrackWidth( PNS_ITEM* aItem )
return 0; 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 ); assert( jt != NULL );

View File

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

View File

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