2007-06-05 12:10:51 +00:00
|
|
|
/*********************************************/
|
|
|
|
/* 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->m_Layer;
|
|
|
|
while ( (Track = Fast_Locate_Piste((TRACK*)Track->Pnext,NULL,
|
|
|
|
Segm->RefTrack->m_Start,
|
|
|
|
masque_layer)) != NULL )
|
|
|
|
{
|
|
|
|
if( layer != Track->m_Layer )
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|