Added functions to resolve connectivity queries in ratsnest (GAL).
This commit is contained in:
parent
e6a10faab7
commit
190af5d95b
|
@ -4,21 +4,21 @@
|
|||
* Copyright (C) 2013 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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<EDGE_PTR>* 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.
|
||||
|
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
|
||||
const std::vector<RN_NODE_PTR>& aNodes )
|
||||
static std::vector<RN_EDGE_MST_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
|
||||
std::vector<RN_NODE_PTR>& aNodes )
|
||||
{
|
||||
unsigned int nodeNumber = aNodes.size();
|
||||
unsigned int mstExpectedSize = nodeNumber - 1;
|
||||
unsigned int mstSize = 0;
|
||||
bool ratsnestLines = false;
|
||||
|
||||
// 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 );
|
||||
|
||||
// Set tags for marking cycles
|
||||
boost::unordered_map<RN_NODE_PTR, int> 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<std::list<int> > cycles( nodeNumber );
|
||||
|
@ -123,27 +127,40 @@ std::vector<RN_EDGE_PTR>* 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<int>::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<RN_EDGE_PTR>* 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<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 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<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()
|
|||
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<RN_EDGE_PTR>( 0 ) );
|
||||
m_rnEdges.reset( new std::vector<RN_EDGE_MST_PTR>( 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<RN_EDGE_PTR>( 0 ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Move and sort (sorting speeds up) all nodes to a vector for the Delaunay triangulation
|
||||
std::vector<RN_NODE_PTR> nodes( boardNodes.size() );
|
||||
|
@ -301,7 +318,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode )
|
|||
if( !m_rnEdges )
|
||||
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
|
||||
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<RN_EDGE_PTR>& edges = m_zoneConnections.at( aZone );
|
||||
BOOST_FOREACH( RN_EDGE_PTR& edge, edges )
|
||||
std::deque<RN_EDGE_MST_PTR>& 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_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
|
|||
case PCB_TRACE_T:
|
||||
{
|
||||
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->GetTargetNode() );
|
||||
|
@ -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 )
|
||||
{
|
||||
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<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()
|
||||
{
|
||||
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 );
|
||||
|
||||
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
|
||||
|
|
|
@ -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 <maciej.suminski@cern.ch>
|
||||
*
|
||||
* 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<RN_EDGE_PTR>* GetUnconnected() const
|
||||
const std::vector<RN_EDGE_MST_PTR>* GetUnconnected() const
|
||||
{
|
||||
return m_rnEdges.get();
|
||||
}
|
||||
|
@ -429,22 +438,12 @@ public:
|
|||
std::list<RN_NODE_PTR> 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<RN_EDGE_PTR>* 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<RN_NODE_PTR>& GetSimpleNodes() const
|
||||
inline const std::deque<RN_NODE_PTR>& 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<BOARD_CONNECTED_ITEM*>& 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<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.
|
||||
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;
|
||||
|
||||
///> Flag indicating necessity of recalculation of ratsnest for a net.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
boost::unordered_map<const ZONE_CONTAINER*, std::deque<RN_POLY> > 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<const ZONE_CONTAINER*, std::deque<RN_EDGE_PTR> > 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<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:
|
||||
/**
|
||||
* Function updateNet()
|
||||
|
|
|
@ -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<RN_EDGE_PTR>* edges = net.GetUnconnected();
|
||||
const std::vector<RN_EDGE_MST_PTR>* 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();
|
||||
|
|
Loading…
Reference in New Issue