Loading include/ttl/halfedge/hetriang.h +63 −43 Original line number Original line Diff line number Diff line Loading @@ -100,6 +100,9 @@ protected: /// Node coordinates /// Node coordinates int m_x, m_y; int m_x, m_y; /// Tag for quick connection resolution int m_tag; /// Reference count /// Reference count unsigned int m_refCount; unsigned int m_refCount; Loading @@ -112,7 +115,7 @@ public: #ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID m_id( id_count++ ), m_id( id_count++ ), #endif #endif m_x( aX ), m_y( aY ), m_refCount( 0 ) m_x( aX ), m_y( aY ), m_tag( -1 ), m_refCount( 0 ) { { } } Loading @@ -120,20 +123,32 @@ public: ~NODE() {} ~NODE() {} /// Returns the x-coordinate /// Returns the x-coordinate int GetX() const inline int GetX() const { { return m_x; return m_x; } } /// Returns the y-coordinate /// Returns the y-coordinate int GetY() const inline int GetY() const { { return m_y; 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 #ifdef TTL_USE_NODE_ID /// Returns the id (TTL_USE_NODE_ID must be defined) /// Returns the id (TTL_USE_NODE_ID must be defined) int Id() const inline int Id() const { { return m_id; return m_id; } } Loading @@ -141,29 +156,29 @@ public: #ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG /// Sets the flag (TTL_USE_NODE_FLAG must be defined) /// Sets the flag (TTL_USE_NODE_FLAG must be defined) void SetFlag( bool aFlag ) inline void SetFlag( bool aFlag ) { { m_flag = aFlag; m_flag = aFlag; } } /// Returns the flag (TTL_USE_NODE_FLAG must be defined) /// Returns the flag (TTL_USE_NODE_FLAG must be defined) const bool& GetFlag() const inline const bool& GetFlag() const { { return m_flag; return m_flag; } } #endif #endif void IncRefCount() inline void IncRefCount() { { m_refCount++; m_refCount++; } } void DecRefCount() inline void DecRefCount() { { m_refCount--; m_refCount--; } } unsigned int GetRefCount() const inline unsigned int GetRefCount() const { { return m_refCount; return m_refCount; } } Loading @@ -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 /// Sets the source node void SetSourceNode( const NODE_PTR& aNode ) inline void SetSourceNode( const NODE_PTR& aNode ) { { m_sourceNode = aNode; m_sourceNode = aNode; } } /// Sets the next edge in face /// Sets the next edge in face void SetNextEdgeInFace( const EDGE_PTR& aEdge ) inline void SetNextEdgeInFace( const EDGE_PTR& aEdge ) { { m_nextEdgeInFace = aEdge; m_nextEdgeInFace = aEdge; } } /// Sets the twin edge /// Sets the twin edge void SetTwinEdge( const EDGE_PTR& aEdge ) inline void SetTwinEdge( const EDGE_PTR& aEdge ) { { m_twinEdge = aEdge; m_twinEdge = aEdge; } } /// Sets the edge as a leading edge /// Sets the edge as a leading edge void SetAsLeadingEdge( bool aLeading = true ) inline void SetAsLeadingEdge( bool aLeading = true ) { { m_isLeadingEdge = aLeading; m_isLeadingEdge = aLeading; } } /// Checks if an edge is a leading edge /// Checks if an edge is a leading edge bool IsLeadingEdge() const inline bool IsLeadingEdge() const { { return m_isLeadingEdge; return m_isLeadingEdge; } } /// Returns the twin edge /// Returns the twin edge EDGE_PTR GetTwinEdge() const inline EDGE_PTR GetTwinEdge() const { { return m_twinEdge.lock(); return m_twinEdge.lock(); } } void ClearTwinEdge() inline void ClearTwinEdge() { { m_twinEdge.reset(); m_twinEdge.reset(); } } /// Returns the next edge in face /// Returns the next edge in face const EDGE_PTR& GetNextEdgeInFace() const inline const EDGE_PTR& GetNextEdgeInFace() const { { return m_nextEdgeInFace; return m_nextEdgeInFace; } } /// Retuns the source node /// Retuns the source node const NODE_PTR& GetSourceNode() const inline const NODE_PTR& GetSourceNode() const { { return m_sourceNode; return m_sourceNode; } } Loading @@ -246,12 +271,12 @@ public: return m_nextEdgeInFace->GetSourceNode(); return m_nextEdgeInFace->GetSourceNode(); } } void SetWeight( unsigned int weight ) inline void SetWeight( unsigned int weight ) { { m_weight = weight; m_weight = weight; } } unsigned int GetWeight() const inline unsigned int GetWeight() const { { return m_weight; return m_weight; } } Loading Loading @@ -294,22 +319,17 @@ public: m_weight = aWeight; 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() /// @copydoc Edge::setSourceNode() virtual const NODE_PTR& GetTargetNode() const virtual const NODE_PTR& GetTargetNode() const { { return m_target; return m_target; } } private: EDGE_MST( const EDGE& aEdge ) { assert( false ); } }; }; class DART; // Forward declaration (class in this namespace) class DART; // Forward declaration (class in this namespace) Loading pcbnew/ratsnest_data.cpp +159 −38 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KICAD, a free EDA CAD application. * 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 <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or Loading Loading @@ -96,22 +96,26 @@ bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) } } std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, static std::vector<RN_EDGE_MST_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, const std::vector<RN_NODE_PTR>& aNodes ) std::vector<RN_NODE_PTR>& aNodes ) { { unsigned int nodeNumber = aNodes.size(); unsigned int nodeNumber = aNodes.size(); unsigned int mstExpectedSize = nodeNumber - 1; unsigned int mstExpectedSize = nodeNumber - 1; unsigned int mstSize = 0; unsigned int mstSize = 0; bool ratsnestLines = false; // The output // The output std::vector<RN_EDGE_PTR>* mst = new std::vector<RN_EDGE_PTR>; std::vector<RN_EDGE_MST_PTR>* mst = new std::vector<RN_EDGE_MST_PTR>; mst->reserve( mstExpectedSize ); mst->reserve( mstExpectedSize ); // Set tags for marking cycles // Set tags for marking cycles boost::unordered_map<RN_NODE_PTR, int> tags; boost::unordered_map<RN_NODE_PTR, int> tags; unsigned int tag = 0; 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++; tags[node] = tag++; } // Lists of nodes connected together (subtrees) to detect cycles in the graph // Lists of nodes connected together (subtrees) to detect cycles in the graph std::vector<std::list<int> > cycles( nodeNumber ); std::vector<std::list<int> > cycles( nodeNumber ); Loading @@ -123,27 +127,40 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, while( mstSize < mstExpectedSize && !aEdges.empty() ) while( mstSize < mstExpectedSize && !aEdges.empty() ) { { RN_EDGE_PTR& dt = *aEdges.begin(); RN_EDGE_PTR& dt = aEdges.front(); int srcTag = tags[dt->GetSourceNode()]; int srcTag = tags[dt->GetSourceNode()]; int trgTag = tags[dt->GetTargetNode()]; 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 // Check if by adding this edge we are going to join two different forests if( srcTag != trgTag ) if( srcTag != trgTag ) { { // Update tags // Update tags std::list<int>::iterator it, itEnd; std::list<int>::iterator it, itEnd; if( ratsnestLines ) { for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) tags[aNodes[*it]] = srcTag; 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 // Move nodes that were marked with old tag to the list marked with the new tag cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); if( dt->GetWeight() == 0 ) // Skip already existing connections (weight == 0) if( ratsnestLines ) { mstExpectedSize--; } else { { // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE, // 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 // RN_EDGE_MST saves both source and target node and does not require any other Loading @@ -154,6 +171,11 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, mst->push_back( newEdge ); mst->push_back( newEdge ); ++mstSize; ++mstSize; } } else { // Processing a connection, decrease the expected size of the ratsnest MST --mstExpectedSize; } } } // Remove the edge that was just processed // Remove the edge that was just processed Loading @@ -167,7 +189,7 @@ std::vector<RN_EDGE_PTR>* 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 source = aEdge->GetSourceNode(); RN_NODE_PTR target = aEdge->GetTargetNode(); RN_NODE_PTR target = aEdge->GetTargetNode(); Loading Loading @@ -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, RN_EDGE_MST_PTR RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, unsigned int aDistance ) unsigned int aDistance ) { { m_edges.push_back( boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ) ); RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ); m_edges.push_back( edge ); return m_edges.back(); return edge; } } Loading @@ -252,10 +275,10 @@ void RN_NET::compute() const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes(); const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes(); const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections(); const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections(); // Special case that does need so complicated algorithm // Special cases that does need so complicated algorithm if( boardNodes.size() == 2 ) if( boardNodes.size() <= 2 ) { { m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) ); m_rnEdges.reset( new std::vector<RN_EDGE_MST_PTR>( 0 ) ); // Check if the only possible connection exists // Check if the only possible connection exists if( boardEdges.size() == 0 ) if( boardEdges.size() == 0 ) Loading @@ -268,12 +291,6 @@ void RN_NET::compute() return; return; } } else if( boardNodes.size() <= 1 ) // This case is even simpler { m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) ); return; } // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation std::vector<RN_NODE_PTR> nodes( boardNodes.size() ); std::vector<RN_NODE_PTR> nodes( boardNodes.size() ); Loading Loading @@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode ) if( !m_rnEdges ) if( !m_rnEdges ) return; return; std::vector<RN_EDGE_PTR>::iterator newEnd; std::vector<RN_EDGE_MST_PTR>::iterator newEnd; // Remove all ratsnest edges for associated with the node // Remove all ratsnest edges for associated with the node newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), Loading Loading @@ -377,7 +394,7 @@ void RN_NET::Update() compute(); compute(); BOOST_FOREACH( RN_EDGE_PTR& edge, *m_rnEdges ) BOOST_FOREACH( RN_EDGE_MST_PTR& edge, *m_rnEdges ) validateEdge( edge ); validateEdge( edge ); m_dirty = false; m_dirty = false; Loading @@ -386,8 +403,7 @@ void RN_NET::Update() void RN_NET::AddItem( const D_PAD* aPad ) void RN_NET::AddItem( const D_PAD* aPad ) { { RN_NODE_PTR nodePtr = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); m_pads[aPad] = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); m_pads[aPad] = nodePtr; m_dirty = true; m_dirty = true; } } Loading Loading @@ -505,7 +521,7 @@ void RN_NET::RemoveItem( const TRACK* aTrack ) { { try 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 // Save nodes, so they can be cleared later RN_NODE_PTR aBegin = edge->GetSourceNode(); RN_NODE_PTR aBegin = edge->GetSourceNode(); Loading Loading @@ -546,8 +562,8 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone ) polygons.clear(); polygons.clear(); // Remove all connections added by the zone // Remove all connections added by the zone std::deque<RN_EDGE_PTR>& edges = m_zoneConnections.at( aZone ); std::deque<RN_EDGE_MST_PTR>& edges = m_zoneConnections.at( aZone ); BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) BOOST_FOREACH( RN_EDGE_PTR edge, edges ) m_links.RemoveConnection( edge ); m_links.RemoveConnection( edge ); edges.clear(); edges.clear(); Loading Loading @@ -694,7 +710,7 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con case PCB_TRACE_T: case PCB_TRACE_T: { { const TRACK* track = static_cast<const TRACK*>( aItem ); const TRACK* track = static_cast<const TRACK*>( 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->GetSourceNode() ); nodes.push_back( edge->GetTargetNode() ); nodes.push_back( edge->GetTargetNode() ); Loading @@ -714,6 +730,76 @@ std::list<RN_NODE_PTR> 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<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYPES aTypes ) const { std::list<RN_NODE_PTR> 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<D_PAD*>( 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<VIA*>( 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<TRACK*>( it->first ) ); } } if( aTypes & RN_ZONES ) { for( ZONE_EDGE_MAP::const_iterator it = m_zoneConnections.begin(); it != m_zoneConnections.end(); ++it ) { const std::deque<RN_EDGE_MST_PTR>& edges = it->second; BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, edges ) { if( edge->GetTag() == tag ) { aOutput.push_back( const_cast<ZONE_CONTAINER*>( it->first ) ); break; } } } } } void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) { { int net; int net; Loading Loading @@ -784,11 +870,46 @@ void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) } } void RN_DATA::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, std::list<BOARD_CONNECTED_ITEM*>& 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<RN_NODE_PTR> items1 = m_nets[net1].GetNodes( aItem ); std::list<RN_NODE_PTR> items2 = m_nets[net1].GetNodes( aOther ); assert( !items1.empty() && !items2.empty() ); return ( items1.front()->GetTag() == items2.front()->GetTag() ); } void RN_NET::processZones() void RN_NET::processZones() { { BOOST_FOREACH( std::deque<RN_EDGE_PTR>& edges, m_zoneConnections | boost::adaptors::map_values ) BOOST_FOREACH( std::deque<RN_EDGE_MST_PTR>& 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 ); m_links.RemoveConnection( edge ); edges.clear(); edges.clear(); Loading @@ -814,7 +935,7 @@ void RN_NET::processZones() { { if( poly->HitTest( *point ) ) 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 ); m_zoneConnections[poly->GetParent()].push_back( connection ); // This point already belongs to a polygon, we do not need to check it anymore // This point already belongs to a polygon, we do not need to check it anymore Loading pcbnew/ratsnest_data.h +65 −39 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KICAD, a free EDA CAD application. * 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 <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or Loading Loading @@ -49,6 +49,16 @@ class TRACK; class ZONE_CONTAINER; class ZONE_CONTAINER; class CPolyPt; 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 // Preserve KiCad coding style policy typedef hed::NODE RN_NODE; typedef hed::NODE RN_NODE; typedef hed::NODE_PTR RN_NODE_PTR; typedef hed::NODE_PTR RN_NODE_PTR; Loading Loading @@ -157,7 +167,7 @@ public: * @param aDistance is the distance of the connection (0 means that nodes are actually * @param aDistance is the distance of the connection (0 means that nodes are actually * connected, >0 means a missing connection). * connected, >0 means a missing connection). */ */ const RN_EDGE_PTR& AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, RN_EDGE_MST_PTR AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, unsigned int aDistance = 0 ); unsigned int aDistance = 0 ); /** /** Loading @@ -181,7 +191,7 @@ public: } } protected: 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; RN_NODE_SET m_nodes; ///> List of edges that currently connect nodes. ///> List of edges that currently connect nodes. Loading Loading @@ -210,7 +220,6 @@ public: return m_node; return m_node; } } /** /** * Function GetParent() * Function GetParent() * Returns pointer to zone that is the owner of subpolygon. * Returns pointer to zone that is the owner of subpolygon. Loading Loading @@ -307,7 +316,7 @@ public: * Returns pointer to a vector of edges that makes ratsnest for a given net. * 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. * @return Pointer to a vector of edges that makes ratsnest for a given net. */ */ const std::vector<RN_EDGE_PTR>* GetUnconnected() const const std::vector<RN_EDGE_MST_PTR>* GetUnconnected() const { { return m_rnEdges.get(); return m_rnEdges.get(); } } Loading Loading @@ -429,22 +438,12 @@ public: std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const; 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<RN_EDGE_PTR>* GetEdges() const { return m_rnEdges.get(); } /** /** * Function AddSimpleNode() * Function AddSimpleNode() * Changes drawing mode for a node to simple (i.e. one ratsnest line per node). * 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. * @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 ); m_simpleNodes.push_back( aNode ); aNode->SetFlag( true ); aNode->SetFlag( true ); Loading @@ -456,7 +455,7 @@ public: * target the node). The status is cleared after calling ClearSimple(). * 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. * @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 ); m_blockedNodes.push_back( aNode ); aNode->SetFlag( true ); aNode->SetFlag( true ); Loading @@ -468,7 +467,7 @@ public: * ratsnest line per node). * ratsnest line per node). * @return list of nodes for which ratsnest is drawn in simple mode. * @return list of nodes for which ratsnest is drawn in simple mode. */ */ const std::deque<RN_NODE_PTR>& GetSimpleNodes() const inline const std::deque<RN_NODE_PTR>& GetSimpleNodes() const { { return m_simpleNodes; return m_simpleNodes; } } Loading @@ -477,22 +476,23 @@ public: * Function ClearSimple() * Function ClearSimple() * Removes all nodes and edges that are used for displaying ratsnest in simple mode. * Removes all nodes and edges that are used for displaying ratsnest in simple mode. */ */ void ClearSimple() void 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(); * 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<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYPES aTypes = RN_ALL) const; protected: protected: ///> Validates edge, i.e. 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. ///> 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. ///> Removes all ratsnest edges for a given node. void clearNode( const RN_NODE_PTR& aNode ); void clearNode( const RN_NODE_PTR& aNode ); Loading @@ -507,31 +507,37 @@ protected: RN_LINKS m_links; RN_LINKS m_links; ///> Vector of edges that makes ratsnest for a given net. ///> Vector of edges that makes ratsnest for a given net. boost::shared_ptr< std::vector<RN_EDGE_PTR> > m_rnEdges; boost::shared_ptr< std::vector<RN_EDGE_MST_PTR> > m_rnEdges; ///> List of nodes for which ratsnest is drawn in simple mode. ///> List of nodes for which ratsnest is drawn in simple mode. std::deque<RN_NODE_PTR> m_simpleNodes; std::deque<RN_NODE_PTR> 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<RN_NODE_PTR> m_blockedNodes; std::deque<RN_NODE_PTR> m_blockedNodes; ///> Flag indicating necessity of recalculation of ratsnest for a net. ///> Flag indicating necessity of recalculation of ratsnest for a net. bool m_dirty; bool m_dirty; ///> Helper typedefs typedef boost::unordered_map<const D_PAD*, RN_NODE_PTR> PAD_NODE_MAP; typedef boost::unordered_map<const VIA*, RN_NODE_PTR> VIA_NODE_MAP; typedef boost::unordered_map<const TRACK*, RN_EDGE_MST_PTR> TRACK_EDGE_MAP; typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > ZONE_POLY_MAP; typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_MST_PTR> > ZONE_EDGE_MAP; ///> Map that associates nodes in the ratsnest model to respective nodes. ///> Map that associates nodes in the ratsnest model to respective nodes. boost::unordered_map<const D_PAD*, RN_NODE_PTR> m_pads; PAD_NODE_MAP m_pads; ///> Map that associates nodes in the ratsnest model to respective vias. ///> Map that associates nodes in the ratsnest model to respective vias. boost::unordered_map<const VIA*, RN_NODE_PTR> m_vias; VIA_NODE_MAP m_vias; ///> Map that associates edges in the ratsnest model to respective tracks. ///> Map that associates edges in the ratsnest model to respective tracks. boost::unordered_map<const TRACK*, RN_EDGE_PTR> m_tracks; TRACK_EDGE_MAP m_tracks; ///> Map that associates groups of subpolygons in the ratsnest model to their respective zones. ///> Map that associates groups of subpolygons in the ratsnest model to respective zones. boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > m_zonePolygons; ZONE_POLY_MAP m_zonePolygons; ///> Map that associates groups of edges in the ratsnest model to their respective zones. ///> Map that associates groups of edges in the ratsnest model to respective zones. boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_PTR> > m_zoneConnections; ZONE_EDGE_MAP m_zoneConnections; ///> Visibility flag. ///> Visibility flag. bool m_visible; bool m_visible; Loading Loading @@ -646,6 +652,26 @@ public: return m_nets[aNetCode]; 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<BOARD_CONNECTED_ITEM*>& 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: protected: /** /** * Function updateNet() * Function updateNet() Loading pcbnew/ratsnest_viewitem.cpp +4 −3 Original line number Original line Diff line number Diff line Loading @@ -72,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const // Set brighter color for the temporary ratsnest // Set brighter color for the temporary ratsnest aGal->SetStrokeColor( color.Brightened( 0.8 ) ); 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() ) BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() ) { { RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); Loading @@ -93,11 +93,12 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const if( i != highlightedNet ) if( i != highlightedNet ) aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted const std::vector<RN_EDGE_PTR>* edges = net.GetUnconnected(); const std::vector<RN_EDGE_MST_PTR>* edges = net.GetUnconnected(); if( edges == NULL ) if( edges == NULL ) continue; 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& sourceNode = edge->GetSourceNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode(); Loading Loading
include/ttl/halfedge/hetriang.h +63 −43 Original line number Original line Diff line number Diff line Loading @@ -100,6 +100,9 @@ protected: /// Node coordinates /// Node coordinates int m_x, m_y; int m_x, m_y; /// Tag for quick connection resolution int m_tag; /// Reference count /// Reference count unsigned int m_refCount; unsigned int m_refCount; Loading @@ -112,7 +115,7 @@ public: #ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID m_id( id_count++ ), m_id( id_count++ ), #endif #endif m_x( aX ), m_y( aY ), m_refCount( 0 ) m_x( aX ), m_y( aY ), m_tag( -1 ), m_refCount( 0 ) { { } } Loading @@ -120,20 +123,32 @@ public: ~NODE() {} ~NODE() {} /// Returns the x-coordinate /// Returns the x-coordinate int GetX() const inline int GetX() const { { return m_x; return m_x; } } /// Returns the y-coordinate /// Returns the y-coordinate int GetY() const inline int GetY() const { { return m_y; 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 #ifdef TTL_USE_NODE_ID /// Returns the id (TTL_USE_NODE_ID must be defined) /// Returns the id (TTL_USE_NODE_ID must be defined) int Id() const inline int Id() const { { return m_id; return m_id; } } Loading @@ -141,29 +156,29 @@ public: #ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG /// Sets the flag (TTL_USE_NODE_FLAG must be defined) /// Sets the flag (TTL_USE_NODE_FLAG must be defined) void SetFlag( bool aFlag ) inline void SetFlag( bool aFlag ) { { m_flag = aFlag; m_flag = aFlag; } } /// Returns the flag (TTL_USE_NODE_FLAG must be defined) /// Returns the flag (TTL_USE_NODE_FLAG must be defined) const bool& GetFlag() const inline const bool& GetFlag() const { { return m_flag; return m_flag; } } #endif #endif void IncRefCount() inline void IncRefCount() { { m_refCount++; m_refCount++; } } void DecRefCount() inline void DecRefCount() { { m_refCount--; m_refCount--; } } unsigned int GetRefCount() const inline unsigned int GetRefCount() const { { return m_refCount; return m_refCount; } } Loading @@ -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 /// Sets the source node void SetSourceNode( const NODE_PTR& aNode ) inline void SetSourceNode( const NODE_PTR& aNode ) { { m_sourceNode = aNode; m_sourceNode = aNode; } } /// Sets the next edge in face /// Sets the next edge in face void SetNextEdgeInFace( const EDGE_PTR& aEdge ) inline void SetNextEdgeInFace( const EDGE_PTR& aEdge ) { { m_nextEdgeInFace = aEdge; m_nextEdgeInFace = aEdge; } } /// Sets the twin edge /// Sets the twin edge void SetTwinEdge( const EDGE_PTR& aEdge ) inline void SetTwinEdge( const EDGE_PTR& aEdge ) { { m_twinEdge = aEdge; m_twinEdge = aEdge; } } /// Sets the edge as a leading edge /// Sets the edge as a leading edge void SetAsLeadingEdge( bool aLeading = true ) inline void SetAsLeadingEdge( bool aLeading = true ) { { m_isLeadingEdge = aLeading; m_isLeadingEdge = aLeading; } } /// Checks if an edge is a leading edge /// Checks if an edge is a leading edge bool IsLeadingEdge() const inline bool IsLeadingEdge() const { { return m_isLeadingEdge; return m_isLeadingEdge; } } /// Returns the twin edge /// Returns the twin edge EDGE_PTR GetTwinEdge() const inline EDGE_PTR GetTwinEdge() const { { return m_twinEdge.lock(); return m_twinEdge.lock(); } } void ClearTwinEdge() inline void ClearTwinEdge() { { m_twinEdge.reset(); m_twinEdge.reset(); } } /// Returns the next edge in face /// Returns the next edge in face const EDGE_PTR& GetNextEdgeInFace() const inline const EDGE_PTR& GetNextEdgeInFace() const { { return m_nextEdgeInFace; return m_nextEdgeInFace; } } /// Retuns the source node /// Retuns the source node const NODE_PTR& GetSourceNode() const inline const NODE_PTR& GetSourceNode() const { { return m_sourceNode; return m_sourceNode; } } Loading @@ -246,12 +271,12 @@ public: return m_nextEdgeInFace->GetSourceNode(); return m_nextEdgeInFace->GetSourceNode(); } } void SetWeight( unsigned int weight ) inline void SetWeight( unsigned int weight ) { { m_weight = weight; m_weight = weight; } } unsigned int GetWeight() const inline unsigned int GetWeight() const { { return m_weight; return m_weight; } } Loading Loading @@ -294,22 +319,17 @@ public: m_weight = aWeight; 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() /// @copydoc Edge::setSourceNode() virtual const NODE_PTR& GetTargetNode() const virtual const NODE_PTR& GetTargetNode() const { { return m_target; return m_target; } } private: EDGE_MST( const EDGE& aEdge ) { assert( false ); } }; }; class DART; // Forward declaration (class in this namespace) class DART; // Forward declaration (class in this namespace) Loading
pcbnew/ratsnest_data.cpp +159 −38 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KICAD, a free EDA CAD application. * 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 <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or Loading Loading @@ -96,22 +96,26 @@ bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) } } std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, static std::vector<RN_EDGE_MST_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, const std::vector<RN_NODE_PTR>& aNodes ) std::vector<RN_NODE_PTR>& aNodes ) { { unsigned int nodeNumber = aNodes.size(); unsigned int nodeNumber = aNodes.size(); unsigned int mstExpectedSize = nodeNumber - 1; unsigned int mstExpectedSize = nodeNumber - 1; unsigned int mstSize = 0; unsigned int mstSize = 0; bool ratsnestLines = false; // The output // The output std::vector<RN_EDGE_PTR>* mst = new std::vector<RN_EDGE_PTR>; std::vector<RN_EDGE_MST_PTR>* mst = new std::vector<RN_EDGE_MST_PTR>; mst->reserve( mstExpectedSize ); mst->reserve( mstExpectedSize ); // Set tags for marking cycles // Set tags for marking cycles boost::unordered_map<RN_NODE_PTR, int> tags; boost::unordered_map<RN_NODE_PTR, int> tags; unsigned int tag = 0; 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++; tags[node] = tag++; } // Lists of nodes connected together (subtrees) to detect cycles in the graph // Lists of nodes connected together (subtrees) to detect cycles in the graph std::vector<std::list<int> > cycles( nodeNumber ); std::vector<std::list<int> > cycles( nodeNumber ); Loading @@ -123,27 +127,40 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, while( mstSize < mstExpectedSize && !aEdges.empty() ) while( mstSize < mstExpectedSize && !aEdges.empty() ) { { RN_EDGE_PTR& dt = *aEdges.begin(); RN_EDGE_PTR& dt = aEdges.front(); int srcTag = tags[dt->GetSourceNode()]; int srcTag = tags[dt->GetSourceNode()]; int trgTag = tags[dt->GetTargetNode()]; 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 // Check if by adding this edge we are going to join two different forests if( srcTag != trgTag ) if( srcTag != trgTag ) { { // Update tags // Update tags std::list<int>::iterator it, itEnd; std::list<int>::iterator it, itEnd; if( ratsnestLines ) { for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it ) tags[aNodes[*it]] = srcTag; 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 // Move nodes that were marked with old tag to the list marked with the new tag cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); if( dt->GetWeight() == 0 ) // Skip already existing connections (weight == 0) if( ratsnestLines ) { mstExpectedSize--; } else { { // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE, // 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 // RN_EDGE_MST saves both source and target node and does not require any other Loading @@ -154,6 +171,11 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, mst->push_back( newEdge ); mst->push_back( newEdge ); ++mstSize; ++mstSize; } } else { // Processing a connection, decrease the expected size of the ratsnest MST --mstExpectedSize; } } } // Remove the edge that was just processed // Remove the edge that was just processed Loading @@ -167,7 +189,7 @@ std::vector<RN_EDGE_PTR>* 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 source = aEdge->GetSourceNode(); RN_NODE_PTR target = aEdge->GetTargetNode(); RN_NODE_PTR target = aEdge->GetTargetNode(); Loading Loading @@ -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, RN_EDGE_MST_PTR RN_LINKS::AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, unsigned int aDistance ) unsigned int aDistance ) { { m_edges.push_back( boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ) ); RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ); m_edges.push_back( edge ); return m_edges.back(); return edge; } } Loading @@ -252,10 +275,10 @@ void RN_NET::compute() const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes(); const RN_LINKS::RN_NODE_SET& boardNodes = m_links.GetNodes(); const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections(); const RN_LINKS::RN_EDGE_LIST& boardEdges = m_links.GetConnections(); // Special case that does need so complicated algorithm // Special cases that does need so complicated algorithm if( boardNodes.size() == 2 ) if( boardNodes.size() <= 2 ) { { m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) ); m_rnEdges.reset( new std::vector<RN_EDGE_MST_PTR>( 0 ) ); // Check if the only possible connection exists // Check if the only possible connection exists if( boardEdges.size() == 0 ) if( boardEdges.size() == 0 ) Loading @@ -268,12 +291,6 @@ void RN_NET::compute() return; return; } } else if( boardNodes.size() <= 1 ) // This case is even simpler { m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) ); return; } // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation // Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation std::vector<RN_NODE_PTR> nodes( boardNodes.size() ); std::vector<RN_NODE_PTR> nodes( boardNodes.size() ); Loading Loading @@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode ) if( !m_rnEdges ) if( !m_rnEdges ) return; return; std::vector<RN_EDGE_PTR>::iterator newEnd; std::vector<RN_EDGE_MST_PTR>::iterator newEnd; // Remove all ratsnest edges for associated with the node // Remove all ratsnest edges for associated with the node newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), Loading Loading @@ -377,7 +394,7 @@ void RN_NET::Update() compute(); compute(); BOOST_FOREACH( RN_EDGE_PTR& edge, *m_rnEdges ) BOOST_FOREACH( RN_EDGE_MST_PTR& edge, *m_rnEdges ) validateEdge( edge ); validateEdge( edge ); m_dirty = false; m_dirty = false; Loading @@ -386,8 +403,7 @@ void RN_NET::Update() void RN_NET::AddItem( const D_PAD* aPad ) void RN_NET::AddItem( const D_PAD* aPad ) { { RN_NODE_PTR nodePtr = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); m_pads[aPad] = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); m_pads[aPad] = nodePtr; m_dirty = true; m_dirty = true; } } Loading Loading @@ -505,7 +521,7 @@ void RN_NET::RemoveItem( const TRACK* aTrack ) { { try 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 // Save nodes, so they can be cleared later RN_NODE_PTR aBegin = edge->GetSourceNode(); RN_NODE_PTR aBegin = edge->GetSourceNode(); Loading Loading @@ -546,8 +562,8 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone ) polygons.clear(); polygons.clear(); // Remove all connections added by the zone // Remove all connections added by the zone std::deque<RN_EDGE_PTR>& edges = m_zoneConnections.at( aZone ); std::deque<RN_EDGE_MST_PTR>& edges = m_zoneConnections.at( aZone ); BOOST_FOREACH( RN_EDGE_PTR& edge, edges ) BOOST_FOREACH( RN_EDGE_PTR edge, edges ) m_links.RemoveConnection( edge ); m_links.RemoveConnection( edge ); edges.clear(); edges.clear(); Loading Loading @@ -694,7 +710,7 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con case PCB_TRACE_T: case PCB_TRACE_T: { { const TRACK* track = static_cast<const TRACK*>( aItem ); const TRACK* track = static_cast<const TRACK*>( 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->GetSourceNode() ); nodes.push_back( edge->GetTargetNode() ); nodes.push_back( edge->GetTargetNode() ); Loading @@ -714,6 +730,76 @@ std::list<RN_NODE_PTR> 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<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYPES aTypes ) const { std::list<RN_NODE_PTR> 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<D_PAD*>( 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<VIA*>( 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<TRACK*>( it->first ) ); } } if( aTypes & RN_ZONES ) { for( ZONE_EDGE_MAP::const_iterator it = m_zoneConnections.begin(); it != m_zoneConnections.end(); ++it ) { const std::deque<RN_EDGE_MST_PTR>& edges = it->second; BOOST_FOREACH( const RN_EDGE_MST_PTR& edge, edges ) { if( edge->GetTag() == tag ) { aOutput.push_back( const_cast<ZONE_CONTAINER*>( it->first ) ); break; } } } } } void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) void RN_DATA::AddSimple( const BOARD_ITEM* aItem ) { { int net; int net; Loading Loading @@ -784,11 +870,46 @@ void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) } } void RN_DATA::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, std::list<BOARD_CONNECTED_ITEM*>& 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<RN_NODE_PTR> items1 = m_nets[net1].GetNodes( aItem ); std::list<RN_NODE_PTR> items2 = m_nets[net1].GetNodes( aOther ); assert( !items1.empty() && !items2.empty() ); return ( items1.front()->GetTag() == items2.front()->GetTag() ); } void RN_NET::processZones() void RN_NET::processZones() { { BOOST_FOREACH( std::deque<RN_EDGE_PTR>& edges, m_zoneConnections | boost::adaptors::map_values ) BOOST_FOREACH( std::deque<RN_EDGE_MST_PTR>& 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 ); m_links.RemoveConnection( edge ); edges.clear(); edges.clear(); Loading @@ -814,7 +935,7 @@ void RN_NET::processZones() { { if( poly->HitTest( *point ) ) 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 ); m_zoneConnections[poly->GetParent()].push_back( connection ); // This point already belongs to a polygon, we do not need to check it anymore // This point already belongs to a polygon, we do not need to check it anymore Loading
pcbnew/ratsnest_data.h +65 −39 Original line number Original line Diff line number Diff line /* /* * This program source code file is part of KICAD, a free EDA CAD application. * 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 <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch> * * * This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or Loading Loading @@ -49,6 +49,16 @@ class TRACK; class ZONE_CONTAINER; class ZONE_CONTAINER; class CPolyPt; 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 // Preserve KiCad coding style policy typedef hed::NODE RN_NODE; typedef hed::NODE RN_NODE; typedef hed::NODE_PTR RN_NODE_PTR; typedef hed::NODE_PTR RN_NODE_PTR; Loading Loading @@ -157,7 +167,7 @@ public: * @param aDistance is the distance of the connection (0 means that nodes are actually * @param aDistance is the distance of the connection (0 means that nodes are actually * connected, >0 means a missing connection). * connected, >0 means a missing connection). */ */ const RN_EDGE_PTR& AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, RN_EDGE_MST_PTR AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2, unsigned int aDistance = 0 ); unsigned int aDistance = 0 ); /** /** Loading @@ -181,7 +191,7 @@ public: } } protected: 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; RN_NODE_SET m_nodes; ///> List of edges that currently connect nodes. ///> List of edges that currently connect nodes. Loading Loading @@ -210,7 +220,6 @@ public: return m_node; return m_node; } } /** /** * Function GetParent() * Function GetParent() * Returns pointer to zone that is the owner of subpolygon. * Returns pointer to zone that is the owner of subpolygon. Loading Loading @@ -307,7 +316,7 @@ public: * Returns pointer to a vector of edges that makes ratsnest for a given net. * 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. * @return Pointer to a vector of edges that makes ratsnest for a given net. */ */ const std::vector<RN_EDGE_PTR>* GetUnconnected() const const std::vector<RN_EDGE_MST_PTR>* GetUnconnected() const { { return m_rnEdges.get(); return m_rnEdges.get(); } } Loading Loading @@ -429,22 +438,12 @@ public: std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const; 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<RN_EDGE_PTR>* GetEdges() const { return m_rnEdges.get(); } /** /** * Function AddSimpleNode() * Function AddSimpleNode() * Changes drawing mode for a node to simple (i.e. one ratsnest line per node). * 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. * @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 ); m_simpleNodes.push_back( aNode ); aNode->SetFlag( true ); aNode->SetFlag( true ); Loading @@ -456,7 +455,7 @@ public: * target the node). The status is cleared after calling ClearSimple(). * 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. * @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 ); m_blockedNodes.push_back( aNode ); aNode->SetFlag( true ); aNode->SetFlag( true ); Loading @@ -468,7 +467,7 @@ public: * ratsnest line per node). * ratsnest line per node). * @return list of nodes for which ratsnest is drawn in simple mode. * @return list of nodes for which ratsnest is drawn in simple mode. */ */ const std::deque<RN_NODE_PTR>& GetSimpleNodes() const inline const std::deque<RN_NODE_PTR>& GetSimpleNodes() const { { return m_simpleNodes; return m_simpleNodes; } } Loading @@ -477,22 +476,23 @@ public: * Function ClearSimple() * Function ClearSimple() * Removes all nodes and edges that are used for displaying ratsnest in simple mode. * Removes all nodes and edges that are used for displaying ratsnest in simple mode. */ */ void ClearSimple() void 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(); * 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<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYPES aTypes = RN_ALL) const; protected: protected: ///> Validates edge, i.e. 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. ///> 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. ///> Removes all ratsnest edges for a given node. void clearNode( const RN_NODE_PTR& aNode ); void clearNode( const RN_NODE_PTR& aNode ); Loading @@ -507,31 +507,37 @@ protected: RN_LINKS m_links; RN_LINKS m_links; ///> Vector of edges that makes ratsnest for a given net. ///> Vector of edges that makes ratsnest for a given net. boost::shared_ptr< std::vector<RN_EDGE_PTR> > m_rnEdges; boost::shared_ptr< std::vector<RN_EDGE_MST_PTR> > m_rnEdges; ///> List of nodes for which ratsnest is drawn in simple mode. ///> List of nodes for which ratsnest is drawn in simple mode. std::deque<RN_NODE_PTR> m_simpleNodes; std::deque<RN_NODE_PTR> 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<RN_NODE_PTR> m_blockedNodes; std::deque<RN_NODE_PTR> m_blockedNodes; ///> Flag indicating necessity of recalculation of ratsnest for a net. ///> Flag indicating necessity of recalculation of ratsnest for a net. bool m_dirty; bool m_dirty; ///> Helper typedefs typedef boost::unordered_map<const D_PAD*, RN_NODE_PTR> PAD_NODE_MAP; typedef boost::unordered_map<const VIA*, RN_NODE_PTR> VIA_NODE_MAP; typedef boost::unordered_map<const TRACK*, RN_EDGE_MST_PTR> TRACK_EDGE_MAP; typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > ZONE_POLY_MAP; typedef boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_MST_PTR> > ZONE_EDGE_MAP; ///> Map that associates nodes in the ratsnest model to respective nodes. ///> Map that associates nodes in the ratsnest model to respective nodes. boost::unordered_map<const D_PAD*, RN_NODE_PTR> m_pads; PAD_NODE_MAP m_pads; ///> Map that associates nodes in the ratsnest model to respective vias. ///> Map that associates nodes in the ratsnest model to respective vias. boost::unordered_map<const VIA*, RN_NODE_PTR> m_vias; VIA_NODE_MAP m_vias; ///> Map that associates edges in the ratsnest model to respective tracks. ///> Map that associates edges in the ratsnest model to respective tracks. boost::unordered_map<const TRACK*, RN_EDGE_PTR> m_tracks; TRACK_EDGE_MAP m_tracks; ///> Map that associates groups of subpolygons in the ratsnest model to their respective zones. ///> Map that associates groups of subpolygons in the ratsnest model to respective zones. boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > m_zonePolygons; ZONE_POLY_MAP m_zonePolygons; ///> Map that associates groups of edges in the ratsnest model to their respective zones. ///> Map that associates groups of edges in the ratsnest model to respective zones. boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_EDGE_PTR> > m_zoneConnections; ZONE_EDGE_MAP m_zoneConnections; ///> Visibility flag. ///> Visibility flag. bool m_visible; bool m_visible; Loading Loading @@ -646,6 +652,26 @@ public: return m_nets[aNetCode]; 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<BOARD_CONNECTED_ITEM*>& 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: protected: /** /** * Function updateNet() * Function updateNet() Loading
pcbnew/ratsnest_viewitem.cpp +4 −3 Original line number Original line Diff line number Diff line Loading @@ -72,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const // Set brighter color for the temporary ratsnest // Set brighter color for the temporary ratsnest aGal->SetStrokeColor( color.Brightened( 0.8 ) ); 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() ) BOOST_FOREACH( const RN_NODE_PTR& node, net.GetSimpleNodes() ) { { RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); Loading @@ -93,11 +93,12 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const if( i != highlightedNet ) if( i != highlightedNet ) aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted const std::vector<RN_EDGE_PTR>* edges = net.GetUnconnected(); const std::vector<RN_EDGE_MST_PTR>* edges = net.GetUnconnected(); if( edges == NULL ) if( edges == NULL ) continue; 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& sourceNode = edge->GetSourceNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode(); Loading