Commit 190af5d9 authored by Maciej Suminski's avatar Maciej Suminski

Added functions to resolve connectivity queries in ratsnest (GAL).

parent e6a10faa
...@@ -100,6 +100,9 @@ protected: ...@@ -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;
...@@ -112,7 +115,7 @@ public: ...@@ -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 )
{ {
} }
...@@ -120,20 +123,32 @@ public: ...@@ -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;
} }
...@@ -141,29 +156,29 @@ public: ...@@ -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;
} }
...@@ -187,55 +202,65 @@ public: ...@@ -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;
} }
...@@ -246,12 +271,12 @@ public: ...@@ -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;
} }
...@@ -294,22 +319,17 @@ public: ...@@ -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)
......
/* /*
* 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
...@@ -96,22 +96,26 @@ bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) ...@@ -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 );
...@@ -123,27 +127,40 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -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
...@@ -154,6 +171,11 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -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
...@@ -167,7 +189,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -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();
...@@ -238,12 +260,13 @@ bool RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode ) ...@@ -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;
} }
...@@ -252,10 +275,10 @@ void RN_NET::compute() ...@@ -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 )
...@@ -268,12 +291,6 @@ void RN_NET::compute() ...@@ -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() );
...@@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode ) ...@@ -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(),
...@@ -377,7 +394,7 @@ void RN_NET::Update() ...@@ -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;
...@@ -386,8 +403,7 @@ void RN_NET::Update() ...@@ -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;
} }
...@@ -505,7 +521,7 @@ void RN_NET::RemoveItem( const TRACK* aTrack ) ...@@ -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();
...@@ -546,8 +562,8 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone ) ...@@ -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();
...@@ -694,7 +710,7 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con ...@@ -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() );
...@@ -714,6 +730,76 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con ...@@ -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;
...@@ -784,11 +870,46 @@ void RN_DATA::AddSimple( const VECTOR2I& aPosition, int aNetCode ) ...@@ -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();
...@@ -814,7 +935,7 @@ void RN_NET::processZones() ...@@ -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
......
/* /*
* 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
...@@ -49,6 +49,16 @@ class TRACK; ...@@ -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;
...@@ -157,7 +167,7 @@ public: ...@@ -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 );
/** /**
...@@ -181,7 +191,7 @@ public: ...@@ -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.
...@@ -210,7 +220,6 @@ public: ...@@ -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.
...@@ -307,7 +316,7 @@ public: ...@@ -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();
} }
...@@ -429,22 +438,12 @@ public: ...@@ -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 );
...@@ -456,7 +455,7 @@ public: ...@@ -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 );
...@@ -468,7 +467,7 @@ public: ...@@ -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;
} }
...@@ -477,22 +476,23 @@ public: ...@@ -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 );
...@@ -507,31 +507,37 @@ protected: ...@@ -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;
...@@ -646,6 +652,26 @@ public: ...@@ -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()
......
...@@ -72,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const ...@@ -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() );
...@@ -93,11 +93,12 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const ...@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment