Commit 8a8377ff authored by dickelbeck's avatar dickelbeck

beautification, hit test improvements

parent ea6aba82
/*************************************************/
/* Routines de placement automatique des MODULES */
/*************************************************/
/*************************************************/
/* Routines de placement automatique des MODULES */
/*************************************************/
/* Fichier autoplac.cpp */
/* Fichier autoplac.cpp */
#include "fctsys.h"
#include "gr_basic.h"
......@@ -14,910 +14,971 @@
#include "protos.h"
/************************************************************/
/* Menu et Routines de placement automatique des composants */
/************************************************************/
/************************************************************/
/* Menu et Routines de placement automatique des composants */
/************************************************************/
#define GAIN 16
#define GAIN 16
#define PENALITE 500
/* Penalite pour orientation donnee par CntRot90 et CntRot180:
gradue de 0 ( rotation interdite ) a 10 ( rotation a cout null )
Le cout est ici donne en majoration
/* Penalite pour orientation donnee par CntRot90 et CntRot180:
* gradue de 0 ( rotation interdite ) a 10 ( rotation a cout null )
* Le cout est ici donne en majoration
*/
static float OrientPenality[11] = {
2.0, /* CntRot = 0 en fait rotation interdite */
1.9, /* CntRot = 1 */
1.8, /* CntRot = 2 */
1.7, /* CntRot = 3 */
1.6, /* CntRot = 4 */
1.5, /* CntRot = 5 */
1.4, /* CntRot = 5 */
1.3, /* CntRot = 7 */
1.2, /* CntRot = 8 */
1.1, /* CntRot = 9 */
1.0}; /* CntRot = 10 rotation autorisee, penalite nulle */
static const float OrientPenality[11] = {
2.0, /* CntRot = 0 en fait rotation interdite */
1.9, /* CntRot = 1 */
1.8, /* CntRot = 2 */
1.7, /* CntRot = 3 */
1.6, /* CntRot = 4 */
1.5, /* CntRot = 5 */
1.4, /* CntRot = 5 */
1.3, /* CntRot = 7 */
1.2, /* CntRot = 8 */
1.1, /* CntRot = 9 */
1.0 /* CntRot = 10 rotation autorisee, penalite nulle */
};
/* Etat d'une cellule */
#define OUT_OF_BOARD -2
#define OUT_OF_BOARD -2
#define OCCUPED_By_MODULE -1
/* variables locales */
static wxPoint CurrPosition; // position courante du module en cours de placement
static bool AutoPlaceShowAll = TRUE;
static wxPoint CurrPosition; // position courante du module en cours de placement
static bool AutoPlaceShowAll = TRUE;
float MinCout;
float MinCout;
/* Fonctions locales */
static int TstModuleOnBoard(BOARD * Pcb, MODULE * Module, bool TstOtherSide);
static void Build_PlacedPads_List(BOARD * Pcb);
static int Tri_PlaceModules(MODULE ** pt_ref, MODULE ** pt_compare);
static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
static void Build_PlacedPads_List( BOARD* Pcb );
static int Tri_PlaceModules( MODULE** pt_ref, MODULE** pt_compare );
static void TracePenaliteRectangle(BOARD * Pcb, int ux0, int uy0, int ux1, int uy1,
int marge, int Penalite, int masque_layer);
static MODULE * PickModule( WinEDA_PcbFrame * pcbframe, wxDC * DC );
static void TracePenaliteRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1,
int marge, int Penalite, int masque_layer );
static MODULE* PickModule( WinEDA_PcbFrame* pcbframe, wxDC* DC );
/* variables importees */
extern CHEVELU * local_liste_chevelu; // adresse de base du buffer des chevelus locaux
extern int nb_local_chevelu; // nbr de links du module en deplacement
extern CHEVELU* local_liste_chevelu; // adresse de base du buffer des chevelus locaux
extern int nb_local_chevelu; // nbr de links du module en deplacement
/********************************************************************************/
void WinEDA_PcbFrame::AutoPlaceModule(MODULE * Module, int place_mode, wxDC * DC)
void WinEDA_PcbFrame::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
/********************************************************************************/
/* Routine de Placement Automatique des composants dans le contour du PCB
Les composants ayant le status FIXE ne sont pas bouges
Si le menu appelant est le placement de 1 module, il sera replace
*/
* Les composants ayant le status FIXE ne sont pas bouges
* Si le menu appelant est le placement de 1 module, il sera replace
*/
{
int ii, activ;
MODULE * ThisModule = NULL;
MODULE ** BaseListeModules;
wxPoint PosOK;
wxPoint memopos;
int error;
int NbModules = 0;
int NbTotalModules = 0;
float Pas;
int lay_tmp_TOP, lay_tmp_BOTTOM, OldPasRoute;
if( m_Pcb->m_Modules == NULL ) return;
DrawPanel->m_AbortRequest = FALSE;
DrawPanel->m_AbortEnable = TRUE;
switch( place_mode )
{
case PLACE_1_MODULE:
ThisModule = Module;
if(ThisModule == NULL) return;
ThisModule->m_ModuleStatus &= ~(MODULE_is_PLACED|MODULE_to_PLACE);
break;
case PLACE_OUT_OF_BOARD:
break;
case PLACE_ALL:
if( ! IsOK(this, _("Footprints NOT LOCKED will be moved") ))
return;
break;
case PLACE_INCREMENTAL:
if( ! IsOK(this, _("Footprints NOT PLACED will be moved")) )
return;
break;
}
memopos = CurrPosition;
lay_tmp_BOTTOM = Route_Layer_BOTTOM;
lay_tmp_TOP = Route_Layer_TOP;
OldPasRoute = g_GridRoutingSize;
g_GridRoutingSize = m_CurrentScreen->GetGrid().x;
// Ensure g_GridRoutingSize has a reasonnable value:
if ( g_GridRoutingSize < 10 ) g_GridRoutingSize = 10; // Min value = 1/1000 inch
/* Compute module parmeters used in auto place */
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*)Module->Pnext) // remise a jour du rect d'encadrement
{
Module->Set_Rectangle_Encadrement();
Module->SetRectangleExinscrit();
}
/* Generation du plan de placement */
if( GenPlaceBoard() == 0) return;
/* Mise a jour des parametres modules utiles au placement */
BaseListeModules = GenListeModules(m_Pcb, &NbTotalModules );
MyFree(BaseListeModules);
/* Placement des modules fixes sur le plan de placement */
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*)Module->Pnext )
{
Module->m_ModuleStatus &= ~MODULE_to_PLACE;
switch( place_mode )
{
case PLACE_1_MODULE:
if( ThisModule == Module )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_OUT_OF_BOARD:
Module->m_ModuleStatus &= ~MODULE_is_PLACED;
if( Module->m_ModuleStatus & MODULE_is_LOCKED ) break;
if( ! m_Pcb->m_BoundaryBox.Inside(Module->m_Pos) )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_ALL:
Module->m_ModuleStatus &= ~MODULE_is_PLACED;
if( Module->m_ModuleStatus & MODULE_is_LOCKED ) break;
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_INCREMENTAL:
if( Module->m_ModuleStatus & MODULE_is_LOCKED )
{
Module->m_ModuleStatus &= ~MODULE_is_PLACED; break;
}
if( ! (Module->m_ModuleStatus & MODULE_is_PLACED) )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
}
if( Module->m_ModuleStatus & MODULE_to_PLACE ) // Erase from screen
{
NbModules++;
Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
}
else
{
GenModuleOnBoard(Module);
}
}
/* Placement des modules */
activ = 0; Pas = 100.0;
if( NbModules ) Pas = 100.0 / (float)NbModules;
while( (Module = PickModule(this, DC) ) != NULL )
{
float BestScore;
DisplayActivity((int)(activ * Pas) , wxEmptyString ); activ++;
/* Affichage du remplissage: surface de placement, obstacles, penalites */
DrawInfoPlace(DC);
/* Recherche du placement: orientation 0 */
error = RecherchePlacementModule(Module, DC);
BestScore = MinCout;
PosOK = CurrPosition;
if ( error == ESC ) goto end_of_tst;
/* Recherche du placement: orientation 180 */
ii = Module->m_CntRot180 & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 1800;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
Module->SetRectangleExinscrit();
error = RecherchePlacementModule(Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -1800;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
}
if ( error == ESC ) goto end_of_tst;
}
/* Recherche du placement: orientation 90 */
ii = Module->m_CntRot90 & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 900;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
error = RecherchePlacementModule(Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -900;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
}
if ( error == ESC ) goto end_of_tst;
}
/* Recherche du placement: orientation -90 (ou 270 degres) */
ii = (Module->m_CntRot90 >> 4 ) & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 2700;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
error = RecherchePlacementModule(Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -2700;
Rotate_Module(DC, Module, Angle_Rot_Module, FALSE);
}
if ( error == ESC ) goto end_of_tst;
}
int ii, activ;
MODULE* ThisModule = NULL;
MODULE** BaseListeModules;
wxPoint PosOK;
wxPoint memopos;
int error;
int NbModules = 0;
int NbTotalModules = 0;
float Pas;
int lay_tmp_TOP, lay_tmp_BOTTOM, OldPasRoute;
if( m_Pcb->m_Modules == NULL )
return;
DrawPanel->m_AbortRequest = FALSE;
DrawPanel->m_AbortEnable = TRUE;
switch( place_mode )
{
case PLACE_1_MODULE:
ThisModule = Module;
if( ThisModule == NULL )
return;
ThisModule->m_ModuleStatus &= ~(MODULE_is_PLACED | MODULE_to_PLACE);
break;
case PLACE_OUT_OF_BOARD:
break;
case PLACE_ALL:
if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) )
return;
break;
case PLACE_INCREMENTAL:
if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) )
return;
break;
}
memopos = CurrPosition;
lay_tmp_BOTTOM = Route_Layer_BOTTOM;
lay_tmp_TOP = Route_Layer_TOP;
OldPasRoute = g_GridRoutingSize;
g_GridRoutingSize = m_CurrentScreen->GetGrid().x;
// Ensure g_GridRoutingSize has a reasonnable value:
if( g_GridRoutingSize < 10 )
g_GridRoutingSize = 10; // Min value = 1/1000 inch
/* Compute module parmeters used in auto place */
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext ) // remise a jour du rect d'encadrement
{
Module->Set_Rectangle_Encadrement();
Module->SetRectangleExinscrit();
}
/* Generation du plan de placement */
if( GenPlaceBoard() == 0 )
return;
/* Mise a jour des parametres modules utiles au placement */
BaseListeModules = GenListeModules( m_Pcb, &NbTotalModules );
MyFree( BaseListeModules );
/* Placement des modules fixes sur le plan de placement */
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
Module->m_ModuleStatus &= ~MODULE_to_PLACE;
switch( place_mode )
{
case PLACE_1_MODULE:
if( ThisModule == Module )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_OUT_OF_BOARD:
Module->m_ModuleStatus &= ~MODULE_is_PLACED;
if( Module->m_ModuleStatus & MODULE_is_LOCKED )
break;
if( !m_Pcb->m_BoundaryBox.Inside( Module->m_Pos ) )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_ALL:
Module->m_ModuleStatus &= ~MODULE_is_PLACED;
if( Module->m_ModuleStatus & MODULE_is_LOCKED )
break;
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
case PLACE_INCREMENTAL:
if( Module->m_ModuleStatus & MODULE_is_LOCKED )
{
Module->m_ModuleStatus &= ~MODULE_is_PLACED; break;
}
if( !(Module->m_ModuleStatus & MODULE_is_PLACED) )
Module->m_ModuleStatus |= MODULE_to_PLACE;
break;
}
if( Module->m_ModuleStatus & MODULE_to_PLACE ) // Erase from screen
{
NbModules++;
Module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
}
else
{
GenModuleOnBoard( Module );
}
}
/* Placement des modules */
activ = 0; Pas = 100.0;
if( NbModules )
Pas = 100.0 / (float) NbModules;
while( ( Module = PickModule( this, DC ) ) != NULL )
{
float BestScore;
DisplayActivity( (int) (activ * Pas), wxEmptyString ); activ++;
/* Affichage du remplissage: surface de placement, obstacles, penalites */
DrawInfoPlace( DC );
/* Recherche du placement: orientation 0 */
error = RecherchePlacementModule( Module, DC );
BestScore = MinCout;
PosOK = CurrPosition;
if( error == ESC )
goto end_of_tst;
/* Recherche du placement: orientation 180 */
ii = Module->m_CntRot180 & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 1800;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
Module->SetRectangleExinscrit();
error = RecherchePlacementModule( Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -1800;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
}
if( error == ESC )
goto end_of_tst;
}
/* Recherche du placement: orientation 90 */
ii = Module->m_CntRot90 & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 900;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
error = RecherchePlacementModule( Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -900;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
}
if( error == ESC )
goto end_of_tst;
}
/* Recherche du placement: orientation -90 (ou 270 degres) */
ii = (Module->m_CntRot90 >> 4 ) & 0x0F;
if( ii != 0 )
{
int Angle_Rot_Module = 2700;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
error = RecherchePlacementModule( Module, DC );
MinCout *= OrientPenality[ii];
if( BestScore > MinCout ) /* Cette orientation est meilleure */
{
PosOK = CurrPosition;
BestScore = MinCout;
}
else
{
Angle_Rot_Module = -2700;
Rotate_Module( DC, Module, Angle_Rot_Module, FALSE );
}
if( error == ESC )
goto end_of_tst;
}
end_of_tst:
if ( error == ESC ) break;
/* placement du module */
CurrPosition = m_CurrentScreen->m_Curseur;
m_CurrentScreen->m_Curseur = PosOK;
Place_Module(Module, DC);
m_CurrentScreen->m_Curseur = CurrPosition;
if( error == ESC )
break;
Module->Set_Rectangle_Encadrement();
Module->SetRectangleExinscrit();
/* placement du module */
CurrPosition = m_CurrentScreen->m_Curseur;
m_CurrentScreen->m_Curseur = PosOK;
Place_Module( Module, DC );
m_CurrentScreen->m_Curseur = CurrPosition;
GenModuleOnBoard(Module);
Module->m_ModuleStatus |= MODULE_is_PLACED;
Module->m_ModuleStatus &= ~MODULE_to_PLACE;
}
Module->Set_Rectangle_Encadrement();
Module->SetRectangleExinscrit();
CurrPosition = memopos;
GenModuleOnBoard( Module );
Module->m_ModuleStatus |= MODULE_is_PLACED;
Module->m_ModuleStatus &= ~MODULE_to_PLACE;
}
/* Liberation de la memoire */
Board.UnInitBoard();
CurrPosition = memopos;
Route_Layer_TOP = lay_tmp_TOP;
Route_Layer_BOTTOM = lay_tmp_BOTTOM;
g_GridRoutingSize = OldPasRoute;
/* Liberation de la memoire */
Board.UnInitBoard();
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*)Module->Pnext )
{
Module->Set_Rectangle_Encadrement();
}
Route_Layer_TOP = lay_tmp_TOP;
Route_Layer_BOTTOM = lay_tmp_BOTTOM;
g_GridRoutingSize = OldPasRoute;
/* Recalcul de la liste des pads, detruite par les calculs precedents */
m_Pcb->m_Status_Pcb = 0; build_liste_pads();
Module = m_Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
Module->Set_Rectangle_Encadrement();
}
DrawPanel->ReDraw(DC, TRUE);
/* Recalcul de la liste des pads, detruite par les calculs precedents */
m_Pcb->m_Status_Pcb = 0; build_liste_pads();
DrawPanel->m_AbortEnable = FALSE;
DrawPanel->ReDraw( DC, TRUE );
DrawPanel->m_AbortEnable = FALSE;
}
/**********************************************/
void WinEDA_PcbFrame::DrawInfoPlace(wxDC * DC)
void WinEDA_PcbFrame::DrawInfoPlace( wxDC* DC )
/**********************************************/
/* Affiche a l'ecran les infos de placement
*/
*/
{
int color, ii, jj;
int ox, oy, top_state, bottom_state;
GRSetDrawMode(DC, GR_COPY);
for ( ii = 0; ii < Nrows; ii ++ )
{
oy = m_Pcb->m_BoundaryBox.m_Pos.y + (ii * g_GridRoutingSize);
for (jj = 0; jj < Ncols ; jj ++ )
{
ox = m_Pcb->m_BoundaryBox.m_Pos.x + (jj * g_GridRoutingSize);
/* surface de placement : */
color = BLACK;
top_state = GetCell(ii, jj , TOP);
bottom_state = GetCell(ii, jj , BOTTOM);
if( (top_state & CELL_is_ZONE) ) color = BLUE;
/* obstacles */
if( (top_state & CELL_is_EDGE) || (bottom_state & CELL_is_EDGE)) color = WHITE;
else if( top_state & (HOLE|CELL_is_MODULE) ) color = LIGHTRED;
else if( bottom_state & (HOLE|CELL_is_MODULE) ) color = LIGHTGREEN;
else /* Affichage du remplissage: Penalites */
{
if( GetDist(ii, jj , TOP ) || GetDist(ii, jj , BOTTOM ) )
color = DARKGRAY;
}
GRPutPixel(&DrawPanel->m_ClipBox, DC, ox, oy, color);
}
}
int color, ii, jj;
int ox, oy, top_state, bottom_state;
GRSetDrawMode( DC, GR_COPY );
for( ii = 0; ii < Nrows; ii++ )
{
oy = m_Pcb->m_BoundaryBox.m_Pos.y + (ii * g_GridRoutingSize);
for( jj = 0; jj < Ncols; jj++ )
{
ox = m_Pcb->m_BoundaryBox.m_Pos.x + (jj * g_GridRoutingSize);
/* surface de placement : */
color = BLACK;
top_state = GetCell( ii, jj, TOP );
bottom_state = GetCell( ii, jj, BOTTOM );
if( (top_state & CELL_is_ZONE) )
color = BLUE;
/* obstacles */
if( (top_state & CELL_is_EDGE) || (bottom_state & CELL_is_EDGE) )
color = WHITE;
else if( top_state & (HOLE | CELL_is_MODULE) )
color = LIGHTRED;
else if( bottom_state & (HOLE | CELL_is_MODULE) )
color = LIGHTGREEN;
else /* Affichage du remplissage: Penalites */
{
if( GetDist( ii, jj, TOP ) || GetDist( ii, jj, BOTTOM ) )
color = DARKGRAY;
}
GRPutPixel( &DrawPanel->m_ClipBox, DC, ox, oy, color );
}
}
}
/***************************************/
int WinEDA_PcbFrame::GenPlaceBoard(void)
int WinEDA_PcbFrame::GenPlaceBoard( void )
/***************************************/
/* Routine de generation du board ( cote composant + cote cuivre ) :
Alloue la memoire necessaire pour representer en "bitmap" sur la grille
courante:
- la surface de placement des composant ( le board )
- le bitmap des penalites
et initialise les cellules du board a
- HOLE pour les cellules occupees par un segment EDGE
- CELL_is_ZONE pour les cellules internes au contour EDGE (s'il est ferme)
la surface de placement (board) donne les cellules internes au contour
du pcb, et parmi celle-ci les cellules libres et les cellules deja occupees
le bitmap des penalites donnent les cellules occupes par les modules,
augmentes d'une surface de penalite liee au nombre de pads du module
le bitmap des penalites est mis a 0
l'occupation des cellules est laisse a 0
*/
* Alloue la memoire necessaire pour representer en "bitmap" sur la grille
* courante:
* - la surface de placement des composant ( le board )
* - le bitmap des penalites
* et initialise les cellules du board a
* - HOLE pour les cellules occupees par un segment EDGE
* - CELL_is_ZONE pour les cellules internes au contour EDGE (s'il est ferme)
*
* la surface de placement (board) donne les cellules internes au contour
* du pcb, et parmi celle-ci les cellules libres et les cellules deja occupees
*
* le bitmap des penalites donnent les cellules occupes par les modules,
* augmentes d'une surface de penalite liee au nombre de pads du module
*
* le bitmap des penalites est mis a 0
* l'occupation des cellules est laisse a 0
*/
{
int jj, ii;
int NbCells;
EDA_BaseStruct * PtStruct;
wxString msg;
Board.UnInitBoard();
if( ! SetBoardBoundaryBoxFromEdgesOnly() )
{
DisplayError(this, _("No edge PCB, Unknown board size!"), 30);
return(0);
}
/* The boundary box must have its start point on placing grid: */
m_Pcb->m_BoundaryBox.m_Pos.x -= m_Pcb->m_BoundaryBox.m_Pos.x % g_GridRoutingSize;
m_Pcb->m_BoundaryBox.m_Pos.y -= m_Pcb->m_BoundaryBox.m_Pos.y % g_GridRoutingSize;
/* The boundary box must have its end point on placing grid: */
wxPoint end = m_Pcb->m_BoundaryBox.GetEnd();
end.x -= end.x % g_GridRoutingSize; end.x += g_GridRoutingSize;
end.y -= end.y % g_GridRoutingSize; end.y += g_GridRoutingSize;
m_Pcb->m_BoundaryBox.SetEnd(end);
Nrows = m_Pcb->m_BoundaryBox.GetHeight() / g_GridRoutingSize;
Ncols = m_Pcb->m_BoundaryBox.GetWidth() / g_GridRoutingSize;
/* get a small margin for memory allocation: */
Ncols += 2; Nrows += 2;
NbCells = Ncols * Nrows;
MsgPanel->EraseMsgBox();
msg.Printf( wxT("%d"),Ncols);
Affiche_1_Parametre(this, 1, _("Cols"),msg,GREEN);
msg.Printf( wxT("%d"),Nrows);
Affiche_1_Parametre(this, 7, _("Lines"),msg,GREEN);
msg.Printf( wxT("%d"),NbCells);
Affiche_1_Parametre(this, 14, _("Cells."),msg,YELLOW);
/* Choix du nombre de faces de placement */
Nb_Sides = TWO_SIDES;
Affiche_1_Parametre(this, 22, wxT("S"), ( Nb_Sides == TWO_SIDES ) ? wxT("2") : wxT("1"), WHITE);
/* Creation du mapping du board */
Board.InitBoard();
/* Affichage de la memoire utilisee */
msg.Printf( wxT("%d"), Board.m_MemSize / 1024 );
Affiche_1_Parametre(this, 24, wxT("Mem(Ko)"),msg,CYAN);
Route_Layer_BOTTOM = CMP_N;
if( Nb_Sides == TWO_SIDES ) Route_Layer_BOTTOM = CUIVRE_N;
Route_Layer_TOP = CMP_N;
/* Place the edge layer segments */
PtStruct = m_Pcb->m_Drawings;
TRACK TmpSegm(NULL);
TmpSegm.m_Layer = -1;
TmpSegm.m_NetCode = -1;
TmpSegm.m_Width = g_GridRoutingSize/2;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
DRAWSEGMENT * DrawSegm;
switch( PtStruct->m_StructType)
{
case TYPEDRAWSEGMENT:
DrawSegm = (DRAWSEGMENT *) PtStruct;
if(DrawSegm->m_Layer != EDGE_N) break;
TmpSegm.m_Start = DrawSegm->m_Start;
TmpSegm.m_End = DrawSegm->m_End;
TmpSegm.m_Shape = DrawSegm->m_Shape;
TmpSegm.m_Param = DrawSegm->m_Angle;
TraceSegmentPcb(m_Pcb, &TmpSegm, HOLE|CELL_is_EDGE, g_GridRoutingSize, WRITE_CELL );
break;
case TYPETEXTE:
default: break;
}
}
/* Init du point d'accrochage de la zone */
OrCell(Nrows/2, Ncols/2, BOTTOM, CELL_is_ZONE);
/* Remplissage des cellules de la couche BOTTOM */
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT("%d"), jj++ );
Affiche_1_Parametre(this, 50, _("Loop"),msg,CYAN);
ii = Propagation(this);
}
/* Init de la couche TOP */
if( Board.m_BoardSide[TOP] )
memcpy( Board.m_BoardSide[TOP], Board.m_BoardSide[BOTTOM],NbCells * sizeof(BoardCell));
return(1);
int jj, ii;
int NbCells;
EDA_BaseStruct* PtStruct;
wxString msg;
Board.UnInitBoard();
if( !SetBoardBoundaryBoxFromEdgesOnly() )
{
DisplayError( this, _( "No edge PCB, Unknown board size!" ), 30 );
return 0;
}
/* The boundary box must have its start point on placing grid: */
m_Pcb->m_BoundaryBox.m_Pos.x -= m_Pcb->m_BoundaryBox.m_Pos.x % g_GridRoutingSize;
m_Pcb->m_BoundaryBox.m_Pos.y -= m_Pcb->m_BoundaryBox.m_Pos.y % g_GridRoutingSize;
/* The boundary box must have its end point on placing grid: */
wxPoint end = m_Pcb->m_BoundaryBox.GetEnd();
end.x -= end.x % g_GridRoutingSize; end.x += g_GridRoutingSize;
end.y -= end.y % g_GridRoutingSize; end.y += g_GridRoutingSize;
m_Pcb->m_BoundaryBox.SetEnd( end );
Nrows = m_Pcb->m_BoundaryBox.GetHeight() / g_GridRoutingSize;
Ncols = m_Pcb->m_BoundaryBox.GetWidth() / g_GridRoutingSize;
/* get a small margin for memory allocation: */
Ncols += 2; Nrows += 2;
NbCells = Ncols * Nrows;
MsgPanel->EraseMsgBox();
msg.Printf( wxT( "%d" ), Ncols );
Affiche_1_Parametre( this, 1, _( "Cols" ), msg, GREEN );
msg.Printf( wxT( "%d" ), Nrows );
Affiche_1_Parametre( this, 7, _( "Lines" ), msg, GREEN );
msg.Printf( wxT( "%d" ), NbCells );
Affiche_1_Parametre( this, 14, _( "Cells." ), msg, YELLOW );
/* Choix du nombre de faces de placement */
Nb_Sides = TWO_SIDES;
Affiche_1_Parametre( this, 22, wxT( "S" ), ( Nb_Sides == TWO_SIDES ) ? wxT( "2" ) : wxT(
"1" ), WHITE );
/* Creation du mapping du board */
Board.InitBoard();
/* Affichage de la memoire utilisee */
msg.Printf( wxT( "%d" ), Board.m_MemSize / 1024 );
Affiche_1_Parametre( this, 24, wxT( "Mem(Ko)" ), msg, CYAN );
Route_Layer_BOTTOM = CMP_N;
if( Nb_Sides == TWO_SIDES )
Route_Layer_BOTTOM = CUIVRE_N;
Route_Layer_TOP = CMP_N;
/* Place the edge layer segments */
PtStruct = m_Pcb->m_Drawings;
TRACK TmpSegm( NULL );
TmpSegm.m_Layer = -1;
TmpSegm.m_NetCode = -1;
TmpSegm.m_Width = g_GridRoutingSize / 2;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
DRAWSEGMENT* DrawSegm;
switch( PtStruct->m_StructType )
{
case TYPEDRAWSEGMENT:
DrawSegm = (DRAWSEGMENT*) PtStruct;
if( DrawSegm->m_Layer != EDGE_N )
break;
TmpSegm.m_Start = DrawSegm->m_Start;
TmpSegm.m_End = DrawSegm->m_End;
TmpSegm.m_Shape = DrawSegm->m_Shape;
TmpSegm.m_Param = DrawSegm->m_Angle;
TraceSegmentPcb( m_Pcb, &TmpSegm, HOLE | CELL_is_EDGE, g_GridRoutingSize, WRITE_CELL );
break;
case TYPETEXTE:
default:
break;
}
}
/* Init du point d'accrochage de la zone */
OrCell( Nrows / 2, Ncols / 2, BOTTOM, CELL_is_ZONE );
/* Remplissage des cellules de la couche BOTTOM */
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT( "%d" ), jj++ );
Affiche_1_Parametre( this, 50, _( "Loop" ), msg, CYAN );
ii = Propagation( this );
}
/* Init de la couche TOP */
if( Board.m_BoardSide[TOP] )
memcpy( Board.m_BoardSide[TOP], Board.m_BoardSide[BOTTOM], NbCells * sizeof(BoardCell) );
return 1;
}
/******************************************************/
void WinEDA_PcbFrame::GenModuleOnBoard(MODULE * Module)
void WinEDA_PcbFrame::GenModuleOnBoard( MODULE* Module )
/******************************************************/
/* initialise sur le board de placement les cellules correspondantes au
module Module
*/
* module Module
*/
{
int ox, oy, fx, fy, Penalite;
int marge = g_GridRoutingSize / 2;
int masque_layer;
D_PAD * Pad;
ox = Module->m_RealBoundaryBox.m_Pos.x - marge;
fx = Module->m_RealBoundaryBox.GetRight() + marge;
oy = Module->m_RealBoundaryBox.m_Pos.y - marge;
fy = Module->m_RealBoundaryBox.GetBottom() + marge;
if( ox < m_Pcb->m_BoundaryBox.m_Pos.x)
ox = m_Pcb->m_BoundaryBox.m_Pos.x;
if( ox > m_Pcb->m_BoundaryBox.GetRight())
ox = m_Pcb->m_BoundaryBox.GetRight();
if( fx < m_Pcb->m_BoundaryBox.m_Pos.x) fx = m_Pcb->m_BoundaryBox.m_Pos.x;
if( fx > m_Pcb->m_BoundaryBox.GetRight())
fx = m_Pcb->m_BoundaryBox.GetRight();
if( oy < m_Pcb->m_BoundaryBox.m_Pos.y) oy = m_Pcb->m_BoundaryBox.m_Pos.y;
if( oy > m_Pcb->m_BoundaryBox.GetBottom())
oy = m_Pcb->m_BoundaryBox.GetBottom();
if( fy < m_Pcb->m_BoundaryBox.m_Pos.y) fy = m_Pcb->m_BoundaryBox.m_Pos.y;
if( fy > m_Pcb->m_BoundaryBox.GetBottom())
fy = m_Pcb->m_BoundaryBox.GetBottom();
masque_layer = 0;
if( Module->m_Layer == CMP_N ) masque_layer = CMP_LAYER;
if( Module->m_Layer == CUIVRE_N ) masque_layer = CUIVRE_LAYER;
TraceFilledRectangle(m_Pcb, ox, oy, fx, fy, masque_layer,
CELL_is_MODULE, WRITE_OR_CELL);
/* Trace des pads et leur surface de securite */
marge = g_DesignSettings.m_TrackClearence + g_DesignSettings.m_CurrentTrackWidth;
for(Pad = Module->m_Pads ; Pad != NULL; Pad = (D_PAD *) Pad->Pnext )
{
Place_1_Pad_Board( m_Pcb, Pad, CELL_is_MODULE, marge, WRITE_OR_CELL);
}
/* Trace de la penalite */
marge = (g_GridRoutingSize * Module->m_PadNum ) / GAIN;
Penalite = PENALITE;
TracePenaliteRectangle(m_Pcb, ox, oy, fx, fy, marge, Penalite,
masque_layer);
int ox, oy, fx, fy, Penalite;
int marge = g_GridRoutingSize / 2;
int masque_layer;
D_PAD* Pad;
ox = Module->m_RealBoundaryBox.m_Pos.x - marge;
fx = Module->m_RealBoundaryBox.GetRight() + marge;
oy = Module->m_RealBoundaryBox.m_Pos.y - marge;
fy = Module->m_RealBoundaryBox.GetBottom() + marge;
if( ox < m_Pcb->m_BoundaryBox.m_Pos.x )
ox = m_Pcb->m_BoundaryBox.m_Pos.x;
if( ox > m_Pcb->m_BoundaryBox.GetRight() )
ox = m_Pcb->m_BoundaryBox.GetRight();
if( fx < m_Pcb->m_BoundaryBox.m_Pos.x )
fx = m_Pcb->m_BoundaryBox.m_Pos.x;
if( fx > m_Pcb->m_BoundaryBox.GetRight() )
fx = m_Pcb->m_BoundaryBox.GetRight();
if( oy < m_Pcb->m_BoundaryBox.m_Pos.y )
oy = m_Pcb->m_BoundaryBox.m_Pos.y;
if( oy > m_Pcb->m_BoundaryBox.GetBottom() )
oy = m_Pcb->m_BoundaryBox.GetBottom();
if( fy < m_Pcb->m_BoundaryBox.m_Pos.y )
fy = m_Pcb->m_BoundaryBox.m_Pos.y;
if( fy > m_Pcb->m_BoundaryBox.GetBottom() )
fy = m_Pcb->m_BoundaryBox.GetBottom();
masque_layer = 0;
if( Module->m_Layer == CMP_N )
masque_layer = CMP_LAYER;
if( Module->m_Layer == CUIVRE_N )
masque_layer = CUIVRE_LAYER;
TraceFilledRectangle( m_Pcb, ox, oy, fx, fy, masque_layer,
CELL_is_MODULE, WRITE_OR_CELL );
/* Trace des pads et leur surface de securite */
marge = g_DesignSettings.m_TrackClearence + g_DesignSettings.m_CurrentTrackWidth;
for( Pad = Module->m_Pads; Pad != NULL; Pad = (D_PAD*) Pad->Pnext )
{
Place_1_Pad_Board( m_Pcb, Pad, CELL_is_MODULE, marge, WRITE_OR_CELL );
}
/* Trace de la penalite */
marge = (g_GridRoutingSize * Module->m_PadNum ) / GAIN;
Penalite = PENALITE;
TracePenaliteRectangle( m_Pcb, ox, oy, fx, fy, marge, Penalite,
masque_layer );
}
/************************************************************************/
int WinEDA_PcbFrame::RecherchePlacementModule(MODULE * Module, wxDC * DC)
int WinEDA_PcbFrame::RecherchePlacementModule( MODULE* Module, wxDC* DC )
/************************************************************************/
/*
Routine Principale de recherche de la position optimale du module
Entree:
Module pointe la struct MODULE du module a placer.
Retourne:
1 si placement impossible, 0 si OK
et MinCout = variable externe = cout du meilleur placement
*/
* Routine Principale de recherche de la position optimale du module
* Entree:
* Module pointe la struct MODULE du module a placer.
* Retourne:
* 1 si placement impossible, 0 si OK
* et MinCout = variable externe = cout du meilleur placement
*/
{
int cx, cy;
int ox, oy, fx, fy; /* cadre d'occupation du module centre sur le curseur */
int error = 1;
int DisplayChevelu = 0;
wxPoint LastPosOK;
float mincout, cout, Score;
int Penalite;
bool TstOtherSide;
Module->Display_Infos(this);
Build_PlacedPads_List(m_Pcb);
LastPosOK.x = m_Pcb->m_BoundaryBox.m_Pos.x;
LastPosOK.y = m_Pcb->m_BoundaryBox.m_Pos.y;
cx = Module->m_Pos.x; cy = Module->m_Pos.y;
ox = Module->m_RealBoundaryBox.m_Pos.x - cx;
fx = Module->m_RealBoundaryBox.m_Size.x + ox;
oy = Module->m_RealBoundaryBox.m_Pos.y - cy;
fy = Module->m_RealBoundaryBox.m_Size.y + oy;
CurrPosition.x = m_Pcb->m_BoundaryBox.m_Pos.x - ox;
CurrPosition.y = m_Pcb->m_BoundaryBox.m_Pos.y - oy;
/* remise sur la grille de placement: */
CurrPosition.x -= CurrPosition.x % g_GridRoutingSize;
CurrPosition.y -= CurrPosition.y % g_GridRoutingSize;
g_Offset_Module.x = cx - CurrPosition.x;
g_Offset_Module.y = cy - CurrPosition.y;
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
/* tst des pastilles traversantes, qui pour un circuit imprime ayant des
composants des 2 cotes, peuvent tomber sur un composant de cote oppose:
s'il y a au moins 1 pastille apparaissant sur l'autre cote, ce cote
est teste */
TstOtherSide = FALSE;
if( Nb_Sides == TWO_SIDES )
{
D_PAD * Pad; int masque_otherlayer;
masque_otherlayer = CUIVRE_LAYER;
if ( Module->m_Layer == CUIVRE_N ) masque_otherlayer = CMP_LAYER;
for(Pad = Module->m_Pads ; Pad != NULL; Pad = (D_PAD *) Pad->Pnext )
{
if( (Pad->m_Masque_Layer & masque_otherlayer) == 0 ) continue;
TstOtherSide = TRUE;
break;
}
}
DrawModuleOutlines(DrawPanel, DC, Module);
mincout = -1.0;
Affiche_Message(wxT("Score ??, pos ??") );
for ( ; CurrPosition.x < m_Pcb->m_BoundaryBox.GetRight() - fx;
CurrPosition.x += g_GridRoutingSize )
{
wxYield();
if ( DrawPanel->m_AbortRequest )
{
if ( IsOK(this, _("Ok to abort ?")) ) return ESC;
else DrawPanel->m_AbortRequest = FALSE;
}
cx = Module->m_Pos.x; cy = Module->m_Pos.y;
Module->m_RealBoundaryBox.m_Pos.x = ox + CurrPosition.x;
Module->m_RealBoundaryBox.m_Pos.y = oy + CurrPosition.y;
DrawModuleOutlines(DrawPanel, DC, Module);
g_Offset_Module.x = cx - CurrPosition.x;
CurrPosition.y = m_Pcb->m_BoundaryBox.m_Pos.y - oy;
/* remise sur la grille de placement: */
CurrPosition.y -= CurrPosition.y % g_GridRoutingSize;
DrawModuleOutlines(DrawPanel, DC, Module);
for ( ; CurrPosition.y < m_Pcb->m_BoundaryBox.GetBottom() - fy;
CurrPosition.y += g_GridRoutingSize )
{
/* effacement des traces */
DrawModuleOutlines(DrawPanel, DC, Module);
if (DisplayChevelu) Compute_Ratsnest_PlaceModule(DC);
DisplayChevelu = 0;
Module->m_RealBoundaryBox.m_Pos.x = ox + CurrPosition.x;
Module->m_RealBoundaryBox.m_Pos.y = oy + CurrPosition.y;
g_Offset_Module.y = cy - CurrPosition.y;
DrawModuleOutlines(DrawPanel, DC, Module);
Penalite = TstModuleOnBoard(m_Pcb, Module, TstOtherSide );
if( Penalite >= 0 ) /* c a d si le module peut etre place */
{
error = 0;
build_ratsnest_module(DC, Module);
cout = Compute_Ratsnest_PlaceModule(DC);
DisplayChevelu = 1;
Score = cout + (float) Penalite;
if( (mincout >= Score ) || (mincout < 0 ) )
{
LastPosOK = CurrPosition;
mincout = Score;
wxString msg;
msg.Printf( wxT("Score %d, pos %3.4f, %3.4f"),
(int)mincout,
(float)LastPosOK.x /10000, (float)LastPosOK.y /10000);
Affiche_Message(msg);
}
}
if( DisplayChevelu ) Compute_Ratsnest_PlaceModule(DC);
DisplayChevelu = 0;
}
}
DrawModuleOutlines(DrawPanel, DC, Module); /* effacement du dernier trace */
if (DisplayChevelu) Compute_Ratsnest_PlaceModule(DC);
/* Regeneration des variables modifiees */
Module->m_RealBoundaryBox.m_Pos.x = ox + cx;
Module->m_RealBoundaryBox.m_Pos.y = oy + cy;
CurrPosition = LastPosOK;
m_Pcb->m_Status_Pcb &= ~(CHEVELU_LOCAL_OK | LISTE_PAD_OK );
MinCout = mincout;
return(error);
int cx, cy;
int ox, oy, fx, fy;/* cadre d'occupation du module centre sur le curseur */
int error = 1;
int DisplayChevelu = 0;
wxPoint LastPosOK;
float mincout, cout, Score;
int Penalite;
bool TstOtherSide;
Module->Display_Infos( this );
Build_PlacedPads_List( m_Pcb );
LastPosOK.x = m_Pcb->m_BoundaryBox.m_Pos.x;
LastPosOK.y = m_Pcb->m_BoundaryBox.m_Pos.y;
cx = Module->m_Pos.x; cy = Module->m_Pos.y;
ox = Module->m_RealBoundaryBox.m_Pos.x - cx;
fx = Module->m_RealBoundaryBox.m_Size.x + ox;
oy = Module->m_RealBoundaryBox.m_Pos.y - cy;
fy = Module->m_RealBoundaryBox.m_Size.y + oy;
CurrPosition.x = m_Pcb->m_BoundaryBox.m_Pos.x - ox;
CurrPosition.y = m_Pcb->m_BoundaryBox.m_Pos.y - oy;
/* remise sur la grille de placement: */
CurrPosition.x -= CurrPosition.x % g_GridRoutingSize;
CurrPosition.y -= CurrPosition.y % g_GridRoutingSize;
g_Offset_Module.x = cx - CurrPosition.x;
g_Offset_Module.y = cy - CurrPosition.y;
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
/* tst des pastilles traversantes, qui pour un circuit imprime ayant des
* composants des 2 cotes, peuvent tomber sur un composant de cote oppose:
* s'il y a au moins 1 pastille apparaissant sur l'autre cote, ce cote
* est teste */
TstOtherSide = FALSE;
if( Nb_Sides == TWO_SIDES )
{
D_PAD* Pad; int masque_otherlayer;
masque_otherlayer = CUIVRE_LAYER;
if( Module->m_Layer == CUIVRE_N )
masque_otherlayer = CMP_LAYER;
for( Pad = Module->m_Pads; Pad != NULL; Pad = (D_PAD*) Pad->Pnext )
{
if( (Pad->m_Masque_Layer & masque_otherlayer) == 0 )
continue;
TstOtherSide = TRUE;
break;
}
}
DrawModuleOutlines( DrawPanel, DC, Module );
mincout = -1.0;
Affiche_Message( wxT( "Score ??, pos ??" ) );
for( ; CurrPosition.x < m_Pcb->m_BoundaryBox.GetRight() - fx;
CurrPosition.x += g_GridRoutingSize )
{
wxYield();
if( DrawPanel->m_AbortRequest )
{
if( IsOK( this, _( "Ok to abort ?" ) ) )
return ESC;
else
DrawPanel->m_AbortRequest = FALSE;
}
cx = Module->m_Pos.x; cy = Module->m_Pos.y;
Module->m_RealBoundaryBox.m_Pos.x = ox + CurrPosition.x;
Module->m_RealBoundaryBox.m_Pos.y = oy + CurrPosition.y;
DrawModuleOutlines( DrawPanel, DC, Module );
g_Offset_Module.x = cx - CurrPosition.x;
CurrPosition.y = m_Pcb->m_BoundaryBox.m_Pos.y - oy;
/* remise sur la grille de placement: */
CurrPosition.y -= CurrPosition.y % g_GridRoutingSize;
DrawModuleOutlines( DrawPanel, DC, Module );
for( ; CurrPosition.y < m_Pcb->m_BoundaryBox.GetBottom() - fy;
CurrPosition.y += g_GridRoutingSize )
{
/* effacement des traces */
DrawModuleOutlines( DrawPanel, DC, Module );
if( DisplayChevelu )
Compute_Ratsnest_PlaceModule( DC );
DisplayChevelu = 0;
Module->m_RealBoundaryBox.m_Pos.x = ox + CurrPosition.x;
Module->m_RealBoundaryBox.m_Pos.y = oy + CurrPosition.y;
g_Offset_Module.y = cy - CurrPosition.y;
DrawModuleOutlines( DrawPanel, DC, Module );
Penalite = TstModuleOnBoard( m_Pcb, Module, TstOtherSide );
if( Penalite >= 0 ) /* c a d si le module peut etre place */
{
error = 0;
build_ratsnest_module( DC, Module );
cout = Compute_Ratsnest_PlaceModule( DC );
DisplayChevelu = 1;
Score = cout + (float) Penalite;
if( (mincout >= Score ) || (mincout < 0 ) )
{
LastPosOK = CurrPosition;
mincout = Score;
wxString msg;
msg.Printf( wxT( "Score %d, pos %3.4f, %3.4f" ),
(int) mincout,
(float) LastPosOK.x / 10000, (float) LastPosOK.y / 10000 );
Affiche_Message( msg );
}
}
if( DisplayChevelu )
Compute_Ratsnest_PlaceModule( DC );
DisplayChevelu = 0;
}
}
DrawModuleOutlines( DrawPanel, DC, Module ); /* effacement du dernier trace */
if( DisplayChevelu )
Compute_Ratsnest_PlaceModule( DC );
/* Regeneration des variables modifiees */
Module->m_RealBoundaryBox.m_Pos.x = ox + cx;
Module->m_RealBoundaryBox.m_Pos.y = oy + cy;
CurrPosition = LastPosOK;
m_Pcb->m_Status_Pcb &= ~(CHEVELU_LOCAL_OK | LISTE_PAD_OK );
MinCout = mincout;
return error;
}
/**************************************************************************/
int TstRectangle(BOARD * Pcb, int ux0, int uy0, int ux1, int uy1, int side)
int TstRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side )
/**************************************************************************/
/* tst si la surface rectangulaire (ux,y0 .. ux,y1):
- est sur une zone libre ( retourne OCCUPED_By_MODULE sinon)
- est sur la surface utile du board ( retourne OUT_OF_BOARD sinon)
retourne 0 si OK
*/
/* tst si la surface rectangulaire (ux,y0 .. ux,y1):
* - est sur une zone libre ( retourne OCCUPED_By_MODULE sinon)
* - est sur la surface utile du board ( retourne OUT_OF_BOARD sinon)
*
* retourne 0 si OK
*/
{
int row, col;
int row_min, row_max, col_min, col_max;
unsigned int data;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if (uy0 > row_min*g_GridRoutingSize ) row_min++;
col_min = ux0 / g_GridRoutingSize; if (ux0 > col_min*g_GridRoutingSize ) col_min++;
if( row_min < 0 ) row_min = 0;
if( row_max >= (Nrows-1)) row_max = Nrows-1;
if( col_min < 0 ) col_min = 0;
if( col_max >= (Ncols-1)) col_max = Ncols-1;
for( row = row_min ;row <= row_max ; row++)
{
for(col = col_min;col <= col_max; col++)
{
data = GetCell(row,col,side);
if( (data & CELL_is_ZONE) == 0 ) /* Cellule non autorisee */
return(OUT_OF_BOARD);
if( data & CELL_is_MODULE ) /* Deja utilisee */
return(OCCUPED_By_MODULE);
}
}
return( 0 );
int row, col;
int row_min, row_max, col_min, col_max;
unsigned int data;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if( uy0 > row_min * g_GridRoutingSize )
row_min++;
col_min = ux0 / g_GridRoutingSize; if( ux0 > col_min * g_GridRoutingSize )
col_min++;
if( row_min < 0 )
row_min = 0;
if( row_max >= (Nrows - 1) )
row_max = Nrows - 1;
if( col_min < 0 )
col_min = 0;
if( col_max >= (Ncols - 1) )
col_max = Ncols - 1;
for( row = row_min; row <= row_max; row++ )
{
for( col = col_min; col <= col_max; col++ )
{
data = GetCell( row, col, side );
if( (data & CELL_is_ZONE) == 0 ) /* Cellule non autorisee */
return OUT_OF_BOARD;
if( data & CELL_is_MODULE ) /* Deja utilisee */
return OCCUPED_By_MODULE;
}
}
return 0;
}
/******************************************************************************/
unsigned int CalculePenaliteRectangle(BOARD * Pcb, int ux0, int uy0,
int ux1, int uy1, int side)
unsigned int CalculePenaliteRectangle( BOARD* Pcb, int ux0, int uy0,
int ux1, int uy1, int side )
/******************************************************************************/
/* calcule et retourne la penalite de la surface rectangulaire (ux,y0 .. ux,y1):
( somme des valeurs des cellules du plan des Distances )
*/
* ( somme des valeurs des cellules du plan des Distances )
*/
{
int row, col;
int row_min, row_max, col_min, col_max;
unsigned int Penalite;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if (uy0 > row_min*g_GridRoutingSize ) row_min++;
col_min = ux0 / g_GridRoutingSize; if (ux0 > col_min*g_GridRoutingSize ) col_min++;
if( row_min < 0 ) row_min = 0;
if( row_max >= (Nrows-1)) row_max = Nrows-1;
if( col_min < 0 ) col_min = 0;
if( col_max >= (Ncols-1)) col_max = Ncols-1;
Penalite = 0;
for( row = row_min ;row <= row_max ; row++)
{
for(col = col_min;col <= col_max; col++)
{
Penalite += (int) GetDist(row, col, side );
}
}
return( Penalite );
int row, col;
int row_min, row_max, col_min, col_max;
unsigned int Penalite;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if( uy0 > row_min * g_GridRoutingSize )
row_min++;
col_min = ux0 / g_GridRoutingSize; if( ux0 > col_min * g_GridRoutingSize )
col_min++;
if( row_min < 0 )
row_min = 0;
if( row_max >= (Nrows - 1) )
row_max = Nrows - 1;
if( col_min < 0 )
col_min = 0;
if( col_max >= (Ncols - 1) )
col_max = Ncols - 1;
Penalite = 0;
for( row = row_min; row <= row_max; row++ )
{
for( col = col_min; col <= col_max; col++ )
{
Penalite += (int) GetDist( row, col, side );
}
}
return Penalite;
}
/**********************************************************************/
int TstModuleOnBoard(BOARD * Pcb, MODULE * Module, bool TstOtherSide)
int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide )
/**********************************************************************/
/* Teste si le module peut etre place sur le board.
retourne de diagnostic de TstRectangle().
le module est connu par son rectangle d'encadrement
*/
* retourne de diagnostic de TstRectangle().
* le module est connu par son rectangle d'encadrement
*/
{
int ox, oy, fx, fy;
int error, Penalite, marge, side, otherside;
side = TOP; otherside = BOTTOM;
if ( Module->m_Layer == CUIVRE_N )
{
side = BOTTOM; otherside = TOP;
}
ox = Module->m_RealBoundaryBox.m_Pos.x;
fx = Module->m_RealBoundaryBox.GetRight();
oy = Module->m_RealBoundaryBox.m_Pos.y;
fy = Module->m_RealBoundaryBox.GetBottom();
error = TstRectangle(Pcb, ox, oy, fx, fy, side );
if( error < 0 ) return (error);
if( TstOtherSide )
{
error = TstRectangle(Pcb, ox, oy, fx, fy, otherside );
if( error < 0 ) return (error);
}
marge = (g_GridRoutingSize * Module->m_PadNum ) / GAIN;
Penalite = CalculePenaliteRectangle(Pcb, ox - marge, oy - marge,
fx + marge, fy + marge, side );
return( Penalite );
int ox, oy, fx, fy;
int error, Penalite, marge, side, otherside;
side = TOP; otherside = BOTTOM;
if( Module->m_Layer == CUIVRE_N )
{
side = BOTTOM; otherside = TOP;
}
ox = Module->m_RealBoundaryBox.m_Pos.x;
fx = Module->m_RealBoundaryBox.GetRight();
oy = Module->m_RealBoundaryBox.m_Pos.y;
fy = Module->m_RealBoundaryBox.GetBottom();
error = TstRectangle( Pcb, ox, oy, fx, fy, side );
if( error < 0 )
return error;
if( TstOtherSide )
{
error = TstRectangle( Pcb, ox, oy, fx, fy, otherside );
if( error < 0 )
return error;
}
marge = (g_GridRoutingSize * Module->m_PadNum ) / GAIN;
Penalite = CalculePenaliteRectangle( Pcb, ox - marge, oy - marge,
fx + marge, fy + marge, side );
return Penalite;
}
/************************************************************/
float WinEDA_PcbFrame::Compute_Ratsnest_PlaceModule(wxDC * DC)
float WinEDA_PcbFrame::Compute_Ratsnest_PlaceModule( wxDC* DC )
/************************************************************/
/* Routine affichant le chevelu du module en cours de deplacement, et
evaluant le "cout" de la position.
Le cout est la longueur des chevelus en distance de manhattan, avec
penalite pour les inclinaisons se rapprochant de 45 degre
*/
* evaluant le "cout" de la position.
* Le cout est la longueur des chevelus en distance de manhattan, avec
* penalite pour les inclinaisons se rapprochant de 45 degre
*/
{
CHEVELU* pt_local_chevelu ;
int ii;
float cout, icout;
int ox, oy, fx, fy, dx , dy;
if((m_Pcb->m_Status_Pcb & CHEVELU_LOCAL_OK) == 0)
return(-1);
pt_local_chevelu = local_liste_chevelu;
ii = nb_local_chevelu; cout = 0;
while( ii-- > 0 )
{
if(pt_local_chevelu->status & LOCAL_CHEVELU)
{ // Non Affich
}
else
{
ox = pt_local_chevelu->pad_start->m_Pos.x - g_Offset_Module.x;
oy = pt_local_chevelu->pad_start->m_Pos.y - g_Offset_Module.y;
fx = pt_local_chevelu->pad_end->m_Pos.x;
fy = pt_local_chevelu->pad_end->m_Pos.y;
if ( AutoPlaceShowAll )
{
GRLine(&DrawPanel->m_ClipBox, DC, ox, oy, fx, fy,
0, g_DesignSettings.m_RatsnestColor|GR_XOR) ;
}
/* Evaluation du cout du chevelu: */
dx = fx - ox; dy = fy - oy;
dx = abs(dx); dy = abs( dy );
if( dx < dy ) EXCHG(dx,dy); /* dx >= dy */
/* cout de la distance: */
icout = (float) dx * dx;
/* cout de l'inclinaison */
icout += 3 * (float) dy * dy;
icout = sqrt(icout);
cout += icout; /* cout total = somme des couts de chaque chevelu */
}
pt_local_chevelu++;
}
return (cout);
CHEVELU* pt_local_chevelu;
int ii;
float cout, icout;
int ox, oy, fx, fy, dx, dy;
if( (m_Pcb->m_Status_Pcb & CHEVELU_LOCAL_OK) == 0 )
return -1;
pt_local_chevelu = local_liste_chevelu;
ii = nb_local_chevelu; cout = 0;
while( ii-- > 0 )
{
if( !(pt_local_chevelu->status & LOCAL_CHEVELU) )
{
ox = pt_local_chevelu->pad_start->m_Pos.x - g_Offset_Module.x;
oy = pt_local_chevelu->pad_start->m_Pos.y - g_Offset_Module.y;
fx = pt_local_chevelu->pad_end->m_Pos.x;
fy = pt_local_chevelu->pad_end->m_Pos.y;
if( AutoPlaceShowAll )
{
GRLine( &DrawPanel->m_ClipBox, DC, ox, oy, fx, fy,
0, g_DesignSettings.m_RatsnestColor | GR_XOR );
}
/* Evaluation du cout du chevelu: */
dx = fx - ox; dy = fy - oy;
dx = abs( dx ); dy = abs( dy );
if( dx < dy )
EXCHG( dx, dy );/* dx >= dy */
/* cout de la distance: */
icout = (float) dx * dx;
/* cout de l'inclinaison */
icout += 3 * (float) dy * dy;
icout = sqrt( icout );
cout += icout; /* cout total = somme des couts de chaque chevelu */
}
pt_local_chevelu++;
}
return cout;
}
/********************************************/
void Build_PlacedPads_List(BOARD * Pcb)
void Build_PlacedPads_List( BOARD* Pcb )
/********************************************/
/*
construction de la liste ( sous forme d'une liste de stucture )
des caract utiles des pads du PCB pour Placement Automatique )
Cette liste est restreinte a la liste des pads des modules deja places sur
la carte.
parametres:
adresse du buffer de classement = Pcb->ptr_pads;
Variables globales mise a jour:
pointeur ptr_pads (adr de classement de la liste des pads)
nb_pads = nombre utile de pastilles classes
m_Status_Pcb |= LISTE_PAD_OK
*/
* construction de la liste ( sous forme d'une liste de stucture )
* des caract utiles des pads du PCB pour Placement Automatique )
* Cette liste est restreinte a la liste des pads des modules deja places sur
* la carte.
*
* parametres:
* adresse du buffer de classement = Pcb->ptr_pads;
*
* Variables globales mise a jour:
* pointeur ptr_pads (adr de classement de la liste des pads)
* nb_pads = nombre utile de pastilles classes
* m_Status_Pcb |= LISTE_PAD_OK
*/
{
LISTE_PAD* pt_liste_pad;
MODULE * Module;
D_PAD * PtPad;
if( Pcb->m_Pads ) MyFree( Pcb->m_Pads );
pt_liste_pad = Pcb->m_Pads = NULL;
Pcb->m_NbPads = Pcb->m_NbNodes = 0;
/* Calcul du nombre de pads utiles */
Module = Pcb->m_Modules;
for( ; Module != NULL ; Module = (MODULE*) Module->Pnext)
{
if( Module->m_ModuleStatus & MODULE_to_PLACE ) continue;
PtPad = (D_PAD*) Module->m_Pads;
for(; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
Pcb->m_NbPads++;
}
}
/* Allocation memoire du buffer */
if ( Pcb->m_NbPads > 0)
{
pt_liste_pad = Pcb->m_Pads
= (D_PAD**) MyMalloc(Pcb->m_NbPads * sizeof(D_PAD*) );
}
/* Initialisation du buffer et des variables de travail */
Module = Pcb->m_Modules;
for( ;(Module != NULL) && (pt_liste_pad != NULL); Module = (MODULE*) Module->Pnext)
{
if( Module->m_ModuleStatus & MODULE_to_PLACE ) continue;
PtPad = (D_PAD*) Module->m_Pads;
for(; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
*pt_liste_pad = PtPad;
PtPad->m_physical_connexion = 0;
PtPad->m_logical_connexion = 0;
PtPad->m_Parent = Module;
if(PtPad->m_NetCode) Pcb->m_NbNodes++;
pt_liste_pad++;
}
}
Pcb->m_Status_Pcb |= LISTE_PAD_OK;
Pcb->m_Status_Pcb &= ~(LISTE_CHEVELU_OK | CHEVELU_LOCAL_OK);
adr_lowmem = buf_work;
LISTE_PAD* pt_liste_pad;
MODULE* Module;
D_PAD* PtPad;
if( Pcb->m_Pads )
MyFree( Pcb->m_Pads );
pt_liste_pad = Pcb->m_Pads = NULL;
Pcb->m_NbPads = Pcb->m_NbNodes = 0;
/* Calcul du nombre de pads utiles */
Module = Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
if( Module->m_ModuleStatus & MODULE_to_PLACE )
continue;
PtPad = (D_PAD*) Module->m_Pads;
for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
Pcb->m_NbPads++;
}
}
/* Allocation memoire du buffer */
if( Pcb->m_NbPads > 0 )
{
pt_liste_pad = Pcb->m_Pads
= (D_PAD**) MyMalloc( Pcb->m_NbPads * sizeof(D_PAD *) );
}
/* Initialisation du buffer et des variables de travail */
Module = Pcb->m_Modules;
for( ; (Module != NULL) && (pt_liste_pad != NULL); Module = (MODULE*) Module->Pnext )
{
if( Module->m_ModuleStatus & MODULE_to_PLACE )
continue;
PtPad = (D_PAD*) Module->m_Pads;
for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
{
*pt_liste_pad = PtPad;
PtPad->m_physical_connexion = 0;
PtPad->m_logical_connexion = 0;
PtPad->m_Parent = Module;
if( PtPad->m_NetCode )
Pcb->m_NbNodes++;
pt_liste_pad++;
}
}
Pcb->m_Status_Pcb |= LISTE_PAD_OK;
Pcb->m_Status_Pcb &= ~(LISTE_CHEVELU_OK | CHEVELU_LOCAL_OK);
adr_lowmem = buf_work;
}
......@@ -926,233 +987,255 @@ D_PAD * PtPad;
/*****************************************************************/
/* les cellules ( du plan des Distances ) du rectangle x0,y0 a x1,y1 sont
incrementees de la valeur Penalite
celles qui sont externes au rectangle, mais internes au rectangle
x0,y0 -marge a x1,y1 + marge sont incrementees d'une valeur
(Penalite ... 0) decroissante en fonction de leur eloignement
*/
static void TracePenaliteRectangle(BOARD * Pcb, int ux0, int uy0, int ux1, int uy1 ,
int marge, int Penalite, int masque_layer)
* incrementees de la valeur Penalite
* celles qui sont externes au rectangle, mais internes au rectangle
* x0,y0 -marge a x1,y1 + marge sont incrementees d'une valeur
* (Penalite ... 0) decroissante en fonction de leur eloignement
*/
static void TracePenaliteRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1,
int marge, int Penalite, int masque_layer )
{
int row, col;
int row_min, row_max, col_min, col_max, pmarge;
int trace = 0;
DistCell data, LocalPenalite;
int lgain, cgain;
if(masque_layer & g_TabOneLayerMask[Route_Layer_BOTTOM])
trace = 1; /* Trace sur BOTTOM */
if( (masque_layer & g_TabOneLayerMask[Route_Layer_TOP] ) && Nb_Sides)
trace |= 2; /* Trace sur TOP */
if(trace == 0) return;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
ux0 -= marge; ux1 += marge;
uy0 -= marge; uy1 += marge;
pmarge = marge / g_GridRoutingSize; if (pmarge < 1 ) pmarge = 1;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if (uy0 > row_min*g_GridRoutingSize ) row_min++;
col_min = ux0 / g_GridRoutingSize; if (ux0 > col_min*g_GridRoutingSize ) col_min++;
if( row_min < 0 ) row_min = 0;
if( row_max >= (Nrows-1)) row_max = Nrows-1;
if( col_min < 0 ) col_min = 0;
if( col_max >= (Ncols-1)) col_max = Ncols-1;
for( row = row_min ;row <= row_max ; row++)
{
lgain = 256;
if ( row < pmarge )
lgain = (256 * row) / pmarge;
else if( row > row_max - pmarge )
lgain = (256 * (row_max - row) ) / pmarge;
for(col = col_min;col <= col_max; col++)
{
cgain = 256;
LocalPenalite = Penalite;
if ( col < pmarge )
cgain = (256 * col) / pmarge;
else if( col > col_max - pmarge )
cgain = (256 * (col_max - col) ) / pmarge;
cgain = (cgain * lgain) / 256;
if( cgain != 256 ) LocalPenalite = (LocalPenalite * cgain) / 256;
if(trace & 1)
{
data = GetDist(row,col,BOTTOM) + LocalPenalite;
SetDist(row,col,BOTTOM, data);
}
if(trace & 2)
{
data = GetDist(row,col,TOP);
data = max( data, LocalPenalite);
SetDist(row,col,TOP, data);
}
}
}
int row, col;
int row_min, row_max, col_min, col_max, pmarge;
int trace = 0;
DistCell data, LocalPenalite;
int lgain, cgain;
if( masque_layer & g_TabOneLayerMask[Route_Layer_BOTTOM] )
trace = 1; /* Trace sur BOTTOM */
if( (masque_layer & g_TabOneLayerMask[Route_Layer_TOP] ) && Nb_Sides )
trace |= 2; /* Trace sur TOP */
if( trace == 0 )
return;
ux0 -= Pcb->m_BoundaryBox.m_Pos.x; uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
ux1 -= Pcb->m_BoundaryBox.m_Pos.x; uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
ux0 -= marge; ux1 += marge;
uy0 -= marge; uy1 += marge;
pmarge = marge / g_GridRoutingSize; if( pmarge < 1 )
pmarge = 1;
/* Calcul des coord limites des cellules appartenant au rectangle */
row_max = uy1 / g_GridRoutingSize;
col_max = ux1 / g_GridRoutingSize;
row_min = uy0 / g_GridRoutingSize; if( uy0 > row_min * g_GridRoutingSize )
row_min++;
col_min = ux0 / g_GridRoutingSize; if( ux0 > col_min * g_GridRoutingSize )
col_min++;
if( row_min < 0 )
row_min = 0;
if( row_max >= (Nrows - 1) )
row_max = Nrows - 1;
if( col_min < 0 )
col_min = 0;
if( col_max >= (Ncols - 1) )
col_max = Ncols - 1;
for( row = row_min; row <= row_max; row++ )
{
lgain = 256;
if( row < pmarge )
lgain = (256 * row) / pmarge;
else if( row > row_max - pmarge )
lgain = ( 256 * (row_max - row) ) / pmarge;
for( col = col_min; col <= col_max; col++ )
{
cgain = 256;
LocalPenalite = Penalite;
if( col < pmarge )
cgain = (256 * col) / pmarge;
else if( col > col_max - pmarge )
cgain = ( 256 * (col_max - col) ) / pmarge;
cgain = (cgain * lgain) / 256;
if( cgain != 256 )
LocalPenalite = (LocalPenalite * cgain) / 256;
if( trace & 1 )
{
data = GetDist( row, col, BOTTOM ) + LocalPenalite;
SetDist( row, col, BOTTOM, data );
}
if( trace & 2 )
{
data = GetDist( row, col, TOP );
data = max( data, LocalPenalite );
SetDist( row, col, TOP, data );
}
}
}
}
/***************************************************/
/* Routines de tri de modules, utilisee par qsort: */
/***************************************************/
static int Tri_PlaceModules(MODULE ** pt_ref, MODULE ** pt_compare)
/***************************************************/
/* Routines de tri de modules, utilisee par qsort: */
/***************************************************/
static int Tri_PlaceModules( MODULE** pt_ref, MODULE** pt_compare )
{
float ff, ff1, ff2 ;
ff1 = (*pt_ref)->m_Surface * (*pt_ref)->m_PadNum ;
ff2 = (*pt_compare)->m_Surface * (*pt_compare)->m_PadNum ;
ff = ff1 - ff2 ;
if( ff < 0 ) return(1) ;
if( ff > 0 ) return(-1) ;
return( 0 );
float ff, ff1, ff2;
ff1 = (*pt_ref)->m_Surface * (*pt_ref)->m_PadNum;
ff2 = (*pt_compare)->m_Surface * (*pt_compare)->m_PadNum;
ff = ff1 - ff2;
if( ff < 0 )
return 1;
if( ff > 0 )
return -1;
return 0;
}
static int Tri_RatsModules(MODULE ** pt_ref, MODULE ** pt_compare)
static int Tri_RatsModules( MODULE** pt_ref, MODULE** pt_compare )
{
float ff, ff1, ff2 ;
ff1 = (*pt_ref)->m_Surface * (*pt_ref)->flag;
ff2 = (*pt_compare)->m_Surface * (*pt_compare)->flag;
ff = ff1 - ff2 ;
if( ff < 0 ) return(1) ;
if( ff > 0 ) return(-1) ;
return( 0 );
float ff, ff1, ff2;
ff1 = (*pt_ref)->m_Surface * (*pt_ref)->flag;
ff2 = (*pt_compare)->m_Surface * (*pt_compare)->flag;
ff = ff1 - ff2;
if( ff < 0 )
return 1;
if( ff > 0 )
return -1;
return 0;
}
/***************************************************************/
static MODULE * PickModule(WinEDA_PcbFrame * pcbframe, wxDC * DC)
static MODULE* PickModule( WinEDA_PcbFrame* pcbframe, wxDC* DC )
/***************************************************************/
/* Recherche le "meilleur" module a placer
les criteres de choix sont:
- maximum de chevelus avec les modules deja places
- taille max, et nombre de pads max
*/
* les criteres de choix sont:
* - maximum de chevelus avec les modules deja places
* - taille max, et nombre de pads max
*/
{
MODULE ** BaseListeModules, ** pt_Dmod;
MODULE * Module = NULL, * AltModule = NULL;
CHEVELU* pt_local_chevelu;
int NbModules, ii;
BaseListeModules = GenListeModules(pcbframe->m_Pcb, &NbModules );
if( BaseListeModules == NULL ) return(NULL);
Build_PlacedPads_List(pcbframe->m_Pcb);
/* Tri par surface decroissante des modules
(on place les plus gros en 1er), surface ponderee par le nombre de pads */
qsort(BaseListeModules, NbModules, sizeof(MODULE**),
(int(*)(const void *, const void * ))Tri_PlaceModules);
for(pt_Dmod = BaseListeModules; *pt_Dmod != NULL; pt_Dmod++)
{
(*pt_Dmod)->flag = 0;
if( ! ((*pt_Dmod)->m_ModuleStatus & MODULE_to_PLACE) ) continue;
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
adr_lowmem = buf_work;
(*pt_Dmod)->Display_Infos(pcbframe);
pcbframe->build_ratsnest_module(DC, *pt_Dmod);
/* calcul du nombre de chevelus externes */
pt_local_chevelu = local_liste_chevelu;
ii = nb_local_chevelu;
while( ii-- > 0 )
{
if( (pt_local_chevelu->status & LOCAL_CHEVELU) == 0 )
(*pt_Dmod)->flag++;
pt_local_chevelu++;
}
}
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
qsort(BaseListeModules, NbModules, sizeof(MODULE**),
(int(*)(const void *, const void * ))Tri_RatsModules);
/* Recherche du "meilleur" module */
Module = NULL;
for(pt_Dmod = BaseListeModules; *pt_Dmod != NULL; pt_Dmod++)
{
if( ! ((*pt_Dmod)->m_ModuleStatus & MODULE_to_PLACE) ) continue;
AltModule = *pt_Dmod;
if( (*pt_Dmod)->flag == 0 ) continue;
Module = *pt_Dmod; break;
}
MyFree(BaseListeModules);
if ( Module ) return(Module);
else return(AltModule);
MODULE** BaseListeModules, ** pt_Dmod;
MODULE* Module = NULL, * AltModule = NULL;
CHEVELU* pt_local_chevelu;
int NbModules, ii;
BaseListeModules = GenListeModules( pcbframe->m_Pcb, &NbModules );
if( BaseListeModules == NULL )
return NULL;
Build_PlacedPads_List( pcbframe->m_Pcb );
/* Tri par surface decroissante des modules
* (on place les plus gros en 1er), surface ponderee par le nombre de pads */
qsort( BaseListeModules, NbModules, sizeof(MODULE * *),
( int (*)( const void*, const void* ) )Tri_PlaceModules );
for( pt_Dmod = BaseListeModules; *pt_Dmod != NULL; pt_Dmod++ )
{
(*pt_Dmod)->flag = 0;
if( !( (*pt_Dmod)->m_ModuleStatus & MODULE_to_PLACE ) )
continue;
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
adr_lowmem = buf_work;
(*pt_Dmod)->Display_Infos( pcbframe );
pcbframe->build_ratsnest_module( DC, *pt_Dmod );
/* calcul du nombre de chevelus externes */
pt_local_chevelu = local_liste_chevelu;
ii = nb_local_chevelu;
while( ii-- > 0 )
{
if( (pt_local_chevelu->status & LOCAL_CHEVELU) == 0 )
(*pt_Dmod)->flag++;
pt_local_chevelu++;
}
}
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
qsort( BaseListeModules, NbModules, sizeof(MODULE * *),
( int (*)( const void*, const void* ) )Tri_RatsModules );
/* Recherche du "meilleur" module */
Module = NULL;
for( pt_Dmod = BaseListeModules; *pt_Dmod != NULL; pt_Dmod++ )
{
if( !( (*pt_Dmod)->m_ModuleStatus & MODULE_to_PLACE ) )
continue;
AltModule = *pt_Dmod;
if( (*pt_Dmod)->flag == 0 )
continue;
Module = *pt_Dmod; break;
}
MyFree( BaseListeModules );
if( Module )
return Module;
else
return AltModule;
}
/*******************************************************/
bool WinEDA_PcbFrame::SetBoardBoundaryBoxFromEdgesOnly(void)
bool WinEDA_PcbFrame::SetBoardBoundaryBoxFromEdgesOnly( void )
/*******************************************************/
/* Determine le rectangle d'encadrement du pcb, selon les contours
(couche EDGE) uniquement
Sortie:
m_Pcb->m_BoundaryBox mis a jour
Retourne FALSE si pas de contour
*/
* (couche EDGE) uniquement
* Sortie:
* m_Pcb->m_BoundaryBox mis a jour
* Retourne FALSE si pas de contour
*/
{
int rayon, cx, cy, d;
int xmax, ymax;
EDA_BaseStruct * PtStruct;
DRAWSEGMENT* ptr;
bool succes = FALSE;
if (m_Pcb == NULL) return FALSE;
m_Pcb->m_BoundaryBox.m_Pos.x = m_Pcb->m_BoundaryBox.m_Pos.y = 0x7FFFFFFFl ;
xmax = ymax = -0x7FFFFFFFl ;
/* Analyse des Contours PCB */
PtStruct = m_Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
if( PtStruct->m_StructType != TYPEDRAWSEGMENT ) continue;
succes = TRUE;
ptr = (DRAWSEGMENT*) PtStruct;
d = (ptr->m_Width /2) + 1;
if(ptr->m_Shape == S_CIRCLE)
{
cx = ptr->m_Start.x; cy = ptr->m_Start.y;
rayon = (int)hypot((double)(ptr->m_End.x-cx),(double)(ptr->m_End.y-cy) );
rayon += d;
m_Pcb->m_BoundaryBox.m_Pos.x = min(m_Pcb->m_BoundaryBox.m_Pos.x,cx-rayon);
m_Pcb->m_BoundaryBox.m_Pos.y = min(m_Pcb->m_BoundaryBox.m_Pos.y,cy-rayon);
xmax = max(xmax,cx+rayon);
ymax = max(ymax,cy+rayon);
}
else
{
cx = min(ptr->m_Start.x, ptr->m_End.x );
cy = min(ptr->m_Start.y, ptr->m_End.y);
m_Pcb->m_BoundaryBox.m_Pos.x = min(m_Pcb->m_BoundaryBox.m_Pos.x,cx - d);
m_Pcb->m_BoundaryBox.m_Pos.y = min(m_Pcb->m_BoundaryBox.m_Pos.y,cy - d);
cx = max(ptr->m_Start.x, ptr->m_End.x );
cy = max(ptr->m_Start.y, ptr->m_End.y);
xmax = max(xmax,cx + d);
ymax = max(ymax,cy + d);
}
}
m_Pcb->m_BoundaryBox.SetWidth(xmax - m_Pcb->m_BoundaryBox.m_Pos.x);
m_Pcb->m_BoundaryBox.SetHeight(ymax - m_Pcb->m_BoundaryBox.m_Pos.y);
return(succes);
int rayon, cx, cy, d;
int xmax, ymax;
EDA_BaseStruct* PtStruct;
DRAWSEGMENT* ptr;
bool succes = FALSE;
if( m_Pcb == NULL )
return FALSE;
m_Pcb->m_BoundaryBox.m_Pos.x = m_Pcb->m_BoundaryBox.m_Pos.y = 0x7FFFFFFFl;
xmax = ymax = -0x7FFFFFFFl;
/* Analyse des Contours PCB */
PtStruct = m_Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
if( PtStruct->m_StructType != TYPEDRAWSEGMENT )
continue;
succes = TRUE;
ptr = (DRAWSEGMENT*) PtStruct;
d = (ptr->m_Width / 2) + 1;
if( ptr->m_Shape == S_CIRCLE )
{
cx = ptr->m_Start.x; cy = ptr->m_Start.y;
rayon = (int) hypot( (double) (ptr->m_End.x - cx), (double) (ptr->m_End.y - cy) );
rayon += d;
m_Pcb->m_BoundaryBox.m_Pos.x = min( m_Pcb->m_BoundaryBox.m_Pos.x, cx - rayon );
m_Pcb->m_BoundaryBox.m_Pos.y = min( m_Pcb->m_BoundaryBox.m_Pos.y, cy - rayon );
xmax = max( xmax, cx + rayon );
ymax = max( ymax, cy + rayon );
}
else
{
cx = min( ptr->m_Start.x, ptr->m_End.x );
cy = min( ptr->m_Start.y, ptr->m_End.y );
m_Pcb->m_BoundaryBox.m_Pos.x = min( m_Pcb->m_BoundaryBox.m_Pos.x, cx - d );
m_Pcb->m_BoundaryBox.m_Pos.y = min( m_Pcb->m_BoundaryBox.m_Pos.y, cy - d );
cx = max( ptr->m_Start.x, ptr->m_End.x );
cy = max( ptr->m_Start.y, ptr->m_End.y );
xmax = max( xmax, cx + d );
ymax = max( ymax, cy + d );
}
}
m_Pcb->m_BoundaryBox.SetWidth( xmax - m_Pcb->m_BoundaryBox.m_Pos.x );
m_Pcb->m_BoundaryBox.SetHeight( ymax - m_Pcb->m_BoundaryBox.m_Pos.y );
return succes;
}
......@@ -332,9 +332,10 @@ EDA_BaseStruct* BOARD::FindPadOrModule( const wxPoint& refPos, int layer )
public:
EDA_BaseStruct* found;
int layer;
int layer_mask;
PadOrModule( int alayer ) :
found(0), layer(alayer)
found(0), layer(alayer), layer_mask( g_TabOneLayerMask[alayer] )
{}
SEARCH_RESULT Inspect( EDA_BaseStruct* testItem, const void* testData )
......@@ -343,23 +344,33 @@ EDA_BaseStruct* BOARD::FindPadOrModule( const wxPoint& refPos, int layer )
if( testItem->m_StructType == TYPEPAD )
{
if( testItem->HitTest( refPos ) )
D_PAD* pad = (D_PAD*) testItem;
if( pad->HitTest( refPos ) )
{
found = testItem;
return SEARCH_QUIT;
if( layer_mask & pad->m_Masque_Layer )
{
found = testItem;
return SEARCH_QUIT;
}
else if( !found )
{
MODULE* parent = (MODULE*) pad->m_Parent;
if( IsModuleLayerVisible( parent->m_Layer ) )
found = testItem;
}
}
}
else if( testItem->m_StructType == TYPEMODULE )
{
int mlayer = ((MODULE*)testItem)->m_Layer;
MODULE* module = (MODULE*) testItem;
// consider only visible modules
if( IsModuleLayerVisible( mlayer ) )
if( IsModuleLayerVisible( module->m_Layer ) )
{
if( testItem->HitTest( refPos ) )
if( module->HitTest( refPos ) )
{
if( layer == mlayer )
if( layer == module->m_Layer )
{
found = testItem;
return SEARCH_QUIT;
......
......@@ -27,11 +27,13 @@
D_PAD::D_PAD( MODULE* parent ) : EDA_BaseStruct( parent, TYPEPAD )
{
m_NumPadName = 0;
m_Masque_Layer = CUIVRE_LAYER;
m_NetCode = 0; /* Numero de net pour comparaisons rapides */
m_DrillShape = CIRCLE; // Drill shape = circle
m_NumPadName = 0;
m_Masque_Layer = CUIVRE_LAYER;
m_NetCode = 0; /* Numero de net pour comparaisons rapides */
m_DrillShape = CIRCLE; // Drill shape = circle
m_Size.x = m_Size.y = 500;
if( m_Parent && (m_Parent->m_StructType == TYPEMODULE) )
{
m_Pos = ( (MODULE*) m_Parent )->m_Pos;
......@@ -91,7 +93,8 @@ const wxPoint D_PAD::ReturnShapePos( void )
wxPoint shape_pos;
int dX, dY;
dX = m_Offset.x; dY = m_Offset.y;
dX = m_Offset.x;
dY = m_Offset.y;
RotatePoint( &dX, &dY, m_Orient );
......@@ -458,12 +461,13 @@ void D_PAD::Draw( WinEDA_DrawPanel* panel, wxDC* DC, const wxPoint& offset, int
GRClosedPoly( &panel->m_ClipBox, DC, 4, (int*) coord, 0, color, color );
}
}
break;
default:
break;
}
}
/* Draw the pad hole */
int cx0 = m_Pos.x - offset.x;
......
/******************************************************/
/* editeur de PCB PCBNEW */
/* Fonctions de Nettoyage et reorganisation de Pistes */
/******************************************************/
/******************************************************/
/* editeur de PCB PCBNEW */
/* Fonctions de Nettoyage et reorganisation de Pistes */
/******************************************************/
/* Fichier CLEAN.CPP */
/* Fichier CLEAN.CPP */
#include "fctsys.h"
#include "gr_basic.h"
......@@ -15,21 +15,21 @@
#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 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 );
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 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;
......@@ -39,844 +39,916 @@ static bool s_ConnectToPads = false;
#define CONN2PAD_ENBL
#ifdef CONN2PAD_ENBL
static void ConnectDanglingEndToPad(WinEDA_PcbFrame * frame, wxDC * DC);
static void Gen_Raccord_Track(WinEDA_PcbFrame * frame, wxDC * DC);
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)
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)
*/
* 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);
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 )
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 coordonnes 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;
}
}
}
frame->MsgPanel->EraseMsgBox();
frame->m_Pcb->GetNumSegmTrack(); /* Met a jour le compte */
/* construction de la liste des coordonn�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);
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 */
/* 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 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);
/* 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->Compile_Ratsnest( DC, AFFICHE );
frame->m_CurrentScreen->SetModify();
frame->m_CurrentScreen->SetModify();
}
/*****************************************************************************/
static void suppression_piste_non_connectee(WinEDA_PcbFrame * frame, wxDC * DC)
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
*/
* 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;
}
}
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)
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) ;
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)
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
*/
* 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 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)
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
*/
* 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);
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)
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
*/
* 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;
}
}
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)
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
*/
* 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);
}
}
}
}
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
......@@ -336,9 +336,11 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
bool keep_on_grid = TRUE;
if( m_ID_current_state == ID_PCB_DELETE_ITEM_BUTT )
keep_on_grid = FALSE;
/* Cursor is left off grid if no block in progress and no moving object */
if( GetScreen()->BlockLocate.m_State != STATE_NO_BLOCK )
keep_on_grid = TRUE;
EDA_BaseStruct* DrawStruct = GetScreen()->m_CurrentItem;
if( DrawStruct && DrawStruct->m_Flags )
keep_on_grid = TRUE;
......
......@@ -35,7 +35,8 @@ void WinEDA_PcbFrame::InstallFindFrame( const wxPoint& pos, wxDC* DC )
{
WinEDA_PcbFindFrame* frame = new WinEDA_PcbFindFrame( this, DC, pos );
frame->ShowModal(); frame->Destroy();
frame->ShowModal();
frame->Destroy();
}
......
/****************************************************/
/* Gestion des composants specifiques aux microndes */
/* Generation d'une self */
/****************************************************/
/****************************************************/
/* Gestion des composants specifiques aux microndes */
/* Generation d'une self */
/****************************************************/
/* Fichier GEN_SELF.H */
/* Fichier GEN_SELF.H */
/* Fonctions locales */
static void Exit_Self(WinEDA_DrawPanel * Panel, wxDC *DC);
static EDGE_MODULE * gen_arc(EDGE_MODULE * PtSegm, int cX, int cY, int angle);
static void ShowCadreSelf(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Exit_Self( WinEDA_DrawPanel* Panel, wxDC* DC );
static EDGE_MODULE* gen_arc( EDGE_MODULE* PtSegm, int cX, int cY, int angle );
static void ShowCadreSelf( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
/* structures locales */
class SELFPCB // Definition d'une self constituee par une piste
class SELFPCB // Definition d'une self constituee par une piste
{
public:
int forme; // Serpentin, spirale ..
int orient; // 0..3600
int valeur; // Valeur de la self
wxPoint m_Start;
wxPoint m_End; // Coord du point de depart et d'arrivee
wxSize m_Size;
D_PAD * pt_pad_start, *pt_pad_end; // Pointeurs sur les pads d'extremite
int lng; // Longueur de la piste constituant la self
int m_Width; // m_Size.xur de la piste
int nbrin; // Parametres de calcul: nombre de brins
int lbrin; // longueur du brin
int rayon; // Rayon des raccords entre brins
int delta; // distance aux pads
int forme; // Serpentin, spirale ..
int orient; // 0..3600
int valeur; // Valeur de la self
wxPoint m_Start;
wxPoint m_End; // Coord du point de depart et d'arrivee
wxSize m_Size;
D_PAD* pt_pad_start, * pt_pad_end; // Pointeurs sur les pads d'extremite
int lng; // Longueur de la piste constituant la self
int m_Width; // m_Size.xur de la piste
int nbrin; // Parametres de calcul: nombre de brins
int lbrin; // longueur du brin
int rayon; // Rayon des raccords entre brins
int delta; // distance aux pads
};
/* Variables locales */
static SELFPCB Mself;
static int Self_On;
static int Bl_X0, Bl_Y0 , Bl_Xf, Bl_Yf; // Coord du cadre insrcivant la self
static int Self_On;
static int Bl_X0, Bl_Y0, Bl_Xf, Bl_Yf; // Coord du cadre insrcivant la self
/*************************************************************************/
static void ShowCadreSelf(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
static void ShowCadreSelf( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/*************************************************************************/
/* Routine d'affichage a l'ecran du cadre de la self */
{
int deltaX, deltaY;
/* Calcul de l'orientation et de la taille de la fenetre:
- orient = vert ou Horiz ( dimension max)
- Size.x = Size.y / 2
*/
GRSetDrawMode(DC, GR_XOR);
if( erase)/* effacement du cadre */
{
GRRect( & panel->m_ClipBox, DC, Bl_X0, Bl_Y0, Bl_Xf, Bl_Yf, YELLOW);
}
deltaX = (panel->GetScreen()->m_Curseur.x - Mself.m_Start.x) / 4;
deltaY = (panel->GetScreen()->m_Curseur.y - Mself.m_Start.y) / 4;
Mself.orient = 900;
if( abs(deltaX) > abs(deltaY) ) Mself.orient = 0;
if(Mself.orient == 0)
{
Bl_X0 = Mself.m_Start.x;
Bl_Y0 = Mself.m_Start.y - deltaX;
Bl_Xf = panel->GetScreen()->m_Curseur.x;
Bl_Yf = Mself.m_Start.y + deltaX;
}
else
{
Bl_X0 = Mself.m_Start.x - deltaY;
Bl_Y0 = Mself.m_Start.y;
Bl_Xf = Mself.m_Start.x + deltaY;
Bl_Yf = panel->GetScreen()->m_Curseur.y;
}
GRRect( & panel->m_ClipBox, DC, Bl_X0, Bl_Y0, Bl_Xf, Bl_Yf,YELLOW);
int deltaX, deltaY;
/* Calcul de l'orientation et de la taille de la fenetre:
* - orient = vert ou Horiz ( dimension max)
* - Size.x = Size.y / 2
*/
GRSetDrawMode( DC, GR_XOR );
if( erase )/* effacement du cadre */
{
GRRect( &panel->m_ClipBox, DC, Bl_X0, Bl_Y0, Bl_Xf, Bl_Yf, YELLOW );
}
deltaX = (panel->GetScreen()->m_Curseur.x - Mself.m_Start.x) / 4;
deltaY = (panel->GetScreen()->m_Curseur.y - Mself.m_Start.y) / 4;
Mself.orient = 900;
if( abs( deltaX ) > abs( deltaY ) )
Mself.orient = 0;
if( Mself.orient == 0 )
{
Bl_X0 = Mself.m_Start.x;
Bl_Y0 = Mself.m_Start.y - deltaX;
Bl_Xf = panel->GetScreen()->m_Curseur.x;
Bl_Yf = Mself.m_Start.y + deltaX;
}
else
{
Bl_X0 = Mself.m_Start.x - deltaY;
Bl_Y0 = Mself.m_Start.y;
Bl_Xf = Mself.m_Start.x + deltaY;
Bl_Yf = panel->GetScreen()->m_Curseur.y;
}
GRRect( &panel->m_ClipBox, DC, Bl_X0, Bl_Y0, Bl_Xf, Bl_Yf, YELLOW );
}
/*************************************************/
void Exit_Self(WinEDA_DrawPanel * Panel, wxDC *DC)
void Exit_Self( WinEDA_DrawPanel* Panel, wxDC* DC )
/*************************************************/
/* Routine de fermeture de l'application : ferme les commandes en cours */
{
if(Self_On)
{
Self_On = 0;
Panel->ManageCurseur(Panel, DC, 0); /* efface cadre */
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
}
if( Self_On )
{
Self_On = 0;
Panel->ManageCurseur( Panel, DC, 0 ); /* efface cadre */
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
}
}
/*******************************************/
void WinEDA_PcbFrame::Begin_Self( wxDC *DC)
void WinEDA_PcbFrame::Begin_Self( wxDC* DC )
/*******************************************/
/*
Routine d'initialisation d'un trace de self
*/
* Routine d'initialisation d'un trace de self
*/
{
if( Self_On )
{
Genere_Self( DC );
return;
}
if ( Self_On )
{
Genere_Self(DC);
return;
}
Mself.m_Start = GetScreen()->m_Curseur;
Mself.m_Start = GetScreen()->m_Curseur;
Self_On = 1;
Self_On = 1;
/* Mise a jour de l'origine des coord relatives */
GetScreen()->m_O_Curseur = GetScreen()->m_Curseur;
Affiche_Status_Box();
/* Mise a jour de l'origine des coord relatives */
GetScreen()->m_O_Curseur = GetScreen()->m_Curseur;
Affiche_Status_Box();
Bl_X0 = Mself.m_Start.x; Bl_Y0 = Mself.m_Start.y;
Bl_Xf = Bl_X0; Bl_Yf = Bl_Y0;
Bl_X0 = Mself.m_Start.x; Bl_Y0 = Mself.m_Start.y;
Bl_Xf = Bl_X0; Bl_Yf = Bl_Y0;
DrawPanel->ManageCurseur = ShowCadreSelf;
DrawPanel->ForceCloseManageCurseur = Exit_Self;
DrawPanel->ManageCurseur(DrawPanel, DC, 0); /* Affiche cadre */
DrawPanel->ManageCurseur = ShowCadreSelf;
DrawPanel->ForceCloseManageCurseur = Exit_Self;
DrawPanel->ManageCurseur( DrawPanel, DC, 0 ); /* Affiche cadre */
}
/**********************************************/
MODULE * WinEDA_PcbFrame::Genere_Self( wxDC *DC)
MODULE* WinEDA_PcbFrame::Genere_Self( wxDC* DC )
/**********************************************/
/* Genere une self en forme de serpentin
- longueur Mself.lng
- Extremites Mself.m_Start et Mself.m_End
- Contrainte: m_Start.x = m_End.x ( self verticale )
ou m_Start.y = m_End.y ( self horizontale )
On doit determiner:
Mself.nbrin = nombre de segments perpendiculaires a la direction
( le serpention aura nbrin + 1 demicercles + 2 1/4 de cercle)
Mself.lbrin = longueur d'un brin
Mself.rayon = rayon des parties arrondies du serpentin
Mself.delta = segments raccord entre extremites et le serpention lui meme
Les equations sont
Mself.m_Size.x = 2*Mself.rayon + Mself.lbrin
Mself.m_Size.y = 2*Mself.delta + 2*Mself.nbrin*Mself.rayon
Mself.lng = 2*Mself.delta // Raccords au serpentin
+ (Mself.nbrin-2) * Mself.lbrin //longueur des brins sauf 1er et dernier
+ (Mself.nbrin+1) * ( PI * Mself.rayon) // longueur des arrondis
+ Mself.lbrin/2 - Melf.rayon*2) // longueur du 1er et dernier brin
Les contraintes sont:
nbrin >= 2
Mself.rayon < Mself.m_Size.x
Mself.m_Size.y = Mself.rayon*4 + 2*Mself.raccord
Mself.lbrin > Mself.rayon *2
Le calcul est conduit de la facon suivante:
Initialement:
nbrin = 2
rayon = 4 * m_Size.x (valeur fixe arbitraire)
puis:
on augmente le nombre de brins jusqu'a la longueur desiree
( le rayon est diminue si necessaire )
*/
* - longueur Mself.lng
* - Extremites Mself.m_Start et Mself.m_End
* - Contrainte: m_Start.x = m_End.x ( self verticale )
* ou m_Start.y = m_End.y ( self horizontale )
*
* On doit determiner:
* Mself.nbrin = nombre de segments perpendiculaires a la direction
* ( le serpention aura nbrin + 1 demicercles + 2 1/4 de cercle)
* Mself.lbrin = longueur d'un brin
* Mself.rayon = rayon des parties arrondies du serpentin
* Mself.delta = segments raccord entre extremites et le serpention lui meme
*
* Les equations sont
* Mself.m_Size.x = 2*Mself.rayon + Mself.lbrin
* Mself.m_Size.y = 2*Mself.delta + 2*Mself.nbrin*Mself.rayon
* Mself.lng = 2*Mself.delta // Raccords au serpentin
+ (Mself.nbrin-2) * Mself.lbrin //longueur des brins sauf 1er et dernier
+ (Mself.nbrin+1) * ( PI * Mself.rayon) // longueur des arrondis
+ Mself.lbrin/2 - Melf.rayon*2) // longueur du 1er et dernier brin
*
* Les contraintes sont:
* nbrin >= 2
* Mself.rayon < Mself.m_Size.x
* Mself.m_Size.y = Mself.rayon*4 + 2*Mself.raccord
* Mself.lbrin > Mself.rayon *2
*
* Le calcul est conduit de la facon suivante:
* Initialement:
* nbrin = 2
* rayon = 4 * m_Size.x (valeur fixe arbitraire)
* puis:
* on augmente le nombre de brins jusqu'a la longueur desiree
* ( le rayon est diminue si necessaire )
*
*/
{
EDGE_MODULE * PtSegm, * LastSegm, *FirstSegm, * newedge;
MODULE * Module;
D_PAD * PtPad;
int ii, ll, lextbrin;
float fcoeff;
bool abort = FALSE;
wxString msg;
DrawPanel->ManageCurseur(DrawPanel, DC, FALSE); /* efface cadre */
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
if(Self_On == 0)
{
DisplayError(this, wxT("Starting point not init..")); return NULL;
}
Self_On = 0;
Mself.m_End = m_CurrentScreen->m_Curseur;
/* Agencement des parametres pour simplifier le calcul : */
/* le point de depart doit avoir la coord depart < celle du point de fin */
if(Mself.orient == 0) // Self horizontale
{
Mself.m_End.y = Mself.m_Start.y;
if(Mself.m_Start.x > Mself.m_End.x) EXCHG(Mself.m_Start.x,Mself.m_End.x);
Mself.m_Size.y = Mself.m_End.x - Mself.m_Start.x;
Mself.lng = Mself.m_Size.y;
}
else // Self verticale
{
Mself.m_End.x = Mself.m_Start.x;
if(Mself.m_Start.y > Mself.m_End.y) EXCHG(Mself.m_Start.y,Mself.m_End.y);
Mself.m_Size.y = Mself.m_End.y - Mself.m_Start.y;
Mself.lng = Mself.m_Size.y;
}
/* Entree de la vraie longueur desiree */
if( ! g_UnitMetric )
{
fcoeff = 10000.0 ;
msg.Printf( wxT("%1.4f"), Mself.lng /fcoeff);
abort = Get_Message(_("Length(inch):"),msg, this);
}
else
{
fcoeff = 10000.0/25.4 ;
msg.Printf( wxT("%2.3f"), Mself.lng /fcoeff);
abort = Get_Message( _("Length(mm):"),msg, this);
}
if ( abort ) return NULL;
double fval;
if ( ! msg.ToDouble(&fval) )
{
DisplayError(this, _("Incorrect number, abort"));
return NULL;
}
Mself.lng = (int) round( fval * fcoeff );
/* Controle des valeurs ( ii = valeur minimale de la longueur */
if( Mself.lng < Mself.m_Size.y )
{
DisplayError(this, _("Requested length < minimum length"));
return NULL;
}
/* Generation du composant: calcul des elements de la self */
Mself.m_Width = g_DesignSettings.m_CurrentTrackWidth;
Mself.m_Size.x = Mself.m_Size.y / 2 ;
// Choix d'une Valeur de depart raisonnable pour le rayon des arcs de cercle
Mself.rayon = min(Mself.m_Width * 5, Mself.m_Size.x/4);
/* Calcul des parametres */
for ( Mself.nbrin = 2 ; ; Mself.nbrin++)
{
Mself.delta = (Mself.m_Size.y - ( Mself.rayon * 2 * Mself.nbrin ) ) / 2 ;
if(Mself.delta < Mself.m_Size.y / 10) // C.a.d. si m_Size.yeur self > m_Size.yeur specifiee
{ // Reduction du rayon des arrondis
Mself.delta = Mself.m_Size.y / 10;
Mself.rayon = (Mself.m_Size.y - 2*Mself.delta) / ( 2 * Mself.nbrin) ;
if(Mself.rayon < Mself.m_Width)
{ // Rayon vraiment trop petit...
Affiche_Message(_("Unable to create line: Requested length is too big"));
return NULL;
}
}
Mself.lbrin = Mself.m_Size.x - (Mself.rayon * 2);
lextbrin = (Mself.lbrin/2) - Mself.rayon;
ll = 2 * lextbrin ; // Longueur du 1er et dernier brin
ll += 2 * Mself.delta ; // Longueur des raccord au serpentin
ll += Mself.nbrin * (Mself.lbrin - 2); // longueur des autres brins
ll += ((Mself.nbrin+1) * 314 * Mself.rayon) /100 ;
msg.Printf( _("Segm count = %d, Lenght = "), Mself.nbrin);
wxString stlen;
valeur_param(ll, stlen); msg += stlen;
Affiche_Message(msg);
if ( ll >= Mself.lng) break;
}
/* Generation du composant : le calcul est fait self Verticale */
if( Create_1_Module(DC, wxEmptyString) == NULL ) return NULL;
Module = m_Pcb->m_Modules;
Module->m_LibRef = wxT("MuSelf");
Module->m_Attributs = MOD_VIRTUAL | MOD_CMS;
Module->m_Flags = 0;
Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
/* Generation des elements speciaux: drawsegments */
LastSegm = (EDGE_MODULE*) Module->m_Drawings;
if( LastSegm ) while( LastSegm->Pnext) LastSegm = (EDGE_MODULE*)LastSegm->Pnext;
FirstSegm = PtSegm = new EDGE_MODULE(Module);
if (LastSegm )
{
LastSegm->Pnext = PtSegm;
PtSegm->Pback = LastSegm;
}
else
{
Module->m_Drawings = PtSegm; PtSegm->Pback = Module;
}
PtSegm->m_Start = Mself.m_Start;
PtSegm->m_End.x = Mself.m_Start.x;
PtSegm->m_End.y = PtSegm->m_Start.y + Mself.delta;
PtSegm->m_Width = Mself.m_Width;
PtSegm->m_Layer = Module->m_Layer;
PtSegm->m_Shape = S_SEGMENT;
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm = gen_arc(PtSegm,PtSegm->m_End.x - Mself.rayon, PtSegm->m_End.y, -900);
if(lextbrin)
{
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x -= lextbrin;
}
/* Trace du serpentin */
for (ii = 1 ; ii < Mself.nbrin; ii++)
{
int arc_angle;
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
if( ii & 1) /* brin d'ordre impair : cercles de sens > 0 */
arc_angle = 1800;
else arc_angle = -1800;
PtSegm = gen_arc(PtSegm, PtSegm->m_End.x,
PtSegm->m_End.y + Mself.rayon, arc_angle);
if( ii < Mself.nbrin-1)
{
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
if( ii & 1) PtSegm->m_End.x += Mself.lbrin;
else PtSegm->m_End.x -= Mself.lbrin;
}
}
/* Trace du point final */
if( ii & 1) /* brin final de sens > 0 */
{
if(lextbrin)
{
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x -= lextbrin;
}
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start.x = PtSegm->m_End.x; PtSegm->m_Start.y = PtSegm->m_End.y;
PtSegm = gen_arc(PtSegm, PtSegm->m_End.x, PtSegm->m_End.y + Mself.rayon, 900);
}
else
{
if(lextbrin)
{
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x += lextbrin;
}
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm = gen_arc(PtSegm, PtSegm->m_End.x, PtSegm->m_End.y + Mself.rayon, -900);
}
newedge = new EDGE_MODULE(Module);
newedge->Copy(PtSegm);
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End = Mself.m_End;
PtSegm->Pnext = NULL;
/* Rotation de la self si le trace doit etre horizontal : */
LastSegm = PtSegm;
if ( Mself.orient == 0)
{
for( PtSegm = FirstSegm; PtSegm != NULL; PtSegm = (EDGE_MODULE*) PtSegm->Pnext )
{
RotatePoint(&PtSegm->m_Start.x, &PtSegm->m_Start.y,
FirstSegm->m_Start.x, FirstSegm->m_Start.y, 900 );
if( PtSegm != LastSegm )
RotatePoint(&PtSegm->m_End.x, &PtSegm->m_End.y,
FirstSegm->m_Start.x, FirstSegm->m_Start.y, 900 );
}
}
/* Modif position ancre */
Module->m_Pos.x = LastSegm->m_End.x; Module->m_Pos.y = LastSegm->m_End.y;
/* Placement des 2 pads sur extremite */
PtPad = new D_PAD(Module);
Module->m_Pads = PtPad; PtPad->Pback = Module;
PtPad->SetPadName( wxT("1") );
PtPad->m_Pos.x = LastSegm->m_End.x; PtPad->m_Pos.y = LastSegm->m_End.y;
PtPad->m_Pos0.x = PtPad->m_Pos.x - Module->m_Pos.x;
PtPad->m_Pos0.y = PtPad->m_Pos.y - Module->m_Pos.y;
PtPad->m_Size.x = PtPad->m_Size.y = LastSegm->m_Width;
PtPad->m_Masque_Layer = g_TabOneLayerMask[LastSegm->m_Layer];
PtPad->m_Attribut = SMD;
PtPad->m_PadShape = CIRCLE;
PtPad->m_Rayon = PtPad->m_Size.x / 2;
D_PAD * newpad = new D_PAD(Module);
newpad->Copy(PtPad);
newpad->AddToChain(PtPad);
PtPad = newpad;
PtPad->SetPadName( wxT("2") );
PtPad->m_Pos.x = FirstSegm->m_Start.x; PtPad->m_Pos.y = FirstSegm->m_Start.y;
PtPad->m_Pos0.x = PtPad->m_Pos.x - Module->m_Pos.x;
PtPad->m_Pos0.y = PtPad->m_Pos.y - Module->m_Pos.y;
/* Modif des positions textes */
Module->Display_Infos(this);
Module->m_Value->m_Pos.x = Module->m_Reference->m_Pos.x = ( FirstSegm->m_Start.x + LastSegm->m_End.x ) /2 ;
Module->m_Value->m_Pos.y = Module->m_Reference->m_Pos.y = ( FirstSegm->m_Start.y + LastSegm->m_End.y ) /2 ;
Module->m_Reference->m_Pos.y -= Module->m_Reference->m_Size.y;
Module->m_Value->m_Pos.y += Module->m_Value->m_Size.y;
Module->m_Reference->m_Pos0.x = Module->m_Reference->m_Pos.x - Module->m_Pos.x;
Module->m_Reference->m_Pos0.y = Module->m_Reference->m_Pos.y - Module->m_Pos.y;
Module->m_Value->m_Pos0.x = Module->m_Value->m_Pos.x - Module->m_Pos.x;
Module->m_Value->m_Pos0.y = Module->m_Value->m_Pos.y - Module->m_Pos.y;
/* Init des Coord locales des segments */
for( PtSegm = FirstSegm; PtSegm != NULL; PtSegm = (EDGE_MODULE*) PtSegm->Pnext )
{
PtSegm->m_Start0.x = PtSegm->m_Start.x - Module->m_Pos.x;
PtSegm->m_Start0.y = PtSegm->m_Start.y - Module->m_Pos.y;
PtSegm->m_End0.x = PtSegm->m_End.x - Module->m_Pos.x;
PtSegm->m_End0.y = PtSegm->m_End.y - Module->m_Pos.y;
}
Module->Set_Rectangle_Encadrement();
Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
return Module;
EDGE_MODULE* PtSegm, * LastSegm, * FirstSegm, * newedge;
MODULE* Module;
D_PAD* PtPad;
int ii, ll, lextbrin;
float fcoeff;
bool abort = FALSE;
wxString msg;
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); /* efface cadre */
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
if( Self_On == 0 )
{
DisplayError( this, wxT( "Starting point not init.." ) ); return NULL;
}
Self_On = 0;
Mself.m_End = m_CurrentScreen->m_Curseur;
/* Agencement des parametres pour simplifier le calcul : */
/* le point de depart doit avoir la coord depart < celle du point de fin */
if( Mself.orient == 0 ) // Self horizontale
{
Mself.m_End.y = Mself.m_Start.y;
if( Mself.m_Start.x > Mself.m_End.x )
EXCHG( Mself.m_Start.x, Mself.m_End.x );
Mself.m_Size.y = Mself.m_End.x - Mself.m_Start.x;
Mself.lng = Mself.m_Size.y;
}
else // Self verticale
{
Mself.m_End.x = Mself.m_Start.x;
if( Mself.m_Start.y > Mself.m_End.y )
EXCHG( Mself.m_Start.y, Mself.m_End.y );
Mself.m_Size.y = Mself.m_End.y - Mself.m_Start.y;
Mself.lng = Mself.m_Size.y;
}
/* Entree de la vraie longueur desiree */
if( !g_UnitMetric )
{
fcoeff = 10000.0;
msg.Printf( wxT( "%1.4f" ), Mself.lng / fcoeff );
abort = Get_Message( _( "Length(inch):" ), msg, this );
}
else
{
fcoeff = 10000.0 / 25.4;
msg.Printf( wxT( "%2.3f" ), Mself.lng / fcoeff );
abort = Get_Message( _( "Length(mm):" ), msg, this );
}
if( abort )
return NULL;
double fval;
if( !msg.ToDouble( &fval ) )
{
DisplayError( this, _( "Incorrect number, abort" ) );
return NULL;
}
Mself.lng = (int) round( fval * fcoeff );
/* Controle des valeurs ( ii = valeur minimale de la longueur */
if( Mself.lng < Mself.m_Size.y )
{
DisplayError( this, _( "Requested length < minimum length" ) );
return NULL;
}
/* Generation du composant: calcul des elements de la self */
Mself.m_Width = g_DesignSettings.m_CurrentTrackWidth;
Mself.m_Size.x = Mself.m_Size.y / 2;
// Choix d'une Valeur de depart raisonnable pour le rayon des arcs de cercle
Mself.rayon = min( Mself.m_Width * 5, Mself.m_Size.x / 4 );
/* Calcul des parametres */
for( Mself.nbrin = 2; ; Mself.nbrin++ )
{
Mself.delta = ( Mself.m_Size.y - ( Mself.rayon * 2 * Mself.nbrin ) ) / 2;
if( Mself.delta < Mself.m_Size.y / 10 ) // C.a.d. si m_Size.yeur self > m_Size.yeur specifiee
{ // Reduction du rayon des arrondis
Mself.delta = Mself.m_Size.y / 10;
Mself.rayon = (Mself.m_Size.y - 2 * Mself.delta) / ( 2 * Mself.nbrin);
if( Mself.rayon < Mself.m_Width )
{ // Rayon vraiment trop petit...
Affiche_Message( _( "Unable to create line: Requested length is too big" ) );
return NULL;
}
}
Mself.lbrin = Mself.m_Size.x - (Mself.rayon * 2);
lextbrin = (Mself.lbrin / 2) - Mself.rayon;
ll = 2 * lextbrin; // Longueur du 1er et dernier brin
ll += 2 * Mself.delta; // Longueur des raccord au serpentin
ll += Mself.nbrin * (Mself.lbrin - 2); // longueur des autres brins
ll += ( (Mself.nbrin + 1) * 314 * Mself.rayon ) / 100;
msg.Printf( _( "Segm count = %d, Lenght = " ), Mself.nbrin );
wxString stlen;
valeur_param( ll, stlen ); msg += stlen;
Affiche_Message( msg );
if( ll >= Mself.lng )
break;
}
/* Generation du composant : le calcul est fait self Verticale */
if( Create_1_Module( DC, wxEmptyString ) == NULL )
return NULL;
Module = m_Pcb->m_Modules;
Module->m_LibRef = wxT( "MuSelf" );
Module->m_Attributs = MOD_VIRTUAL | MOD_CMS;
Module->m_Flags = 0;
Module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
/* Generation des elements speciaux: drawsegments */
LastSegm = (EDGE_MODULE*) Module->m_Drawings;
if( LastSegm )
while( LastSegm->Pnext )
LastSegm = (EDGE_MODULE*) LastSegm->Pnext;
FirstSegm = PtSegm = new EDGE_MODULE( Module );
if( LastSegm )
{
LastSegm->Pnext = PtSegm;
PtSegm->Pback = LastSegm;
}
else
{
Module->m_Drawings = PtSegm; PtSegm->Pback = Module;
}
PtSegm->m_Start = Mself.m_Start;
PtSegm->m_End.x = Mself.m_Start.x;
PtSegm->m_End.y = PtSegm->m_Start.y + Mself.delta;
PtSegm->m_Width = Mself.m_Width;
PtSegm->m_Layer = Module->m_Layer;
PtSegm->m_Shape = S_SEGMENT;
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm = gen_arc( PtSegm, PtSegm->m_End.x - Mself.rayon, PtSegm->m_End.y, -900 );
if( lextbrin )
{
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x -= lextbrin;
}
/* Trace du serpentin */
for( ii = 1; ii < Mself.nbrin; ii++ )
{
int arc_angle;
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
if( ii & 1 ) /* brin d'ordre impair : cercles de sens > 0 */
arc_angle = 1800;
else
arc_angle = -1800;
PtSegm = gen_arc( PtSegm, PtSegm->m_End.x,
PtSegm->m_End.y + Mself.rayon, arc_angle );
if( ii < Mself.nbrin - 1 )
{
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
if( ii & 1 )
PtSegm->m_End.x += Mself.lbrin;
else
PtSegm->m_End.x -= Mself.lbrin;
}
}
/* Trace du point final */
if( ii & 1 ) /* brin final de sens > 0 */
{
if( lextbrin )
{
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x -= lextbrin;
}
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start.x = PtSegm->m_End.x; PtSegm->m_Start.y = PtSegm->m_End.y;
PtSegm = gen_arc( PtSegm, PtSegm->m_End.x, PtSegm->m_End.y + Mself.rayon, 900 );
}
else
{
if( lextbrin )
{
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End.x += lextbrin;
}
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm = gen_arc( PtSegm, PtSegm->m_End.x, PtSegm->m_End.y + Mself.rayon, -900 );
}
newedge = new EDGE_MODULE( Module );
newedge->Copy( PtSegm );
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start = PtSegm->m_End;
PtSegm->m_End = Mself.m_End;
PtSegm->Pnext = NULL;
/* Rotation de la self si le trace doit etre horizontal : */
LastSegm = PtSegm;
if( Mself.orient == 0 )
{
for( PtSegm = FirstSegm; PtSegm != NULL; PtSegm = (EDGE_MODULE*) PtSegm->Pnext )
{
RotatePoint( &PtSegm->m_Start.x, &PtSegm->m_Start.y,
FirstSegm->m_Start.x, FirstSegm->m_Start.y, 900 );
if( PtSegm != LastSegm )
RotatePoint( &PtSegm->m_End.x, &PtSegm->m_End.y,
FirstSegm->m_Start.x, FirstSegm->m_Start.y, 900 );
}
}
/* Modif position ancre */
Module->m_Pos.x = LastSegm->m_End.x; Module->m_Pos.y = LastSegm->m_End.y;
/* Placement des 2 pads sur extremite */
PtPad = new D_PAD( Module );
Module->m_Pads = PtPad; PtPad->Pback = Module;
PtPad->SetPadName( wxT( "1" ) );
PtPad->m_Pos.x = LastSegm->m_End.x; PtPad->m_Pos.y = LastSegm->m_End.y;
PtPad->m_Pos0.x = PtPad->m_Pos.x - Module->m_Pos.x;
PtPad->m_Pos0.y = PtPad->m_Pos.y - Module->m_Pos.y;
PtPad->m_Size.x = PtPad->m_Size.y = LastSegm->m_Width;
PtPad->m_Masque_Layer = g_TabOneLayerMask[LastSegm->m_Layer];
PtPad->m_Attribut = SMD;
PtPad->m_PadShape = CIRCLE;
PtPad->m_Rayon = PtPad->m_Size.x / 2;
D_PAD* newpad = new D_PAD( Module );
newpad->Copy( PtPad );
newpad->AddToChain( PtPad );
PtPad = newpad;
PtPad->SetPadName( wxT( "2" ) );
PtPad->m_Pos.x = FirstSegm->m_Start.x; PtPad->m_Pos.y = FirstSegm->m_Start.y;
PtPad->m_Pos0.x = PtPad->m_Pos.x - Module->m_Pos.x;
PtPad->m_Pos0.y = PtPad->m_Pos.y - Module->m_Pos.y;
/* Modif des positions textes */
Module->Display_Infos( this );
Module->m_Value->m_Pos.x = Module->m_Reference->m_Pos.x = ( FirstSegm->m_Start.x +
LastSegm->m_End.x ) / 2;
Module->m_Value->m_Pos.y = Module->m_Reference->m_Pos.y = ( FirstSegm->m_Start.y +
LastSegm->m_End.y ) / 2;
Module->m_Reference->m_Pos.y -= Module->m_Reference->m_Size.y;
Module->m_Value->m_Pos.y += Module->m_Value->m_Size.y;
Module->m_Reference->m_Pos0.x = Module->m_Reference->m_Pos.x - Module->m_Pos.x;
Module->m_Reference->m_Pos0.y = Module->m_Reference->m_Pos.y - Module->m_Pos.y;
Module->m_Value->m_Pos0.x = Module->m_Value->m_Pos.x - Module->m_Pos.x;
Module->m_Value->m_Pos0.y = Module->m_Value->m_Pos.y - Module->m_Pos.y;
/* Init des Coord locales des segments */
for( PtSegm = FirstSegm; PtSegm != NULL; PtSegm = (EDGE_MODULE*) PtSegm->Pnext )
{
PtSegm->m_Start0.x = PtSegm->m_Start.x - Module->m_Pos.x;
PtSegm->m_Start0.y = PtSegm->m_Start.y - Module->m_Pos.y;
PtSegm->m_End0.x = PtSegm->m_End.x - Module->m_Pos.x;
PtSegm->m_End0.y = PtSegm->m_End.y - Module->m_Pos.y;
}
Module->Set_Rectangle_Encadrement();
Module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
return Module;
}
/**************************************************************************/
static EDGE_MODULE * gen_arc(EDGE_MODULE * PtSegm, int cX, int cY, int angle)
static EDGE_MODULE* gen_arc( EDGE_MODULE* PtSegm, int cX, int cY, int angle )
/**************************************************************************/
/* Genere un arc de EDGE_MODULE :
de centre cX,cY
d'angle "angle"
de point de depart donne dans la structure pointee par PtSegm, qui doit
entre a jour (type,net..)
Retourne un pointeur sur la derniere structure EDGE_MODULE generee
*/
* de centre cX,cY
* d'angle "angle"
* de point de depart donne dans la structure pointee par PtSegm, qui doit
* entre a jour (type,net..)
* Retourne un pointeur sur la derniere structure EDGE_MODULE generee
*/
{
int ii, nb_seg;
float alpha, beta, fsin, fcos;
int x0, xr0, y0, yr0;
EDGE_MODULE * newedge;
angle = -angle;
y0 = PtSegm->m_Start.x - cX; x0 = PtSegm->m_Start.y - cY;
nb_seg = (abs(angle)) / 225 ; if(nb_seg == 0) nb_seg = 1 ;
alpha = ( (float)angle * 3.14159 / 1800 ) / nb_seg;
for ( ii = 1 ; ii <= nb_seg ; ii++ )
{
if( ii > 1)
{
newedge = new EDGE_MODULE( (MODULE*) NULL);
newedge->Copy(PtSegm);
newedge->m_Parent = PtSegm->m_Parent;
newedge->AddToChain(PtSegm);
PtSegm = newedge;
PtSegm->m_Start.x = PtSegm->m_End.x; PtSegm->m_Start.y = PtSegm->m_End.y;
}
beta = (alpha * ii);
fcos = cos(beta); fsin = sin(beta);
xr0 = (int)(x0 * fcos + y0 * fsin);
yr0 = (int)(y0 * fcos - x0 * fsin);
PtSegm->m_End.x = cX + yr0; PtSegm->m_End.y = cY + xr0 ;
}
return( PtSegm );
int ii, nb_seg;
float alpha, beta, fsin, fcos;
int x0, xr0, y0, yr0;
EDGE_MODULE* newedge;
angle = -angle;
y0 = PtSegm->m_Start.x - cX; x0 = PtSegm->m_Start.y - cY;
nb_seg = ( abs( angle ) ) / 225; if( nb_seg == 0 )
nb_seg = 1;
alpha = ( (float) angle * 3.14159 / 1800 ) / nb_seg;
for( ii = 1; ii <= nb_seg; ii++ )
{
if( ii > 1 )
{
newedge = new EDGE_MODULE( (MODULE*) NULL );
newedge->Copy( PtSegm );
newedge->m_Parent = PtSegm->m_Parent;
newedge->AddToChain( PtSegm );
PtSegm = newedge;
PtSegm->m_Start.x = PtSegm->m_End.x; PtSegm->m_Start.y = PtSegm->m_End.y;
}
beta = (alpha * ii);
fcos = cos( beta ); fsin = sin( beta );
xr0 = (int) (x0 * fcos + y0 * fsin);
yr0 = (int) (y0 * fcos - x0 * fsin);
PtSegm->m_End.x = cX + yr0; PtSegm->m_End.y = cY + xr0;
}
return PtSegm;
}
......@@ -16,6 +16,7 @@
/* fonctions locales */
EDA_BaseStruct* Locate_MirePcb( EDA_BaseStruct* PtStruct, int LayerSearch, int typeloc );
D_PAD* Locate_Any_Pad( BOARD* Pcb, const wxPoint& ref_pos, bool OnlyCurrentLayer );
/**
......@@ -390,10 +391,10 @@ DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc )
}
/*************************************************/
/* D_PAD * Locate_Any_Pad(int typeloc, bool OnlyCurrentLayer) */
/* D_PAD* Locate_Any_Pad(int ref_pos, bool OnlyCurrentLayer) */
/*************************************************/
/*************************************************
* D_PAD * Locate_Any_Pad(int typeloc, bool OnlyCurrentLayer)
* D_PAD* Locate_Any_Pad(int ref_pos, bool OnlyCurrentLayer)
*************************************************/
/*
* localisation de la pastille pointee par la coordonnee ref_pos.x,,ref_pos.y, ou
......
/********************************************************/
/* Modification de la place, orient, nombre des MODULES */
/********************************************************/
/********************************************************/
/* Modification de la place, orient, nombre des MODULES */
/********************************************************/
/* Fichier MODULES.Cpp */
/* Fichier MODULES.Cpp */
#include "fctsys.h"
#include "gr_basic.h"
......@@ -19,643 +19,724 @@
/* fonctions externes */
/* Fonctions locales */
static int ChangeSideMaskLayer(int masque);
static void Exit_Module(WinEDA_DrawPanel * Panel, wxDC *DC) ;
static int ChangeSideMaskLayer( int masque );
static void Exit_Module( WinEDA_DrawPanel* Panel, wxDC* DC );
/* Variables locales : */
static int ModuleInitOrient; // Lors des moves, val init de l'orient (pour annulation)
static int ModuleInitLayer; // Lors des moves, val init de la couche (pour annulation)
static int ModuleInitOrient; // Lors des moves, val init de l'orient (pour annulation)
static int ModuleInitLayer; // Lors des moves, val init de la couche (pour annulation)
/*************************************************************************/
void Show_Pads_On_Off(WinEDA_DrawPanel * panel, wxDC * DC, MODULE * module)
void Show_Pads_On_Off( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* module )
/**************************************************************************/
/* Fonction appelee lors de l'activation/desactivation de la visualisation
des Pads du module en deplacement
Effacement ou visu des Pads selon conditions initiales
*/
* des Pads du module en deplacement
* Effacement ou visu des Pads selon conditions initiales
*/
{
D_PAD* pt_pad;
bool pad_fill_tmp;
if(module == 0 ) return ;
pad_fill_tmp = DisplayOpt.DisplayPadFill;
DisplayOpt.DisplayPadFill = FALSE; /* Trace en SKETCH */
pt_pad = module->m_Pads;
for( ;pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
pt_pad->Draw(panel, DC, g_Offset_Module, GR_XOR) ;
}
DisplayOpt.DisplayPadFill = pad_fill_tmp;
D_PAD* pt_pad;
bool pad_fill_tmp;
if( module == 0 )
return;
pad_fill_tmp = DisplayOpt.DisplayPadFill;
DisplayOpt.DisplayPadFill = FALSE; /* Trace en SKETCH */
pt_pad = module->m_Pads;
for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
pt_pad->Draw( panel, DC, g_Offset_Module, GR_XOR );
}
DisplayOpt.DisplayPadFill = pad_fill_tmp;
}
/***************************************************************************/
/* Fonction appelee lors de l'activation/desactivation de la visualisation */
/* du rastnest du module en deplacement */
/* Effacement ou visu du rastnest selon conditions initiales */
/***************************************************************************/
void Rastnest_On_Off(WinEDA_DrawPanel * panel, wxDC * DC, MODULE * module)
void Rastnest_On_Off( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* module )
{
WinEDA_BasePcbFrame * frame = (WinEDA_BasePcbFrame *)panel->m_Parent;
frame->build_ratsnest_module(DC, module) ;
frame->trace_ratsnest_module(DC);
WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) panel->m_Parent;
frame->build_ratsnest_module( DC, module );
frame->trace_ratsnest_module( DC );
}
/***************************************************/
MODULE * WinEDA_BasePcbFrame::GetModuleByName(void)
MODULE* WinEDA_BasePcbFrame::GetModuleByName( void )
/***************************************************/
/* Get a module name from user and return a pointer to the corresponding module
*/
*/
{
wxString modulename;
MODULE * module = NULL;
Get_Message(_("Footprint name:"), modulename, this);
if ( ! modulename.IsEmpty() )
{
module = m_Pcb->m_Modules;
while (module )
{
if ( module->m_Reference->m_Text.CmpNoCase(modulename) == 0 ) break;
module = module->Next();
}
}
return module;
wxString modulename;
MODULE* module = NULL;
Get_Message( _( "Footprint name:" ), modulename, this );
if( !modulename.IsEmpty() )
{
module = m_Pcb->m_Modules;
while( module )
{
if( module->m_Reference->m_Text.CmpNoCase( modulename ) == 0 )
break;
module = module->Next();
}
}
return module;
}
/**********************************************************************/
void WinEDA_PcbFrame::StartMove_Module(MODULE * module, wxDC * DC)
void WinEDA_PcbFrame::StartMove_Module( MODULE* module, wxDC* DC )
/**********************************************************************/
{
if (module == NULL ) return;
m_CurrentScreen->m_CurrentItem = module;
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
module->m_Flags |= IS_MOVED;
ModuleInitOrient = module->m_Orient;
ModuleInitLayer = module->m_Layer;
/* Effacement chevelu general si necessaire */
if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);
if( g_DragSegmentList ) /* Anormal ! */
{
EraseDragListe();
}
if( g_Drag_Pistes_On)
{
Build_Drag_Liste(DrawPanel, DC, module);
}
m_Pcb->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST;
DrawPanel->ManageCurseur = Montre_Position_Empreinte;
DrawPanel->ForceCloseManageCurseur = Exit_Module;
DrawPanel->m_AutoPAN_Request = TRUE;
// effacement module a l'ecran:
module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
// Reaffichage
DrawPanel->ManageCurseur(DrawPanel, DC, FALSE);
if( module == NULL )
return;
m_CurrentScreen->m_CurrentItem = module;
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
module->m_Flags |= IS_MOVED;
ModuleInitOrient = module->m_Orient;
ModuleInitLayer = module->m_Layer;
/* Effacement chevelu general si necessaire */
if( g_Show_Ratsnest )
DrawGeneralRatsnest( DC );
if( g_DragSegmentList ) /* Anormal ! */
{
EraseDragListe();
}
if( g_Drag_Pistes_On )
{
Build_Drag_Liste( DrawPanel, DC, module );
}
m_Pcb->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST;
DrawPanel->ManageCurseur = Montre_Position_Empreinte;
DrawPanel->ForceCloseManageCurseur = Exit_Module;
DrawPanel->m_AutoPAN_Request = TRUE;
// effacement module a l'ecran:
module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
// Reaffichage
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
}
/**************************************************/
void Exit_Module(WinEDA_DrawPanel * Panel, wxDC *DC)
void Exit_Module( WinEDA_DrawPanel* Panel, wxDC* DC )
/***************************************************/
/* fonction de sortie de l'application */
{
DRAG_SEGM * pt_drag;
TRACK * pt_segm;
MODULE * module;
WinEDA_BasePcbFrame * pcbframe = (WinEDA_BasePcbFrame*)Panel->m_Parent;
module = (MODULE *) pcbframe->m_CurrentScreen->m_CurrentItem;
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
if (module)
{
// effacement module a l'ecran:
DrawModuleOutlines(Panel, DC, module);
/* restitution de l'empreinte si move ou effacement copie*/
if (module->m_Flags & IS_MOVED )
{
/* Move en cours : remise a l'etat d'origine */
if( g_Drag_Pistes_On)
{
/* Effacement des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
pt_segm = pt_drag->m_Segm;
pt_segm->Draw(Panel, DC, GR_XOR);
}
}
/* Remise en etat d'origine des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
pt_segm = pt_drag->m_Segm; pt_segm->SetState(EDIT,OFF);
pt_drag->SetInitialValues();
pt_segm->Draw(Panel, DC, GR_OR);
}
EraseDragListe();
module->m_Flags = 0;
}
if (module->m_Flags & IS_NEW )
{
DeleteStructure(module);
module = NULL;
pcbframe->m_Pcb->m_Status_Pcb = 0 ;
pcbframe->build_liste_pads() ;
}
}
/* Reaffichage du module a l'ecran */
if ( module )
{
if ( ModuleInitOrient != module->m_Orient )
pcbframe->Rotate_Module(NULL,module, ModuleInitOrient, FALSE);
if( ModuleInitLayer != module->m_Layer )
pcbframe->Change_Side_Module(module, NULL);
module->Draw(Panel, DC, wxPoint(0,0), GR_OR);
}
g_Drag_Pistes_On = FALSE;
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
pcbframe->m_CurrentScreen->m_CurrentItem = NULL;
DRAG_SEGM* pt_drag;
TRACK* pt_segm;
MODULE* module;
WinEDA_BasePcbFrame* pcbframe = (WinEDA_BasePcbFrame*) Panel->m_Parent;
module = (MODULE*) pcbframe->m_CurrentScreen->m_CurrentItem;
pcbframe->m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
if( module )
{
// effacement module a l'ecran:
DrawModuleOutlines( Panel, DC, module );
/* restitution de l'empreinte si move ou effacement copie*/
if( module->m_Flags & IS_MOVED )
{
/* Move en cours : remise a l'etat d'origine */
if( g_Drag_Pistes_On )
{
/* Effacement des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
pt_segm = pt_drag->m_Segm;
pt_segm->Draw( Panel, DC, GR_XOR );
}
}
/* Remise en etat d'origine des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
pt_segm = pt_drag->m_Segm; pt_segm->SetState( EDIT, OFF );
pt_drag->SetInitialValues();
pt_segm->Draw( Panel, DC, GR_OR );
}
EraseDragListe();
module->m_Flags = 0;
}
if( module->m_Flags & IS_NEW )
{
DeleteStructure( module );
module = NULL;
pcbframe->m_Pcb->m_Status_Pcb = 0;
pcbframe->build_liste_pads();
}
}
/* Reaffichage du module a l'ecran */
if( module )
{
if( ModuleInitOrient != module->m_Orient )
pcbframe->Rotate_Module( NULL, module, ModuleInitOrient, FALSE );
if( ModuleInitLayer != module->m_Layer )
pcbframe->Change_Side_Module( module, NULL );
module->Draw( Panel, DC, wxPoint( 0, 0 ), GR_OR );
}
g_Drag_Pistes_On = FALSE;
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
pcbframe->m_CurrentScreen->m_CurrentItem = NULL;
}
/**********************************************************/
MODULE * WinEDA_BasePcbFrame::Copie_Module(MODULE * module)
MODULE* WinEDA_BasePcbFrame::Copie_Module( MODULE* module )
/**********************************************************/
/* copie le module "module" en position courante */
{
MODULE * newmodule;
MODULE* newmodule;
if (module == NULL ) return NULL;
if( module == NULL )
return NULL;
m_CurrentScreen->SetModify();
m_CurrentScreen->SetModify();
/* Duplication du module */
m_Pcb->m_Status_Pcb = 0;
newmodule = new MODULE(m_Pcb);
newmodule->Copy(module);
newmodule->m_Parent = m_Pcb;
newmodule->AddToChain(module);
newmodule->m_Flags = IS_NEW;
/* Duplication du module */
m_Pcb->m_Status_Pcb = 0;
newmodule = new MODULE( m_Pcb );
newmodule->Copy( module );
newmodule->m_Parent = m_Pcb;
newmodule->AddToChain( module );
newmodule->m_Flags = IS_NEW;
build_liste_pads();
build_liste_pads();
newmodule->Display_Infos(this);
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
return newmodule;
newmodule->Display_Infos( this );
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
return newmodule;
}
/**********************************************************************************/
void Montre_Position_Empreinte(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
void Montre_Position_Empreinte( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/**********************************************************************************/
/* redessin du contour de l'empreinte lors des deplacements de la souris
*/
*/
{
MODULE * module = (MODULE *) panel->m_Parent->m_CurrentScreen->m_CurrentItem;
MODULE* module = (MODULE*) panel->m_Parent->m_CurrentScreen->m_CurrentItem;
if ( module == NULL ) return;
if( module == NULL )
return;
/* efface ancienne position */
if( erase )
{
DrawModuleOutlines(panel, DC, module);
}
/* efface ancienne position */
if( erase )
{
DrawModuleOutlines( panel, DC, module );
}
/* Redessine le module a la nouvelle place */
g_Offset_Module.x = module->m_Pos.x - panel->m_Parent->m_CurrentScreen->m_Curseur.x;
g_Offset_Module.y = module->m_Pos.y - panel->m_Parent->m_CurrentScreen->m_Curseur.y;
DrawModuleOutlines(panel, DC, module);
/* Redessine le module a la nouvelle place */
g_Offset_Module.x = module->m_Pos.x - panel->m_Parent->m_CurrentScreen->m_Curseur.x;
g_Offset_Module.y = module->m_Pos.y - panel->m_Parent->m_CurrentScreen->m_Curseur.y;
DrawModuleOutlines( panel, DC, module );
Dessine_Segments_Dragges(panel, DC);
Dessine_Segments_Dragges( panel, DC );
}
/**************************************************************/
bool WinEDA_PcbFrame::Delete_Module(MODULE * module, wxDC * DC)
bool WinEDA_PcbFrame::Delete_Module( MODULE* module, wxDC* DC )
/**************************************************************/
/*
Commande Delete Module :
Suppression d'une empreinte
les pointeurs divers sont mis a jour
*/
* Commande Delete Module :
* Suppression d'une empreinte
* les pointeurs divers sont mis a jour
*/
{
EDA_BaseStruct * PtBack, *PtNext;
wxString msg;
/* Si l'empreinte est selectee , on ne peut pas l'effacer ! */
if ( module == NULL ) return FALSE;
/* Confirmation de l'effacement */
module->Display_Infos(this);
msg << _("Delete Module") << wxT(" ") << module->m_Reference->m_Text
<< wxT(" (") << _("Value ") << module->m_Value->m_Text
<< wxT(") ?");
if( !IsOK(this, msg ) )
{
return FALSE;
}
m_CurrentScreen->SetModify();
/* Erase rastnest if needed */
if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);
/* Effacement du module a l'ecran */
if ( DC ) module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
/* Suppression du chainage */
PtBack = module->Pback;
PtNext = module->Pnext;
if( PtBack == (EDA_BaseStruct*) m_Pcb )
{
m_Pcb->m_Modules = (MODULE*)PtNext;
}
else
{
PtBack->Pnext = PtNext;
}
if(PtNext) PtNext->Pback = PtBack;
/* Sauvegarde en buffer des undelete */
SaveItemEfface( module, 1);
m_Pcb->m_Status_Pcb = 0 ;
build_liste_pads() ;
ReCompile_Ratsnest_After_Changes( DC );
return TRUE;
EDA_BaseStruct* PtBack, * PtNext;
wxString msg;
/* Si l'empreinte est selectee , on ne peut pas l'effacer ! */
if( module == NULL )
return FALSE;
/* Confirmation de l'effacement */
module->Display_Infos( this );
msg << _( "Delete Module" ) << wxT( " " ) << module->m_Reference->m_Text
<< wxT( " (" ) << _( "Value " ) << module->m_Value->m_Text
<< wxT( ") ?" );
if( !IsOK( this, msg ) )
{
return FALSE;
}
m_CurrentScreen->SetModify();
/* Erase rastnest if needed */
if( g_Show_Ratsnest )
DrawGeneralRatsnest( DC );
/* Effacement du module a l'ecran */
if( DC )
module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
/* Suppression du chainage */
PtBack = module->Pback;
PtNext = module->Pnext;
if( PtBack == (EDA_BaseStruct*) m_Pcb )
{
m_Pcb->m_Modules = (MODULE*) PtNext;
}
else
{
PtBack->Pnext = PtNext;
}
if( PtNext )
PtNext->Pback = PtBack;
/* Sauvegarde en buffer des undelete */
SaveItemEfface( module, 1 );
m_Pcb->m_Status_Pcb = 0;
build_liste_pads();
ReCompile_Ratsnest_After_Changes( DC );
return TRUE;
}
/**********************************************************************/
void WinEDA_BasePcbFrame::Change_Side_Module(MODULE * Module, wxDC * DC)
void WinEDA_BasePcbFrame::Change_Side_Module( MODULE* Module, wxDC* DC )
/**********************************************************************/
/* Change de cote un composant : il y a inversion MIROIR autour de l'axe X
Le changement n'est fait que si la couche est
- CUIVRE ou CMP
Si DC == NULL, il n'y a pas de redessin du composant et du chevelu
*/
* Le changement n'est fait que si la couche est
* - CUIVRE ou CMP
* Si DC == NULL, il n'y a pas de redessin du composant et du chevelu
*/
{
D_PAD* pt_pad ;
TEXTE_MODULE* pt_texte;
EDGE_MODULE * pt_edgmod ;
EDA_BaseStruct * PtStruct;
if ( Module == NULL ) return;
if( (Module->m_Layer != CMP_N) && (Module->m_Layer != CUIVRE_N) ) return;
m_CurrentScreen->SetModify();
if ( ! (Module->m_Flags & IS_MOVED) )
{
m_Pcb->m_Status_Pcb &= ~( LISTE_CHEVELU_OK | CONNEXION_OK);
if ( DC ) Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
/* Effacement chevelu general si necessaire */
if ( DC && g_Show_Ratsnest) DrawGeneralRatsnest(DC);
/* Init des variables utilisees dans la routine Dessine_Drag_segment() */
g_Offset_Module.x = 0;
g_Offset_Module.y = 0;
}
else // Module en deplacement
{
/* efface empreinte ( vue en contours) si elle a ete deja dessinee */
if ( DC )
{
DrawModuleOutlines(DrawPanel, DC, Module);
Dessine_Segments_Dragges(DrawPanel, DC);
}
}
/* mise a jour du Flag de l'empreinte et des couches des contours et textes */
Module->m_Layer = ChangeSideNumLayer(Module->m_Layer);
/* Inversion miroir de l'orientation */
Module->m_Orient = - Module->m_Orient;
NORMALIZE_ANGLE_POS(Module->m_Orient);
/* Inversion miroir + layers des pastilles */
pt_pad = Module->m_Pads;
for ( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
pt_pad->m_Pos.y -= Module->m_Pos.y ;
pt_pad->m_Pos.y = -pt_pad->m_Pos.y;
pt_pad->m_Pos.y += Module->m_Pos.y;
pt_pad->m_Pos0.y = - pt_pad->m_Pos0.y;
pt_pad->m_Offset.y = -pt_pad->m_Offset.y;
pt_pad->m_DeltaSize.y = -pt_pad->m_DeltaSize.y;
NEGATE_AND_NORMALIZE_ANGLE_POS(pt_pad->m_Orient);
/* change cote pour pastilles surfaciques */
pt_pad->m_Masque_Layer = ChangeSideMaskLayer(pt_pad->m_Masque_Layer);
}
/* Inversion miroir de la Reference et mise en miroir : */
pt_texte = Module->m_Reference;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1 ;
NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
if( Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
if( (Module->m_Layer == SILKSCREEN_N_CU) ||
(Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
pt_texte->m_Miroir = 0 ;
/* Inversion miroir de la Valeur et mise en miroir : */
pt_texte = Module->m_Value;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1 ;
NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
if( Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
if( (Module->m_Layer == SILKSCREEN_N_CU) ||
(Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
pt_texte->m_Miroir = 0 ;
/* Inversion miroir des dessins de l'empreinte : */
PtStruct = Module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext)
{
switch( PtStruct->m_StructType)
{
case TYPEEDGEMODULE:
pt_edgmod = (EDGE_MODULE *) PtStruct;
pt_edgmod->m_Start.y -= Module->m_Pos.y;
pt_edgmod->m_Start.y = -pt_edgmod->m_Start.y ;
pt_edgmod->m_Start.y += Module->m_Pos.y;
pt_edgmod->m_End.y -= Module->m_Pos.y;
pt_edgmod->m_End.y = -pt_edgmod->m_End.y ;
pt_edgmod->m_End.y += Module->m_Pos.y;
/* inversion des coords locales */
pt_edgmod->m_Start0.y = -pt_edgmod->m_Start0.y;
pt_edgmod->m_End0.y = -pt_edgmod->m_End0.y;
if ( pt_edgmod->m_Shape == S_ARC )
{
pt_edgmod->m_Angle = - pt_edgmod->m_Angle;
}
pt_edgmod->m_Layer = ChangeSideNumLayer(pt_edgmod->m_Layer);
break;
case TYPETEXTEMODULE:
/* Inversion miroir de la position et mise en miroir : */
pt_texte = (TEXTE_MODULE*)PtStruct;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1 ;
NEGATE_AND_NORMALIZE_ANGLE_POS(pt_texte->m_Orient);
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer(pt_texte->m_Layer);
if( Module->m_Layer == CUIVRE_N) pt_texte->m_Layer = SILKSCREEN_N_CU;
if(Module->m_Layer == CMP_N) pt_texte->m_Layer = SILKSCREEN_N_CMP;
if((Module->m_Layer == SILKSCREEN_N_CU) ||
(Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N))
pt_texte->m_Miroir = 0 ;
break;
default: DisplayError(this, wxT("Unknown Draw Type")); break;
}
}
/* calcul du rectangle d'encadrement */
Module->Set_Rectangle_Encadrement();
Module->Display_Infos(this);
if( !(Module->m_Flags & IS_MOVED) ) /* Inversion simple */
{
if ( DC )
{
Module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
/* affichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
}
}
else
{
if ( DC )
{
DrawModuleOutlines(DrawPanel, DC, Module);
Dessine_Segments_Dragges(DrawPanel, DC);
}
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
}
D_PAD* pt_pad;
TEXTE_MODULE* pt_texte;
EDGE_MODULE* pt_edgmod;
EDA_BaseStruct* PtStruct;
if( Module == NULL )
return;
if( (Module->m_Layer != CMP_N) && (Module->m_Layer != CUIVRE_N) )
return;
m_CurrentScreen->SetModify();
if( !(Module->m_Flags & IS_MOVED) )
{
m_Pcb->m_Status_Pcb &= ~( LISTE_CHEVELU_OK | CONNEXION_OK);
if( DC )
Module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
/* Effacement chevelu general si necessaire */
if( DC && g_Show_Ratsnest )
DrawGeneralRatsnest( DC );
/* Init des variables utilisees dans la routine Dessine_Drag_segment() */
g_Offset_Module.x = 0;
g_Offset_Module.y = 0;
}
else // Module en deplacement
{
/* efface empreinte ( vue en contours) si elle a ete deja dessinee */
if( DC )
{
DrawModuleOutlines( DrawPanel, DC, Module );
Dessine_Segments_Dragges( DrawPanel, DC );
}
}
/* mise a jour du Flag de l'empreinte et des couches des contours et textes */
Module->m_Layer = ChangeSideNumLayer( Module->m_Layer );
/* Inversion miroir de l'orientation */
Module->m_Orient = -Module->m_Orient;
NORMALIZE_ANGLE_POS( Module->m_Orient );
/* Inversion miroir + layers des pastilles */
pt_pad = Module->m_Pads;
for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
pt_pad->m_Pos.y -= Module->m_Pos.y;
pt_pad->m_Pos.y = -pt_pad->m_Pos.y;
pt_pad->m_Pos.y += Module->m_Pos.y;
pt_pad->m_Pos0.y = -pt_pad->m_Pos0.y;
pt_pad->m_Offset.y = -pt_pad->m_Offset.y;
pt_pad->m_DeltaSize.y = -pt_pad->m_DeltaSize.y;
NEGATE_AND_NORMALIZE_ANGLE_POS( pt_pad->m_Orient );
/* change cote pour pastilles surfaciques */
pt_pad->m_Masque_Layer = ChangeSideMaskLayer( pt_pad->m_Masque_Layer );
}
/* Inversion miroir de la Reference et mise en miroir : */
pt_texte = Module->m_Reference;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1;
NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient );
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer( pt_texte->m_Layer );
if( Module->m_Layer == CUIVRE_N )
pt_texte->m_Layer = SILKSCREEN_N_CU;
if( Module->m_Layer == CMP_N )
pt_texte->m_Layer = SILKSCREEN_N_CMP;
if( (Module->m_Layer == SILKSCREEN_N_CU)
|| (Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
pt_texte->m_Miroir = 0;
/* Inversion miroir de la Valeur et mise en miroir : */
pt_texte = Module->m_Value;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1;
NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient );
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer( pt_texte->m_Layer );
if( Module->m_Layer == CUIVRE_N )
pt_texte->m_Layer = SILKSCREEN_N_CU;
if( Module->m_Layer == CMP_N )
pt_texte->m_Layer = SILKSCREEN_N_CMP;
if( (Module->m_Layer == SILKSCREEN_N_CU)
|| (Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
pt_texte->m_Miroir = 0;
/* Inversion miroir des dessins de l'empreinte : */
PtStruct = Module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
{
switch( PtStruct->m_StructType )
{
case TYPEEDGEMODULE:
pt_edgmod = (EDGE_MODULE*) PtStruct;
pt_edgmod->m_Start.y -= Module->m_Pos.y;
pt_edgmod->m_Start.y = -pt_edgmod->m_Start.y;
pt_edgmod->m_Start.y += Module->m_Pos.y;
pt_edgmod->m_End.y -= Module->m_Pos.y;
pt_edgmod->m_End.y = -pt_edgmod->m_End.y;
pt_edgmod->m_End.y += Module->m_Pos.y;
/* inversion des coords locales */
pt_edgmod->m_Start0.y = -pt_edgmod->m_Start0.y;
pt_edgmod->m_End0.y = -pt_edgmod->m_End0.y;
if( pt_edgmod->m_Shape == S_ARC )
{
pt_edgmod->m_Angle = -pt_edgmod->m_Angle;
}
pt_edgmod->m_Layer = ChangeSideNumLayer( pt_edgmod->m_Layer );
break;
case TYPETEXTEMODULE:
/* Inversion miroir de la position et mise en miroir : */
pt_texte = (TEXTE_MODULE*) PtStruct;
pt_texte->m_Pos.y -= Module->m_Pos.y;
pt_texte->m_Pos.y = -pt_texte->m_Pos.y;
pt_texte->m_Pos.y += Module->m_Pos.y;
pt_texte->m_Pos0.y = pt_texte->m_Pos0.y;
pt_texte->m_Miroir = 1;
NEGATE_AND_NORMALIZE_ANGLE_POS( pt_texte->m_Orient );
pt_texte->m_Layer = Module->m_Layer;
pt_texte->m_Layer = ChangeSideNumLayer( pt_texte->m_Layer );
if( Module->m_Layer == CUIVRE_N )
pt_texte->m_Layer = SILKSCREEN_N_CU;
if( Module->m_Layer == CMP_N )
pt_texte->m_Layer = SILKSCREEN_N_CMP;
if( (Module->m_Layer == SILKSCREEN_N_CU)
|| (Module->m_Layer == ADHESIVE_N_CU) || (Module->m_Layer == CUIVRE_N) )
pt_texte->m_Miroir = 0;
break;
default:
DisplayError( this, wxT( "Unknown Draw Type" ) ); break;
}
}
/* calcul du rectangle d'encadrement */
Module->Set_Rectangle_Encadrement();
Module->Display_Infos( this );
if( !(Module->m_Flags & IS_MOVED) ) /* Inversion simple */
{
if( DC )
{
Module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
/* affichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
}
}
else
{
if( DC )
{
DrawModuleOutlines( DrawPanel, DC, Module );
Dessine_Segments_Dragges( DrawPanel, DC );
}
m_Pcb->m_Status_Pcb &= ~CHEVELU_LOCAL_OK;
}
}
/*********************************************/
static int ChangeSideMaskLayer(int masque)
static int ChangeSideMaskLayer( int masque )
/*********************************************/
/* Routine de recalcul du masque-layer lors des
echanges cote cu/cmp pour les couches CU/CMP specialisees
(cuivre, serigr., pate , soudure)
*/
* echanges cote cu/cmp pour les couches CU/CMP specialisees
* (cuivre, serigr., pate , soudure)
*/
{
int newmasque;
newmasque = masque & ~(CUIVRE_LAYER | CMP_LAYER |
SILKSCREEN_LAYER_CU | SILKSCREEN_LAYER_CMP |
ADHESIVE_LAYER_CU | ADHESIVE_LAYER_CMP |
SOLDERMASK_LAYER_CU | SOLDERMASK_LAYER_CMP |
SOLDERPASTE_LAYER_CU | SOLDERPASTE_LAYER_CMP |
ADHESIVE_LAYER_CU | ADHESIVE_LAYER_CMP);
int newmasque;
newmasque = masque & ~(CUIVRE_LAYER | CMP_LAYER |
SILKSCREEN_LAYER_CU | SILKSCREEN_LAYER_CMP |
ADHESIVE_LAYER_CU | ADHESIVE_LAYER_CMP |
SOLDERMASK_LAYER_CU | SOLDERMASK_LAYER_CMP |
SOLDERPASTE_LAYER_CU | SOLDERPASTE_LAYER_CMP |
ADHESIVE_LAYER_CU | ADHESIVE_LAYER_CMP);
if( masque & CUIVRE_LAYER )
newmasque |= CMP_LAYER;
if( masque & CMP_LAYER )
newmasque |= CUIVRE_LAYER;
if( masque & SILKSCREEN_LAYER_CU )
newmasque |= SILKSCREEN_LAYER_CMP;
if( masque & SILKSCREEN_LAYER_CMP )
newmasque |= SILKSCREEN_LAYER_CU;
if( masque & ADHESIVE_LAYER_CU )
newmasque |= ADHESIVE_LAYER_CMP;
if( masque & ADHESIVE_LAYER_CMP )
newmasque |= ADHESIVE_LAYER_CU;
if( masque & SOLDERMASK_LAYER_CU )
newmasque |= SOLDERMASK_LAYER_CMP;
if( masque & SOLDERMASK_LAYER_CMP )
newmasque |= SOLDERMASK_LAYER_CU;
if( masque & SOLDERPASTE_LAYER_CU )
newmasque |= SOLDERPASTE_LAYER_CMP;
if( masque & SOLDERPASTE_LAYER_CMP )
newmasque |= SOLDERPASTE_LAYER_CU;
if( masque & ADHESIVE_LAYER_CU )
newmasque |= ADHESIVE_LAYER_CMP;
if( masque & ADHESIVE_LAYER_CMP )
newmasque |= ADHESIVE_LAYER_CU;
return newmasque;
}
if( masque & CUIVRE_LAYER) newmasque |= CMP_LAYER;
if( masque & CMP_LAYER) newmasque |= CUIVRE_LAYER;
if( masque & SILKSCREEN_LAYER_CU) newmasque |= SILKSCREEN_LAYER_CMP;
if( masque & SILKSCREEN_LAYER_CMP) newmasque |= SILKSCREEN_LAYER_CU;
/*************************************/
int ChangeSideNumLayer( int oldlayer )
/*************************************/
if( masque & ADHESIVE_LAYER_CU) newmasque |= ADHESIVE_LAYER_CMP;
if( masque & ADHESIVE_LAYER_CMP) newmasque |= ADHESIVE_LAYER_CU;
/* Routine de recalcul du numero de couche lors des
* echanges cote cu/cmp pour les couches CU/CMP specialisees
* (cuivre, serigr., pate , soudure)
*/
{
int newlayer;
if( masque & SOLDERMASK_LAYER_CU) newmasque |= SOLDERMASK_LAYER_CMP;
if( masque & SOLDERMASK_LAYER_CMP) newmasque |= SOLDERMASK_LAYER_CU;
switch( oldlayer )
{
case CUIVRE_N:
newlayer = CMP_N; break;
if( masque & SOLDERPASTE_LAYER_CU) newmasque |= SOLDERPASTE_LAYER_CMP;
if( masque & SOLDERPASTE_LAYER_CMP) newmasque |= SOLDERPASTE_LAYER_CU;
case CMP_N:
newlayer = CUIVRE_N; break;
if( masque & ADHESIVE_LAYER_CU) newmasque |= ADHESIVE_LAYER_CMP;
if( masque & ADHESIVE_LAYER_CMP) newmasque |= ADHESIVE_LAYER_CU;
case SILKSCREEN_N_CU:
newlayer = SILKSCREEN_N_CMP; break;
return(newmasque);
}
case SILKSCREEN_N_CMP:
newlayer = SILKSCREEN_N_CU; break;
case ADHESIVE_N_CU:
newlayer = ADHESIVE_N_CMP; break;
/*************************************/
int ChangeSideNumLayer(int oldlayer)
/*************************************/
/* Routine de recalcul du numero de couche lors des
echanges cote cu/cmp pour les couches CU/CMP specialisees
(cuivre, serigr., pate , soudure)
*/
{
int newlayer;
case ADHESIVE_N_CMP:
newlayer = ADHESIVE_N_CU; break;
switch ( oldlayer )
{
case CUIVRE_N: newlayer = CMP_N; break;
case CMP_N: newlayer = CUIVRE_N; break;
case SOLDERMASK_N_CU:
newlayer = SOLDERMASK_N_CMP; break;
case SILKSCREEN_N_CU: newlayer = SILKSCREEN_N_CMP; break;
case SILKSCREEN_N_CMP: newlayer = SILKSCREEN_N_CU; break;
case SOLDERMASK_N_CMP:
newlayer = SOLDERMASK_N_CU; break;
case ADHESIVE_N_CU: newlayer = ADHESIVE_N_CMP; break;
case ADHESIVE_N_CMP: newlayer = ADHESIVE_N_CU; break;
case SOLDERPASTE_N_CU:
newlayer = SOLDERPASTE_N_CMP; break;
case SOLDERMASK_N_CU: newlayer = SOLDERMASK_N_CMP; break;
case SOLDERMASK_N_CMP: newlayer = SOLDERMASK_N_CU; break;
case SOLDERPASTE_N_CMP:
newlayer = SOLDERPASTE_N_CU; break;
case SOLDERPASTE_N_CU: newlayer = SOLDERPASTE_N_CMP; break;
case SOLDERPASTE_N_CMP: newlayer = SOLDERPASTE_N_CU; break;
default:
newlayer = oldlayer;
}
default: newlayer = oldlayer;
}
return(newlayer);
return newlayer;
}
/*****************************************************************/
void WinEDA_BasePcbFrame::Place_Module(MODULE * module, wxDC * DC)
void WinEDA_BasePcbFrame::Place_Module( MODULE* module, wxDC* DC )
/*****************************************************************/
/* Place a l'endroit pointe par la souris le module deja existant selectionne
auparavant.
Entree: module = num du module a replacer
DC ( si NULL: pas d'affichage a l'cran
Sortie :
mise a jour des nouvelles coord des differents elements du module
affichage a l'ecran du module
*/
* auparavant.
* Entree: module = num du module a replacer
* DC ( si NULL: pas d'affichage a l'�ran
* Sortie :
* mise a jour des nouvelles coord des differents elements du module
* affichage a l'ecran du module
*/
{
TRACK * pt_segm;
DRAG_SEGM * pt_drag;
wxPoint newpos;
if ( module == 0 ) return ;
m_CurrentScreen->SetModify();
m_Pcb->m_Status_Pcb &= ~( LISTE_CHEVELU_OK | CONNEXION_OK);
if(g_Show_Module_Ratsnest && (m_Pcb->m_Status_Pcb & LISTE_PAD_OK) && DC)
trace_ratsnest_module(DC);
newpos = m_CurrentScreen->m_Curseur;
module->SetPosition(newpos);
if ( DC ) module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
/* Tracage des segments dragges et liberation memoire */
if( g_DragSegmentList )
{
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
pt_segm = pt_drag->m_Segm;
pt_segm->SetState(EDIT,OFF);
if ( DC ) pt_segm->Draw(DrawPanel, DC, GR_OR);
}
EraseDragListe();
}
/* affichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
module->Display_Infos(this);
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
module->m_Flags = 0;
g_Drag_Pistes_On = FALSE;
TRACK* pt_segm;
DRAG_SEGM* pt_drag;
wxPoint newpos;
if( module == 0 )
return;
m_CurrentScreen->SetModify();
m_Pcb->m_Status_Pcb &= ~( LISTE_CHEVELU_OK | CONNEXION_OK);
if( g_Show_Module_Ratsnest && (m_Pcb->m_Status_Pcb & LISTE_PAD_OK) && DC )
trace_ratsnest_module( DC );
newpos = m_CurrentScreen->m_Curseur;
module->SetPosition( newpos );
if( DC )
module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
/* Tracage des segments dragges et liberation memoire */
if( g_DragSegmentList )
{
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
pt_segm = pt_drag->m_Segm;
pt_segm->SetState( EDIT, OFF );
if( DC )
pt_segm->Draw( DrawPanel, DC, GR_OR );
}
EraseDragListe();
}
/* affichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
module->Display_Infos( this );
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
module->m_Flags = 0;
g_Drag_Pistes_On = FALSE;
}
/***********************************************************************/
void WinEDA_BasePcbFrame::Rotate_Module(wxDC * DC, MODULE * module,
int angle, bool incremental)
void WinEDA_BasePcbFrame::Rotate_Module( wxDC* DC, MODULE* module,
int angle, bool incremental )
/***********************************************************************/
/*
Fait tourner l'empreinte de angle degres, dans le sens < 0.
Si incremental == TRUE, la rotation est faite a partir de la derniere orientation,
sinon le module est mis dans l'orientation absolue angle.
Si DC == NULL, le composant n'est pas redessine.
Sinon, il est efface, tourne et redessine
*/
* Fait tourner l'empreinte de angle degres, dans le sens < 0.
* Si incremental == TRUE, la rotation est faite a partir de la derniere orientation,
* sinon le module est mis dans l'orientation absolue angle.
* Si DC == NULL, le composant n'est pas redessine.
* Sinon, il est efface, tourne et redessine
*/
{
if ( module == NULL ) return;
m_CurrentScreen->SetModify();
/* efface ancienne position */
if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
{
if ( DC )
{
module->Draw(DrawPanel, DC, wxPoint(0,0), GR_XOR);
/* Reaffichage chevelu general si necessaire */
if(g_Show_Ratsnest) DrawGeneralRatsnest(DC);
}
}
else
{
/* reaffiche module en mouvement */
if ( DC )
{
DrawModuleOutlines(DrawPanel, DC, module);
Dessine_Segments_Dragges(DrawPanel, DC);
}
}
m_Pcb->m_Status_Pcb &= ~(LISTE_CHEVELU_OK | CONNEXION_OK);
if ( incremental )
module->SetOrientation(module->m_Orient + angle);
else
module->SetOrientation(angle);
module->Display_Infos(this);
if ( DC )
{
if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
{
module->Draw(DrawPanel, DC, wxPoint(0,0), GR_OR);
/* Reaffichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
}
else
{
/* reaffiche module en mouvement */
DrawModuleOutlines(DrawPanel, DC, module);
Dessine_Segments_Dragges(DrawPanel, DC);
}
}
if( module == NULL )
return;
m_CurrentScreen->SetModify();
/* efface ancienne position */
if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
{
if( DC )
{
module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_XOR );
/* Reaffichage chevelu general si necessaire */
if( g_Show_Ratsnest )
DrawGeneralRatsnest( DC );
}
}
else
{
/* reaffiche module en mouvement */
if( DC )
{
DrawModuleOutlines( DrawPanel, DC, module );
Dessine_Segments_Dragges( DrawPanel, DC );
}
}
m_Pcb->m_Status_Pcb &= ~(LISTE_CHEVELU_OK | CONNEXION_OK);
if( incremental )
module->SetOrientation( module->m_Orient + angle );
else
module->SetOrientation( angle );
module->Display_Infos( this );
if( DC )
{
if( !(module->m_Flags & IS_MOVED) ) /* Rotation simple */
{
module->Draw( DrawPanel, DC, wxPoint( 0, 0 ), GR_OR );
/* Reaffichage chevelu general si necessaire */
ReCompile_Ratsnest_After_Changes( DC );
}
else
{
/* reaffiche module en mouvement */
DrawModuleOutlines( DrawPanel, DC, module );
Dessine_Segments_Dragges( DrawPanel, DC );
}
}
}
......@@ -663,33 +744,33 @@ void WinEDA_BasePcbFrame::Rotate_Module(wxDC * DC, MODULE * module,
/* Redessine en mode XOR la silouhette du module */
/*************************************************/
void DrawModuleOutlines(WinEDA_DrawPanel * panel, wxDC * DC, MODULE * module)
void DrawModuleOutlines( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* module )
{
int pad_fill_tmp;
D_PAD* pt_pad;
if(module == NULL) return ;
module->DrawEdgesOnly(panel, DC, g_Offset_Module, GR_XOR);
if(g_Show_Pads_Module_in_Move)
{
pad_fill_tmp = DisplayOpt.DisplayPadFill;
DisplayOpt.DisplayPadFill = SKETCH; /* Trace en SKETCH en deplacement */
pt_pad = module->m_Pads;
for ( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext)
{
pt_pad->Draw(panel, DC, g_Offset_Module, GR_XOR);
}
DisplayOpt.DisplayPadFill = pad_fill_tmp;
}
if(g_Show_Module_Ratsnest && panel)
{
WinEDA_BasePcbFrame * frame = (WinEDA_BasePcbFrame * ) panel->m_Parent;
frame->build_ratsnest_module(DC, module);
frame->trace_ratsnest_module(DC);
}
int pad_fill_tmp;
D_PAD* pt_pad;
if( module == NULL )
return;
module->DrawEdgesOnly( panel, DC, g_Offset_Module, GR_XOR );
if( g_Show_Pads_Module_in_Move )
{
pad_fill_tmp = DisplayOpt.DisplayPadFill;
DisplayOpt.DisplayPadFill = SKETCH; /* Trace en SKETCH en deplacement */
pt_pad = module->m_Pads;
for( ; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
pt_pad->Draw( panel, DC, g_Offset_Module, GR_XOR );
}
DisplayOpt.DisplayPadFill = pad_fill_tmp;
}
if( g_Show_Module_Ratsnest && panel )
{
WinEDA_BasePcbFrame* frame = (WinEDA_BasePcbFrame*) panel->m_Parent;
frame->build_ratsnest_module( DC, module );
frame->trace_ratsnest_module( DC );
}
}
/****************************************************/
/* Edition des pistes */
/* Routines de duplication et deplacement de pistes */
/****************************************************/
/****************************************************/
/* Edition des pistes */
/* Routines de duplication et deplacement de pistes */
/****************************************************/
#include "fctsys.h"
#include "gr_basic.h"
......@@ -17,629 +17,663 @@
/* Routines externes */
static void Show_MoveTrack(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Exit_MoveTrack(WinEDA_DrawPanel * Panel, wxDC *DC);
static void Show_MoveTrack( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Exit_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC );
#if 0
/* Routines Locales */
static void Duplic_Track(COMMAND * Cmd);
static void Place_Dupl_Route(COMMAND * Cmd);
static void Duplic_Track( COMMAND* Cmd );
static void Place_Dupl_Route( COMMAND* Cmd );
#endif
/* variables locales */
static wxPoint PosInit, LastPos;
static TRACK * NewTrack; /* Nouvelle piste creee ou piste deplacee */
static int NbPtNewTrack;
static int Old_HightLigth_NetCode;
static bool Old_HightLigt_Status;
static TRACK* NewTrack; /* Nouvelle piste creee ou piste deplacee */
static int NbPtNewTrack;
static int Old_HightLigth_NetCode;
static bool Old_HightLigt_Status;
/**************************************************************/
static void Exit_MoveTrack(WinEDA_DrawPanel * Panel, wxDC *DC)
static void Exit_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC )
/***************************************************************/
/* routine d'annulation de la commande drag, copy ou move track si une piste est en cours
de tracage, ou de sortie de l'application EDITRACK.
Appel par la touche ESC
* de tracage, ou de sortie de l'application EDITRACK.
* Appel par la touche ESC
*/
{
TRACK * NextS;
int ii;
/* Effacement du trace en cours */
wxPoint oldpos = Panel->GetScreen()->m_Curseur;
Panel->GetScreen()->m_Curseur = PosInit;
Panel->ManageCurseur(Panel, DC, TRUE);
Panel->GetScreen()->m_Curseur = oldpos;
g_HightLigt_Status = FALSE;
( (WinEDA_PcbFrame *)Panel->m_Parent)->DrawHightLight( DC, g_HightLigth_NetCode) ;
if( NewTrack )
{
if (NewTrack->m_Flags & IS_NEW )
{
for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS)
{
if(NewTrack == NULL) break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
else /* Move : remise en ancienne position */
{
TRACK * Track = NewTrack;
int dx = LastPos.x - PosInit.x;
int dy = LastPos.y - PosInit.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext)
{
if( Track == NULL ) break;
Track->m_Start.x -= dx;
Track->m_Start.y -= dy;
Track->m_End.x -= dx;
Track->m_End.y -= dy;
Track->m_Flags = 0;
}
Trace_Une_Piste(Panel, DC, NewTrack,NbPtNewTrack,GR_OR);
}
NewTrack = NULL;
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
Panel->GetScreen()->m_CurrentItem = NULL;
Panel->m_Parent->EraseMsgBox();
/* Annulation deplacement et Redessin des segments dragges */
DRAG_SEGM * pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
TRACK * Track = pt_drag->m_Segm;
pt_drag->SetInitialValues();
Track->SetState(EDIT,OFF);
Track->m_Flags = 0;
Track->Draw(Panel, DC, GR_OR);
}
g_HightLigth_NetCode = Old_HightLigth_NetCode;
g_HightLigt_Status = Old_HightLigt_Status;
if(g_HightLigt_Status)
( (WinEDA_PcbFrame *)Panel->m_Parent)->DrawHightLight( DC, g_HightLigth_NetCode) ;
EraseDragListe();
}
TRACK* NextS;
int ii;
/* Effacement du trace en cours */
wxPoint oldpos = Panel->GetScreen()->m_Curseur;
Panel->GetScreen()->m_Curseur = PosInit;
Panel->ManageCurseur( Panel, DC, TRUE );
Panel->GetScreen()->m_Curseur = oldpos;
g_HightLigt_Status = FALSE;
( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
if( NewTrack )
{
if( NewTrack->m_Flags & IS_NEW )
{
for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS )
{
if( NewTrack == NULL )
break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
else /* Move : remise en ancienne position */
{
TRACK* Track = NewTrack;
int dx = LastPos.x - PosInit.x;
int dy = LastPos.y - PosInit.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
{
if( Track == NULL )
break;
Track->m_Start.x -= dx;
Track->m_Start.y -= dy;
Track->m_End.x -= dx;
Track->m_End.y -= dy;
Track->m_Flags = 0;
}
Trace_Une_Piste( Panel, DC, NewTrack, NbPtNewTrack, GR_OR );
}
NewTrack = NULL;
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
Panel->GetScreen()->m_CurrentItem = NULL;
Panel->m_Parent->EraseMsgBox();
/* Annulation deplacement et Redessin des segments dragges */
DRAG_SEGM* pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
TRACK* Track = pt_drag->m_Segm;
pt_drag->SetInitialValues();
Track->SetState( EDIT, OFF );
Track->m_Flags = 0;
Track->Draw( Panel, DC, GR_OR );
}
g_HightLigth_NetCode = Old_HightLigth_NetCode;
g_HightLigt_Status = Old_HightLigt_Status;
if( g_HightLigt_Status )
( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
EraseDragListe();
}
/*************************************************************************/
static void Show_MoveTrack(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
static void Show_MoveTrack( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/*************************************************************************/
/* redessin du contour de la piste lors des deplacements de la souris */
{
int ii, dx, dy;
TRACK * Track;
BASE_SCREEN * screen = panel->GetScreen();
int track_fill_copy = DisplayOpt.DisplayPcbTrackFill;
DisplayOpt.DisplayPcbTrackFill = SKETCH ;
erase = TRUE;
/* efface ancienne position si elle a ete deja dessinee */
if( erase )
{
if ( NewTrack ) Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,GR_XOR) ;
}
/* mise a jour des coordonnees des segments de la piste */
wxPoint Pos = screen->m_Curseur;
dx = Pos.x - LastPos.x;
dy = Pos.y - LastPos.y;
LastPos = Pos;
ii = NbPtNewTrack, Track = NewTrack;
for( ; ii > 0; ii--, Track = Track->Next() )
{
if( Track->m_Flags & STARTPOINT)
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT)
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
}
/* dessin de la nouvelle piste */
Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,GR_XOR) ;
/* Tracage des segments dragges */
DRAG_SEGM * pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
Track = pt_drag->m_Segm;
if ( erase ) Track->Draw(panel, DC, GR_XOR);
if( Track->m_Flags & STARTPOINT)
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT)
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
Track->Draw(panel, DC, GR_XOR);
}
DisplayOpt.DisplayPcbTrackFill = track_fill_copy ;
}
int ii, dx, dy;
TRACK* Track;
BASE_SCREEN* screen = panel->GetScreen();
int track_fill_copy = DisplayOpt.DisplayPcbTrackFill;
DisplayOpt.DisplayPcbTrackFill = SKETCH;
erase = TRUE;
/* efface ancienne position si elle a ete deja dessinee */
if( erase )
{
if( NewTrack )
Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, GR_XOR );
}
/* mise a jour des coordonnees des segments de la piste */
wxPoint Pos = screen->m_Curseur;
dx = Pos.x - LastPos.x;
dy = Pos.y - LastPos.y;
LastPos = Pos;
ii = NbPtNewTrack, Track = NewTrack;
for( ; ii > 0; ii--, Track = Track->Next() )
{
if( Track->m_Flags & STARTPOINT )
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT )
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
}
/* dessin de la nouvelle piste */
Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, GR_XOR );
/* Tracage des segments dragges */
DRAG_SEGM* pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
Track = pt_drag->m_Segm;
if( erase )
Track->Draw( panel, DC, GR_XOR );
if( Track->m_Flags & STARTPOINT )
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT )
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
Track->Draw( panel, DC, GR_XOR );
}
DisplayOpt.DisplayPcbTrackFill = track_fill_copy;
}
/***********************************************************************************/
void WinEDA_PcbFrame::Start_MoveOneTrackSegment(TRACK * track, wxDC * DC, bool Drag)
void WinEDA_PcbFrame::Start_MoveOneTrackSegment( TRACK* track, wxDC* DC, bool Drag )
/***********************************************************************************/
{
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if(g_HightLigt_Status) Hight_Light(DC);
if ( Drag && track->m_StructType == TYPEVIA)
{
track->m_Flags = IS_DRAGGED|STARTPOINT|ENDPOINT;
Collect_TrackSegmentsToDrag(DrawPanel, DC, track->m_Start,
track->ReturnMaskLayer(), track->m_NetCode);
NewTrack = track;
NbPtNewTrack = 1;
PosInit = track->m_Start;
}
else
{
int diag = track->IsPointOnEnds(GetScreen()->m_Curseur, -1);
wxPoint pos = (diag & STARTPOINT) ? track->m_Start : track->m_End;
Collect_TrackSegmentsToDrag(DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode);
track->m_Flags |= IS_DRAGGED;
NewTrack = NULL;
NbPtNewTrack = 0;
PosInit = pos;
}
LastPos = PosInit;
DrawPanel->ManageCurseur = Show_MoveTrack;
DrawPanel->ForceCloseManageCurseur = Exit_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode) ;
DrawPanel->ManageCurseur(DrawPanel, DC, TRUE);
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if( g_HightLigt_Status )
Hight_Light( DC );
if( Drag && track->m_StructType == TYPEVIA )
{
track->m_Flags = IS_DRAGGED | STARTPOINT | ENDPOINT;
Collect_TrackSegmentsToDrag( DrawPanel, DC, track->m_Start,
track->ReturnMaskLayer(), track->m_NetCode );
NewTrack = track;
NbPtNewTrack = 1;
PosInit = track->m_Start;
}
else
{
int diag = track->IsPointOnEnds( GetScreen()->m_Curseur, -1 );
wxPoint pos = (diag & STARTPOINT) ? track->m_Start : track->m_End;
Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode );
track->m_Flags |= IS_DRAGGED;
NewTrack = NULL;
NbPtNewTrack = 0;
PosInit = pos;
}
LastPos = PosInit;
DrawPanel->ManageCurseur = Show_MoveTrack;
DrawPanel->ForceCloseManageCurseur = Exit_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode );
DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
}
/**********************************************************************/
bool WinEDA_PcbFrame::PlaceDraggedTrackSegment(TRACK * Track, wxDC * DC)
bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC )
/**********************************************************************/
/* Place a dragged track segment or via */
{
int errdrc;
DRAG_SEGM * pt_drag;
if(Track == NULL ) return FALSE;
// DRC control:
if(Drc_On)
{
errdrc = Drc(this, DC, Track, m_Pcb->m_Track,1);
if(errdrc == BAD_DRC) return FALSE;
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext)
{
errdrc = Drc(this, DC, pt_drag->m_Segm, m_Pcb->m_Track,1);
if(errdrc == BAD_DRC) return FALSE;
}
}
// DRC Ok: place track segments
Track->m_Flags = 0;
Track->Draw(DrawPanel, DC, GR_OR);
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext)
{
Track = pt_drag->m_Segm;
Track->SetState(EDIT,OFF);
Track->m_Flags = 0;
Track->Draw(DrawPanel, DC, GR_OR);
}
EraseDragListe();
GetScreen()->SetModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
return TRUE;
int errdrc;
DRAG_SEGM* pt_drag;
if( Track == NULL )
return FALSE;
// DRC control:
if( Drc_On )
{
errdrc = Drc( this, DC, Track, m_Pcb->m_Track, 1 );
if( errdrc == BAD_DRC )
return FALSE;
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext )
{
errdrc = Drc( this, DC, pt_drag->m_Segm, m_Pcb->m_Track, 1 );
if( errdrc == BAD_DRC )
return FALSE;
}
}
// DRC Ok: place track segments
Track->m_Flags = 0;
Track->Draw( DrawPanel, DC, GR_OR );
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext )
{
Track = pt_drag->m_Segm;
Track->SetState( EDIT, OFF );
Track->m_Flags = 0;
Track->Draw( DrawPanel, DC, GR_OR );
}
EraseDragListe();
GetScreen()->SetModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
return TRUE;
}
#if 0
/***********************************************/
void WinEDA_PcbFrame::Place_Dupl_Route(Track * Track, wxDC * DC)
void WinEDA_PcbFrame::Place_Dupl_Route( Track* Track, wxDC* DC )
/******************************************/
/*
Routine de placement d'une piste (succession de segments)
*/
* Routine de placement d'une piste (succession de segments)
*/
{
D_PAD * pt_pad;
TRACK * pt_track, *Track, * pt_classe, *NextS;
int masquelayer;
EDA_BaseStruct * LockPoint;
int ii, old_net_code, new_net_code, DRC_error = 0;
wxDC * DC = Cmd->DC;
ActiveDrawPanel->ManageCurseur = NULL;
if( NewTrack == NULL ) return ;
old_net_code = NewTrack->net_code;
/* Placement du flag BUSY de la piste originelle, qui ne doit
pas etre vue dans les recherches de raccordement suivantes */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->SetState(BUSY, ON);
}
/* Detection du nouveau net_code */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->net_code = 0;
}
new_net_code = 0;
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack ; ii++, pt_track = (TRACK*)pt_track->Pnext)
{
/* Localisation de la pastille ou segment en debut de segment: */
masquelayer = tab_layer[pt_track->Layer];
LockPoint = LocateLockPoint(pt_track->m_Start.x,pt_track->m_Start.y,masquelayer);
if( LockPoint )
{
if ( LockPoint->m_StructType == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if ( new_net_code > 0 ) break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
new_net_code = Track->net_code;
if ( new_net_code > 0 ) break;
}
}
LockPoint = LocateLockPoint(pt_track->m_End.x,pt_track->m_End.y,masquelayer);
if( LockPoint )
{
if ( LockPoint->m_StructType == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if ( new_net_code > 0 ) break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
new_net_code = Track->net_code;
if ( new_net_code > 0 ) break;
}
}
}
/* Mise a jour du nouveau net code de la piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*)pt_track->Pnext)
{
pt_track->net_code = new_net_code;
}
/* Controle DRC de la nouvelle piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = pt_track->Next() )
{
if( Drc_On == RUN )
if( drc(DC, pt_track, pt_pcb->Track, 1) == BAD_DRC )
{
if( confirmation(" Erreur DRC, Place piste:") == YES ) continue;
else { DRC_error = 1; break; }
}
}
if( DRC_error == 0)
{
if(FlagState == MOVE_ROUTE)
{
/* copie nouvelle piste */
pt_track = NewTrack;
NewTrack = pt_track->Copy(NbPtNewTrack);
/* effacement ancienne ( chainage et liens mauvais */
ii = NbPtNewTrack;
for ( ; ii > 0; ii --, pt_track = NextS)
{
NextS = (TRACK*) pt_track->Pnext;
DeleteStructure(pt_track);
}
test_1_net_connexion(DC, old_net_code );
}
pt_classe = NewTrack->GetBestInsertPoint();
NewTrack->Insert(pt_classe);
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_OR) ;
/* Mise a jour des connexions sur pads et sur pistes */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = NextS)
{
NextS = (TRACK*)pt_track->Pnext;
pt_track->SetState(BEGIN_ONPAD|END_ONPAD, OFF);
masquelayer = tab_layer[pt_track->Layer];
/* Localisation de la pastille ou segment sur debut segment: */
LockPoint = LocateLockPoint(pt_track->m_Start.x,pt_track->m_Start.y,masquelayer);
if( LockPoint )
{
pt_track->start = LockPoint;
if ( LockPoint->m_StructType == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState(BEGIN_ONPAD, ON);
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
CreateLockPoint(&pt_track->m_Start.x,&pt_track->m_Start.y,Track,pt_track);
}
}
/* Localisation de la pastille ou segment sur fin de segment: */
LockPoint = LocateLockPoint(pt_track->m_End.x,pt_track->m_End.y,masquelayer);
if( LockPoint )
{
pt_track->end = LockPoint;
if ( LockPoint->m_StructType == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState(END_ONPAD, ON);
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK *) LockPoint;
CreateLockPoint(&pt_track->m_Start.x,&pt_track->m_Start.y,Track,pt_track);
}
}
}
/* Suppression du flag BUSY */
ii = NbPtNewTrack; pt_track = NewTrack;
for ( ; ii > 0; ii --, pt_track = (TRACK*) pt_track->Pnext)
{
pt_track->SetState(BUSY, OFF);
}
test_1_net_connexion(DC, new_net_code );
ActiveScreen->SetModify();
}
else /* Erreur DRC: Annulation commande */
{
DisplayOpt.DisplayPcbTrackFill = SKETCH ;
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_XOR);
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy ;
if(FlagState == MOVE_ROUTE)
{ /* Remise en position de la piste deplacee */
Track = NewTrack;
PosInitX -= Track->m_Start.x; PosInitY -= Track->m_Start.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext)
{
if( Track == NULL ) break;
Track->m_Start.x += PosInitX; Track->m_Start.y += PosInitY;
Track->m_End.x += PosInitX; Track->m_End.y += PosInitY;
Track->SetState(BUSY,OFF);
}
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_OR);
}
if (FlagState == COPY_ROUTE )
{ /* Suppression copie */
for( ii = 0; ii < NbPtNewTrack; NewTrack = NextS)
{
if(NewTrack == NULL) break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
}
NewTrack = NULL;
Affiche_Infos_Status_Pcb(Cmd);
if(Etat_Surbrillance) Hight_Light(DC);
D_PAD* pt_pad;
TRACK* pt_track, * Track, * pt_classe, * NextS;
int masquelayer;
EDA_BaseStruct* LockPoint;
int ii, old_net_code, new_net_code, DRC_error = 0;
wxDC* DC = Cmd->DC;
ActiveDrawPanel->ManageCurseur = NULL;
if( NewTrack == NULL )
return;
old_net_code = NewTrack->net_code;
/* Placement du flag BUSY de la piste originelle, qui ne doit
* pas etre vue dans les recherches de raccordement suivantes */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->SetState( BUSY, ON );
}
/* Detection du nouveau net_code */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->net_code = 0;
}
new_net_code = 0;
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
{
/* Localisation de la pastille ou segment en debut de segment: */
masquelayer = tab_layer[pt_track->Layer];
LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
if( LockPoint )
{
if( LockPoint->m_StructType == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if( new_net_code > 0 )
break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
new_net_code = Track->net_code;
if( new_net_code > 0 )
break;
}
}
LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
if( LockPoint )
{
if( LockPoint->m_StructType == TYPEPAD )
{
pt_pad = (D_PAD*) LockPoint;
new_net_code = pt_pad->net_code;
if( new_net_code > 0 )
break;
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
new_net_code = Track->net_code;
if( new_net_code > 0 )
break;
}
}
}
/* Mise a jour du nouveau net code de la piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->net_code = new_net_code;
}
/* Controle DRC de la nouvelle piste */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = pt_track->Next() )
{
if( Drc_On == RUN )
if( drc( DC, pt_track, pt_pcb->Track, 1 ) == BAD_DRC )
{
if( confirmation( " Erreur DRC, Place piste:" ) == YES )
continue;
else
{
DRC_error = 1; break;
}
}
}
if( DRC_error == 0 )
{
if( FlagState == MOVE_ROUTE )
{
/* copie nouvelle piste */
pt_track = NewTrack;
NewTrack = pt_track->Copy( NbPtNewTrack );
/* effacement ancienne ( chainage et liens mauvais */
ii = NbPtNewTrack;
for( ; ii > 0; ii--, pt_track = NextS )
{
NextS = (TRACK*) pt_track->Pnext;
DeleteStructure( pt_track );
}
test_1_net_connexion( DC, old_net_code );
}
pt_classe = NewTrack->GetBestInsertPoint();
NewTrack->Insert( pt_classe );
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
/* Mise a jour des connexions sur pads et sur pistes */
ii = 0; pt_track = NewTrack;
for( ; ii < NbPtNewTrack; ii++, pt_track = NextS )
{
NextS = (TRACK*) pt_track->Pnext;
pt_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
masquelayer = tab_layer[pt_track->Layer];
/* Localisation de la pastille ou segment sur debut segment: */
LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
if( LockPoint )
{
pt_track->start = LockPoint;
if( LockPoint->m_StructType == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState( BEGIN_ONPAD, ON );
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
}
}
/* Localisation de la pastille ou segment sur fin de segment: */
LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
if( LockPoint )
{
pt_track->end = LockPoint;
if( LockPoint->m_StructType == TYPEPAD )
{ /* fin de piste sur un pad */
pt_pad = (D_PAD*) LockPoint;
pt_track->SetState( END_ONPAD, ON );
}
else /* debut de piste sur un segment de piste */
{
Track = (TRACK*) LockPoint;
CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
}
}
}
/* Suppression du flag BUSY */
ii = NbPtNewTrack; pt_track = NewTrack;
for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
{
pt_track->SetState( BUSY, OFF );
}
test_1_net_connexion( DC, new_net_code );
ActiveScreen->SetModify();
}
else /* Erreur DRC: Annulation commande */
{
DisplayOpt.DisplayPcbTrackFill = SKETCH;
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
if( FlagState == MOVE_ROUTE )
{ /* Remise en position de la piste deplacee */
Track = NewTrack;
PosInitX -= Track->m_Start.x; PosInitY -= Track->m_Start.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
{
if( Track == NULL )
break;
Track->m_Start.x += PosInitX; Track->m_Start.y += PosInitY;
Track->m_End.x += PosInitX; Track->m_End.y += PosInitY;
Track->SetState( BUSY, OFF );
}
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
}
if( FlagState == COPY_ROUTE )
{ /* Suppression copie */
for( ii = 0; ii < NbPtNewTrack; NewTrack = NextS )
{
if( NewTrack == NULL )
break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
}
NewTrack = NULL;
Affiche_Infos_Status_Pcb( Cmd );
if( Etat_Surbrillance )
Hight_Light( DC );
}
/************************************************/
void WinEDA_PcbFrame::Start_CopieMove_Route(TRACK * track, wxDC * DC, bool Drag)
void WinEDA_PcbFrame::Start_CopieMove_Route( TRACK* track, wxDC* DC, bool Drag )
/************************************************/
/* Routine permettant la recopie d'une piste (suite de segments) deja tracee
*/
*/
{
int ii;
TRACK *pt_segm, *pt_track;
int masquelayer = tab_layer[ActiveScreen->Active_Layer];
wxDC * DC = Cmd->DC;
if( NewTrack ) return;
FlagState = (int)Cmd->Menu->param_inf;
/* Recherche de la piste sur la couche active (non zone) */
for(pt_segm = pt_pcb->Track; pt_segm != NULL; pt_segm = (TRACK*)pt_segm->Pnext)
{
pt_segm = Locate_Pistes(pt_segm,masquelayer, CURSEUR_OFF_GRILLE);
if( pt_segm == NULL ) break ;
break ;
}
if( pt_segm != NULL )
{
if (FlagState == COPY_ROUTE )
pt_track = Marque_Une_Piste(DC, pt_segm, &NbPtNewTrack, 0);
else pt_track = Marque_Une_Piste(DC, pt_segm, &NbPtNewTrack, GR_XOR);
if(NbPtNewTrack) /* Il y a NbPtNewTrack segments de piste a traiter */
{
/* effacement du flag BUSY de la piste originelle */
ii = NbPtNewTrack; pt_segm = pt_track;
for ( ; ii > 0; ii --, pt_segm = (TRACK*) pt_segm->Pnext)
{
pt_segm->SetState(BUSY, OFF);
}
if (FlagState == COPY_ROUTE )
NewTrack = pt_track->Copy(NbPtNewTrack);
else NewTrack = pt_track;
Affiche_Infos_Piste(Cmd, pt_track) ;
startX = ActiveScreen->Curseur_X;
startY = ActiveScreen->Curseur_Y;
Place_Dupl_Route_Item.State = WAIT;
ActiveDrawPanel->ManageCurseur = Show_Move_Piste;
DisplayOpt.DisplayPcbTrackFill = SKETCH ;
Trace_Une_Piste(DC, NewTrack,NbPtNewTrack,GR_XOR) ;
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy ;
PosInitX = NewTrack->m_Start.x; PosInitY = NewTrack->m_Start.y;
}
}
int ii;
TRACK* pt_segm, * pt_track;
int masquelayer = tab_layer[ActiveScreen->Active_Layer];
wxDC* DC = Cmd->DC;
if( NewTrack )
return;
FlagState = (int) Cmd->Menu->param_inf;
/* Recherche de la piste sur la couche active (non zone) */
for( pt_segm = pt_pcb->Track; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
{
pt_segm = Locate_Pistes( pt_segm, masquelayer, CURSEUR_OFF_GRILLE );
if( pt_segm == NULL )
break;
break;
}
if( pt_segm != NULL )
{
if( FlagState == COPY_ROUTE )
pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, 0 );
else
pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, GR_XOR );
if( NbPtNewTrack ) /* Il y a NbPtNewTrack segments de piste a traiter */
{
/* effacement du flag BUSY de la piste originelle */
ii = NbPtNewTrack; pt_segm = pt_track;
for( ; ii > 0; ii--, pt_segm = (TRACK*) pt_segm->Pnext )
{
pt_segm->SetState( BUSY, OFF );
}
if( FlagState == COPY_ROUTE )
NewTrack = pt_track->Copy( NbPtNewTrack );
else
NewTrack = pt_track;
Affiche_Infos_Piste( Cmd, pt_track );
startX = ActiveScreen->Curseur_X;
startY = ActiveScreen->Curseur_Y;
Place_Dupl_Route_Item.State = WAIT;
ActiveDrawPanel->ManageCurseur = Show_Move_Piste;
DisplayOpt.DisplayPcbTrackFill = SKETCH;
Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
PosInitX = NewTrack->m_Start.x; PosInitY = NewTrack->m_Start.y;
}
}
}
#endif
/************************************************************************/
EDA_BaseStruct * LocateLockPoint(BOARD * Pcb, wxPoint pos, int LayerMask)
EDA_BaseStruct* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
/************************************************************************/
/* Routine trouvant le point " d'accrochage " d'une extremite de piste.
Ce point peut etre un PAD ou un autre segment de piste
Retourne:
- pointeur sur ce PAD ou:
- pointeur sur le segment ou:
- NULL
Parametres d'appel:
coord pX, pY du point tst
masque des couches a tester
*/
* Ce point peut etre un PAD ou un autre segment de piste
* Retourne:
* - pointeur sur ce PAD ou:
* - pointeur sur le segment ou:
* - NULL
* Parametres d'appel:
* coord pX, pY du point tst
* masque des couches a tester
*/
{
D_PAD * pt_pad;
TRACK * ptsegm;
MODULE * Module;
/* detection du point type PAD */
pt_pad = NULL;
Module = Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*)Module->Pnext )
{
pt_pad = Locate_Pads(Module, pos, LayerMask);
if (pt_pad) return(pt_pad);
}
/* ici aucun pad n'a ete localise: detection d'un segment de piste */
ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos, LayerMask);
if( ptsegm == NULL )
ptsegm = Locate_Pistes( Pcb->m_Track, pos, LayerMask);
return(ptsegm);
D_PAD* pt_pad;
TRACK* ptsegm;
MODULE* Module;
/* detection du point type PAD */
pt_pad = NULL;
Module = Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
pt_pad = Locate_Pads( Module, pos, LayerMask );
if( pt_pad )
return pt_pad;
}
/* ici aucun pad n'a ete localise: detection d'un segment de piste */
ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos, LayerMask );
if( ptsegm == NULL )
ptsegm = Locate_Pistes( Pcb->m_Track, pos, LayerMask );
return ptsegm;
}
/******************************************************************************/
TRACK * CreateLockPoint(int *pX, int *pY, TRACK * ptsegm, TRACK * refsegm)
TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm )
/******************************************************************************/
/* Routine de creation d'un point intermediaire sur un segment
le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
retourne:
NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
a une extremite ou:
pointeur sur le segment cree
si refsegm != NULL refsegm est pointeur sur le segment incident,
et le point cree est l'intersection des 2 axes des segments ptsegm et
refsegm
retourne la valeur exacte de pX et pY
Si ptsegm pointe sur une via:
retourne la valeur exacte de pX et pY et ptsegm,
mais ne cree pas de point supplementaire
*/
* le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
* retourne:
* NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
* a une extremite ou:
* pointeur sur le segment cree
* si refsegm != NULL refsegm est pointeur sur le segment incident,
* et le point cree est l'intersection des 2 axes des segments ptsegm et
* refsegm
* retourne la valeur exacte de pX et pY
* Si ptsegm pointe sur une via:
* retourne la valeur exacte de pX et pY et ptsegm,
* mais ne cree pas de point supplementaire
*
*/
{
int cX, cY;
int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
int ox, oy, fx , fy; /* coord de refsegm / origine de prsegm */
TRACK * NewTrack;
if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) ) return(NULL);
if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) ) return(NULL);
/* le point n'est pas sur une extremite de piste */
if(ptsegm->m_StructType == TYPEVIA )
{
*pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
return(ptsegm);
}
/* calcul des coord vraies du point intermediaire dans le repere d'origine
= origine de ptsegm */
cX = *pX - ptsegm->m_Start.x;
int cX, cY;
int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */
TRACK* NewTrack;
if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) )
return NULL;
if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) )
return NULL;
/* le point n'est pas sur une extremite de piste */
if( ptsegm->m_StructType == TYPEVIA )
{
*pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
return ptsegm;
}
/* calcul des coord vraies du point intermediaire dans le repere d'origine
* = origine de ptsegm */
cX = *pX - ptsegm->m_Start.x;
cY = *pY - ptsegm->m_Start.y;
dx = ptsegm->m_End.x - ptsegm->m_Start.x;
dx = ptsegm->m_End.x - ptsegm->m_Start.x;
dy = ptsegm->m_End.y - ptsegm->m_Start.y;
// ***** A COMPLETER : non utilise
if ( refsegm )
{
ox = refsegm->m_Start.x - ptsegm->m_Start.x;
if( refsegm )
{
ox = refsegm->m_Start.x - ptsegm->m_Start.x;
oy = refsegm->m_Start.y - ptsegm->m_Start.y;
fx = refsegm->m_End.x - ptsegm->m_Start.x;
fx = refsegm->m_End.x - ptsegm->m_Start.x;
fy = refsegm->m_End.y - ptsegm->m_Start.y;
}
/* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
if ( dx == 0 ) cX = 0; /* segm horizontal */
else cY = (cX * dy) / dx;
}
/* creation du point intermediaire ( c'est a dire creation d'un nouveau
segment, debutant au point intermediaire */
/* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
if( dx == 0 )
cX = 0; /* segm horizontal */
else
cY = (cX * dy) / dx;
cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
NewTrack = ptsegm->Copy();
/* creation du point intermediaire ( c'est a dire creation d'un nouveau
* segment, debutant au point intermediaire */
NewTrack->Insert(NULL, ptsegm);
/* correction du pointeur de fin du nouveau segment */
NewTrack->end = ptsegm->end;
cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
NewTrack = ptsegm->Copy();
/* le segment primitif finit au nouveau point : */
ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
ptsegm->SetState(END_ONPAD, OFF);
NewTrack->Insert( NULL, ptsegm );
/* correction du pointeur de fin du nouveau segment */
NewTrack->end = ptsegm->end;
/* le nouveau segment debute au nouveau point : */
ptsegm = NewTrack;;
ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
ptsegm->SetState(BEGIN_ONPAD, OFF);
*pX = cX; *pY = cY;
/* le segment primitif finit au nouveau point : */
ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
ptsegm->SetState( END_ONPAD, OFF );
return(ptsegm);
/* le nouveau segment debute au nouveau point : */
ptsegm = NewTrack;;
ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
ptsegm->SetState( BEGIN_ONPAD, OFF );
*pX = cX; *pY = cY;
return ptsegm;
}
/****************************************************/
/* Track editing */
/* routines to move and drag track segments or node */
/****************************************************/
/****************************************************/
/* Track editing */
/* routines to move and drag track segments or node */
/****************************************************/
#include "fctsys.h"
#include "gr_basic.h"
......@@ -18,853 +18,937 @@
/* local functions */
static void Show_MoveNode(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Show_Drag_Track_Segment_With_Cte_Slope(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Abort_MoveTrack(WinEDA_DrawPanel * Panel, wxDC *DC);
static bool InitialiseDragParameters(void);
static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Show_Drag_Track_Segment_With_Cte_Slope( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC );
static bool InitialiseDragParameters( void );
/* variables locales */
static wxPoint PosInit, s_LastPos;
static TRACK * NewTrack; /* Nouvelle piste creee ou piste deplacee */
static int NbPtNewTrack;
static int Old_HightLigth_NetCode;
static bool Old_HightLigt_Status;
static double s_StartSegmentSlope, s_EndSegmentSlope, s_MovingSegmentSlope,
s_StartSegment_Yorg, s_EndSegment_Yorg,
s_MovingSegment_Yorg; //slope and intercept parameters of lines
bool s_StartPointVertical,s_EndPointVertical,
s_MovingSegmentVertical,s_MovingSegmentHorizontal,
s_StartPointHorizontal,s_EndPointHorizontal; // vertical or horizontal line indicators
bool s_StartSegmentPresent, s_EndSegmentPresent;
static TRACK* NewTrack; /* Nouvelle piste creee ou piste deplacee */
static int NbPtNewTrack;
static int Old_HightLigth_NetCode;
static bool Old_HightLigt_Status;
static double s_StartSegmentSlope, s_EndSegmentSlope, s_MovingSegmentSlope,
s_StartSegment_Yorg, s_EndSegment_Yorg,
s_MovingSegment_Yorg; //slope and intercept parameters of lines
bool s_StartPointVertical, s_EndPointVertical,
s_MovingSegmentVertical, s_MovingSegmentHorizontal,
s_StartPointHorizontal, s_EndPointHorizontal; // vertical or horizontal line indicators
bool s_StartSegmentPresent, s_EndSegmentPresent;
/**************************************************************/
static void Abort_MoveTrack(WinEDA_DrawPanel * Panel, wxDC *DC)
static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC )
/***************************************************************/
/* routine d'annulation de la commande drag, copy ou move track si une piste est en cours
de tracage, ou de sortie de l'application EDITRACK.
*/
* de tracage, ou de sortie de l'application EDITRACK.
*/
{
TRACK * NextS;
int ii;
/* Erase the current drawings */
wxPoint oldpos = Panel->GetScreen()->m_Curseur;
Panel->GetScreen()->m_Curseur = PosInit;
if ( Panel->ManageCurseur ) Panel->ManageCurseur(Panel, DC, TRUE);
Panel->GetScreen()->m_Curseur = oldpos;
g_HightLigt_Status = FALSE;
( (WinEDA_PcbFrame *)Panel->m_Parent)->DrawHightLight( DC, g_HightLigth_NetCode) ;
if( NewTrack )
{
if (NewTrack->m_Flags & IS_NEW )
{
for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS)
{
if(NewTrack == NULL) break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
else /* Move : remise en ancienne position */
{
TRACK * Track = NewTrack;
int dx = s_LastPos.x - PosInit.x;
int dy = s_LastPos.y - PosInit.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext)
{
if( Track == NULL ) break;
Track->m_Start.x -= dx;
Track->m_Start.y -= dy;
Track->m_End.x -= dx;
Track->m_End.y -= dy;
Track->m_Flags = 0;
}
Trace_Une_Piste(Panel, DC, NewTrack,NbPtNewTrack,GR_OR);
}
NewTrack = NULL;
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
Panel->GetScreen()->m_CurrentItem = NULL;
Panel->m_Parent->EraseMsgBox();
/* Annulation deplacement et Redessin des segments dragges */
DRAG_SEGM * pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
TRACK * Track = pt_drag->m_Segm;
pt_drag->SetInitialValues();
Track->SetState(EDIT,OFF);
Track->m_Flags = 0;
Track->Draw(Panel, DC, GR_OR);
}
g_HightLigth_NetCode = Old_HightLigth_NetCode;
g_HightLigt_Status = Old_HightLigt_Status;
if(g_HightLigt_Status)
( (WinEDA_PcbFrame *)Panel->m_Parent)->DrawHightLight( DC, g_HightLigth_NetCode) ;
EraseDragListe();
TRACK* NextS;
int ii;
/* Erase the current drawings */
wxPoint oldpos = Panel->GetScreen()->m_Curseur;
Panel->GetScreen()->m_Curseur = PosInit;
if( Panel->ManageCurseur )
Panel->ManageCurseur( Panel, DC, TRUE );
Panel->GetScreen()->m_Curseur = oldpos;
g_HightLigt_Status = FALSE;
( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
if( NewTrack )
{
if( NewTrack->m_Flags & IS_NEW )
{
for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS )
{
if( NewTrack == NULL )
break;
NextS = (TRACK*) NewTrack->Pnext;
delete NewTrack;
}
}
else /* Move : remise en ancienne position */
{
TRACK* Track = NewTrack;
int dx = s_LastPos.x - PosInit.x;
int dy = s_LastPos.y - PosInit.y;
for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
{
if( Track == NULL )
break;
Track->m_Start.x -= dx;
Track->m_Start.y -= dy;
Track->m_End.x -= dx;
Track->m_End.y -= dy;
Track->m_Flags = 0;
}
Trace_Une_Piste( Panel, DC, NewTrack, NbPtNewTrack, GR_OR );
}
NewTrack = NULL;
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
Panel->GetScreen()->m_CurrentItem = NULL;
Panel->m_Parent->EraseMsgBox();
/* Annulation deplacement et Redessin des segments dragges */
DRAG_SEGM* pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
TRACK* Track = pt_drag->m_Segm;
pt_drag->SetInitialValues();
Track->SetState( EDIT, OFF );
Track->m_Flags = 0;
Track->Draw( Panel, DC, GR_OR );
}
g_HightLigth_NetCode = Old_HightLigth_NetCode;
g_HightLigt_Status = Old_HightLigt_Status;
if( g_HightLigt_Status )
( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
EraseDragListe();
}
/*************************************************************************/
static void Show_MoveNode(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/*************************************************************************/
/* Redraw the moved node according to the mouse cursor position */
{
int ii, dx, dy;
TRACK * Track;
BASE_SCREEN * screen = panel->GetScreen();
int track_fill_copy = DisplayOpt.DisplayPcbTrackFill;
int draw_mode = GR_XOR | GR_SURBRILL;
DisplayOpt.DisplayPcbTrackFill = FALSE ;
erase = TRUE;
/* erase the current moved track segments from screen */
if( erase )
{
if ( NewTrack ) Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,draw_mode) ;
}
/* set the new track coordinates */
wxPoint Pos = screen->m_Curseur;
dx = Pos.x - s_LastPos.x;
dy = Pos.y - s_LastPos.y;
s_LastPos = Pos;
ii = NbPtNewTrack, Track = NewTrack;
for( ; (ii > 0) && (Track != NULL); ii--, Track = Track->Next() )
{
if( Track->m_Flags & STARTPOINT)
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT)
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
}
/* Redraw the current moved track segments */
Trace_Une_Piste(panel, DC, NewTrack,NbPtNewTrack,GR_XOR) ;
DRAG_SEGM * pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
Track = pt_drag->m_Segm;
if ( erase ) Track->Draw(panel, DC, draw_mode);
if( Track->m_Flags & STARTPOINT)
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT)
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
Track->Draw(panel, DC, draw_mode);
}
DisplayOpt.DisplayPcbTrackFill = track_fill_copy ;
}
int ii, dx, dy;
TRACK* Track;
BASE_SCREEN* screen = panel->GetScreen();
int track_fill_copy = DisplayOpt.DisplayPcbTrackFill;
int draw_mode = GR_XOR | GR_SURBRILL;
DisplayOpt.DisplayPcbTrackFill = FALSE;
erase = TRUE;
/* erase the current moved track segments from screen */
if( erase )
{
if( NewTrack )
Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, draw_mode );
}
/* set the new track coordinates */
wxPoint Pos = screen->m_Curseur;
dx = Pos.x - s_LastPos.x;
dy = Pos.y - s_LastPos.y;
s_LastPos = Pos;
ii = NbPtNewTrack, Track = NewTrack;
for( ; (ii > 0) && (Track != NULL); ii--, Track = Track->Next() )
{
if( Track->m_Flags & STARTPOINT )
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT )
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
}
/* Redraw the current moved track segments */
Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, GR_XOR );
DRAG_SEGM* pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
Track = pt_drag->m_Segm;
if( erase )
Track->Draw( panel, DC, draw_mode );
if( Track->m_Flags & STARTPOINT )
{
Track->m_Start.x += dx; Track->m_Start.y += dy;
}
if( Track->m_Flags & ENDPOINT )
{
Track->m_End.x += dx; Track->m_End.y += dy;
}
Track->Draw( panel, DC, draw_mode );
}
DisplayOpt.DisplayPcbTrackFill = track_fill_copy;
}
/*************************************************************************/
static void Show_Drag_Track_Segment_With_Cte_Slope(WinEDA_DrawPanel * panel,
wxDC * DC, bool erase)
static void Show_Drag_Track_Segment_With_Cte_Slope( WinEDA_DrawPanel* panel,
wxDC* DC, bool erase )
/*************************************************************************/
/* drawing the track segment movement
> s_MovingSegmentSlope slope = moving track segment slope
> s_StartSegmentSlope slope = slope of the segment connected to the start point of the moving segment
> s_EndSegmentSlope slope = slope of the segment connected to the end point of the moving segment
moved segment function :
yt=s_MovingSegmentSlope * x + s_MovingSegment_Yorg
segment connected to moved segment's start:
y1 = s_StartSegmentSlope * x + s_StartSegment_Yorg
segment connected to moved segment's end:
y2=s_EndSegmentSlope * x + s_EndSegment_Yorg
first intersection point will be located at
y1=yt ->
xi1=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_StartSegmentSlope-s_MovingSegmentSlope)
yi1=s_MovingSegmentSlope*xi1+s_MovingSegment_Yorg
or yi1=s_StartSegmentSlope*xi1+s_MovingSegment_Yorg
second intersection point
y2=yt ->
xi2=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_MovingSegmentSlope-s_MovingSegmentSlope)
yi2=s_MovingSegmentSlope*xi2+s_MovingSegment_Yorg
or yi1=s_EndSegmentSlope*xi2+s_MovingSegment_Yorg
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!! special attention to vertical segments because
!!!!! their slope=infinite
!!!!! intersection point will be calculated using the
!!!!! segment intersecting it
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Slope parametres are computed once, because they can become undetermined when moving segments
(i.e. when a segment lenght is 0) and we want keep them constant
*/
* > s_MovingSegmentSlope slope = moving track segment slope
* > s_StartSegmentSlope slope = slope of the segment connected to the start point of the moving segment
* > s_EndSegmentSlope slope = slope of the segment connected to the end point of the moving segment
*
* moved segment function :
* yt=s_MovingSegmentSlope * x + s_MovingSegment_Yorg
*
* segment connected to moved segment's start:
* y1 = s_StartSegmentSlope * x + s_StartSegment_Yorg
*
* segment connected to moved segment's end:
* y2=s_EndSegmentSlope * x + s_EndSegment_Yorg
*
* first intersection point will be located at
* y1=yt ->
* xi1=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_StartSegmentSlope-s_MovingSegmentSlope)
* yi1=s_MovingSegmentSlope*xi1+s_MovingSegment_Yorg
* or yi1=s_StartSegmentSlope*xi1+s_MovingSegment_Yorg
*
* second intersection point
* y2=yt ->
* xi2=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_MovingSegmentSlope-s_MovingSegmentSlope)
* yi2=s_MovingSegmentSlope*xi2+s_MovingSegment_Yorg
* or yi1=s_EndSegmentSlope*xi2+s_MovingSegment_Yorg
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!! special attention to vertical segments because
* !!!!! their slope=infinite
* !!!!! intersection point will be calculated using the
* !!!!! segment intersecting it
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Slope parametres are computed once, because they can become undetermined when moving segments
* (i.e. when a segment lenght is 0) and we want keep them constant
*/
{
double xi1=0,yi1=0,xi2=0,yi2=0; // calculated intersection points
double tx1,tx2,ty1,ty2; // temporary storage of points
int dx, dy;
BASE_SCREEN * screen = panel->GetScreen();
bool update=true;
TRACK * Track;
DRAG_SEGM * TrackSegWrapper = g_DragSegmentList;
TRACK * tSegmentToStart = NULL, * tSegmentToEnd = NULL;
if ( TrackSegWrapper == NULL ) return;
Track = TrackSegWrapper->m_Segm; if (Track == NULL ) return;
TrackSegWrapper = TrackSegWrapper->Pnext;
if ( TrackSegWrapper )
{
if ( s_EndSegmentPresent )
{
tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
TrackSegWrapper = TrackSegWrapper->Pnext;
}
if ( s_StartSegmentPresent )
{
if ( TrackSegWrapper )
tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
}
}
int draw_mode = GR_XOR | GR_SURBRILL;
/* Undraw the current moved track segments before modification*/
double xi1 = 0, yi1 = 0, xi2 = 0, yi2 = 0; // calculated intersection points
double tx1, tx2, ty1, ty2; // temporary storage of points
int dx, dy;
BASE_SCREEN* screen = panel->GetScreen();
bool update = true;
TRACK* Track;
DRAG_SEGM* TrackSegWrapper = g_DragSegmentList;
TRACK* tSegmentToStart = NULL, * tSegmentToEnd = NULL;
if( TrackSegWrapper == NULL )
return;
Track = TrackSegWrapper->m_Segm; if( Track == NULL )
return;
TrackSegWrapper = TrackSegWrapper->Pnext;
if( TrackSegWrapper )
{
if( s_EndSegmentPresent )
{
tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
TrackSegWrapper = TrackSegWrapper->Pnext;
}
if( s_StartSegmentPresent )
{
if( TrackSegWrapper )
tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
}
}
int draw_mode = GR_XOR | GR_SURBRILL;
/* Undraw the current moved track segments before modification*/
// if( erase )
{
Track->Draw(panel, DC, draw_mode);
if ( tSegmentToStart ) tSegmentToStart->Draw(panel, DC, draw_mode);
if ( tSegmentToEnd ) tSegmentToEnd->Draw(panel, DC, draw_mode);
}
/* Compute the new track segment position */
wxPoint Pos = screen->m_Curseur;
{
Track->Draw( panel, DC, draw_mode );
if( tSegmentToStart )
tSegmentToStart->Draw( panel, DC, draw_mode );
if( tSegmentToEnd )
tSegmentToEnd->Draw( panel, DC, draw_mode );
}
/* Compute the new track segment position */
wxPoint Pos = screen->m_Curseur;
dx = Pos.x - s_LastPos.x;
dy = Pos.y - s_LastPos.y;
//move the line by dx and dy
tx1 = (double)(Track->m_Start.x + dx);
ty1 = (double)(Track->m_Start.y + dy);
tx2 = (double)(Track->m_End.x + dx);
ty2 = (double)(Track->m_End.y + dy);
// recalculate the segments new parameters and intersection points
// only the intercept will change, segment slopes does not change
// because we are moving parallel with is initial state
if (!s_MovingSegmentVertical) {
s_MovingSegment_Yorg = ty1 - (s_MovingSegmentSlope * tx1);
}
if ((!s_EndPointVertical) && (!s_MovingSegmentVertical)) {
xi2 = (s_MovingSegment_Yorg - s_EndSegment_Yorg) / (s_EndSegmentSlope - s_MovingSegmentSlope);
} else {
if (!s_EndPointVertical) {
xi2 = tx2;
} else {
//P1=P2
if (!s_EndPointHorizontal) {
xi2 = tx2-dx;
} else {
update=false;
}
}
}
if (!s_MovingSegmentVertical)
{
yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
}
else
{
if (!s_EndPointVertical) {
yi2 = s_EndSegmentSlope * (xi2) + s_EndSegment_Yorg;
}
else
{
if (!s_EndPointHorizontal) {
update=false;
}
else {
yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
}
}
}
if ((!s_StartPointVertical) && (!s_MovingSegmentVertical))
{
xi1 = (s_MovingSegment_Yorg - s_StartSegment_Yorg) / (s_StartSegmentSlope - s_MovingSegmentSlope);
}
else
{
if (!s_StartPointVertical) {
xi1 = tx1;
}
else
{
//P1=P2
if (!s_StartPointHorizontal) {
xi1 = tx1-dx;
}
else
{
if (!s_StartPointHorizontal) {
update=false;
}
}
}
}
if (!s_MovingSegmentVertical) {
yi1 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
}
else {
if (!s_StartPointVertical) {
yi1 = s_StartSegmentSlope * (xi1) + s_StartSegment_Yorg;
} else {
if (!s_StartPointHorizontal) {
update=false;
} else {
yi2 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
}
}
}
// update the segment coordinates (if possible)
if ( tSegmentToStart == NULL )
{
xi1 = tx1; yi1 = ty1;
}
if ( tSegmentToEnd == NULL )
{
xi2 = tx2; yi2 = ty2;
}
if (update)
{
s_LastPos=Pos;
Track->m_Start.x = (int) round(xi1);
Track->m_Start.y = (int) round(yi1);
Track->m_End.x = (int) round(xi2);
Track->m_End.y = (int) round(yi2);
if ( tSegmentToEnd )
{
if ( tSegmentToEnd->m_Flags & STARTPOINT )
tSegmentToEnd->m_Start = Track->m_End;
else tSegmentToEnd->m_End = Track->m_End;
}
if ( tSegmentToStart )
{
if ( tSegmentToStart->m_Flags & STARTPOINT )
tSegmentToStart->m_Start = Track->m_Start;
else tSegmentToStart->m_End = Track->m_Start;
}
}
Track->Draw(panel, DC, draw_mode);
if ( tSegmentToStart ) tSegmentToStart->Draw(panel, DC, draw_mode);
if ( tSegmentToEnd ) tSegmentToEnd->Draw(panel, DC, draw_mode);
//move the line by dx and dy
tx1 = (double) (Track->m_Start.x + dx);
ty1 = (double) (Track->m_Start.y + dy);
tx2 = (double) (Track->m_End.x + dx);
ty2 = (double) (Track->m_End.y + dy);
// recalculate the segments new parameters and intersection points
// only the intercept will change, segment slopes does not change
// because we are moving parallel with is initial state
if( !s_MovingSegmentVertical )
{
s_MovingSegment_Yorg = ty1 - (s_MovingSegmentSlope * tx1);
}
if( (!s_EndPointVertical) && (!s_MovingSegmentVertical) )
{
xi2 = (s_MovingSegment_Yorg -
s_EndSegment_Yorg) / (s_EndSegmentSlope - s_MovingSegmentSlope);
}
else
{
if( !s_EndPointVertical )
{
xi2 = tx2;
}
else
{
//P1=P2
if( !s_EndPointHorizontal )
{
xi2 = tx2 - dx;
}
else
{
update = false;
}
}
}
if( !s_MovingSegmentVertical )
{
yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
}
else
{
if( !s_EndPointVertical )
{
yi2 = s_EndSegmentSlope * (xi2) + s_EndSegment_Yorg;
}
else
{
if( !s_EndPointHorizontal )
{
update = false;
}
else
{
yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
}
}
}
if( (!s_StartPointVertical) && (!s_MovingSegmentVertical) )
{
xi1 = (s_MovingSegment_Yorg -
s_StartSegment_Yorg) / (s_StartSegmentSlope - s_MovingSegmentSlope);
}
else
{
if( !s_StartPointVertical )
{
xi1 = tx1;
}
else
{
//P1=P2
if( !s_StartPointHorizontal )
{
xi1 = tx1 - dx;
}
else
{
if( !s_StartPointHorizontal )
{
update = false;
}
}
}
}
if( !s_MovingSegmentVertical )
{
yi1 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
}
else
{
if( !s_StartPointVertical )
{
yi1 = s_StartSegmentSlope * (xi1) + s_StartSegment_Yorg;
}
else
{
if( !s_StartPointHorizontal )
{
update = false;
}
else
{
yi2 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
}
}
}
// update the segment coordinates (if possible)
if( tSegmentToStart == NULL )
{
xi1 = tx1; yi1 = ty1;
}
if( tSegmentToEnd == NULL )
{
xi2 = tx2; yi2 = ty2;
}
if( update )
{
s_LastPos = Pos;
Track->m_Start.x = (int) round( xi1 );
Track->m_Start.y = (int) round( yi1 );
Track->m_End.x = (int) round( xi2 );
Track->m_End.y = (int) round( yi2 );
if( tSegmentToEnd )
{
if( tSegmentToEnd->m_Flags & STARTPOINT )
tSegmentToEnd->m_Start = Track->m_End;
else
tSegmentToEnd->m_End = Track->m_End;
}
if( tSegmentToStart )
{
if( tSegmentToStart->m_Flags & STARTPOINT )
tSegmentToStart->m_Start = Track->m_Start;
else
tSegmentToStart->m_End = Track->m_Start;
}
}
Track->Draw( panel, DC, draw_mode );
if( tSegmentToStart )
tSegmentToStart->Draw( panel, DC, draw_mode );
if( tSegmentToEnd )
tSegmentToEnd->Draw( panel, DC, draw_mode );
}
/**********************************/
bool InitialiseDragParameters(void)
bool InitialiseDragParameters( void )
/**********************************/
/* Init variables (slope, Y intersect point, flags) for Show_Drag_Track_Segment_With_Cte_Slope()
return TRUE if Ok, FALSE if dragging is not possible
(2 colinear segments)
*/
* return TRUE if Ok, FALSE if dragging is not possible
* (2 colinear segments)
*/
{
double tx1,tx2,ty1,ty2; // temporary storage of points
TRACK * Track;
DRAG_SEGM * TrackSegWrapper = g_DragSegmentList;
TRACK * tSegmentToStart = NULL, * tSegmentToEnd = NULL;
if ( TrackSegWrapper == NULL ) return FALSE;
Track = TrackSegWrapper->m_Segm;
if (Track == NULL ) return FALSE;
TrackSegWrapper = TrackSegWrapper->Pnext;
if ( TrackSegWrapper )
{
if ( s_EndSegmentPresent )
{
tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
TrackSegWrapper = TrackSegWrapper->Pnext;
}
if ( s_StartSegmentPresent )
{
if ( TrackSegWrapper )
tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
}
}
s_StartPointVertical=false;
s_EndPointVertical=false;
s_MovingSegmentVertical=false;
s_StartPointHorizontal=false;
s_EndPointHorizontal=false;
s_MovingSegmentHorizontal=false;
double tx1, tx2, ty1, ty2; // temporary storage of points
TRACK* Track;
DRAG_SEGM* TrackSegWrapper = g_DragSegmentList;
TRACK* tSegmentToStart = NULL, * tSegmentToEnd = NULL;
if( TrackSegWrapper == NULL )
return FALSE;
Track = TrackSegWrapper->m_Segm;
if( Track == NULL )
return FALSE;
TrackSegWrapper = TrackSegWrapper->Pnext;
if( TrackSegWrapper )
{
if( s_EndSegmentPresent )
{
tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
TrackSegWrapper = TrackSegWrapper->Pnext;
}
if( s_StartSegmentPresent )
{
if( TrackSegWrapper )
tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
}
}
s_StartPointVertical = false;
s_EndPointVertical = false;
s_MovingSegmentVertical = false;
s_StartPointHorizontal = false;
s_EndPointHorizontal = false;
s_MovingSegmentHorizontal = false;
// Init parameters for the starting point of the moved segment
if ( tSegmentToStart )
{
if ( tSegmentToStart->m_Flags & ENDPOINT )
{
tx1=(double)tSegmentToStart->m_Start.x;
ty1=(double)tSegmentToStart->m_Start.y;
tx2=(double)tSegmentToStart->m_End.x;
ty2=(double)tSegmentToStart->m_End.y;
}
else
{
tx1=(double)tSegmentToStart->m_End.x;
ty1=(double)tSegmentToStart->m_End.y;
tx2=(double)tSegmentToStart->m_Start.x;
ty2=(double)tSegmentToStart->m_Start.y;
}
}
else // move the start point on a line starting at Track->m_Start, and perpendicular to Track
{
tx1 = (double)Track->m_Start.x;
ty1 = (double)Track->m_Start.y;
tx2 = (double)Track->m_End.x;
ty2 = (double)Track->m_End.y;
RotatePoint(&tx2, &ty2, tx1, ty1, 900);
}
if (tx1!=tx2) {
s_StartSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
s_StartSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
} else {
s_StartPointVertical=true; //signal first segment vertical
}
if (ty1==ty2) {
s_StartPointHorizontal=true;
}
if( tSegmentToStart )
{
if( tSegmentToStart->m_Flags & ENDPOINT )
{
tx1 = (double) tSegmentToStart->m_Start.x;
ty1 = (double) tSegmentToStart->m_Start.y;
tx2 = (double) tSegmentToStart->m_End.x;
ty2 = (double) tSegmentToStart->m_End.y;
}
else
{
tx1 = (double) tSegmentToStart->m_End.x;
ty1 = (double) tSegmentToStart->m_End.y;
tx2 = (double) tSegmentToStart->m_Start.x;
ty2 = (double) tSegmentToStart->m_Start.y;
}
}
else // move the start point on a line starting at Track->m_Start, and perpendicular to Track
{
tx1 = (double) Track->m_Start.x;
ty1 = (double) Track->m_Start.y;
tx2 = (double) Track->m_End.x;
ty2 = (double) Track->m_End.y;
RotatePoint( &tx2, &ty2, tx1, ty1, 900 );
}
if( tx1!=tx2 )
{
s_StartSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
s_StartSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
}
else
{
s_StartPointVertical = true; //signal first segment vertical
}
if( ty1==ty2 )
{
s_StartPointHorizontal = true;
}
// Init parameters for the ending point of the moved segment
if ( tSegmentToEnd )
{
//check if second line is vertical
if ( tSegmentToEnd->m_Flags & STARTPOINT )
{
tx1=(double)tSegmentToEnd->m_Start.x;
ty1=(double)tSegmentToEnd->m_Start.y;
tx2=(double)tSegmentToEnd->m_End.x;
ty2=(double)tSegmentToEnd->m_End.y;
}
else
{
tx1=(double)tSegmentToEnd->m_End.x;
ty1=(double)tSegmentToEnd->m_End.y;
tx2=(double)tSegmentToEnd->m_Start.x;
ty2=(double)tSegmentToEnd->m_Start.y;
}
}
else // move the start point on a line starting at Track->m_End, and perpendicular to Track
{
tx1 = (double)Track->m_End.x;
ty1 = (double)Track->m_End.y;
tx2 = (double)Track->m_Start.x;
ty2 = (double)Track->m_Start.y;
RotatePoint(&tx2, &ty2, tx1, ty1, -900);
}
if (tx2!=tx1) {
s_EndSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
s_EndSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
} else {
s_EndPointVertical = true; //signal second segment vertical
}
if (ty1==ty2) {
s_EndPointHorizontal = true;
}
if( tSegmentToEnd )
{
//check if second line is vertical
if( tSegmentToEnd->m_Flags & STARTPOINT )
{
tx1 = (double) tSegmentToEnd->m_Start.x;
ty1 = (double) tSegmentToEnd->m_Start.y;
tx2 = (double) tSegmentToEnd->m_End.x;
ty2 = (double) tSegmentToEnd->m_End.y;
}
else
{
tx1 = (double) tSegmentToEnd->m_End.x;
ty1 = (double) tSegmentToEnd->m_End.y;
tx2 = (double) tSegmentToEnd->m_Start.x;
ty2 = (double) tSegmentToEnd->m_Start.y;
}
}
else // move the start point on a line starting at Track->m_End, and perpendicular to Track
{
tx1 = (double) Track->m_End.x;
ty1 = (double) Track->m_End.y;
tx2 = (double) Track->m_Start.x;
ty2 = (double) Track->m_Start.y;
RotatePoint( &tx2, &ty2, tx1, ty1, -900 );
}
if( tx2!=tx1 )
{
s_EndSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
s_EndSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
}
else
{
s_EndPointVertical = true; //signal second segment vertical
}
if( ty1==ty2 )
{
s_EndPointHorizontal = true;
}
// Init parameters for the moved segment
tx1 = (double)Track->m_Start.x;
ty1 = (double)Track->m_Start.y;
tx2 = (double)Track->m_End.x;
ty2 = (double)Track->m_End.y;
if (tx2 != tx1) {
s_MovingSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
} else {
s_MovingSegmentVertical = true; //signal vertical line
}
if (ty1==ty2) {
s_MovingSegmentHorizontal=true;
}
// Test if drag is possible:
if( s_MovingSegmentVertical )
{
if ( s_EndPointVertical || s_StartPointVertical ) return false;
}
else
{ if ( ! s_EndPointVertical && (s_MovingSegmentSlope == s_EndSegmentSlope) ) return false;
if ( ! s_StartPointVertical && (s_MovingSegmentSlope == s_StartSegmentSlope) ) return false;
}
return TRUE;
tx1 = (double) Track->m_Start.x;
ty1 = (double) Track->m_Start.y;
tx2 = (double) Track->m_End.x;
ty2 = (double) Track->m_End.y;
if( tx2 != tx1 )
{
s_MovingSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
}
else
{
s_MovingSegmentVertical = true; //signal vertical line
}
if( ty1==ty2 )
{
s_MovingSegmentHorizontal = true;
}
// Test if drag is possible:
if( s_MovingSegmentVertical )
{
if( s_EndPointVertical || s_StartPointVertical )
return false;
}
else
{
if( !s_EndPointVertical && (s_MovingSegmentSlope == s_EndSegmentSlope) )
return false;
if( !s_StartPointVertical && (s_MovingSegmentSlope == s_StartSegmentSlope) )
return false;
}
return TRUE;
}
/*************************************************************************************/
void WinEDA_PcbFrame::Start_MoveOneNodeOrSegment(TRACK * track, wxDC * DC, int command)
void WinEDA_PcbFrame::Start_MoveOneNodeOrSegment( TRACK* track, wxDC* DC, int command )
/*************************************************************************************/
/* Init parametres to move one node:
a via or/and a terminal point of a track segment
The terminal point of other connected segments (if any) are moved too.
*/
* a via or/and a terminal point of a track segment
* The terminal point of other connected segments (if any) are moved too.
*/
{
if ( ! track ) return;
NewTrack = NULL;
NbPtNewTrack = 0;
EraseDragListe();
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if(g_HightLigt_Status) Hight_Light(DC);
PosInit = GetScreen()->m_Curseur;
if ( track->m_StructType == TYPEVIA)
{
track->m_Flags = IS_DRAGGED|STARTPOINT|ENDPOINT;
if ( command != ID_POPUP_PCB_MOVE_TRACK_SEGMENT )
{
Collect_TrackSegmentsToDrag(DrawPanel, DC, track->m_Start,
track->ReturnMaskLayer(), track->m_NetCode);
}
NewTrack = track;
NbPtNewTrack = 1;
PosInit = track->m_Start;
}
else
{
int diag = track->IsPointOnEnds(GetScreen()->m_Curseur, -1);
wxPoint pos;
switch ( command )
{
case ID_POPUP_PCB_MOVE_TRACK_SEGMENT:
track->m_Flags |= IS_DRAGGED|ENDPOINT|STARTPOINT;
AddSegmentToDragList(DrawPanel, DC, track->m_Flags, track);
break;
case ID_POPUP_PCB_DRAG_TRACK_SEGMENT:
pos = track->m_Start;
Collect_TrackSegmentsToDrag(DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode);
pos = track->m_End;
track->m_Flags |= IS_DRAGGED|ENDPOINT|STARTPOINT;
Collect_TrackSegmentsToDrag(DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode);
break;
case ID_POPUP_PCB_MOVE_TRACK_NODE:
pos = (diag & STARTPOINT) ? track->m_Start : track->m_End;
Collect_TrackSegmentsToDrag(DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode);
PosInit = pos;
break;
}
track->m_Flags |= IS_DRAGGED;
}
s_LastPos = PosInit;
DrawPanel->ManageCurseur = Show_MoveNode;
DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode) ;
DrawPanel->ManageCurseur(DrawPanel, DC, TRUE);
}
if( !track )
return;
NewTrack = NULL;
NbPtNewTrack = 0;
EraseDragListe();
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if( g_HightLigt_Status )
Hight_Light( DC );
PosInit = GetScreen()->m_Curseur;
if( track->m_StructType == TYPEVIA )
{
track->m_Flags = IS_DRAGGED | STARTPOINT | ENDPOINT;
if( command != ID_POPUP_PCB_MOVE_TRACK_SEGMENT )
{
Collect_TrackSegmentsToDrag( DrawPanel, DC, track->m_Start,
track->ReturnMaskLayer(), track->m_NetCode );
}
NewTrack = track;
NbPtNewTrack = 1;
PosInit = track->m_Start;
}
else
{
int diag = track->IsPointOnEnds( GetScreen()->m_Curseur, -1 );
wxPoint pos;
switch( command )
{
case ID_POPUP_PCB_MOVE_TRACK_SEGMENT:
track->m_Flags |= IS_DRAGGED | ENDPOINT | STARTPOINT;
AddSegmentToDragList( DrawPanel, DC, track->m_Flags, track );
break;
case ID_POPUP_PCB_DRAG_TRACK_SEGMENT:
pos = track->m_Start;
Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode );
pos = track->m_End;
track->m_Flags |= IS_DRAGGED | ENDPOINT | STARTPOINT;
Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode );
break;
case ID_POPUP_PCB_MOVE_TRACK_NODE:
pos = (diag & STARTPOINT) ? track->m_Start : track->m_End;
Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
track->ReturnMaskLayer(), track->m_NetCode );
PosInit = pos;
break;
}
track->m_Flags |= IS_DRAGGED;
}
s_LastPos = PosInit;
DrawPanel->ManageCurseur = Show_MoveNode;
DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode );
DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
}
/***********************************************************************************/
void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope(TRACK * track, wxDC * DC)
void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC )
/***********************************************************************************/
{
TRACK * TrackToStartPoint = NULL;
TRACK * TrackToEndPoint = NULL;
bool error = FALSE;
if ( ! track ) return;
s_StartSegmentPresent = s_EndSegmentPresent = TRUE;
if ( (track->start == NULL) || (track->start->m_StructType == TYPETRACK) )
TrackToStartPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START);
// Test if more than one segment is connected to this point
if ( TrackToStartPoint )
{
TrackToStartPoint->SetState(BUSY,ON);
if ( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START) ) error = TRUE;
TrackToStartPoint->SetState(BUSY,OFF);
}
if ( (track->end == NULL) || (track->end->m_StructType == TYPETRACK) )
TrackToEndPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END);
// Test if more than one segment is connected to this point
if ( TrackToEndPoint )
{
TrackToEndPoint->SetState(BUSY,ON);
if ( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END) ) error = TRUE;
TrackToEndPoint->SetState(BUSY,OFF);
}
if ( error )
{
DisplayError( this, _("Unable to drag this segment: too many segments connected") );
return;
}
if ( !TrackToStartPoint || (TrackToStartPoint->m_StructType != TYPETRACK) )
s_StartSegmentPresent = FALSE;
if ( !TrackToEndPoint || (TrackToEndPoint->m_StructType != TYPETRACK) )
s_EndSegmentPresent = FALSE;
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if(g_HightLigt_Status) Hight_Light(DC);
EraseDragListe();
NewTrack = NULL;
NbPtNewTrack = 0;
track->m_Flags = IS_DRAGGED;
if( TrackToStartPoint )
{
int flag = STARTPOINT;
if ( track->m_Start != TrackToStartPoint->m_Start ) flag = ENDPOINT;
AddSegmentToDragList(DrawPanel, DC, flag, TrackToStartPoint);
track->m_Flags |= STARTPOINT;
}
if( TrackToEndPoint )
{
int flag = STARTPOINT;
if ( track->m_End != TrackToEndPoint->m_Start ) flag = ENDPOINT;
AddSegmentToDragList(DrawPanel, DC, flag, TrackToEndPoint);
track->m_Flags |= ENDPOINT;
}
AddSegmentToDragList(DrawPanel, DC, track->m_Flags, track);
PosInit=GetScreen()->m_Curseur;
s_LastPos = GetScreen()->m_Curseur;
DrawPanel->ManageCurseur = Show_Drag_Track_Segment_With_Cte_Slope;
DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode) ;
if ( ! InitialiseDragParameters() )
{
DisplayError( this, _("Unable to drag this segment: two collinear segments") );
DrawPanel->ManageCurseur = NULL;
Abort_MoveTrack(DrawPanel, DC);
return;
}
TRACK* TrackToStartPoint = NULL;
TRACK* TrackToEndPoint = NULL;
bool error = FALSE;
if( !track )
return;
s_StartSegmentPresent = s_EndSegmentPresent = TRUE;
if( (track->start == NULL) || (track->start->m_StructType == TYPETRACK) )
TrackToStartPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START );
// Test if more than one segment is connected to this point
if( TrackToStartPoint )
{
TrackToStartPoint->SetState( BUSY, ON );
if( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START ) )
error = TRUE;
TrackToStartPoint->SetState( BUSY, OFF );
}
if( (track->end == NULL) || (track->end->m_StructType == TYPETRACK) )
TrackToEndPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END );
// Test if more than one segment is connected to this point
if( TrackToEndPoint )
{
TrackToEndPoint->SetState( BUSY, ON );
if( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END ) )
error = TRUE;
TrackToEndPoint->SetState( BUSY, OFF );
}
if( error )
{
DisplayError( this, _( "Unable to drag this segment: too many segments connected" ) );
return;
}
if( !TrackToStartPoint || (TrackToStartPoint->m_StructType != TYPETRACK) )
s_StartSegmentPresent = FALSE;
if( !TrackToEndPoint || (TrackToEndPoint->m_StructType != TYPETRACK) )
s_EndSegmentPresent = FALSE;
/* Change hight light net: the new one will be hightlighted */
Old_HightLigt_Status = g_HightLigt_Status;
Old_HightLigth_NetCode = g_HightLigth_NetCode;
if( g_HightLigt_Status )
Hight_Light( DC );
EraseDragListe();
NewTrack = NULL;
NbPtNewTrack = 0;
track->m_Flags = IS_DRAGGED;
if( TrackToStartPoint )
{
int flag = STARTPOINT;
if( track->m_Start != TrackToStartPoint->m_Start )
flag = ENDPOINT;
AddSegmentToDragList( DrawPanel, DC, flag, TrackToStartPoint );
track->m_Flags |= STARTPOINT;
}
if( TrackToEndPoint )
{
int flag = STARTPOINT;
if( track->m_End != TrackToEndPoint->m_Start )
flag = ENDPOINT;
AddSegmentToDragList( DrawPanel, DC, flag, TrackToEndPoint );
track->m_Flags |= ENDPOINT;
}
AddSegmentToDragList( DrawPanel, DC, track->m_Flags, track );
PosInit = GetScreen()->m_Curseur;
s_LastPos = GetScreen()->m_Curseur;
DrawPanel->ManageCurseur = Show_Drag_Track_Segment_With_Cte_Slope;
DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
g_HightLigth_NetCode = track->m_NetCode;
g_HightLigt_Status = TRUE;
DrawHightLight( DC, g_HightLigth_NetCode );
if( !InitialiseDragParameters() )
{
DisplayError( this, _( "Unable to drag this segment: two collinear segments" ) );
DrawPanel->ManageCurseur = NULL;
Abort_MoveTrack( DrawPanel, DC );
return;
}
}
/**********************************************************************/
bool WinEDA_PcbFrame::PlaceDraggedTrackSegment(TRACK * Track, wxDC * DC)
bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC )
/**********************************************************************/
/* Place a dragged (or moved) track segment or via */
{
int errdrc;
DRAG_SEGM * pt_drag;
if(Track == NULL ) return FALSE;
int current_net_code = Track->m_NetCode;
// DRC control:
if(Drc_On)
{
errdrc = Drc(this, DC, Track, m_Pcb->m_Track,1);
if(errdrc == BAD_DRC) return FALSE;
/* Redraw the dragged segments */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext)
{
errdrc = Drc(this, DC, pt_drag->m_Segm, m_Pcb->m_Track,1);
if(errdrc == BAD_DRC) return FALSE;
}
}
int draw_mode = GR_OR | GR_SURBRILL;
// DRC Ok: place track segments
Track->m_Flags = 0;
Track->SetState(EDIT,OFF);
Track->Draw(DrawPanel, DC, draw_mode);
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext)
{
Track = pt_drag->m_Segm;
Track->SetState(EDIT,OFF);
Track->m_Flags = 0;
Track->Draw(DrawPanel, DC, draw_mode);
/* Test the connections modified by the move
(only pad connection must be tested, track connection will be tested by test_1_net_connexion() ) */
int masque_layer = g_TabOneLayerMask[Track->m_Layer];
Track->start = Fast_Locate_Pad_Connecte(m_Pcb, Track->m_Start, masque_layer);
Track->end = Fast_Locate_Pad_Connecte(m_Pcb, Track->m_End, masque_layer);
}
EraseDragListe();
GetScreen()->SetModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
if ( current_net_code > 0 ) test_1_net_connexion(DC, current_net_code);
return TRUE;
int errdrc;
DRAG_SEGM* pt_drag;
if( Track == NULL )
return FALSE;
int current_net_code = Track->m_NetCode;
// DRC control:
if( Drc_On )
{
errdrc = Drc( this, DC, Track, m_Pcb->m_Track, 1 );
if( errdrc == BAD_DRC )
return FALSE;
/* Redraw the dragged segments */
pt_drag = g_DragSegmentList;
for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
{
errdrc = Drc( this, DC, pt_drag->m_Segm, m_Pcb->m_Track, 1 );
if( errdrc == BAD_DRC )
return FALSE;
}
}
int draw_mode = GR_OR | GR_SURBRILL;
// DRC Ok: place track segments
Track->m_Flags = 0;
Track->SetState( EDIT, OFF );
Track->Draw( DrawPanel, DC, draw_mode );
/* Tracage des segments dragges */
pt_drag = g_DragSegmentList;
for( ; pt_drag; pt_drag = pt_drag->Pnext )
{
Track = pt_drag->m_Segm;
Track->SetState( EDIT, OFF );
Track->m_Flags = 0;
Track->Draw( DrawPanel, DC, draw_mode );
/* Test the connections modified by the move
* (only pad connection must be tested, track connection will be tested by test_1_net_connexion() ) */
int masque_layer = g_TabOneLayerMask[Track->m_Layer];
Track->start = Fast_Locate_Pad_Connecte( m_Pcb, Track->m_Start, masque_layer );
Track->end = Fast_Locate_Pad_Connecte( m_Pcb, Track->m_End, masque_layer );
}
EraseDragListe();
GetScreen()->SetModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
if( current_net_code > 0 )
test_1_net_connexion( DC, current_net_code );
return TRUE;
}
/************************************************************************/
EDA_BaseStruct * LocateLockPoint(BOARD * Pcb, wxPoint pos, int LayerMask)
EDA_BaseStruct* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
/************************************************************************/
/* Routine trouvant le point " d'accrochage " d'une extremite de piste.
Ce point peut etre un PAD ou un autre segment de piste
Retourne:
- pointeur sur ce PAD ou:
- pointeur sur le segment ou:
- NULL
Parametres d'appel:
coord pX, pY du point tst
masque des couches a tester
*/
* Ce point peut etre un PAD ou un autre segment de piste
* Retourne:
* - pointeur sur ce PAD ou:
* - pointeur sur le segment ou:
* - NULL
* Parametres d'appel:
* coord pX, pY du point tst
* masque des couches a tester
*/
{
D_PAD * pt_pad;
TRACK * ptsegm;
MODULE * Module;
/* detection du point type PAD */
pt_pad = NULL;
Module = Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*)Module->Pnext )
{
pt_pad = Locate_Pads(Module, pos, LayerMask);
if (pt_pad) return(pt_pad);
}
/* ici aucun pad n'a ete localise: detection d'un segment de piste */
ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos, LayerMask);
if( ptsegm == NULL )
ptsegm = Locate_Pistes( Pcb->m_Track, pos, LayerMask);
return(ptsegm);
D_PAD* pt_pad;
TRACK* ptsegm;
MODULE* Module;
/* detection du point type PAD */
pt_pad = NULL;
Module = Pcb->m_Modules;
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
pt_pad = Locate_Pads( Module, pos, LayerMask );
if( pt_pad )
return pt_pad;
}
/* ici aucun pad n'a ete localise: detection d'un segment de piste */
ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos, LayerMask );
if( ptsegm == NULL )
ptsegm = Locate_Pistes( Pcb->m_Track, pos, LayerMask );
return ptsegm;
}
/******************************************************************************/
TRACK * CreateLockPoint(int *pX, int *pY, TRACK * ptsegm, TRACK * refsegm)
TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm )
/******************************************************************************/
/* Routine de creation d'un point intermediaire sur un segment
le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
retourne:
NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
a une extremite ou:
pointeur sur le segment cree
si refsegm != NULL refsegm est pointeur sur le segment incident,
et le point cree est l'intersection des 2 axes des segments ptsegm et
refsegm
retourne la valeur exacte de pX et pY
Si ptsegm pointe sur une via:
retourne la valeur exacte de pX et pY et ptsegm,
mais ne cree pas de point supplementaire
*/
* le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
* retourne:
* NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
* a une extremite ou:
* pointeur sur le segment cree
* si refsegm != NULL refsegm est pointeur sur le segment incident,
* et le point cree est l'intersection des 2 axes des segments ptsegm et
* refsegm
* retourne la valeur exacte de pX et pY
* Si ptsegm pointe sur une via:
* retourne la valeur exacte de pX et pY et ptsegm,
* mais ne cree pas de point supplementaire
*
*/
{
int cX, cY;
int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
int ox, oy, fx , fy; /* coord de refsegm / origine de prsegm */
TRACK * NewTrack;
if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) ) return(NULL);
if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) ) return(NULL);
/* le point n'est pas sur une extremite de piste */
if(ptsegm->m_StructType == TYPEVIA )
{
*pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
return(ptsegm);
}
/* calcul des coord vraies du point intermediaire dans le repere d'origine
= origine de ptsegm */
cX = *pX - ptsegm->m_Start.x;
int cX, cY;
int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */
TRACK* NewTrack;
if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) )
return NULL;
if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) )
return NULL;
/* le point n'est pas sur une extremite de piste */
if( ptsegm->m_StructType == TYPEVIA )
{
*pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
return ptsegm;
}
/* calcul des coord vraies du point intermediaire dans le repere d'origine
* = origine de ptsegm */
cX = *pX - ptsegm->m_Start.x;
cY = *pY - ptsegm->m_Start.y;
dx = ptsegm->m_End.x - ptsegm->m_Start.x;
dx = ptsegm->m_End.x - ptsegm->m_Start.x;
dy = ptsegm->m_End.y - ptsegm->m_Start.y;
// ***** A COMPLETER : non utilise
if ( refsegm )
{
ox = refsegm->m_Start.x - ptsegm->m_Start.x;
if( refsegm )
{
ox = refsegm->m_Start.x - ptsegm->m_Start.x;
oy = refsegm->m_Start.y - ptsegm->m_Start.y;
fx = refsegm->m_End.x - ptsegm->m_Start.x;
fx = refsegm->m_End.x - ptsegm->m_Start.x;
fy = refsegm->m_End.y - ptsegm->m_Start.y;
}
}
/* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
if ( dx == 0 ) cX = 0; /* segm horizontal */
else cY = (cX * dy) / dx;
/* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
if( dx == 0 )
cX = 0; /* segm horizontal */
else
cY = (cX * dy) / dx;
/* creation du point intermediaire ( c'est a dire creation d'un nouveau
segment, debutant au point intermediaire */
/* creation du point intermediaire ( c'est a dire creation d'un nouveau
* segment, debutant au point intermediaire */
cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
NewTrack = ptsegm->Copy();
cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
NewTrack = ptsegm->Copy();
NewTrack->Insert(NULL, ptsegm);
/* correction du pointeur de fin du nouveau segment */
NewTrack->end = ptsegm->end;
NewTrack->Insert( NULL, ptsegm );
/* correction du pointeur de fin du nouveau segment */
NewTrack->end = ptsegm->end;
/* le segment primitif finit au nouveau point : */
ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
ptsegm->SetState(END_ONPAD, OFF);
/* le segment primitif finit au nouveau point : */
ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
ptsegm->SetState( END_ONPAD, OFF );
/* le nouveau segment debute au nouveau point : */
ptsegm = NewTrack;;
ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
ptsegm->SetState(BEGIN_ONPAD, OFF);
*pX = cX; *pY = cY;
return(ptsegm);
/* le nouveau segment debute au nouveau point : */
ptsegm = NewTrack;;
ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
ptsegm->SetState( BEGIN_ONPAD, OFF );
*pX = cX; *pY = cY;
return ptsegm;
}
/* Set up the basic primitives for Layer control */
/* Set up the basic primitives for Layer control */
#include "fctsys.h"
#include "gr_basic.h"
......@@ -14,11 +14,12 @@
/* Fonctions locales: */
enum layer_sel_id {
ID_LAYER_OK = 1800,
ID_LAYER_CANCEL,
ID_LAYER_SELECT_TOP,
ID_LAYER_SELECT_BOTTOM,
ID_LAYER_SELECT
ID_LAYER_OK = 1800,
ID_LAYER_CANCEL,
ID_LAYER_SELECT_TOP,
ID_LAYER_SELECT_BOTTOM,
ID_LAYER_SELECT
};
......@@ -26,122 +27,136 @@ enum layer_sel_id {
/* classe pour la frame de selection de layers */
/***********************************************/
class WinEDA_SelLayerFrame: public wxDialog
class WinEDA_SelLayerFrame : public wxDialog
{
private:
WinEDA_BasePcbFrame *m_Parent;
wxRadioBox * m_LayerList;
int m_LayerId[NB_LAYERS];
WinEDA_BasePcbFrame* m_Parent;
wxRadioBox* m_LayerList;
int m_LayerId[NB_LAYERS];
public:
// Constructor and destructor
WinEDA_SelLayerFrame(WinEDA_BasePcbFrame *parent, int default_layer,
int min_layer, int max_layer);
~WinEDA_SelLayerFrame(void) {};
// Constructor and destructor
WinEDA_SelLayerFrame( WinEDA_BasePcbFrame* parent, int default_layer,
int min_layer, int max_layer );
~WinEDA_SelLayerFrame( void ) { };
private:
void Sel_Layer(wxCommandEvent& event);
void Cancel(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
void Sel_Layer( wxCommandEvent& event );
void Cancel( wxCommandEvent& event );
DECLARE_EVENT_TABLE()
};
/* Table des evenements pour WinEDA_SelLayerFrame */
BEGIN_EVENT_TABLE(WinEDA_SelLayerFrame, wxDialog)
EVT_BUTTON(ID_LAYER_OK, WinEDA_SelLayerFrame::Sel_Layer)
EVT_BUTTON(ID_LAYER_CANCEL, WinEDA_SelLayerFrame::Cancel)
EVT_RADIOBOX(ID_LAYER_SELECT, WinEDA_SelLayerFrame::Sel_Layer)
BEGIN_EVENT_TABLE( WinEDA_SelLayerFrame, wxDialog )
EVT_BUTTON( ID_LAYER_OK, WinEDA_SelLayerFrame::Sel_Layer )
EVT_BUTTON( ID_LAYER_CANCEL, WinEDA_SelLayerFrame::Cancel )
EVT_RADIOBOX( ID_LAYER_SELECT, WinEDA_SelLayerFrame::Sel_Layer )
END_EVENT_TABLE()
/***********************************************************************************/
int WinEDA_BasePcbFrame::SelectLayer(int default_layer, int min_layer, int max_layer)
int WinEDA_BasePcbFrame::SelectLayer( int default_layer, int min_layer, int max_layer )
/***********************************************************************************/
/* Install the dialog box for layer selection
default_layer = Preselection
min_layer = val min de layer selectionnable (-1 si pas de val mini)
max_layer = val max de layer selectionnable (-1 si pas de val maxi)
*/
* default_layer = Preselection
* min_layer = val min de layer selectionnable (-1 si pas de val mini)
* max_layer = val max de layer selectionnable (-1 si pas de val maxi)
*/
{
int layer;
WinEDA_SelLayerFrame * frame =
new WinEDA_SelLayerFrame(this, default_layer,min_layer, max_layer);
layer = frame->ShowModal(); frame->Destroy();
return layer;
int layer;
WinEDA_SelLayerFrame* frame =
new WinEDA_SelLayerFrame( this, default_layer, min_layer, max_layer );
layer = frame->ShowModal(); frame->Destroy();
return layer;
}
/***********************************************************************/
WinEDA_SelLayerFrame::WinEDA_SelLayerFrame(WinEDA_BasePcbFrame *parent,
int default_layer, int min_layer, int max_layer):
wxDialog(parent, -1, _("Select Layer:"),wxPoint(-1,-1),
wxSize(470, 250),
DIALOG_STYLE )
WinEDA_SelLayerFrame::WinEDA_SelLayerFrame( WinEDA_BasePcbFrame* parent,
int default_layer, int min_layer, int max_layer ) :
wxDialog( parent, -1, _( "Select Layer:" ), wxPoint( -1, -1 ),
wxSize( 470, 250 ),
DIALOG_STYLE )
/***********************************************************************/
{
wxButton * Button;
int ii, yy, xx;
wxPoint pos;
wxString LayerList[NB_LAYERS];
int LayerCount, LayerSelect = -1;
m_Parent = parent;
SetFont(*g_DialogFont);
/* Construction de la liste des couches autorises */
LayerCount = 0;
int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount-1];
Masque_Layer += ALL_NO_CU_LAYERS;
for ( ii = 0; ii < NB_LAYERS ; ii ++ )
{
m_LayerId[ii] = 0;
if ( (g_TabOneLayerMask[ii] & Masque_Layer) )
{
if ( min_layer > ii ) continue;
if ( (max_layer >= 0) && (max_layer < ii) ) break;
LayerList[LayerCount] = ReturnPcbLayerName(ii);
if ( ii == default_layer ) LayerSelect = LayerCount;
m_LayerId[LayerCount] = ii;
LayerCount++;
}
}
pos.x = 5; pos.y = 5;
m_LayerList = new wxRadioBox(this, ID_LAYER_SELECT, _("Layer"),
pos, wxSize(-1,-1), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS);
if ( LayerSelect >= 0 ) m_LayerList->SetSelection(LayerSelect);
m_LayerList->GetSize(&xx, &yy);
pos.x += xx + 12;
Button = new wxButton(this,ID_LAYER_OK,
_("OK"), pos);
Button->SetForegroundColour(*wxBLUE);
pos.y += Button->GetSize().y + 5;
Button = new wxButton(this,ID_LAYER_CANCEL,
_("Cancel"), pos);
Button->SetForegroundColour(*wxRED);
wxButton* Button;
int ii, yy, xx;
wxPoint pos;
wxString LayerList[NB_LAYERS];
int LayerCount, LayerSelect = -1;
m_Parent = parent;
SetFont( *g_DialogFont );
/* Construction de la liste des couches autoris�s */
LayerCount = 0;
int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount - 1];
Masque_Layer += ALL_NO_CU_LAYERS;
for( ii = 0; ii < NB_LAYERS; ii++ )
{
m_LayerId[ii] = 0;
if( (g_TabOneLayerMask[ii] & Masque_Layer) )
{
if( min_layer > ii )
continue;
if( (max_layer >= 0) && (max_layer < ii) )
break;
LayerList[LayerCount] = ReturnPcbLayerName( ii );
if( ii == default_layer )
LayerSelect = LayerCount;
m_LayerId[LayerCount] = ii;
LayerCount++;
}
}
pos.x = 5; pos.y = 5;
m_LayerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ),
pos, wxSize( -1, -1 ), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
if( LayerSelect >= 0 )
m_LayerList->SetSelection( LayerSelect );
m_LayerList->GetSize( &xx, &yy );
pos.x += xx + 12;
Button = new wxButton( this, ID_LAYER_OK,
_( "OK" ), pos );
Button->SetForegroundColour( *wxBLUE );
pos.y += Button->GetSize().y + 5;
Button = new wxButton( this, ID_LAYER_CANCEL,
_( "Cancel" ), pos );
Button->SetForegroundColour( *wxRED );
/* Redimensionnement de la boite de dialogue: */
pos.x += Button->GetSize().x + 10;
SetSize(-1, -1, pos.x , yy + 35);
pos.x += Button->GetSize().x + 10;
SetSize( -1, -1, pos.x, yy + 35 );
}
/***************************************************************/
void WinEDA_SelLayerFrame::Sel_Layer(wxCommandEvent& event)
void WinEDA_SelLayerFrame::Sel_Layer( wxCommandEvent& event )
/***************************************************************/
{
int ii = m_LayerId[m_LayerList->GetSelection()];
EndModal(ii);
int ii = m_LayerId[m_LayerList->GetSelection()];
EndModal( ii );
}
/***************************************************************/
void WinEDA_SelLayerFrame::Cancel(wxCommandEvent& event)
void WinEDA_SelLayerFrame::Cancel( wxCommandEvent& event )
/***************************************************************/
{
EndModal(-1);
EndModal( -1 );
}
......@@ -149,129 +164,130 @@ void WinEDA_SelLayerFrame::Cancel(wxCommandEvent& event)
/* classe pour la frame de selection de paires de layers */
/*********************************************************/
class WinEDA_SelLayerPairFrame: public wxDialog
class WinEDA_SelLayerPairFrame : public wxDialog
{
private:
WinEDA_BasePcbFrame *m_Parent;
wxRadioBox * m_LayerListTOP;
wxRadioBox * m_LayerListBOTTOM;
int m_LayerId[NB_COPPER_LAYERS];
WinEDA_BasePcbFrame* m_Parent;
wxRadioBox* m_LayerListTOP;
wxRadioBox* m_LayerListBOTTOM;
int m_LayerId[NB_COPPER_LAYERS];
public:
// Constructor and destructor
WinEDA_SelLayerPairFrame(WinEDA_BasePcbFrame *parent);
~WinEDA_SelLayerPairFrame(void) {};
// Constructor and destructor
WinEDA_SelLayerPairFrame( WinEDA_BasePcbFrame* parent );
~WinEDA_SelLayerPairFrame( void ) { };
private:
void Sel_Layer(wxCommandEvent& event);
void Cancel(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
void Sel_Layer( wxCommandEvent& event );
void Cancel( wxCommandEvent& event );
DECLARE_EVENT_TABLE()
};
/* Table des evenements pour WinEDA_SelLayerPairFrame */
BEGIN_EVENT_TABLE(WinEDA_SelLayerPairFrame, wxDialog)
EVT_BUTTON(ID_LAYER_OK, WinEDA_SelLayerPairFrame::Sel_Layer)
EVT_BUTTON(ID_LAYER_CANCEL, WinEDA_SelLayerPairFrame::Cancel)
EVT_RADIOBOX(ID_LAYER_SELECT, WinEDA_SelLayerPairFrame::Sel_Layer)
BEGIN_EVENT_TABLE( WinEDA_SelLayerPairFrame, wxDialog )
EVT_BUTTON( ID_LAYER_OK, WinEDA_SelLayerPairFrame::Sel_Layer )
EVT_BUTTON( ID_LAYER_CANCEL, WinEDA_SelLayerPairFrame::Cancel )
EVT_RADIOBOX( ID_LAYER_SELECT, WinEDA_SelLayerPairFrame::Sel_Layer )
END_EVENT_TABLE()
/***********************************************/
void WinEDA_BasePcbFrame::SelectLayerPair(void)
void WinEDA_BasePcbFrame::SelectLayerPair( void )
/***********************************************/
/* Affiche une double liste de layers cuivre pour selection d'une paire de layers
pour autorutage, vias...
*/
* pour autorutage, vias...
*/
{
WinEDA_SelLayerPairFrame * frame =
new WinEDA_SelLayerPairFrame(this);
frame->ShowModal(); frame->Destroy();
DrawPanel->MouseToCursorSchema();
SetToolbars();
WinEDA_SelLayerPairFrame* frame =
new WinEDA_SelLayerPairFrame( this );
frame->ShowModal(); frame->Destroy();
DrawPanel->MouseToCursorSchema();
SetToolbars();
}
/*******************************************************************************/
WinEDA_SelLayerPairFrame::WinEDA_SelLayerPairFrame(WinEDA_BasePcbFrame *parent):
wxDialog(parent, -1, _("Select Layer Pair:"),wxPoint(-1,-1),
wxSize(470, 250), DIALOG_STYLE )
WinEDA_SelLayerPairFrame::WinEDA_SelLayerPairFrame( WinEDA_BasePcbFrame* parent ) :
wxDialog( parent, -1, _( "Select Layer Pair:" ), wxPoint( -1, -1 ),
wxSize( 470, 250 ), DIALOG_STYLE )
/*******************************************************************************/
{
wxButton * Button;
int ii, LayerCount;
int yy, xx;
wxPoint pos;
wxString LayerList[NB_COPPER_LAYERS];
int LayerTopSelect = 0, LayerBottomSelect = 0 ;
m_Parent = parent;
SetFont(*g_DialogFont);
PCB_SCREEN * screen = (PCB_SCREEN *) m_Parent->m_CurrentScreen;
/* Construction de la liste des couches autorises */
int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount-1];
Masque_Layer += ALL_NO_CU_LAYERS;
for ( ii = 0, LayerCount = 0; ii < NB_COPPER_LAYERS ; ii ++ )
{
m_LayerId[ii] = 0;
if ( (g_TabOneLayerMask[ii] & Masque_Layer) )
{
LayerList[LayerCount] = ReturnPcbLayerName(ii);
if ( ii == screen->m_Route_Layer_TOP )
LayerTopSelect = LayerCount;
if ( ii == screen->m_Route_Layer_BOTTOM )
LayerBottomSelect = LayerCount;
m_LayerId[LayerCount] = ii;
LayerCount++;
}
}
pos.x = 5; pos.y = 5;
m_LayerListTOP = new wxRadioBox(this, ID_LAYER_SELECT_TOP, _("Top Layer"),
pos, wxSize(-1,-1), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS);
m_LayerListTOP->SetSelection(LayerTopSelect);
m_LayerListTOP->GetSize(&xx, &yy);
pos.x += xx + 12;
m_LayerListBOTTOM = new wxRadioBox(this, ID_LAYER_SELECT_BOTTOM, _("Bottom Layer"),
pos, wxSize(-1,-1), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS);
m_LayerListBOTTOM->SetSelection(LayerBottomSelect);
m_LayerListBOTTOM->GetSize(&xx, &yy);
pos.x += xx + 12;
Button = new wxButton(this,ID_LAYER_OK,
_("OK"), pos);
Button->SetForegroundColour(*wxBLUE);
pos.y += Button->GetSize().y + 5;
Button = new wxButton(this,ID_LAYER_CANCEL,
_("Cancel"), pos);
Button->SetForegroundColour(*wxRED);
wxButton* Button;
int ii, LayerCount;
int yy, xx;
wxPoint pos;
wxString LayerList[NB_COPPER_LAYERS];
int LayerTopSelect = 0, LayerBottomSelect = 0;
m_Parent = parent;
SetFont( *g_DialogFont );
PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->m_CurrentScreen;
/* Construction de la liste des couches autoris�s */
int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount - 1];
Masque_Layer += ALL_NO_CU_LAYERS;
for( ii = 0, LayerCount = 0; ii < NB_COPPER_LAYERS; ii++ )
{
m_LayerId[ii] = 0;
if( (g_TabOneLayerMask[ii] & Masque_Layer) )
{
LayerList[LayerCount] = ReturnPcbLayerName( ii );
if( ii == screen->m_Route_Layer_TOP )
LayerTopSelect = LayerCount;
if( ii == screen->m_Route_Layer_BOTTOM )
LayerBottomSelect = LayerCount;
m_LayerId[LayerCount] = ii;
LayerCount++;
}
}
pos.x = 5; pos.y = 5;
m_LayerListTOP = new wxRadioBox( this, ID_LAYER_SELECT_TOP, _( "Top Layer" ),
pos, wxSize( -1, -1 ), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
m_LayerListTOP->SetSelection( LayerTopSelect );
m_LayerListTOP->GetSize( &xx, &yy );
pos.x += xx + 12;
m_LayerListBOTTOM = new wxRadioBox( this, ID_LAYER_SELECT_BOTTOM, _( "Bottom Layer" ),
pos, wxSize( -1, -1 ), LayerCount, LayerList,
(LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
m_LayerListBOTTOM->SetSelection( LayerBottomSelect );
m_LayerListBOTTOM->GetSize( &xx, &yy );
pos.x += xx + 12;
Button = new wxButton( this, ID_LAYER_OK, _( "OK" ), pos );
Button->SetForegroundColour( *wxBLUE );
pos.y += Button->GetSize().y + 5;
Button = new wxButton( this, ID_LAYER_CANCEL, _( "Cancel" ), pos );
Button->SetForegroundColour( *wxRED );
/* Redimensionnement de la boite de dialogue: */
pos.x += Button->GetSize().x + 10;
SetSize(-1, -1, pos.x , yy + 35);
pos.x += Button->GetSize().x + 10;
SetSize( -1, -1, pos.x, yy + 35 );
}
/***************************************************************/
void WinEDA_SelLayerPairFrame::Sel_Layer(wxCommandEvent& event)
void WinEDA_SelLayerPairFrame::Sel_Layer( wxCommandEvent& event )
/***************************************************************/
{
PCB_SCREEN * screen = (PCB_SCREEN *) m_Parent->m_CurrentScreen;
PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->m_CurrentScreen;
screen->m_Route_Layer_TOP = m_LayerId[m_LayerListTOP->GetSelection()];
screen->m_Route_Layer_BOTTOM = m_LayerId[m_LayerListBOTTOM->GetSelection()];
EndModal(0);
screen->m_Route_Layer_TOP = m_LayerId[m_LayerListTOP->GetSelection()];
screen->m_Route_Layer_BOTTOM = m_LayerId[m_LayerListBOTTOM->GetSelection()];
EndModal( 0 );
}
/***************************************************************/
void WinEDA_SelLayerPairFrame::Cancel(wxCommandEvent& event)
void WinEDA_SelLayerPairFrame::Cancel( wxCommandEvent& event )
/***************************************************************/
{
EndModal(-1);
EndModal( -1 );
}
/****************************/
/* affichage des empreintes */
/****************************/
/****************************/
/* affichage des empreintes */
/****************************/
#include "fctsys.h"
#include "gr_basic.h"
......@@ -12,160 +12,171 @@
#define Pad_fill (Pad_Fill_Item.State == RUN)
static void Pad_Surbrillance(WinEDA_DrawPanel * panel, wxDC * DC, MODULE * Module, int NetCode);
static void Pad_Surbrillance( WinEDA_DrawPanel* panel, wxDC* DC, MODULE* Module, int NetCode );
/* variables locales : */
static int draw_mode ;
static int draw_mode;
/*********************************************************/
void WinEDA_PcbFrame::Liste_Equipot(wxCommandEvent & event)
void WinEDA_PcbFrame::Liste_Equipot( wxCommandEvent& event )
/*********************************************************/
/* Display a filtered list of equipot names
if an equipot is selected the corresponding tracks and pads are highlighted
*/
* if an equipot is selected the corresponding tracks and pads are highlighted
*/
{
EQUIPOT * Equipot ;
wxString msg;
WinEDA_TextFrame * List;
int ii, jj;
msg = wxT("*");
Get_Message(_("Filter for net names:"),msg, this);
if ( msg.IsEmpty() ) return;
List = new WinEDA_TextFrame(this, _("List Nets") );
Equipot = (EQUIPOT*) m_Pcb->m_Equipots;
for ( ; Equipot != NULL; Equipot = (EQUIPOT*)Equipot->Pnext )
{
wxString Line;
/* calcul adr relative du nom de la pastille reference de la piste */
if( ! WildCompareString(msg, Equipot->m_Netname, FALSE ) ) continue ;
Line.Printf( wxT("net_code = %3.3d [%.16s] "),Equipot->m_NetCode,
Equipot->m_Netname.GetData());
List->Append(Line);
}
ii = List->ShowModal(); List->Destroy();
if (ii < 0) return;
/* Recherche du numero de net rellement selectionn */
Equipot = (EQUIPOT*) m_Pcb->m_Equipots;
for ( jj = 0; Equipot != NULL; Equipot = (EQUIPOT*)Equipot->Pnext )
{
/* calcul adr relative du nom de la pastille reference de la piste */
if( ! WildCompareString(msg, Equipot->m_Netname, FALSE) ) continue ;
if ( ii == jj )
{
ii = Equipot->m_NetCode;
break;
}
jj++;
}
wxClientDC dc(DrawPanel);
DrawPanel->PrepareGraphicContext(&dc);
if(g_HightLigt_Status) Hight_Light(&dc);
g_HightLigth_NetCode = ii;
Hight_Light(&dc);
EQUIPOT* Equipot;
wxString msg;
WinEDA_TextFrame* List;
int ii, jj;
msg = wxT( "*" );
Get_Message( _( "Filter for net names:" ), msg, this );
if( msg.IsEmpty() )
return;
List = new WinEDA_TextFrame( this, _( "List Nets" ) );
Equipot = (EQUIPOT*) m_Pcb->m_Equipots;
for( ; Equipot != NULL; Equipot = (EQUIPOT*) Equipot->Pnext )
{
wxString Line;
/* calcul adr relative du nom de la pastille reference de la piste */
if( !WildCompareString( msg, Equipot->m_Netname, FALSE ) )
continue;
Line.Printf( wxT( "net_code = %3.3d [%.16s] " ), Equipot->m_NetCode,
Equipot->m_Netname.GetData() );
List->Append( Line );
}
ii = List->ShowModal(); List->Destroy();
if( ii < 0 )
return;
/* Recherche du numero de net rellement selectionn�*/
Equipot = (EQUIPOT*) m_Pcb->m_Equipots;
for( jj = 0; Equipot != NULL; Equipot = (EQUIPOT*) Equipot->Pnext )
{
/* calcul adr relative du nom de la pastille reference de la piste */
if( !WildCompareString( msg, Equipot->m_Netname, FALSE ) )
continue;
if( ii == jj )
{
ii = Equipot->m_NetCode;
break;
}
jj++;
}
wxClientDC dc( DrawPanel );
DrawPanel->PrepareGraphicContext( &dc );
if( g_HightLigt_Status )
Hight_Light( &dc );
g_HightLigth_NetCode = ii;
Hight_Light( &dc );
}
/**************************************************/
int WinEDA_PcbFrame::Select_High_Light(wxDC * DC)
int WinEDA_PcbFrame::Select_High_Light( wxDC* DC )
/**************************************************/
/* Localise track ou pad et met en surbrillance le net correspondant
Retourne le netcode, ou -1 si pas de net localis */
* Retourne le netcode, ou -1 si pas de net localis�*/
{
TRACK * pt_piste;
D_PAD* pt_pad ;
int masquelayer = g_TabOneLayerMask[GetScreen()->m_Active_Layer];
int code = -1;
if ( g_HightLigt_Status ) Hight_Light(DC);
pt_piste = Locate_Pistes(m_Pcb->m_Track, masquelayer, CURSEUR_OFF_GRILLE);
if ( pt_piste)
{
code = g_HightLigth_NetCode = pt_piste->m_NetCode;
Hight_Light(DC);
}
else
{
pt_pad = Locate_Any_Pad(m_Pcb, CURSEUR_OFF_GRILLE);
if( pt_pad != NULL )
{
code = g_HightLigth_NetCode = pt_pad->m_NetCode ;
Hight_Light(DC) ;
}
}
return code;
TRACK* pt_piste;
D_PAD* pt_pad;
int masquelayer = g_TabOneLayerMask[GetScreen()->m_Active_Layer];
int code = -1;
if( g_HightLigt_Status )
Hight_Light( DC );
pt_piste = Locate_Pistes( m_Pcb->m_Track, masquelayer, CURSEUR_OFF_GRILLE );
if( pt_piste )
{
code = g_HightLigth_NetCode = pt_piste->m_NetCode;
Hight_Light( DC );
}
else
{
pt_pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE );
if( pt_pad != NULL )
{
code = g_HightLigth_NetCode = pt_pad->m_NetCode;
Hight_Light( DC );
}
}
return code;
}
/*******************************************/
void WinEDA_PcbFrame::Hight_Light(wxDC * DC)
void WinEDA_PcbFrame::Hight_Light( wxDC* DC )
/*******************************************/
/*
fonction d'appel de Surbrillance a partir du menu
Met ou supprime la surbrillance d'un net pointe par la souris
*/
* fonction d'appel de Surbrillance a partir du menu
* Met ou supprime la surbrillance d'un net pointe par la souris
*/
{
g_HightLigt_Status = !g_HightLigt_Status;
DrawHightLight( DC, g_HightLigth_NetCode) ;
g_HightLigt_Status = !g_HightLigt_Status;
DrawHightLight( DC, g_HightLigth_NetCode );
}
/****************************************************************/
void WinEDA_PcbFrame::DrawHightLight(wxDC * DC, int NetCode)
void WinEDA_PcbFrame::DrawHightLight( wxDC* DC, int NetCode )
/****************************************************************/
/* Turn On or OFF the HightLight for trcak and pads with the netcode "NetCode'
*/
*/
{
TRACK * pts ;
MODULE * Module;
if(g_HightLigt_Status ) draw_mode = GR_SURBRILL | GR_OR;
else draw_mode = GR_AND | GR_SURBRILL;
Module = m_Pcb->m_Modules;
/* Redraw pads */
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
Pad_Surbrillance(DrawPanel, DC, Module, NetCode) ;
}
/* Redraw track and vias: */
for ( pts = m_Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext)
{
if( pts->m_NetCode == NetCode )
{
pts->Draw(DrawPanel, DC, draw_mode);
}
}
TRACK* pts;
MODULE* Module;
if( g_HightLigt_Status )
draw_mode = GR_SURBRILL | GR_OR;
else
draw_mode = GR_AND | GR_SURBRILL;
Module = m_Pcb->m_Modules;
/* Redraw pads */
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
{
Pad_Surbrillance( DrawPanel, DC, Module, NetCode );
}
/* Redraw track and vias: */
for( pts = m_Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext )
{
if( pts->m_NetCode == NetCode )
{
pts->Draw( DrawPanel, DC, draw_mode );
}
}
}
/*******************************************************/
static void Pad_Surbrillance(WinEDA_DrawPanel * panel,
wxDC * DC, MODULE * Module, int NetCode)
static void Pad_Surbrillance( WinEDA_DrawPanel* panel,
wxDC* DC, MODULE* Module, int NetCode )
/*******************************************************/
/* Mise en Surbrillance des Pads */
{
D_PAD * pt_pad ;
/* trace des pastilles */
for(pt_pad = Module->m_Pads; pt_pad != NULL; pt_pad = (D_PAD*)pt_pad->Pnext)
{
if ( pt_pad->m_NetCode == NetCode )
{
pt_pad->Draw(panel, DC, wxPoint(0,0),draw_mode);
}
}
D_PAD* pt_pad;
/* trace des pastilles */
for( pt_pad = Module->m_Pads; pt_pad != NULL; pt_pad = (D_PAD*) pt_pad->Pnext )
{
if( pt_pad->m_NetCode == NetCode )
{
pt_pad->Draw( panel, DC, wxPoint( 0, 0 ), draw_mode );
}
}
}
......@@ -51,7 +51,7 @@
/* Data to build the layer pair indicator button */
static wxBitmap* LayerPairBitmap = NULL;
static char s_BitmapLayerIcon[16][16] = {
static const char s_BitmapLayerIcon[16][16] = {
// 0 = draw pixel with active layer color
// 1 = draw pixel with top layer color (top/bottom layer used in autoroute and place via)
// 2 = draw pixel with bottom layer color
......
/////////////////////////////////////////////////////////////////////////////
// Name: zones.cpp
// Purpose:
// Author: jean-pierre Charras
......@@ -11,7 +12,7 @@
// Generated by DialogBlocks (unregistered), 25/01/2006 11:35:19
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#if defined (__GNUG__) && !defined (NO_GCC_PRAGMA)
#pragma implementation "zones.h"
#endif
......@@ -35,19 +36,19 @@
////@end XPM images
/* Routines Locales */
static void Display_Zone_Netname(WinEDA_PcbFrame *frame);
static void Exit_Zones(WinEDA_DrawPanel * Panel, wxDC *DC);
static void Show_Zone_Edge_While_MoveMouse(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
static void Genere_Segments_Zone(WinEDA_PcbFrame *frame, wxDC * DC, int net_code);
static bool Genere_Pad_Connexion(WinEDA_PcbFrame *frame, wxDC * DC, int layer);
static void Display_Zone_Netname( WinEDA_PcbFrame* frame );
static void Exit_Zones( WinEDA_DrawPanel* Panel, wxDC* DC );
static void Show_Zone_Edge_While_MoveMouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Genere_Segments_Zone( WinEDA_PcbFrame* frame, wxDC* DC, int net_code );
static bool Genere_Pad_Connexion( WinEDA_PcbFrame* frame, wxDC* DC, int layer );
/* Variables locales */
static bool Zone_Debug = FALSE;
static bool Zone_45_Only = FALSE;
static bool Zone_Exclude_Pads = TRUE;
static bool Zone_Genere_Freins_Thermiques = TRUE;
static bool Zone_Debug = FALSE;
static bool Zone_45_Only = FALSE;
static bool Zone_Exclude_Pads = TRUE;
static bool Zone_Genere_Freins_Thermiques = TRUE;
static unsigned long s_TimeStamp; /* signature temporelle pour la zone generee */
static unsigned long s_TimeStamp; /* signature temporelle pour la zone generee */
/*!
* WinEDA_ZoneFrame type definition
......@@ -62,11 +63,11 @@ IMPLEMENT_DYNAMIC_CLASS( WinEDA_ZoneFrame, wxDialog )
BEGIN_EVENT_TABLE( WinEDA_ZoneFrame, wxDialog )
////@begin WinEDA_ZoneFrame event table entries
EVT_BUTTON( ID_FILL_ZONE, WinEDA_ZoneFrame::ExecFillZone )
EVT_BUTTON( ID_FILL_ZONE, WinEDA_ZoneFrame::ExecFillZone )
EVT_BUTTON( wxID_CANCEL, WinEDA_ZoneFrame::OnCancelClick )
EVT_BUTTON( wxID_CANCEL, WinEDA_ZoneFrame::OnCancelClick )
EVT_BUTTON( ID_SET_OPTIONS_ZONE, WinEDA_ZoneFrame::ExecFillZone )
EVT_BUTTON( ID_SET_OPTIONS_ZONE, WinEDA_ZoneFrame::ExecFillZone )
////@end WinEDA_ZoneFrame event table entries
......@@ -76,148 +77,197 @@ END_EVENT_TABLE()
* WinEDA_ZoneFrame constructors
*/
WinEDA_ZoneFrame::WinEDA_ZoneFrame( )
WinEDA_ZoneFrame::WinEDA_ZoneFrame()
{
}
WinEDA_ZoneFrame::WinEDA_ZoneFrame( WinEDA_PcbFrame* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
WinEDA_ZoneFrame::WinEDA_ZoneFrame( WinEDA_PcbFrame* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style )
{
m_Parent = parent;
Create(parent, id, caption, pos, size, style);
m_Parent = parent;
Create( parent, id, caption, pos, size, style );
}
/*!
* WinEDA_ZoneFrame creator
*/
bool WinEDA_ZoneFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
bool WinEDA_ZoneFrame::Create( wxWindow* parent,
wxWindowID id,
const wxString& caption,
const wxPoint& pos,
const wxSize& size,
long style )
{
////@begin WinEDA_ZoneFrame member initialisation
m_GridCtrl = NULL;
m_ClearanceValueTitle = NULL;
m_ZoneClearanceCtrl = NULL;
m_ZoneClearanceCtrl = NULL;
m_FillOpt = NULL;
m_OrientEdgesOpt = NULL;
////@end WinEDA_ZoneFrame member initialisation
////@begin WinEDA_ZoneFrame creation
SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
SetExtraStyle( GetExtraStyle() | wxWS_EX_BLOCK_EVENTS );
wxDialog::Create( parent, id, caption, pos, size, style );
CreateControls();
GetSizer()->Fit(this);
GetSizer()->SetSizeHints(this);
GetSizer()->Fit( this );
GetSizer()->SetSizeHints( this );
Centre();
////@end WinEDA_ZoneFrame creation
return true;
return true;
}
/*!
* Control creation for WinEDA_ZoneFrame
*/
void WinEDA_ZoneFrame::CreateControls()
{
SetFont(*g_DialogFont);
SetFont( *g_DialogFont );
////@begin WinEDA_ZoneFrame content construction
// Generated by DialogBlocks, 03/03/2006 13:36:21 (unregistered)
WinEDA_ZoneFrame* itemDialog1 = this;
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
itemDialog1->SetSizer(itemBoxSizer2);
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer( wxHORIZONTAL );
itemDialog1->SetSizer( itemBoxSizer2 );
wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW|wxALL, 5);
wxBoxSizer* itemBoxSizer3 = new wxBoxSizer( wxVERTICAL );
itemBoxSizer2->Add( itemBoxSizer3, 0, wxGROW | wxALL, 5 );
wxString m_GridCtrlStrings[] = {
_("0.00000"),
_("0.00000"),
_("0.00000"),
_("0.00000")
static const wxString m_GridCtrlStrings[] = {
_( "0.00000" ),
_( "0.00000" ),
_( "0.00000" ),
_( "0.00000" )
};
m_GridCtrl = new wxRadioBox( itemDialog1, ID_RADIOBOX, _("Grid size:"), wxDefaultPosition, wxDefaultSize, 4, m_GridCtrlStrings, 1, wxRA_SPECIFY_COLS );
itemBoxSizer3->Add(m_GridCtrl, 0, wxALIGN_LEFT|wxALL, 5);
m_ClearanceValueTitle = new wxStaticText( itemDialog1, wxID_STATIC, _("Zone clearance value (mm):"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer3->Add(m_ClearanceValueTitle, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);
m_ZoneClearanceCtrl = new wxTextCtrl( itemDialog1, ID_TEXTCTRL, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer3->Add(m_ZoneClearanceCtrl, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxBOTTOM, 5);
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
wxBoxSizer* itemBoxSizer8 = new wxBoxSizer(wxVERTICAL);
itemBoxSizer2->Add(itemBoxSizer8, 0, wxGROW|wxALL, 5);
wxString m_FillOptStrings[] = {
_("Include Pads"),
_("Thermal"),
_("Exclude Pads")
m_GridCtrl = new wxRadioBox( itemDialog1, ID_RADIOBOX, _(
"Grid size:" ), wxDefaultPosition, wxDefaultSize, 4,
m_GridCtrlStrings, 1, wxRA_SPECIFY_COLS );
itemBoxSizer3->Add( m_GridCtrl, 0, wxALIGN_LEFT | wxALL, 5 );
m_ClearanceValueTitle = new wxStaticText( itemDialog1, wxID_STATIC,
_("Zone clearance value (mm):"),
wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer3->Add( m_ClearanceValueTitle,
0,
wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP | wxADJUST_MINSIZE,
5 );
m_ZoneClearanceCtrl = new wxTextCtrl( itemDialog1, ID_TEXTCTRL, _T(
"" ), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer3->Add( m_ZoneClearanceCtrl, 0, wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
itemBoxSizer2->Add( 5, 5, 0, wxGROW | wxALL, 5 );
wxBoxSizer* itemBoxSizer8 = new wxBoxSizer( wxVERTICAL );
itemBoxSizer2->Add( itemBoxSizer8, 0, wxGROW | wxALL, 5 );
static const wxString m_FillOptStrings[] = {
_( "Include Pads" ),
_( "Thermal" ),
_( "Exclude Pads" )
};
m_FillOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX1, _("Pad options:"), wxDefaultPosition, wxDefaultSize, 3, m_FillOptStrings, 1, wxRA_SPECIFY_COLS );
itemBoxSizer8->Add(m_FillOpt, 0, wxALIGN_LEFT|wxALL, 5);
wxString m_OrientEdgesOptStrings[] = {
_("Any"),
_("H , V and 45 deg")
m_FillOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX1, _(
"Pad options:" ), wxDefaultPosition, wxDefaultSize, 3,
m_FillOptStrings, 1, wxRA_SPECIFY_COLS );
itemBoxSizer8->Add( m_FillOpt, 0, wxALIGN_LEFT | wxALL, 5 );
static const wxString m_OrientEdgesOptStrings[] = {
_( "Any" ),
_( "H , V and 45 deg" )
};
m_OrientEdgesOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX2, _("Zone edges orient:"), wxDefaultPosition, wxDefaultSize, 2, m_OrientEdgesOptStrings, 1, wxRA_SPECIFY_COLS );
itemBoxSizer8->Add(m_OrientEdgesOpt, 0, wxALIGN_RIGHT|wxALL, 5);
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
wxBoxSizer* itemBoxSizer12 = new wxBoxSizer(wxVERTICAL);
itemBoxSizer2->Add(itemBoxSizer12, 0, wxALIGN_TOP|wxALL, 5);
wxButton* itemButton13 = new wxButton( itemDialog1, ID_FILL_ZONE, _("Fill"), wxDefaultPosition, wxDefaultSize, 0 );
m_OrientEdgesOpt = new wxRadioBox( itemDialog1, ID_RADIOBOX2,
_("Zone edges orient:" ), wxDefaultPosition,
wxDefaultSize, 2, m_OrientEdgesOptStrings, 1,
wxRA_SPECIFY_COLS );
itemBoxSizer8->Add( m_OrientEdgesOpt, 0, wxALIGN_RIGHT | wxALL, 5 );
itemBoxSizer2->Add( 5, 5, 0, wxGROW | wxALL, 5 );
wxBoxSizer* itemBoxSizer12 = new wxBoxSizer( wxVERTICAL );
itemBoxSizer2->Add( itemBoxSizer12, 0, wxALIGN_TOP | wxALL, 5 );
wxButton* itemButton13 = new wxButton( itemDialog1, ID_FILL_ZONE,
_("Fill"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton13->SetDefault();
itemButton13->SetForegroundColour(wxColour(204, 0, 0));
itemBoxSizer12->Add(itemButton13, 0, wxGROW|wxALL, 5);
itemButton13->SetForegroundColour( wxColour( 204, 0, 0 ) );
itemBoxSizer12->Add( itemButton13, 0, wxGROW | wxALL, 5 );
wxButton* itemButton14 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton14->SetForegroundColour(wxColour(0, 0, 255));
itemBoxSizer12->Add(itemButton14, 0, wxGROW|wxALL, 5);
wxButton* itemButton14 = new wxButton( itemDialog1, wxID_CANCEL,
_("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton14->SetForegroundColour( wxColour( 0, 0, 255 ) );
itemBoxSizer12->Add( itemButton14, 0, wxGROW | wxALL, 5 );
wxButton* itemButton15 = new wxButton( itemDialog1, ID_SET_OPTIONS_ZONE, _("Update Options"), wxDefaultPosition, wxDefaultSize, 0 );
itemButton15->SetForegroundColour(wxColour(0, 100, 0));
itemBoxSizer12->Add(itemButton15, 0, wxGROW|wxALL, 5);
wxButton* itemButton15 = new wxButton( itemDialog1, ID_SET_OPTIONS_ZONE,
_("Update Options" ), wxDefaultPosition, wxDefaultSize, 0 );
itemButton15->SetForegroundColour( wxColour( 0, 100, 0 ) );
itemBoxSizer12->Add( itemButton15, 0, wxGROW | wxALL, 5 );
itemBoxSizer2->Add(5, 5, 0, wxGROW|wxALL, 5);
itemBoxSizer2->Add( 5, 5, 0, wxGROW | wxALL, 5 );
////@end WinEDA_ZoneFrame content construction
wxString title = _("Zone clearance value:") + ReturnUnitSymbol(g_UnitMetric);
wxString title = _( "Zone clearance value:" ) + ReturnUnitSymbol( g_UnitMetric );
m_ClearanceValueTitle->SetLabel( title );
title = _("Grid :") + ReturnUnitSymbol(g_UnitMetric);;
m_GridCtrl->SetLabel(title);
if ( g_DesignSettings.m_ZoneClearence == 0 )
g_DesignSettings.m_ZoneClearence = g_DesignSettings.m_TrackClearence;
title = ReturnStringFromValue( g_UnitMetric, g_DesignSettings.m_ZoneClearence, m_Parent->m_InternalUnits);
m_ZoneClearanceCtrl->SetValue( title );
if ( Zone_45_Only ) m_OrientEdgesOpt->SetSelection(1);
int GridList[4] = { 50,100,250,500}, selection = 0;
for ( unsigned ii = 0; ii < m_GridCtrl->GetCount(); ii++ )
{
wxString msg = ReturnStringFromValue(g_UnitMetric, GridList[ii], m_Parent->m_InternalUnits);
m_GridCtrl->SetString(ii,msg);
if ( g_GridRoutingSize == GridList[ii] ) selection = ii;
}
m_GridCtrl->SetSelection(selection);
if ( Zone_Exclude_Pads)
{
if ( Zone_Genere_Freins_Thermiques ) m_FillOpt->SetSelection(1);
else m_FillOpt->SetSelection(2);
}
title = _( "Grid :" ) + ReturnUnitSymbol( g_UnitMetric );;
m_GridCtrl->SetLabel( title );
if( g_DesignSettings.m_ZoneClearence == 0 )
g_DesignSettings.m_ZoneClearence = g_DesignSettings.m_TrackClearence;
title = ReturnStringFromValue( g_UnitMetric,
g_DesignSettings.m_ZoneClearence,
m_Parent->m_InternalUnits );
m_ZoneClearanceCtrl->SetValue( title );
if( Zone_45_Only )
m_OrientEdgesOpt->SetSelection( 1 );
static const int GridList[4] = { 50, 100, 250, 500 };
int selection = 0;
for( unsigned ii = 0; ii < m_GridCtrl->GetCount(); ii++ )
{
wxString msg = ReturnStringFromValue( g_UnitMetric,
GridList[ii],
m_Parent->m_InternalUnits );
m_GridCtrl->SetString( ii, msg );
if( g_GridRoutingSize == GridList[ii] )
selection = ii;
}
m_GridCtrl->SetSelection( selection );
if( Zone_Exclude_Pads )
{
if( Zone_Genere_Freins_Thermiques )
m_FillOpt->SetSelection( 1 );
else
m_FillOpt->SetSelection( 2 );
}
}
/*!
* Should we show tooltips?
*/
......@@ -227,6 +277,7 @@ bool WinEDA_ZoneFrame::ShowToolTips()
return true;
}
/*!
* Get bitmap resources
*/
......@@ -235,11 +286,13 @@ wxBitmap WinEDA_ZoneFrame::GetBitmapResource( const wxString& name )
{
// Bitmap retrieval
////@begin WinEDA_ZoneFrame bitmap retrieval
wxUnusedVar(name);
wxUnusedVar( name );
return wxNullBitmap;
////@end WinEDA_ZoneFrame bitmap retrieval
}
/*!
* Get icon resources
*/
......@@ -248,11 +301,13 @@ wxIcon WinEDA_ZoneFrame::GetIconResource( const wxString& name )
{
// Icon retrieval
////@begin WinEDA_ZoneFrame icon retrieval
wxUnusedVar(name);
wxUnusedVar( name );
return wxNullIcon;
////@end WinEDA_ZoneFrame icon retrieval
}
/*!
* wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
*/
......@@ -262,6 +317,7 @@ void WinEDA_ZoneFrame::OnCancelClick( wxCommandEvent& event )
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in WinEDA_ZoneFrame.
// Before editing this code, remove the block markers.
event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in WinEDA_ZoneFrame.
}
......@@ -270,995 +326,1066 @@ void WinEDA_ZoneFrame::OnCancelClick( wxCommandEvent& event )
* wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON2
*/
/***********************************************************/
void WinEDA_ZoneFrame::ExecFillZone( wxCommandEvent & event)
void WinEDA_ZoneFrame::ExecFillZone( wxCommandEvent& event )
/***********************************************************/
{
switch ( m_FillOpt->GetSelection() )
{
case 0:
Zone_Exclude_Pads = FALSE;
Zone_Genere_Freins_Thermiques = FALSE;
break;
case 1:
Zone_Exclude_Pads = TRUE;
Zone_Genere_Freins_Thermiques = TRUE;
break;
case 2:
Zone_Exclude_Pads = TRUE;
Zone_Genere_Freins_Thermiques = FALSE;
break;
}
switch ( m_GridCtrl->GetSelection() )
{
case 0:
g_GridRoutingSize = 50;
break;
case 1:
g_GridRoutingSize = 100;
break;
case 2:
g_GridRoutingSize = 250;
break;
case 3:
g_GridRoutingSize = 500;
break;
}
wxString txtvalue = m_ZoneClearanceCtrl->GetValue();
g_DesignSettings.m_ZoneClearence =
ReturnValueFromString( g_UnitMetric, txtvalue, m_Parent->m_InternalUnits);
if ( m_OrientEdgesOpt->GetSelection() == 0) Zone_45_Only = FALSE;
else Zone_45_Only = TRUE;
if ( event.GetId() == ID_SET_OPTIONS_ZONE ) EndModal(1);
else EndModal(0);
switch( m_FillOpt->GetSelection() )
{
case 0:
Zone_Exclude_Pads = FALSE;
Zone_Genere_Freins_Thermiques = FALSE;
break;
case 1:
Zone_Exclude_Pads = TRUE;
Zone_Genere_Freins_Thermiques = TRUE;
break;
case 2:
Zone_Exclude_Pads = TRUE;
Zone_Genere_Freins_Thermiques = FALSE;
break;
}
switch( m_GridCtrl->GetSelection() )
{
case 0:
g_GridRoutingSize = 50;
break;
case 1:
g_GridRoutingSize = 100;
break;
case 2:
g_GridRoutingSize = 250;
break;
case 3:
g_GridRoutingSize = 500;
break;
}
wxString txtvalue = m_ZoneClearanceCtrl->GetValue();
g_DesignSettings.m_ZoneClearence =
ReturnValueFromString( g_UnitMetric, txtvalue, m_Parent->m_InternalUnits );
if( m_OrientEdgesOpt->GetSelection() == 0 )
Zone_45_Only = FALSE;
else
Zone_45_Only = TRUE;
if( event.GetId() == ID_SET_OPTIONS_ZONE )
EndModal( 1 );
else
EndModal( 0 );
}
/**************************************************************/
void WinEDA_PcbFrame::Edit_Zone_Width(wxDC * DC, SEGZONE * Zone)
void WinEDA_PcbFrame::Edit_Zone_Width( wxDC* DC, SEGZONE* Zone )
/**************************************************************/
/* Edite (change la largeur des segments) la zone Zone.
La zone est constituee des segments zones de meme TimeStamp
*/
* La zone est constituee des segments zones de meme TimeStamp
*/
{
SEGZONE * pt_segm, * NextS ;
unsigned long TimeStamp;
bool modify = FALSE;
double f_new_width;
int w_tmp;
wxString Line;
wxString Msg( _("New zone segment width: ") );
if ( Zone == NULL ) return;
f_new_width = To_User_Unit(g_UnitMetric, Zone->m_Width, GetScreen()->GetInternalUnits());
Line.Printf(wxT("%.4f"), f_new_width);
Msg += g_UnitMetric ? wxT("(mm)") : wxT("(\")");
if ( Get_Message(Msg, Line, this) != 0 ) return;
w_tmp = g_DesignSettings.m_CurrentTrackWidth;
Line.ToDouble( &f_new_width);
g_DesignSettings.m_CurrentTrackWidth = From_User_Unit(g_UnitMetric, f_new_width, GetScreen()->GetInternalUnits());
TimeStamp = Zone->m_TimeStamp;
for( pt_segm = (SEGZONE*)m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS)
{
NextS = (SEGZONE*) pt_segm->Pnext;
if(pt_segm->m_TimeStamp == TimeStamp)
{
modify = TRUE;
Edit_TrackSegm_Width(DC, pt_segm);
}
}
g_DesignSettings.m_CurrentTrackWidth = w_tmp;
if ( modify )
{
GetScreen()->SetModify();
DrawPanel->Refresh();
}
SEGZONE* pt_segm, * NextS;
unsigned long TimeStamp;
bool modify = FALSE;
double f_new_width;
int w_tmp;
wxString Line;
wxString Msg( _( "New zone segment width: " ) );
if( Zone == NULL )
return;
f_new_width = To_User_Unit( g_UnitMetric, Zone->m_Width, GetScreen()->GetInternalUnits() );
Line.Printf( wxT( "%.4f" ), f_new_width );
Msg += g_UnitMetric ? wxT( "(mm)" ) : wxT( "(\")" );
if( Get_Message( Msg, Line, this ) != 0 )
return;
w_tmp = g_DesignSettings.m_CurrentTrackWidth;
Line.ToDouble( &f_new_width );
g_DesignSettings.m_CurrentTrackWidth = From_User_Unit( g_UnitMetric,
f_new_width, GetScreen()->GetInternalUnits() );
TimeStamp = Zone->m_TimeStamp;
for( pt_segm = (SEGZONE*) m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS )
{
NextS = (SEGZONE*) pt_segm->Pnext;
if( pt_segm->m_TimeStamp == TimeStamp )
{
modify = TRUE;
Edit_TrackSegm_Width( DC, pt_segm );
}
}
g_DesignSettings.m_CurrentTrackWidth = w_tmp;
if( modify )
{
GetScreen()->SetModify();
DrawPanel->Refresh();
}
}
/**********************************************************/
void WinEDA_PcbFrame::Delete_Zone(wxDC * DC, SEGZONE * Zone)
void WinEDA_PcbFrame::Delete_Zone( wxDC* DC, SEGZONE* Zone )
/**********************************************************/
/* Efface la zone Zone.
La zone est constituee des segments zones de meme TimeStamp
*/
* La zone est constituee des segments zones de meme TimeStamp
*/
{
SEGZONE * pt_segm, * NextS ;
unsigned long TimeStamp;
int nb_segm = 0;
bool modify = FALSE;
TimeStamp = Zone->m_TimeStamp;
for( pt_segm = (SEGZONE*)m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS)
{
NextS = (SEGZONE*) pt_segm->Pnext;
if(pt_segm->m_TimeStamp == TimeStamp)
{
modify = TRUE;
/* effacement des segments a l'ecran */
Trace_Une_Piste(DrawPanel, DC, pt_segm, nb_segm, GR_XOR);
DeleteStructure(pt_segm);
}
}
if ( modify )
{
GetScreen()->SetModify();
GetScreen()->SetRefreshReq();
}
SEGZONE* pt_segm, * NextS;
unsigned long TimeStamp;
int nb_segm = 0;
bool modify = FALSE;
TimeStamp = Zone->m_TimeStamp;
for( pt_segm = (SEGZONE*) m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS )
{
NextS = (SEGZONE*) pt_segm->Pnext;
if( pt_segm->m_TimeStamp == TimeStamp )
{
modify = TRUE;
/* effacement des segments a l'ecran */
Trace_Une_Piste( DrawPanel, DC, pt_segm, nb_segm, GR_XOR );
DeleteStructure( pt_segm );
}
}
if( modify )
{
GetScreen()->SetModify();
GetScreen()->SetRefreshReq();
}
}
/*****************************************************************************/
EDGE_ZONE * WinEDA_PcbFrame::Del_SegmEdgeZone(wxDC * DC, EDGE_ZONE * edge_zone)
EDGE_ZONE* WinEDA_PcbFrame::Del_SegmEdgeZone( wxDC* DC, EDGE_ZONE* edge_zone )
/*****************************************************************************/
/* Routine d'effacement du segment de limite zone en cours de trace */
{
EDGE_ZONE * Segm, * previous_segm;
if (m_Pcb->m_CurrentLimitZone) Segm = m_Pcb->m_CurrentLimitZone;
else Segm = edge_zone;
if( Segm == NULL) return NULL;
Trace_DrawSegmentPcb(DrawPanel, DC, Segm, GR_XOR);
previous_segm = (EDGE_ZONE *)Segm->Pback;
delete Segm;
Segm = previous_segm;
m_Pcb->m_CurrentLimitZone = Segm;
GetScreen()->m_CurrentItem = Segm;
if( Segm )
{
Segm->Pnext = NULL;
if( DrawPanel->ManageCurseur)
DrawPanel->ManageCurseur(DrawPanel, DC, TRUE);
}
else
{
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
GetScreen()->m_CurrentItem = NULL;
}
return Segm;
EDGE_ZONE* Segm, * previous_segm;
if( m_Pcb->m_CurrentLimitZone )
Segm = m_Pcb->m_CurrentLimitZone;
else
Segm = edge_zone;
if( Segm == NULL )
return NULL;
Trace_DrawSegmentPcb( DrawPanel, DC, Segm, GR_XOR );
previous_segm = (EDGE_ZONE*) Segm->Pback;
delete Segm;
Segm = previous_segm;
m_Pcb->m_CurrentLimitZone = Segm;
GetScreen()->m_CurrentItem = Segm;
if( Segm )
{
Segm->Pnext = NULL;
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
}
else
{
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
GetScreen()->m_CurrentItem = NULL;
}
return Segm;
}
/*********************************************/
void WinEDA_PcbFrame::CaptureNetName(wxDC * DC)
void WinEDA_PcbFrame::CaptureNetName( wxDC* DC )
/*********************************************/
/* routine permettant de capturer le nom net net (netcode) d'un pad
ou d'une piste pour l'utiliser comme netcode de zone
*/
* ou d'une piste pour l'utiliser comme netcode de zone
*/
{
D_PAD* pt_pad = 0;
TRACK * adrpiste ;
MODULE * Module;
int masquelayer = g_TabOneLayerMask[GetScreen()->m_Active_Layer];
int netcode;
netcode = -1;
MsgPanel->EraseMsgBox();
adrpiste = Locate_Pistes(m_Pcb->m_Track, masquelayer,CURSEUR_OFF_GRILLE);
if ( adrpiste == NULL )
{
pt_pad = Locate_Any_Pad(m_Pcb, CURSEUR_OFF_GRILLE);
if(pt_pad) /* Verif qu'il est bien sur la couche active */
{
Module = (MODULE*) pt_pad->m_Parent;
pt_pad = Locate_Pads(Module,g_TabOneLayerMask[GetScreen()->m_Active_Layer],
CURSEUR_OFF_GRILLE);
}
if( pt_pad )
{
pt_pad->Display_Infos(this);
netcode = pt_pad->m_NetCode;
}
}
else
{
Affiche_Infos_Piste(this, adrpiste) ;
netcode = adrpiste->m_NetCode;
}
// Mise en surbrillance du net
if(g_HightLigt_Status) Hight_Light(DC);
g_HightLigth_NetCode = netcode;
if ( g_HightLigth_NetCode >= 0 )
{
Hight_Light(DC);
}
/* Affichage du net selectionne pour la zone a tracer */
Display_Zone_Netname(this);
D_PAD* pt_pad = 0;
TRACK* adrpiste;
MODULE* Module;
int masquelayer = g_TabOneLayerMask[GetScreen()->m_Active_Layer];
int netcode;
netcode = -1;
MsgPanel->EraseMsgBox();
adrpiste = Locate_Pistes( m_Pcb->m_Track, masquelayer, CURSEUR_OFF_GRILLE );
if( adrpiste == NULL )
{
pt_pad = Locate_Any_Pad( m_Pcb, CURSEUR_OFF_GRILLE );
if( pt_pad ) /* Verif qu'il est bien sur la couche active */
{
Module = (MODULE*) pt_pad->m_Parent;
pt_pad = Locate_Pads( Module, g_TabOneLayerMask[GetScreen()->m_Active_Layer],
CURSEUR_OFF_GRILLE );
}
if( pt_pad )
{
pt_pad->Display_Infos( this );
netcode = pt_pad->m_NetCode;
}
}
else
{
Affiche_Infos_Piste( this, adrpiste );
netcode = adrpiste->m_NetCode;
}
// Mise en surbrillance du net
if( g_HightLigt_Status )
Hight_Light( DC );
g_HightLigth_NetCode = netcode;
if( g_HightLigth_NetCode >= 0 )
{
Hight_Light( DC );
}
/* Affichage du net selectionne pour la zone a tracer */
Display_Zone_Netname( this );
}
/*******************************************************/
static void Display_Zone_Netname(WinEDA_PcbFrame *frame)
static void Display_Zone_Netname( WinEDA_PcbFrame* frame )
/*******************************************************/
/*
Affiche le net_code et le nom de net couramment selectionne
*/
* Affiche le net_code et le nom de net couramment selectionne
*/
{
EQUIPOT * pt_equipot;
wxString line;
pt_equipot = frame->m_Pcb->m_Equipots;
if( g_HightLigth_NetCode > 0 )
{
for( ; pt_equipot != NULL; pt_equipot = (EQUIPOT*)pt_equipot->Pnext)
{
if( pt_equipot->m_NetCode == g_HightLigth_NetCode) break;
}
if( pt_equipot )
{
line.Printf( wxT("Zone: Net[%d] <%s>"),g_HightLigth_NetCode,
pt_equipot->m_Netname.GetData());
}
else line.Printf( wxT("Zone: NetCode[%d], Equipot not found"),
g_HightLigth_NetCode);
}
line = _("Zone: No net selected");
frame->Affiche_Message(line);
EQUIPOT* pt_equipot;
wxString line;
pt_equipot = frame->m_Pcb->m_Equipots;
if( g_HightLigth_NetCode > 0 )
{
for( ; pt_equipot != NULL; pt_equipot = (EQUIPOT*) pt_equipot->Pnext )
{
if( pt_equipot->m_NetCode == g_HightLigth_NetCode )
break;
}
if( pt_equipot )
{
line.Printf( wxT( "Zone: Net[%d] <%s>" ), g_HightLigth_NetCode,
pt_equipot->m_Netname.GetData() );
}
else
line.Printf( wxT( "Zone: NetCode[%d], Equipot not found" ),
g_HightLigth_NetCode );
}
line = _( "Zone: No net selected" );
frame->Affiche_Message( line );
}
/********************************************************/
static void Exit_Zones(WinEDA_DrawPanel * Panel, wxDC *DC)
static void Exit_Zones( WinEDA_DrawPanel* Panel, wxDC* DC )
/********************************************************/
/* routine d'annulation de la Commande Begin_Zone si une piste est en cours
de tracage, ou de sortie de l'application SEGZONES.
Appel par la touche ESC
* de tracage, ou de sortie de l'application SEGZONES.
* Appel par la touche ESC
*/
{
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*)Panel->m_Parent;
if( pcbframe->m_Pcb->m_CurrentLimitZone )
{
if( Panel->ManageCurseur ) /* trace en cours */
{
Panel->ManageCurseur(Panel, DC, 0);
}
pcbframe->DelLimitesZone(DC, FALSE);
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
pcbframe->GetScreen()->m_CurrentItem = NULL;
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent;
if( pcbframe->m_Pcb->m_CurrentLimitZone )
{
if( Panel->ManageCurseur ) /* trace en cours */
{
Panel->ManageCurseur( Panel, DC, 0 );
}
pcbframe->DelLimitesZone( DC, FALSE );
}
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
pcbframe->GetScreen()->m_CurrentItem = NULL;
}
/**************************************************************/
void WinEDA_BasePcbFrame::DelLimitesZone(wxDC *DC, bool Redraw)
void WinEDA_BasePcbFrame::DelLimitesZone( wxDC* DC, bool Redraw )
/**************************************************************/
/* Supprime la liste des segments constituant la frontiere courante
Libere la memoire correspondante
*/
* Libere la memoire correspondante
*/
{
EDGE_ZONE * segment, * Next;
if( m_Pcb->m_CurrentLimitZone == NULL ) return;
if ( ! IsOK(this, _("Delete Current Zone Edges")) ) return;
/* efface ancienne limite de zone */
segment = m_Pcb->m_CurrentLimitZone;
for( ; segment != NULL; segment = Next)
{
Next = (EDGE_ZONE*) segment->Pback;
if ( Redraw ) Trace_DrawSegmentPcb(DrawPanel, DC, segment,GR_XOR);
segment->Pnext = NULL; delete segment;
}
GetScreen()->m_CurrentItem = NULL;
m_Pcb->m_CurrentLimitZone = NULL;
EDGE_ZONE* segment, * Next;
if( m_Pcb->m_CurrentLimitZone == NULL )
return;
if( !IsOK( this, _( "Delete Current Zone Edges" ) ) )
return;
/* efface ancienne limite de zone */
segment = m_Pcb->m_CurrentLimitZone;
for( ; segment != NULL; segment = Next )
{
Next = (EDGE_ZONE*) segment->Pback;
if( Redraw )
Trace_DrawSegmentPcb( DrawPanel, DC, segment, GR_XOR );
segment->Pnext = NULL; delete segment;
}
GetScreen()->m_CurrentItem = NULL;
m_Pcb->m_CurrentLimitZone = NULL;
}
/********************************************/
EDGE_ZONE * WinEDA_PcbFrame::Begin_Zone(void)
EDGE_ZONE* WinEDA_PcbFrame::Begin_Zone( void )
/********************************************/
/*
Routine d'initialisation d'un trace de Limite de Zone ou
de placement d'un point intermediaire
*/
* Routine d'initialisation d'un trace de Limite de Zone ou
* de placement d'un point intermediaire
*/
{
EDGE_ZONE * oldedge, * newedge = NULL;
oldedge = m_Pcb->m_CurrentLimitZone;
if( (m_Pcb->m_CurrentLimitZone == NULL ) || /* debut reel du trace */
(DrawPanel->ManageCurseur == NULL) ) /* reprise d'un trace complementaire */
{
m_Pcb->m_CurrentLimitZone = newedge = new EDGE_ZONE( m_Pcb );
newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED;
newedge->Pback = oldedge;
if(oldedge) oldedge->Pnext = newedge;
newedge->m_Layer = GetScreen()->m_Active_Layer;
newedge->m_Width = 2 ; /* Largeur minimum tracable */
newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur;
m_Pcb->m_CurrentLimitZone = newedge;
DrawPanel->ManageCurseur = Show_Zone_Edge_While_MoveMouse;
DrawPanel->ForceCloseManageCurseur = Exit_Zones;
}
else /* piste en cours : les coord du point d'arrivee ont ete mises
a jour par la routine Show_Zone_Edge_While_MoveMouse*/
{
if( (oldedge->m_Start.x != oldedge->m_End.x) ||
(oldedge->m_Start.y != oldedge->m_End.y) )
{
newedge = new EDGE_ZONE( oldedge);
newedge->Pback = oldedge;
oldedge->Pnext = newedge;
newedge->m_Flags = IS_NEW | IS_MOVED;
newedge->m_Start = newedge->m_End = oldedge->m_End;
newedge->m_Layer = GetScreen()->m_Active_Layer;
m_Pcb->m_CurrentLimitZone = newedge;
}
}
return newedge;
EDGE_ZONE* oldedge, * newedge = NULL;
oldedge = m_Pcb->m_CurrentLimitZone;
if( (m_Pcb->m_CurrentLimitZone == NULL ) /* debut reel du trace */
|| (DrawPanel->ManageCurseur == NULL) ) /* reprise d'un trace complementaire */
{
m_Pcb->m_CurrentLimitZone = newedge = new EDGE_ZONE( m_Pcb );
newedge->m_Flags = IS_NEW | STARTPOINT | IS_MOVED;
newedge->Pback = oldedge;
if( oldedge )
oldedge->Pnext = newedge;
newedge->m_Layer = GetScreen()->m_Active_Layer;
newedge->m_Width = 2; /* Largeur minimum tracable */
newedge->m_Start = newedge->m_End = GetScreen()->m_Curseur;
m_Pcb->m_CurrentLimitZone = newedge;
DrawPanel->ManageCurseur = Show_Zone_Edge_While_MoveMouse;
DrawPanel->ForceCloseManageCurseur = Exit_Zones;
}
else /* piste en cours : les coord du point d'arrivee ont ete mises
* a jour par la routine Show_Zone_Edge_While_MoveMouse*/
{
if( (oldedge->m_Start.x != oldedge->m_End.x)
|| (oldedge->m_Start.y != oldedge->m_End.y) )
{
newedge = new EDGE_ZONE( oldedge );
newedge->Pback = oldedge;
oldedge->Pnext = newedge;
newedge->m_Flags = IS_NEW | IS_MOVED;
newedge->m_Start = newedge->m_End = oldedge->m_End;
newedge->m_Layer = GetScreen()->m_Active_Layer;
m_Pcb->m_CurrentLimitZone = newedge;
}
}
return newedge;
}
/*********************************************/
void WinEDA_PcbFrame::End_Zone(wxDC * DC)
void WinEDA_PcbFrame::End_Zone( wxDC* DC )
/*********************************************/
/*
Routine de fin de trace d'une zone (succession de segments)
*/
* Routine de fin de trace d'une zone (succession de segments)
*/
{
EDGE_ZONE * PtLim;
if( m_Pcb->m_CurrentLimitZone )
{
Begin_Zone();
/* le dernier point genere est de longueur tj nulle donc inutile. */
/* il sera raccorde au point de depart */
PtLim = m_Pcb->m_CurrentLimitZone;
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
while( PtLim && PtLim->Pback)
{
PtLim = (EDGE_ZONE*) PtLim->Pback;
if ( PtLim->m_Flags & STARTPOINT) break;
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
}
if( PtLim )
{
PtLim->m_Flags &= ~(IS_NEW|IS_MOVED);
m_Pcb->m_CurrentLimitZone->m_End = PtLim->m_Start;
}
Trace_DrawSegmentPcb(DrawPanel, DC, m_Pcb->m_CurrentLimitZone,GR_XOR);
}
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
EDGE_ZONE* PtLim;
if( m_Pcb->m_CurrentLimitZone )
{
Begin_Zone();
/* le dernier point genere est de longueur tj nulle donc inutile. */
/* il sera raccorde au point de depart */
PtLim = m_Pcb->m_CurrentLimitZone;
PtLim->m_Flags &= ~(IS_NEW | IS_MOVED);
while( PtLim && PtLim->Pback )
{
PtLim = (EDGE_ZONE*) PtLim->Pback;
if( PtLim->m_Flags & STARTPOINT )
break;
PtLim->m_Flags &= ~(IS_NEW | IS_MOVED);
}
if( PtLim )
{
PtLim->m_Flags &= ~(IS_NEW | IS_MOVED);
m_Pcb->m_CurrentLimitZone->m_End = PtLim->m_Start;
}
Trace_DrawSegmentPcb( DrawPanel, DC, m_Pcb->m_CurrentLimitZone, GR_XOR );
}
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
}
/******************************************************************************************/
static void Show_Zone_Edge_While_MoveMouse(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
static void Show_Zone_Edge_While_MoveMouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/******************************************************************************************/
/* redessin du contour de la piste lors des deplacements de la souris
*/
*/
{
EDGE_ZONE * PtLim, * edgezone;
WinEDA_PcbFrame * pcbframe = (WinEDA_PcbFrame *) panel->m_Parent;
if( pcbframe->m_Pcb->m_CurrentLimitZone == NULL ) return ;
/* efface ancienne position si elle a ete deja dessinee */
if( erase )
{
PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
{
Trace_DrawSegmentPcb(panel, DC, PtLim,GR_XOR);
}
}
/* mise a jour de la couche */
edgezone = PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
{
PtLim->m_Layer = pcbframe->GetScreen()->m_Active_Layer;
}
/* dessin de la nouvelle piste : mise a jour du point d'arrivee */
if (Zone_45_Only)
{/* Calcul de l'extremite de la piste pour orientations permises:
horiz,vertical ou 45 degre */
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
Calcule_Coord_Extremite_45(edgezone->m_Start.x, edgezone->m_Start.y,
&edgezone->m_End.x, &edgezone->m_End.y);
}
else /* ici l'angle d'inclinaison est quelconque */
{
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
}
PtLim = edgezone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
{
Trace_DrawSegmentPcb(panel, DC, PtLim,GR_XOR);
}
EDGE_ZONE* PtLim, * edgezone;
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) panel->m_Parent;
if( pcbframe->m_Pcb->m_CurrentLimitZone == NULL )
return;
/* efface ancienne position si elle a ete deja dessinee */
if( erase )
{
PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
Trace_DrawSegmentPcb( panel, DC, PtLim, GR_XOR );
}
}
/* mise a jour de la couche */
edgezone = PtLim = pcbframe->m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
PtLim->m_Layer = pcbframe->GetScreen()->m_Active_Layer;
}
/* dessin de la nouvelle piste : mise a jour du point d'arrivee */
if( Zone_45_Only )
{/* Calcul de l'extremite de la piste pour orientations permises:
* horiz,vertical ou 45 degre */
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
Calcule_Coord_Extremite_45( edgezone->m_Start.x, edgezone->m_Start.y,
&edgezone->m_End.x, &edgezone->m_End.y );
}
else /* ici l'angle d'inclinaison est quelconque */
{
edgezone->m_End = pcbframe->GetScreen()->m_Curseur;
}
PtLim = edgezone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
Trace_DrawSegmentPcb( panel, DC, PtLim, GR_XOR );
}
}
/**********************************************/
void WinEDA_PcbFrame::Fill_Zone(wxDC * DC)
void WinEDA_PcbFrame::Fill_Zone( wxDC* DC )
/**********************************************/
/*
Fonction generale de creation de zone
Un contour de zone doit exister, sinon l'ensemble du PCB est utilise
ce qui permet de creer des obstacles et donc des parties non remplies.
Le remplissage s'effectue a partir du point d'ancrage, jusque ves les limites
On place la zone sur la couche (layer) active.
"Hight Light" la zone fera partie de ce net
*/
/*
* Fonction generale de creation de zone
* Un contour de zone doit exister, sinon l'ensemble du PCB est utilise
*
* ce qui permet de creer des obstacles et donc des parties non remplies.
*
* Le remplissage s'effectue a partir du point d'ancrage, jusque ves les limites
*
*
* On place la zone sur la couche (layer) active.
*
*
* "Hight Light" la zone fera partie de ce net
*/
{
int ii, jj;
EDGE_ZONE* PtLim;
int lp_tmp, lay_tmp_TOP, lay_tmp_BOTTOM;
EQUIPOT* pt_equipot;
int save_isol = g_DesignSettings.m_TrackClearence;
wxPoint ZoneStartFill;
wxString msg;
MsgPanel->EraseMsgBox();
if ( m_Pcb->ComputeBoundaryBox() == FALSE )
{
DisplayError(this, wxT("Board is empty!"), 10);
return;
}
DrawPanel->m_IgnoreMouseEvents = TRUE;
WinEDA_ZoneFrame * frame = new WinEDA_ZoneFrame(this);
ii = frame->ShowModal(); frame->Destroy();
DrawPanel->MouseToCursorSchema();
DrawPanel->m_IgnoreMouseEvents = FALSE;
if ( ii ) return;
g_DesignSettings.m_TrackClearence = g_DesignSettings.m_ZoneClearence;
/* mise a jour de la couche */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback)
{
Trace_DrawSegmentPcb(DrawPanel, DC, PtLim, GR_XOR);
PtLim->m_Layer = GetScreen()->m_Active_Layer;
Trace_DrawSegmentPcb(DrawPanel, DC, PtLim, GR_XOR);
}
s_TimeStamp = time( NULL );
/* Calcul du pas de routage fixe a 5 mils et plus */
E_scale = g_GridRoutingSize / 50 ; if (g_GridRoutingSize < 1 ) g_GridRoutingSize = 1 ;
/* calcule de Ncols et Nrow, taille de la matrice de routage */
ComputeMatriceSize(this, g_GridRoutingSize);
/* Determination de la cellule pointee par la souris */
ZoneStartFill.x = (GetScreen()->m_Curseur.x - m_Pcb->m_BoundaryBox.m_Pos.x + (g_GridRoutingSize/2) ) / g_GridRoutingSize;
ZoneStartFill.y = (GetScreen()->m_Curseur.y - m_Pcb->m_BoundaryBox.m_Pos.y + (g_GridRoutingSize/2) ) / g_GridRoutingSize;
if(ZoneStartFill.x < 0) ZoneStartFill.x = 0;
if(ZoneStartFill.x >= Ncols) ZoneStartFill.x = Ncols-1;
if(ZoneStartFill.y < 0) ZoneStartFill.y = 0;
if(ZoneStartFill.y >= Nrows) ZoneStartFill.y = Nrows-1;
/* Creation du mapping de la matrice de routage */
Nb_Sides = ONE_SIDE;
if( Board.InitBoard() < 0)
{
DisplayError(this, wxT("Mo memory for creating zones"));
return;
}
msg.Printf( wxT("%d"),Ncols);
Affiche_1_Parametre(this, 1, wxT("Cols"),msg,GREEN);
msg.Printf( wxT("%d"),Nrows);
Affiche_1_Parametre(this, 7, wxT("Lines"),msg,GREEN);
msg.Printf( wxT("%d"), Board.m_MemSize / 1024 );
Affiche_1_Parametre(this, 14, wxT("Mem(Ko)"),msg,CYAN);
lay_tmp_BOTTOM = Route_Layer_BOTTOM;
lay_tmp_TOP = Route_Layer_TOP;
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
lp_tmp = g_DesignSettings.m_CurrentTrackWidth; g_DesignSettings.m_CurrentTrackWidth = g_GridRoutingSize;
/* Affichage du NetName */
if(g_HightLigth_NetCode > 0)
{
pt_equipot = GetEquipot(m_Pcb, g_HightLigth_NetCode);
if( pt_equipot == NULL)
{
if(g_HightLigth_NetCode > 0 ) DisplayError(this, wxT("Equipot Error"));
}
else msg = pt_equipot->m_Netname;
}
else msg = _("No Net");
Affiche_1_Parametre(this, 22,_("NetName"),msg,RED) ;
/* Init des points d'accrochage possibles de la zone:
les pistes du net sont des points d'accrochage convenables*/
TRACK * pt_segm = m_Pcb->m_Track;
for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext)
{
if(g_HightLigth_NetCode != pt_segm->m_NetCode) continue;
if ( pt_segm->m_Layer != GetScreen()->m_Active_Layer ) continue;
if (pt_segm->m_StructType != TYPETRACK ) continue;
TraceSegmentPcb(m_Pcb, pt_segm, CELL_is_FRIEND, 0, WRITE_CELL );
}
/* Trace des contours du PCB sur la matrice de routage: */
Route_Layer_BOTTOM = Route_Layer_TOP = EDGE_N;
PlaceCells(m_Pcb, -1, 0);
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
/* Trace des limites de la zone sur la matrice de routage: */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*)PtLim->Pback)
{
int ux0, uy0, ux1, uy1;
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
TraceLignePcb(ux0,uy0,ux1,uy1,-1,HOLE|CELL_is_EDGE,WRITE_CELL);
}
OrCell(ZoneStartFill.y,ZoneStartFill.x, BOTTOM, CELL_is_ZONE);
/* Marquage des cellules faisant partie de la zone*/
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT("%d"), jj++ );
Affiche_1_Parametre(this, 50, wxT("Iter."),msg,CYAN);
ii = Propagation(this);
}
/* Selection des cellules convenables pour les points d'ancrage de la zone */
for( ii = 0; ii < Nrows ; ii++)
{
for( jj = 0; jj < Ncols ; jj++)
{
long cell = GetCell(ii,jj,BOTTOM);
if( (cell & CELL_is_ZONE) )
{
if ( (cell & CELL_is_FRIEND) == 0)
AndCell(ii,jj,BOTTOM, (BoardCell) ~(CELL_is_FRIEND|CELL_is_ZONE) );
}
}
}
int ii, jj;
EDGE_ZONE* PtLim;
int lp_tmp, lay_tmp_TOP, lay_tmp_BOTTOM;
EQUIPOT* pt_equipot;
int save_isol = g_DesignSettings.m_TrackClearence;
wxPoint ZoneStartFill;
wxString msg;
MsgPanel->EraseMsgBox();
if( m_Pcb->ComputeBoundaryBox() == FALSE )
{
DisplayError( this, wxT( "Board is empty!" ), 10 );
return;
}
DrawPanel->m_IgnoreMouseEvents = TRUE;
WinEDA_ZoneFrame* frame = new WinEDA_ZoneFrame( this );
ii = frame->ShowModal(); frame->Destroy();
DrawPanel->MouseToCursorSchema();
DrawPanel->m_IgnoreMouseEvents = FALSE;
if( ii )
return;
g_DesignSettings.m_TrackClearence = g_DesignSettings.m_ZoneClearence;
/* mise a jour de la couche */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
Trace_DrawSegmentPcb( DrawPanel, DC, PtLim, GR_XOR );
PtLim->m_Layer = GetScreen()->m_Active_Layer;
Trace_DrawSegmentPcb( DrawPanel, DC, PtLim, GR_XOR );
}
s_TimeStamp = time( NULL );
/* Calcul du pas de routage fixe a 5 mils et plus */
E_scale = g_GridRoutingSize / 50; if( g_GridRoutingSize < 1 )
g_GridRoutingSize = 1;
/* calcule de Ncols et Nrow, taille de la matrice de routage */
ComputeMatriceSize( this, g_GridRoutingSize );
/* Determination de la cellule pointee par la souris */
ZoneStartFill.x = ( GetScreen()->m_Curseur.x - m_Pcb->m_BoundaryBox.m_Pos.x +
(g_GridRoutingSize / 2) ) / g_GridRoutingSize;
ZoneStartFill.y = ( GetScreen()->m_Curseur.y - m_Pcb->m_BoundaryBox.m_Pos.y +
(g_GridRoutingSize / 2) ) / g_GridRoutingSize;
if( ZoneStartFill.x < 0 )
ZoneStartFill.x = 0;
if( ZoneStartFill.x >= Ncols )
ZoneStartFill.x = Ncols - 1;
if( ZoneStartFill.y < 0 )
ZoneStartFill.y = 0;
if( ZoneStartFill.y >= Nrows )
ZoneStartFill.y = Nrows - 1;
/* Creation du mapping de la matrice de routage */
Nb_Sides = ONE_SIDE;
if( Board.InitBoard() < 0 )
{
DisplayError( this, wxT( "Mo memory for creating zones" ) );
return;
}
msg.Printf( wxT( "%d" ), Ncols );
Affiche_1_Parametre( this, 1, wxT( "Cols" ), msg, GREEN );
msg.Printf( wxT( "%d" ), Nrows );
Affiche_1_Parametre( this, 7, wxT( "Lines" ), msg, GREEN );
msg.Printf( wxT( "%d" ), Board.m_MemSize / 1024 );
Affiche_1_Parametre( this, 14, wxT( "Mem(Ko)" ), msg, CYAN );
lay_tmp_BOTTOM = Route_Layer_BOTTOM;
lay_tmp_TOP = Route_Layer_TOP;
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
lp_tmp = g_DesignSettings.m_CurrentTrackWidth;
g_DesignSettings.m_CurrentTrackWidth = g_GridRoutingSize;
/* Affichage du NetName */
if( g_HightLigth_NetCode > 0 )
{
pt_equipot = GetEquipot( m_Pcb, g_HightLigth_NetCode );
if( pt_equipot == NULL )
{
if( g_HightLigth_NetCode > 0 )
DisplayError( this, wxT( "Equipot Error" ) );
}
else
msg = pt_equipot->m_Netname;
}
else
msg = _( "No Net" );
Affiche_1_Parametre( this, 22, _( "NetName" ), msg, RED );
/* Init des points d'accrochage possibles de la zone:
* les pistes du net sont des points d'accrochage convenables*/
TRACK* pt_segm = m_Pcb->m_Track;
for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
{
if( g_HightLigth_NetCode != pt_segm->m_NetCode )
continue;
if( pt_segm->m_Layer != GetScreen()->m_Active_Layer )
continue;
if( pt_segm->m_StructType != TYPETRACK )
continue;
TraceSegmentPcb( m_Pcb, pt_segm, CELL_is_FRIEND, 0, WRITE_CELL );
}
/* Trace des contours du PCB sur la matrice de routage: */
Route_Layer_BOTTOM = Route_Layer_TOP = EDGE_N;
PlaceCells( m_Pcb, -1, 0 );
Route_Layer_BOTTOM = Route_Layer_TOP = GetScreen()->m_Active_Layer;
/* Trace des limites de la zone sur la matrice de routage: */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
int ux0, uy0, ux1, uy1;
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
TraceLignePcb( ux0, uy0, ux1, uy1, -1, HOLE | CELL_is_EDGE, WRITE_CELL );
}
OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE );
/* Marquage des cellules faisant partie de la zone*/
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT( "%d" ), jj++ );
Affiche_1_Parametre( this, 50, wxT( "Iter." ), msg, CYAN );
ii = Propagation( this );
}
/* Selection des cellules convenables pour les points d'ancrage de la zone */
for( ii = 0; ii < Nrows; ii++ )
{
for( jj = 0; jj < Ncols; jj++ )
{
long cell = GetCell( ii, jj, BOTTOM );
if( (cell & CELL_is_ZONE) )
{
if( (cell & CELL_is_FRIEND) == 0 )
AndCell( ii, jj, BOTTOM, (BoardCell) ~(CELL_is_FRIEND | CELL_is_ZONE) );
}
}
}
/* Maintenant, toutes les cellules candidates sont marquees */
/* Placement des cellules (pads, tracks, vias, edges pcb ou segments)
faisant des obsctacles sur la matrice de routage */
ii = 0;
if( Zone_Exclude_Pads ) ii = FORCE_PADS;
Affiche_1_Parametre(this, 42, wxT("GenZone"),wxEmptyString,RED);
PlaceCells(m_Pcb, g_HightLigth_NetCode, ii);
Affiche_1_Parametre(this, -1, wxEmptyString, _("Ok"),RED);
/* Trace des limites de la zone sur la matrice de routage
(a pu etre detruit par PlaceCells()) : */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*)PtLim->Pback)
{
int ux0, uy0, ux1, uy1;
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
TraceLignePcb(ux0,uy0,ux1,uy1,-1,HOLE|CELL_is_EDGE,WRITE_CELL);
}
/* Init du point d'accrochage de la zone donné par la position souris
(a pu etre detruit par PlaceCells()) : */
OrCell(ZoneStartFill.y,ZoneStartFill.x, BOTTOM, CELL_is_ZONE);
if(Zone_Debug) DisplayBoard(DrawPanel, DC);
/* Remplissage des cellules (creation effective de la zone)*/
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT("%d"), jj++ );
Affiche_1_Parametre(this, 50, wxT("Iter."),msg,CYAN);
ii = Propagation(this);
}
if(Zone_Debug) DisplayBoard(DrawPanel, DC);
/* Generation des segments de piste type Zone correspondants*/
if(g_HightLigth_NetCode < 0 )
Genere_Segments_Zone(this, DC, 0);
else Genere_Segments_Zone(this, DC, g_HightLigth_NetCode);
/* Trace des connexions type frein thermique */
g_DesignSettings.m_CurrentTrackWidth = lp_tmp;
if ( Zone_Exclude_Pads && Zone_Genere_Freins_Thermiques)
Genere_Pad_Connexion(this, DC, GetScreen()->m_Active_Layer);
g_DesignSettings.m_TrackClearence = save_isol;
GetScreen()->SetModify();
/* Liberation de la memoire */
Board.UnInitBoard();
/* Reprise des conditions initiales */
Route_Layer_TOP = lay_tmp_TOP;
Route_Layer_BOTTOM = lay_tmp_BOTTOM;
/* Placement des cellules (pads, tracks, vias, edges pcb ou segments)
* faisant des obsctacles sur la matrice de routage */
ii = 0;
if( Zone_Exclude_Pads )
ii = FORCE_PADS;
Affiche_1_Parametre( this, 42, wxT( "GenZone" ), wxEmptyString, RED );
PlaceCells( m_Pcb, g_HightLigth_NetCode, ii );
Affiche_1_Parametre( this, -1, wxEmptyString, _( "Ok" ), RED );
/* Trace des limites de la zone sur la matrice de routage
* (a pu etre detruit par PlaceCells()) : */
PtLim = m_Pcb->m_CurrentLimitZone;
for( ; PtLim != NULL; PtLim = (EDGE_ZONE*) PtLim->Pback )
{
int ux0, uy0, ux1, uy1;
ux0 = PtLim->m_Start.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy0 = PtLim->m_Start.y - m_Pcb->m_BoundaryBox.m_Pos.y;
ux1 = PtLim->m_End.x - m_Pcb->m_BoundaryBox.m_Pos.x;
uy1 = PtLim->m_End.y - m_Pcb->m_BoundaryBox.m_Pos.y;
TraceLignePcb( ux0, uy0, ux1, uy1, -1, HOLE | CELL_is_EDGE, WRITE_CELL );
}
/* Init du point d'accrochage de la zone donné par la position souris
* (a pu etre detruit par PlaceCells()) : */
OrCell( ZoneStartFill.y, ZoneStartFill.x, BOTTOM, CELL_is_ZONE );
if( Zone_Debug )
DisplayBoard( DrawPanel, DC );
/* Remplissage des cellules (creation effective de la zone)*/
ii = 1; jj = 1;
while( ii )
{
msg.Printf( wxT( "%d" ), jj++ );
Affiche_1_Parametre( this, 50, wxT( "Iter." ), msg, CYAN );
ii = Propagation( this );
}
if( Zone_Debug )
DisplayBoard( DrawPanel, DC );
/* Generation des segments de piste type Zone correspondants*/
if( g_HightLigth_NetCode < 0 )
Genere_Segments_Zone( this, DC, 0 );
else
Genere_Segments_Zone( this, DC, g_HightLigth_NetCode );
/* Trace des connexions type frein thermique */
g_DesignSettings.m_CurrentTrackWidth = lp_tmp;
if( Zone_Exclude_Pads && Zone_Genere_Freins_Thermiques )
Genere_Pad_Connexion( this, DC, GetScreen()->m_Active_Layer );
g_DesignSettings.m_TrackClearence = save_isol;
GetScreen()->SetModify();
/* Liberation de la memoire */
Board.UnInitBoard();
/* Reprise des conditions initiales */
Route_Layer_TOP = lay_tmp_TOP;
Route_Layer_BOTTOM = lay_tmp_BOTTOM;
}
/*******************************************************************************/
static void Genere_Segments_Zone(WinEDA_PcbFrame *frame, wxDC * DC, int net_code)
static void Genere_Segments_Zone( WinEDA_PcbFrame* frame, wxDC* DC, int net_code )
/*******************************************************************************/
/* Genere les segments de piste dans les limites de la zone a remplir
Algorithme:
procede en 2 balayages
- Gauche->droite
- Haut->Bas
Parametres:
net_code = net_code a attribuer au segment de zone
TimeStamp(global): signature temporelle d'identification
(mis en .start)
*/
* Algorithme:
* procede en 2 balayages
* - Gauche->droite
* - Haut->Bas
* Parametres:
* net_code = net_code a attribuer au segment de zone
* TimeStamp(global): signature temporelle d'identification
* (mis en .start)
*/
{
int row, col;
long current_cell, old_cell;
int ux0 = 0, uy0 = 0, ux1 = 0, uy1 = 0;
int Xmin = frame->m_Pcb->m_BoundaryBox.m_Pos.x;
int Ymin = frame->m_Pcb->m_BoundaryBox.m_Pos.y;
SEGZONE * pt_track;
int layer = frame->GetScreen()->m_Active_Layer;
int nbsegm = 0;
wxString msg;
/* balayage Gauche-> droite */
Affiche_1_Parametre(frame, 64, wxT("Segm H"), wxT("0"),BROWN);
for( row = 0; row < Nrows ; row++)
{
old_cell = 0;
uy0 = uy1 = (row * g_GridRoutingSize) + Ymin;
for( col = 0; col < Ncols ; col++)
{
current_cell = GetCell(row,col,BOTTOM) & CELL_is_ZONE;
if(current_cell) /* ce point doit faire partie d'un segment */
{
ux1 = (col * g_GridRoutingSize) + Xmin;
if( old_cell == 0 ) ux0 = ux1;
}
if( ! current_cell || (col == Ncols-1) ) /* peut etre fin d'un segment */
{
if( (old_cell) && (ux0 != ux1) )
{ /* un segment avait debute de longueur > 0 */
pt_track = new SEGZONE(frame->m_Pcb);
pt_track->m_Layer = layer;
pt_track->m_NetCode = net_code;
pt_track->m_Width = g_GridRoutingSize;
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
pt_track->m_TimeStamp = s_TimeStamp;
pt_track->Insert(frame->m_Pcb, NULL);
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
nbsegm++;
}
}
old_cell = current_cell;
}
msg.Printf( wxT("%d"),nbsegm);
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,BROWN);
}
Affiche_1_Parametre(frame, 72, wxT("Segm V"), wxT("0"),BROWN);
for( col = 0; col < Ncols ; col++)
{
old_cell = 0;
ux0 = ux1 = (col * g_GridRoutingSize) + Xmin;
for( row = 0; row < Nrows ; row++)
{
current_cell = GetCell(row,col,BOTTOM) & CELL_is_ZONE;
if(current_cell) /* ce point doit faire partie d'un segment */
{
uy1 = (row * g_GridRoutingSize) + Ymin;
if( old_cell == 0 ) uy0 = uy1;
}
if( ! current_cell || (row == Nrows-1) ) /* peut etre fin d'un segment */
{
if( (old_cell) && (uy0 != uy1) )
{ /* un segment avait debute de longueur > 0 */
pt_track = new SEGZONE(frame->m_Pcb);
pt_track->m_Layer = layer;
pt_track->m_Width = g_GridRoutingSize;
pt_track->m_NetCode = net_code;
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
pt_track->m_TimeStamp = s_TimeStamp;
pt_track->Insert(frame->m_Pcb, NULL);
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
nbsegm++;
}
}
old_cell = current_cell;
}
msg.Printf( wxT("%d"),nbsegm);
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,BROWN);
}
int row, col;
long current_cell, old_cell;
int ux0 = 0, uy0 = 0, ux1 = 0, uy1 = 0;
int Xmin = frame->m_Pcb->m_BoundaryBox.m_Pos.x;
int Ymin = frame->m_Pcb->m_BoundaryBox.m_Pos.y;
SEGZONE* pt_track;
int layer = frame->GetScreen()->m_Active_Layer;
int nbsegm = 0;
wxString msg;
/* balayage Gauche-> droite */
Affiche_1_Parametre( frame, 64, wxT( "Segm H" ), wxT( "0" ), BROWN );
for( row = 0; row < Nrows; row++ )
{
old_cell = 0;
uy0 = uy1 = (row * g_GridRoutingSize) + Ymin;
for( col = 0; col < Ncols; col++ )
{
current_cell = GetCell( row, col, BOTTOM ) & CELL_is_ZONE;
if( current_cell ) /* ce point doit faire partie d'un segment */
{
ux1 = (col * g_GridRoutingSize) + Xmin;
if( old_cell == 0 )
ux0 = ux1;
}
if( !current_cell || (col == Ncols - 1) ) /* peut etre fin d'un segment */
{
if( (old_cell) && (ux0 != ux1) )
{
/* un segment avait debute de longueur > 0 */
pt_track = new SEGZONE( frame->m_Pcb );
pt_track->m_Layer = layer;
pt_track->m_NetCode = net_code;
pt_track->m_Width = g_GridRoutingSize;
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
pt_track->m_TimeStamp = s_TimeStamp;
pt_track->Insert( frame->m_Pcb, NULL );
pt_track->Draw( frame->DrawPanel, DC, GR_OR );
nbsegm++;
}
}
old_cell = current_cell;
}
msg.Printf( wxT( "%d" ), nbsegm );
Affiche_1_Parametre( frame, -1, wxEmptyString, msg, BROWN );
}
Affiche_1_Parametre( frame, 72, wxT( "Segm V" ), wxT( "0" ), BROWN );
for( col = 0; col < Ncols; col++ )
{
old_cell = 0;
ux0 = ux1 = (col * g_GridRoutingSize) + Xmin;
for( row = 0; row < Nrows; row++ )
{
current_cell = GetCell( row, col, BOTTOM ) & CELL_is_ZONE;
if( current_cell ) /* ce point doit faire partie d'un segment */
{
uy1 = (row * g_GridRoutingSize) + Ymin;
if( old_cell == 0 )
uy0 = uy1;
}
if( !current_cell || (row == Nrows - 1) ) /* peut etre fin d'un segment */
{
if( (old_cell) && (uy0 != uy1) )
{
/* un segment avait debute de longueur > 0 */
pt_track = new SEGZONE( frame->m_Pcb );
pt_track->m_Layer = layer;
pt_track->m_Width = g_GridRoutingSize;
pt_track->m_NetCode = net_code;
pt_track->m_Start.x = ux0; pt_track->m_Start.y = uy0;
pt_track->m_End.x = ux1; pt_track->m_End.y = uy1;
pt_track->m_TimeStamp = s_TimeStamp;
pt_track->Insert( frame->m_Pcb, NULL );
pt_track->Draw( frame->DrawPanel, DC, GR_OR );
nbsegm++;
}
}
old_cell = current_cell;
}
msg.Printf( wxT( "%d" ), nbsegm );
Affiche_1_Parametre( frame, -1, wxEmptyString, msg, BROWN );
}
}
/********************************************/
int Propagation(WinEDA_PcbFrame * frame)
int Propagation( WinEDA_PcbFrame* frame )
/********************************************/
/* Determine les cellules inscrites dans les limites de la zone a remplir
Algorithme:
Si une cellule disponible a un voisin faisant partie de la zone, elle
devient elle meme partie de la zone
On procede en 4 balayages de la matrice des cellules
- Gauche->droite de Haut->bas
- Droite->gauche de Haut->bas
- Bas->Haut de Droite->gauche
- Bas->Haut de Gauche->Droite
et pour chaque balayage, on considere des 2 cellules voisines de
la cellule courants: cellule precedente sur la ligne et cellule precedente
sur la colonne.
La routine peut demander plusieurs iterations
les iterations doivent continuer juqu'a ce que la routine ne trouve plus
de cellules a modifier.
Retourne:
Nombre de cellules modifiees (c.a.d mises a la valeur CELL_is_ZONE.
*/
* Algorithme:
* Si une cellule disponible a un voisin faisant partie de la zone, elle
* devient elle meme partie de la zone
* On procede en 4 balayages de la matrice des cellules
* - Gauche->droite de Haut->bas
* - Droite->gauche de Haut->bas
* - Bas->Haut de Droite->gauche
* - Bas->Haut de Gauche->Droite
* et pour chaque balayage, on considere des 2 cellules voisines de
* la cellule courants: cellule precedente sur la ligne et cellule precedente
* sur la colonne.
*
* La routine peut demander plusieurs iterations
* les iterations doivent continuer juqu'a ce que la routine ne trouve plus
* de cellules a modifier.
* Retourne:
* Nombre de cellules modifiees (c.a.d mises a la valeur CELL_is_ZONE.
*/
{
int row, col, nn;
long current_cell, old_cell_H;
int long * pt_cell_V;
int nbpoints = 0;
int row, col, nn;
long current_cell, old_cell_H;
int long* pt_cell_V;
int nbpoints = 0;
#define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
wxString msg;
Affiche_1_Parametre(frame, 57, wxT("Detect"),msg,CYAN);
/* balayage Gauche-> droite de Haut->bas */
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("1"),CYAN);
// Reservation memoire pour stockahe de 1 ligne ou une colonne de cellules
nn = MAX(Nrows, Ncols) * sizeof(*pt_cell_V);
pt_cell_V = (long *) MyMalloc(nn);
memset(pt_cell_V, 0, nn);
for( row = 0; row < Nrows ; row++)
{
old_cell_H = 0;
for( col = 0; col < Ncols ; col++)
{
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE;
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[col] & CELL_is_ZONE) )
{
OrCell(row,col,BOTTOM,CELL_is_ZONE);
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[col] = old_cell_H = current_cell;
}
}
/* balayage Droite-> gauche de Haut->bas */
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("2"),CYAN);
memset(pt_cell_V, 0, nn);
for( row = 0; row < Nrows ; row++)
{
old_cell_H = 0;
for( col = Ncols -1 ; col >= 0 ; col--)
{
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[col] & CELL_is_ZONE) )
{
OrCell(row,col,BOTTOM,CELL_is_ZONE);
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[col] = old_cell_H = current_cell;
}
}
/* balayage Bas->Haut de Droite->gauche */
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("3"),CYAN);
memset(pt_cell_V, 0, nn);
for( col = Ncols -1 ; col >= 0 ; col--)
{
old_cell_H = 0;
for( row = Nrows-1; row >= 0 ; row--)
{
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[row] & CELL_is_ZONE) )
{
OrCell(row,col,BOTTOM,CELL_is_ZONE);
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[row] = old_cell_H = current_cell;
}
}
/* balayage Bas->Haut de Gauche->Droite*/
Affiche_1_Parametre(frame, -1, wxEmptyString, wxT("4"),CYAN);
memset(pt_cell_V, 0, nn);
for( col = 0 ; col < Ncols ; col++)
{
old_cell_H = 0;
for( row = Nrows-1; row >= 0 ; row--)
{
current_cell = GetCell(row,col,BOTTOM) & NO_CELL_ZONE ;
if(current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[row] & CELL_is_ZONE) )
{
OrCell(row,col,BOTTOM,CELL_is_ZONE) ;
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[row] = old_cell_H = current_cell;
}
}
MyFree(pt_cell_V);
return(nbpoints);
wxString msg;
Affiche_1_Parametre( frame, 57, wxT( "Detect" ), msg, CYAN );
/* balayage Gauche-> droite de Haut->bas */
Affiche_1_Parametre( frame, -1, wxEmptyString, wxT( "1" ), CYAN );
// Reservation memoire pour stockahe de 1 ligne ou une colonne de cellules
nn = MAX( Nrows, Ncols ) * sizeof(*pt_cell_V);
pt_cell_V = (long*) MyMalloc( nn );
memset( pt_cell_V, 0, nn );
for( row = 0; row < Nrows; row++ )
{
old_cell_H = 0;
for( col = 0; col < Ncols; col++ )
{
current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
if( current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[col] & CELL_is_ZONE) )
{
OrCell( row, col, BOTTOM, CELL_is_ZONE );
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[col] = old_cell_H = current_cell;
}
}
/* balayage Droite-> gauche de Haut->bas */
Affiche_1_Parametre( frame, -1, wxEmptyString, wxT( "2" ), CYAN );
memset( pt_cell_V, 0, nn );
for( row = 0; row < Nrows; row++ )
{
old_cell_H = 0;
for( col = Ncols - 1; col >= 0; col-- )
{
current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
if( current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[col] & CELL_is_ZONE) )
{
OrCell( row, col, BOTTOM, CELL_is_ZONE );
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[col] = old_cell_H = current_cell;
}
}
/* balayage Bas->Haut de Droite->gauche */
Affiche_1_Parametre( frame, -1, wxEmptyString, wxT( "3" ), CYAN );
memset( pt_cell_V, 0, nn );
for( col = Ncols - 1; col >= 0; col-- )
{
old_cell_H = 0;
for( row = Nrows - 1; row >= 0; row-- )
{
current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
if( current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[row] & CELL_is_ZONE) )
{
OrCell( row, col, BOTTOM, CELL_is_ZONE );
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[row] = old_cell_H = current_cell;
}
}
/* balayage Bas->Haut de Gauche->Droite*/
Affiche_1_Parametre( frame, -1, wxEmptyString, wxT( "4" ), CYAN );
memset( pt_cell_V, 0, nn );
for( col = 0; col < Ncols; col++ )
{
old_cell_H = 0;
for( row = Nrows - 1; row >= 0; row-- )
{
current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
if( current_cell == 0 ) /* une cellule libre a ete trouvee */
{
if( (old_cell_H & CELL_is_ZONE)
|| (pt_cell_V[row] & CELL_is_ZONE) )
{
OrCell( row, col, BOTTOM, CELL_is_ZONE );
current_cell = CELL_is_ZONE;
nbpoints++;
}
}
pt_cell_V[row] = old_cell_H = current_cell;
}
}
MyFree( pt_cell_V );
return nbpoints;
}
/*****************************************************************************/
static bool Genere_Pad_Connexion(WinEDA_PcbFrame *frame, wxDC * DC, int layer)
static bool Genere_Pad_Connexion( WinEDA_PcbFrame* frame, wxDC* DC, int layer )
/*****************************************************************************/
/* Generation des segments de zone de connexion zone / pad pour constitution
de freins thermiques
*/
* de freins thermiques
*/
{
int ii, jj, Npads;
D_PAD * pt_pad;
LISTE_PAD * pt_liste_pad;
TRACK * pt_track, * loctrack;
int angle;
int cX, cY, dx, dy;
int sommet[4][2];
wxString msg;
if( frame->m_Pcb->m_Zone == NULL ) return FALSE; /* pas de zone */
if( frame->m_Pcb->m_Zone->m_TimeStamp != s_TimeStamp ) /* c'est une autre zone */
return FALSE;
/* Calcul du nombre de pads a traiter et affichage */
Affiche_1_Parametre(frame, 50, wxT("NPads"),wxT(" "),CYAN);
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
for ( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++)
{
pt_pad = *pt_liste_pad;
/* la pastille doit etre du meme net */
if(pt_pad->m_NetCode != g_HightLigth_NetCode) continue;
/* la pastille doit exister sur la couche */
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 ) continue;
Npads++;
}
msg.Printf( wxT("%d"), Npads );
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,CYAN);
Affiche_1_Parametre(frame, 57, wxT("Pads"), wxT(" "),CYAN);
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
for ( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++)
{
pt_pad = *pt_liste_pad;
/* la pastille doit etre du meme net */
if(pt_pad->m_NetCode != g_HightLigth_NetCode) continue;
/* la pastille doit exister sur la couche */
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 ) continue;
/* traitement du pad en cours */
Npads++; msg.Printf( wxT("%d"), Npads );
Affiche_1_Parametre(frame, -1, wxEmptyString,msg,CYAN);
cX = pt_pad->m_Pos.x; cY = pt_pad->m_Pos.y;
dx = pt_pad->m_Size.x / 2;
dy = pt_pad->m_Size.y / 2;
dx += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
dy += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
if(pt_pad->m_PadShape == TRAPEZE)
{
dx += abs(pt_pad->m_DeltaSize.y) / 2;
dy += abs(pt_pad->m_DeltaSize.x) / 2;
}
/* calcul des coord des 4 segments a rajouter a partir du centre cX,cY */
sommet[0][0] = 0; sommet[0][1] = -dy;
sommet[1][0] = -dx; sommet[1][1] = 0;
sommet[2][0] = 0; sommet[2][1] = dy;
sommet[3][0] = dx; sommet[3][1] = 0;
angle = pt_pad->m_Orient;
for(jj = 0; jj < 4; jj++)
{
RotatePoint(&sommet[jj][0], &sommet[jj][1], angle);
pt_track = new SEGZONE(frame->m_Pcb);
pt_track->m_Layer = layer;
pt_track->m_Width = g_DesignSettings.m_CurrentTrackWidth;
pt_track->m_NetCode = g_HightLigth_NetCode;
pt_track->start = pt_pad;
pt_track->m_Start.x = cX; pt_track->m_Start.y = cY;
pt_track->m_End.x = cX + sommet[jj][0];
pt_track->m_End.y = cY + sommet[jj][1];
pt_track->m_TimeStamp = s_TimeStamp;
/* tst si trace possible */
if( Drc(frame, DC, pt_track,frame->m_Pcb->m_Track,0) == BAD_DRC )
{
delete pt_track; continue;
}
/* on doit pouvoir se connecter sur la zone */
loctrack = Locate_Zone(frame->m_Pcb->m_Zone,pt_track->m_End, layer);
if( (loctrack == NULL) || (loctrack->m_TimeStamp != s_TimeStamp) )
{
delete pt_track; continue;
}
pt_track->Insert(frame->m_Pcb, NULL);
pt_track->Draw(frame->DrawPanel, DC, GR_OR);
}
}
return TRUE;
int ii, jj, Npads;
D_PAD* pt_pad;
LISTE_PAD* pt_liste_pad;
TRACK* pt_track, * loctrack;
int angle;
int cX, cY, dx, dy;
int sommet[4][2];
wxString msg;
if( frame->m_Pcb->m_Zone == NULL )
return FALSE; /* pas de zone */
if( frame->m_Pcb->m_Zone->m_TimeStamp != s_TimeStamp ) /* c'est une autre zone */
return FALSE;
/* Calcul du nombre de pads a traiter et affichage */
Affiche_1_Parametre( frame, 50, wxT( "NPads" ), wxT( " " ), CYAN );
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
for( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++ )
{
pt_pad = *pt_liste_pad;
/* la pastille doit etre du meme net */
if( pt_pad->m_NetCode != g_HightLigth_NetCode )
continue;
/* la pastille doit exister sur la couche */
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 )
continue;
Npads++;
}
msg.Printf( wxT( "%d" ), Npads );
Affiche_1_Parametre( frame, -1, wxEmptyString, msg, CYAN );
Affiche_1_Parametre( frame, 57, wxT( "Pads" ), wxT( " " ), CYAN );
pt_liste_pad = (LISTE_PAD*) frame->m_Pcb->m_Pads;
for( ii = 0, Npads = 0; ii < frame->m_Pcb->m_NbPads; ii++, pt_liste_pad++ )
{
pt_pad = *pt_liste_pad;
/* la pastille doit etre du meme net */
if( pt_pad->m_NetCode != g_HightLigth_NetCode )
continue;
/* la pastille doit exister sur la couche */
if( (pt_pad->m_Masque_Layer & g_TabOneLayerMask[layer]) == 0 )
continue;
/* traitement du pad en cours */
Npads++; msg.Printf( wxT( "%d" ), Npads );
Affiche_1_Parametre( frame, -1, wxEmptyString, msg, CYAN );
cX = pt_pad->m_Pos.x; cY = pt_pad->m_Pos.y;
dx = pt_pad->m_Size.x / 2;
dy = pt_pad->m_Size.y / 2;
dx += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
dy += g_DesignSettings.m_TrackClearence + g_GridRoutingSize;
if( pt_pad->m_PadShape == TRAPEZE )
{
dx += abs( pt_pad->m_DeltaSize.y ) / 2;
dy += abs( pt_pad->m_DeltaSize.x ) / 2;
}
/* calcul des coord des 4 segments a rajouter a partir du centre cX,cY */
sommet[0][0] = 0; sommet[0][1] = -dy;
sommet[1][0] = -dx; sommet[1][1] = 0;
sommet[2][0] = 0; sommet[2][1] = dy;
sommet[3][0] = dx; sommet[3][1] = 0;
angle = pt_pad->m_Orient;
for( jj = 0; jj < 4; jj++ )
{
RotatePoint( &sommet[jj][0], &sommet[jj][1], angle );
pt_track = new SEGZONE( frame->m_Pcb );
pt_track->m_Layer = layer;
pt_track->m_Width = g_DesignSettings.m_CurrentTrackWidth;
pt_track->m_NetCode = g_HightLigth_NetCode;
pt_track->start = pt_pad;
pt_track->m_Start.x = cX; pt_track->m_Start.y = cY;
pt_track->m_End.x = cX + sommet[jj][0];
pt_track->m_End.y = cY + sommet[jj][1];
pt_track->m_TimeStamp = s_TimeStamp;
/* tst si trace possible */
if( Drc( frame, DC, pt_track, frame->m_Pcb->m_Track, 0 ) == BAD_DRC )
{
delete pt_track; continue;
}
/* on doit pouvoir se connecter sur la zone */
loctrack = Locate_Zone( frame->m_Pcb->m_Zone, pt_track->m_End, layer );
if( (loctrack == NULL) || (loctrack->m_TimeStamp != s_TimeStamp) )
{
delete pt_track; continue;
}
pt_track->Insert( frame->m_Pcb, NULL );
pt_track->Draw( frame->DrawPanel, DC, GR_OR );
}
}
return TRUE;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment