2007-06-05 12:10:51 +00:00
|
|
|
|
/****************************************/
|
|
|
|
|
/**** Routine de trace GERBER RS274X ****/
|
|
|
|
|
/****************************************/
|
|
|
|
|
|
|
|
|
|
#include "fctsys.h"
|
|
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "plot_common.h"
|
|
|
|
|
#include "pcbnew.h"
|
|
|
|
|
#include "pcbplot.h"
|
|
|
|
|
#include "trigo.h"
|
|
|
|
|
#include "plotgerb.h"
|
|
|
|
|
|
|
|
|
|
#include "protos.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Variables locales : */
|
|
|
|
|
static int s_Last_D_code ;
|
|
|
|
|
static float Gerb_scale_plot; /*Coeff de conversion d'unites des traces */
|
|
|
|
|
static int scale_spot_mini; /* Ouverture mini (pour remplissages) */
|
|
|
|
|
static D_CODE * s_DCodeList; /* Pointeur sur la zone de stockage des D_CODES */
|
|
|
|
|
wxString GerberFullFileName;
|
|
|
|
|
static double scale_x , scale_y ; /* echelles de convertion en X et Y (compte tenu
|
|
|
|
|
des unites relatives du PCB et des traceurs*/
|
|
|
|
|
static bool ShowDcodeError = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Routines Locales */
|
|
|
|
|
|
|
|
|
|
static void Init_Trace_GERBER(WinEDA_BasePcbFrame * frame, FILE * gerbfile);
|
|
|
|
|
static void Init_ApertureList(void);
|
|
|
|
|
static void Fin_Trace_GERBER(WinEDA_BasePcbFrame * frame, FILE * gerbfile);
|
|
|
|
|
static void Plot_1_CIRCLE_pad_GERBER(wxPoint pos,int diametre) ;
|
|
|
|
|
static void trace_1_pastille_OVALE_GERBER(wxPoint pos, wxSize size,int orient);
|
|
|
|
|
static void PlotRectangularPad_GERBER(wxPoint pos, wxSize size, int orient);
|
|
|
|
|
|
|
|
|
|
static D_CODE * get_D_code(int dx,int dy, int type, int drill ) ;
|
|
|
|
|
static void trace_1_pad_TRAPEZE_GERBER(wxPoint pos, wxSize size,wxSize delta,
|
|
|
|
|
int orient,int modetrace);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************************/
|
|
|
|
|
void WinEDA_BasePcbFrame::Genere_GERBER(const wxString & FullFileName, int Layer,
|
|
|
|
|
bool PlotOriginIsAuxAxis)
|
|
|
|
|
/********************************************************************************/
|
|
|
|
|
/* Genere les divers fichiers de trace:
|
|
|
|
|
Pour chaque couche 1 fichier xxxc.PHO au format RS274X
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int tracevia = 1;
|
|
|
|
|
|
|
|
|
|
EraseMsgBox();
|
|
|
|
|
GerberFullFileName = FullFileName;
|
|
|
|
|
|
|
|
|
|
g_PlotOrient = 0;
|
|
|
|
|
if (Plot_Set_MIROIR) g_PlotOrient |= PLOT_MIROIR;
|
|
|
|
|
|
|
|
|
|
/* Calcul des echelles de conversion */
|
|
|
|
|
Gerb_scale_plot = 1.0; /* pour unites gerber en 0,1 Mils, format 3.4 */
|
|
|
|
|
scale_spot_mini = (int)(spot_mini * 10 * Gerb_scale_plot);
|
|
|
|
|
scale_x = Scale_X * Gerb_scale_plot;
|
|
|
|
|
scale_y = Scale_Y * Gerb_scale_plot;
|
|
|
|
|
g_PlotOffset.x = 0;
|
|
|
|
|
g_PlotOffset.y = 0;
|
|
|
|
|
if ( PlotOriginIsAuxAxis )
|
|
|
|
|
{
|
|
|
|
|
g_PlotOffset = m_Auxiliary_Axis_Position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dest = wxFopen(FullFileName, wxT("wt"));
|
|
|
|
|
if (dest == NULL)
|
|
|
|
|
{
|
|
|
|
|
wxString msg = _("unable to create file ") + FullFileName;
|
|
|
|
|
DisplayError(this, msg); return ;
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-13 15:35:40 +00:00
|
|
|
|
setlocale(LC_NUMERIC, "C");
|
|
|
|
|
|
|
|
|
|
InitPlotParametresGERBER(g_PlotOffset, scale_x, scale_y);
|
|
|
|
|
|
|
|
|
|
/* Clear the memory used for handle the D_CODE (aperture) list */
|
|
|
|
|
Init_ApertureList();
|
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
Affiche_1_Parametre(this, 0, _("File"),FullFileName,CYAN) ;
|
|
|
|
|
|
|
|
|
|
Init_Trace_GERBER(this, dest) ;
|
|
|
|
|
|
|
|
|
|
nb_plot_erreur = 0 ;
|
|
|
|
|
|
|
|
|
|
int layer_mask = g_TabOneLayerMask[Layer];
|
|
|
|
|
switch(Layer)
|
|
|
|
|
{
|
|
|
|
|
case CUIVRE_N :
|
|
|
|
|
case LAYER_N_2 :
|
|
|
|
|
case LAYER_N_3 :
|
|
|
|
|
case LAYER_N_4 :
|
|
|
|
|
case LAYER_N_5 :
|
|
|
|
|
case LAYER_N_6 :
|
|
|
|
|
case LAYER_N_7 :
|
|
|
|
|
case LAYER_N_8 :
|
|
|
|
|
case LAYER_N_9 :
|
|
|
|
|
case LAYER_N_10 :
|
|
|
|
|
case LAYER_N_11:
|
|
|
|
|
case LAYER_N_12:
|
|
|
|
|
case LAYER_N_13 :
|
|
|
|
|
case LAYER_N_14 :
|
|
|
|
|
case LAYER_N_15 :
|
|
|
|
|
case CMP_N :
|
|
|
|
|
Plot_Layer_GERBER(dest,layer_mask, 0, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SOLDERMASK_N_CU :
|
|
|
|
|
case SOLDERMASK_N_CMP : /* Trace du vernis epargne */
|
|
|
|
|
if ( g_DrawViaOnMaskLayer ) tracevia = 1;
|
|
|
|
|
else tracevia = 0;
|
|
|
|
|
Plot_Layer_GERBER(dest, layer_mask, g_DesignSettings.m_MaskMargin, tracevia);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SOLDERPASTE_N_CU :
|
|
|
|
|
case SOLDERPASTE_N_CMP : /* Trace du masque de pate de soudure */
|
|
|
|
|
Plot_Layer_GERBER(dest, layer_mask, 0, 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
Plot_Serigraphie(PLOT_FORMAT_GERBER,dest, layer_mask);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Fin_Trace_GERBER(this, dest) ;
|
2007-06-13 15:35:40 +00:00
|
|
|
|
setlocale(LC_NUMERIC, "");
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
|
void WinEDA_BasePcbFrame::Plot_Layer_GERBER(FILE * File,int masque_layer,
|
|
|
|
|
int garde, int tracevia)
|
|
|
|
|
/***********************************************************************/
|
|
|
|
|
/* Trace en format GERBER. d'une couche cuivre ou masque
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
wxPoint pos;
|
|
|
|
|
wxSize size;
|
|
|
|
|
MODULE * Module;
|
|
|
|
|
D_PAD * PtPad;
|
|
|
|
|
TRACK * track ;
|
|
|
|
|
EDA_BaseStruct * PtStruct;
|
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
|
|
masque_layer |= EDGE_LAYER; /* Les elements de la couche EDGE sont tj traces */
|
|
|
|
|
|
|
|
|
|
/* trace des elements type Drawings Pcb : */
|
|
|
|
|
PtStruct = m_Pcb->m_Drawings;
|
|
|
|
|
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
|
|
|
|
|
{
|
|
|
|
|
switch( PtStruct->m_StructType )
|
|
|
|
|
{
|
|
|
|
|
case TYPEDRAWSEGMENT:
|
|
|
|
|
PlotDrawSegment( (DRAWSEGMENT*) PtStruct, PLOT_FORMAT_GERBER,
|
|
|
|
|
masque_layer);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPETEXTE:
|
|
|
|
|
PlotTextePcb((TEXTE_PCB*) PtStruct,PLOT_FORMAT_GERBER,
|
|
|
|
|
masque_layer);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPECOTATION:
|
|
|
|
|
PlotCotation((COTATION*) PtStruct, PLOT_FORMAT_GERBER,
|
|
|
|
|
masque_layer);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPEMIRE:
|
|
|
|
|
PlotMirePcb((MIREPCB*) PtStruct, PLOT_FORMAT_GERBER,
|
|
|
|
|
masque_layer);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TYPEMARQUEUR:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
DisplayError(this, wxT("Type Draw non gere"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Trace des Elements des modules autres que pads */
|
|
|
|
|
nb_items = 0 ;
|
|
|
|
|
Affiche_1_Parametre(this, 38, wxT("DrawMod"), wxEmptyString,GREEN) ;
|
|
|
|
|
Module = m_Pcb->m_Modules;
|
|
|
|
|
for( ; Module != NULL ;Module = (MODULE *)Module->Pnext )
|
|
|
|
|
{
|
|
|
|
|
PtStruct = Module->m_Drawings;
|
|
|
|
|
for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
|
|
|
|
|
{
|
|
|
|
|
switch( PtStruct->m_StructType )
|
|
|
|
|
{
|
|
|
|
|
case TYPEEDGEMODULE:
|
2007-08-23 04:28:46 +00:00
|
|
|
|
if( masque_layer & g_TabOneLayerMask[((EDGE_MODULE*)PtStruct)->GetLayer()] )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
Plot_1_EdgeModule(PLOT_FORMAT_GERBER, (EDGE_MODULE*) PtStruct);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Trace des Elements des modules : Pastilles */
|
|
|
|
|
nb_items = 0 ;
|
|
|
|
|
Affiche_1_Parametre(this, 48, wxT("Pads"),wxEmptyString,GREEN) ;
|
|
|
|
|
Module = m_Pcb->m_Modules;
|
|
|
|
|
for( ; Module != NULL ;Module = (MODULE *)Module->Pnext )
|
|
|
|
|
{
|
|
|
|
|
PtPad = (D_PAD*) Module->m_Pads;
|
|
|
|
|
for ( ; PtPad != NULL ; PtPad = (D_PAD*)PtPad->Pnext )
|
|
|
|
|
{
|
|
|
|
|
wxPoint shape_pos;
|
|
|
|
|
if( (PtPad->m_Masque_Layer & masque_layer) == 0)
|
|
|
|
|
continue ;
|
|
|
|
|
shape_pos = PtPad->ReturnShapePos();
|
|
|
|
|
pos = shape_pos;
|
|
|
|
|
|
|
|
|
|
size.x = PtPad->m_Size.x + (garde * 2) ;
|
|
|
|
|
size.y = PtPad->m_Size.y + (garde * 2) ;
|
|
|
|
|
|
|
|
|
|
/* Don't draw a null size item : */
|
|
|
|
|
if ( (size.x == 0) || (size.y == 0) ) continue;
|
|
|
|
|
|
|
|
|
|
nb_items++ ;
|
|
|
|
|
|
|
|
|
|
switch (PtPad->m_PadShape)
|
|
|
|
|
{
|
|
|
|
|
case CIRCLE :
|
|
|
|
|
Plot_1_CIRCLE_pad_GERBER(pos,size.x) ;
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
|
|
case OVALE :
|
|
|
|
|
{
|
|
|
|
|
trace_1_pastille_OVALE_GERBER(pos, size,PtPad->m_Orient);
|
|
|
|
|
break ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TRAPEZE :
|
|
|
|
|
{
|
|
|
|
|
wxSize delta = PtPad->m_DeltaSize;
|
|
|
|
|
trace_1_pad_TRAPEZE_GERBER(pos,size,
|
|
|
|
|
delta, PtPad->m_Orient, FILLED) ;
|
|
|
|
|
break ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case RECT:
|
|
|
|
|
default:
|
|
|
|
|
PlotRectangularPad_GERBER(pos,size, PtPad->m_Orient) ;
|
|
|
|
|
break ;
|
|
|
|
|
}
|
|
|
|
|
msg.Printf( wxT("%d"),nb_items) ;
|
|
|
|
|
Affiche_1_Parametre(this, 48,wxEmptyString, msg,GREEN) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* trace des VIAS : */
|
|
|
|
|
if(tracevia)
|
|
|
|
|
{
|
|
|
|
|
nb_items = 0 ;
|
|
|
|
|
Affiche_1_Parametre(this, 56, wxT("Vias"), wxEmptyString,RED) ;
|
|
|
|
|
for( track = m_Pcb->m_Track; track != NULL; track = (TRACK*) track->Pnext)
|
|
|
|
|
{
|
|
|
|
|
if( track->m_StructType != TYPEVIA ) continue;
|
|
|
|
|
SEGVIA * Via = (SEGVIA *) track;
|
|
|
|
|
/* vias not plotted if not on selected layer, but if layer
|
|
|
|
|
== SOLDERMASK_LAYER_CU or SOLDERMASK_LAYER_CMP, vias are drawn ,
|
|
|
|
|
if they are on a external copper layer
|
|
|
|
|
*/
|
|
|
|
|
int via_mask_layer = Via->ReturnMaskLayer();
|
|
|
|
|
if ( (via_mask_layer & CUIVRE_LAYER ) ) via_mask_layer |= SOLDERMASK_LAYER_CU;
|
|
|
|
|
if ( (via_mask_layer & CMP_LAYER ) ) via_mask_layer |= SOLDERMASK_LAYER_CMP;
|
|
|
|
|
if( (via_mask_layer & masque_layer) == 0 ) continue;
|
|
|
|
|
|
|
|
|
|
pos = Via->m_Start;
|
|
|
|
|
size.x = size.y = Via->m_Width + (garde * 2);
|
|
|
|
|
Plot_1_CIRCLE_pad_GERBER(pos,size.x) ;
|
|
|
|
|
nb_items++ ; msg.Printf( wxT("%d"),nb_items) ;
|
|
|
|
|
Affiche_1_Parametre(this, 56,wxEmptyString, msg,RED) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* trace des pistes : */
|
|
|
|
|
nb_items = 0 ;
|
|
|
|
|
Affiche_1_Parametre(this, 64, wxT("Tracks"),wxEmptyString,YELLOW) ;
|
|
|
|
|
|
|
|
|
|
for( track = m_Pcb->m_Track; track != NULL; track = (TRACK*) track->Pnext)
|
|
|
|
|
{
|
|
|
|
|
wxPoint end;
|
|
|
|
|
|
|
|
|
|
if ( track->m_StructType == TYPEVIA ) continue ;
|
2007-08-23 04:28:46 +00:00
|
|
|
|
if( (g_TabOneLayerMask[track->GetLayer()] & masque_layer) == 0 ) continue;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
size.x = size.y = track->m_Width;
|
|
|
|
|
pos = track->m_Start; end = track->m_End;
|
|
|
|
|
|
|
|
|
|
PlotGERBERLine(pos,end, size.x) ;
|
|
|
|
|
|
|
|
|
|
nb_items++ ; msg.Printf( wxT("%d"),nb_items) ;
|
|
|
|
|
Affiche_1_Parametre(this, 64, wxEmptyString, msg,YELLOW) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* trace des zones: */
|
|
|
|
|
nb_items = 0 ;
|
|
|
|
|
if ( m_Pcb->m_Zone ) Affiche_1_Parametre(this, 72, wxT("Zones "),wxEmptyString,YELLOW) ;
|
|
|
|
|
|
|
|
|
|
for( track = m_Pcb->m_Zone; track != NULL; track = (TRACK*) track->Pnext)
|
|
|
|
|
{
|
|
|
|
|
wxPoint end;
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
if( (g_TabOneLayerMask[track->GetLayer()] & masque_layer) == 0 ) continue;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
size.x = size.y = track->m_Width;
|
|
|
|
|
pos = track->m_Start; end = track->m_End;
|
|
|
|
|
|
|
|
|
|
PlotGERBERLine(pos,end, size.x) ;
|
|
|
|
|
|
|
|
|
|
nb_items++ ; msg.Printf( wxT("%d"),nb_items) ;
|
|
|
|
|
Affiche_1_Parametre(this, 72, wxEmptyString,msg,YELLOW) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************/
|
|
|
|
|
void trace_1_pastille_OVALE_GERBER(wxPoint pos, wxSize size, int orient)
|
|
|
|
|
/**********************************************************************/
|
|
|
|
|
/* Trace 1 pastille OVALE en position pos_X,Y:
|
|
|
|
|
dimensions dx,dy,
|
|
|
|
|
orientation orient
|
|
|
|
|
Pour une orientation verticale ou horizontale, la forme est flashee
|
|
|
|
|
Pour une orientation quelconque la forme est tracee comme un segment
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * dcode_ptr;
|
|
|
|
|
int x0, y0, x1, y1, delta;
|
|
|
|
|
|
|
|
|
|
if( (orient == 900) || (orient == 2700)) /* orient tournee de 90 deg */
|
|
|
|
|
{
|
|
|
|
|
EXCHG(size.x,size.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Trace de la forme flashee */
|
|
|
|
|
if( (orient == 0) || (orient == 900) ||
|
|
|
|
|
(orient == 1800) || (orient == 2700) )
|
|
|
|
|
{
|
|
|
|
|
UserToDeviceCoordinate(pos) ;
|
|
|
|
|
UserToDeviceSize(size);
|
|
|
|
|
|
|
|
|
|
dcode_ptr = get_D_code(size.x,size.y,GERB_OVALE,0) ;
|
|
|
|
|
if (dcode_ptr->m_NumDcode != s_Last_D_code )
|
|
|
|
|
{
|
|
|
|
|
sprintf(cbuf,"G54D%d*\n",dcode_ptr->m_NumDcode) ;
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
s_Last_D_code = dcode_ptr->m_NumDcode;
|
|
|
|
|
}
|
|
|
|
|
sprintf(cbuf,"X%5.5dY%5.5dD03*\n", pos.x, pos.y);
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else /* Forme tracee comme un segment */
|
|
|
|
|
{
|
|
|
|
|
if(size.x > size.y )
|
|
|
|
|
{
|
|
|
|
|
EXCHG(size.x,size.y); orient += 900;
|
|
|
|
|
}
|
|
|
|
|
/* la pastille est ramenee a une pastille ovale avec dy > dx */
|
|
|
|
|
delta = size.y - size.x;
|
|
|
|
|
x0 = 0; y0 = -delta / 2;
|
|
|
|
|
x1 = 0; y1 = delta / 2;
|
|
|
|
|
RotatePoint(&x0,&y0, orient);
|
|
|
|
|
RotatePoint(&x1,&y1, orient);
|
|
|
|
|
PlotGERBERLine( wxPoint(pos.x + x0, pos.y + y0),
|
|
|
|
|
wxPoint(pos.x + x1, pos.y + y1), size.x);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
void Plot_1_CIRCLE_pad_GERBER(wxPoint pos,int diametre)
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
/* Plot a circulat pad or via at the user position pos
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * dcode_ptr;
|
|
|
|
|
wxSize size(diametre, diametre);
|
|
|
|
|
|
|
|
|
|
UserToDeviceCoordinate(pos);
|
|
|
|
|
UserToDeviceSize(size);
|
|
|
|
|
|
|
|
|
|
dcode_ptr = get_D_code(size.x,size.x,GERB_CIRCLE,0) ;
|
|
|
|
|
if (dcode_ptr->m_NumDcode != s_Last_D_code )
|
|
|
|
|
{
|
|
|
|
|
sprintf(cbuf,"G54D%d*\n", dcode_ptr->m_NumDcode) ;
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
s_Last_D_code = dcode_ptr->m_NumDcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sprintf(cbuf,"X%5.5dY%5.5dD03*\n", pos.x, pos.y);
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
void PlotRectangularPad_GERBER(wxPoint pos, wxSize size, int orient)
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/*
|
|
|
|
|
Trace 1 pad rectangulaire d'orientation quelconque
|
|
|
|
|
donne par son centre, ses dimensions, et son orientation
|
|
|
|
|
Pour une orientation verticale ou horizontale, la forme est flashee
|
|
|
|
|
Pour une orientation quelconque la forme est tracee par 4 segments
|
|
|
|
|
de largeur 1/2 largeur pad
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * dcode_ptr;
|
|
|
|
|
|
|
|
|
|
/* Trace de la forme flashee */
|
|
|
|
|
switch (orient)
|
|
|
|
|
{
|
|
|
|
|
case 900 :
|
|
|
|
|
case 2700 : /* la rotation de 90 ou 270 degres revient a permutter des dimensions */
|
|
|
|
|
EXCHG(size.x,size.y);
|
|
|
|
|
case 1800 :
|
|
|
|
|
case 0 :
|
|
|
|
|
UserToDeviceCoordinate(pos) ;
|
|
|
|
|
UserToDeviceSize(size);
|
|
|
|
|
|
|
|
|
|
dcode_ptr = get_D_code(size.x,size.y,GERB_RECT,0) ;
|
|
|
|
|
if (dcode_ptr->m_NumDcode != s_Last_D_code )
|
|
|
|
|
{
|
|
|
|
|
sprintf(cbuf,"G54D%d*\n", dcode_ptr->m_NumDcode) ;
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
s_Last_D_code = dcode_ptr->m_NumDcode;
|
|
|
|
|
}
|
|
|
|
|
sprintf(cbuf,"X%5.5dY%5.5dD03*\n", pos.x, pos.y);
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: /* Forme tracee par remplissage */
|
|
|
|
|
trace_1_pad_TRAPEZE_GERBER(pos, size, wxSize(0, 0), orient,FILLED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
void trace_1_contour_GERBER(wxPoint pos, wxSize size, wxSize delta,
|
|
|
|
|
int penwidth, int orient)
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
/*
|
|
|
|
|
Trace 1 contour rectangulaire ou trapezoidal d'orientation quelconque
|
|
|
|
|
donne par son centre,
|
|
|
|
|
ses dimensions ,
|
|
|
|
|
ses variations ,
|
|
|
|
|
l'epaisseur du trait,
|
|
|
|
|
et son orientation orient
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int ii;
|
|
|
|
|
wxPoint coord[4];
|
|
|
|
|
|
|
|
|
|
size.x /= 2; size.y /= 2 ;
|
|
|
|
|
delta.x /= 2; delta.y /= 2 ; /* demi dim dx et dy */
|
|
|
|
|
|
|
|
|
|
coord[0].x = pos.x - size.x - delta.y;
|
|
|
|
|
coord[0].y = pos.y + size.y + delta.x;
|
|
|
|
|
|
|
|
|
|
coord[1].x = pos.x - size.x + delta.y;
|
|
|
|
|
coord[1].y = pos.y - size.y - delta.x;
|
|
|
|
|
|
|
|
|
|
coord[2].x = pos.x + size.x - delta.y;
|
|
|
|
|
coord[2].y = pos.y - size.y + delta.x;
|
|
|
|
|
|
|
|
|
|
coord[3].x = pos.x + size.x + delta.y;
|
|
|
|
|
coord[3].y = pos.y + size.y - delta.x;
|
|
|
|
|
|
|
|
|
|
for (ii = 0; ii < 4; ii++)
|
|
|
|
|
{
|
|
|
|
|
RotatePoint(&coord[ii].x, &coord[ii].y, pos.x, pos.y, orient);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PlotGERBERLine( coord[0], coord[1], penwidth);
|
|
|
|
|
PlotGERBERLine( coord[1], coord[2], penwidth);
|
|
|
|
|
PlotGERBERLine( coord[2], coord[3], penwidth);
|
|
|
|
|
PlotGERBERLine( coord[3], coord[0], penwidth);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************/
|
|
|
|
|
void trace_1_pad_TRAPEZE_GERBER(wxPoint pos, wxSize size,wxSize delta,
|
|
|
|
|
int orient,int modetrace)
|
|
|
|
|
/*******************************************************************/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Trace 1 pad trapezoidal donne par :
|
|
|
|
|
son centre pos.x,pos.y
|
|
|
|
|
ses dimensions size.x et size.y
|
|
|
|
|
les variations delta.x et delta.y ( 1 des deux au moins doit etre nulle)
|
|
|
|
|
son orientation orient en 0.1 degres
|
|
|
|
|
le mode de trace (FILLED, SKETCH, FILAIRE)
|
|
|
|
|
|
|
|
|
|
Le trace n'est fait que pour un trapeze, c.a.d que delta.x ou delta.y
|
|
|
|
|
= 0.
|
|
|
|
|
|
|
|
|
|
les notation des sommets sont ( vis a vis de la table tracante )
|
|
|
|
|
|
|
|
|
|
" 0 ------------- 3 "
|
|
|
|
|
" . . "
|
|
|
|
|
" . O . "
|
|
|
|
|
" . . "
|
|
|
|
|
" 1 ---- 2 "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exemple de Disposition pour delta.y > 0, delta.x = 0
|
|
|
|
|
" 1 ---- 2 "
|
|
|
|
|
" . . "
|
|
|
|
|
" . O . "
|
|
|
|
|
" . . "
|
|
|
|
|
" 0 ------------- 3 "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exemple de Disposition pour delta.y = 0, delta.x > 0
|
|
|
|
|
" 0 "
|
|
|
|
|
" . . "
|
|
|
|
|
" . . "
|
|
|
|
|
" . 3 "
|
|
|
|
|
" . . "
|
|
|
|
|
" . O . "
|
|
|
|
|
" . . "
|
|
|
|
|
" . 2 "
|
|
|
|
|
" . . "
|
|
|
|
|
" . . "
|
|
|
|
|
" 1 "
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int ii , jj;
|
|
|
|
|
int dx,dy;
|
|
|
|
|
wxPoint polygone[4]; /* coord sommets */
|
|
|
|
|
int coord[8];
|
|
|
|
|
int ddx, ddy ;
|
|
|
|
|
|
|
|
|
|
/* calcul des dimensions optimales du spot choisi = 1/4 plus petite dim */
|
|
|
|
|
dx = size.x - abs(delta.y);
|
|
|
|
|
dy = size.y - abs(delta.x);
|
|
|
|
|
|
|
|
|
|
dx = size.x / 2; dy = size.y / 2 ;
|
|
|
|
|
ddx = delta.x / 2; ddy = delta.y / 2 ;
|
|
|
|
|
|
|
|
|
|
polygone[0].x = - dx - ddy; polygone[0].y = + dy + ddx;
|
|
|
|
|
polygone[1].x = - dx + ddy; polygone[1].y = - dy - ddx;
|
|
|
|
|
polygone[2].x = + dx - ddy; polygone[2].y = - dy + ddx;
|
|
|
|
|
polygone[3].x = + dx + ddy; polygone[3].y = + dy - ddx;
|
|
|
|
|
|
|
|
|
|
/* Dessin du polygone et Remplissage eventuel de l'interieur */
|
|
|
|
|
|
|
|
|
|
for (ii = 0, jj = 0; ii < 4; ii++)
|
|
|
|
|
{
|
|
|
|
|
RotatePoint(&polygone[ii].x, &polygone[ii].y, orient);
|
|
|
|
|
coord[jj] = polygone[ii].x += pos.x;
|
|
|
|
|
jj++;
|
|
|
|
|
coord[jj] = polygone[ii].y += pos.y;
|
|
|
|
|
jj++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(modetrace != FILLED )
|
|
|
|
|
{
|
|
|
|
|
PlotGERBERLine( polygone[0], polygone[1], scale_spot_mini);
|
|
|
|
|
PlotGERBERLine( polygone[1], polygone[2], scale_spot_mini);
|
|
|
|
|
PlotGERBERLine( polygone[2], polygone[3], scale_spot_mini);
|
|
|
|
|
PlotGERBERLine( polygone[3], polygone[0], scale_spot_mini);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
PlotPolygon_GERBER(4, coord, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************/
|
|
|
|
|
void PlotGERBERLine(wxPoint start, wxPoint end, int large)
|
|
|
|
|
/**********************************************************/
|
|
|
|
|
/* Trace 1 segment de piste :
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * dcode_ptr;
|
|
|
|
|
|
|
|
|
|
UserToDeviceCoordinate(start);
|
|
|
|
|
UserToDeviceCoordinate(end);
|
|
|
|
|
|
|
|
|
|
dcode_ptr = get_D_code(large,large,GERB_LINE,0) ;
|
|
|
|
|
if (dcode_ptr->m_NumDcode != s_Last_D_code )
|
|
|
|
|
{
|
|
|
|
|
sprintf(cbuf,"G54D%d*\n", dcode_ptr->m_NumDcode) ;
|
|
|
|
|
fputs(cbuf,dest) ;
|
|
|
|
|
s_Last_D_code = dcode_ptr->m_NumDcode;
|
|
|
|
|
}
|
|
|
|
|
sprintf(cbuf,"X%5.5dY%5.5dD02*\n",start.x,start.y) ; fputs(cbuf,dest) ;
|
|
|
|
|
sprintf(cbuf,"X%5.5dY%5.5dD01*\n",end.x,end.y) ; fputs(cbuf,dest) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************************************************/
|
|
|
|
|
void PlotCircle_GERBER( wxPoint centre, int rayon, int epaisseur)
|
|
|
|
|
/********************************************************************/
|
|
|
|
|
/* routine de trace de 1 cercle de centre centre par approximation de segments
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int ii ;
|
|
|
|
|
int ox, oy, fx, fy;
|
|
|
|
|
int delta; /* increment (en 0.1 degres) angulaire pour trace de cercles */
|
|
|
|
|
|
|
|
|
|
delta = 120; /* un cercle sera trace en 3600/delta segments */
|
|
|
|
|
/* Correction pour petits cercles par rapport a l'epaisseur du trait */
|
|
|
|
|
if( rayon < (epaisseur * 10) ) delta = 225; /* 16 segm pour 360 deg */
|
|
|
|
|
if( rayon < (epaisseur * 5) ) delta = 300; /* 12 segm pour 360 deg */
|
|
|
|
|
if( rayon < (epaisseur * 2) ) delta = 600; /* 6 segm pour 360 deg */
|
|
|
|
|
|
|
|
|
|
ox = centre.x + rayon; oy = centre.y;
|
|
|
|
|
for (ii = delta ; ii < 3600 ; ii += delta )
|
|
|
|
|
{
|
|
|
|
|
fx = centre.x + (int)(rayon * fcosinus[ii]);
|
|
|
|
|
fy = centre.y + (int)(rayon * fsinus[ii]);
|
|
|
|
|
PlotGERBERLine(wxPoint(ox,oy), wxPoint(fx,fy), epaisseur) ;
|
|
|
|
|
ox = fx; oy = fy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fx = centre.x + rayon; fy = centre.y;
|
|
|
|
|
PlotGERBERLine(wxPoint(ox,oy), wxPoint(fx,fy), epaisseur) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************/
|
|
|
|
|
void PlotPolygon_GERBER(int nb_segm, int * coord, bool fill)
|
|
|
|
|
/***************************************************************/
|
|
|
|
|
{
|
|
|
|
|
int ii;
|
|
|
|
|
wxPoint pos;
|
|
|
|
|
|
|
|
|
|
fputs("G36*\n", dest);
|
|
|
|
|
pos.x = *coord; coord++;
|
|
|
|
|
pos.y = *coord; coord++;
|
|
|
|
|
UserToDeviceCoordinate(pos);
|
|
|
|
|
fprintf(dest, "X%5.5dY%5.5dD02*\n", pos.x, pos.y );
|
|
|
|
|
for ( ii = 1; ii < nb_segm; ii++ )
|
|
|
|
|
{
|
|
|
|
|
pos.x = *coord; coord++;
|
|
|
|
|
pos.y = *coord; coord++;
|
|
|
|
|
UserToDeviceCoordinate(pos);
|
|
|
|
|
fprintf(dest, "X%5.5dY%5.5dD01*\n", pos.x, pos.y );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fputs("G37*\n", dest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************/
|
|
|
|
|
D_CODE * get_D_code(int dx,int dy, int type, int drill )
|
|
|
|
|
/*******************************************************/
|
|
|
|
|
/*
|
|
|
|
|
Fonction Recherchant et Creant eventuellement la description
|
|
|
|
|
du D_CODE du type et dimensions demandees
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * ptr_tool, * last_dcode_ptr;
|
|
|
|
|
int num_new_D_code = FIRST_DCODE_VALUE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ptr_tool = last_dcode_ptr = s_DCodeList;
|
|
|
|
|
|
|
|
|
|
while(ptr_tool && ptr_tool->m_Type >= 0 )
|
|
|
|
|
{
|
|
|
|
|
if( ( ptr_tool->m_Size.x == dx ) &&
|
|
|
|
|
( ptr_tool->m_Size.y == dy ) &&
|
|
|
|
|
( ptr_tool->m_Type == type ) )
|
|
|
|
|
return(ptr_tool); /* D_code deja existant */
|
|
|
|
|
last_dcode_ptr = ptr_tool;
|
|
|
|
|
ptr_tool = ptr_tool->m_Pnext ;
|
|
|
|
|
num_new_D_code++ ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* At this point, the requested D_CODE does not exist: It will be created */
|
|
|
|
|
if ( ptr_tool == NULL ) /* We must create a new data */
|
|
|
|
|
{
|
|
|
|
|
ptr_tool = new D_CODE();
|
|
|
|
|
ptr_tool->m_NumDcode = num_new_D_code;
|
|
|
|
|
if ( last_dcode_ptr )
|
|
|
|
|
{
|
|
|
|
|
ptr_tool->m_Pback = last_dcode_ptr;
|
|
|
|
|
last_dcode_ptr->m_Pnext = ptr_tool;
|
|
|
|
|
}
|
|
|
|
|
else s_DCodeList = ptr_tool;
|
|
|
|
|
}
|
|
|
|
|
ptr_tool->m_Size.x = dx ;
|
|
|
|
|
ptr_tool->m_Size.y = dy ;
|
|
|
|
|
ptr_tool->m_Type = type ;
|
|
|
|
|
return(ptr_tool);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
void Init_Trace_GERBER(WinEDA_BasePcbFrame * frame, FILE * gerbfile)
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
{
|
|
|
|
|
char Line[1024];
|
|
|
|
|
|
|
|
|
|
s_Last_D_code = 0 ;
|
|
|
|
|
|
|
|
|
|
DateAndTime(Line);
|
|
|
|
|
wxString Title = g_Main_Title + wxT(" ") + GetBuildVersion();
|
|
|
|
|
fprintf(gerbfile,"G04 (Genere par %s) le %s*\n",CONV_TO_UTF8(Title), Line);
|
|
|
|
|
|
|
|
|
|
// Specify linear interpol (G01), unit = INCH (G70), abs format (G90):
|
|
|
|
|
fputs("G01*\nG70*\nG90*\n", gerbfile);
|
|
|
|
|
fputs("%MOIN*%\n", gerbfile); // set unites = INCHES
|
|
|
|
|
|
|
|
|
|
/* Set gerber format to 3.4 */
|
|
|
|
|
strcpy(Line,"G04 Gerber Fmt 3.4, Leading zero omitted, Abs format*\n%FSLAX34Y34*%\n") ;
|
|
|
|
|
|
|
|
|
|
fputs(Line,gerbfile);
|
|
|
|
|
|
|
|
|
|
fputs("G04 APERTURE LIST*\n", gerbfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************/
|
|
|
|
|
static void Init_ApertureList(void)
|
|
|
|
|
/***********************************/
|
|
|
|
|
/* Init the memory to handle the aperture list:
|
|
|
|
|
the member .m_Type is used by get_D_code() to handle the end of list:
|
|
|
|
|
.m_Type < 0 is the first free aperture descr */
|
|
|
|
|
{
|
|
|
|
|
D_CODE * ptr_tool;
|
|
|
|
|
|
|
|
|
|
ptr_tool = s_DCodeList;
|
|
|
|
|
while ( ptr_tool )
|
|
|
|
|
{
|
|
|
|
|
s_DCodeList->m_Type = -1;
|
|
|
|
|
ptr_tool = ptr_tool->m_Pnext ;
|
|
|
|
|
}
|
|
|
|
|
ShowDcodeError = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
void Fin_Trace_GERBER(WinEDA_BasePcbFrame * frame, FILE * gerbfile)
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
{
|
|
|
|
|
char line[1024];
|
|
|
|
|
wxString TmpFileName, msg;
|
|
|
|
|
FILE * outfile;
|
|
|
|
|
|
|
|
|
|
fputs("M02*\n",gerbfile);
|
|
|
|
|
fclose(gerbfile);
|
|
|
|
|
|
|
|
|
|
// Reouverture gerbfile pour ajout des Apertures
|
|
|
|
|
gerbfile = wxFopen(GerberFullFileName, wxT("rt") );
|
|
|
|
|
if (gerbfile == NULL)
|
|
|
|
|
{
|
|
|
|
|
msg.Printf( _("unable to reopen file <%s>"),GerberFullFileName.GetData() ) ;
|
|
|
|
|
DisplayError(frame, msg); return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ouverture tmpfile
|
|
|
|
|
TmpFileName = GerberFullFileName + wxT(".$$$");
|
|
|
|
|
outfile = wxFopen(TmpFileName, wxT("wt") );
|
|
|
|
|
if ( outfile == NULL )
|
|
|
|
|
{
|
|
|
|
|
fclose(gerbfile);
|
|
|
|
|
DisplayError(frame, wxT("Fin_Trace_GERBER(): Can't Open tmp file"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Placement des Apertures en RS274X
|
|
|
|
|
rewind(gerbfile);
|
|
|
|
|
while ( fgets(line, 1024, gerbfile) )
|
|
|
|
|
{
|
|
|
|
|
fputs(line, outfile);
|
|
|
|
|
if ( strcmp(strtok(line, "\n\r"),"G04 APERTURE LIST*") == 0 )
|
|
|
|
|
{
|
|
|
|
|
frame->Gen_D_CODE_File(outfile);
|
|
|
|
|
fputs("G04 APERTURE END LIST*\n", outfile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(outfile);
|
|
|
|
|
fclose(gerbfile);
|
|
|
|
|
wxRemoveFile(GerberFullFileName);
|
|
|
|
|
wxRenameFile(TmpFileName, GerberFullFileName);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************/
|
|
|
|
|
int WinEDA_BasePcbFrame::Gen_D_CODE_File(FILE * penfile)
|
|
|
|
|
/******************************************************/
|
|
|
|
|
/* Genere la liste courante des D_CODES
|
|
|
|
|
Retourne le nombre de D_Codes utilises
|
|
|
|
|
Genere une sequence RS274X
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
D_CODE * ptr_tool;
|
|
|
|
|
int nb_dcodes = 0 ;
|
|
|
|
|
|
|
|
|
|
/* Init : */
|
|
|
|
|
ptr_tool = s_DCodeList;
|
|
|
|
|
|
|
|
|
|
while(ptr_tool && (ptr_tool->m_Type >= 0 ) )
|
|
|
|
|
{
|
|
|
|
|
float fscale = 0.0001; // For 3.4 format
|
|
|
|
|
char * text;
|
|
|
|
|
sprintf(cbuf,"%%ADD%d", ptr_tool->m_NumDcode);
|
|
|
|
|
text = cbuf + strlen(cbuf);
|
|
|
|
|
switch ( ptr_tool->m_Type )
|
|
|
|
|
{
|
|
|
|
|
case 1: // Circle (flash )
|
|
|
|
|
sprintf(text,"C,%f*%%\n", ptr_tool->m_Size.x * fscale);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2: // RECT
|
|
|
|
|
sprintf(text,"R,%fX%f*%%\n", ptr_tool->m_Size.x * fscale,
|
|
|
|
|
ptr_tool->m_Size.y * fscale);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3: // Circle ( lines )
|
|
|
|
|
sprintf(text,"C,%f*%%\n", ptr_tool->m_Size.x * fscale);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 4: // OVALE
|
|
|
|
|
sprintf(text,"O,%fX%f*%%\n", ptr_tool->m_Size.x * fscale,
|
|
|
|
|
ptr_tool->m_Size.y * fscale);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
DisplayError(this, wxT("Gen_D_CODE_File(): Dcode Type err") );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// compensation localisation printf (float x.y g<>n<EFBFBD>r<EFBFBD> x,y)
|
|
|
|
|
to_point ( text + 2 );
|
|
|
|
|
|
|
|
|
|
fputs(cbuf,penfile) ;
|
|
|
|
|
ptr_tool = ptr_tool->m_Pnext; nb_dcodes++ ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(nb_dcodes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|