Commit 936d831b authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew: more work on a better algorithm to calculate the full ratsnest.

Lee algorithm replaced by a Minimun Spanning Tree algo (using Prim's algorithm ).
Tested on a 5350 pads board, it is more than 100 times faster.
Also fix a crash when clicking on tool  "delete selected items" (main horizontal toolbar),
and remove this tool (currently, no code in Pcbnew for this tool)
parent ed2141a6
......@@ -352,7 +352,11 @@ public:
*/
void TraceModuleRatsNest( wxDC* aDC );
void Build_Board_Ratsnest( wxDC* DC );
/**
* Function Build_Board_Ratsnest.
* Calculates the full ratsnest depending only on pads.
*/
void Build_Board_Ratsnest();
/**
* function Displays the general ratsnest
......
......@@ -132,6 +132,7 @@ set(PCBNEW_SRCS
magnetic_tracks_functions.cpp
menubar_modedit.cpp
menubar_pcbframe.cpp
minumun_spanning_tree.cpp
mirepcb.cpp
modedit.cpp
modedit_onclick.cpp
......
......@@ -66,7 +66,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
int itmp;
INSTALL_UNBUFFERED_DC( dc, DrawPanel );
BOARD_ITEM* DrawStruct = GetCurItem();
MODULE* module;
DrawPanel->CrossHairOff( &dc );
......@@ -1080,8 +1079,8 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
default:
wxString msg;
msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() id %d error" ),
DrawStruct->Type() );
msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ),
id );
DisplayError( this, msg );
break;
}
......
/**
* @file minumun_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 "minumun_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 = 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 );
}
}
/**
* @file minumun_spanning_tree.h
*/
#include <vector>
/**
* @brief The class MIN_SPAN_TREE calculates the rectilinear minimum spanning tree
* of a set of points (pads usually having the same net)
* this class is an abstract class because you must provide the function
* int GetWeight( int aItem1, int aItem2 )
* that calculate the distance between 2 items
* MIN_SPAN_TREE does not know anything about the actual items to link
* by the tree
*/
class MIN_SPAN_TREE
{
protected:
int m_Size; /* The number of nodes in the graph
*/
private:
std::vector<char> inTree; /* inTree[ii] is a flag set to 1 if the node ii
* is already in the minimum spanning tree; 0 otherwise
*/
std::vector<int> linkedTo; /* linkedTo[ii] holds the index of the node ii would have to be
* linked to in order to get a distance of d[ii]
* NOTE: linkedTo[0] is the starting point of the tree
* linkedTo[1] is the first linked point to use
* ii and linkedTo[ii] are the 2 ends of an edge in the graph
*/
std::vector<int> distTo; /* distTo[ii] is the distance between node ii and the minimum spanning
* tree;
* this is initially infinity (INT_MAX);
* if ii is already in the tree, then d[ii] is undefined;
* this is just a temporary variable. It's not necessary but speeds
* up execution considerably (by a factor of n)
*/
public:
MIN_SPAN_TREE();
void MSP_Init( int aNodesCount );
void BuildTree();
int GetWhoTo( int aIdx )
{
return linkedTo[aIdx];
}
int GetDist( int aIdx )
{
return distTo[aIdx];
}
/**
* Function GetWeight
* calculates the weight between 2 items
* NOTE: The weight between a node and itself should be 0
* It is virtual pure, you must provide your GetWeight function
* @param aItem1 = first item
* @param aItem2 = other item
* @return the weight between items ( usually the distance )
*/
virtual int GetWeight( int aItem1, int aItem2 ) = 0;
private:
/**
* Function updateDistances
* should be called immediately after target is added to the tree;
* updates d so that the values are correct (goes through target's
* neighbours making sure that the distances between them and the tree
* are indeed minimum)
* @param target = index of curr item
*/
void updateDistances( int aTarget );
};
This diff is collapsed.
......@@ -204,11 +204,12 @@ void PCB_EDIT_FRAME::ReCreateHToolbar()
m_HToolBar->AddTool( ID_OPEN_MODULE_EDITOR, wxEmptyString, KiBitmap( modedit_xpm ),
_( "Open module editor" ) );
#if 0
// Not yet existing commands
m_HToolBar->AddSeparator();
m_HToolBar->AddTool( wxID_CUT, wxEmptyString, KiBitmap( cut_button_xpm ),
_( "Cut selected item" ) );
#if 0
m_HToolBar->AddTool( wxID_COPY, wxEmptyString, KiBitmap( copy_button_xpm ),
_( "Copy selected item" ) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment