Loading pcbnew/class_board.cpp +76 −72 Original line number Original line Diff line number Diff line Loading @@ -4,6 +4,7 @@ */ */ #include <limits.h> #include <limits.h> #include <algorithm> #include "fctsys.h" #include "fctsys.h" #include "common.h" #include "common.h" Loading @@ -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 ), Loading Loading @@ -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++ ) { pad = aPadList[ii]; if( pad->m_Pos != aPosition ) break; if( (aLayerMask & pad->m_layerMask) != 0 ) return pad; } } // search previous if( pad->m_Pos.x > aPosition.x ) /* Must search before this item */ for( int ii = idx-1 ;ii >=0; ii-- ) { { ptr_pad -= nb_pad; pad = aPadList[ii]; if( pad->m_Pos != aPosition ) if( ptr_pad < aPad ) break; ptr_pad = aPad; 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 ); } } Loading pcbnew/class_board.h +7 −6 Original line number Original line Diff line number Diff line Loading @@ -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 ); /** /** Loading pcbnew/class_track.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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 ) { { Loading pcbnew/class_track.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading pcbnew/connect.cpp +257 −41 Original line number Original line Diff line number Diff line Loading @@ -4,7 +4,6 @@ */ */ #include "fctsys.h" #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "common.h" #include "pcbcommon.h" #include "pcbcommon.h" #include "macros.h" #include "macros.h" Loading @@ -14,7 +13,6 @@ #include "class_board.h" #include "class_board.h" #include "pcbnew.h" #include "pcbnew.h" #include "protos.h" extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb ); extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb ); Loading @@ -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 Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* pt_end_conn ); static void RebuildTrackChain( BOARD* pcb ); 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 <TRACK*> m_Connected; // List of connected tracks/vias // to a given track or via std::vector <CONNECTED_POINT> m_Candidates; // List of points to test // (end points of tracks or vias location ) private: BOARD * m_brd; // the master board. public: CONNECTIONS( BOARD * aBrd ); ~CONNECTIONS() {}; /** Function BuildCandidatesList * Fills m_Candidates with all connecting points (track ends or via location) * with tracks from aBegin to aEnd. * if aBegin == NULL, use first track in brd list * if aEnd == NULL, uses all tracks from aBegin in brd list */ void BuildCandidatesList( TRACK * aBegin = NULL, TRACK * aEnd = NULL); /** * function SearchConnectedTracks * Fills m_Connected with tracks/vias connected to aTrack * @param aTrack = track or via to use as reference */ int SearchConnectedTracks( const TRACK * aTrack ); private: /** * function searchEntryPoint * Search an item in m_Connected connected to aPoint * note m_Connected containts usually more than one candidate * and searchEntryPoint returns an index to one of these candidates * Others are neightbor of the indexed item. * @param aPoint is the reference coordinates * @return the index of item found or -1 if no candidate */ int searchEntryPoint( const wxPoint & aPoint); }; /* sort function used to sort .m_Connected by X the Y values * items are sorted by X coordinate value, * and for same X value, by Y coordinate value. */ static bool sortConnectedPointByXthenYCoordinates( const CONNECTED_POINT & aRef, const CONNECTED_POINT & aTst ) { if( aRef.m_Point.x == aTst.m_Point.x ) return aRef.m_Point.y < aTst.m_Point.y; return aRef.m_Point.x < aTst.m_Point.x; } CONNECTIONS::CONNECTIONS( BOARD * aBrd ) { m_brd = aBrd; } void CONNECTIONS::BuildCandidatesList( TRACK * aBegin, TRACK * aEnd) { m_Connected.clear(); if( aBegin == NULL ) aBegin = m_brd->m_Track; unsigned ii = 0; // Count candidates ( i.e. end points ) for( const TRACK* track = aBegin; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) ii++; else ii += 2; if( track == aEnd ) break; } // Build candidate list m_Connected.reserve( ii ); for( TRACK* track = aBegin; track != aEnd; track = track->Next() ) { CONNECTED_POINT candidate( track, track->m_Start); m_Candidates.push_back( candidate ); if( track->Type() != PCB_VIA_T ) { candidate.m_Track = track; candidate.m_Point = track->m_End; m_Candidates.push_back( candidate ); } if( track == aEnd ) break; } // Sort list by increasing X coordinate, // and for increasing Y coordinate when items have the same X coordinate // So candidates to the same location are consecutive in list. sort( m_Candidates.begin(), m_Candidates.end(), sortConnectedPointByXthenYCoordinates ); } int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) { int count = 0; m_Connected.clear(); int layerMask = aTrack->ReturnMaskLayer(); // Search for connections to starting point: wxPoint position = aTrack->m_Start; for( int kk = 0; kk < 2; kk++ ) { int idx = searchEntryPoint( position ); if ( idx >= 0 ) { // search after: for ( unsigned ii = idx; ii < m_Candidates.size(); ii ++ ) { if( m_Candidates[ii].m_Track == aTrack ) continue; if( m_Candidates[ii].m_Point != position ) break; if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) m_Connected.push_back( m_Candidates[ii].m_Track ); } // search before: for ( unsigned ii = idx-1; ii >= 0; ii -- ) { if( m_Candidates[ii].m_Track == aTrack ) continue; if( m_Candidates[ii].m_Point != position ) break; if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) m_Connected.push_back( m_Candidates[ii].m_Track ); } } // Search for connections to ending point: if( aTrack->Type() == PCB_VIA_T ) break; position = aTrack->m_End; } return count; } int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint) { // Search the aPoint coordinates in m_Candidates // m_Candidates is sorted by X then Y values, and a fast binary search is used int idxmax = m_Candidates.size()-1; int delta = m_Candidates.size(); if( delta & 1 && delta > 1 ) delta += 1; delta /= 2; int idx = delta; // Starting index is the middle of list while( delta ) { if( (delta & 1) && ( delta > 1 ) ) delta++; delta /= 2; CONNECTED_POINT & candidate = m_Candidates[idx]; if( candidate.m_Point == aPoint ) // candidate found { return idx; } // Not found: test the middle of the remaining sub list if( candidate.m_Point.x == aPoint.x ) // Must search considering Y coordinate { if(candidate.m_Point.y < aPoint.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( candidate.m_Point.x < aPoint.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 -1; } /** /** Loading Loading @@ -472,9 +688,6 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* } } #define POS_AFF_CHREF 62 void PCB_BASE_FRAME::RecalculateAllTracksNetcode() void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { { TRACK* pt_trace; TRACK* pt_trace; Loading Loading @@ -507,7 +720,8 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() /**************************************************************/ /**************************************************************/ /* Pass 1: search the connections between track ends and pads */ /* Pass 1: search the connections between track ends and pads */ /**************************************************************/ /**************************************************************/ m_Pcb->GetSortedPadListByXCoord( sortedPads ); m_Pcb->GetSortedPadListByXthenYCoord( sortedPads ); /* Reset variables and flags used in computation */ /* Reset variables and flags used in computation */ pt_trace = m_Pcb->m_Track; pt_trace = m_Pcb->m_Track; Loading @@ -529,7 +743,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; /* Search for a pad on the segment starting point */ /* Search for a pad on the segment starting point */ pt_trace->start = m_Pcb->GetPad( &sortedPads[0], pt_trace->m_Start, layerMask ); pt_trace->start = m_Pcb->GetPad( sortedPads, pt_trace->m_Start, layerMask ); if( pt_trace->start != NULL ) if( pt_trace->start != NULL ) { { Loading @@ -538,7 +752,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } /* Search for a pad on the segment ending point */ /* Search for a pad on the segment ending point */ pt_trace->end = m_Pcb->GetPad( &sortedPads[0], pt_trace->m_End, layerMask ); pt_trace->end = m_Pcb->GetPad( sortedPads, pt_trace->m_End, layerMask ); if( pt_trace->end != NULL ) if( pt_trace->end != NULL ) { { Loading @@ -547,17 +761,16 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } } } /*****************************************************/ /*****************************************************/ /* Pass 2: search the connections between track ends */ /* Pass 2: search the connections between track ends */ /*****************************************************/ /*****************************************************/ /* the .start and .end member pointers are updated, only if NULLs /* the .start and .end member pointers are updated, only if NULLs * (if not nuls, the end is already connected to a pad). * (if not null, the end is already connected to a pad). * the connection (if found) is between segments * the connection (if found) is between segments * when a track has a net code and the other has a null net code, the null net code is changed * when a track has a net code and the other has a null net code, the null net code is changed */ */ #if 1 #if 0 for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->start == NULL ) if( pt_trace->start == NULL ) Loading @@ -571,41 +784,44 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } } } #else #else CONNECTIONS connections( m_Pcb ); connections.BuildCandidatesList(); for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->start != NULL ) if( pt_trace->start != NULL && pt_trace->end != NULL ) continue; continue; TRACK * candidate = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); connections.SearchConnectedTracks( pt_trace ); if( candidate == NULL ) for( unsigned ii = 0; ii < connections.m_Connected.size(); ii ++ ) continue; if( candidate->start == pt_trace || candidate->end == pt_trace ) { candidate->SetState( BUSY, ON ); pt_trace->start = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); candidate->SetState( BUSY, OFF ); } else pt_trace->start = candidate; } for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->end != NULL ) TRACK * candidate = connections.m_Connected[ii]; continue; TRACK * candidate = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); // Do not create a link to an other track already linked if( candidate == NULL ) // to avoid loops when we have 4 and more ends at the same location continue; // like this case for 4 tracks named A, B, C ,D: // A links B; B links A and C links D; D links C, but never C or D links A or B // Try to find a not already linked track: if( candidate->start == pt_trace || candidate->end == pt_trace ) if( candidate->start == pt_trace || candidate->end == pt_trace ) continue; // A link is found: if( pt_trace->start == NULL ) { { candidate->SetState( BUSY, ON ); if( ( pt_trace->m_Start == candidate->m_Start ) || pt_trace->end = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); ( pt_trace->m_Start == candidate->m_End ) ) candidate->SetState( BUSY, OFF ); pt_trace->start = candidate; } } else if( pt_trace->end == NULL ) { if( ( pt_trace->m_End == candidate->m_Start ) || ( pt_trace->m_End == candidate->m_End ) ) pt_trace->end = candidate; pt_trace->end = candidate; } } } } #endif #endif /**********************************************************/ /**********************************************************/ /* Propagate net codes from a segment to an other segment */ /* Propagate net codes from a segment to an other segment */ /**********************************************************/ /**********************************************************/ Loading Loading
pcbnew/class_board.cpp +76 −72 Original line number Original line Diff line number Diff line Loading @@ -4,6 +4,7 @@ */ */ #include <limits.h> #include <limits.h> #include <algorithm> #include "fctsys.h" #include "fctsys.h" #include "common.h" #include "common.h" Loading @@ -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 ), Loading Loading @@ -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++ ) { pad = aPadList[ii]; if( pad->m_Pos != aPosition ) break; if( (aLayerMask & pad->m_layerMask) != 0 ) return pad; } } // search previous if( pad->m_Pos.x > aPosition.x ) /* Must search before this item */ for( int ii = idx-1 ;ii >=0; ii-- ) { { ptr_pad -= nb_pad; pad = aPadList[ii]; if( pad->m_Pos != aPosition ) if( ptr_pad < aPad ) break; ptr_pad = aPad; 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 ); } } Loading
pcbnew/class_board.h +7 −6 Original line number Original line Diff line number Diff line Loading @@ -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 ); /** /** Loading
pcbnew/class_track.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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 ) { { Loading
pcbnew/class_track.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
pcbnew/connect.cpp +257 −41 Original line number Original line Diff line number Diff line Loading @@ -4,7 +4,6 @@ */ */ #include "fctsys.h" #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "common.h" #include "pcbcommon.h" #include "pcbcommon.h" #include "macros.h" #include "macros.h" Loading @@ -14,7 +13,6 @@ #include "class_board.h" #include "class_board.h" #include "pcbnew.h" #include "pcbnew.h" #include "protos.h" extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb ); extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb ); Loading @@ -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 Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* pt_end_conn ); static void RebuildTrackChain( BOARD* pcb ); 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 <TRACK*> m_Connected; // List of connected tracks/vias // to a given track or via std::vector <CONNECTED_POINT> m_Candidates; // List of points to test // (end points of tracks or vias location ) private: BOARD * m_brd; // the master board. public: CONNECTIONS( BOARD * aBrd ); ~CONNECTIONS() {}; /** Function BuildCandidatesList * Fills m_Candidates with all connecting points (track ends or via location) * with tracks from aBegin to aEnd. * if aBegin == NULL, use first track in brd list * if aEnd == NULL, uses all tracks from aBegin in brd list */ void BuildCandidatesList( TRACK * aBegin = NULL, TRACK * aEnd = NULL); /** * function SearchConnectedTracks * Fills m_Connected with tracks/vias connected to aTrack * @param aTrack = track or via to use as reference */ int SearchConnectedTracks( const TRACK * aTrack ); private: /** * function searchEntryPoint * Search an item in m_Connected connected to aPoint * note m_Connected containts usually more than one candidate * and searchEntryPoint returns an index to one of these candidates * Others are neightbor of the indexed item. * @param aPoint is the reference coordinates * @return the index of item found or -1 if no candidate */ int searchEntryPoint( const wxPoint & aPoint); }; /* sort function used to sort .m_Connected by X the Y values * items are sorted by X coordinate value, * and for same X value, by Y coordinate value. */ static bool sortConnectedPointByXthenYCoordinates( const CONNECTED_POINT & aRef, const CONNECTED_POINT & aTst ) { if( aRef.m_Point.x == aTst.m_Point.x ) return aRef.m_Point.y < aTst.m_Point.y; return aRef.m_Point.x < aTst.m_Point.x; } CONNECTIONS::CONNECTIONS( BOARD * aBrd ) { m_brd = aBrd; } void CONNECTIONS::BuildCandidatesList( TRACK * aBegin, TRACK * aEnd) { m_Connected.clear(); if( aBegin == NULL ) aBegin = m_brd->m_Track; unsigned ii = 0; // Count candidates ( i.e. end points ) for( const TRACK* track = aBegin; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) ii++; else ii += 2; if( track == aEnd ) break; } // Build candidate list m_Connected.reserve( ii ); for( TRACK* track = aBegin; track != aEnd; track = track->Next() ) { CONNECTED_POINT candidate( track, track->m_Start); m_Candidates.push_back( candidate ); if( track->Type() != PCB_VIA_T ) { candidate.m_Track = track; candidate.m_Point = track->m_End; m_Candidates.push_back( candidate ); } if( track == aEnd ) break; } // Sort list by increasing X coordinate, // and for increasing Y coordinate when items have the same X coordinate // So candidates to the same location are consecutive in list. sort( m_Candidates.begin(), m_Candidates.end(), sortConnectedPointByXthenYCoordinates ); } int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack ) { int count = 0; m_Connected.clear(); int layerMask = aTrack->ReturnMaskLayer(); // Search for connections to starting point: wxPoint position = aTrack->m_Start; for( int kk = 0; kk < 2; kk++ ) { int idx = searchEntryPoint( position ); if ( idx >= 0 ) { // search after: for ( unsigned ii = idx; ii < m_Candidates.size(); ii ++ ) { if( m_Candidates[ii].m_Track == aTrack ) continue; if( m_Candidates[ii].m_Point != position ) break; if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) m_Connected.push_back( m_Candidates[ii].m_Track ); } // search before: for ( unsigned ii = idx-1; ii >= 0; ii -- ) { if( m_Candidates[ii].m_Track == aTrack ) continue; if( m_Candidates[ii].m_Point != position ) break; if( (m_Candidates[ii].m_Track->ReturnMaskLayer() & layerMask ) != 0 ) m_Connected.push_back( m_Candidates[ii].m_Track ); } } // Search for connections to ending point: if( aTrack->Type() == PCB_VIA_T ) break; position = aTrack->m_End; } return count; } int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint) { // Search the aPoint coordinates in m_Candidates // m_Candidates is sorted by X then Y values, and a fast binary search is used int idxmax = m_Candidates.size()-1; int delta = m_Candidates.size(); if( delta & 1 && delta > 1 ) delta += 1; delta /= 2; int idx = delta; // Starting index is the middle of list while( delta ) { if( (delta & 1) && ( delta > 1 ) ) delta++; delta /= 2; CONNECTED_POINT & candidate = m_Candidates[idx]; if( candidate.m_Point == aPoint ) // candidate found { return idx; } // Not found: test the middle of the remaining sub list if( candidate.m_Point.x == aPoint.x ) // Must search considering Y coordinate { if(candidate.m_Point.y < aPoint.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( candidate.m_Point.x < aPoint.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 -1; } /** /** Loading Loading @@ -472,9 +688,6 @@ static void Build_Pads_Info_Connections_By_Tracks( TRACK* pt_start_conn, TRACK* } } #define POS_AFF_CHREF 62 void PCB_BASE_FRAME::RecalculateAllTracksNetcode() void PCB_BASE_FRAME::RecalculateAllTracksNetcode() { { TRACK* pt_trace; TRACK* pt_trace; Loading Loading @@ -507,7 +720,8 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() /**************************************************************/ /**************************************************************/ /* Pass 1: search the connections between track ends and pads */ /* Pass 1: search the connections between track ends and pads */ /**************************************************************/ /**************************************************************/ m_Pcb->GetSortedPadListByXCoord( sortedPads ); m_Pcb->GetSortedPadListByXthenYCoord( sortedPads ); /* Reset variables and flags used in computation */ /* Reset variables and flags used in computation */ pt_trace = m_Pcb->m_Track; pt_trace = m_Pcb->m_Track; Loading @@ -529,7 +743,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; layerMask = g_TabOneLayerMask[pt_trace->GetLayer()]; /* Search for a pad on the segment starting point */ /* Search for a pad on the segment starting point */ pt_trace->start = m_Pcb->GetPad( &sortedPads[0], pt_trace->m_Start, layerMask ); pt_trace->start = m_Pcb->GetPad( sortedPads, pt_trace->m_Start, layerMask ); if( pt_trace->start != NULL ) if( pt_trace->start != NULL ) { { Loading @@ -538,7 +752,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } /* Search for a pad on the segment ending point */ /* Search for a pad on the segment ending point */ pt_trace->end = m_Pcb->GetPad( &sortedPads[0], pt_trace->m_End, layerMask ); pt_trace->end = m_Pcb->GetPad( sortedPads, pt_trace->m_End, layerMask ); if( pt_trace->end != NULL ) if( pt_trace->end != NULL ) { { Loading @@ -547,17 +761,16 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } } } /*****************************************************/ /*****************************************************/ /* Pass 2: search the connections between track ends */ /* Pass 2: search the connections between track ends */ /*****************************************************/ /*****************************************************/ /* the .start and .end member pointers are updated, only if NULLs /* the .start and .end member pointers are updated, only if NULLs * (if not nuls, the end is already connected to a pad). * (if not null, the end is already connected to a pad). * the connection (if found) is between segments * the connection (if found) is between segments * when a track has a net code and the other has a null net code, the null net code is changed * when a track has a net code and the other has a null net code, the null net code is changed */ */ #if 1 #if 0 for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->start == NULL ) if( pt_trace->start == NULL ) Loading @@ -571,41 +784,44 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } } } #else #else CONNECTIONS connections( m_Pcb ); connections.BuildCandidatesList(); for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->start != NULL ) if( pt_trace->start != NULL && pt_trace->end != NULL ) continue; continue; TRACK * candidate = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); connections.SearchConnectedTracks( pt_trace ); if( candidate == NULL ) for( unsigned ii = 0; ii < connections.m_Connected.size(); ii ++ ) continue; if( candidate->start == pt_trace || candidate->end == pt_trace ) { candidate->SetState( BUSY, ON ); pt_trace->start = pt_trace->GetTrace( m_Pcb->m_Track, NULL, START ); candidate->SetState( BUSY, OFF ); } else pt_trace->start = candidate; } for( pt_trace = m_Pcb->m_Track; pt_trace != NULL; pt_trace = pt_trace->Next() ) { { if( pt_trace->end != NULL ) TRACK * candidate = connections.m_Connected[ii]; continue; TRACK * candidate = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); // Do not create a link to an other track already linked if( candidate == NULL ) // to avoid loops when we have 4 and more ends at the same location continue; // like this case for 4 tracks named A, B, C ,D: // A links B; B links A and C links D; D links C, but never C or D links A or B // Try to find a not already linked track: if( candidate->start == pt_trace || candidate->end == pt_trace ) if( candidate->start == pt_trace || candidate->end == pt_trace ) continue; // A link is found: if( pt_trace->start == NULL ) { { candidate->SetState( BUSY, ON ); if( ( pt_trace->m_Start == candidate->m_Start ) || pt_trace->end = pt_trace->GetTrace( m_Pcb->m_Track, NULL, END ); ( pt_trace->m_Start == candidate->m_End ) ) candidate->SetState( BUSY, OFF ); pt_trace->start = candidate; } } else if( pt_trace->end == NULL ) { if( ( pt_trace->m_End == candidate->m_Start ) || ( pt_trace->m_End == candidate->m_End ) ) pt_trace->end = candidate; pt_trace->end = candidate; } } } } #endif #endif /**********************************************************/ /**********************************************************/ /* Propagate net codes from a segment to an other segment */ /* Propagate net codes from a segment to an other segment */ /**********************************************************/ /**********************************************************/ Loading