/*********************************************/ /* Edition des pistes: Routines d'effacement */ /* Effacement de segment, piste, net et zone */ /*********************************************/ #include "fctsys.h" #include "common.h" #include "pcbnew.h" #include "protos.h" class TSTSEGM /* memorisation des segments marques */ { public: TSTSEGM* Pnext, * Pback; TRACK* RefTrack; public: TSTSEGM( TRACK * Father ) { Pback = Pnext = NULL; RefTrack = Father; } }; /* Routines externes : */ void Montre_Position_New_Piste( int flag );/* defini dans editrack.cc */ /* Routines Locales */ static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masklayer ); /* Variables locales */ TSTSEGM* ListSegm = NULL; /****************************************************************************/ TRACK* Marque_Une_Piste( WinEDA_BasePcbFrame* frame, wxDC* DC, TRACK* pt_segm, int* nb_segm, int flagcolor ) /****************************************************************************/ /* Routine de Marquage de 1 piste, a partir du segment pointe par pt_segm. * 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 */ { int NbSegmBusy, masque_layer; TRACK* Track, * FirstTrack, * NextTrack; TSTSEGM* Segm, * NextSegm; *nb_segm = 0; if( pt_segm == NULL ) return NULL; /* Marquage du segment pointe */ if( flagcolor ) pt_segm->Draw( frame->DrawPanel, DC, flagcolor ); pt_segm->SetState( BUSY, ON ); masque_layer = pt_segm->ReturnMaskLayer(); ListSegm = new TSTSEGM( pt_segm ); /* 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 */ if( pt_segm->m_StructType == TYPEVIA ) { TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL; Segm1 = Fast_Locate_Piste( frame->m_Pcb->m_Track, NULL, pt_segm->m_Start, masque_layer ); if( Segm1 ) { Segm2 = Fast_Locate_Piste( (TRACK*) Segm1->Pnext, NULL, pt_segm->m_Start, masque_layer ); } if( Segm2 ) { Segm3 = Fast_Locate_Piste( (TRACK*) Segm2->Pnext, NULL, pt_segm->m_Start, masque_layer ); } if( Segm3 ) { *nb_segm = 1; return pt_segm; } if( Segm1 ) { masque_layer = Segm1->ReturnMaskLayer(); Marque_Chaine_segments( frame->m_Pcb, pt_segm->m_Start, masque_layer ); } if( Segm2 ) { masque_layer = Segm2->ReturnMaskLayer(); Marque_Chaine_segments( frame->m_Pcb, pt_segm->m_Start, masque_layer ); } } else /* Marquage de la chaine connectee aux extremites du segment */ { Marque_Chaine_segments( frame->m_Pcb, pt_segm->m_Start, masque_layer ); Marque_Chaine_segments( frame->m_Pcb, pt_segm->m_End, masque_layer ); } /* marquage des vias (vias non connectees ou inutiles */ for( Segm = ListSegm; Segm != NULL; Segm = Segm->Pnext ) { int layer; if( Segm->RefTrack->m_StructType != TYPEVIA ) continue; if( Segm->RefTrack == pt_segm ) continue; Segm->RefTrack->SetState( BUSY, ON ); masque_layer = Segm->RefTrack->ReturnMaskLayer(); Track = Fast_Locate_Piste( frame->m_Pcb->m_Track, NULL, Segm->RefTrack->m_Start, masque_layer ); if( Track == NULL ) continue; /* Test des connexions: si via utile: suppression marquage */ layer = Track->GetLayer(); while( ( Track = Fast_Locate_Piste( (TRACK*) Track->Pnext, NULL, Segm->RefTrack->m_Start, masque_layer ) ) != NULL ) { if( layer != Track->GetLayer() ) { Segm->RefTrack->SetState( BUSY, OFF ); break; } } } /* liberation memoire */ for( Segm = ListSegm; Segm != NULL; Segm = NextSegm ) { NextSegm = Segm->Pnext; delete Segm; } ListSegm = NULL; /* Reclassement des segments marques en une chaine */ FirstTrack = frame->m_Pcb->m_Track; NbSegmBusy = 0; for( ; FirstTrack != NULL; FirstTrack = (TRACK*) FirstTrack->Pnext ) { /* recherche du debut de la liste des segments marques a BUSY */ if( FirstTrack->GetState( BUSY ) ) { NbSegmBusy = 1; break; } } /* Reclassement de la chaine debutant a FirstTrack et finissant * au dernier segment marque. FirstTrack n'est pas modifie */ Track = (TRACK*) FirstTrack->Pnext; for( ; Track != NULL; Track = NextTrack ) { NextTrack = (TRACK*) Track->Pnext; if( Track->GetState( BUSY ) ) { NbSegmBusy++; Track->UnLink(); Track->Insert( frame->m_Pcb, FirstTrack ); } } *nb_segm = NbSegmBusy; if( flagcolor ) Trace_Une_Piste( frame->DrawPanel, DC, FirstTrack, NbSegmBusy, flagcolor ); return FirstTrack; } /********************************************************************************/ static void Marque_Chaine_segments( BOARD* Pcb, wxPoint ref_pos, int masque_layer ) /********************************************************************************/ /* * routine utilisee par Supprime_1_Piste() * Positionne le bit BUSY dans la chaine de segments commencant * au point ox, oy sur la couche layer * * Les vias sont mises en liste des segments traites mais ne sont pas * marquees. */ { 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; TSTSEGM* Segm; 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; masque_layer = pt_via->ReturnMaskLayer(); Segm = new TSTSEGM( pt_via ); Segm->Pnext = ListSegm; ListSegm->Pback = Segm; ListSegm = Segm; } /* 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 ) ) { pt_segm = (TRACK*) pt_segm->Pnext; continue; } if( pt_segm == pt_via ) /* deja traite */ { pt_segm = (TRACK*) pt_segm->Pnext; continue; } NbSegm++; if( NbSegm == 1 ) /* 1ere detection de segment de piste */ { MarqSegm = pt_segm; pt_segm = (TRACK*) pt_segm->Pnext; } else /* 2eme detection de segment -> fin de piste */ { return; } } if( MarqSegm ) { /* preparation de la nouvelle recherche */ masque_layer = MarqSegm->ReturnMaskLayer(); 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 */ Segm = new TSTSEGM( MarqSegm ); Segm->Pnext = ListSegm; ListSegm->Pback = Segm; ListSegm = Segm; MarqSegm->SetState( BUSY, ON ); } else return; } } /********************************************************/ int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack ) /**********************************************************/ /* Calcule les coordonnes des extremites d'une piste * 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 */ { 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; for( ; (Track != NULL) && (ii < NbSegm); ii++, Track = (TRACK*) Track->Pnext ) { TrackListEnd = Track; Track->m_Param = 0; } /* Calcul des extremites */ NbEnds = 0; Track = RefTrack; ii = 0; for( ; (Track != NULL) && (ii < NbSegm); ii++, Track = (TRACK*) Track->Pnext ) { if( Track->m_StructType == TYPEVIA ) 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; /* permutation de ox,oy avec fx,fy */ BeginPad = Track->GetState( BEGIN_ONPAD ); EndPad = Track->GetState( END_ONPAD ); Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); if( BeginPad ) Track->SetState( END_ONPAD, ON ); if( EndPad ) Track->SetState( BEGIN_ONPAD, ON ); EXCHG( Track->m_Start, Track->m_End ); EXCHG( Track->start, Track->end ); ok = 1; return ok; } } 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; *StartTrack = Track; NbEnds++; /* permutation de ox,oy avec fx,fy */ BeginPad = Track->GetState( BEGIN_ONPAD ); EndPad = Track->GetState( END_ONPAD ); Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF ); if( BeginPad ) Track->SetState( END_ONPAD, ON ); if( EndPad ) Track->SetState( BEGIN_ONPAD, ON ); EXCHG( Track->m_Start, Track->m_End ); EXCHG( Track->start, Track->end ); break; case 1: *EndTrack = Track; ok = 1; return ok; } } } return ok; } /***************************************************************************/ void ListSetState( EDA_BaseStruct* Start, int NbItem, int State, int onoff ) /***************************************************************************/ /* Met a jour le membre .state d'une chaine de structures */ { if( Start == NULL ) return; for( ; (Start != NULL) && (NbItem > 0); NbItem--, Start = Start->Pnext ) { Start->SetState( State, onoff ); } }