From 0fbf31ef38a62a08d6975a8f6e2c182f7e3a5969 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 3 Aug 2015 21:11:51 +0200 Subject: [PATCH] P&S: memory mgr & disappearing trace fixes. Still a bit buggy, though... --- pcbnew/router/pns_diff_pair_placer.cpp | 2 +- pcbnew/router/pns_dragger.cpp | 36 +- pcbnew/router/pns_dragger.h | 6 +- pcbnew/router/pns_item.h | 78 ++-- pcbnew/router/pns_itemset.cpp | 36 +- pcbnew/router/pns_itemset.h | 94 ++++- pcbnew/router/pns_joint.h | 31 +- pcbnew/router/pns_line.cpp | 5 + pcbnew/router/pns_line_placer.cpp | 47 +-- pcbnew/router/pns_line_placer.h | 2 +- pcbnew/router/pns_meander_placer.cpp | 16 +- pcbnew/router/pns_meander_placer.h | 2 +- pcbnew/router/pns_meander_skew_placer.cpp | 7 +- pcbnew/router/pns_node.cpp | 77 ++-- pcbnew/router/pns_node.h | 13 +- pcbnew/router/pns_shove.cpp | 479 +++++++++++----------- pcbnew/router/pns_shove.h | 46 +-- pcbnew/router/pns_sizes_settings.cpp | 2 +- pcbnew/router/pns_topology.cpp | 48 ++- pcbnew/router/router_tool.cpp | 2 +- 20 files changed, 594 insertions(+), 435 deletions(-) diff --git a/pcbnew/router/pns_diff_pair_placer.cpp b/pcbnew/router/pns_diff_pair_placer.cpp index 749e8060dd..a4f536ec5d 100644 --- a/pcbnew/router/pns_diff_pair_placer.cpp +++ b/pcbnew/router/pns_diff_pair_placer.cpp @@ -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; diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp index 9964040fb6..27b45d36d9 100644 --- a/pcbnew/router/pns_dragger.cpp +++ b/pcbnew/router/pns_dragger.cpp @@ -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 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( 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->Remove( &origLine ); + 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 ); diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h index ced82083d9..95384dd9e1 100644 --- a/pcbnew/router/pns_dragger.h +++ b/pcbnew/router/pns_dragger.h @@ -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 m_origViaConnections; - std::vector m_draggedViaConnections; + PNS_ITEMSET m_origViaConnections; + PNS_ITEMSET m_draggedViaConnections; PNS_VIA* m_initialVia; PNS_ITEMSET m_draggedItems; }; diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index cd53b76b61..339751e2de 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -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; diff --git a/pcbnew/router/pns_itemset.cpp b/pcbnew/router/pns_itemset.cpp index a21c645c57..65ce45a7b0 100644 --- a/pcbnew/router/pns_itemset.cpp +++ b/pcbnew/router/pns_itemset.cpp @@ -21,22 +21,40 @@ #include #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 ); } diff --git a/pcbnew/router/pns_itemset.h b/pcbnew/router/pns_itemset.h index 3f25f3d35d..f4264c1d67 100644 --- a/pcbnew/router/pns_itemset.h +++ b/pcbnew/router/pns_itemset.h @@ -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 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 + 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( 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 diff --git a/pcbnew/router/pns_joint.h b/pcbnew/router/pns_joint.h index 78cb36e4d2..9cb674dbf6 100644 --- a/pcbnew/router/pns_joint.h +++ b/pcbnew/router/pns_joint.h @@ -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( 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( 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 ) diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 45a95a49e6..35c839c752 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -115,7 +115,9 @@ 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 ); diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 2ea675f15a..0cab79133b 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -690,7 +690,6 @@ void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, co return; PNS_SEGMENT* s_old = static_cast( 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( 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, ¤t ); + 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 lines; + std::vector 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 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; } diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 285a21338a..0f3b4a7605 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -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() diff --git a/pcbnew/router/pns_meander_placer.cpp b/pcbnew/router/pns_meander_placer.cpp index b0f4baffd6..23145f0534 100644 --- a/pcbnew/router/pns_meander_placer.cpp +++ b/pcbnew/router/pns_meander_placer.cpp @@ -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 ); } diff --git a/pcbnew/router/pns_meander_placer.h b/pcbnew/router/pns_meander_placer.h index 227a0ce291..cbf667e57e 100644 --- a/pcbnew/router/pns_meander_placer.h +++ b/pcbnew/router/pns_meander_placer.h @@ -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; diff --git a/pcbnew/router/pns_meander_skew_placer.cpp b/pcbnew/router/pns_meander_skew_placer.cpp index be1ba85e01..b0c9236fa6 100644 --- a/pcbnew/router/pns_meander_skew_placer.cpp +++ b/pcbnew/router/pns_meander_skew_placer.cpp @@ -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 ); diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 6c2b15ac90..6487cea3b7 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -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* 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& aFo #endif -int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector& aLines ) +int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector& aLines ) { BOOST_FOREACH( PNS_ITEM* item, aA.LinkList() ) { if( item->Kind() == PNS_ITEM::SEGMENT ) { PNS_SEGMENT* seg = static_cast( 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(); } diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index 0f2fb49cb5..296932b14f 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -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 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& aLines ); + std::vector& 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 m_garbageItems; }; #endif diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 17dfe14d3c..14db9d0855 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -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( aSeg ), aIndex ); - - m_gcItems.push_back( l ); - - return l; + return m_currentNode->AssembleLine( const_cast( 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) + 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( 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 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::iterator i = m_lineStack.begin(); i != m_lineStack.end(); ) + for( std::vector::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::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + for( std::vector::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::iterator i = m_optimizerQueue.begin(); i != m_optimizerQueue.end(); ) + for( std::vector::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++; } @@ -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( ¤tLine, 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( ¤tLine->Via(), revVia ) ) + if( currentLine.EndsWithVia() && m_currentNode->CheckColliding( ¤tLine.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( ¤tLine, (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( 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::iterator i = m_optimizerQueue.begin(); + for( std::vector::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::iterator i = m_optimizerQueue.begin(); + for( std::vector::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 ); } diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index 37cb04d273..b8b4dfef99 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -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 HULL_SET; typedef boost::optional OPT_LINE; - typedef std::pair LINE_PAIR; + typedef std::pair LINE_PAIR; typedef std::vector 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 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 m_nodeStack; - std::vector m_lineStack; - std::vector m_optimizerQueue; - std::vector m_gcItems; + std::vector m_lineStack; + std::vector 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 diff --git a/pcbnew/router/pns_sizes_settings.cpp b/pcbnew/router/pns_sizes_settings.cpp index 94f12ac04a..6bce41190c 100644 --- a/pcbnew/router/pns_sizes_settings.cpp +++ b/pcbnew/router/pns_sizes_settings.cpp @@ -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( aItem->Owner() )->FindJoint( p, aItem ); assert( jt != NULL ); diff --git a/pcbnew/router/pns_topology.cpp b/pcbnew/router/pns_topology.cpp index 9af81ae3fc..2044aefbf0 100644 --- a/pcbnew/router/pns_topology.cpp +++ b/pcbnew/router/pns_topology.cpp @@ -37,17 +37,17 @@ bool PNS_TOPOLOGY::SimplifyLine( PNS_LINE* aLine ) return false; PNS_SEGMENT* root = ( *aLine->LinkedSegments() )[0]; - std::auto_ptr 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 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 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,32 +362,36 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ) } } } - } else + } + else + { return false; + } if( !coupledSeg ) return false; - std::auto_ptr lp( m_world->AssembleLine( refSeg ) ); - std::auto_ptr ln( m_world->AssembleLine( coupledSeg ) ); + PNS_LINE lp = m_world->AssembleLine( refSeg ); + PNS_LINE ln = m_world->AssembleLine( coupledSeg ); if( DpNetPolarity( refNet ) < 0 ) { std::swap( lp, ln ); } - int gap = -1 ; + 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; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 382fb70666..ac491e3ddf 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -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;