Ratsnest algorithm handles items in pad areas (GAL).

This commit is contained in:
Maciej Suminski 2015-09-01 13:44:07 +02:00
parent 24e7f961b9
commit 3cddf14e73
2 changed files with 128 additions and 66 deletions

View File

@ -251,6 +251,43 @@ void RN_NET::validateEdge( RN_EDGE_MST_PTR& aEdge )
} }
void RN_NET::removeNode( RN_NODE_PTR& aNode, const BOARD_CONNECTED_ITEM* aParent )
{
aNode->RemoveParent( aParent );
if( m_links.RemoveNode( aNode ) )
{
clearNode( aNode );
m_dirty = true;
}
}
void RN_NET::removeEdge( RN_EDGE_MST_PTR& aEdge, const BOARD_CONNECTED_ITEM* aParent )
{
// Save nodes, so they can be cleared later
RN_NODE_PTR start = aEdge->GetSourceNode();
RN_NODE_PTR end = aEdge->GetTargetNode();
start->RemoveParent( aParent );
end->RemoveParent( aParent );
// Connection has to be removed before running RemoveNode(),
// as RN_NODE influences the reference counter
m_links.RemoveConnection( aEdge );
// Remove nodes associated with the edge. It is done in a safe way, there is a check
// if nodes are not used by other edges.
if( m_links.RemoveNode( start ) )
clearNode( start );
if( m_links.RemoveNode( end ) )
clearNode( end );
m_dirty = true;
}
const RN_NODE_PTR& RN_LINKS::AddNode( int aX, int aY ) const RN_NODE_PTR& RN_LINKS::AddNode( int aX, int aY )
{ {
RN_NODE_SET::iterator node; RN_NODE_SET::iterator node;
@ -276,7 +313,7 @@ bool RN_LINKS::RemoveNode( const RN_NODE_PTR& aNode )
RN_EDGE_MST_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 )
{ {
assert( aNode1 != aNode2 ); assert( aNode1 != aNode2 );
RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance ); RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance );
@ -377,6 +414,7 @@ void RN_NET::Update()
{ {
// Add edges resulting from nodes being connected by zones // Add edges resulting from nodes being connected by zones
processZones(); processZones();
processPads();
compute(); compute();
@ -391,7 +429,7 @@ void RN_NET::AddItem( const D_PAD* aPad )
{ {
RN_NODE_PTR node = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y ); RN_NODE_PTR node = m_links.AddNode( aPad->GetPosition().x, aPad->GetPosition().y );
node->AddParent( aPad ); node->AddParent( aPad );
m_pads[aPad] = node; m_pads[aPad].m_Node = node;
m_dirty = true; m_dirty = true;
} }
@ -442,73 +480,42 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone )
void RN_NET::RemoveItem( const D_PAD* aPad ) void RN_NET::RemoveItem( const D_PAD* aPad )
{ {
try PAD_NODE_MAP::iterator it = m_pads.find( aPad );
{
RN_NODE_PTR node = m_pads.at( aPad );
node->RemoveParent( aPad );
if( m_links.RemoveNode( node ) ) if( it == m_pads.end() )
clearNode( node ); return;
m_pads.erase( aPad ); RN_PAD_DATA& pad_data = it->second;
removeNode( pad_data.m_Node, aPad );
m_dirty = true; BOOST_FOREACH( RN_EDGE_MST_PTR& edge, pad_data.m_Edges )
} removeEdge( edge, aPad );
catch( ... )
{ m_pads.erase( aPad );
}
} }
void RN_NET::RemoveItem( const VIA* aVia ) void RN_NET::RemoveItem( const VIA* aVia )
{ {
try VIA_NODE_MAP::iterator it = m_vias.find( aVia );
{
RN_NODE_PTR node = m_vias.at( aVia );
node->RemoveParent( aVia );
if( m_links.RemoveNode( node ) ) if( it == m_vias.end() )
clearNode( node ); return;
m_vias.erase( aVia ); removeNode( it->second, aVia );
m_vias.erase( it );
m_dirty = true;
}
catch( ... )
{
}
} }
void RN_NET::RemoveItem( const TRACK* aTrack ) void RN_NET::RemoveItem( const TRACK* aTrack )
{ {
try TRACK_EDGE_MAP::iterator it = m_tracks.find( aTrack );
{
RN_EDGE_MST_PTR& edge = m_tracks.at( aTrack );
// Save nodes, so they can be cleared later if( it == m_tracks.end() )
RN_NODE_PTR start = edge->GetSourceNode(); return;
start->RemoveParent( aTrack );
RN_NODE_PTR end = edge->GetTargetNode();
end->RemoveParent( aTrack );
m_links.RemoveConnection( edge ); removeEdge( it->second, aTrack );
m_tracks.erase( it );
// Remove nodes associated with the edge. It is done in a safe way, there is a check
// if nodes are not used by other edges.
if( m_links.RemoveNode( start ) )
clearNode( start );
if( m_links.RemoveNode( end ) )
clearNode( end );
m_tracks.erase( aTrack );
m_dirty = true;
}
catch( ... )
{
}
} }
@ -524,24 +531,16 @@ void RN_NET::RemoveItem( const ZONE_CONTAINER* aZone )
// Remove all subpolygons that make the zone // Remove all subpolygons that make the zone
std::deque<RN_POLY>& polygons = zoneData.m_Polygons; std::deque<RN_POLY>& polygons = zoneData.m_Polygons;
BOOST_FOREACH( RN_POLY& polygon, polygons ) BOOST_FOREACH( RN_POLY& polygon, polygons )
{ removeNode( polygon.GetNode(), aZone );
RN_NODE_PTR node = polygon.GetNode();
node->RemoveParent( aZone );
if( m_links.RemoveNode( node ) )
clearNode( node );
}
polygons.clear(); polygons.clear();
// Remove all connections added by the zone // Remove all connections added by the zone
std::deque<RN_EDGE_MST_PTR>& edges = zoneData.m_Edges; std::deque<RN_EDGE_MST_PTR>& edges = zoneData.m_Edges;
BOOST_FOREACH( RN_EDGE_PTR edge, edges ) BOOST_FOREACH( RN_EDGE_MST_PTR edge, edges )
m_links.RemoveConnection( edge ); removeEdge( edge, aZone );
edges.clear(); edges.clear();
m_zones.erase( it ); m_zones.erase( it );
m_dirty = true;
} }
@ -680,7 +679,7 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
case PCB_PAD_T: case PCB_PAD_T:
{ {
const D_PAD* pad = static_cast<const D_PAD*>( aItem ); const D_PAD* pad = static_cast<const D_PAD*>( aItem );
nodes.push_back( m_pads.at( pad ) ); nodes.push_back( m_pads.at( pad ).m_Node );
} }
break; break;
@ -776,7 +775,7 @@ void RN_NET::GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
{ {
for( PAD_NODE_MAP::const_iterator it = m_pads.begin(); it != m_pads.end(); ++it ) for( PAD_NODE_MAP::const_iterator it = m_pads.begin(); it != m_pads.end(); ++it )
{ {
if( it->second->GetTag() == tag ) if( it->second.m_Node->GetTag() == tag )
aOutput.push_back( const_cast<D_PAD*>( it->first ) ); aOutput.push_back( const_cast<D_PAD*>( it->first ) );
} }
} }
@ -972,6 +971,8 @@ void RN_NET::processZones()
if( *point != node && ( (*point)->GetLayers() & layers ).any() if( *point != node && ( (*point)->GetLayers() & layers ).any()
&& poly->HitTest( *point ) ) && poly->HitTest( *point ) )
{ {
//(*point)->AddParent( zone ); // do not assign parent for helper links
RN_EDGE_MST_PTR connection = m_links.AddConnection( node, *point ); RN_EDGE_MST_PTR connection = m_links.AddConnection( node, *point );
zoneData.m_Edges.push_back( connection ); zoneData.m_Edges.push_back( connection );
@ -989,6 +990,42 @@ void RN_NET::processZones()
} }
void RN_NET::processPads()
{
for( PAD_NODE_MAP::iterator it = m_pads.begin(); it != m_pads.end(); ++it )
{
const D_PAD* pad = it->first;
RN_NODE_PTR node = it->second.m_Node;
std::deque<RN_EDGE_MST_PTR>& edges = it->second.m_Edges;
// Reset existing connections
BOOST_FOREACH( RN_EDGE_MST_PTR edge, edges )
m_links.RemoveConnection( edge );
LSET layers = pad->GetLayerSet();
RN_LINKS::RN_NODE_SET candidates = m_links.GetNodes();
RN_LINKS::RN_NODE_SET::iterator point, pointEnd;
point = candidates.begin();
pointEnd = candidates.end();
while( point != pointEnd )
{
if( *point != node && ( (*point)->GetLayers() & layers ).any() &&
pad->HitTest( wxPoint( (*point)->GetX(), (*point)->GetY() ) ) )
{
//(*point)->AddParent( pad ); // do not assign parent for helper links
RN_EDGE_MST_PTR connection = m_links.AddConnection( node, *point );
edges.push_back( connection );
}
++point;
}
}
}
void RN_DATA::Add( const BOARD_ITEM* aItem ) void RN_DATA::Add( const BOARD_ITEM* aItem )
{ {
int net; int net;

View File

@ -279,6 +279,11 @@ public:
return m_node; return m_node;
} }
inline RN_NODE_PTR& GetNode()
{
return m_node;
}
/** /**
* Function HitTest() * Function HitTest()
* Tests if selected node is located within polygon boundaries. * Tests if selected node is located within polygon boundaries.
@ -545,12 +550,21 @@ protected:
///> 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_MST_PTR& aEdge ); void validateEdge( RN_EDGE_MST_PTR& aEdge );
// TODO
void removeNode( RN_NODE_PTR& aNode, const BOARD_CONNECTED_ITEM* aParent );
// TODO
void removeEdge( RN_EDGE_MST_PTR& aEdge, const BOARD_CONNECTED_ITEM* aParent );
///> 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 );
///> Adds appropriate edges for nodes that are connected by zones. ///> Adds appropriate edges for nodes that are connected by zones.
void processZones(); void processZones();
// TODO
void processPads();
///> Recomputes ratsnset from scratch. ///> Recomputes ratsnset from scratch.
void compute(); void compute();
@ -569,6 +583,7 @@ protected:
///> 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;
// TODO
typedef struct typedef struct
{ {
///> Subpolygons belonging to a zone ///> Subpolygons belonging to a zone
@ -578,8 +593,18 @@ protected:
std::deque<RN_EDGE_MST_PTR> m_Edges; std::deque<RN_EDGE_MST_PTR> m_Edges;
} RN_ZONE_DATA; } RN_ZONE_DATA;
// TODO
typedef struct
{
// TODO
RN_NODE_PTR m_Node;
// TODO
std::deque<RN_EDGE_MST_PTR> m_Edges;
} RN_PAD_DATA;
///> Helper typedefs ///> Helper typedefs
typedef boost::unordered_map<const D_PAD*, RN_NODE_PTR> PAD_NODE_MAP; typedef boost::unordered_map<const D_PAD*, RN_PAD_DATA> PAD_NODE_MAP;
typedef boost::unordered_map<const VIA*, RN_NODE_PTR> VIA_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 TRACK*, RN_EDGE_MST_PTR> TRACK_EDGE_MAP;
typedef boost::unordered_map<const ZONE_CONTAINER*, RN_ZONE_DATA> ZONE_DATA_MAP; typedef boost::unordered_map<const ZONE_CONTAINER*, RN_ZONE_DATA> ZONE_DATA_MAP;