2011-11-06 16:16:19 +00:00
|
|
|
/**
|
2011-11-07 18:04:19 +00:00
|
|
|
* @file minimun_spanning_tree.cpp
|
2011-11-06 16:16:19 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Jean-Pierre Charras
|
|
|
|
* Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
|
|
|
|
*
|
|
|
|
* derived from this article:
|
|
|
|
* http://compprog.wordpress.com/2007/11/09/minimal-spanning-trees-prims-algorithm
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
2011-11-07 18:04:19 +00:00
|
|
|
#include "minimun_spanning_tree.h"
|
2011-11-06 16:16:19 +00:00
|
|
|
#include "class_pad.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The class MIN_SPAN_TREE calculates the rectilinear minimum spanning tree
|
|
|
|
* of a set of points (pads usually having the same net)
|
|
|
|
* using the Prim's algorithm.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prim's Algorithm
|
|
|
|
* Step 0
|
|
|
|
* Pick any vertex as a starting vertex. (Call it S).
|
|
|
|
* Mark it with any given flag, say 1.
|
|
|
|
*
|
|
|
|
* Step 1
|
|
|
|
* Find the nearest neighbour of S (call it P1).
|
|
|
|
* Mark both P1 and the edge SP1.
|
|
|
|
* cheapest unmarked edge in the graph that doesn't close a marked circuit.
|
|
|
|
* Mark this edge.
|
|
|
|
*
|
|
|
|
* Step 2
|
|
|
|
* Find the nearest unmarked neighbour to the marked subgraph
|
|
|
|
* (i.e., the closest vertex to any marked vertex).
|
|
|
|
* Mark it and the edge connecting the vertex.
|
|
|
|
*
|
|
|
|
* Step 3
|
|
|
|
* Repeat Step 2 until all vertices are marked.
|
|
|
|
* The marked subgraph is a minimum spanning tree.
|
|
|
|
*/
|
|
|
|
MIN_SPAN_TREE::MIN_SPAN_TREE()
|
|
|
|
{
|
|
|
|
MSP_Init( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MIN_SPAN_TREE::MSP_Init( int aNodesCount )
|
|
|
|
{
|
|
|
|
m_Size = aNodesCount;
|
|
|
|
inTree.clear();
|
|
|
|
linkedTo.clear();
|
|
|
|
distTo.clear();
|
|
|
|
|
|
|
|
if( m_Size == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Reserve space in memory
|
|
|
|
inTree.reserve( m_Size );
|
|
|
|
linkedTo.reserve( m_Size );
|
|
|
|
distTo.reserve( m_Size );
|
|
|
|
|
|
|
|
// Initialize values:
|
|
|
|
for( int ii = 0; ii < m_Size; ii++ )
|
|
|
|
{
|
|
|
|
// Initialise dist with infinity:
|
|
|
|
distTo.push_back( INT_MAX );
|
|
|
|
|
|
|
|
// Mark all nodes as NOT beeing in the minimum spanning tree:
|
|
|
|
inTree.push_back( 0 );
|
|
|
|
|
|
|
|
linkedTo.push_back( 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* updateDistances(int target)
|
|
|
|
* should be called immediately after target is added to the tree;
|
|
|
|
* updates dist so that the values are correct (goes through target's
|
|
|
|
* neighbours making sure that the distances between them and the tree
|
|
|
|
* are indeed minimum)
|
|
|
|
*/
|
|
|
|
void MIN_SPAN_TREE::updateDistances( int target )
|
|
|
|
{
|
|
|
|
for( int ii = 0; ii < m_Size; ++ii )
|
|
|
|
{
|
|
|
|
if( !inTree[ii] ) // no need to evaluate weight for already in tree items
|
|
|
|
{
|
|
|
|
int weight = GetWeight( target, ii );
|
|
|
|
if( (weight > 0) && (distTo[ii] > weight ) )
|
|
|
|
{
|
|
|
|
distTo[ii] = weight;
|
|
|
|
linkedTo[ii] = target;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MIN_SPAN_TREE::BuildTree()
|
|
|
|
{
|
|
|
|
/* Add the first node to the tree */
|
|
|
|
inTree[0] = 1;
|
|
|
|
updateDistances( 0 );
|
|
|
|
|
|
|
|
for( int treeSize = 1; treeSize < m_Size; ++treeSize )
|
|
|
|
{
|
|
|
|
// Find the node with the smallest distance to the tree
|
|
|
|
int min = -1;
|
|
|
|
for( int ii = 0; ii < m_Size; ++ii )
|
|
|
|
{
|
|
|
|
if( !inTree[ii] )
|
|
|
|
{
|
|
|
|
if( (min == -1) || (distTo[min] > distTo[ii]) )
|
|
|
|
min = ii;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inTree[min] = 1;
|
|
|
|
updateDistances( min );
|
|
|
|
}
|
|
|
|
}
|