~pierre-parent-k/kicad/length-tunning

« back to all changes in this revision

Viewing changes to pcbnew/class_track.cpp

  • Committer: Pierre Parent
  • Date: 2014-07-06 10:32:13 UTC
  • mfrom: (4798.1.179 kicad)
  • Revision ID: pierre.parent@insa-rouen.fr-20140706103213-wjsdy0hc9q6wbz5v
Merge with lp:kicad 4977

Show diffs side-by-side

added added

removed removed

Lines of Context:
66
66
}
67
67
 
68
68
 
69
 
/*
70
 
 * return true if the dist between p1 and p2 < max_dist
71
 
 * Currently in test (currently ratsnest algos work only if p1 == p2)
72
 
 */
73
 
inline bool IsNear( wxPoint& p1, wxPoint& p2, int max_dist )
74
 
{
75
 
#if 0   // Do not change it: does not work
76
 
    int dist;
77
 
    dist = abs( p1.x - p2.x ) + abs( p1.y - p2.y );
78
 
    dist *= 7;
79
 
    dist /= 10;
80
 
 
81
 
    if ( dist < max_dist )
82
 
        return true;
83
 
#else
84
 
    if ( p1 == p2 )
85
 
        return true;
86
 
#endif
87
 
    return false;
88
 
}
89
 
 
90
 
 
91
 
TRACK* GetTrace( TRACK* aStartTrace, TRACK* aEndTrace, const wxPoint& aPosition,
92
 
                 LAYER_MSK aLayerMask )
93
 
{
94
 
    TRACK* PtSegm;
95
 
 
96
 
    if( aStartTrace == NULL )
97
 
        return NULL;
98
 
 
99
 
    for( PtSegm = aStartTrace; PtSegm != NULL; PtSegm =  PtSegm->Next() )
 
69
TRACK* GetTrack( TRACK* aStartTrace, const TRACK* aEndTrace,
 
70
        const wxPoint& aPosition, LSET aLayerMask )
 
71
{
 
72
    for( TRACK *PtSegm = aStartTrace; PtSegm != NULL; PtSegm = PtSegm->Next() )
100
73
    {
101
74
        if( PtSegm->GetState( IS_DELETED | BUSY ) == 0 )
102
75
        {
103
76
            if( aPosition == PtSegm->GetStart() )
104
77
            {
105
 
                if( aLayerMask & PtSegm->GetLayerMask() )
 
78
                if( ( aLayerMask & PtSegm->GetLayerSet() ).any() )
106
79
                    return PtSegm;
107
80
            }
108
81
 
109
82
            if( aPosition == PtSegm->GetEnd() )
110
83
            {
111
 
                if( aLayerMask & PtSegm->GetLayerMask() )
 
84
                if( ( aLayerMask & PtSegm->GetLayerSet() ).any() )
112
85
                    return PtSegm;
113
86
            }
114
87
        }
125
98
    BOARD_CONNECTED_ITEM( aParent, idtype )
126
99
{
127
100
    m_Width = Millimeter2iu( 0.2 );
128
 
    m_Shape = S_SEGMENT;
129
101
    start   = end = NULL;
130
 
    SetDrillDefault();
131
102
    m_Param = 0;
132
103
}
133
104
 
179
150
}
180
151
 
181
152
 
182
 
SEGVIA::SEGVIA( BOARD_ITEM* aParent ) :
 
153
VIA::VIA( BOARD_ITEM* aParent ) :
183
154
    TRACK( aParent, PCB_VIA_T )
184
155
{
185
 
    SetShape( VIA_THROUGH );
186
 
    m_Width = Millimeter2iu( 0.5 );
 
156
    SetViaType( VIA_THROUGH );
 
157
    m_BottomLayer = B_Cu;
 
158
    SetDrillDefault();
187
159
}
188
160
 
189
161
 
190
 
EDA_ITEM* SEGVIA::Clone() const
 
162
EDA_ITEM* VIA::Clone() const
191
163
{
192
 
    return new SEGVIA( *this );
 
164
    return new VIA( *this );
193
165
}
194
166
 
195
167
 
196
 
wxString SEGVIA::GetSelectMenuText() const
 
168
wxString VIA::GetSelectMenuText() const
197
169
{
198
170
    wxString text;
199
171
    wxString format;
200
172
    BOARD* board = GetBoard();
201
173
 
202
 
    int shape = GetShape();
203
 
 
204
 
    if( shape == VIA_BLIND_BURIED )
 
174
    switch( GetViaType() )
 
175
    {
 
176
    case VIA_BLIND_BURIED:
205
177
        format = _( "Blind/Buried Via %s, net[%s] (%d) on layers %s/%s" );
206
 
    else if( shape == VIA_MICROVIA )
 
178
        break;
 
179
    case VIA_MICROVIA:
207
180
        format = _( "Micro Via %s, Net [%s] (%d) on layers %s/%s" );
 
181
        break;
208
182
    // else say nothing about normal (through) vias
209
 
    else format = _( "Via %s net [%s] (%d) on layers %s/%s" );
 
183
    default:
 
184
        format = _( "Via %s net [%s] (%d) on layers %s/%s" );
 
185
        break;
 
186
    }
 
187
 
210
188
 
211
189
    if( board )
212
190
    {
213
191
        wxString netname = GetNetname();
214
192
 
215
193
        // say which layers, only two for now
216
 
        LAYER_NUM topLayer;
217
 
        LAYER_NUM botLayer;
 
194
        LAYER_ID topLayer;
 
195
        LAYER_ID botLayer;
218
196
        LayerPair( &topLayer, &botLayer );
219
197
        text.Printf( format.GetData(), GetChars( ShowWidth() ),
220
198
                     GetChars( netname ), GetNetCode(),
224
202
    }
225
203
    else
226
204
    {
227
 
        wxFAIL_MSG( wxT( "SEGVIA::GetSelectMenuText: BOARD is NULL" ) );
 
205
        wxFAIL_MSG( wxT( "VIA::GetSelectMenuText: BOARD is NULL" ) );
228
206
        text.Printf( format.GetData(), GetChars( ShowWidth() ),
229
207
                     wxT( "???" ), 0,
230
208
                     wxT( "??" ), wxT( "??" ) );
242
220
}
243
221
 
244
222
 
245
 
int TRACK::GetDrillValue() const
 
223
int VIA::GetDrillValue() const
246
224
{
247
 
    if( Type() != PCB_VIA_T )
248
 
        return 0;
249
 
 
250
225
    if( m_Drill > 0 )      // Use the specific value.
251
226
        return m_Drill;
252
227
 
253
228
    // Use the default value from the Netclass
254
 
    NETCLASS* netclass = GetNetClass();
 
229
    NETCLASSPTR netclass = GetNetClass();
255
230
 
256
 
    if( m_Shape == VIA_MICROVIA )
 
231
    if( GetViaType() == VIA_MICROVIA )
257
232
        return netclass->GetuViaDrill();
258
233
 
259
234
    return netclass->GetViaDrill();
368
343
{
369
344
    m_Start.y = aCentre.y - (m_Start.y - aCentre.y);
370
345
    m_End.y   = aCentre.y - (m_End.y - aCentre.y);
371
 
 
372
 
    if( Type() != PCB_VIA_T )
373
 
        SetLayer( FlipLayer( GetLayer() ) );
 
346
    SetLayer( FlipLayer( GetLayer() ) );
 
347
}
 
348
 
 
349
 
 
350
void VIA::Flip( const wxPoint& aCentre )
 
351
{
 
352
    m_Start.y = aCentre.y - (m_Start.y - aCentre.y);
 
353
    m_End.y   = aCentre.y - (m_End.y - aCentre.y);
374
354
}
375
355
 
376
356
 
391
371
}
392
372
 
393
373
 
394
 
bool SEGVIA::IsOnLayer( LAYER_NUM layer_number ) const
 
374
bool VIA::IsOnLayer( LAYER_ID layer_number ) const
395
375
{
396
 
    LAYER_NUM bottom_layer, top_layer;
 
376
    LAYER_ID bottom_layer, top_layer;
397
377
 
398
378
    LayerPair( &top_layer, &bottom_layer );
399
379
 
400
 
    if( bottom_layer <= layer_number && layer_number <= top_layer )
 
380
    wxASSERT( top_layer <= bottom_layer );
 
381
 
 
382
    if( top_layer <= layer_number && layer_number <= bottom_layer )
401
383
        return true;
402
384
    else
403
385
        return false;
404
386
}
405
387
 
406
388
 
407
 
LAYER_MSK TRACK::GetLayerMask() const
408
 
{
409
 
    if( Type() == PCB_VIA_T )
410
 
    {
411
 
        int via_type = GetShape();
412
 
 
413
 
        if( via_type == VIA_THROUGH )
414
 
            return ALL_CU_LAYERS;
415
 
 
416
 
        // VIA_BLIND_BURIED or VIA_MICRVIA:
417
 
 
418
 
        LAYER_NUM bottom_layer, top_layer;
419
 
 
420
 
        // LayerPair() knows how layers are stored
421
 
        ( (SEGVIA*) this )->LayerPair( &top_layer, &bottom_layer );
422
 
 
423
 
        LAYER_MSK layermask = NO_LAYERS;
424
 
 
425
 
        while( bottom_layer <= top_layer )
426
 
        {
427
 
            layermask |= ::GetLayerMask( bottom_layer );
428
 
            ++bottom_layer;
429
 
        }
430
 
 
431
 
        return layermask;
432
 
    }
433
 
    else
434
 
    {
435
 
        return ::GetLayerMask( m_Layer );
436
 
    }
437
 
}
438
 
 
439
 
 
440
 
void SEGVIA::SetLayerPair( LAYER_NUM top_layer, LAYER_NUM bottom_layer )
441
 
{
442
 
    if( GetShape() == VIA_THROUGH )
443
 
    {
444
 
        top_layer    = LAYER_N_FRONT;
445
 
        bottom_layer = LAYER_N_BACK;
446
 
    }
447
 
 
448
 
    if( bottom_layer > top_layer )
449
 
        EXCHG( bottom_layer, top_layer );
450
 
 
451
 
    // XXX EVIL usage of LAYER
452
 
    m_Layer = (top_layer & 15) + ( (bottom_layer & 15) << 4 );
453
 
}
454
 
 
455
 
 
456
 
void SEGVIA::LayerPair( LAYER_NUM* top_layer, LAYER_NUM* bottom_layer ) const
457
 
{
458
 
    LAYER_NUM b_layer = LAYER_N_BACK;
459
 
    LAYER_NUM t_layer = LAYER_N_FRONT;
460
 
 
461
 
    if( GetShape() != VIA_THROUGH )
462
 
    {
463
 
        // XXX EVIL usage of LAYER
464
 
        b_layer = (m_Layer >> 4) & 15;
465
 
        t_layer = m_Layer & 15;
466
 
 
467
 
        if( b_layer > t_layer )
 
389
LSET VIA::GetLayerSet() const
 
390
{
 
391
    if( GetViaType() == VIA_THROUGH )
 
392
        return LSET::AllCuMask();
 
393
 
 
394
    // VIA_BLIND_BURIED or VIA_MICRVIA:
 
395
 
 
396
    LAYER_ID bottom_layer, top_layer;
 
397
 
 
398
    // LayerPair() knows how layers are stored
 
399
    LayerPair( &top_layer, &bottom_layer );
 
400
 
 
401
    LSET layermask;
 
402
 
 
403
    wxASSERT( top_layer <= bottom_layer );
 
404
 
 
405
    // LAYER_IDs are numbered from front to back, this is top to bottom.
 
406
    for( LAYER_NUM id = top_layer;  id <= bottom_layer;  ++id )
 
407
    {
 
408
        layermask.set( id );
 
409
    }
 
410
 
 
411
    return layermask;
 
412
}
 
413
 
 
414
 
 
415
LSET TRACK::GetLayerSet() const
 
416
{
 
417
    return LSET( m_Layer );
 
418
}
 
419
 
 
420
 
 
421
void VIA::SetLayerPair( LAYER_ID aTopLayer, LAYER_ID aBottomLayer )
 
422
{
 
423
    if( GetViaType() == VIA_THROUGH )
 
424
    {
 
425
        aTopLayer    = F_Cu;
 
426
        aBottomLayer = B_Cu;
 
427
    }
 
428
 
 
429
    if( aBottomLayer < aTopLayer )
 
430
        EXCHG( aBottomLayer, aTopLayer );
 
431
 
 
432
    m_Layer = aTopLayer;
 
433
    m_BottomLayer = aBottomLayer;
 
434
}
 
435
 
 
436
 
 
437
void VIA::LayerPair( LAYER_ID* top_layer, LAYER_ID* bottom_layer ) const
 
438
{
 
439
    LAYER_ID t_layer = F_Cu;
 
440
    LAYER_ID b_layer = B_Cu;
 
441
 
 
442
    if( GetViaType() != VIA_THROUGH )
 
443
    {
 
444
        b_layer = m_BottomLayer;
 
445
        t_layer = m_Layer;
 
446
 
 
447
        if( b_layer < t_layer )
468
448
            EXCHG( b_layer, t_layer );
469
449
    }
470
450
 
557
537
        return NULL;
558
538
}
559
539
 
560
 
 
561
 
void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
562
 
                  const wxPoint& aOffset )
 
540
void TRACK::DrawShortNetname( EDA_DRAW_PANEL* panel,
 
541
        wxDC* aDC, GR_DRAWMODE aDrawMode, EDA_COLOR_T aBgColor )
563
542
{
564
 
    int l_trace;
565
 
    int radius;
566
 
    LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
567
 
 
568
 
    if( Type() == PCB_ZONE_T && DisplayOpt.DisplayZonesMode != 0 )
569
 
        return;
570
 
 
571
 
    BOARD * brd =  GetBoard( );
572
 
    EDA_COLOR_T color = brd->GetLayerColor(m_Layer);
573
 
 
574
 
    if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
575
 
        return;
576
 
 
577
 
#ifdef USE_WX_OVERLAY
578
 
    // If dragged not draw in OnPaint otherwise remains impressed in wxOverlay
579
 
    if( (m_Flags && IS_DRAGGED) && aDC->IsKindOf(wxCLASSINFO(wxPaintDC)))
580
 
      return;
581
 
#endif
582
 
 
583
 
    if( ( aDrawMode & GR_ALLOW_HIGHCONTRAST ) && DisplayOpt.ContrastModeDisplay )
584
 
    {
585
 
        if( !IsOnLayer( curr_layer ) )
586
 
            ColorTurnToDarkDarkGray( &color );
587
 
    }
588
 
 
589
 
    if( aDrawMode & GR_HIGHLIGHT )
590
 
        ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) );
591
 
 
592
 
    ColorApplyHighlightFlag( &color );
593
 
 
594
 
    SetAlpha( &color, 150 );
595
 
 
596
 
    GRSetDrawMode( aDC, aDrawMode );
597
 
 
598
 
 
599
 
    l_trace = m_Width >> 1;
600
 
 
601
 
    if( m_Shape == S_CIRCLE )
602
 
    {
603
 
        radius = KiROUND( GetLineLength( m_Start, m_End ) );
604
 
 
605
 
        if( aDC->LogicalToDeviceXRel( l_trace ) <= MIN_DRAW_WIDTH )
606
 
        {
607
 
            GRCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
608
 
                      m_Start.y + aOffset.y, radius, color );
609
 
        }
610
 
        else
611
 
        {
612
 
 
613
 
            if( aDC->LogicalToDeviceXRel( l_trace ) <= MIN_DRAW_WIDTH ) // Line mode if too small
614
 
            {
615
 
                GRCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
616
 
                          m_Start.y + aOffset.y, radius, color );
617
 
            }
618
 
            else if( ( !DisplayOpt.DisplayPcbTrackFill) || GetState( FORCE_SKETCH ) )
619
 
            {
620
 
                GRCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
621
 
                          m_Start.y + aOffset.y, radius - l_trace, color );
622
 
                GRCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
623
 
                          m_Start.y + aOffset.y, radius + l_trace, color );
624
 
            }
625
 
            else
626
 
            {
627
 
                GRCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
628
 
                          m_Start.y + aOffset.y, radius, m_Width, color );
629
 
            }
630
 
        }
631
 
 
632
 
        return;
633
 
    }
634
 
 
635
 
    if( aDC->LogicalToDeviceXRel( l_trace ) <= MIN_DRAW_WIDTH )
636
 
    {
637
 
        GRLine( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, 0, color );
638
 
        return;
639
 
    }
640
 
 
641
 
    if( !DisplayOpt.DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
642
 
    {
643
 
        GRCSegm( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, m_Width, color );
644
 
    }
645
 
    else
646
 
    {
647
 
        GRFillCSegm( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
648
 
                     m_Start.y + aOffset.y,
649
 
                     m_End.x + aOffset.x, m_End.y + aOffset.y, m_Width, color );
650
 
    }
651
 
 
652
 
    if( panel->GetScreen()->m_IsPrinting )
653
 
        return;
654
 
 
655
 
    // Show clearance for tracks, not for zone segments
656
 
    if( ShowClearance( this ) )
657
 
    {
658
 
        GRCSegm( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset,
659
 
                 m_Width + (GetClearance() * 2), color );
660
 
    }
661
 
 
662
 
    /* Display the short netname for tracks, not for zone segments.
663
 
     *  we must filter tracks, to avoid a lot of texts.
 
543
    /* we must filter tracks, to avoid a lot of texts.
664
544
     *  - only tracks with a length > 10 * thickness are eligible
665
545
     * and, of course, if we are not printing the board
666
546
     */
667
 
    if( Type() == PCB_ZONE_T )
668
 
        return;
669
 
 
670
547
    if( DisplayOpt.DisplayNetNamesMode == 0 || DisplayOpt.DisplayNetNamesMode == 1 )
671
548
        return;
672
549
 
703
580
 
704
581
        // Calculate angle: if the track segment is vertical, angle = 90 degrees
705
582
        // If horizontal 0 degrees, otherwise compute it
706
 
        double angle;                              // angle is in 0.1 degree
 
583
        double angle;        // angle is in 0.1 degree
707
584
 
708
585
        if( dy == 0 )        // Horizontal segment
709
586
        {
723
600
            }
724
601
        }
725
602
 
 
603
        LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
726
604
        if( ( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE )
727
605
         && ( !(!IsOnLayer( curr_layer )&& DisplayOpt.ContrastModeDisplay) ) )
728
606
        {
732
610
            tsize = (tsize * 7) / 10;       // small reduction to give a better look
733
611
            EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
734
612
            DrawGraphicHaloText( clipbox, aDC, tpos,
735
 
                                    color, BLACK, WHITE, net->GetShortNetname(), angle,
736
 
                                    wxSize( tsize, tsize ),
737
 
                                    GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
738
 
                                    tsize / 7,
739
 
                                    false, false );
 
613
                                 aBgColor, BLACK, WHITE, net->GetShortNetname(), angle,
 
614
                                 wxSize( tsize, tsize ),
 
615
                                 GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
 
616
                                 tsize / 7,
 
617
                                 false, false );
740
618
        }
741
619
    }
742
620
}
743
621
 
744
622
 
 
623
void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
 
624
                  const wxPoint& aOffset )
 
625
{
 
626
    BOARD * brd = GetBoard( );
 
627
    EDA_COLOR_T color = brd->GetLayerColor(m_Layer);
 
628
 
 
629
    if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
 
630
        return;
 
631
 
 
632
#ifdef USE_WX_OVERLAY
 
633
    // If dragged not draw in OnPaint otherwise remains impressed in wxOverlay
 
634
    if( (m_Flags & IS_DRAGGED) && aDC->IsKindOf(wxCLASSINFO(wxPaintDC)))
 
635
      return;
 
636
#endif
 
637
 
 
638
    if( ( aDrawMode & GR_ALLOW_HIGHCONTRAST ) && DisplayOpt.ContrastModeDisplay )
 
639
    {
 
640
        LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
 
641
 
 
642
        if( !IsOnLayer( curr_layer ) )
 
643
            ColorTurnToDarkDarkGray( &color );
 
644
    }
 
645
 
 
646
    if( aDrawMode & GR_HIGHLIGHT )
 
647
        ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) );
 
648
 
 
649
    ColorApplyHighlightFlag( &color );
 
650
 
 
651
    SetAlpha( &color, 150 );
 
652
 
 
653
    GRSetDrawMode( aDC, aDrawMode );
 
654
 
 
655
    int l_trace = m_Width / 2;
 
656
 
 
657
    if( aDC->LogicalToDeviceXRel( l_trace ) <= MIN_DRAW_WIDTH )
 
658
    {
 
659
        GRLine( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, 0, color );
 
660
        return;
 
661
    }
 
662
 
 
663
    if( !DisplayOpt.DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
 
664
    {
 
665
        GRCSegm( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, m_Width, color );
 
666
    }
 
667
    else
 
668
    {
 
669
        GRFillCSegm( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
 
670
                     m_Start.y + aOffset.y,
 
671
                     m_End.x + aOffset.x, m_End.y + aOffset.y, m_Width, color );
 
672
    }
 
673
 
 
674
    if( panel->GetScreen()->m_IsPrinting )
 
675
        return;
 
676
 
 
677
    // Show clearance for tracks, not for zone segments
 
678
    if( ShowClearance( this ) )
 
679
    {
 
680
        GRCSegm( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset,
 
681
                 m_Width + (GetClearance() * 2), color );
 
682
    }
 
683
 
 
684
    DrawShortNetname( panel, aDC, aDrawMode, color );
 
685
}
 
686
 
 
687
 
 
688
void SEGZONE::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
 
689
                    const wxPoint& aOffset )
 
690
{
 
691
    if( DisplayOpt.DisplayZonesMode != 0 )
 
692
        return;
 
693
 
 
694
    BOARD * brd = GetBoard( );
 
695
    EDA_COLOR_T color = brd->GetLayerColor(m_Layer);
 
696
 
 
697
    if( brd->IsLayerVisible( m_Layer ) == false && !( aDrawMode & GR_HIGHLIGHT ) )
 
698
        return;
 
699
 
 
700
#ifdef USE_WX_OVERLAY
 
701
    // If dragged not draw in OnPaint otherwise remains impressed in wxOverlay
 
702
    if( (m_Flags & IS_DRAGGED) && aDC->IsKindOf(wxCLASSINFO(wxPaintDC)))
 
703
      return;
 
704
#endif
 
705
 
 
706
    if( ( aDrawMode & GR_ALLOW_HIGHCONTRAST ) && DisplayOpt.ContrastModeDisplay )
 
707
    {
 
708
        LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
 
709
 
 
710
        if( !IsOnLayer( curr_layer ) )
 
711
            ColorTurnToDarkDarkGray( &color );
 
712
    }
 
713
 
 
714
    if( aDrawMode & GR_HIGHLIGHT )
 
715
        ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) );
 
716
 
 
717
    ColorApplyHighlightFlag( &color );
 
718
 
 
719
    SetAlpha( &color, 150 );
 
720
 
 
721
    GRSetDrawMode( aDC, aDrawMode );
 
722
 
 
723
    int l_trace = m_Width / 2;
 
724
 
 
725
    if( aDC->LogicalToDeviceXRel( l_trace ) <= MIN_DRAW_WIDTH )
 
726
    {
 
727
        GRLine( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, 0, color );
 
728
        return;
 
729
    }
 
730
 
 
731
    if( !DisplayOpt.DisplayPcbTrackFill || GetState( FORCE_SKETCH ) )
 
732
    {
 
733
        GRCSegm( panel->GetClipBox(), aDC, m_Start + aOffset, m_End + aOffset, m_Width, color );
 
734
    }
 
735
    else
 
736
    {
 
737
        GRFillCSegm( panel->GetClipBox(), aDC, m_Start.x + aOffset.x,
 
738
                     m_Start.y + aOffset.y,
 
739
                     m_End.x + aOffset.x, m_End.y + aOffset.y, m_Width, color );
 
740
    }
 
741
 
 
742
    // No clearance or netnames for zones
 
743
}
 
744
 
 
745
 
745
746
void TRACK::ViewGetLayers( int aLayers[], int& aCount ) const
746
747
{
747
748
    // Show the track and its netname on different layers
764
765
}
765
766
 
766
767
 
767
 
void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
 
768
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode,
768
769
                   const wxPoint& aOffset )
769
770
{
770
771
    int radius;
771
 
    LAYER_NUM curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
 
772
    LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
772
773
 
773
774
    int fillvia = 0;
774
775
    PCB_BASE_FRAME* frame  = (PCB_BASE_FRAME*) panel->GetParent();
780
781
    GRSetDrawMode( aDC, aDrawMode );
781
782
 
782
783
    BOARD * brd =  GetBoard( );
783
 
    EDA_COLOR_T color = brd->GetVisibleElementColor(VIAS_VISIBLE + m_Shape);
 
784
    EDA_COLOR_T color = brd->GetVisibleElementColor(VIAS_VISIBLE + GetViaType());
784
785
 
785
 
    if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + m_Shape) ) == false
 
786
    if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + GetViaType()) ) == false
786
787
        && ( color & HIGHLIGHT_FLAG ) != HIGHLIGHT_FLAG )
787
788
        return;
788
789
 
847
848
                {
848
849
                    blackpenstate = GetGRForceBlackPenState();
849
850
                    GRForceBlackPen( false );
850
 
                    color = g_DrawBgColor;
 
851
                    color = WHITE;
851
852
                }
852
853
                else
853
854
                {
879
880
 
880
881
    // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer
881
882
    // (so we can see 2 superimposed microvias ):
882
 
    if( GetShape() == VIA_MICROVIA )
 
883
    if( GetViaType() == VIA_MICROVIA )
883
884
    {
884
885
        int ax, ay, bx, by;
885
886
 
886
 
        if( IsOnLayer( LAYER_N_BACK ) )
 
887
        if( IsOnLayer( B_Cu ) )
887
888
        {
888
889
            ax = radius; ay = 0;
889
890
            bx = drill_radius; by = 0;
894
895
            bx = by = (drill_radius * 707) / 1000;
895
896
        }
896
897
 
897
 
        /* lines | or \ */
 
898
        // lines '|' or '\'
898
899
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax,
899
900
                m_Start.y + aOffset.y - ay,
900
901
                m_Start.x + aOffset.x - bx,
904
905
                m_Start.x + aOffset.x + ax,
905
906
                m_Start.y + aOffset.y + ay, 0, color );
906
907
 
907
 
        // lines - or /
 
908
        // lines - or '/'
908
909
        GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay,
909
910
                m_Start.y + aOffset.y - ax,
910
911
                m_Start.x + aOffset.x + by,
917
918
 
918
919
    // for Buried Vias, draw a partial line : orient depending on layer pair
919
920
    // (so we can see superimposed buried vias ):
920
 
    if( GetShape() == VIA_BLIND_BURIED )
 
921
    if( GetViaType() == VIA_BLIND_BURIED )
921
922
    {
922
923
        int ax = 0, ay = radius, bx = 0, by = drill_radius;
923
 
        LAYER_NUM layer_top, layer_bottom;
 
924
        LAYER_ID layer_top, layer_bottom;
924
925
 
925
 
        ( (SEGVIA*) this )->LayerPair( &layer_top, &layer_bottom );
 
926
        ( (VIA*) this )->LayerPair( &layer_top, &layer_bottom );
926
927
 
927
928
        // lines for the top layer
928
929
        RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) );
978
979
}
979
980
 
980
981
 
981
 
void SEGVIA::ViewGetLayers( int aLayers[], int& aCount ) const
 
982
void VIA::ViewGetLayers( int aLayers[], int& aCount ) const
982
983
{
983
984
    // Just show it on common via & via holes layers
984
 
    aLayers[0] = ITEM_GAL_LAYER( VIAS_VISIBLE );
 
985
    aLayers[0] = ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE );
985
986
    aLayers[1] = ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE );
986
987
    aCount = 2;
987
988
}
1015
1016
        }
1016
1017
    }
1017
1018
 
1018
 
    NETCLASS* netclass = GetNetClass();
 
1019
    NETCLASSPTR netclass = GetNetClass();
1019
1020
 
1020
1021
    if( netclass )
1021
1022
    {
1035
1036
    }
1036
1037
}
1037
1038
 
1038
 
 
1039
 
void TRACK::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList )
 
1039
void TRACK::GetMsgPanelInfoBase_Common( std::vector< MSG_PANEL_ITEM >& aList )
1040
1040
{
1041
1041
    wxString msg;
1042
 
    BOARD*   board = GetBoard();
1043
 
 
1044
 
    switch( Type() )
1045
 
    {
1046
 
    case PCB_VIA_T:
1047
 
        switch( GetShape() )
1048
 
        {
1049
 
        default:
1050
 
        case 0:
1051
 
            msg =  wxT( "???" ); // Not used yet, does not exist currently
1052
 
            break;
1053
 
 
1054
 
        case 1:
1055
 
            msg = _( "Micro Via" ); // from external layer (TOP or BOTTOM) from
1056
 
                                    // the near neighbor inner layer only
1057
 
            break;
1058
 
 
1059
 
        case 2:
1060
 
            msg = _( "Blind/Buried Via" );  // from inner or external to inner
1061
 
                                            // or external layer (no restriction)
1062
 
            break;
1063
 
 
1064
 
        case 3:
1065
 
            msg =  _( "Through Via" );  // Usual via (from TOP to BOTTOM layer only )
1066
 
            break;
1067
 
        }
1068
 
 
1069
 
        break;
1070
 
 
1071
 
    case PCB_TRACE_T:
1072
 
        msg = _( "Track" );
1073
 
        break;
1074
 
 
1075
 
    case PCB_ZONE_T:
1076
 
        msg = _( "Zone" );
1077
 
        break;
1078
 
 
1079
 
    default:
1080
 
        msg = wxT( "???" );
1081
 
        break;
1082
 
    }
1083
 
 
1084
 
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
1085
 
 
1086
 
    // Display Net Name (in Pcbnew)
1087
 
    if( board )
 
1042
 
 
1043
    // Display Net Name
 
1044
    if( GetBoard() )
1088
1045
    {
1089
1046
        NETINFO_ITEM* net = GetNet();
1090
1047
 
1095
1052
 
1096
1053
        aList.push_back( MSG_PANEL_ITEM( _( "NetName" ), msg, RED ) );
1097
1054
 
1098
 
        /* Display net code : (useful in test or debug) */
 
1055
        // Display net code : (useful in test or debug)
1099
1056
        msg.Printf( wxT( "%d.%d" ), GetNetCode(), GetSubNet() );
1100
1057
        aList.push_back( MSG_PANEL_ITEM( _( "NetCode" ), msg, RED ) );
1101
1058
    }
1127
1084
 
1128
1085
#endif  // defined(DEBUG)
1129
1086
 
1130
 
    /* Display the State member */
 
1087
    // Display the State member
1131
1088
    msg = wxT( ". . " );
1132
1089
 
1133
1090
    if( GetState( TRACK_LOCKED ) )
1137
1094
        msg[2] = 'A';
1138
1095
 
1139
1096
    aList.push_back( MSG_PANEL_ITEM( _( "Status" ), msg, MAGENTA ) );
1140
 
 
1141
 
    /* Display layer or layer pair) */
1142
 
    if( Type() == PCB_VIA_T )
1143
 
    {
1144
 
        SEGVIA* Via = (SEGVIA*) this;
1145
 
        LAYER_NUM top_layer, bottom_layer;
1146
 
 
1147
 
        Via->LayerPair( &top_layer, &bottom_layer );
1148
 
        if( board )
1149
 
            msg = board->GetLayerName( top_layer ) + wxT( "/" )
1150
 
                + board->GetLayerName( bottom_layer );
1151
 
        else
1152
 
            msg.Printf(wxT("%d/%d"), top_layer, bottom_layer );
1153
 
    }
1154
 
    else
1155
 
    {
1156
 
        if( board )
1157
 
            msg = board->GetLayerName( m_Layer );
1158
 
        else
1159
 
            msg.Printf(wxT("%d"), m_Layer );
1160
 
    }
1161
 
 
1162
 
    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), msg, BROWN ) );
1163
 
 
1164
 
    // Display width
1165
 
    msg = ::CoordinateToString( (unsigned) m_Width );
1166
 
 
1167
 
    if( Type() == PCB_VIA_T )      // Display Diam and Drill values
1168
 
    {
1169
 
        // Display diameter value:
1170
 
        aList.push_back( MSG_PANEL_ITEM( _( "Diam" ), msg, DARKCYAN ) );
1171
 
 
1172
 
        // Display drill value
1173
 
        int drill_value = GetDrillValue();
1174
 
 
1175
 
        msg = ::CoordinateToString( drill_value );
1176
 
 
1177
 
        wxString title = _( "Drill" );
1178
 
        title += wxT( " " );
1179
 
 
1180
 
        if( m_Drill >= 0 )
1181
 
            title += _( "(Specific)" );
1182
 
        else
1183
 
            title += _( "(Default)" );
1184
 
 
1185
 
        aList.push_back( MSG_PANEL_ITEM( title, msg, RED ) );
1186
 
    }
1187
 
    else
1188
 
    {
1189
 
        aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, DARKCYAN ) );
1190
 
    }
1191
 
 
1192
 
    // Display segment length
1193
 
    if( Type() != PCB_VIA_T )      // Display Diam and Drill values
1194
 
    {
1195
 
        msg = ::LengthDoubleToString( GetLength() );
1196
 
        aList.push_back( MSG_PANEL_ITEM( _( "Segment Length" ), msg, DARKCYAN ) );
1197
 
    }
1198
 
}
1199
 
 
1200
 
 
1201
 
bool TRACK::HitTest( const wxPoint& aPosition )
1202
 
{
1203
 
    int max_dist = m_Width >> 1;
1204
 
 
1205
 
    if( Type() == PCB_VIA_T )
1206
 
    {
1207
 
        // rel_pos is aPosition relative to m_Start (or the center of the via)
1208
 
        wxPoint rel_pos = aPosition - m_Start;
1209
 
        double dist = (double) rel_pos.x * rel_pos.x + (double) rel_pos.y * rel_pos.y;
1210
 
        return  dist <= (double) max_dist * max_dist;
1211
 
    }
1212
 
 
1213
 
    return TestSegmentHit( aPosition, m_Start, m_End, max_dist );
 
1097
}
 
1098
 
 
1099
void TRACK::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList )
 
1100
{
 
1101
    wxString msg;
 
1102
    BOARD* board = GetBoard();
 
1103
 
 
1104
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), _( "Track" ), DARKCYAN ) );
 
1105
 
 
1106
    GetMsgPanelInfoBase_Common( aList );
 
1107
 
 
1108
    // Display layer
 
1109
    if( board )
 
1110
        msg = board->GetLayerName( m_Layer );
 
1111
    else
 
1112
        msg.Printf(wxT("%d"), m_Layer );
 
1113
 
 
1114
    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), msg, BROWN ) );
 
1115
 
 
1116
    // Display width
 
1117
    msg = ::CoordinateToString( (unsigned) m_Width );
 
1118
 
 
1119
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, DARKCYAN ) );
 
1120
 
 
1121
    // Display segment length
 
1122
    msg = ::LengthDoubleToString( GetLength() );
 
1123
    aList.push_back( MSG_PANEL_ITEM( _( "Segment Length" ), msg, DARKCYAN ) );
 
1124
}
 
1125
 
 
1126
void SEGZONE::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList )
 
1127
{
 
1128
    wxString msg;
 
1129
    BOARD* board = GetBoard();
 
1130
 
 
1131
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), _( "Zone " ), DARKCYAN ) );
 
1132
 
 
1133
    GetMsgPanelInfoBase_Common( aList );
 
1134
 
 
1135
    // Display layer
 
1136
    if( board )
 
1137
        msg = board->GetLayerName( m_Layer );
 
1138
    else
 
1139
        msg.Printf(wxT("%d"), m_Layer );
 
1140
 
 
1141
    aList.push_back( MSG_PANEL_ITEM( _( "Layer" ), msg, BROWN ) );
 
1142
 
 
1143
    // Display width
 
1144
    msg = ::CoordinateToString( (unsigned) m_Width );
 
1145
 
 
1146
    aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, DARKCYAN ) );
 
1147
 
 
1148
    // Display segment length
 
1149
    msg = ::LengthDoubleToString( GetLength() );
 
1150
    aList.push_back( MSG_PANEL_ITEM( _( "Segment Length" ), msg, DARKCYAN ) );
 
1151
}
 
1152
 
 
1153
void VIA::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList )
 
1154
{
 
1155
    wxString msg;
 
1156
    BOARD*   board = GetBoard();
 
1157
 
 
1158
    switch( GetViaType() )
 
1159
    {
 
1160
    default:
 
1161
    case VIA_NOT_DEFINED:
 
1162
        msg =  wxT( "???" ); // Not used yet, does not exist currently
 
1163
        break;
 
1164
 
 
1165
    case VIA_MICROVIA:
 
1166
        msg = _( "Micro Via" ); // from external layer (TOP or BOTTOM) from
 
1167
                                    // the near neighbor inner layer only
 
1168
        break;
 
1169
 
 
1170
    case VIA_BLIND_BURIED:
 
1171
        msg = _( "Blind/Buried Via" );  // from inner or external to inner
 
1172
                                            // or external layer (no restriction)
 
1173
        break;
 
1174
 
 
1175
    case VIA_THROUGH:
 
1176
        msg =  _( "Through Via" );  // Usual via (from TOP to BOTTOM layer only )
 
1177
        break;
 
1178
    }
 
1179
 
 
1180
    aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
 
1181
 
 
1182
    GetMsgPanelInfoBase_Common( aList );
 
1183
 
 
1184
 
 
1185
    // Display layer pair
 
1186
    LAYER_ID top_layer, bottom_layer;
 
1187
 
 
1188
    LayerPair( &top_layer, &bottom_layer );
 
1189
    if( board )
 
1190
        msg = board->GetLayerName( top_layer ) + wxT( "/" )
 
1191
            + board->GetLayerName( bottom_layer );
 
1192
    else
 
1193
        msg.Printf(wxT("%d/%d"), top_layer, bottom_layer );
 
1194
 
 
1195
    aList.push_back( MSG_PANEL_ITEM( _( "Layers" ), msg, BROWN ) );
 
1196
 
 
1197
    // Display width
 
1198
    msg = ::CoordinateToString( (unsigned) m_Width );
 
1199
 
 
1200
    // Display diameter value:
 
1201
    aList.push_back( MSG_PANEL_ITEM( _( "Diam" ), msg, DARKCYAN ) );
 
1202
 
 
1203
    // Display drill value
 
1204
    int drill_value = GetDrillValue();
 
1205
 
 
1206
    msg = ::CoordinateToString( drill_value );
 
1207
 
 
1208
    wxString title = _( "Drill" );
 
1209
    title += wxT( " " );
 
1210
 
 
1211
    if( m_Drill >= 0 )
 
1212
        title += _( "(Specific)" );
 
1213
    else
 
1214
        title += _( "(Default)" );
 
1215
 
 
1216
    aList.push_back( MSG_PANEL_ITEM( title, msg, RED ) );
 
1217
}
 
1218
 
 
1219
 
 
1220
bool TRACK::HitTest( const wxPoint& aPosition ) const
 
1221
{
 
1222
    return TestSegmentHit( aPosition, m_Start, m_End, m_Width / 2 );
 
1223
}
 
1224
 
 
1225
bool VIA::HitTest( const wxPoint& aPosition ) const
 
1226
{
 
1227
    int max_dist = m_Width / 2;
 
1228
 
 
1229
    // rel_pos is aPosition relative to m_Start (or the center of the via)
 
1230
    wxPoint rel_pos = aPosition - m_Start;
 
1231
    double dist = (double) rel_pos.x * rel_pos.x + (double) rel_pos.y * rel_pos.y;
 
1232
    return  dist <= (double) max_dist * max_dist;
1214
1233
}
1215
1234
 
1216
1235
 
1217
1236
bool TRACK::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
1218
1237
{
 
1238
    EDA_RECT arect = aRect;
 
1239
    arect.Inflate( aAccuracy );
 
1240
 
 
1241
    if( aContained )
 
1242
        /* Tracks are a special case:
 
1243
         * they are considered inside the rect if one end is inside the rect */
 
1244
        return arect.Contains( GetStart() ) || arect.Contains( GetEnd() );
 
1245
    else
 
1246
        return arect.Intersects( GetStart(), GetEnd() );
 
1247
}
 
1248
 
 
1249
bool VIA::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
 
1250
{
1219
1251
    EDA_RECT box;
1220
1252
    EDA_RECT arect = aRect;
1221
1253
    arect.Inflate( aAccuracy );
1222
1254
 
1223
 
    if( Type() == PCB_VIA_T )
1224
 
    {
1225
 
        box.SetOrigin( GetStart() );
1226
 
        box.Inflate( GetWidth() >> 1 );
 
1255
    box.SetOrigin( GetStart() );
 
1256
    box.Inflate( GetWidth() / 2 );
1227
1257
 
1228
 
        if(aContained)
1229
 
            return arect.Contains( box );
1230
 
        else
1231
 
            return arect.Intersects( box );
1232
 
    }
 
1258
    if( aContained )
 
1259
        return arect.Contains( box );
1233
1260
    else
1234
 
    {
1235
 
        if( aContained )
1236
 
            // Tracks are a specila case:
1237
 
            // they are considered inside the rect if one end
1238
 
            // is inside the rect
1239
 
            return arect.Contains( GetStart() ) || arect.Contains( GetEnd() );
1240
 
        else
1241
 
            return arect.Intersects( GetStart(), GetEnd() );
1242
 
    }
1243
 
}
1244
 
 
1245
 
 
1246
 
TRACK* TRACK::GetVia( const wxPoint& aPosition, LAYER_NUM aLayer)
1247
 
{
1248
 
    TRACK* track;
1249
 
 
1250
 
    for( track = this;   track;  track = track->Next() )
1251
 
    {
1252
 
        if( track->Type() != PCB_VIA_T )
1253
 
            continue;
1254
 
 
1255
 
        if( !track->HitTest( aPosition ) )
1256
 
            continue;
1257
 
 
1258
 
        if( track->GetState( BUSY | IS_DELETED ) )
1259
 
            continue;
1260
 
 
1261
 
        if( aLayer == UNDEFINED_LAYER )
1262
 
            break;
1263
 
 
1264
 
        if( track->IsOnLayer( aLayer ) )
1265
 
            break;
1266
 
    }
1267
 
 
1268
 
    return track;
1269
 
}
1270
 
 
1271
 
 
1272
 
TRACK* TRACK::GetVia( TRACK* aEndTrace, const wxPoint& aPosition, LAYER_MSK aLayerMask )
1273
 
{
1274
 
    TRACK* trace;
1275
 
 
1276
 
    for( trace = this; trace != NULL; trace = trace->Next() )
1277
 
    {
1278
 
        if( trace->Type() == PCB_VIA_T )
 
1261
        return arect.Intersects( box );
 
1262
}
 
1263
 
 
1264
 
 
1265
VIA* TRACK::GetVia( const wxPoint& aPosition, LAYER_ID aLayer)
 
1266
{
 
1267
    for( VIA* via = GetFirstVia( this ); via; via = GetFirstVia( via->Next() ) )
 
1268
    {
 
1269
        if( via->HitTest( aPosition ) &&
 
1270
                !via->GetState( BUSY | IS_DELETED ) &&
 
1271
                ((aLayer == UNDEFINED_LAYER) || (via->IsOnLayer( aLayer ))) )
 
1272
            return via;
 
1273
    }
 
1274
 
 
1275
    return NULL;
 
1276
}
 
1277
 
 
1278
 
 
1279
VIA* TRACK::GetVia( TRACK* aEndTrace, const wxPoint& aPosition, LSET aLayerMask )
 
1280
{
 
1281
    for( VIA* via = GetFirstVia( this, aEndTrace ); via; via = GetFirstVia( via->Next() ) )
 
1282
    {
 
1283
        if( via->HitTest( aPosition ) &&
 
1284
            !via->GetState( BUSY | IS_DELETED ) &&
 
1285
            ( aLayerMask & via->GetLayerSet() ).any()
 
1286
            )
1279
1287
        {
1280
 
            if( aPosition == trace->m_Start )
1281
 
            {
1282
 
                if( trace->GetState( BUSY | IS_DELETED ) == 0 )
1283
 
                {
1284
 
                    if( aLayerMask & trace->GetLayerMask() )
1285
 
                        return trace;
1286
 
                }
1287
 
            }
 
1288
            return via;
1288
1289
        }
1289
 
 
1290
 
        if( trace == aEndTrace )
1291
 
            break;
1292
1290
    }
1293
1291
 
1294
1292
    return NULL;
1295
1293
}
1296
1294
 
1297
1295
 
1298
 
TRACK* TRACK::GetTrace( TRACK* aStartTrace, TRACK* aEndTrace, int aEndPoint )
 
1296
TRACK* TRACK::GetTrack( TRACK* aStartTrace, TRACK* aEndTrace, ENDPOINT_T aEndPoint,
 
1297
        bool aSameNetOnly, bool aSequential )
1299
1298
{
1300
 
    const int NEIGHTBOUR_COUNT_MAX = 50;
1301
 
 
 
1299
    const   wxPoint& position = GetEndPoint( aEndPoint );
 
1300
    LSET    refLayers = GetLayerSet();
1302
1301
    TRACK*  previousSegment;
1303
1302
    TRACK*  nextSegment;
1304
 
    int     Reflayer;
1305
 
    wxPoint position;
1306
 
    int     ii;
1307
 
    int     max_dist;
1308
1303
 
1309
 
    if( aEndPoint == FLG_START )
1310
 
        position = m_Start;
 
1304
    if( aSequential )
 
1305
    {
 
1306
        // Simple sequential search: from aStartTrace forward to aEndTrace
 
1307
        previousSegment = NULL;
 
1308
        nextSegment = aStartTrace;
 
1309
    }
1311
1310
    else
1312
 
        position = m_End;
1313
 
 
1314
 
    Reflayer = GetLayerMask();
1315
 
 
1316
 
    previousSegment = nextSegment = this;
1317
 
 
1318
 
    // Local search:
1319
 
    for( ii = 0; ii < NEIGHTBOUR_COUNT_MAX; ii++ )
1320
 
    {
1321
 
        if( (nextSegment == NULL) && (previousSegment == NULL) )
1322
 
            break;
 
1311
    {
 
1312
        /* Local bidirectional search: from this backward to aStartTrace
 
1313
         * AND forward to aEndTrace. The idea is that nearest segments
 
1314
         * are found (on average) faster in this way. In fact same-net
 
1315
         * segments are almost guaranteed to be found faster, in a global
 
1316
         * search, since they are grouped together in the track list */
 
1317
        previousSegment = this;
 
1318
        nextSegment = this;
 
1319
    }
 
1320
 
 
1321
    while( nextSegment || previousSegment )
 
1322
    {
 
1323
        // Terminate the search in the direction if the netcode mismatches
 
1324
        if( aSameNetOnly )
 
1325
        {
 
1326
            if( nextSegment && (nextSegment->GetNetCode() != GetNetCode()) )
 
1327
                nextSegment = NULL;
 
1328
            if( previousSegment && (previousSegment->GetNetCode() != GetNetCode()) )
 
1329
                previousSegment = NULL;
 
1330
        }
1323
1331
 
1324
1332
        if( nextSegment )
1325
1333
        {
1326
 
            if( nextSegment->GetState( BUSY | IS_DELETED ) )
1327
 
                goto suite;
1328
 
 
1329
 
            if( nextSegment == this )
1330
 
                goto suite;
1331
 
 
1332
 
            /* max_dist is the max distance between 2 track ends which
1333
 
             * ensure a copper continuity */
1334
 
            max_dist = ( nextSegment->m_Width + this->m_Width ) / 2;
1335
 
 
1336
 
            if( IsNear( position, nextSegment->m_Start, max_dist ) )
1337
 
            {
1338
 
                if( Reflayer & nextSegment->GetLayerMask() )
1339
 
                    return nextSegment;
1340
 
            }
1341
 
 
1342
 
            if( IsNear( position, nextSegment->m_End, max_dist ) )
1343
 
            {
1344
 
                if( Reflayer & nextSegment->GetLayerMask() )
1345
 
                    return nextSegment;
1346
 
            }
1347
 
suite:
 
1334
            if ( (nextSegment != this) &&
 
1335
                 !nextSegment->GetState( BUSY | IS_DELETED ) &&
 
1336
                 ( refLayers & nextSegment->GetLayerSet() ).any() )
 
1337
            {
 
1338
                if( (position == nextSegment->m_Start) ||
 
1339
                    (position == nextSegment->m_End) )
 
1340
                    return nextSegment;
 
1341
            }
 
1342
 
 
1343
            // Keep looking forward
1348
1344
            if( nextSegment == aEndTrace )
1349
1345
                nextSegment = NULL;
1350
1346
            else
1351
 
                nextSegment =  nextSegment->Next();
 
1347
                nextSegment = nextSegment->Next();
1352
1348
        }
1353
1349
 
 
1350
        // Same as above, looking back. During sequential search this branch is inactive
1354
1351
        if( previousSegment )
1355
1352
        {
1356
 
            if( previousSegment->GetState( BUSY | IS_DELETED ) )
1357
 
                goto suite1;
1358
 
 
1359
 
            if( previousSegment == this )
1360
 
                goto suite1;
1361
 
 
1362
 
            max_dist = ( previousSegment->m_Width + m_Width ) / 2;
1363
 
 
1364
 
            if( IsNear( position, previousSegment->m_Start, max_dist ) )
1365
 
            {
1366
 
                if( Reflayer & previousSegment->GetLayerMask() )
1367
 
                    return previousSegment;
1368
 
            }
1369
 
 
1370
 
            if( IsNear( position, previousSegment->m_End, max_dist ) )
1371
 
            {
1372
 
                if( Reflayer & previousSegment->GetLayerMask() )
1373
 
                    return previousSegment;
1374
 
            }
1375
 
suite1:
 
1353
            if( (previousSegment != this) &&
 
1354
                !previousSegment->GetState( BUSY | IS_DELETED ) &&
 
1355
                ( refLayers & previousSegment->GetLayerSet() ).any()
 
1356
                )
 
1357
            {
 
1358
                if( (position == previousSegment->m_Start) ||
 
1359
                    (position == previousSegment->m_End) )
 
1360
                    return previousSegment;
 
1361
            }
 
1362
 
1376
1363
            if( previousSegment == aStartTrace )
1377
1364
                previousSegment = NULL;
1378
 
            else if( previousSegment->Type() != PCB_T )
1379
 
                previousSegment =  previousSegment->Back();
1380
1365
            else
1381
 
                previousSegment = NULL;
1382
 
        }
1383
 
    }
1384
 
 
1385
 
    // General search
1386
 
    for( nextSegment = aStartTrace; nextSegment != NULL; nextSegment =  nextSegment->Next() )
1387
 
    {
1388
 
        if( nextSegment->GetState( IS_DELETED | BUSY ) )
1389
 
        {
1390
 
            if( nextSegment == aEndTrace )
1391
 
                break;
1392
 
 
1393
 
            continue;
1394
 
        }
1395
 
 
1396
 
        if( nextSegment == this )
1397
 
        {
1398
 
            if( nextSegment == aEndTrace )
1399
 
                break;
1400
 
 
1401
 
            continue;
1402
 
        }
1403
 
 
1404
 
        max_dist = ( nextSegment->m_Width + m_Width ) / 2;
1405
 
 
1406
 
        if( IsNear( position, nextSegment->m_Start, max_dist ) )
1407
 
        {
1408
 
            if( Reflayer & nextSegment->GetLayerMask() )
1409
 
                return nextSegment;
1410
 
        }
1411
 
 
1412
 
        if( IsNear( position, nextSegment->m_End, max_dist ) )
1413
 
        {
1414
 
            if( Reflayer & nextSegment->GetLayerMask() )
1415
 
                return nextSegment;
1416
 
        }
1417
 
 
1418
 
        if( nextSegment == aEndTrace )
1419
 
            break;
 
1366
                previousSegment = previousSegment->Back();
 
1367
        }
1420
1368
    }
1421
1369
 
1422
1370
    return NULL;
1427
1375
{
1428
1376
    TRACK* Track, * via, * segm, * TrackListEnd;
1429
1377
    int      NbEnds, ii, ok = 0;
1430
 
    LAYER_MSK layerMask;
 
1378
    LSET layerMask;
1431
1379
 
1432
1380
    if( aCount <= 1 )
1433
1381
    {
1435
1383
        return 1;
1436
1384
    }
1437
1385
 
1438
 
    /* Calculation of the limit analysis. */
 
1386
    // Calculation of the limit analysis.
1439
1387
    *aStartTrace = *aEndTrace = NULL;
1440
1388
    TrackListEnd = Track = this;
1441
1389
    ii = 0;
1446
1394
        Track->m_Param = 0;
1447
1395
    }
1448
1396
 
1449
 
    /* Calculate the extremes. */
 
1397
    // Calculate the extremes.
1450
1398
    NbEnds = 0;
1451
1399
    Track = this;
1452
1400
    ii = 0;
1456
1404
        if( Track->Type() == PCB_VIA_T )
1457
1405
            continue;
1458
1406
 
1459
 
        layerMask = Track->GetLayerMask();
 
1407
        layerMask = Track->GetLayerSet();
1460
1408
        via = GetVia( TrackListEnd, Track->m_Start, layerMask );
1461
1409
 
1462
1410
        if( via )
1463
1411
        {
1464
 
            layerMask |= via->GetLayerMask();
 
1412
            layerMask |= via->GetLayerSet();
1465
1413
            via->SetState( BUSY, true );
1466
1414
        }
1467
1415
 
1468
1416
        Track->SetState( BUSY, true );
1469
 
        segm = ::GetTrace( this, TrackListEnd, Track->m_Start, layerMask );
 
1417
        segm = ::GetTrack( this, TrackListEnd, Track->m_Start, layerMask );
1470
1418
        Track->SetState( BUSY, false );
1471
1419
 
1472
1420
        if( via )
1484
1432
                int BeginPad, EndPad;
1485
1433
                *aEndTrace = Track;
1486
1434
 
1487
 
                /* Swap ox, oy with fx, fy */
 
1435
                // Swap ox, oy with fx, fy
1488
1436
                BeginPad = Track->GetState( BEGIN_ONPAD );
1489
1437
                EndPad   = Track->GetState( END_ONPAD );
1490
1438
 
1503
1451
            }
1504
1452
        }
1505
1453
 
1506
 
        layerMask = Track->GetLayerMask();
 
1454
        layerMask = Track->GetLayerSet();
1507
1455
        via = GetVia( TrackListEnd, Track->m_End, layerMask );
1508
1456
 
1509
1457
        if( via )
1510
1458
        {
1511
 
            layerMask |= via->GetLayerMask();
 
1459
            layerMask |= via->GetLayerSet();
1512
1460
            via->SetState( BUSY, true );
1513
1461
        }
1514
1462
 
1515
1463
        Track->SetState( BUSY, true );
1516
 
        segm = ::GetTrace( this, TrackListEnd, Track->m_End, layerMask );
 
1464
        segm = ::GetTrack( this, TrackListEnd, Track->m_End, layerMask );
1517
1465
        Track->SetState( BUSY, false );
1518
1466
 
1519
1467
        if( via )
1528
1476
                *aStartTrace = Track;
1529
1477
                NbEnds++;
1530
1478
 
1531
 
                /* Swap ox, oy with fx, fy */
 
1479
                // Swap ox, oy with fx, fy
1532
1480
                BeginPad = Track->GetState( BEGIN_ONPAD );
1533
1481
                EndPad   = Track->GetState( END_ONPAD );
1534
1482