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