/*******************/ /* Locate element. */ /*******************/ #include "fctsys.h" #include "common.h" #include "pcbnew.h" #include "class_board_design_settings.h" #include "protos.h" /* * return true if the dist between p1 and p2 < max_dist * Currently in test (currently rasnest algos work only if p1 == p2) */ inline bool IsPointsAreNear(wxPoint & p1, wxPoint & p2, int max_dist) { #if 0 // Do not change it: does not work { int dist; dist = abs(p1.x - p2.x) + abs (p1.y - p2.y); dist *= 7; dist /= 10; if ( dist < max_dist ) return true; } #else if ( p1 == p2 ) return true; #endif return false; } /** * Search for the track (or via) segment which is connected to the track * segment PtRefSegm * if extr == START, the starting track segment PtRefSegm is used to locate * a connected segment * if extr == END, the ending track segment PtRefSegm is used * The test connection consider only end track segments * * Search is made from pt_base to pt_lim (in the track linked list) * if pt_lim == NULL, the search is made from pt_base to the end of list * * In order to have a fast computation time: * a first search is made considering only the +/- 50 next door neighbor * of PtRefSegm. * if no track is found : the entire list is tested * * @param PtRefSegm = reference segment * @param pt_base = lower limit for search * @param pt_lim = upper limit for search (can be NULL) * @param extr = START or END = end of ref track segment to use in tests */ TRACK* GetConnectedTrace( TRACK* PtRefSegm, TRACK* pt_base, TRACK* pt_lim, int extr ) { const int NEIGHTBOUR_COUNT_MAX = 50; TRACK* PtSegmB, * PtSegmN; int Reflayer; wxPoint pos_ref; int ii; int max_dist; if( extr == START ) pos_ref = PtRefSegm->m_Start; else pos_ref = PtRefSegm->m_End; Reflayer = PtRefSegm->ReturnMaskLayer(); PtSegmB = PtSegmN = PtRefSegm; for( ii = 0; ii < NEIGHTBOUR_COUNT_MAX; ii++ ) { if( (PtSegmN == NULL) && (PtSegmB == NULL) ) break; if( PtSegmN ) { if( PtSegmN->GetState( BUSY | IS_DELETED ) ) goto suite; if( PtSegmN == PtRefSegm ) goto suite; /* max_dist is the max distance between 2 track ends which * ensure a copper continuity */ max_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2; if( IsPointsAreNear(pos_ref, PtSegmN->m_Start, max_dist) ) { if( Reflayer & PtSegmN->ReturnMaskLayer() ) return PtSegmN; } if( IsPointsAreNear(pos_ref, PtSegmN->m_End, max_dist) ) { if( Reflayer & PtSegmN->ReturnMaskLayer() ) return PtSegmN; } suite: if( PtSegmN == pt_lim ) PtSegmN = NULL; else PtSegmN = PtSegmN->Next(); } if( PtSegmB ) { if( PtSegmB->GetState( BUSY | IS_DELETED ) ) goto suite1; if( PtSegmB == PtRefSegm ) goto suite1; max_dist = (PtSegmB->m_Width + PtRefSegm->m_Width)/2; if( IsPointsAreNear(pos_ref, PtSegmB->m_Start, max_dist) ) { if( Reflayer & PtSegmB->ReturnMaskLayer() ) return PtSegmB; } if( IsPointsAreNear(pos_ref, PtSegmB->m_End, max_dist) ) { if( Reflayer & PtSegmB->ReturnMaskLayer() ) return PtSegmB; } suite1: if( PtSegmB == pt_base ) PtSegmB = NULL; else if( PtSegmB->Type() != TYPE_PCB ) PtSegmB = PtSegmB->Back(); else PtSegmB = NULL; } } /* General search. */ for( PtSegmN = pt_base; PtSegmN != NULL; PtSegmN = PtSegmN->Next() ) { if( PtSegmN->GetState( IS_DELETED | BUSY ) ) { if( PtSegmN == pt_lim ) break; continue; } if( PtSegmN == PtRefSegm ) { if( PtSegmN == pt_lim ) break; continue; } max_dist = ( PtSegmN->m_Width + PtRefSegm->m_Width ) / 2; if( IsPointsAreNear( pos_ref, PtSegmN->m_Start, max_dist ) ) { if( Reflayer & PtSegmN->ReturnMaskLayer() ) return PtSegmN; } if( IsPointsAreNear( pos_ref, PtSegmN->m_End, max_dist ) ) { if( Reflayer & PtSegmN->ReturnMaskLayer() ) return PtSegmN; } if( PtSegmN == pt_lim ) break; } return NULL; }