From 0c67e26e9c4fd841a03923fd52f61ace949b3845 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 31 Jan 2014 18:05:11 +0100 Subject: [PATCH] Added the dynamic ratsnest for the tracks that are currently routed with the PNS router. --- pcbnew/ratsnest_data.cpp | 71 ++++++++++++++++++++++++++--------- pcbnew/ratsnest_data.h | 51 +++++++++++++++++++++---- pcbnew/ratsnest_viewitem.cpp | 11 +++--- pcbnew/router/pns_router.h | 17 ++++++--- pcbnew/router/router_tool.cpp | 27 +++++++++++++ 5 files changed, 141 insertions(+), 36 deletions(-) diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index 948362317f..bf58ea31b2 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -705,12 +705,9 @@ void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) if( net < 1 ) // do not process unconnected items return; - // Get list of nodes responding to the item - std::list nodes = m_nets[net].GetNodes( item ); - std::list::iterator it, itEnd; - - for( it = nodes.begin(), itEnd = nodes.end(); it != itEnd; ++it ) - m_nets[net].AddSimpleNode( *it ); + // Add all nodes belonging to the item + BOOST_FOREACH( RN_NODE_PTR node, m_nets[net].GetNodes( item ) ) + m_nets[net].AddSimpleNode( node ); } else if( aItem->Type() == PCB_MODULE_T ) { @@ -726,6 +723,46 @@ void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) } +void RN_DATA::AddBlocked( const BOARD_ITEM* aItem ) +{ + int net; + + if( aItem->IsConnected() ) + { + const BOARD_CONNECTED_ITEM* item = static_cast( aItem ); + net = item->GetNet(); + + if( net < 1 ) // do not process unconnected items + return; + + // Block all nodes belonging to the item + BOOST_FOREACH( RN_NODE_PTR node, m_nets[net].GetNodes( item ) ) + m_nets[net].AddBlockedNode( node ); + } + else if( aItem->Type() == PCB_MODULE_T ) + { + const MODULE* module = static_cast( aItem ); + + for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) + AddBlocked( pad ); + + return; + } + else + return; +} + + +void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) +{ + assert( aNetCode > 0 ); + + RN_NODE_PTR newNode = boost::make_shared( aPosition.x, aPosition.y ); + + m_nets[aNetCode].AddSimpleNode( newNode ); +} + + void RN_NET::processZones() { BOOST_FOREACH( std::deque& edges, m_zoneConnections | boost::adaptors::map_values ) @@ -773,17 +810,6 @@ void RN_NET::processZones() } -void RN_DATA::updateNet( int aNetCode ) -{ - assert( aNetCode < (int) m_nets.size() ); - if( aNetCode < 1 ) - return; - - m_nets[aNetCode].ClearSimple(); - m_nets[aNetCode].Update(); -} - - void RN_DATA::Add( const BOARD_ITEM* aItem ) { int net; @@ -946,3 +972,14 @@ void RN_DATA::Recalculate( int aNet ) updateNet( aNet ); } } + + +void RN_DATA::updateNet( int aNetCode ) +{ + assert( aNetCode < (int) m_nets.size() ); + if( aNetCode < 1 ) + return; + + m_nets[aNetCode].ClearSimple(); + m_nets[aNetCode].Update(); +} diff --git a/pcbnew/ratsnest_data.h b/pcbnew/ratsnest_data.h index d51c070ee8..712909f2fa 100644 --- a/pcbnew/ratsnest_data.h +++ b/pcbnew/ratsnest_data.h @@ -284,7 +284,7 @@ public: /** * Function MarkDirty() - * Marks ratsnest for given net as 'dirty', ie. requiring recomputation. + * Marks ratsnest for given net as 'dirty', i.e. requiring recomputation. */ void MarkDirty() { @@ -432,7 +432,7 @@ public: /** * Function GetEdges() * Returns pointer to the vector of edges that makes ratsnest for a given net. - * @return Pointer to the vector of edges that makes ratsnest for a given net + * @return Pointer to the vector of edges that makes ratsnest for a given net. */ const std::vector* GetEdges() const { @@ -441,8 +441,8 @@ public: /** * Function AddSimpleNode() - * Changes drawing mode for a node to simple (ie. one ratsnest line per node). - * @param aNode is a node that changes its drawing mode.. + * Changes drawing mode for a node to simple (i.e. one ratsnest line per node). + * @param aNode is a node that changes its drawing mode. */ void AddSimpleNode( RN_NODE_PTR& aNode ) { @@ -450,9 +450,21 @@ public: aNode->SetFlag( true ); } + /** + * Function AddBlockedNode() + * Specifies a node as not suitable as a ratsnest line target (i.e. ratsnest lines will not + * target the node). The status is cleared after calling ClearSimple(). + * @param aNode is the node that is not going to be used as a ratsnest line target. + */ + void AddBlockedNode( RN_NODE_PTR& aNode ) + { + m_blockedNodes.push_back( aNode ); + aNode->SetFlag( true ); + } + /** * Function GetSimpleNodes() - * Returns list of nodes for which ratsnest is drawn in simple mode (ie. one + * Returns list of nodes for which ratsnest is drawn in simple mode (i.e. one * ratsnest line per node). * @return list of nodes for which ratsnest is drawn in simple mode. */ @@ -470,11 +482,15 @@ public: BOOST_FOREACH( const RN_NODE_PTR& node, m_simpleNodes ) node->SetFlag( false ); + BOOST_FOREACH( const RN_NODE_PTR& node, m_blockedNodes ) + node->SetFlag( false ); + m_simpleNodes.clear(); + m_blockedNodes.clear(); } protected: - ///> Validates edge, ie. modifies source and target nodes for an edge + ///> Validates edge, i.e. modifies source and target nodes for an edge ///> to make sure that they are not ones with the flag set. void validateEdge( RN_EDGE_PTR& aEdge ); @@ -496,6 +512,9 @@ protected: ///> List of nodes for which ratsnest is drawn in simple mode. std::deque m_simpleNodes; + ///> List of nodes which should be used as ratsnest target nodes.. + std::deque m_blockedNodes; + ///> Flag indicating necessity of recalculation of ratsnest for a net. bool m_dirty; @@ -556,12 +575,30 @@ public: /** * Function AddSimple() - * Sets an item to be drawn in simple mode (ie. one line per node, instead of full ratsnest). + * Sets an item to be drawn in simple mode (i.e. one line per node, instead of full ratsnest). * It is used for drawing quick, temporary ratsnest, eg. while moving an item. * @param aItem is an item to be drawn in simple node. */ void AddSimple( const BOARD_ITEM* aItem ); + /** + * Function AddSimple() + * Allows to draw a ratsnest line using a position expressed in world coordinates and a + * net code (so there is no need to have a real BOARD_ITEM to draw ratsnest line). + * It is used for drawing quick, temporary ratsnest, eg. while moving an item. + * @param aPosition is the point for which ratsnest line are going to be drawn. + * @param aNetCode determines the net code for which the ratsnest line are going to be drawn. + */ + void AddSimple( const VECTOR2I& aPosition, int aNetCode ); + + /** + * Function AddBlocked() + * Specifies an item as not suitable as a ratsnest line target (i.e. ratsnest lines will not + * target its node(s)). The status is cleared after calling ClearSimple(). + * @param aItem is the item of which node(s) are not going to be used as a ratsnest line target. + */ + void AddBlocked( const BOARD_ITEM* aItem ); + /** * Function ClearSimple() * Clears the list of nodes for which ratsnest is drawn in simple mode (one line per node). diff --git a/pcbnew/ratsnest_viewitem.cpp b/pcbnew/ratsnest_viewitem.cpp index 7bf9d79568..5de2527111 100644 --- a/pcbnew/ratsnest_viewitem.cpp +++ b/pcbnew/ratsnest_viewitem.cpp @@ -63,14 +63,11 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const for( int i = 1; i < m_data->GetNetCount(); ++i ) { - const RN_NET& net = m_data->GetNet( i ); + RN_NET& net = m_data->GetNet( i ); if( !net.IsVisible() ) continue; - // Avoid duplicate destinations for ratsnest lines by storing already used nodes - boost::unordered_set usedDestinations; - // Set brighter color for the temporary ratsnest aGal->SetStrokeColor( color.Brightened( 0.8 ) ); @@ -79,13 +76,15 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const { RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); - if( dest && usedDestinations.find( dest ) == usedDestinations.end() ) + if( dest ) { VECTOR2D origin( node->GetX(), node->GetY() ); VECTOR2D end( dest->GetX(), dest->GetY() ); aGal->DrawLine( origin, end ); - usedDestinations.insert( dest ); + + // Avoid duplicate destinations for ratsnest lines by storing already used nodes + net.AddBlockedNode( dest ); } } diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 3ba7be0125..430f950a37 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -139,15 +139,20 @@ public: const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ); /** - * Returns the last changes introduced by the router. After calling the method the list of - * changes is cleared, so only the latest changes are stored. + * Returns the last changes introduced by the router (since the last time ClearLastChanges() + * was called or a new track has been started). */ - PICKED_ITEMS_LIST GetLastChanges() + const PICKED_ITEMS_LIST& GetLastChanges() const { - PICKED_ITEMS_LIST copy = m_undoBuffer; - m_undoBuffer.ClearItemsList(); // TODO and delete? + return m_undoBuffer; + } - return copy; + /** + * Clears the list of recent changes, saved to be stored in the undo buffer. + */ + void ClearLastChanges() + { + m_undoBuffer.ClearItemsList(); } private: diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 94475132e2..9a8528d23a 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -32,6 +32,8 @@ #include +#include + #include "router_tool.h" #include "pns_segment.h" #include "pns_router.h" @@ -282,6 +284,30 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) ctls->ForceCursorPosition( false ); } + // Draw ratsnest for the currently routed track + RN_DATA* ratsnest = getModel( PCB_T )->GetRatsnest(); + ratsnest->ClearSimple(); + + if( ( m_endItem == NULL || m_endItem == m_startItem ) && m_startItem->GetNet() > 0 ) + { + // The ending node has to be first, so the line for the track is drawn first + ratsnest->AddSimple( m_endSnapPoint, m_startItem->GetNet() ); + + // Those nodes are added just to force ratsnest not to drawn + // lines to already routed parts of the track + const PICKED_ITEMS_LIST& changes = m_router->GetLastChanges(); + for( unsigned int i = 0; i < changes.GetCount(); ++i ) + { + // Block the new tracks, do not handle tracks that were moved + // (moved tracks are saved in the undo buffer with UR_DELETED status instead) + if( changes.GetPickedItemStatus( i ) == UR_NEW ) + ratsnest->AddBlocked( static_cast( changes.GetPickedItem( i ) ) ); + } + + // Also the origin of the new track should be skipped in the ratsnest shown for the routed track + ratsnest->AddBlocked( static_cast( m_startItem->GetParent() ) ); + } + if( m_endItem ) TRACE( 0, "%s, layer : %d", m_endItem->GetKindStr().c_str() % m_endItem->GetLayers().Start() ); @@ -382,6 +408,7 @@ void ROUTER_TOOL::startRouting() // Save the recent changes in the undo buffer getEditFrame()->SaveCopyInUndoList( m_router->GetLastChanges(), UR_UNSPECIFIED ); + m_router->ClearLastChanges(); getEditFrame()->OnModify(); } else