Commit d5ea4750 authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew: starting work on better ratsnest and connections calculations algorithms.

This first draft should fix bug 851670 and is faster than existing alogorithm.
parent 0ee7234c
......@@ -4,6 +4,7 @@
*/
#include <limits.h>
#include <algorithm>
#include "fctsys.h"
#include "common.h"
......@@ -30,18 +31,6 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD_DESIGN_SETTINGS boardDesignSettings;
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
*/
static int sortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
D_PAD* ref = *(D_PAD**) pt_ref;
D_PAD* comp = *(D_PAD**) pt_comp;
return ref->m_Pos.x - comp->m_Pos.x;
}
BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
BOARD_ITEM( (BOARD_ITEM*)parent, PCB_T ),
......@@ -1688,93 +1677,108 @@ D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, int aLayerMask )
}
D_PAD* BOARD::GetPad( D_PAD** aPad, const wxPoint& aPosition, int aLayerMask )
D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, int aLayerMask )
{
D_PAD* pad;
int ii;
int nb_pad = GetPadsCount();
D_PAD** ptr_pad = aPad;
D_PAD** lim = aPad + nb_pad - 1;
ptr_pad = aPad;
// Search the aPoint coordinates in aPadList
// aPadList is sorted by X then Y values, and a fast binary search is used
int idxmax = aPadList.size()-1;
while( nb_pad )
int delta = aPadList.size();
if( delta & 1 && delta > 1 )
delta += 1;
delta /= 2;
int idx = delta; // Starting index is the middle of list
while( delta )
{
pad = *ptr_pad;
ii = nb_pad;
nb_pad >>= 1;
if( (delta & 1) && ( delta > 1 ) )
delta++;
delta /= 2;
if( (ii & 1) && ( ii > 1 ) )
nb_pad++;
D_PAD* pad = aPadList[idx];
if( pad->m_Pos.x < aPosition.x ) /* Must search after this item */
if( pad->m_Pos == aPosition ) // candidate found
{
ptr_pad += nb_pad;
// The pad must match the layer mask:
if( (aLayerMask & pad->m_layerMask) != 0 )
return pad;
if( ptr_pad > lim )
ptr_pad = lim;
// More than one pad can be at aPosition
// search for a pad at aPosition that matched this mask
continue;
}
if( pad->m_Pos.x > aPosition.x ) /* Must search before this item */
{
ptr_pad -= nb_pad;
if( ptr_pad < aPad )
ptr_pad = aPad;
// search next
for( int ii = idx+1; ii <= idxmax; ii++ )
{
pad = aPadList[ii];
if( pad->m_Pos != aPosition )
break;
if( (aLayerMask & pad->m_layerMask) != 0 )
return pad;
}
// search previous
for( int ii = idx-1 ;ii >=0; ii-- )
{
pad = aPadList[ii];
if( pad->m_Pos != aPosition )
break;
if( (aLayerMask & pad->m_layerMask) != 0 )
return pad;
}
continue;
// Not found:
return 0;
}
/* A suitable block is found (X coordinate matches the px reference: but we
* must matches the Y coordinate */
if( pad->m_Pos.x == aPosition.x )
if( pad->m_Pos.x == aPosition.x ) // Must search considering Y coordinate
{
/* Search the beginning of the block */
while( ptr_pad >= aPad )
if(pad->m_Pos.y < aPosition.y) // Must search after this item
{
pad = *ptr_pad;
if( pad->m_Pos.x == aPosition.x )
ptr_pad--;
else
break;
idx += delta;
if( idx > idxmax )
idx = idxmax;
}
ptr_pad++; /* ptr_pad = first pad which have pad->m_Pos.x = px */
for( ; ; ptr_pad++ )
else // Must search before this item
{
if( ptr_pad > lim )
return NULL; /* outside suitable block */
pad = *ptr_pad;
if( pad->m_Pos.x != aPosition.x )
return NULL; /* outside suitable block */
if( pad->m_Pos.y != aPosition.y )
continue;
/* A Pad if found here: but it must mach the layer */
if( pad->m_layerMask & aLayerMask ) // Matches layer => a connected pad is found!
return pad;
idx -= delta;
if( idx < 0 )
idx = 0;
}
}
else if( pad->m_Pos.x < aPosition.x ) // Must search after this item
{
idx += delta;
if( idx > idxmax )
idx = idxmax;
}
else // Must search before this item
{
idx -= delta;
if( idx < 0 )
idx = 0;
}
}
return NULL;
}
void BOARD::GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector )
/**
* Function SortPadsByXCoord
* is used by GetSortedPadListByXCoord to Sort a pad list by x coordinate value.
*/
static bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
{
if( ref->m_Pos.x == comp->m_Pos.x )
return ref->m_Pos.y < comp->m_Pos.y;
return ref->m_Pos.x < comp->m_Pos.x;
}
void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector )
{
aVector.insert( aVector.end(), m_NetInfo->m_PadsFullList.begin(),
m_NetInfo->m_PadsFullList.end() );
qsort( &aVector[0], GetPadsCount(), sizeof( D_PAD*), sortPadsByXCoord );
sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
}
......
......@@ -1162,22 +1162,23 @@ public:
* function.
* </p>
* @note The normal pad list is sorted by increasing netcodes.
* @param aPad A D_PAD object pointer the first pad in the list to begin searching.
* @param aPadList = the list of pads candidates (a std::vector<D_PAD*>)
* @param aPosition A wxPoint object containing the position to test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A D_PAD object pointer to the connected pad.
* @return a D_PAD object pointer to the connected pad.
*/
D_PAD* GetPad( D_PAD** aPad, const wxPoint& aPosition, int aLayerMask );
D_PAD* GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, int aLayerMask );
/**
* Function GetSortedPadListByXCoord
* Function GetSortedPadListByXthenYCoord
* first empties then fills the vector with all pads and sorts them by
* increasing x coordinate. The vector only holds pointers to the pads and
* increasing x coordinate, and for increasing y coordinate for same values of x coordinates.
* The vector only holds pointers to the pads and
* those pointers are only references to pads which are owned by the BOARD
* through other links.
* @param aVector Where to put the pad pointers.
*/
void GetSortedPadListByXCoord( std::vector<D_PAD*>& aVector );
void GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector );
/**
......
......@@ -447,7 +447,7 @@ bool SEGVIA::IsOnLayer( int layer_number ) const
}
int TRACK::ReturnMaskLayer()
int TRACK::ReturnMaskLayer() const
{
if( Type() == PCB_VIA_T )
{
......
......@@ -225,7 +225,7 @@ public:
* TRACK segment or SEGVIA physically resides.
* @return int - a layer mask, see pcbstruct.h's LAYER_BACK, etc.
*/
int ReturnMaskLayer();
int ReturnMaskLayer() const;
/**
* Function IsPointOnEnds
......
This diff is collapsed.
......@@ -414,12 +414,12 @@ void DRC::testPad2Pad()
{
std::vector<D_PAD*> sortedPads;
m_pcb->GetSortedPadListByXCoord( sortedPads );
m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
// find the max size of the pads (used to stop the test)
int max_size = 0;
for( unsigned i = 0; i<sortedPads.size(); ++i )
for( unsigned i = 0; i < sortedPads.size(); ++i )
{
D_PAD* pad = sortedPads[i];
......@@ -431,7 +431,7 @@ void DRC::testPad2Pad()
// Test the pads
D_PAD** listEnd = &sortedPads[ sortedPads.size() ];
for( unsigned i = 0; i<sortedPads.size(); ++i )
for( unsigned i = 0; i< sortedPads.size(); ++i )
{
D_PAD* pad = sortedPads[i];
......
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