Ratsnest fix (GAL).

This commit is contained in:
Maciej Suminski 2015-06-04 14:54:07 +02:00
parent d89d1d49a3
commit a2b8ab6b41
3 changed files with 67 additions and 44 deletions

View File

@ -42,7 +42,7 @@
#ifndef _HE_TRIANG_H_
#define _HE_TRIANG_H_
#define TTL_USE_NODE_ID // Each node gets it's own unique id
//#define TTL_USE_NODE_ID // Each node gets it's own unique id
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
#include <list>

View File

@ -136,15 +136,15 @@ static std::vector<RN_EDGE_MST_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
int srcTag = tags[dt->GetSourceNode()];
int trgTag = tags[dt->GetTargetNode()];
// Check if by adding this edge we are going to join two different forests
if( srcTag != trgTag )
{
// 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;
@ -267,6 +267,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,
unsigned int aDistance )
{
assert( aNode1 != aNode2 );
RN_EDGE_MST_PTR edge = boost::make_shared<RN_EDGE_MST>( aNode1, aNode2, aDistance );
m_edges.push_back( edge );
@ -279,7 +280,7 @@ 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 cases that does need so complicated algorithm
// Special cases do not need complicated algorithms
if( boardNodes.size() <= 2 )
{
m_rnEdges.reset( new std::vector<RN_EDGE_MST_PTR>( 0 ) );
@ -326,7 +327,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode )
// Remove all ratsnest edges for associated with the node
newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(),
boost::bind( isEdgeConnectingNode, _1, boost::ref( aNode ) ) );
boost::bind( isEdgeConnectingNode, _1, boost::cref( aNode ) ) );
m_rnEdges->resize( std::distance( m_rnEdges->begin(), newEnd ) );
}
@ -334,11 +335,11 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode )
RN_POLY::RN_POLY( const CPolyPt* aBegin, const CPolyPt* aEnd, const ZONE_CONTAINER* aParent,
RN_LINKS& aConnections, const BOX2I& aBBox ) :
m_parent( aParent), m_begin( aBegin ), m_end( aEnd ), m_bbox( aBBox )
m_parent( aParent ), m_begin( aBegin ), m_end( aEnd ), m_bbox( aBBox )
{
m_node = aConnections.AddNode( m_begin->x, m_begin->y );
// Mark it as not feasible as a destination of ratsnest edges
// Mark it as not appropriate as a destination of ratsnest edges
// (edges coming out from a polygon vertex look weird)
m_node->SetFlag( true );
}
@ -426,9 +427,11 @@ void RN_NET::AddItem( const TRACK* aTrack )
RN_NODE_PTR start = m_links.AddNode( aTrack->GetStart().x, aTrack->GetStart().y );
RN_NODE_PTR end = m_links.AddNode( aTrack->GetEnd().x, aTrack->GetEnd().y );
if( start != end )
{
m_tracks[aTrack] = m_links.AddConnection( start, end );
m_dirty = true;
}
}
@ -436,6 +439,7 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone )
{
// Prepare a list of polygons (every zone can contain one or more polygons)
const std::vector<CPolyPt>& polyPoints = aZone->GetFilledPolysList().GetList();
if( polyPoints.size() == 0 )
return;
@ -449,21 +453,8 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone )
{
const CPolyPt& point = polyPoints[i];
// Determine bounding box
if( point.x < origin.x )
origin.x = point.x;
else if( point.x > end.x )
end.x = point.x;
if( point.y < origin.y )
origin.y = point.y;
else if( point.y > end.y )
end.y = point.y;
if( point.end_contour )
{
// The last vertex is enclosing the polygon (it repeats at the beginning and
// at the end), so we skip it
m_zonePolygons[aZone].push_back( RN_POLY( &polyPoints[idxStart], &point, aZone,
m_links, BOX2I( origin, end - origin ) ) );
@ -477,6 +468,19 @@ void RN_NET::AddItem( const ZONE_CONTAINER* aZone )
end.y = polyPoints[idxStart].y;
}
}
else
{
// Determine bounding box
if( point.x < origin.x )
origin.x = point.x;
else if( point.x > end.x )
end.x = point.x;
if( point.y < origin.y )
origin.y = point.y;
else if( point.y > end.y )
end.y = point.y;
}
}
m_dirty = true;
@ -721,11 +725,21 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
}
break;
case PCB_ZONE_AREA_T:
{
const ZONE_CONTAINER* zone = static_cast<const ZONE_CONTAINER*>( aItem );
const std::deque<RN_POLY>& polys = m_zonePolygons.at( zone );
for( std::deque<RN_POLY>::const_iterator it = polys.begin(); it != polys.end(); ++it )
nodes.push_back( it->GetNode() );
}
break;
default:
break;
}
}
catch ( ... )
catch( ... )
{
return nodes;
}
@ -959,30 +973,32 @@ void RN_NET::processZones()
edges.clear();
}
RN_LINKS::RN_NODE_SET candidates = m_links.GetNodes();
BOOST_FOREACH( std::deque<RN_POLY>& polygons, m_zonePolygons | boost::adaptors::map_values )
{
if( polygons.empty() )
continue;
RN_LINKS::RN_NODE_SET candidates = m_links.GetNodes();
RN_LINKS::RN_NODE_SET::iterator point, pointEnd;
// Sorting by area should speed up the processing, as smaller polygons are computed
// faster and may reduce the number of points for further checks
std::sort( polygons.begin(), polygons.end(), sortArea );
std::deque<RN_POLY>::iterator poly = polygons.begin(), polyEnd = polygons.end();
for( std::deque<RN_POLY>::iterator poly = polygons.begin(), polyEnd = polygons.end();
poly != polyEnd; ++poly )
{
const RN_NODE_PTR& node = poly->GetNode();
std::deque<RN_EDGE_MST_PTR>& connections = m_zoneConnections[poly->GetParent()];
for( ; poly != polyEnd; ++poly )
{
point = candidates.begin();
pointEnd = candidates.end();
while( point != pointEnd )
{
if( *point == node )
{
++point;
continue;
}
if( poly->HitTest( *point ) )
{
RN_EDGE_MST_PTR connection = m_links.AddConnection( node, *point );
@ -1142,8 +1158,9 @@ void RN_DATA::Update( const BOARD_ITEM* aItem )
void RN_DATA::ProcessBoard()
{
int netCount = m_board->GetNetCount();
m_nets.clear();
m_nets.resize( m_board->GetNetCount() );
m_nets.resize( netCount );
int netCode;
// Iterate over all items that may need to be connected
@ -1153,7 +1170,9 @@ void RN_DATA::ProcessBoard()
{
netCode = pad->GetNetCode();
if( netCode > 0 )
assert( netCode >= 0 && netCode < netCount );
if( netCode > 0 && netCode < netCount )
m_nets[netCode].AddItem( pad );
}
}
@ -1162,7 +1181,9 @@ void RN_DATA::ProcessBoard()
{
netCode = track->GetNetCode();
if( netCode > 0 )
assert( netCode >= 0 && netCode < netCount );
if( netCode > 0 && netCode < netCount )
{
if( track->Type() == PCB_VIA_T )
m_nets[netCode].AddItem( static_cast<VIA*>( track ) );
@ -1177,7 +1198,9 @@ void RN_DATA::ProcessBoard()
netCode = zone->GetNetCode();
if( netCode > 0 )
assert( netCode >= 0 && netCode < netCount );
if( netCode > 0 && netCode < netCount )
m_nets[netCode].AddItem( zone );
}

View File

@ -215,7 +215,7 @@ public:
* Returns node representing a polygon (it has the same coordinates as the first point of its
* bounding polyline.
*/
const RN_NODE_PTR& GetNode() const
inline const RN_NODE_PTR& GetNode() const
{
return m_node;
}
@ -556,7 +556,7 @@ protected:
/**
* Class RN_DATA
*
* Stores information about unconnected items for the whole PCB.
* Stores information about unconnected items for a board.
*/
class RN_DATA
{