955 lines
33 KiB
C++
955 lines
33 KiB
C++
/******************************************************/
|
||
/* editeur de PCB PCBNEW */
|
||
/* Fonctions de Nettoyage et reorganisation de Pistes */
|
||
/******************************************************/
|
||
|
||
/* Fichier CLEAN.CPP */
|
||
|
||
#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 */
|
||
#define AFFICHE 1
|
||
#define POS_AFF_PASSE 40
|
||
#define POS_AFF_VAR 50
|
||
#define POS_AFF_MAX 60
|
||
#define POS_AFF_NUMSEGM 70
|
||
|
||
/* Routines locales : */
|
||
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 );
|
||
|
||
/* Variables locales : */
|
||
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;
|
||
|
||
#include "cleaningoptions_dialog.cpp"
|
||
|
||
#define CONN2PAD_ENBL
|
||
|
||
#ifdef CONN2PAD_ENBL
|
||
static void ConnectDanglingEndToPad( WinEDA_PcbFrame* frame, wxDC* DC );
|
||
static void Gen_Raccord_Track( WinEDA_PcbFrame* frame, wxDC* DC );
|
||
|
||
#endif
|
||
|
||
/*****************************************/
|
||
void WinEDA_PcbFrame::Clean_Pcb( wxDC* DC )
|
||
/*****************************************/
|
||
|
||
/* Regroupement des segments de meme piste.
|
||
* Suppression des points inutiles
|
||
* - via sur pad
|
||
* - points de couche et coord identiques
|
||
* - points alignes (supp du pt milieu)
|
||
*/
|
||
{
|
||
s_ConnectToPads = false;
|
||
WinEDA_CleaningOptionsFrame* frame = new WinEDA_CleaningOptionsFrame( this, DC );
|
||
frame->ShowModal(); frame->Destroy();
|
||
DrawPanel->Refresh( true );
|
||
}
|
||
|
||
|
||
/************************************************************/
|
||
void Clean_Pcb_Items( WinEDA_PcbFrame* frame, wxDC* DC )
|
||
/************************************************************/
|
||
{
|
||
frame->MsgPanel->EraseMsgBox();
|
||
frame->m_Pcb->GetNumSegmTrack(); /* Met a jour le compte */
|
||
/* 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();
|
||
|
||
if( s_CleanVias ) /* delete redundant vias */
|
||
{
|
||
TRACK* track, * next_track;
|
||
for( track = frame->m_Pcb->m_Track; track != NULL; track = track->Next() )
|
||
{
|
||
if( track->m_Shape != VIA_NORMALE )
|
||
continue;
|
||
/* 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();
|
||
if( alt_track->m_Shape != VIA_NORMALE )
|
||
continue;
|
||
if( alt_track->m_Start != track->m_Start )
|
||
continue;
|
||
/* 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();
|
||
if( track->m_Shape != VIA_NORMALE )
|
||
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
|
||
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);
|
||
}
|
||
#endif
|
||
|
||
/* suppression des segments de longueur nulle et des points intermediaires
|
||
* alignes */
|
||
if( s_MergeSegments )
|
||
clean_segments( frame, DC );
|
||
|
||
/* suppression des pistes non connectees ( c.a.d dont 1 extremite est en l'air) */
|
||
if( s_DeleteUnconnectedSegm )
|
||
suppression_piste_non_connectee( frame, DC );
|
||
|
||
frame->Compile_Ratsnest( DC, AFFICHE );
|
||
|
||
frame->m_CurrentScreen->SetModify();
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
static void suppression_piste_non_connectee( WinEDA_PcbFrame* frame, wxDC* DC )
|
||
/*****************************************************************************/
|
||
|
||
/*
|
||
* 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
|
||
*/
|
||
{
|
||
TRACK* PtSegm, * pt_other, * pt_via;
|
||
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;
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
frame->m_Pcb->m_NbSegmTrack++;
|
||
NextS = PtSegm->Pnext;
|
||
if( PtSegm->m_StructType == TYPEVIA )
|
||
{
|
||
if( (PtSegm->m_Start.x != PtSegm->m_End.x )
|
||
|| (PtSegm->m_Start.y != PtSegm->m_End.y ) )
|
||
{
|
||
PtSegm->m_End.x = PtSegm->m_Start.x;
|
||
PtSegm->m_End.y = PtSegm->m_Start.y;
|
||
ii++;
|
||
msg.Printf( wxT( "%d " ), ii );
|
||
Affiche_1_Parametre( frame, POS_AFF_PASSE, _( "ViaDef" ), msg, LIGHTRED );
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
|
||
/* Suppression des pistes en l'air */
|
||
PtSegm = frame->m_Pcb->m_Track; ii = 0;
|
||
percent = 0; oldpercent = -1;
|
||
oldnetcode = 0; PtStartNetCode = frame->m_Pcb->m_Track;
|
||
for( ; PtSegm != NULL; PtSegm = (TRACK*) NextS, ii++ )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
/* 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;
|
||
|
||
if( PtSegm->m_NetCode != oldnetcode )
|
||
{
|
||
PtStartNetCode = PtSegm; oldnetcode = PtSegm->m_NetCode;
|
||
}
|
||
|
||
flag_erase = 0; type_end = 0;
|
||
/* y a t-il une pastille sur chaque extremite */
|
||
|
||
masklayer = PtSegm->ReturnMaskLayer();
|
||
|
||
ptr_pad = Fast_Locate_Pad_Connecte( frame->m_Pcb, PtSegm->m_Start, masklayer );
|
||
|
||
if( ptr_pad != NULL )
|
||
{
|
||
PtSegm->start = ptr_pad;
|
||
type_end |= START_SUR_PAD;
|
||
}
|
||
|
||
ptr_pad = Fast_Locate_Pad_Connecte( frame->m_Pcb, PtSegm->m_End, masklayer );
|
||
|
||
if( ptr_pad != NULL )
|
||
{
|
||
PtSegm->end = ptr_pad;
|
||
type_end |= END_SUR_PAD;
|
||
}
|
||
|
||
/* Test si une extremite est connectee sur une piste */
|
||
if( (type_end & START_SUR_PAD ) == 0 )
|
||
{
|
||
pt_other = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, START );
|
||
|
||
if( pt_other == NULL )
|
||
flag_erase |= 1;
|
||
|
||
else /* Segment ou via connectee a cette extremite */
|
||
{
|
||
PtSegm->start = pt_other;
|
||
if( pt_other->m_StructType == TYPEVIA ) /* recherche d'un autre segment */
|
||
{
|
||
PtSegm->SetState( BUSY, ON );
|
||
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;
|
||
PtSegm->SetState( BUSY, OFF );
|
||
}
|
||
}
|
||
}
|
||
|
||
if( (type_end & END_SUR_PAD ) == 0 )
|
||
{
|
||
pt_other = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, END );
|
||
if( pt_other == NULL )
|
||
flag_erase |= 0x10;
|
||
else /* Segment ou via connectee a cette extremite */
|
||
{
|
||
PtSegm->end = pt_other;
|
||
if( pt_other->m_StructType == TYPEVIA ) /* recherche d'un autre segment */
|
||
{
|
||
PtSegm->SetState( BUSY, ON );
|
||
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;
|
||
PtSegm->SetState( BUSY, OFF );
|
||
}
|
||
}
|
||
}
|
||
|
||
if( flag_erase )
|
||
{
|
||
oldpercent = -1; /* force affichage activite */
|
||
nbpoints_supprimes++; ii--;
|
||
msg.Printf( wxT( "%d " ), nbpoints_supprimes );
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "NoConn." ), msg, LIGHTRED );
|
||
|
||
/* rectification du pointeur PtSegm pour repartir en debut
|
||
* du block des segments de meme net_code */
|
||
if( PtSegm == PtStartNetCode )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
PtStartNetCode = (TRACK*) NextS;
|
||
}
|
||
else
|
||
NextS = PtStartNetCode;
|
||
|
||
/* Suppression du segment */
|
||
PtSegm->Draw( frame->DrawPanel, DC, GR_XOR );
|
||
DeleteStructure( PtSegm );
|
||
if( NextS == NULL )
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/************************************************************/
|
||
static int clean_segments( WinEDA_PcbFrame* frame, wxDC* DC )
|
||
/************************************************************/
|
||
/* Supprime segments nulls, points inutiles .. */
|
||
{
|
||
TRACK* PtSegm, * pt_aux;
|
||
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;
|
||
nbpoints_supprimes = 0; PtSegm = frame->m_Pcb->m_Track;
|
||
percent = 0; oldpercent = -1;
|
||
frame->MsgPanel->EraseMsgBox();
|
||
frame->Affiche_Message( _( "Clean Null Segments" ) );
|
||
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "NullSeg" ), wxT( "0" ), a_color );
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
if( !PtSegm->IsNull() )
|
||
continue;
|
||
|
||
/* Lenght segment = 0; delete it */
|
||
PtSegm->Draw( frame->DrawPanel, DC, GR_XOR );
|
||
DeleteStructure( PtSegm );
|
||
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 );
|
||
percent = 0; oldpercent = -1;
|
||
PtSegm = frame->m_Pcb->m_Track;
|
||
for( ii = 0; PtSegm != NULL; PtSegm = (TRACK*) PtSegm->Pnext, ii++ )
|
||
{
|
||
/* 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 );
|
||
msg.Printf( wxT( "%d" ), ii );
|
||
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, wxT( "Segm" ), msg, CYAN );
|
||
|
||
if( frame->DrawPanel->m_AbortRequest )
|
||
return -1;
|
||
}
|
||
|
||
for( pt_aux = (TRACK*) PtSegm->Pnext; pt_aux != NULL; pt_aux = (TRACK*) NextS )
|
||
{
|
||
int erase = 0;
|
||
NextS = pt_aux->Pnext;
|
||
|
||
if( PtSegm->m_StructType != pt_aux->m_StructType )
|
||
continue;
|
||
if( PtSegm->m_Layer != pt_aux->m_Layer )
|
||
continue;
|
||
if( PtSegm->m_NetCode != pt_aux->m_NetCode )
|
||
break;
|
||
|
||
if( (PtSegm->m_Start.x == pt_aux->m_Start.x )
|
||
&& (PtSegm->m_Start.y == pt_aux->m_Start.y) )
|
||
{
|
||
if( (PtSegm->m_End.x == pt_aux->m_End.x ) && (PtSegm->m_End.y==pt_aux->m_End.y) )
|
||
erase = 1;
|
||
}
|
||
|
||
if( (PtSegm->m_Start.x==pt_aux->m_End.x ) && (PtSegm->m_Start.y == pt_aux->m_End.y) )
|
||
{
|
||
if( (PtSegm->m_End.x==pt_aux->m_Start.x ) && (PtSegm->m_End.y==pt_aux->m_Start.y) )
|
||
erase = 1;
|
||
}
|
||
|
||
/* suppression du point en trop */
|
||
if( erase )
|
||
{
|
||
ii--;
|
||
pt_aux->Draw( frame->DrawPanel, DC, GR_OR );
|
||
DeleteStructure( pt_aux );
|
||
nbpoints_supprimes++;
|
||
|
||
msg.Printf( wxT( " %d" ), nbpoints_supprimes );
|
||
Affiche_1_Parametre( frame, 50, wxEmptyString, msg, a_color );
|
||
}
|
||
}
|
||
}
|
||
|
||
/**************************************************************/
|
||
/* suppression des points intermediaires ( segments alignes ) */
|
||
/**************************************************************/
|
||
|
||
PtSegm = frame->m_Pcb->m_Track; nbpoints_supprimes = 0;
|
||
percent = 0; oldpercent = -1;
|
||
frame->Affiche_Message( _( "Merging Segments:" ) );
|
||
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "Merge" ), _( "0" ), a_color );
|
||
|
||
ii = 0;
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm!= NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
TRACK* pt_segm_s, * pt_segm_e, * pt_segm_delete;
|
||
|
||
NextS = PtSegm->Pnext;
|
||
/* affichage activite */
|
||
ii++;
|
||
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
|
||
if( percent != oldpercent )
|
||
{
|
||
frame->DisplayActivity( percent, _( "Merge: " ) );
|
||
oldpercent = percent;
|
||
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 )
|
||
return -1;
|
||
}
|
||
|
||
if( PtSegm->m_StructType != TYPETRACK )
|
||
continue;
|
||
|
||
flag = no_inc = 0;
|
||
|
||
/* Recherche d'un point possible raccorde sur DEBUT de segment: */
|
||
for( pt_segm_s = (TRACK*) PtSegm->Pnext; ; )
|
||
{
|
||
pt_segm_s = Locate_Piste_Connectee( PtSegm, pt_segm_s,
|
||
NULL, START );
|
||
if( pt_segm_s )
|
||
{
|
||
/* les 2 segments doivent avoir meme largeur */
|
||
if( PtSegm->m_Width != pt_segm_s->m_Width )
|
||
break;
|
||
|
||
/* Ce ne peut etre une via */
|
||
if( pt_segm_s->m_StructType != TYPETRACK )
|
||
break;
|
||
|
||
/* On ne peut avoir que 1 seul segment connecte */
|
||
pt_segm_s->SetState( BUSY, ON );
|
||
pt_aux = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
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 */
|
||
{
|
||
pt_segm_delete = AlignSegment( frame->m_Pcb, PtSegm, pt_segm_s, START );
|
||
if( pt_segm_delete )
|
||
{
|
||
nbpoints_supprimes++; no_inc = 1;
|
||
DeleteStructure( pt_segm_delete );
|
||
}
|
||
}
|
||
|
||
/* Recherche d'un point possible raccorde sur FIN de segment: */
|
||
for( pt_segm_e = (TRACK*) PtSegm->Pnext; ; )
|
||
{
|
||
pt_segm_e = Locate_Piste_Connectee( PtSegm, pt_segm_e,
|
||
NULL, END );
|
||
if( pt_segm_e )
|
||
{
|
||
/* les 2 segments doivent avoir meme largeur */
|
||
if( PtSegm->m_Width != pt_segm_e->m_Width )
|
||
break;
|
||
/* Ce ne peut etre une via */
|
||
if( pt_segm_e->m_StructType != TYPETRACK )
|
||
break;
|
||
|
||
/* On ne peut avoir que 1 seul segment connecte */
|
||
pt_segm_e->SetState( BUSY, ON );
|
||
pt_aux = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
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 */
|
||
{
|
||
pt_segm_delete = AlignSegment( frame->m_Pcb, PtSegm, pt_segm_e, END );
|
||
if( pt_segm_delete )
|
||
{
|
||
nbpoints_supprimes++; no_inc = 1;
|
||
DeleteStructure( pt_segm_delete );
|
||
}
|
||
}
|
||
|
||
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 );
|
||
NextS = PtSegm->Pnext;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extremite )
|
||
/****************************************************************************/
|
||
|
||
/* Routine utilisee par clean_segments.
|
||
* 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
|
||
*/
|
||
{
|
||
int refdx, refdy, segmdx, segmdy;/* projections des segments */
|
||
int flag = 0;
|
||
|
||
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;
|
||
|
||
/* 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)
|
||
&& (refdy * segmdx != -refdx * segmdy) )
|
||
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,
|
||
g_TabOneLayerMask[pt_ref->m_Layer] ) )
|
||
return NULL;
|
||
|
||
if( (pt_ref->m_Start.x == pt_segm->m_Start.x)
|
||
&& (pt_ref->m_Start.y == pt_segm->m_Start.y) )
|
||
{
|
||
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 */
|
||
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_End, g_TabOneLayerMask[pt_ref->m_Layer] ) )
|
||
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;
|
||
}
|
||
|
||
|
||
/***************************************************************************/
|
||
int Netliste_Controle_piste( WinEDA_PcbFrame* frame, wxDC* DC, int affiche )
|
||
/***************************************************************************/
|
||
|
||
/*
|
||
* verification des connexions.
|
||
* Supprime les segments mal connectes, c.a.d. interconnectant des segments
|
||
* de net_code differents
|
||
*/
|
||
{
|
||
TRACK* PtSegm, * pt_aux;
|
||
EDA_BaseStruct* NextS;
|
||
int net_code_s, net_code_e;
|
||
int nbpoints_modifies = 0;
|
||
int flag = 0;
|
||
int ii, percent, oldpercent;
|
||
wxString msg;
|
||
|
||
a_color = RED;
|
||
percent = 0; oldpercent = -1;
|
||
|
||
frame->Affiche_Message( _( "DRC Control:" ) );
|
||
|
||
frame->DrawPanel->m_AbortRequest = FALSE;
|
||
|
||
if( affiche )
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "NetCtr" ), wxT( "0 " ), a_color );
|
||
|
||
ii = 0;
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) PtSegm->Pnext )
|
||
{
|
||
/* affichage activite */
|
||
ii++;
|
||
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
|
||
if( percent != oldpercent )
|
||
{
|
||
frame->DisplayActivity( percent, wxT( "Drc: " ) );
|
||
oldpercent = percent;
|
||
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
|
||
Affiche_1_Parametre( frame, POS_AFF_MAX, wxT( "Max" ), msg, GREEN );
|
||
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;
|
||
}
|
||
|
||
PtSegm->SetState( FLAG0, OFF );
|
||
|
||
/* Calcul du net_code des elements raccordes sur le point de debut */
|
||
net_code_s = -1;
|
||
if( (PtSegm->start != NULL)
|
||
&& ( ( (EDA_BaseStruct*) (PtSegm->start) )->m_StructType == TYPEPAD ) )
|
||
net_code_s = ( (D_PAD*) (PtSegm->start) )->m_NetCode;
|
||
|
||
else
|
||
{
|
||
pt_aux = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, START );
|
||
if( pt_aux )
|
||
net_code_s = pt_aux->m_NetCode;
|
||
}
|
||
if( net_code_s < 0 )
|
||
continue;/* Extremite en l'air */
|
||
|
||
/* Calcul du net_code des elements raccordes sur le point de fin */
|
||
net_code_e = -1;
|
||
if( (PtSegm->end != NULL)
|
||
&& ( ( (EDA_BaseStruct*) (PtSegm->end) )->m_StructType == TYPEPAD ) )
|
||
net_code_e = ( (D_PAD*) (PtSegm->end) )->m_NetCode;
|
||
|
||
else
|
||
{
|
||
pt_aux = Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, END );
|
||
if( pt_aux )
|
||
net_code_e = pt_aux->m_NetCode;
|
||
}
|
||
|
||
if( net_code_e < 0 )
|
||
continue;/* Extremite en l'air */
|
||
|
||
/* Marquage des segments a supprimer */
|
||
if( net_code_s != net_code_e )
|
||
{
|
||
PtSegm->SetState( FLAG0, ON );
|
||
}
|
||
}
|
||
|
||
/* Suppression effective des segments */
|
||
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
if( PtSegm->GetState( FLAG0 ) ) /* Connexion erronee : a supprimer */
|
||
{
|
||
PtSegm->SetState( FLAG0, OFF );
|
||
flag = 1; oldpercent = -1;
|
||
frame->m_Pcb->m_Status_Pcb = 0;
|
||
frame->Supprime_Une_Piste( DC, PtSegm );
|
||
NextS = frame->m_Pcb->m_Track; /* NextS a peut etre ete efface */
|
||
if( affiche )
|
||
{
|
||
nbpoints_modifies++;
|
||
msg.Printf( wxT( "%d " ), nbpoints_modifies );
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
|
||
}
|
||
}
|
||
}
|
||
|
||
return flag;
|
||
}
|
||
|
||
|
||
#ifdef CONN2PAD_ENBL
|
||
|
||
/***************************************************************/
|
||
static void Gen_Raccord_Track( WinEDA_PcbFrame* frame, wxDC* DC )
|
||
/***************************************************************/
|
||
|
||
/* Teste les extremites de segments :
|
||
* 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
|
||
*/
|
||
{
|
||
TRACK* PtSegm, * pt_aux, * NewTrack;
|
||
EDA_BaseStruct* NextS;
|
||
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;
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
/* affichage activite */
|
||
ii++;
|
||
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
|
||
if( percent != oldpercent )
|
||
{
|
||
frame->DisplayActivity( percent, wxT( "Tracks: " ) );
|
||
oldpercent = percent;
|
||
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 )
|
||
return;
|
||
|
||
masquelayer = PtSegm->ReturnMaskLayer();
|
||
|
||
/* examen du point de depart du segment de reference */
|
||
for( pt_aux = frame->m_Pcb->m_Track; ; pt_aux = (TRACK*) pt_aux->Pnext )
|
||
{
|
||
if( pt_aux == NULL )
|
||
break;
|
||
pt_aux = Locate_Pistes( pt_aux, PtSegm->m_Start, masquelayer );
|
||
if( pt_aux == NULL )
|
||
break;
|
||
if( pt_aux == PtSegm )
|
||
continue;
|
||
if( pt_aux->m_StructType == TYPEVIA )
|
||
continue;
|
||
if( PtSegm->m_Start == pt_aux->m_Start )
|
||
continue;
|
||
if( PtSegm->m_Start == pt_aux->m_End )
|
||
continue;
|
||
|
||
// Test si autre extremite du segment ne serait pas deja connectee
|
||
if( PtSegm->m_End == pt_aux->m_Start )
|
||
continue;
|
||
if( PtSegm->m_End == pt_aux->m_End )
|
||
continue;
|
||
|
||
pt_aux->Draw( frame->DrawPanel, DC, GR_XOR );
|
||
NewTrack = pt_aux->Copy();
|
||
NewTrack->Insert( frame->m_Pcb, pt_aux );
|
||
nn++;
|
||
frame->m_Pcb->m_NbSegmTrack++;
|
||
msg.Printf( wxT( "%d" ), nn );
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "New <" ), msg, YELLOW );
|
||
pt_aux->m_End = PtSegm->m_Start;
|
||
NewTrack->m_Start = PtSegm->m_Start;
|
||
Trace_Une_Piste( frame->DrawPanel, DC, pt_aux, 2, GR_OR );
|
||
pt_aux = NewTrack;
|
||
}
|
||
|
||
/* examen du point de fin du segment de reference */
|
||
for( pt_aux = frame->m_Pcb->m_Track; pt_aux != NULL; pt_aux = (TRACK*) pt_aux->Pnext )
|
||
{
|
||
pt_aux = Locate_Pistes( pt_aux, PtSegm->m_End, masquelayer );
|
||
if( pt_aux == NULL )
|
||
break;
|
||
if( pt_aux == PtSegm )
|
||
continue;
|
||
if( pt_aux->m_StructType == TYPEVIA )
|
||
continue;
|
||
|
||
if( (PtSegm->m_End.x == pt_aux->m_Start.x) && (PtSegm->m_End.y == pt_aux->m_Start.y) )
|
||
continue;
|
||
if( (PtSegm->m_End.x == pt_aux->m_End.x) && (PtSegm->m_End.y == pt_aux->m_End.y) )
|
||
continue;
|
||
|
||
if( (PtSegm->m_Start.x == pt_aux->m_Start.x)
|
||
&& (PtSegm->m_Start.y == pt_aux->m_Start.y) )
|
||
continue;
|
||
if( (PtSegm->m_Start.x == pt_aux->m_End.x) && (PtSegm->m_Start.y == pt_aux->m_End.y) )
|
||
continue;
|
||
|
||
pt_aux->Draw( frame->DrawPanel, DC, GR_XOR );
|
||
|
||
NewTrack = pt_aux->Copy();
|
||
NewTrack->Insert( frame->m_Pcb, pt_aux );
|
||
|
||
frame->m_Pcb->m_NbSegmTrack++;
|
||
nn++; msg.Printf( wxT( "%d" ), nn );
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxT( "New >" ), msg, YELLOW );
|
||
pt_aux->m_End.x = PtSegm->m_End.x; pt_aux->m_End.y = PtSegm->m_End.y;
|
||
NewTrack->m_Start.x = PtSegm->m_End.x; NewTrack->m_Start.y = PtSegm->m_End.y;
|
||
Trace_Une_Piste( frame->DrawPanel, DC, pt_aux, 2, GR_OR );
|
||
pt_aux = NewTrack;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
void ConnectDanglingEndToPad( WinEDA_PcbFrame* frame, wxDC* DC )
|
||
/**************************************************************/
|
||
|
||
/*
|
||
* rajoute eventuellement un segment a une extremite de piste connectee
|
||
* a un pad si cette extremite n'est pas exactement connectee au centre
|
||
* du pad.
|
||
* Ceci permet un controle plus rapide des connexions
|
||
*/
|
||
{
|
||
TRACK* PtSegm;
|
||
EDA_BaseStruct* NextS;
|
||
D_PAD* ptr_pad;
|
||
int nb_new_piste = 0, ii;
|
||
int percent, oldpercent;
|
||
wxString msg;
|
||
|
||
a_color = GREEN;
|
||
percent = 0; oldpercent = -1;
|
||
|
||
frame->DrawPanel->m_AbortRequest = FALSE;
|
||
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, _( "Centre" ), _( "0 " ), a_color );
|
||
|
||
ii = 0;
|
||
for( PtSegm = frame->m_Pcb->m_Track; PtSegm != NULL; PtSegm = (TRACK*) NextS )
|
||
{
|
||
NextS = PtSegm->Pnext;
|
||
/* affichage activite */
|
||
ii++;
|
||
percent = (100 * ii) / frame->m_Pcb->m_NbSegmTrack;
|
||
if( percent != oldpercent )
|
||
{
|
||
frame->DisplayActivity( percent, _( "Pads: " ) );
|
||
oldpercent = percent;
|
||
msg.Printf( wxT( "%d" ), frame->m_Pcb->m_NbSegmTrack );
|
||
Affiche_1_Parametre( frame, POS_AFF_MAX, _( "Max" ), msg, GREEN );
|
||
msg.Printf( wxT( "%d" ), ii );
|
||
Affiche_1_Parametre( frame, POS_AFF_NUMSEGM, _( "Segm" ), msg, CYAN );
|
||
|
||
if( frame->DrawPanel->m_AbortRequest )
|
||
return;
|
||
}
|
||
|
||
ptr_pad = Locate_Pad_Connecte( frame->m_Pcb, PtSegm, START );
|
||
if( ptr_pad != NULL )
|
||
{ /* Test si point piste non deja connecte a un autre segment */
|
||
if( PtSegm->m_Start != ptr_pad->m_Pos )
|
||
{
|
||
if( Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, START ) == NULL )
|
||
{
|
||
TRACK* NewTrack = PtSegm->Copy();
|
||
NewTrack->Insert( frame->m_Pcb, PtSegm );
|
||
NewTrack->m_End = ptr_pad->m_Pos;
|
||
NewTrack->start = PtSegm;
|
||
NewTrack->end = ptr_pad;
|
||
nb_new_piste++;
|
||
NewTrack->Draw( frame->DrawPanel, DC, GR_OR );
|
||
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
|
||
}
|
||
}
|
||
}
|
||
|
||
ptr_pad = Locate_Pad_Connecte( frame->m_Pcb, PtSegm, END );
|
||
if( ptr_pad != NULL )
|
||
{ /* Test si point piste "en l'air" */
|
||
if( (PtSegm->m_End.x != ptr_pad->m_Pos.x)
|
||
|| (PtSegm->m_End.y != ptr_pad->m_Pos.y) )
|
||
{
|
||
if( Locate_Piste_Connectee( PtSegm, frame->m_Pcb->m_Track,
|
||
NULL, END ) == NULL )
|
||
{
|
||
TRACK* NewTrack = PtSegm->Copy();
|
||
NewTrack->Insert( frame->m_Pcb, PtSegm );
|
||
NewTrack->m_Start.x = ptr_pad->m_Pos.x;
|
||
NewTrack->m_Start.y = ptr_pad->m_Pos.y;
|
||
NewTrack->start = ptr_pad;
|
||
NewTrack->end = PtSegm;
|
||
nb_new_piste++;
|
||
|
||
msg.Printf( wxT( "e %d" ), nb_new_piste );
|
||
Affiche_1_Parametre( frame, POS_AFF_VAR, wxEmptyString, msg, a_color );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|