From 190af5d95b51303d4776954c8c3e7fb80ddadab8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 9 Mar 2015 13:41:34 +0100 Subject: [PATCH] Added functions to resolve connectivity queries in ratsnest (GAL). --- include/ttl/halfedge/hetriang.h | 106 ++++++++++------- pcbnew/ratsnest_data.cpp | 197 ++++++++++++++++++++++++++------ pcbnew/ratsnest_data.h | 104 ++++++++++------- pcbnew/ratsnest_viewitem.cpp | 7 +- 4 files changed, 291 insertions(+), 123 deletions(-) diff --git a/include/ttl/halfedge/hetriang.h b/include/ttl/halfedge/hetriang.h index f84c542e5a..39e54d87c6 100644 --- a/include/ttl/halfedge/hetriang.h +++ b/include/ttl/halfedge/hetriang.h @@ -4,21 +4,21 @@ * Copyright (C) 2013 CERN * @author Maciej Suminski * - * Contact information: E-mail: tor.dokken@sintef.no - * SINTEF ICT, Department of Applied Mathematics, - * P.O. Box 124 Blindern, - * 0314 Oslo, Norway. + * Contact information: E-mail: tor.dokken@sintef.no + * SINTEF ICT, Department of Applied Mathematics, + * P.O. Box 124 Blindern, + * 0314 Oslo, Norway. * * This file is part of TTL. * * TTL is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. + * License, or (at your option) any later version. * - * TTL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * TTL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public @@ -36,7 +36,7 @@ * disclosing the source code of your own applications. * * This file may be used in accordance with the terms contained in a - * written agreement between you and SINTEF ICT. + * written agreement between you and SINTEF ICT. */ #ifndef _HE_TRIANG_H_ @@ -100,6 +100,9 @@ protected: /// Node coordinates int m_x, m_y; + /// Tag for quick connection resolution + int m_tag; + /// Reference count unsigned int m_refCount; @@ -112,7 +115,7 @@ public: #ifdef TTL_USE_NODE_ID m_id( id_count++ ), #endif - m_x( aX ), m_y( aY ), m_refCount( 0 ) + m_x( aX ), m_y( aY ), m_tag( -1 ), m_refCount( 0 ) { } @@ -120,20 +123,32 @@ public: ~NODE() {} /// Returns the x-coordinate - int GetX() const + inline int GetX() const { return m_x; } /// Returns the y-coordinate - int GetY() const + inline int GetY() const { return m_y; } + /// Returns tag, common identifier for connected nodes + inline int GetTag() const + { + return m_tag; + } + + /// Sets tag, common identifier for connected nodes + inline void SetTag( int aTag ) + { + m_tag = aTag; + } + #ifdef TTL_USE_NODE_ID /// Returns the id (TTL_USE_NODE_ID must be defined) - int Id() const + inline int Id() const { return m_id; } @@ -141,35 +156,35 @@ public: #ifdef TTL_USE_NODE_FLAG /// Sets the flag (TTL_USE_NODE_FLAG must be defined) - void SetFlag( bool aFlag ) + inline void SetFlag( bool aFlag ) { m_flag = aFlag; } /// Returns the flag (TTL_USE_NODE_FLAG must be defined) - const bool& GetFlag() const + inline const bool& GetFlag() const { return m_flag; } #endif - void IncRefCount() + inline void IncRefCount() { m_refCount++; } - void DecRefCount() + inline void DecRefCount() { m_refCount--; } - unsigned int GetRefCount() const + inline unsigned int GetRefCount() const { return m_refCount; } }; - + /** * \class EDGE * \brief \b %Edge class in the in the half-edge data structure. @@ -187,55 +202,65 @@ public: { } + /// Returns tag, common identifier for connected nodes + inline int GetTag() const + { + int tag = GetSourceNode()->GetTag(); + if( tag >= 0 ) + return tag; + + return GetTargetNode()->GetTag(); + } + /// Sets the source node - void SetSourceNode( const NODE_PTR& aNode ) + inline void SetSourceNode( const NODE_PTR& aNode ) { m_sourceNode = aNode; } /// Sets the next edge in face - void SetNextEdgeInFace( const EDGE_PTR& aEdge ) + inline void SetNextEdgeInFace( const EDGE_PTR& aEdge ) { m_nextEdgeInFace = aEdge; } /// Sets the twin edge - void SetTwinEdge( const EDGE_PTR& aEdge ) + inline void SetTwinEdge( const EDGE_PTR& aEdge ) { m_twinEdge = aEdge; } /// Sets the edge as a leading edge - void SetAsLeadingEdge( bool aLeading = true ) + inline void SetAsLeadingEdge( bool aLeading = true ) { m_isLeadingEdge = aLeading; } /// Checks if an edge is a leading edge - bool IsLeadingEdge() const + inline bool IsLeadingEdge() const { return m_isLeadingEdge; } /// Returns the twin edge - EDGE_PTR GetTwinEdge() const + inline EDGE_PTR GetTwinEdge() const { return m_twinEdge.lock(); } - void ClearTwinEdge() + inline void ClearTwinEdge() { m_twinEdge.reset(); } /// Returns the next edge in face - const EDGE_PTR& GetNextEdgeInFace() const + inline const EDGE_PTR& GetNextEdgeInFace() const { return m_nextEdgeInFace; } /// Retuns the source node - const NODE_PTR& GetSourceNode() const + inline const NODE_PTR& GetSourceNode() const { return m_sourceNode; } @@ -246,12 +271,12 @@ public: return m_nextEdgeInFace->GetSourceNode(); } - void SetWeight( unsigned int weight ) + inline void SetWeight( unsigned int weight ) { m_weight = weight; } - unsigned int GetWeight() const + inline unsigned int GetWeight() const { return m_weight; } @@ -294,22 +319,17 @@ public: m_weight = aWeight; } - EDGE_MST( const EDGE& edge ) - { - m_sourceNode = edge.GetSourceNode(); - m_target = edge.GetTargetNode(); - m_weight = edge.GetWeight(); - } - - ~EDGE_MST() - { - } - /// @copydoc Edge::setSourceNode() virtual const NODE_PTR& GetTargetNode() const { return m_target; } + +private: + EDGE_MST( const EDGE& aEdge ) + { + assert( false ); + } }; class DART; // Forward declaration (class in this namespace) @@ -410,7 +430,7 @@ public: /// Swaps the edge associated with diagonal void SwapEdge( EDGE_PTR& aDiagonal ); - /// Splits the triangle associated with edge into three new triangles joining at point + /// Splits the triangle associated with edge into three new triangles joining at point EDGE_PTR SplitTriangle( EDGE_PTR& aEdge, const NODE_PTR& aPoint ); // Functions required by TTL for removing nodes in a Delaunay triangulation @@ -440,7 +460,7 @@ public: std::list* GetEdges( bool aSkipBoundaryEdges = false ) const; #ifdef TTL_USE_NODE_FLAG - /// Sets flag in all the nodes + /// Sets flag in all the nodes void FlagNodes( bool aFlag ) const; /// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node. diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index deb6d08024..b543b61d26 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KICAD, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2015 CERN * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -96,22 +96,26 @@ bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) } -std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, - const std::vector& aNodes ) +static std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, + std::vector& aNodes ) { unsigned int nodeNumber = aNodes.size(); unsigned int mstExpectedSize = nodeNumber - 1; unsigned int mstSize = 0; + bool ratsnestLines = false; // The output - std::vector* mst = new std::vector; + std::vector* mst = new std::vector; mst->reserve( mstExpectedSize ); // Set tags for marking cycles boost::unordered_map tags; unsigned int tag = 0; - BOOST_FOREACH( const RN_NODE_PTR& node, aNodes ) + BOOST_FOREACH( RN_NODE_PTR& node, aNodes ) + { + node->SetTag( tag ); tags[node] = tag++; + } // Lists of nodes connected together (subtrees) to detect cycles in the graph std::vector > cycles( nodeNumber ); @@ -123,27 +127,40 @@ std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, while( mstSize < mstExpectedSize && !aEdges.empty() ) { - RN_EDGE_PTR& dt = *aEdges.begin(); + RN_EDGE_PTR& dt = aEdges.front(); int srcTag = tags[dt->GetSourceNode()]; int trgTag = tags[dt->GetTargetNode()]; + // Because edges are sorted by their weight, first we always process connected + // items (weight == 0). Once we stumble upon an edge with non-zero weight, + // it means that the rest of the lines are ratsnest. + if( !ratsnestLines && dt->GetWeight() != 0 ) + ratsnestLines = true; + // Check if by adding this edge we are going to join two different forests if( srcTag != trgTag ) { // Update tags std::list::iterator it, itEnd; - for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) - tags[aNodes[*it]] = srcTag; + + if( ratsnestLines ) + { + for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) + tags[aNodes[*it]] = srcTag; + } + else + { + for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) { + tags[aNodes[*it]] = srcTag; + aNodes[*it]->SetTag( srcTag ); + } + } // Move nodes that were marked with old tag to the list marked with the new tag cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); - if( dt->GetWeight() == 0 ) // Skip already existing connections (weight == 0) - { - mstExpectedSize--; - } - else + if( ratsnestLines ) { // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE, // RN_EDGE_MST saves both source and target node and does not require any other @@ -154,6 +171,11 @@ std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, mst->push_back( newEdge ); ++mstSize; } + else + { + // Processing a connection, decrease the expected size of the ratsnest MST + --mstExpectedSize; + } } // Remove the edge that was just processed @@ -167,7 +189,7 @@ std::vector* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, } -void RN_NET::validateEdge( RN_EDGE_PTR& aEdge ) +void RN_NET::validateEdge( RN_EDGE_MST_PTR& aEdge ) { RN_NODE_PTR source = aEdge->GetSourceNode(); RN_NODE_PTR target = aEdge->GetTargetNode(); @@ -238,12 +260,13 @@ bool RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode ) } -const RN_EDGE_PTR& RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, - unsigned int aDistance ) +RN_EDGE_MST_PTR RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, + unsigned int aDistance ) { - m_edges.push_back( boost::make_shared( aNode1, aNode2, aDistance ) ); + RN_EDGE_MST_PTR edge = boost::make_shared( aNode1, aNode2, aDistance ); + m_edges.push_back( edge ); - return m_edges.back(); + return edge; } @@ -252,10 +275,10 @@ void RN_NET::compute() const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes(); const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections(); - // Special case that does need so complicated algorithm - if( boardNodes.size() == 2 ) + // Special cases that does need so complicated algorithm + if( boardNodes.size() <= 2 ) { - m_rnEdges.reset( new std::vector( 0 ) ); + m_rnEdges.reset( new std::vector( 0 ) ); // Check if the only possible connection exists if( boardEdges.size() == 0 ) @@ -268,12 +291,6 @@ void RN_NET::compute() return; } - else if( boardNodes.size() <= 1 ) // This case is even simpler - { - m_rnEdges.reset( new std::vector( 0 ) ); - - return; - } // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation std::vector nodes( boardNodes.size() ); @@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode ) if( !m_rnEdges ) return; - std::vector::iterator newEnd; + std::vector::iterator newEnd; // Remove all ratsnest edges for associated with the node newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), @@ -377,7 +394,7 @@ void RN_NET::Update() compute(); - BOOST_FOREACH( RN_EDGE_PTR& edge, *m_rnEdges ) + BOOST_FOREACH( RN_EDGE_MST_PTR& edge, *m_rnEdges ) validateEdge( edge ); m_dirty = false; @@ -386,8 +403,7 @@ void RN_NET::Update() void RN_NET::AddItem( const D_PAD* aPad ) { - RN_NODE_PTR nodePtr = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); - m_pads[aPad] = nodePtr; + m_pads[aPad] = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); m_dirty = true; } @@ -505,7 +521,7 @@ void RN_NET::RemoveItem( const TRACK* aTrack ) { try { - RN_EDGE_PTR& edge = m_tracks.at( aTrack ); + RN_EDGE_MST_PTR& edge = m_tracks.at( aTrack ); // Save nodes, so they can be cleared later RN_NODE_PTR aBegin = edge->GetSourceNode(); @@ -546,8 +562,8 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone ) polygons.clear(); // Remove all connections added by the zone - std::deque& edges = m_zoneConnections.at( aZone ); - BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) + std::deque& edges = m_zoneConnections.at( aZone ); + BOOST_FOREACH( RN_EDGE_PTR edge, edges ) m_links.RemoveConnection( edge ); edges.clear(); @@ -694,7 +710,7 @@ std::list RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con case PCB_TRACE_T: { const TRACK* track = static_cast( aItem ); - RN_EDGE_PTR edge = m_tracks.at( track ); + const RN_EDGE_MST_PTR& edge = m_tracks.at( track ); nodes.push_back( edge->GetSourceNode() ); nodes.push_back( edge->GetTargetNode() ); @@ -714,6 +730,76 @@ std::list RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con } +void RN_NET::ClearSimple() +{ + 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(); +} + + +void RN_NET::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, + std::list& aOutput, + RN_ITEM_TYPES aTypes ) const +{ + std::list nodes = GetNodes( aItem ); + assert( !nodes.empty() ); + + int tag = nodes.front()->GetTag(); + assert( tag >= 0 ); + + if( aTypes & RN_PADS ) + { + for( PAD_NODE_MAP::const_iterator it = m_pads.begin(); it != m_pads.end(); ++it ) + { + if( it->second->GetTag() == tag ) + aOutput.push_back( const_cast( it->first ) ); + } + } + + if( aTypes & RN_VIAS ) + { + for( VIA_NODE_MAP::const_iterator it = m_vias.begin(); it != m_vias.end(); ++it ) + { + if( it->second->GetTag() == tag ) + aOutput.push_back( const_cast( it->first ) ); + } + } + + if( aTypes & RN_TRACKS ) + { + for( TRACK_EDGE_MAP::const_iterator it = m_tracks.begin(); it != m_tracks.end(); ++it ) + { + if( it->second->GetTag() == tag ) + aOutput.push_back( const_cast( it->first ) ); + } + } + + if( aTypes & RN_ZONES ) + { + for( ZONE_EDGE_MAP::const_iterator it = m_zoneConnections.begin(); + it != m_zoneConnections.end(); ++it ) + { + const std::deque& edges = it->second; + + BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, edges ) + { + if( edge->GetTag() == tag ) + { + aOutput.push_back( const_cast( it->first ) ); + break; + } + } + } + } +} + + void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) { int net; @@ -784,11 +870,46 @@ void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) } +void RN_DATA::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, + std::list& aOutput, + RN_ITEM_TYPES aTypes ) const +{ + int net = aItem->GetNetCode(); + + if( net < 1 ) + return; + + assert( net < (int) m_nets.size() ); + + m_nets[net].GetConnectedItems( aItem, aOutput, aTypes ); +} + + +bool RN_DATA::AreConnected( const BOARD_CONNECTED_ITEM* aItem, const BOARD_CONNECTED_ITEM* aOther ) +{ + int net1 = aItem->GetNetCode(); + int net2 = aOther->GetNetCode(); + + if( net1 < 1 || net2 < 1 || net1 != net2 ) + return false; + + assert( net1 < (int) m_nets.size() && net2 < (int) m_nets.size() ); + + // net1 == net2 + std::list items1 = m_nets[net1].GetNodes( aItem ); + std::list items2 = m_nets[net1].GetNodes( aOther ); + + assert( !items1.empty() && !items2.empty() ); + + return ( items1.front()->GetTag() == items2.front()->GetTag() ); +} + + void RN_NET::processZones() { - BOOST_FOREACH( std::deque& edges, m_zoneConnections | boost::adaptors::map_values ) + BOOST_FOREACH( std::deque& edges, m_zoneConnections | boost::adaptors::map_values ) { - BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) + BOOST_FOREACH( RN_EDGE_MST_PTR edge, edges ) m_links.RemoveConnection( edge ); edges.clear(); @@ -814,7 +935,7 @@ void RN_NET::processZones() { if( poly->HitTest( *point ) ) { - const RN_EDGE_PTR& connection = m_links.AddConnection( poly->GetNode(), *point ); + RN_EDGE_MST_PTR connection = m_links.AddConnection( poly->GetNode(), *point ); m_zoneConnections[poly->GetParent()].push_back( connection ); // This point already belongs to a polygon, we do not need to check it anymore diff --git a/pcbnew/ratsnest_data.h b/pcbnew/ratsnest_data.h index 348c31902e..ce2ef4fa9b 100644 --- a/pcbnew/ratsnest_data.h +++ b/pcbnew/ratsnest_data.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KICAD, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2015 CERN * @author Maciej Suminski * * This program is free software; you can redistribute it and/or @@ -49,6 +49,16 @@ class TRACK; class ZONE_CONTAINER; class CPolyPt; +///> Types of items that are handled by the class +enum RN_ITEM_TYPES +{ + RN_PADS = 0x01, + RN_VIAS = 0x02, + RN_TRACKS = 0x04, + RN_ZONES = 0x08, + RN_ALL = 0xFF +}; + // Preserve KiCad coding style policy typedef hed::NODE RN_NODE; typedef hed::NODE_PTR RN_NODE_PTR; @@ -157,8 +167,8 @@ public: * @param aDistance is the distance of the connection (0 means that nodes are actually * connected, >0 means a missing connection). */ - const RN_EDGE_PTR& AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, - unsigned int aDistance = 0 ); + RN_EDGE_MST_PTR AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, + unsigned int aDistance = 0 ); /** * Function RemoveConnection() @@ -181,7 +191,7 @@ public: } protected: - ///> Set of nodes that are used are expected to be connected together. + ///> Set of nodes that are expected to be connected together (vias, tracks, pads). RN_NODE_SET m_nodes; ///> List of edges that currently connect nodes. @@ -210,7 +220,6 @@ public: return m_node; } - /** * Function GetParent() * Returns pointer to zone that is the owner of subpolygon. @@ -307,7 +316,7 @@ public: * Returns pointer to a vector of edges that makes ratsnest for a given net. * @return Pointer to a vector of edges that makes ratsnest for a given net. */ - const std::vector* GetUnconnected() const + const std::vector* GetUnconnected() const { return m_rnEdges.get(); } @@ -429,22 +438,12 @@ public: std::list GetClosestNodes( const RN_NODE_PTR& aNode, const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const; - /** - * 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. - */ - const std::vector* GetEdges() const - { - return m_rnEdges.get(); - } - /** * Function AddSimpleNode() * 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 ) + inline void AddSimpleNode( RN_NODE_PTR& aNode ) { m_simpleNodes.push_back( aNode ); aNode->SetFlag( true ); @@ -456,7 +455,7 @@ public: * 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 ) + inline void AddBlockedNode( RN_NODE_PTR& aNode ) { m_blockedNodes.push_back( aNode ); aNode->SetFlag( true ); @@ -468,7 +467,7 @@ public: * ratsnest line per node). * @return list of nodes for which ratsnest is drawn in simple mode. */ - const std::deque& GetSimpleNodes() const + inline const std::deque& GetSimpleNodes() const { return m_simpleNodes; } @@ -477,22 +476,23 @@ public: * Function ClearSimple() * Removes all nodes and edges that are used for displaying ratsnest in simple mode. */ - void ClearSimple() - { - BOOST_FOREACH( const RN_NODE_PTR& node, m_simpleNodes ) - node->SetFlag( false ); + void ClearSimple(); - BOOST_FOREACH( const RN_NODE_PTR& node, m_blockedNodes ) - node->SetFlag( false ); - - m_simpleNodes.clear(); - m_blockedNodes.clear(); - } + /** + * Function GetConnectedItems() + * Adds items that are connected together to a list. + * @param aItem is the reference item to find other connected items. + * @param aOutput is the list that will contain found items. + * @param aTypes allows to filter by item types. + */ + void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, + std::list& aOutput, + RN_ITEM_TYPES aTypes = RN_ALL) const; protected: ///> 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 ); + void validateEdge( RN_EDGE_MST_PTR& aEdge ); ///> Removes all ratsnest edges for a given node. void clearNode( const RN_NODE_PTR& aNode ); @@ -507,31 +507,37 @@ protected: RN_LINKS m_links; ///> Vector of edges that makes ratsnest for a given net. - boost::shared_ptr< std::vector > m_rnEdges; + boost::shared_ptr< std::vector > m_rnEdges; ///> 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.. + ///> List of nodes which will not be used as ratsnest target nodes. std::deque m_blockedNodes; ///> Flag indicating necessity of recalculation of ratsnest for a net. bool m_dirty; + ///> Helper typedefs + typedef boost::unordered_map PAD_NODE_MAP; + typedef boost::unordered_map VIA_NODE_MAP; + typedef boost::unordered_map TRACK_EDGE_MAP; + typedef boost::unordered_map > ZONE_POLY_MAP; + typedef boost::unordered_map > ZONE_EDGE_MAP; ///> Map that associates nodes in the ratsnest model to respective nodes. - boost::unordered_map m_pads; + PAD_NODE_MAP m_pads; ///> Map that associates nodes in the ratsnest model to respective vias. - boost::unordered_map m_vias; + VIA_NODE_MAP m_vias; ///> Map that associates edges in the ratsnest model to respective tracks. - boost::unordered_map m_tracks; + TRACK_EDGE_MAP m_tracks; - ///> Map that associates groups of subpolygons in the ratsnest model to their respective zones. - boost::unordered_map > m_zonePolygons; + ///> Map that associates groups of subpolygons in the ratsnest model to respective zones. + ZONE_POLY_MAP m_zonePolygons; - ///> Map that associates groups of edges in the ratsnest model to their respective zones. - boost::unordered_map > m_zoneConnections; + ///> Map that associates groups of edges in the ratsnest model to respective zones. + ZONE_EDGE_MAP m_zoneConnections; ///> Visibility flag. bool m_visible; @@ -646,6 +652,26 @@ public: return m_nets[aNetCode]; } + /** + * Function GetConnectedItems() + * Adds items that are connected together to a list. + * @param aItem is the reference item to find other connected items. + * @param aOutput is the list that will contain found items. + * @param aTypes allows to filter by item types. + */ + void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, + std::list& aOutput, + RN_ITEM_TYPES aTypes = RN_ALL ) const; + + /** + * Function AreConnected() + * Checks if two items are connected with copper. + * @param aThis is the first item. + * @param aOther is the second item. + * @return True if they are connected, false otherwise. + */ + bool AreConnected( const BOARD_CONNECTED_ITEM* aItem, const BOARD_CONNECTED_ITEM* aOther ); + protected: /** * Function updateNet() diff --git a/pcbnew/ratsnest_viewitem.cpp b/pcbnew/ratsnest_viewitem.cpp index 1f40f8ed26..d10c9314bf 100644 --- a/pcbnew/ratsnest_viewitem.cpp +++ b/pcbnew/ratsnest_viewitem.cpp @@ -72,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const // Set brighter color for the temporary ratsnest aGal->SetStrokeColor( color.Brightened( 0.8 ) ); - // Draw the "dynamic" ratsnest (ie. for objects that may be currently being moved) + // Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved) BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() ) { RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); @@ -93,11 +93,12 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const if( i != highlightedNet ) aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted - const std::vector* edges = net.GetUnconnected(); + const std::vector* edges = net.GetUnconnected(); + if( edges == NULL ) continue; - BOOST_FOREACH( const RN_EDGE_PTR& edge, *edges ) + BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, *edges ) { const RN_NODE_PTR& sourceNode = edge->GetSourceNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode();