diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index 5e9252d94d..84ae639f62 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -4,6 +4,7 @@
*/
#include
+#include
#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,80 +1677,83 @@ 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& aPadList, const wxPoint& aPosition, int aLayerMask )
{
- D_PAD* pad;
- int ii;
+ // 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;
- 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;
- 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;
-
- continue;
- }
-
- /* 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 )
- {
- /* Search the beginning of the block */
- while( ptr_pad >= aPad )
+ // search next
+ for( int ii = idx+1; ii <= idxmax; ii++ )
{
- pad = *ptr_pad;
-
- if( pad->m_Pos.x == aPosition.x )
- ptr_pad--;
- else
+ pad = aPadList[ii];
+ if( pad->m_Pos != aPosition )
break;
- }
-
- ptr_pad++; /* ptr_pad = first pad which have pad->m_Pos.x = px */
-
- for( ; ; ptr_pad++ )
- {
- 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!
+ 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;
+ }
+
+ // Not found:
+ return 0;
+ }
+
+ if( pad->m_Pos.x == aPosition.x ) // Must search considering Y coordinate
+ {
+ if(pad->m_Pos.y < aPosition.y) // 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;
+ }
+ }
+ 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;
}
}
@@ -1769,12 +1761,24 @@ D_PAD* BOARD::GetPad( D_PAD** aPad, const wxPoint& aPosition, int aLayerMask )
}
-void BOARD::GetSortedPadListByXCoord( std::vector& 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& 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 );
}
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 0eba6b2158..4966a88014 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -1162,22 +1162,23 @@ public:
* function.
*
* @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)
* @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& 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& aVector );
+ void GetSortedPadListByXthenYCoord( std::vector& aVector );
/**
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index bcf3ae0c4b..85deee363e 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -447,7 +447,7 @@ bool SEGVIA::IsOnLayer( int layer_number ) const
}
-int TRACK::ReturnMaskLayer()
+int TRACK::ReturnMaskLayer() const
{
if( Type() == PCB_VIA_T )
{
diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h
index d8869df940..d75df2d294 100644
--- a/pcbnew/class_track.h
+++ b/pcbnew/class_track.h
@@ -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
diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp
index a1a30f1f21..8b5c73c371 100644
--- a/pcbnew/connect.cpp
+++ b/pcbnew/connect.cpp
@@ -4,7 +4,6 @@
*/
#include "fctsys.h"
-#include "gr_basic.h"
#include "common.h"
#include "pcbcommon.h"
#include "macros.h"
@@ -14,7 +13,6 @@
#include "class_board.h"
#include "pcbnew.h"
-#include "protos.h"
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb );
@@ -25,7 +23,225 @@ static void Propagate_SubNet( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void RebuildTrackChain( BOARD* pcb );
-/*..*/
+
+// A helper class to handle connection points
+class CONNECTED_POINT
+{
+public:
+ TRACK * m_Track; // a link to the connected item (track or via)
+ wxPoint m_Point; // the connection point
+
+ CONNECTED_POINT( TRACK * aTrack, wxPoint & aPoint)
+ {
+ m_Track = aTrack;
+ m_Point = aPoint;
+ }
+};
+
+// A helper class to handle connection calculations:
+class CONNECTIONS
+{
+public:
+ std::vector