locate.cpp 17.1 KB
Newer Older
1 2 3
/*******************/
/* Locate element. */
/*******************/
4

5

6 7 8 9
#include "fctsys.h"

#include "common.h"
#include "pcbnew.h"
charras's avatar
charras committed
10
#include "class_board_design_settings.h"
11 12 13

#include "protos.h"

dickelbeck's avatar
dickelbeck committed
14

15

16 17 18
/**
 * Function RefPos
 * returns the reference position, coming from either the mouse position or the
dickelbeck's avatar
dickelbeck committed
19
 * the cursor position, based on whether the typeloc has the CURSEUR_OFF_GRILLE
20 21
 * flag ORed in or not.
 * @param typeloc int with possible CURSEUR_OFF_GRILLE bit on.
dickelbeck's avatar
dickelbeck committed
22
 * @return wxPoint - The reference point, either the mouse position or
23
 *   the cursor position.
dickelbeck's avatar
dickelbeck committed
24
 */
25 26
wxPoint inline RefPos( int typeloc )
{
27
    return ActiveScreen->RefPos( (typeloc & CURSEUR_OFF_GRILLE) != 0 );
28
}
dickelbeck's avatar
dickelbeck committed
29

30

31 32 33 34 35 36 37 38 39
/* Locates a via point pX, pY
 * If layer < 0 will be located via whatever layer
 * If layer = 0 .. 15 Via will be located according to its type:
 * - Traverse: all layers
 * - = Blind between layers useful
 * - Blind idem
 * Entry: coord point of reference, layer
 * Output: NULL if not via
 * (* TRACK) address via
dickelbeck's avatar
dickelbeck committed
40
 */
41
TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer )
42
{
dickelbeck's avatar
dickelbeck committed
43
    TRACK* track;
44

dickelbeck's avatar
dickelbeck committed
45
    for( track = Pcb->m_Track;  track; track = track->Next() )
46
    {
47
        if( track->Type() != TYPE_VIA )
dickelbeck's avatar
dickelbeck committed
48
            continue;
dickelbeck's avatar
dickelbeck committed
49
        if( track->m_Start != pos )
dickelbeck's avatar
dickelbeck committed
50
            continue;
dickelbeck's avatar
dickelbeck committed
51
        if( track->GetState( BUSY | DELETED ) )
dickelbeck's avatar
dickelbeck committed
52 53
            continue;
        if( layer < 0 )
dickelbeck's avatar
dickelbeck committed
54 55 56
            break;
        if( track->IsOnLayer( layer ) )
            break;
57
    }
dickelbeck's avatar
dickelbeck committed
58

dickelbeck's avatar
dickelbeck committed
59
    return track;
60 61 62
}


dickelbeck's avatar
dickelbeck committed
63
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& pos, int layer )
64
{
dickelbeck's avatar
dickelbeck committed
65
    TRACK* track;
66

dickelbeck's avatar
dickelbeck committed
67
    for( track = aStart;   track;  track = track->Next() )
68
    {
69
        if( track->Type() != TYPE_VIA )
70
            continue;
dickelbeck's avatar
dickelbeck committed
71
        if( !track->HitTest(pos) )
72
            continue;
dickelbeck's avatar
dickelbeck committed
73
        if( track->GetState( BUSY | DELETED ) )
74 75
            continue;
        if( layer < 0 )
dickelbeck's avatar
dickelbeck committed
76 77 78
            break;
        if( track->IsOnLayer( layer ) )
            break;
79 80
    }

dickelbeck's avatar
dickelbeck committed
81
    return track;
82 83 84
}


85 86 87 88 89 90 91
/* Location of the pellet CONNECTED developed a test track
 * input: ptr_piste: pointer to the segment of track
 * Extr = flag = START -> beginning of the test segment
 * END -> end of the segment to be tested
 * Returns:
 * A pointer to the description of the pad if found.
 * NULL pointer if pad NOT FOUND
dickelbeck's avatar
dickelbeck committed
92
 */
93
D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_piste, int extr )
94
{
dickelbeck's avatar
dickelbeck committed
95 96
    D_PAD*  ptr_pad = NULL;
    wxPoint ref_pos;
97

dickelbeck's avatar
dickelbeck committed
98
    int     masque_layer = g_TabOneLayerMask[ptr_piste->GetLayer()];
dickelbeck's avatar
dickelbeck committed
99

dickelbeck's avatar
dickelbeck committed
100 101
    if( extr == START )
    {
102
        ref_pos = ptr_piste->m_Start;
dickelbeck's avatar
dickelbeck committed
103
    }
104
    else
dickelbeck's avatar
dickelbeck committed
105
    {
106
        ref_pos = ptr_piste->m_End;
dickelbeck's avatar
dickelbeck committed
107
    }
dickelbeck's avatar
dickelbeck committed
108

dickelbeck's avatar
dickelbeck committed
109
    for( MODULE* module = Pcb->m_Modules;  module;  module = module->Next() )
dickelbeck's avatar
dickelbeck committed
110 111 112 113 114
    {
        ptr_pad = Locate_Pads( module, ref_pos, masque_layer );
        if( ptr_pad != NULL )
            break;
    }
115

dickelbeck's avatar
dickelbeck committed
116 117
    return ptr_pad;
}
118 119 120


/*
121 122 123 124 125 126 127 128
 * Locate pad pointed to by the coordinates ref_pos.x,, ref_pos.y or
 * the mouse, search done on all tracks.
 * Input:
 * - mouse coord or ref_pos
 * Returns:
 * Pointer to the pad if found.
 * NULL pointer if pad NOT FOUND
 * Num_empr = number of fingerprint pad
dickelbeck's avatar
dickelbeck committed
129
 *
130
 * Priority is the active layer
dickelbeck's avatar
dickelbeck committed
131 132
 */
D_PAD* Locate_Any_Pad( BOARD* Pcb, int typeloc, bool OnlyCurrentLayer )
133
{
134
    wxPoint ref_pos = RefPos( typeloc );
dickelbeck's avatar
dickelbeck committed
135
    return Locate_Any_Pad( Pcb, ref_pos, OnlyCurrentLayer );
136 137
}

dickelbeck's avatar
dickelbeck committed
138

139 140
D_PAD* Locate_Any_Pad( BOARD* Pcb, const wxPoint& ref_pos,
                       bool OnlyCurrentLayer )
141
{
142 143
    int layer_mask =
        g_TabOneLayerMask[ ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer];
dickelbeck's avatar
dickelbeck committed
144

dickelbeck's avatar
dickelbeck committed
145
    for( MODULE* module=Pcb->m_Modules;  module;   module = module->Next() )
146
    {
dickelbeck's avatar
dickelbeck committed
147
        D_PAD*  pt_pad;
dickelbeck's avatar
dickelbeck committed
148

149
        /* First: Search a pad on the active layer: */
dickelbeck's avatar
dickelbeck committed
150 151
        if( ( pt_pad = Locate_Pads( module, ref_pos, layer_mask ) ) != NULL )
            return pt_pad;
152

dickelbeck's avatar
dickelbeck committed
153 154
        /* If not found, search on other layers: */
        if( !OnlyCurrentLayer )
155
        {
dickelbeck's avatar
dickelbeck committed
156 157
            if( ( pt_pad = Locate_Pads( module, ref_pos, ALL_LAYERS ) ) != NULL )
                return pt_pad;
158 159
        }
    }
dickelbeck's avatar
dickelbeck committed
160 161

    return NULL;
162 163 164
}


165 166 167 168 169 170 171 172
/* Locate pad pointed to by the coordinate ref_pos.x,, ref_pos.y or
 * the mouse on the current footprint.
 * Input:
 * - General parameters of the footprint update by characters()
 * - = Masque_layer layer(s) (bit_masque) which must be the pad
 * Returns:
 * A pointer to the pad if found
 * NULL pointer if pad NOT FOUND
dickelbeck's avatar
dickelbeck committed
173 174
 */
D_PAD* Locate_Pads( MODULE* module, int masque_layer, int typeloc )
175
{
176
    wxPoint ref_pos = RefPos( typeloc );
dickelbeck's avatar
dickelbeck committed
177
    return Locate_Pads( module, ref_pos, masque_layer );
178 179 180
}


dickelbeck's avatar
dickelbeck committed
181
D_PAD* Locate_Pads( MODULE* module, const wxPoint& ref_pos, int masque_layer )
182
{
dickelbeck's avatar
dickelbeck committed
183
    for( D_PAD* pt_pad = module->m_Pads;   pt_pad;   pt_pad = pt_pad->Next() )
184
    {
185 186
        /* ... and on the correct layer. */
        if( ( pt_pad->m_Masque_Layer & masque_layer ) == 0 )
dickelbeck's avatar
dickelbeck committed
187
            continue;
188

189 190
        if( pt_pad->HitTest( ref_pos ) )
            return pt_pad;
191
    }
dickelbeck's avatar
dickelbeck committed
192 193

    return NULL;
194 195 196
}


197 198 199
/**
 * Function Locate_Prefered_Module
 * locates a footprint by its bounding rectangle.  If several footprints
200 201
 * are possible, then the priority is: the closest on the active layer, then
 * closest.
202
 * The current mouse or cursor coordinates are grabbed from the active window
203 204 205
 * to perform hit-testing.
 * distance is calculated via manhattan distance from the center of the
 * bounding rectangle to the cursor position.
206 207 208 209
 *
 * @param Pcb The BOARD to search within.
 * @param typeloc Flag bits, tuning the search, see pcbnew.h
 * @return MODULE* - the best module or NULL if none.
dickelbeck's avatar
dickelbeck committed
210
 */
211
MODULE* Locate_Prefered_Module( BOARD* Pcb, int typeloc )
212
{
dickelbeck's avatar
dickelbeck committed
213
    MODULE* pt_module;
214 215 216 217 218 219 220
    int     lx, ly;
    MODULE* module      = NULL;
    MODULE* Altmodule   = NULL;
    int     min_dim     = 0x7FFFFFFF;
    int     alt_min_dim = 0x7FFFFFFF;
    int     layer;
    wxPoint ref_pos;
dickelbeck's avatar
dickelbeck committed
221

222 223
    ref_pos = RefPos( typeloc );

224
    pt_module = Pcb->m_Modules;
225
    for(  ;  pt_module;  pt_module = (MODULE*) pt_module->Next() )
226
    {
227 228
        // is the ref point within the module's bounds?
        if( !pt_module->HitTest( ref_pos ) )
229 230
            continue;

231 232
        // if caller wants to ignore locked modules, and this one is locked,
        // skip it.
233 234
        if( (typeloc & IGNORE_LOCKED) && pt_module->IsLocked() )
            continue;
dickelbeck's avatar
dickelbeck committed
235

236 237 238 239 240
        /* Calculate priority: the priority is given to the layer of the
         * module and the copper layer if the module layer is indelible,
         * adhesive copper, a layer if cmp module layer is indelible,
         * adhesive component.
         */
241
        layer = pt_module->GetLayer();
242 243

        if( layer==ADHESIVE_N_CU || layer==SILKSCREEN_N_CU )
dickelbeck's avatar
dickelbeck committed
244
            layer = LAYER_N_BACK;
245 246

        else if( layer==ADHESIVE_N_CMP || layer==SILKSCREEN_N_CMP )
dickelbeck's avatar
dickelbeck committed
247
            layer = LAYER_N_FRONT;
dickelbeck's avatar
dickelbeck committed
248

249
        /* Test of minimum size to choosing the best candidate. */
dickelbeck's avatar
dickelbeck committed
250

251 252 253 254 255 256
        int offx = pt_module->m_BoundaryBox.m_Size.x / 2 +
            pt_module->m_BoundaryBox.m_Pos.x +
            pt_module->m_Pos.x;
        int offy = pt_module->m_BoundaryBox.m_Size.y / 2
            + pt_module->m_BoundaryBox.m_Pos.y
            + pt_module->m_Pos.y;
dickelbeck's avatar
dickelbeck committed
257
        //off x & offy point to the middle of the box.
258
        int dist = abs( ref_pos.x - offx ) + abs( ref_pos.y - offy );
dickelbeck's avatar
dickelbeck committed
259 260
        lx = pt_module->m_BoundaryBox.GetWidth();
        ly = pt_module->m_BoundaryBox.GetHeight();
261 262
        //int dist = MIN(lx, ly);  // to pick the smallest module (kinda
        // screwy with same-sized modules -- this is bad!)
dickelbeck's avatar
dickelbeck committed
263

264 265 266 267 268
        if( ( (PCB_SCREEN*) ActiveScreen )->m_Active_Layer == layer )
        {
            if( dist <= min_dim )
            {
                /* better footprint shown on the active layer */
dickelbeck's avatar
dickelbeck committed
269
                module  = pt_module;
270
                min_dim = dist;
271 272
            }
        }
273 274 275
        else if( !( typeloc & MATCH_LAYER )
            && ( !( typeloc & VISIBLE_ONLY )
                 || IsModuleLayerVisible( layer ) ) )
276
        {
277
            if( dist <= alt_min_dim )
dickelbeck's avatar
dickelbeck committed
278
            {
279
                /* better footprint shown on other layers */
dickelbeck's avatar
dickelbeck committed
280
                Altmodule   = pt_module;
281
                alt_min_dim = dist;
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
            }
        }
    }

    if( module )
    {
        return module;
    }

    if( Altmodule )
    {
        return Altmodule;
    }

    return NULL;
297 298
}

299

300
/*
301 302
 * return true if the dist between p1 and p2 < max_dist
 * Currently in test (currently rasnest algos work only if p1 == p2)
303
*/
304
inline bool IsPointsAreNear(wxPoint & p1, wxPoint & p2, int max_dist)
305
{
306
#if 0   // Do not change it: does not work
dickelbeck's avatar
dickelbeck committed
307
{
308
int dist;
dickelbeck's avatar
dickelbeck committed
309 310 311 312
    dist = abs(p1.x - p2.x) + abs (p1.y - p2.y);
    dist *= 7;
    dist /= 10;
    if ( dist < max_dist ) return true;
313
}
314
#else
dickelbeck's avatar
dickelbeck committed
315
    if ( p1 == p2 ) return true;
316
#endif
dickelbeck's avatar
dickelbeck committed
317
    return false;
318 319
}

dickelbeck's avatar
dickelbeck committed
320

321 322 323 324
/** 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
325 326
 *  if extr == END, the ending track segment PtRefSegm is used
 *  The test connection consider only end track segments
dickelbeck's avatar
dickelbeck committed
327
 *
328 329 330 331
 *  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:
332 333
 *  a first search is made considering only the +/- 50 next door neighbor
 *  of PtRefSegm.
334 335 336 337 338 339
 *  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
dickelbeck's avatar
dickelbeck committed
340
 */
341 342
TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
                               TRACK* pt_lim, int extr )
343
{
344 345
    const int NEIGHTBOUR_COUNT_MAX = 50;

dickelbeck's avatar
dickelbeck committed
346 347 348 349
    TRACK*  PtSegmB, * PtSegmN;
    int     Reflayer;
    wxPoint pos_ref;
    int     ii;
dickelbeck's avatar
dickelbeck committed
350
    int     max_dist;
351

dickelbeck's avatar
dickelbeck committed
352 353 354 355
    if( extr == START )
        pos_ref = PtRefSegm->m_Start;
    else
        pos_ref = PtRefSegm->m_End;
356 357 358 359 360

    Reflayer = PtRefSegm->ReturnMaskLayer();

    PtSegmB = PtSegmN = PtRefSegm;

361
    for( ii = 0; ii < NEIGHTBOUR_COUNT_MAX; ii++ )
dickelbeck's avatar
dickelbeck committed
362 363 364
    {
        if( (PtSegmN == NULL) && (PtSegmB == NULL) )
            break;
365

366
        if( PtSegmN )
dickelbeck's avatar
dickelbeck committed
367 368 369 370 371
        {
            if( PtSegmN->GetState( BUSY | DELETED ) )
                goto suite;
            if( PtSegmN == PtRefSegm )
                goto suite;
372

373 374
            /* max_dist is the max distance between 2 track ends which
             * ensure a copper continuity */
dickelbeck's avatar
dickelbeck committed
375
            max_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2;
376

377
            if( IsPointsAreNear(pos_ref, PtSegmN->m_Start, max_dist) )
378
            {
dickelbeck's avatar
dickelbeck committed
379 380 381
                if( Reflayer & PtSegmN->ReturnMaskLayer() )
                    return PtSegmN;
            }
382

383
            if( IsPointsAreNear(pos_ref, PtSegmN->m_End, max_dist) )
384
            {
dickelbeck's avatar
dickelbeck committed
385 386
                if( Reflayer & PtSegmN->ReturnMaskLayer() )
                    return PtSegmN;
387
            }
dickelbeck's avatar
dickelbeck committed
388 389 390 391
suite:
            if( PtSegmN == pt_lim )
                PtSegmN = NULL;
            else
392
                PtSegmN =  PtSegmN->Next();
dickelbeck's avatar
dickelbeck committed
393
        }
394 395

        if( PtSegmB )
dickelbeck's avatar
dickelbeck committed
396 397 398 399 400
        {
            if( PtSegmB->GetState( BUSY | DELETED ) )
                goto suite1;
            if( PtSegmB == PtRefSegm )
                goto suite1;
401

dickelbeck's avatar
dickelbeck committed
402
            max_dist = (PtSegmB->m_Width + PtRefSegm->m_Width)/2;
403

404
            if( IsPointsAreNear(pos_ref, PtSegmB->m_Start, max_dist) )
405
            {
dickelbeck's avatar
dickelbeck committed
406 407 408
                if( Reflayer & PtSegmB->ReturnMaskLayer() )
                    return PtSegmB;
            }
409

410
            if( IsPointsAreNear(pos_ref, PtSegmB->m_End, max_dist) )
411
            {
dickelbeck's avatar
dickelbeck committed
412 413
                if( Reflayer & PtSegmB->ReturnMaskLayer() )
                    return PtSegmB;
414
            }
dickelbeck's avatar
dickelbeck committed
415 416 417
suite1:
            if( PtSegmB == pt_base )
                PtSegmB = NULL;
418
            else if( PtSegmB->Type() != TYPE_PCB )
419
                PtSegmB =  PtSegmB->Back();
dickelbeck's avatar
dickelbeck committed
420 421
            else
                PtSegmB = NULL;
422
        }
dickelbeck's avatar
dickelbeck committed
423
    }
424

425
    /* General search. */
426
    for( PtSegmN = pt_base; PtSegmN != NULL; PtSegmN =  PtSegmN->Next() )
dickelbeck's avatar
dickelbeck committed
427 428
    {
        if( PtSegmN->GetState( DELETED | BUSY ) )
429
        {
dickelbeck's avatar
dickelbeck committed
430 431
            if( PtSegmN == pt_lim )
                break;
432
            continue;
dickelbeck's avatar
dickelbeck committed
433 434 435 436 437
        }
        if( PtSegmN == PtRefSegm )
        {
            if( PtSegmN == pt_lim )
                break;
438
            continue;
dickelbeck's avatar
dickelbeck committed
439
        }
440

441
        max_dist = ( PtSegmN->m_Width + PtRefSegm->m_Width ) / 2;
442

443 444
        if( IsPointsAreNear( pos_ref, PtSegmN->m_Start, max_dist ) )
        {
dickelbeck's avatar
dickelbeck committed
445 446 447
            if( Reflayer & PtSegmN->ReturnMaskLayer() )
                return PtSegmN;
        }
448

449 450
        if( IsPointsAreNear( pos_ref, PtSegmN->m_End, max_dist ) )
        {
dickelbeck's avatar
dickelbeck committed
451 452
            if( Reflayer & PtSegmN->ReturnMaskLayer() )
                return PtSegmN;
453
        }
dickelbeck's avatar
dickelbeck committed
454 455 456 457 458
        if( PtSegmN == pt_lim )
            break;
    }

    return NULL;
459 460
}

dickelbeck's avatar
dickelbeck committed
461

462
/*
463 464 465
 * 1 - Locate segment of track leading from the mouse.
 * 2 - Locate segment of track point by point
 * ref_pos.x, ref_pos.y.r
dickelbeck's avatar
dickelbeck committed
466
 *
467
 * The search begins to address start_adresse
dickelbeck's avatar
dickelbeck committed
468 469
 */
TRACK* Locate_Pistes( TRACK* start_adresse, int MasqueLayer, int typeloc )
470
{
471
    wxPoint ref_pos = RefPos( typeloc );
472

dickelbeck's avatar
dickelbeck committed
473
    return Locate_Pistes( start_adresse, ref_pos, MasqueLayer );
474 475 476
}


477 478
TRACK* Locate_Pistes( TRACK* start_adresse, const wxPoint& ref_pos,
                      int MasqueLayer )
479
{
480
    for( TRACK* track = start_adresse;   track;  track =  track->Next() )
481
    {
482 483 484 485
        int layer = track->GetLayer();

        if( track->GetState( BUSY | DELETED ) )
        {
486 487 488
            // D( printf( "track %p is BUSY | DELETED. BUSY=%d DELETED=%d\n",
            //            track, track->GetState( BUSY ),
            //            track->GetState( DELETED ) );)
dickelbeck's avatar
dickelbeck committed
489
            continue;
490
        }
dickelbeck's avatar
dickelbeck committed
491

492
        if( g_DesignSettings.IsLayerVisible( layer ) == false )
493
            continue;
494

495
        if( track->Type() == TYPE_VIA ) /* VIA encountered. */
496
        {
497 498
            if( track->HitTest( ref_pos ) )
                return track;
dickelbeck's avatar
dickelbeck committed
499 500 501
        }
        else
        {
502
            if( (g_TabOneLayerMask[layer] & MasqueLayer) == 0 )
503
                continue;   /* Segments on different layers. */
dickelbeck's avatar
dickelbeck committed
504

505 506
            if( track->HitTest( ref_pos ) )
                return track;
507 508
        }
    }
dickelbeck's avatar
dickelbeck committed
509

dickelbeck's avatar
dickelbeck committed
510 511
    return NULL;
}
512

dickelbeck's avatar
dickelbeck committed
513
/*
514 515 516
 * 1 - Locate zone area by the mouse.
 * 2 - Locate zone area by point
 * def_pos.x, ref_pos.y.r
dickelbeck's avatar
dickelbeck committed
517
 *
518
 * If layer == -1, tst layer is not
dickelbeck's avatar
dickelbeck committed
519
 *
520
 * The search begins to address start_adresse
dickelbeck's avatar
dickelbeck committed
521 522
 */
TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc )
523
{
524
    wxPoint ref_pos = RefPos( typeloc );
525

dickelbeck's avatar
dickelbeck committed
526
    return Locate_Zone( start_adresse, ref_pos, layer );
527 528 529
}


dickelbeck's avatar
dickelbeck committed
530
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer )
531
{
532
    for( TRACK* Zone = start_adresse;  Zone;   Zone =  Zone->Next() )
dickelbeck's avatar
dickelbeck committed
533
    {
534
        if( (layer != -1) && (Zone->GetLayer() != layer) )
dickelbeck's avatar
dickelbeck committed
535
            continue;
dickelbeck's avatar
dickelbeck committed
536

dickelbeck's avatar
dickelbeck committed
537
        if( Zone->HitTest( ref_pos ) )
dickelbeck's avatar
dickelbeck committed
538 539
            return Zone;
    }
540

dickelbeck's avatar
dickelbeck committed
541 542
    return NULL;
}
543 544


545 546 547 548
/* Find the pad center px, py,
 * The layer INDICATED BY masque_layer (bitwise)
 * (Runway end)
 * The list of pads must already exist.
dickelbeck's avatar
dickelbeck committed
549
 *
550 551 552 553
 * Returns:
 *   NULL if no pad located.
 *   Pointer to the structure corresponding descr_pad if pad found
 * (Good position and good layer).
dickelbeck's avatar
dickelbeck committed
554
 */
555 556
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos,
                                 int masque_layer )
557
{
558
    for( unsigned i=0; i<Pcb->GetPadsCount();  ++i )
dickelbeck's avatar
dickelbeck committed
559
    {
560
        D_PAD* pad = Pcb->m_NetInfo->GetPad(i);
561

dickelbeck's avatar
dickelbeck committed
562 563
        if( pad->m_Pos != ref_pos )
            continue;
564

565
        /* Pad found, it must be on the correct layer */
dickelbeck's avatar
dickelbeck committed
566 567 568
        if( pad->m_Masque_Layer & masque_layer )
            return pad;
    }
569

dickelbeck's avatar
dickelbeck committed
570
    return NULL;
571 572 573
}


574 575 576 577 578 579 580
/* Locate segment with one end that coincides with the point x, y
 * Data on layers by masklayer
 * Research is done to address start_adr has end_adr
 * If end_adr = NULL, end search list
 * The segments of track marks with the flag are not DELETED or taken
 * into account
 */
dickelbeck's avatar
dickelbeck committed
581 582
TRACK* Fast_Locate_Piste( TRACK* start_adr, TRACK* end_adr,
                          const wxPoint& ref_pos, int MaskLayer )
583
{
dickelbeck's avatar
dickelbeck committed
584
    TRACK* PtSegm;
585

dickelbeck's avatar
dickelbeck committed
586 587
    if( start_adr == NULL )
        return NULL;
588

589
    for( PtSegm = start_adr; PtSegm != NULL; PtSegm =  PtSegm->Next() )
dickelbeck's avatar
dickelbeck committed
590 591
    {
        if( PtSegm->GetState( DELETED | BUSY ) == 0 )
592 593
        {
            if( ref_pos == PtSegm->m_Start )
dickelbeck's avatar
dickelbeck committed
594
            {
dickelbeck's avatar
dickelbeck committed
595 596 597
                if( MaskLayer & PtSegm->ReturnMaskLayer() )
                    return PtSegm;
            }
598 599

            if( ref_pos == PtSegm->m_End )
dickelbeck's avatar
dickelbeck committed
600
            {
dickelbeck's avatar
dickelbeck committed
601 602
                if( MaskLayer & PtSegm->ReturnMaskLayer() )
                    return PtSegm;
603 604
            }
        }
dickelbeck's avatar
dickelbeck committed
605 606 607 608 609
        if( PtSegm == end_adr )
            break;
    }

    return NULL;
610 611
}

dickelbeck's avatar
dickelbeck committed
612

613 614 615 616 617
/* Locates via through the point x, y, on layer data by masklayer.
 * Search is done to address start_adr has end_adr.
 * If end_adr = NULL, end search list
 * Vias whose parameter has the State or DELETED bit BUSY = 1 are ignored
 */
dickelbeck's avatar
dickelbeck committed
618 619
TRACK* Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr,
                        const wxPoint& pos, int MaskLayer )
620
{
dickelbeck's avatar
dickelbeck committed
621
    TRACK* PtSegm;
622

623
    for( PtSegm = start_adr; PtSegm != NULL; PtSegm = PtSegm->Next() )
dickelbeck's avatar
dickelbeck committed
624
    {
625
        if( PtSegm->Type() == TYPE_VIA )
626 627
        {
            if( pos == PtSegm->m_Start )
dickelbeck's avatar
dickelbeck committed
628 629
            {
                if( PtSegm->GetState( BUSY | DELETED ) == 0 )
dickelbeck's avatar
dickelbeck committed
630
                {
dickelbeck's avatar
dickelbeck committed
631 632
                    if( MaskLayer & PtSegm->ReturnMaskLayer() )
                        return PtSegm;
633 634 635
                }
            }
        }
dickelbeck's avatar
dickelbeck committed
636 637 638 639 640
        if( PtSegm == end_adr )
            break;
    }

    return NULL;
641
}