track.cpp 13.2 KB
Newer Older
1 2 3 4
/*********************************************/
/* Edition des pistes: Routines d'effacement */
/* Effacement de segment, piste, net et zone */
/*********************************************/
5 6 7 8 9 10 11 12

#include "fctsys.h"

#include "common.h"
#include "pcbnew.h"

#include "protos.h"

13 14 15

typedef std::vector<TRACK*> TRACK_PTRS;

16 17

/* Routines externes : */
18
void        Montre_Position_New_Piste( int flag );/* defini dans editrack.cc */
19 20 21


/* Routines Locales */
22
static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masklayer, TRACK_PTRS* aList );
23 24 25

/* Variables locales */

26

27
/* Routine de Marquage de 1 piste, a partir du segment pointe par pt_segm.
28 29 30 31 32 33 34 35
 *  le segment pointe est marque puis les segments connectes
 *  jusqu'a un pad ou un point de jonction de plus de 2 segments
 *  le marquage est la mise a 1 du bit BUSY
 *  Les segments sont ensuite reclasses pour etre contigus en liste chainee
 *  Retourne:
 *      adresse du 1er segment de la chaine creee
 *      nombre de segments
 */
36 37 38 39 40 41 42 43 44 45 46 47 48

/**
 * Function Marque_Une_Piste
 * marks a chain of track segments, starting at aTrackList.
 * Each segment is marked by setting the BUSY bit into m_Flags.  Electrical continuity
 * is detected by walking each segment, and finally the segments are rearranged
 * into a contiguous chain within the given list.
 * @param aTrackList The first interesting segment within a list of many
 *  interesting and uninteresting segments.
 * @return TRACK* the first in the chain of interesting segments.
 */
TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC,
                         TRACK* aTrackList, int* nb_segm, int flagcolor )
49
{
50 51 52
    int         NbSegmBusy;

    TRACK_PTRS  trackList;
53 54

    *nb_segm = 0;
55
    if( aTrackList == NULL )
56 57 58 59
        return NULL;

    /* Marquage du segment pointe */
    if( flagcolor )
60
        aTrackList->Draw( frame->DrawPanel, DC, flagcolor );
61

62 63 64 65
    aTrackList->SetState( BUSY, ON );
    int masque_layer = aTrackList->ReturnMaskLayer();

    trackList.push_back( aTrackList );
66 67 68 69 70

    /* Traitement du segment pointe : si c'est un segment, le cas est simple.
     *  Si c'est une via, on doit examiner le nombre de segments connectes.
     *  Si <=2, on doit detecter une piste, si > 2 seule la via est marquee
     */
71
    if( aTrackList->Type() == TYPE_VIA )
72 73
    {
        TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
74
        Segm1 = Fast_Locate_Piste( frame->GetBoard()->m_Track, NULL,
75
                                   aTrackList->m_Start, masque_layer );
76 77
        if( Segm1 )
        {
78
            Segm2 = Fast_Locate_Piste( Segm1->Next(), NULL,
79
                                      aTrackList->m_Start, masque_layer );
80 81 82
        }
        if( Segm2 )
        {
83
            Segm3 = Fast_Locate_Piste( Segm2->Next(), NULL,
84
                                      aTrackList->m_Start, masque_layer );
85 86 87
        }
        if( Segm3 )
        {
88 89
            *nb_segm = 1;
            return aTrackList;
90 91 92 93
        }
        if( Segm1 )
        {
            masque_layer = Segm1->ReturnMaskLayer();
94
            Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList );
95 96 97 98
        }
        if( Segm2 )
        {
            masque_layer = Segm2->ReturnMaskLayer();
99
            Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList );
100 101
        }
    }
102 103

    else    // mark the chain using both ends of the initial segment
104
    {
105 106
        Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_Start, masque_layer, &trackList );
        Marque_Chaine_segments( frame->GetBoard(), aTrackList->m_End, masque_layer, &trackList );
107 108
    }

109 110 111
    //  marquage des vias (vias non connectees ou inutiles
    // go through the list backwards.
    for( int i = trackList.size()-1;  i>=0;  --i )
112
    {
113 114 115
        TRACK*  via = trackList[i];

        if( via->Type() != TYPE_VIA )
116
            continue;
117

118
        if( via == aTrackList )
119
            continue;
120

121
        via->SetState( BUSY, ON );
122

123
        masque_layer = via->ReturnMaskLayer();
124

125
        TRACK* track = Fast_Locate_Piste( frame->GetBoard()->m_Track,
126 127
                                         NULL, via->m_Start, masque_layer );
        if( track == NULL )
128
            continue;
129

130
        /* Test des connexions: si via utile: suppression marquage */
131
        int layer = track->GetLayer();
132

133 134
        while( ( track = Fast_Locate_Piste( track->Next(), NULL,
                         via->m_Start, masque_layer ) ) != NULL )
135
        {
136
            if( layer != track->GetLayer() )
137
            {
138
                via->SetState( BUSY, OFF );
139 140 141 142 143 144
                break;
            }
        }
    }

    /* Reclassement des segments marques en une chaine */
145 146
    NbSegmBusy = 0;
    TRACK* firstTrack;
147
    for( firstTrack = frame->GetBoard()->m_Track;  firstTrack;  firstTrack = firstTrack->Next() )
148
    {
149 150
        // recherche du debut de la liste des segments marques a BUSY
        if( firstTrack->GetState( BUSY ) )
151
        {
152 153
            NbSegmBusy = 1;
            break;
154 155 156
        }
    }

157 158 159
    wxASSERT( firstTrack );

    if( firstTrack )
160
    {
161 162 163 164 165 166 167 168
        DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
        wxASSERT(list);

        /* Reclassement de la chaine debutant a FirstTrack et finissant
         * au dernier segment marque. FirstTrack n'est pas modifie
         */
        TRACK* next;
        for( TRACK* track = firstTrack->Next(); track; track = next )
169
        {
170 171 172 173 174 175 176 177 178
            next = track->Next();
            if( track->GetState( BUSY ) )
            {
                NbSegmBusy++;

                track->UnLink();

                list->Insert( track, firstTrack->Next() );
            }
179 180 181 182 183 184
        }
    }

    *nb_segm = NbSegmBusy;

    if( flagcolor )
185
        Trace_Une_Piste( frame->DrawPanel, DC, firstTrack, NbSegmBusy, flagcolor );
186

187
    return firstTrack;
188 189 190 191
}


/********************************************************************************/
192
static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masque_layer, TRACK_PTRS* aList )
193 194
/********************************************************************************/

195 196 197 198
/*
 *  routine utilisee par Supprime_1_Piste()
 *  Positionne le bit BUSY dans la chaine de segments commencant
 *  au point ox, oy sur la couche layer
199
 *
200 201 202
 *  Les vias sont mises en liste des segments traites mais ne sont pas
 *  marquees.
 */
203
{
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    TRACK*   pt_segm,   // Pointe le segment courant analyse
    * pt_via,           // pointe la via reperee, eventuellement a detruire
    * MarqSegm;         // pointe le segment a detruire (= NULL ou pt_segm
    int      NbSegm;

    if( Pcb->m_Track == NULL )
        return;

    /* Marquage de la chaine */
    for( ; ; )
    {
        if( Fast_Locate_Pad_Connecte( Pcb, ref_pos, masque_layer ) != NULL )
            return;

        /* Localisation d'une via (car elle connecte plusieurs segments) */
        pt_via = Fast_Locate_Via( Pcb->m_Track, NULL, ref_pos, masque_layer );
        if( pt_via )
        {
            if( pt_via->GetState( EDIT ) )
                return;
224

225 226
            masque_layer = pt_via->ReturnMaskLayer();

227
            aList->push_back( pt_via );
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
        }

        /* Recherche des segments connectes au point ref_pos
         *  si 1 segment: peut etre marque
         *  si > 1 segment:
         *      le segment ne peut etre marque
         */
        pt_segm = Pcb->m_Track; MarqSegm = NULL;
        NbSegm  = 0;
        while( ( pt_segm = Fast_Locate_Piste( pt_segm, NULL,
                                              ref_pos, masque_layer ) ) != NULL )
        {
            if( pt_segm->GetState( EDIT ) ) /* Fin de piste */
                return;

            if( pt_segm->GetState( BUSY ) )
            {
245
                pt_segm = pt_segm->Next();
246 247 248 249 250
                continue;
            }

            if( pt_segm == pt_via )  /* deja traite */
            {
251
                pt_segm = pt_segm->Next();
252 253 254 255 256 257 258
                continue;
            }

            NbSegm++;
            if( NbSegm == 1 ) /* 1ere detection de segment de piste */
            {
                MarqSegm = pt_segm;
259
                pt_segm  = pt_segm->Next();
260 261 262 263 264 265 266 267 268 269 270
            }
            else /* 2eme detection de segment -> fin de piste */
            {
                return;
            }
        }

        if( MarqSegm )
        {
            /* preparation de la nouvelle recherche */
            masque_layer = MarqSegm->ReturnMaskLayer();
271

272 273 274 275 276 277 278 279 280 281 282 283
            if( ref_pos == MarqSegm->m_Start )
            {
                ref_pos = MarqSegm->m_End;
            }
            else
            {
                ref_pos = MarqSegm->m_Start;
            }

            pt_segm = Pcb->m_Track; /* reinit recherche des segments */

            /* Marquage et mise en liste du segment */
284
            aList->push_back( MarqSegm );
285 286 287 288 289
            MarqSegm->SetState( BUSY, ON );
        }
        else
            return;
    }
290 291 292
}


293 294 295
/********************************************************/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm,
                     TRACK** StartTrack, TRACK** EndTrack )
296
/**********************************************************/
297

298
/* Calcule les coordonnes des extremites d'une piste
299 300 301 302 303 304
 *  retourne 1 si OK, 0 si piste bouclee
 *  Retourne dans *StartTrack en *EndTrack les segments de debut et fin
 *  Les coord StartTrack->m_Start.x, m_Start.y contiennent le debut de la piste
 *  Les coord EndTrack->m_End.x, m_End.y contiennent le debut de la piste
 *  Les segments sont supposes chaines de facon consecutive
 */
305
{
306 307 308 309 310 311 312 313 314 315 316 317
    TRACK* Track, * via, * segm, * TrackListEnd;
    int    NbEnds, masque_layer, ii, ok = 0;

    if( NbSegm <= 1 )
    {
        *StartTrack = *EndTrack = RefTrack;
        return 1;   /* cas trivial */
    }

    /* calcul de la limite d'analyse */
    *StartTrack  = *EndTrack = NULL;
    TrackListEnd = Track = RefTrack; ii = 0;
318
    for( ; (Track != NULL) && (ii < NbSegm); ii++, Track = Track->Next() )
319 320 321 322 323 324 325
    {
        TrackListEnd   = Track;
        Track->m_Param = 0;
    }

    /* Calcul des extremites */
    NbEnds = 0; Track = RefTrack; ii = 0;
326
    for( ; (Track != NULL) && (ii < NbSegm); ii++, Track = Track->Next() )
327
    {
328
        if( Track->Type() == TYPE_VIA )
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
            continue;

        masque_layer = Track->ReturnMaskLayer();
        via = Fast_Locate_Via( RefTrack, TrackListEnd,
                               Track->m_Start, masque_layer );
        if( via )
        {
            masque_layer |= via->ReturnMaskLayer();
            via->SetState( BUSY, ON );
        }

        Track->SetState( BUSY, ON );
        segm = Fast_Locate_Piste( RefTrack, TrackListEnd,
                                  Track->m_Start, masque_layer );
        Track->SetState( BUSY, OFF );
        if( via )
            via->SetState( BUSY, OFF );

        if( segm == NULL )
        {
            switch( NbEnds )
            {
            case 0:
                *StartTrack = Track; NbEnds++;
                break;

            case 1:
                int BeginPad, EndPad;
                *EndTrack = Track;
358

359 360 361
                /* permutation de ox,oy avec fx,fy */
                BeginPad = Track->GetState( BEGIN_ONPAD );
                EndPad   = Track->GetState( END_ONPAD );
362

363
                Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
364

365 366 367 368
                if( BeginPad )
                    Track->SetState( END_ONPAD, ON );
                if( EndPad )
                    Track->SetState( BEGIN_ONPAD, ON );
369

370 371
                EXCHG( Track->m_Start, Track->m_End );
                EXCHG( Track->start, Track->end );
372 373
                ok = 1;
                return ok;
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
            }
        }

        masque_layer = Track->ReturnMaskLayer();
        via = Fast_Locate_Via( RefTrack, TrackListEnd,
                               Track->m_End, masque_layer );
        if( via )
        {
            masque_layer |= via->ReturnMaskLayer();
            via->SetState( BUSY, ON );
        }

        Track->SetState( BUSY, ON );
        segm = Fast_Locate_Piste( RefTrack, TrackListEnd,
                                  Track->m_End, masque_layer );
        Track->SetState( BUSY, OFF );
        if( via )
            via->SetState( BUSY, OFF );
        if( segm == NULL )
        {
            switch( NbEnds )
            {
            case 0:
                int BeginPad, EndPad;
398 399 400
                *StartTrack = Track;
                NbEnds++;

401 402 403
                /* permutation de ox,oy avec fx,fy */
                BeginPad = Track->GetState( BEGIN_ONPAD );
                EndPad   = Track->GetState( END_ONPAD );
404

405
                Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
406

407 408 409 410
                if( BeginPad )
                    Track->SetState( END_ONPAD, ON );
                if( EndPad )
                    Track->SetState( BEGIN_ONPAD, ON );
411

412 413 414 415 416 417
                EXCHG( Track->m_Start, Track->m_End );
                EXCHG( Track->start, Track->end );
                break;

            case 1:
                *EndTrack = Track;
418 419
                ok = 1;
                return ok;
420 421 422 423 424
            }
        }
    }

    return ok;
425 426 427 428
}


/***************************************************************************/
429
void ListSetState( EDA_BaseStruct* Start, int NbItem, int State, int onoff )
430
/***************************************************************************/
431

432
/* Met a jour le membre .state d'une chaine de structures
433
 */
434
{
435 436
    if( Start == NULL )
        return;
437

438
    for( ; (Start != NULL) && (NbItem > 0); NbItem--, Start = Start->Next() )
439 440 441
    {
        Start->SetState( State, onoff );
    }
442
}