You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							145 lines
						
					
					
						
							4.0 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							145 lines
						
					
					
						
							4.0 KiB
						
					
					
				| /** | |
|  * @file minimun_spanning_tree.cpp | |
|  */ | |
| 
 | |
| /* | |
|  * 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> | |
|  | |
| #include <minimun_spanning_tree.h> | |
| #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 = std::max( aNodesCount, 1 ); | |
|     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 ); | |
|     } | |
| }
 |