kicad/pcbnew/clean.cpp

1042 lines
34 KiB
C++
Raw Normal View History

2007-08-10 19:14:51 +00:00
/******************************************************/
/* editeur de PCB PCBNEW */
/* Fonctions de Nettoyage et reorganisation de Pistes */
/******************************************************/
2007-05-06 16:03:28 +00:00
2007-08-10 19:14:51 +00:00
/* Fichier CLEAN.CPP */
2007-05-06 16:03:28 +00:00
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
#include "autorout.h"
#include "protos.h"
/* Constantes de controle de l'affichage des messages */
2007-08-10 19:14:51 +00:00
#define AFFICHE 1
#define POS_AFF_PASSE 40
#define POS_AFF_VAR 50
#define POS_AFF_MAX 60
2007-05-06 16:03:28 +00:00
#define POS_AFF_NUMSEGM 70
/* Routines locales : */
2007-08-10 19:14:51 +00:00
static int clean_segments( WinEDA_PcbFrame* frame, wxDC* DC );
static void suppression_piste_non_connectee( WinEDA_PcbFrame* frame, wxDC* DC );
static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extremite );
static void Clean_Pcb_Items( WinEDA_PcbFrame* frame, wxDC* DC );
2007-05-06 16:03:28 +00:00
/* Variables locales : */
2007-08-10 19:14:51 +00:00
static bool a_color; /* couleur du message */
static bool s_CleanVias = true;
static bool s_MergeSegments = true;
static bool s_DeleteUnconnectedSegm = true;
static bool s_ConnectToPads = false;
2007-05-06 16:03:28 +00:00
#include "cleaningoptions_dialog.cpp"
#define CONN2PAD_ENBL
#ifdef CONN2PAD_ENBL
2007-08-10 19:14:51 +00:00
static void ConnectDanglingEndToPad( WinEDA_PcbFrame* frame, wxDC* DC );
static void Gen_Raccord_Track( WinEDA_PcbFrame* frame, wxDC* DC );
#endif
2007-05-06 16:03:28 +00:00
/*****************************************/
2007-08-10 19:14:51 +00:00
void WinEDA_PcbFrame::Clean_Pcb( wxDC* DC )
2007-05-06 16:03:28 +00:00
/*****************************************/
2007-08-10 19:14:51 +00:00
2007-05-06 16:03:28 +00:00
/* Regroupement des segments de meme piste.
2007-08-10 19:14:51 +00:00
* Suppression des points inutiles
* - via sur pad
* - points de couche et coord identiques
* - points alignes (supp du pt milieu)
*/
2007-05-06 16:03:28 +00:00
{
2007-08-10 19:14:51 +00:00
s_ConnectToPads = false;
WinEDA_CleaningOptionsFrame* frame = new WinEDA_CleaningOptionsFrame( this, DC );
2007-10-15 03:26:38 +00:00
frame->ShowModal();
frame->Destroy();
2007-08-10 19:14:51 +00:00
DrawPanel->Refresh( true );
}
2007-08-10 19:14:51 +00:00
/************************************************************/
2007-08-10 19:14:51 +00:00
void Clean_Pcb_Items( WinEDA_PcbFrame* frame, wxDC* DC )
/************************************************************/
{
2007-08-10 19:14:51 +00:00
frame->MsgPanel->EraseMsgBox();
frame->m_Pcb->GetNumSegmTrack(); /* Met a jour le compte */
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
/* construction de la liste des coordonn<6E>s des pastilles */
frame->m_Pcb->m_Status_Pcb = 0;
frame->build_liste_pads();
frame->recalcule_pad_net_code();
2007-10-15 03:26:38 +00:00
if( s_CleanVias ) /* delete redundant vias */
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* track;
TRACK* next_track;
2007-08-10 19:14:51 +00:00
for( track = frame->m_Pcb->m_Track; track != NULL; track = track->Next() )
{
2007-10-19 06:31:17 +00:00
if( track->m_Shape != THROUGH_VIA )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
/* Search and delete others vias at same location */
TRACK* alt_track = track->Next();
for( ; alt_track != NULL; alt_track = next_track )
{
next_track = alt_track->Next();
2007-10-19 06:31:17 +00:00
if( alt_track->m_Shape != THROUGH_VIA )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
if( alt_track->m_Start != track->m_Start )
continue;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
/* delete via */
alt_track->UnLink();
delete alt_track;
}
}
/* Delete Via on pads at same location */
for( track = frame->m_Pcb->m_Track; track != NULL; track = next_track )
{
next_track = track->Next();
2007-10-19 06:31:17 +00:00
if( track->m_Shape != THROUGH_VIA )
2007-08-10 19:14:51 +00:00
continue;
D_PAD* pad = Fast_Locate_Pad_Connecte( frame->m_Pcb, track->m_Start, ALL_CU_LAYERS );
if( pad && (pad->m_Masque_Layer & EXTERNAL_LAYERS) == EXTERNAL_LAYERS ) // redundant Via
{
/* delete via */
track->UnLink();
delete track;
}
}
}
#ifdef CONN2PAD_ENBL
2007-08-10 19:14:51 +00:00
if( s_ConnectToPads ) /* Creation de points de connexion */
{
/* Raccordement des extremites de piste au centre des pastilles : */
ConnectDanglingEndToPad( frame, DC );
/* Creation de points de raccordements aux intersections de pistes */
// Gen_Raccord_Track(frame, DC);
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
}
2007-05-06 16:03:28 +00:00
#endif
2007-08-10 19:14:51 +00:00
/* suppression des segments de longueur nulle et des points intermediaires
* alignes */
if( s_MergeSegments )
clean_segments( frame, DC );
2007-05-06 16:03:28 +00:00
2007-08-10 19:14:51 +00:00
/* suppression des pistes non connectees ( c.a.d dont 1 extremite est en l'air) */
if( s_DeleteUnconnectedSegm )
suppression_piste_non_connectee( frame, DC );
2007-05-06 16:03:28 +00:00
2007-08-10 19:14:51 +00:00
frame->Compile_Ratsnest( DC, AFFICHE );
2007-05-06 16:03:28 +00:00
2007-08-10 19:14:51 +00:00
frame->m_CurrentScreen->SetModify();
2007-05-06 16:03:28 +00:00
}
/*****************************************************************************/
2007-08-10 19:14:51 +00:00
static void suppression_piste_non_connectee( WinEDA_PcbFrame* frame, wxDC* DC )
2007-05-06 16:03:28 +00:00
/*****************************************************************************/
2007-08-10 19:14:51 +00:00
2007-05-06 16:03:28 +00:00
/*
2007-08-10 19:14:51 +00:00
* Supprime les segments de piste ayant 1 ou 2 extremites non connectees
* Cas des vias:
* si une extremite de segment est connectee uniquement a une via, la via
* et le segment seront supprimes
*/
2007-05-06 16:03:28 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* segment, * pt_other, * pt_via;
2007-08-10 19:14:51 +00:00
TRACK* PtStartNetCode;
EDA_BaseStruct* NextS;
D_PAD* ptr_pad;
int nbpoints_supprimes = 0;
int masklayer, oldnetcode;
int type_end, flag_erase;
int ii, percent, oldpercent;
wxString msg;
frame->Affiche_Message( _( "Delete unconnected tracks:" ) );
frame->DrawPanel->m_AbortRequest = FALSE;
/* Correction des defauts des vias et recalcul du nombre de segm */
frame->m_Pcb->m_NbSegmTrack = 0; ii = 0;
2007-10-15 03:26:38 +00:00
for( segment = frame->m_Pcb->m_Track; segment != NULL; segment = (TRACK*) NextS )
2007-08-10 19:14:51 +00:00
{
frame->m_Pcb->m_NbSegmTrack++;
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
if( segment->Type() == TYPEVIA )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
if( (segment->m_Start.x != segment->m_End.x )
|| (segment->m_Start.y != segment->m_End.y ) )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
segment->m_End.x = segment->m_Start.x;
segment->m_End.y = segment->m_Start.y;
2007-08-10 19:14:51 +00:00
ii++;
msg.Printf( wxT( "%d " ), ii );
Affiche_1_Parametre( frame, POS_AFF_PASSE, _( "ViaDef" ), msg, LIGHTRED );
}
continue;
}
}
/* Suppression des pistes en l'air */
2007-10-15 03:26:38 +00:00
segment = frame->m_Pcb->m_Track;
percent = 0;
oldpercent = -1;
oldnetcode = 0;
PtStartNetCode = frame->m_Pcb->m_Track;
for( ii = 0; segment != NULL; segment = (TRACK*) NextS, ii++ )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
2007-08-10 19:14:51 +00:00
/* Affiche activite */
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
oldpercent = percent;
frame->DisplayActivity( percent, wxT( "No Conn: " ) );
msg.Printf( wxT( "%d " ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
msg.Printf( wxT( "%d " ), ii );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
}
if( frame->DrawPanel->m_AbortRequest )
break;
2007-10-15 03:26:38 +00:00
if( segment->GetNet() != oldnetcode )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
PtStartNetCode = segment; oldnetcode = segment->GetNet();
2007-08-10 19:14:51 +00:00
}
flag_erase = 0; type_end = 0;
/* y a t-il une pastille sur chaque extremite */
2007-10-15 03:26:38 +00:00
masklayer = segment->ReturnMaskLayer();
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
ptr_pad = Fast_Locate_Pad_Connecte( frame->m_Pcb, segment->m_Start, masklayer );
2007-08-10 19:14:51 +00:00
if( ptr_pad != NULL )
{
2007-10-15 03:26:38 +00:00
segment->start = ptr_pad;
2007-08-10 19:14:51 +00:00
type_end |= START_SUR_PAD;
}
2007-10-15 03:26:38 +00:00
ptr_pad = Fast_Locate_Pad_Connecte( frame->m_Pcb, segment->m_End, masklayer );
2007-08-10 19:14:51 +00:00
if( ptr_pad != NULL )
{
2007-10-15 03:26:38 +00:00
segment->end = ptr_pad;
2007-08-10 19:14:51 +00:00
type_end |= END_SUR_PAD;
}
/* Test si une extremite est connectee sur une piste */
if( (type_end & START_SUR_PAD ) == 0 )
{
2007-10-15 03:26:38 +00:00
pt_other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, START );
if( pt_other == NULL )
flag_erase |= 1;
else /* Segment ou via connectee a cette extremite */
{
2007-10-15 03:26:38 +00:00
segment->start = pt_other;
2007-09-01 12:00:30 +00:00
if( pt_other->Type() == TYPEVIA ) /* recherche d'un autre segment */
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
segment->SetState( BUSY, ON );
2007-08-10 19:14:51 +00:00
pt_via = pt_other;
pt_other = Locate_Piste_Connectee( pt_via, frame->m_Pcb->m_Track,
NULL, START );
if( pt_other == NULL )
flag_erase |= 2;
2007-10-15 03:26:38 +00:00
segment->SetState( BUSY, OFF );
2007-08-10 19:14:51 +00:00
}
}
}
if( (type_end & END_SUR_PAD ) == 0 )
{
2007-10-15 03:26:38 +00:00
pt_other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, END );
if( pt_other == NULL )
flag_erase |= 0x10;
else /* Segment ou via connectee a cette extremite */
{
2007-10-15 03:26:38 +00:00
segment->end = pt_other;
2007-09-01 12:00:30 +00:00
if( pt_other->Type() == TYPEVIA ) /* recherche d'un autre segment */
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
segment->SetState( BUSY, ON );
2007-08-10 19:14:51 +00:00
pt_via = pt_other;
pt_other = Locate_Piste_Connectee( pt_via, frame->m_Pcb->m_Track,
NULL, END );
if( pt_other == NULL )
flag_erase |= 0x20;
2007-10-15 03:26:38 +00:00
segment->SetState( BUSY, OFF );
2007-08-10 19:14:51 +00:00
}
}
}
if( flag_erase )
{
oldpercent = -1; /* force affichage activite */
2007-10-15 03:26:38 +00:00
nbpoints_supprimes++;
ii--;
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d " ), nbpoints_supprimes );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "NoConn." ), msg, LIGHTRED );
2007-10-15 03:26:38 +00:00
/* rectification du pointeur segment pour repartir en debut
2007-08-10 19:14:51 +00:00
* du block des segments de meme net_code */
2007-10-15 03:26:38 +00:00
if( segment == PtStartNetCode )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
2007-08-10 19:14:51 +00:00
PtStartNetCode = (TRACK*) NextS;
}
else
NextS = PtStartNetCode;
/* Suppression du segment */
2007-10-15 03:26:38 +00:00
segment->Draw( frame->DrawPanel, DC, GR_XOR );
segment->DeleteStructure();
2007-08-10 19:14:51 +00:00
if( NextS == NULL )
break;
}
}
2007-05-06 16:03:28 +00:00
}
/************************************************************/
2007-08-10 19:14:51 +00:00
static int clean_segments( WinEDA_PcbFrame* frame, wxDC* DC )
2007-05-06 16:03:28 +00:00
/************************************************************/
/* Supprime segments nulls, points inutiles .. */
{
2007-10-15 03:26:38 +00:00
TRACK* segment, * pt_aux;
2007-08-10 19:14:51 +00:00
EDA_BaseStruct* NextS;
int ii, nbpoints_supprimes = 0;
int flag, no_inc, percent, oldpercent;
wxString msg;
frame->DrawPanel->m_AbortRequest = FALSE;
/**********************************************/
/* suppression des segments de longueur nulle */
/**********************************************/
a_color = GREEN;
2007-10-15 03:26:38 +00:00
nbpoints_supprimes = 0;
percent = 0;
oldpercent = -1;
2007-08-10 19:14:51 +00:00
frame->MsgPanel->EraseMsgBox();
frame->Affiche_Message( _( "Clean Null Segments" ) );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "NullSeg" ), wxT( "0" ), a_color );
2007-10-15 03:26:38 +00:00
segment = frame->m_Pcb->m_Track;
for( segment = frame->m_Pcb->m_Track; segment != NULL; segment = (TRACK*) NextS )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
if( !segment->IsNull() )
2007-08-10 19:14:51 +00:00
continue;
/* Lenght segment = 0; delete it */
2007-10-15 03:26:38 +00:00
segment->Draw( frame->DrawPanel, DC, GR_XOR );
segment->DeleteStructure();
2007-08-10 19:14:51 +00:00
nbpoints_supprimes++;
msg.Printf( wxT( " %d" ), nbpoints_supprimes );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
}
/**************************************/
/* suppression des segments confondus */
/**************************************/
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "Ident" ), wxT( "0" ), a_color );
2007-10-15 03:26:38 +00:00
percent = 0;
oldpercent = -1;
segment = frame->m_Pcb->m_Track;
for( ii = 0; segment != NULL; segment = (TRACK*) segment->Pnext, ii++ )
2007-08-10 19:14:51 +00:00
{
/* affichage activite */
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
frame->DisplayActivity( percent, wxT( "Id segm: " ) );
oldpercent = percent;
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), ii );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
if( frame->DrawPanel->m_AbortRequest )
return -1;
}
2007-10-15 03:26:38 +00:00
for( pt_aux = (TRACK*) segment->Pnext; pt_aux != NULL; pt_aux = (TRACK*) NextS )
2007-08-10 19:14:51 +00:00
{
int erase = 0;
NextS = pt_aux->Pnext;
2007-10-15 03:26:38 +00:00
if( segment->Type() != pt_aux->Type() )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->GetLayer() != pt_aux->GetLayer() )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->GetNet() != pt_aux->GetNet() )
2007-08-10 19:14:51 +00:00
break;
2007-10-15 03:26:38 +00:00
if( segment->m_Start == pt_aux->m_Start )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
if( segment->m_End == pt_aux->m_End )
2007-08-10 19:14:51 +00:00
erase = 1;
}
2007-10-15 03:26:38 +00:00
if( segment->m_Start == pt_aux->m_End )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
if( segment->m_End == pt_aux->m_Start )
2007-08-10 19:14:51 +00:00
erase = 1;
}
/* suppression du point en trop */
if( erase )
{
ii--;
pt_aux->Draw( frame->DrawPanel, DC, GR_OR );
pt_aux->DeleteStructure();
2007-08-10 19:14:51 +00:00
nbpoints_supprimes++;
msg.Printf( wxT( " %d" ), nbpoints_supprimes );
Affiche_1_Parametre( frame, 50, wxEmptyString, msg, a_color );
}
}
}
/**************************************************************/
/* suppression des points intermediaires ( segments alignes ) */
/**************************************************************/
2007-10-15 03:26:38 +00:00
nbpoints_supprimes = 0;
percent = 0;
oldpercent = -1;
2007-08-10 19:14:51 +00:00
frame->Affiche_Message( _( "Merging Segments:" ) );
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "Merge" ), _( "0" ), a_color );
ii = 0;
2007-10-15 03:26:38 +00:00
segment = frame->m_Pcb->m_Track;
for( segment = frame->m_Pcb->m_Track; segment!= NULL; segment = (TRACK*) NextS )
2007-08-10 19:14:51 +00:00
{
TRACK* pt_segm_s, * pt_segm_e, * pt_segm_delete;
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
2007-08-10 19:14:51 +00:00
/* affichage activite */
ii++;
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
frame->DisplayActivity( percent, _( "Merge: " ) );
oldpercent = percent;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), ii );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
if( frame->DrawPanel->m_AbortRequest )
return -1;
}
2007-10-15 03:26:38 +00:00
if( segment->Type() != TYPETRACK )
2007-08-10 19:14:51 +00:00
continue;
flag = no_inc = 0;
/* Recherche d'un point possible raccorde sur DEBUT de segment: */
2007-10-15 03:26:38 +00:00
for( pt_segm_s = (TRACK*) segment->Pnext; ; )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
pt_segm_s = Locate_Piste_Connectee( segment, pt_segm_s,
2007-08-10 19:14:51 +00:00
NULL, START );
if( pt_segm_s )
{
/* les 2 segments doivent avoir meme largeur */
2007-10-15 03:26:38 +00:00
if( segment->m_Width != pt_segm_s->m_Width )
2007-08-10 19:14:51 +00:00
break;
/* Ce ne peut etre une via */
2007-09-01 12:00:30 +00:00
if( pt_segm_s->Type() != TYPETRACK )
2007-08-10 19:14:51 +00:00
break;
/* On ne peut avoir que 1 seul segment connecte */
pt_segm_s->SetState( BUSY, ON );
2007-10-15 03:26:38 +00:00
pt_aux = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, START );
pt_segm_s->SetState( BUSY, OFF );
if( pt_aux == NULL )
flag = 1;/* OK */
break;
}
break;
}
if( flag ) /* debut de segment raccorde a un autre segment */
{
2007-10-15 03:26:38 +00:00
pt_segm_delete = AlignSegment( frame->m_Pcb, segment, pt_segm_s, START );
2007-08-10 19:14:51 +00:00
if( pt_segm_delete )
{
nbpoints_supprimes++; no_inc = 1;
pt_segm_delete->DeleteStructure();
2007-08-10 19:14:51 +00:00
}
}
/* Recherche d'un point possible raccorde sur FIN de segment: */
2007-10-15 03:26:38 +00:00
for( pt_segm_e = (TRACK*) segment->Pnext; ; )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
pt_segm_e = Locate_Piste_Connectee( segment, pt_segm_e,
2007-08-10 19:14:51 +00:00
NULL, END );
if( pt_segm_e )
{
/* les 2 segments doivent avoir meme largeur */
2007-10-15 03:26:38 +00:00
if( segment->m_Width != pt_segm_e->m_Width )
2007-08-10 19:14:51 +00:00
break;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
/* Ce ne peut etre une via */
2007-09-01 12:00:30 +00:00
if( pt_segm_e->Type() != TYPETRACK )
2007-08-10 19:14:51 +00:00
break;
/* On ne peut avoir que 1 seul segment connecte */
pt_segm_e->SetState( BUSY, ON );
2007-10-15 03:26:38 +00:00
pt_aux = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, END );
pt_segm_e->SetState( BUSY, OFF );
if( pt_aux == NULL )
flag |= 2;/* Ok */
break;
}
else
break;
}
if( flag & 2 ) /* FIN de segment raccorde a un autre segment */
{
2007-10-15 03:26:38 +00:00
pt_segm_delete = AlignSegment( frame->m_Pcb, segment, pt_segm_e, END );
2007-08-10 19:14:51 +00:00
if( pt_segm_delete )
{
nbpoints_supprimes++; no_inc = 1;
pt_segm_delete->DeleteStructure();
2007-08-10 19:14:51 +00:00
}
}
if( no_inc ) /* Le segment en cours a ete modifie, il faut le reexaminer */
{
msg.Printf( wxT( "%d " ), nbpoints_supprimes );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
2007-10-15 03:26:38 +00:00
NextS = segment->Pnext;
2007-08-10 19:14:51 +00:00
}
}
return 0;
2007-05-06 16:03:28 +00:00
}
2007-08-10 19:14:51 +00:00
2007-05-06 16:03:28 +00:00
/****************************************************************************/
2007-08-10 19:14:51 +00:00
static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extremite )
2007-05-06 16:03:28 +00:00
/****************************************************************************/
2007-08-10 19:14:51 +00:00
2007-05-06 16:03:28 +00:00
/* Routine utilisee par clean_segments.
2007-08-10 19:14:51 +00:00
* Verifie l'alignement de pt_segm / pt_ref. et verifie que le point commun
* a faire disparaitre n'est pas sur un pad.
* l'extremite testee est debut (extremite == START) ou fin (extremite == FIN)
* si il y a alignement, modifie les coord d'extremite de pt_ref et retourne
* pt_segm.
* sinon retourne NULL
*/
2007-05-06 16:03:28 +00:00
{
2007-08-10 19:14:51 +00:00
int refdx, refdy, segmdx, segmdy;/* projections des segments */
int flag = 0;
2007-10-15 03:26:38 +00:00
refdx = pt_ref->m_End.x - pt_ref->m_Start.x;
refdy = pt_ref->m_End.y - pt_ref->m_Start.y;
segmdx = pt_segm->m_End.x - pt_segm->m_Start.x;
segmdy = pt_segm->m_End.y - pt_segm->m_Start.y;
2007-08-10 19:14:51 +00:00
/* Tst alignement vertical possible: */
if( refdx == 0 )
{
if( segmdx != 0 )
return NULL;
else
flag = 1;
}
/* Tst alignement horizontal possible: */
if( refdy == 0 )
{
if( segmdy != 0 )
return NULL;
else
flag = 2;
}
/* tst si il y a alignement d'angle qcq
* il faut que refdy/refdx == (+/-)segmdy/segmdx, c.a.d meme direction */
if( flag == 0 )
{
if( (refdy * segmdx != refdx * segmdy)
2007-10-15 03:26:38 +00:00
&& (refdy * segmdx != -refdx * segmdy) )
2007-08-10 19:14:51 +00:00
return NULL;
flag = 4;
}
/* Ici il y a alignement: il faut determiner les positions relatives
* pour supprimer le point commun et le remplacer */
if( extremite == START )
{
/* Ce ne doit pas etre sur un pad */
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_Start,
2007-08-23 04:28:46 +00:00
g_TabOneLayerMask[pt_ref->GetLayer()] ) )
2007-08-10 19:14:51 +00:00
return NULL;
if( (pt_ref->m_Start.x == pt_segm->m_Start.x)
2007-10-15 03:26:38 +00:00
&& (pt_ref->m_Start.y == pt_segm->m_Start.y) )
2007-08-10 19:14:51 +00:00
{
pt_ref->m_Start.x = pt_segm->m_End.x; pt_ref->m_Start.y = pt_segm->m_End.y;
return pt_segm;
}
else /* connexion par la fin de pt_segm */
{
pt_ref->m_Start.x = pt_segm->m_Start.x; pt_ref->m_Start.y = pt_segm->m_Start.y;
return pt_segm;
}
}
else /* extremite == END */
{
/* Ce ne doit pas etre sur un pad */
2007-08-23 04:28:46 +00:00
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_End, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
2007-08-10 19:14:51 +00:00
return NULL;
if( pt_ref->m_End == pt_segm->m_Start )
{
pt_ref->m_End = pt_segm->m_End;
return pt_segm;
}
else /* connexion par la fin de pt_segm */
{
pt_ref->m_End = pt_segm->m_Start;
return pt_segm;
}
}
return NULL;
2007-05-06 16:03:28 +00:00
}
/***************************************************************************/
2007-08-10 19:14:51 +00:00
int Netliste_Controle_piste( WinEDA_PcbFrame* frame, wxDC* DC, int affiche )
/***************************************************************************/
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
/**
* Function Netliste_Controle_piste
* finds all track segments which are mis-connected (to more than one net).
* When such a bad segment is found, mark it as needing to be removed (supression).
2007-08-10 19:14:51 +00:00
*/
2007-05-06 16:03:28 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* segment;
TRACK* other;
TRACK* next;
2007-08-10 19:14:51 +00:00
int net_code_s, net_code_e;
int nbpoints_modifies = 0;
int flag = 0;
wxString msg;
2007-10-15 03:26:38 +00:00
int percent = 0;
int oldpercent = -1;
2007-08-10 19:14:51 +00:00
a_color = RED;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
frame->Affiche_Message( _( "DRC Control:" ) );
frame->DrawPanel->m_AbortRequest = FALSE;
if( affiche )
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "NetCtr" ), wxT( "0 " ), a_color );
2007-10-15 03:26:38 +00:00
int ii = 0;
for( segment = frame->m_Pcb->m_Track; segment; segment = (TRACK*) segment->Next() )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
// display activity
2007-08-10 19:14:51 +00:00
ii++;
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
frame->DisplayActivity( percent, wxT( "Drc: " ) );
oldpercent = percent;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
if( frame->DrawPanel->m_AbortRequest )
return flag;
}
2007-10-15 03:26:38 +00:00
segment->SetState( FLAG0, OFF );
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
// find the netcode for segment using anything connected to the "start" of "segment"
2007-08-10 19:14:51 +00:00
net_code_s = -1;
2007-10-15 03:26:38 +00:00
if( segment->start && segment->start->Type()==TYPEPAD )
{
// get the netcode of the pad to propagate.
net_code_s = ((D_PAD*)(segment->start))->GetNet();
}
2007-08-10 19:14:51 +00:00
else
{
2007-10-15 03:26:38 +00:00
other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, START );
2007-10-15 03:26:38 +00:00
if( other )
net_code_s = other->GetNet();
2007-08-10 19:14:51 +00:00
}
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
if( net_code_s < 0 )
2007-10-15 03:26:38 +00:00
continue; // the "start" of segment is not connected
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
// find the netcode for segment using anything connected to the "end" of "segment"
2007-08-10 19:14:51 +00:00
net_code_e = -1;
2007-10-15 03:26:38 +00:00
if( segment->end && segment->end->Type()==TYPEPAD )
{
net_code_e = ((D_PAD*)(segment->end))->GetNet();
}
2007-08-10 19:14:51 +00:00
else
{
2007-10-15 03:26:38 +00:00
other = Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, END );
2007-10-15 03:26:38 +00:00
if( other )
net_code_e = other->GetNet();
2007-08-10 19:14:51 +00:00
}
if( net_code_e < 0 )
2007-10-15 03:26:38 +00:00
continue; // the "end" of segment is not connected
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
// the obtained netcodes do not agree, mark the segment as needing to be removed
2007-08-10 19:14:51 +00:00
if( net_code_s != net_code_e )
{
2007-10-15 03:26:38 +00:00
segment->SetState( FLAG0, ON );
2007-08-10 19:14:51 +00:00
}
}
2007-10-15 03:26:38 +00:00
// suppression of segments
for( segment = frame->m_Pcb->m_Track; segment; segment = next )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
next = (TRACK*) segment->Next();
if( segment->GetState( FLAG0 ) ) //* if segment is marked as needing to be removed
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
segment->SetState( FLAG0, OFF );
flag = 1;
oldpercent = -1;
2007-08-10 19:14:51 +00:00
frame->m_Pcb->m_Status_Pcb = 0;
2007-10-15 03:26:38 +00:00
frame->Supprime_Une_Piste( DC, segment );
next = frame->m_Pcb->m_Track; /* NextS a peut etre ete efface */
2007-08-10 19:14:51 +00:00
if( affiche )
{
nbpoints_modifies++;
msg.Printf( wxT( "%d " ), nbpoints_modifies );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
}
}
}
return flag;
2007-05-06 16:03:28 +00:00
}
#ifdef CONN2PAD_ENBL
2007-05-06 16:03:28 +00:00
/***************************************************************/
2007-08-10 19:14:51 +00:00
static void Gen_Raccord_Track( WinEDA_PcbFrame* frame, wxDC* DC )
2007-05-06 16:03:28 +00:00
/***************************************************************/
2007-10-15 03:26:38 +00:00
/**
* Function Gen_Raccord_Track
* tests the ends of segments. If and end is on a segment of other track, but not
* on other's end, the other segment is cut into 2, the point of cut being the end of
* segment first being operated on. This is done so that the subsequent tests
* of connection, which do not test segment overlaps, will see this continuity.
*/
2007-05-06 16:03:28 +00:00
/* Teste les extremites de segments :
2007-08-10 19:14:51 +00:00
* si une extremite est sur un segment de piste, mais pas sur une extremite,
* le segment est coupe en 2, le point de coupure etant l'extremite du segment
* Ceci est fait pour que les tests de connexion qui ne testent que les extremites
* de segments voient la connexion
*/
2007-05-06 16:03:28 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* segment;
TRACK* other;
TRACK* next;
2007-08-10 19:14:51 +00:00
int nn = 0;
int masquelayer;
int ii, percent, oldpercent;
wxString msg;
frame->Affiche_Message( wxT( "Gen Raccords sur Pistes:" ) );
if( frame->m_Pcb->GetNumSegmTrack() == 0 )
return;
frame->DrawPanel->m_AbortRequest = FALSE;
oldpercent = -1; ii = 0;
2007-10-15 03:26:38 +00:00
for( segment = frame->m_Pcb->m_Track; segment; segment = next )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
next = (TRACK*) segment->Next();
// display activity
2007-08-10 19:14:51 +00:00
ii++;
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
frame->DisplayActivity( percent, wxT( "Tracks: " ) );
oldpercent = percent;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), ii );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
}
if( frame->DrawPanel->m_AbortRequest )
return;
2007-10-15 03:26:38 +00:00
masquelayer = segment->ReturnMaskLayer();
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
// look at the "start" of the "segment"
for( other = frame->m_Pcb->m_Track; other; other = (TRACK*) other->Next() )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* newTrack;
other = Locate_Pistes( other, segment->m_Start, masquelayer );
if( other == NULL )
2007-08-10 19:14:51 +00:00
break;
2007-10-15 03:26:38 +00:00
if( other == segment )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( other->Type() == TYPEVIA )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_Start == other->m_Start )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_Start == other->m_End )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
// Test if the "end" of this segment is already connected to other
if( segment->m_End == other->m_Start )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_End == other->m_End )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
other->Draw( frame->DrawPanel, DC, GR_XOR );
2007-08-10 19:14:51 +00:00
nn++;
msg.Printf( wxT( "%d" ), nn );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "New <" ), msg, YELLOW );
2007-10-15 03:26:38 +00:00
frame->m_Pcb->m_NbSegmTrack++;
// create a new segment and insert it next to "other", then shorten other.
newTrack = other->Copy();
newTrack->Insert( frame->m_Pcb, other );
other->m_End = segment->m_Start;
newTrack->m_Start = segment->m_Start;
Trace_Une_Piste( frame->DrawPanel, DC, other, 2, GR_OR );
// skip forward one, skipping the newTrack
other = newTrack;
2007-08-10 19:14:51 +00:00
}
2007-10-15 03:26:38 +00:00
// look at the "end" of the "segment"
for( other = frame->m_Pcb->m_Track; other; other = (TRACK*) other->Next() )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* newTrack;
other = Locate_Pistes( other, segment->m_End, masquelayer );
if( other == NULL )
2007-08-10 19:14:51 +00:00
break;
2007-10-15 03:26:38 +00:00
if( other == segment )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( other->Type() == TYPEVIA )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_End == other->m_Start )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_End == other->m_End )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_Start == other->m_Start )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
if( segment->m_Start == other->m_End )
2007-08-10 19:14:51 +00:00
continue;
2007-10-15 03:26:38 +00:00
other->Draw( frame->DrawPanel, DC, GR_XOR );
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
nn++;
msg.Printf( wxT( "%d" ), nn );
2007-08-10 19:14:51 +00:00
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "New >" ), msg, YELLOW );
2007-10-15 03:26:38 +00:00
frame->m_Pcb->m_NbSegmTrack++;
// create a new segment and insert it next to "other", then shorten other.
newTrack = other->Copy();
newTrack->Insert( frame->m_Pcb, other );
other->m_End = segment->m_End;
newTrack->m_Start = segment->m_End;
Trace_Une_Piste( frame->DrawPanel, DC, other, 2, GR_OR );
// skip forward one, skipping the newTrack
other = newTrack;
2007-08-10 19:14:51 +00:00
}
}
2007-05-06 16:03:28 +00:00
}
2007-08-10 19:14:51 +00:00
/***************************************************************/
2007-08-10 19:14:51 +00:00
void ConnectDanglingEndToPad( WinEDA_PcbFrame* frame, wxDC* DC )
/**************************************************************/
2007-08-10 19:14:51 +00:00
2007-10-15 03:26:38 +00:00
/**
* Function ConnectDanglingEndToPad
* possibly adds a segment to the end of any and all tracks if their end is not exactly
* connected into the center of the pad. This allows faster control of
* connections.
2007-08-10 19:14:51 +00:00
*/
2007-05-06 16:03:28 +00:00
{
2007-10-15 03:26:38 +00:00
TRACK* segment;
TRACK* next;
int nb_new_piste = 0;
2007-08-10 19:14:51 +00:00
wxString msg;
2007-10-15 03:26:38 +00:00
int percent = 0;
int oldpercent = -1;
2007-08-10 19:14:51 +00:00
a_color = GREEN;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
frame->DrawPanel->m_AbortRequest = FALSE;
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "Centre" ), _( "0 " ), a_color );
2007-10-15 03:26:38 +00:00
int ii = 0;
for( segment = frame->m_Pcb->m_Track; segment; segment = next )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
D_PAD* pad;
next = (TRACK*) segment->Next();
2007-08-10 19:14:51 +00:00
ii++;
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
if( percent != oldpercent )
{
frame->DisplayActivity( percent, _( "Pads: " ) );
oldpercent = percent;
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
Affiche_1_Parametre( frame, POS_AFF_MAX, _( "Max" ), msg, GREEN );
2007-10-15 03:26:38 +00:00
2007-08-10 19:14:51 +00:00
msg.Printf( wxT( "%d" ), ii );
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, _( "Segm" ), msg, CYAN );
if( frame->DrawPanel->m_AbortRequest )
return;
}
2007-10-15 03:26:38 +00:00
pad = Locate_Pad_Connecte( frame->m_Pcb, segment, START );
if( pad )
{
// test if the track is not precisely starting on the found pad
if( segment->m_Start != pad->m_Pos )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
if( Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, START ) == NULL )
{
2007-10-15 03:26:38 +00:00
TRACK* newTrack = segment->Copy();
newTrack->Insert( frame->m_Pcb, segment );
newTrack->m_End = pad->m_Pos;
newTrack->start = segment;
newTrack->end = pad;
2007-08-10 19:14:51 +00:00
nb_new_piste++;
2007-10-15 03:26:38 +00:00
newTrack->Draw( frame->DrawPanel, DC, GR_OR );
2007-08-10 19:14:51 +00:00
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
}
}
}
2007-10-15 03:26:38 +00:00
pad = Locate_Pad_Connecte( frame->m_Pcb, segment, END );
if( pad )
{
// test if the track is not precisely ending on the found pad
if( segment->m_End != pad->m_Pos )
2007-08-10 19:14:51 +00:00
{
2007-10-15 03:26:38 +00:00
if( Locate_Piste_Connectee( segment, frame->m_Pcb->m_Track,
2007-08-10 19:14:51 +00:00
NULL, END ) == NULL )
{
2007-10-15 03:26:38 +00:00
TRACK* newTrack = segment->Copy();
newTrack->Insert( frame->m_Pcb, segment );
newTrack->m_Start = pad->m_Pos;
newTrack->start = pad;
newTrack->end = segment;
2007-08-10 19:14:51 +00:00
nb_new_piste++;
msg.Printf( wxT( "e %d" ), nb_new_piste );
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
}
}
}
}
2007-05-06 16:03:28 +00:00
}
#endif