184 lines
4.7 KiB
C++
184 lines
4.7 KiB
C++
/*******************/
|
|
/* 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;
|
|
}
|