2007-06-05 12:10:51 +00:00
|
|
|
|
/********************************************************/
|
|
|
|
|
/**** Routine de lecture et visu d'un fichier GERBER ****/
|
|
|
|
|
/********************************************************/
|
|
|
|
|
|
|
|
|
|
#include "fctsys.h"
|
|
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "gerbview.h"
|
|
|
|
|
#include "pcbplot.h"
|
|
|
|
|
|
|
|
|
|
#include "protos.h"
|
|
|
|
|
|
|
|
|
|
#define IsNumber(x) ( ( ((x) >= '0') && ((x) <='9') ) ||\
|
|
|
|
|
((x) == '-') || ((x) == '+') || ((x) == '.'))
|
|
|
|
|
/* Format Gerber : NOTES :
|
|
|
|
|
Fonctions preparatoires:
|
|
|
|
|
Gn =
|
|
|
|
|
G01 interpolation lineaire ( trace de droites )
|
|
|
|
|
G02,G20,G21 Interpolation circulaire , sens trigo < 0
|
|
|
|
|
G03,G30,G31 Interpolation circulaire , sens trigo > 0
|
|
|
|
|
G04 commentaire
|
|
|
|
|
G06 Interpolation parabolique
|
|
|
|
|
G07 Interpolation cubique
|
|
|
|
|
G10 interpolation lineaire ( echelle 10x )
|
|
|
|
|
G11 interpolation lineaire ( echelle 0.1x )
|
|
|
|
|
G12 interpolation lineaire ( echelle 0.01x )
|
|
|
|
|
G52 plot symbole reference par Dnn code
|
|
|
|
|
G53 plot symbole reference par Dnn ; symbole tourne de -90 degres
|
|
|
|
|
G54 Selection d'outil
|
|
|
|
|
G55 Mode exposition photo
|
|
|
|
|
G56 plot symbole reference par Dnn A code
|
|
|
|
|
G57 affiche le symbole reference sur la console
|
|
|
|
|
G58 plot et affiche le symbole reference sur la console
|
|
|
|
|
G60 interpolation lineaire ( echelle 100x )
|
|
|
|
|
G70 Unites = Inches
|
|
|
|
|
G71 Unites = Millimetres
|
|
|
|
|
G74 supprime interpolation circulaire sur 360 degre, revient a G01
|
|
|
|
|
G75 Active interpolation circulaire sur 360 degre
|
|
|
|
|
G90 Mode Coordonnees absolues
|
|
|
|
|
G91 Mode Coordonnees Relatives
|
|
|
|
|
|
|
|
|
|
Coordonnees X,Y
|
|
|
|
|
X,Y sont suivies de + ou - et de m+n chiffres (non separes)
|
|
|
|
|
m = partie entiere
|
|
|
|
|
n = partie apres la virgule
|
|
|
|
|
formats classiques : m = 2, n = 3 (format 2.3)
|
|
|
|
|
m = 3, n = 4 (format 3.4)
|
|
|
|
|
ex:
|
|
|
|
|
G__ X00345Y-06123 D__*
|
|
|
|
|
|
|
|
|
|
Outils et D_CODES
|
|
|
|
|
numero d'outil ( identification des formes )
|
|
|
|
|
1 a 99 (classique)
|
|
|
|
|
1 a 999
|
|
|
|
|
D_CODES:
|
|
|
|
|
|
|
|
|
|
D01 ... D9 = codes d'action:
|
|
|
|
|
D01 = activation de lumiere (baisser de plume) lors du d<EFBFBD>placement
|
|
|
|
|
D02 = extinction de lumiere (lever de plume) lors du d<EFBFBD>placement
|
|
|
|
|
D03 = Flash
|
|
|
|
|
D09 = VAPE Flash
|
|
|
|
|
D51 = precede par G54 -> Select VAPE
|
|
|
|
|
|
|
|
|
|
D10 ... D255 = Indentification d'outils ( d'ouvertures )
|
|
|
|
|
Ne sont pas tj dans l'ordre ( voir tableau dans PCBPLOT.H)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Type d'action du phototraceur:
|
|
|
|
|
#define GERB_ACTIVE_DRAW 1 // activation de lumiere ( baisser de plume)
|
|
|
|
|
#define GERB_STOP_DRAW 2 // extinction de lumiere ( lever de plume)
|
|
|
|
|
#define GERB_FLASH 3 // Flash
|
|
|
|
|
|
|
|
|
|
#define NEGATE(nb) (nb) = -(nb)
|
|
|
|
|
|
|
|
|
|
/* Variables locales : */
|
|
|
|
|
static wxPoint LastPosition;
|
|
|
|
|
|
|
|
|
|
/* Routines Locales */
|
|
|
|
|
|
|
|
|
|
static void Append_1_Line_GERBER(int Dcode_index, WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & startpoint,const wxPoint & endpoint,
|
|
|
|
|
int largeur);
|
|
|
|
|
static void Append_1_Flash_GERBER(int Dcode_index, WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & pos,const wxSize & size, int forme);
|
|
|
|
|
static void Append_1_Flash_ROND_GERBER(int Dcode_index, WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & pos, int diametre);
|
|
|
|
|
static void Append_1_SEG_ARC_GERBER(int Dcode_index,
|
|
|
|
|
WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & startpoint, const wxPoint & endpoint,
|
|
|
|
|
const wxPoint & rel_center, int largeur,
|
|
|
|
|
bool trigo_sens, bool multiquadrant);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
|
|
|
static void Append_1_Flash_ROND_GERBER(int Dcode_tool,
|
|
|
|
|
WinEDA_GerberFrame * frame,
|
|
|
|
|
wxDC * DC, const wxPoint & pos,int diametre)
|
|
|
|
|
/****************************************************************/
|
|
|
|
|
/* Trace 1 flash ROND en position pos
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
TRACK * track;
|
|
|
|
|
|
|
|
|
|
track = new TRACK(frame->m_Pcb);
|
|
|
|
|
track->Insert(frame->m_Pcb, NULL);
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
track->SetLayer( frame->GetScreen()->m_Active_Layer );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
track->m_Width = diametre ;
|
|
|
|
|
track->m_Start = track->m_End = pos;
|
|
|
|
|
NEGATE(track->m_Start.y);
|
|
|
|
|
NEGATE(track->m_End.y);
|
|
|
|
|
track->m_NetCode = Dcode_tool;
|
|
|
|
|
track->m_Shape = S_SPOT_CIRCLE;
|
|
|
|
|
|
|
|
|
|
Trace_Segment(frame->DrawPanel, DC, track, GR_OR) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**********************************************************************/
|
|
|
|
|
static void Append_1_Flash_GERBER(int Dcode_index,
|
|
|
|
|
WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & pos,const wxSize & size,int forme)
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
/*
|
|
|
|
|
Trace 1 flash rectangulaire ou ovale vertical ou horizontal
|
|
|
|
|
donne par son centre et ses dimensions X et Y
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
TRACK * track;
|
|
|
|
|
int width, len;
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
width = MIN( size.x, size.y );
|
|
|
|
|
len = MAX( size.x, size.y ) - width;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
track = new TRACK(frame->m_Pcb);
|
|
|
|
|
track->Insert(frame->m_Pcb, NULL);
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
track->SetLayer( frame->GetScreen()->m_Active_Layer );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
track->m_Width = width;
|
|
|
|
|
track->m_Start = track->m_End = pos;
|
|
|
|
|
NEGATE(track->m_Start.y);
|
|
|
|
|
NEGATE(track->m_End.y);
|
|
|
|
|
track->m_NetCode = Dcode_index;
|
|
|
|
|
|
|
|
|
|
if ( forme == OVALE )
|
|
|
|
|
track->m_Shape = S_SPOT_OVALE;
|
|
|
|
|
else
|
|
|
|
|
track->m_Shape = S_SPOT_RECT; // donc rectangle ou carr<72>
|
|
|
|
|
|
|
|
|
|
len >>= 1;
|
|
|
|
|
if ( size.x > size.y ) // ovale / rect horizontal
|
|
|
|
|
{
|
|
|
|
|
track->m_Start.x -= len ;
|
|
|
|
|
track->m_End.x += len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else // ovale / rect vertical
|
|
|
|
|
{
|
|
|
|
|
track->m_Start.y -= len;
|
|
|
|
|
track->m_End.y += len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Trace_Segment(frame->DrawPanel, DC, track, GR_OR) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
static void Append_1_Line_GERBER(int Dcode_index,
|
|
|
|
|
WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & startpoint, const wxPoint & endpoint,
|
|
|
|
|
int largeur)
|
|
|
|
|
/********************************************************************/
|
|
|
|
|
{
|
|
|
|
|
TRACK * track;
|
|
|
|
|
|
|
|
|
|
track = new TRACK( frame->m_Pcb );
|
|
|
|
|
track->Insert(frame->m_Pcb, NULL);
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
track->SetLayer( frame->GetScreen()->m_Active_Layer );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
track->m_Width = largeur ;
|
|
|
|
|
track->m_Start = startpoint;
|
|
|
|
|
NEGATE(track->m_Start.y);
|
|
|
|
|
track->m_End = endpoint;
|
|
|
|
|
NEGATE(track->m_End.y);
|
|
|
|
|
track->m_NetCode = Dcode_index;
|
|
|
|
|
|
|
|
|
|
Trace_Segment(frame->DrawPanel, DC, track,GR_OR) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
static void Append_1_SEG_ARC_GERBER(int Dcode_index,
|
|
|
|
|
WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
const wxPoint & startpoint, const wxPoint & endpoint,
|
|
|
|
|
const wxPoint & rel_center, int largeur,
|
|
|
|
|
bool trigo_sens, bool multiquadrant)
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
|
|
|
|
|
/* creation d'un arc:
|
|
|
|
|
si multiquadrant == TRUE arc de 0 a 360 degres
|
|
|
|
|
et rel_center est la coordonn<EFBFBD>e du centre relativement au startpoint
|
|
|
|
|
|
|
|
|
|
si multiquadrant == FALSE arc de 0 <EFBFBD> 90 entierement contenu dans le meme quadrant
|
|
|
|
|
et rel_center est la coordonn<EFBFBD>e du centre relativement au startpoint,
|
|
|
|
|
mais en VALEUR ABSOLUE et le signe des valeurs x et y de rel_center doit
|
|
|
|
|
etre deduit de cette limite de 90 degres
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
TRACK * track;
|
|
|
|
|
wxPoint center, delta;
|
|
|
|
|
|
|
|
|
|
track = new TRACK( frame->m_Pcb );
|
|
|
|
|
track->Insert(frame->m_Pcb, NULL);
|
|
|
|
|
|
|
|
|
|
track->m_Shape = S_ARC;
|
2007-08-23 04:28:46 +00:00
|
|
|
|
track->SetLayer( frame->GetScreen()->m_Active_Layer );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
track->m_Width = largeur ;
|
|
|
|
|
|
|
|
|
|
if ( multiquadrant )
|
|
|
|
|
{
|
|
|
|
|
center.x = startpoint.x + rel_center.x;
|
|
|
|
|
center.y = startpoint.y - rel_center.y;
|
|
|
|
|
|
|
|
|
|
if ( !trigo_sens )
|
|
|
|
|
{
|
|
|
|
|
track->m_Start = startpoint;
|
|
|
|
|
track->m_End = endpoint;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
track->m_Start = endpoint;
|
|
|
|
|
track->m_End = startpoint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
center = rel_center;
|
|
|
|
|
delta.x = endpoint.x - startpoint.x;
|
|
|
|
|
delta.y = endpoint.y - startpoint.y;
|
|
|
|
|
// il faut corriger de signe de rel_center.x et rel_center.y
|
|
|
|
|
// selon le quadrant ou on se trouve
|
|
|
|
|
if ( (delta.x >= 0) && (delta.y >= 0) ) // 1er quadrant
|
|
|
|
|
{
|
|
|
|
|
center.x = - center.x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if ( (delta.x < 0) && (delta.y >= 0) ) // 2eme quadrant
|
|
|
|
|
{
|
|
|
|
|
center.x = - center.x;
|
|
|
|
|
center.y = - center.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if ( (delta.x < 0) && (delta.y < 0) ) // 3eme quadrant
|
|
|
|
|
{
|
|
|
|
|
center.y = - center.y;
|
|
|
|
|
}
|
|
|
|
|
else // 4eme qadrant: les 2 coord sont >= 0!
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
center.x += startpoint.x;
|
|
|
|
|
center.y = startpoint.y + center.y ;
|
|
|
|
|
|
|
|
|
|
if ( trigo_sens )
|
|
|
|
|
{
|
|
|
|
|
track->m_Start = startpoint;
|
|
|
|
|
track->m_End = endpoint;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
track->m_Start = endpoint;
|
|
|
|
|
track->m_End = startpoint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
track->m_NetCode = Dcode_index;
|
|
|
|
|
track->m_Param = center.x;
|
|
|
|
|
track->m_Sous_Netcode = center.y;
|
|
|
|
|
|
|
|
|
|
NEGATE(track->m_Start.y);
|
|
|
|
|
NEGATE(track->m_End.y);
|
|
|
|
|
NEGATE(track->m_Sous_Netcode);
|
|
|
|
|
|
|
|
|
|
Trace_Segment(frame->DrawPanel, DC, track,GR_OR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************/
|
|
|
|
|
/* Routines utilis<69>es en lecture de ficher gerber */
|
|
|
|
|
/**************************************************/
|
|
|
|
|
/* ces routines lisent la chaine de texte point<6E>e par Text.
|
|
|
|
|
Apres appel, Text pointe le debut de la sequence non lue
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/***********************************************/
|
|
|
|
|
wxPoint GERBER_Descr::ReadXYCoord(char * &Text)
|
|
|
|
|
/***********************************************/
|
|
|
|
|
/* Retourne la coord courante pointee par Text (XnnnnYmmmm)
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
wxPoint pos = m_CurrentPos;
|
|
|
|
|
int type_coord = 0, current_coord, nbchar;
|
|
|
|
|
bool is_float = FALSE;
|
|
|
|
|
char * text;
|
|
|
|
|
char line[256];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( m_Relative ) pos.x = pos.y = 0;
|
|
|
|
|
else pos = m_CurrentPos;
|
|
|
|
|
|
|
|
|
|
if ( Text == NULL ) return pos;
|
|
|
|
|
|
|
|
|
|
text = line;
|
|
|
|
|
while ( * Text )
|
|
|
|
|
{
|
|
|
|
|
if ( (* Text == 'X') || (* Text == 'Y') )
|
|
|
|
|
{
|
|
|
|
|
type_coord = * Text;
|
|
|
|
|
Text++;
|
|
|
|
|
text = line; nbchar = 0;
|
|
|
|
|
while( IsNumber(*Text) )
|
|
|
|
|
{
|
|
|
|
|
if ( *Text == '.' ) is_float = TRUE;
|
|
|
|
|
*(text++) = *(Text++);
|
|
|
|
|
if ( (*Text >= '0') && (*Text <='9') ) nbchar++;
|
|
|
|
|
}
|
|
|
|
|
*text = 0;
|
|
|
|
|
if ( is_float )
|
|
|
|
|
{
|
|
|
|
|
if ( m_GerbMetric )
|
|
|
|
|
current_coord = (int) round(atof(line) / 0.00254);
|
|
|
|
|
else
|
|
|
|
|
current_coord = (int) round(atof(line) * PCB_INTERNAL_UNIT);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y;
|
|
|
|
|
if ( m_NoTrailingZeros )
|
|
|
|
|
{
|
|
|
|
|
int min_digit = (type_coord == 'X') ? m_FmtLen.x : m_FmtLen.y;
|
|
|
|
|
while (nbchar < min_digit) { *(text++) ='0'; nbchar++; }
|
|
|
|
|
*text=0;
|
|
|
|
|
}
|
|
|
|
|
current_coord = atoi(line);
|
|
|
|
|
double real_scale = 1.0;
|
|
|
|
|
switch( fmt_scale)
|
|
|
|
|
{
|
|
|
|
|
case 0: real_scale = 10000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 1: real_scale = 1000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 2: real_scale = 100.0;
|
|
|
|
|
break;
|
|
|
|
|
case 3: real_scale = 10.0;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
break;
|
|
|
|
|
case 5: real_scale = 0.1;
|
|
|
|
|
break;
|
|
|
|
|
case 6: real_scale = 0.01;
|
|
|
|
|
break;
|
|
|
|
|
case 7: real_scale = 0.001;
|
|
|
|
|
break;
|
|
|
|
|
case 8: real_scale = 0.0001;
|
|
|
|
|
break;
|
|
|
|
|
case 9: real_scale = 0.00001;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( m_GerbMetric ) real_scale = real_scale / 25.4;
|
|
|
|
|
current_coord = (int) round(current_coord * real_scale);
|
|
|
|
|
}
|
|
|
|
|
if ( type_coord == 'X' ) pos.x = current_coord;
|
|
|
|
|
else if ( type_coord == 'Y' ) pos.y = current_coord;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_Relative )
|
|
|
|
|
{
|
|
|
|
|
pos.x += m_CurrentPos.x;
|
|
|
|
|
pos.y += m_CurrentPos.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_CurrentPos = pos;
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
wxPoint GERBER_Descr::ReadIJCoord(char * &Text)
|
|
|
|
|
/************************************************/
|
|
|
|
|
/* Retourne la coord type InnJnn courante pointee par Text (InnnnJmmmm)
|
|
|
|
|
Ces coordonn<EFBFBD>es sont relatives, donc si une coord est absente, sa valeur
|
|
|
|
|
par defaut est 0
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
wxPoint pos(0,0);
|
|
|
|
|
int type_coord = 0, current_coord, nbchar;
|
|
|
|
|
bool is_float = FALSE;
|
|
|
|
|
char * text;
|
|
|
|
|
char line[256];
|
|
|
|
|
|
|
|
|
|
if ( Text == NULL ) return pos;
|
|
|
|
|
|
|
|
|
|
text = line;
|
|
|
|
|
while ( * Text )
|
|
|
|
|
{
|
|
|
|
|
if ( (* Text == 'I') || (* Text == 'J') )
|
|
|
|
|
{
|
|
|
|
|
type_coord = * Text;
|
|
|
|
|
Text++;
|
|
|
|
|
text = line; nbchar = 0;
|
|
|
|
|
while( IsNumber(*Text) )
|
|
|
|
|
{
|
|
|
|
|
if ( *Text == '.' ) is_float = TRUE;
|
|
|
|
|
*(text++) = *(Text++);
|
|
|
|
|
if ( (*Text >= '0') && (*Text <='9') ) nbchar++;
|
|
|
|
|
}
|
|
|
|
|
*text = 0;
|
|
|
|
|
if ( is_float )
|
|
|
|
|
{
|
|
|
|
|
if ( m_GerbMetric )
|
|
|
|
|
current_coord = (int) round(atof(line) / 0.00254);
|
|
|
|
|
else
|
|
|
|
|
current_coord = (int) round(atof(line) * PCB_INTERNAL_UNIT);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int fmt_scale = (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y;
|
|
|
|
|
if ( m_NoTrailingZeros )
|
|
|
|
|
{
|
|
|
|
|
int min_digit = (type_coord == 'I') ? m_FmtLen.x : m_FmtLen.y;
|
|
|
|
|
while (nbchar < min_digit) { *(text++) ='0'; nbchar++; }
|
|
|
|
|
*text=0;
|
|
|
|
|
}
|
|
|
|
|
current_coord = atoi(line);
|
|
|
|
|
double real_scale = 1.0;
|
|
|
|
|
switch( fmt_scale)
|
|
|
|
|
{
|
|
|
|
|
case 0: real_scale = 10000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 1: real_scale = 1000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 2: real_scale = 100.0;
|
|
|
|
|
break;
|
|
|
|
|
case 3: real_scale = 10.0;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
break;
|
|
|
|
|
case 5: real_scale = 0.1;
|
|
|
|
|
break;
|
|
|
|
|
case 6: real_scale = 0.01;
|
|
|
|
|
break;
|
|
|
|
|
case 7: real_scale = 0.001;
|
|
|
|
|
break;
|
|
|
|
|
case 8: real_scale = 0.0001;
|
|
|
|
|
break;
|
|
|
|
|
case 9: real_scale = 0.00001;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( m_GerbMetric ) real_scale = real_scale / 25.4;
|
|
|
|
|
current_coord = (int) round(current_coord * real_scale);
|
|
|
|
|
}
|
|
|
|
|
if ( type_coord == 'I' ) pos.x = current_coord;
|
|
|
|
|
else if ( type_coord == 'J' ) pos.y = current_coord;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
m_IJPos = pos;
|
|
|
|
|
return pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************/
|
|
|
|
|
int GERBER_Descr::ReturnGCodeNumber(char * &Text)
|
|
|
|
|
/*****************************************************/
|
|
|
|
|
/* Lit la sequence Gnn et retourne la valeur nn
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int ii = 0;
|
|
|
|
|
char * text;
|
|
|
|
|
char line[1024];
|
|
|
|
|
|
|
|
|
|
if ( Text == NULL ) return 0;
|
|
|
|
|
Text++;
|
|
|
|
|
text = line;
|
|
|
|
|
while( IsNumber(*Text) )
|
|
|
|
|
{
|
|
|
|
|
*(text++) = *(Text++);
|
|
|
|
|
}
|
|
|
|
|
*text = 0;
|
|
|
|
|
ii = atoi(line);
|
|
|
|
|
return ii;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************/
|
|
|
|
|
int GERBER_Descr::ReturnDCodeNumber(char * &Text)
|
|
|
|
|
/**************************************************/
|
|
|
|
|
/* Lit la sequence Dnn et retourne la valeur nn
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
int ii = 0;
|
|
|
|
|
char * text;
|
|
|
|
|
char line[1024];
|
|
|
|
|
|
|
|
|
|
if ( Text == NULL ) return 0;
|
|
|
|
|
Text ++;
|
|
|
|
|
text = line;
|
|
|
|
|
while( IsNumber(*Text) ) *(text++) = *(Text++);
|
|
|
|
|
*text = 0;
|
|
|
|
|
ii = atoi(line);
|
|
|
|
|
return ii;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
bool GERBER_Descr::Execute_G_Command(char * &text, int G_commande)
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
switch (G_commande)
|
|
|
|
|
{
|
|
|
|
|
case GC_LINEAR_INTERPOL_1X:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_LINEAR_1X;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_CIRCLE_NEG_INTERPOL:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_ARC_NEG;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_CIRCLE_POS_INTERPOL:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_ARC_POS;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_COMMENT:
|
|
|
|
|
text = NULL;
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
|
|
case GC_LINEAR_INTERPOL_10X:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_LINEAR_10X;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_LINEAR_INTERPOL_0P1X:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_LINEAR_01X;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_LINEAR_INTERPOL_0P01X:
|
|
|
|
|
m_Iterpolation = GERB_INTERPOL_LINEAR_001X;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_SELECT_TOOL:
|
|
|
|
|
{
|
|
|
|
|
int D_commande = ReturnDCodeNumber(text);
|
|
|
|
|
if ( D_commande < FIRST_DCODE) return FALSE;
|
|
|
|
|
if (D_commande > (MAX_TOOLS-1)) D_commande = MAX_TOOLS-1;
|
|
|
|
|
m_Current_Tool = D_commande;
|
2007-08-23 04:28:46 +00:00
|
|
|
|
D_CODE * pt_Dcode = ReturnToolDescr( m_Layer, D_commande );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
if ( pt_Dcode ) pt_Dcode->m_InUse = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case GC_SPECIFY_INCHES:
|
|
|
|
|
m_GerbMetric = FALSE; // FALSE = Inches, TRUE = metric
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_SPECIFY_MILLIMETERS:
|
|
|
|
|
m_GerbMetric = TRUE; // FALSE = Inches, TRUE = metric
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_TURN_OFF_360_INTERPOL:
|
|
|
|
|
m_360Arc_enbl = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_TURN_ON_360_INTERPOL:
|
|
|
|
|
m_360Arc_enbl = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_SPECIFY_ABSOLUES_COORD:
|
|
|
|
|
m_Relative = FALSE; // FALSE = absolute Coord, RUE = relative Coord
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_SPECIFY_RELATIVEES_COORD:
|
|
|
|
|
m_Relative = TRUE; // FALSE = absolute Coord, RUE = relative Coord
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_TURN_ON_POLY_FILL:
|
|
|
|
|
m_PolygonFillMode = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_TURN_OFF_POLY_FILL:
|
|
|
|
|
m_PolygonFillMode = FALSE;
|
|
|
|
|
m_PolygonFillModeState = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GC_MOVE: // Non existant
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
wxString msg; msg.Printf( wxT("G%.2d command not handled"),G_commande);
|
|
|
|
|
DisplayError(NULL, msg);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
bool GERBER_Descr::Execute_DCODE_Command(WinEDA_GerberFrame * frame, wxDC * DC,
|
|
|
|
|
char * &text, int D_commande)
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
{
|
|
|
|
|
wxSize size(15, 15);
|
|
|
|
|
int shape = 1, dcode = 0;
|
|
|
|
|
D_CODE * pt_Tool = NULL;
|
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
|
|
if(D_commande >= FIRST_DCODE ) // This is a "Set tool" command
|
|
|
|
|
{
|
|
|
|
|
if (D_commande > (MAX_TOOLS-1)) D_commande = MAX_TOOLS-1;
|
|
|
|
|
m_Current_Tool = D_commande;
|
|
|
|
|
D_CODE * pt_Dcode = ReturnToolDescr(m_Layer, D_commande);
|
|
|
|
|
if ( pt_Dcode ) pt_Dcode->m_InUse = TRUE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else // D_commande = 0..9: this is a pen command (usualy D1, D2 or D3)
|
|
|
|
|
{
|
|
|
|
|
m_Last_Pen_Command = D_commande;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m_PolygonFillMode ) // Enter a polygon description:
|
|
|
|
|
{
|
|
|
|
|
switch ( D_commande )
|
|
|
|
|
{
|
|
|
|
|
case 1: //code D01 Draw line, exposure ON
|
|
|
|
|
{
|
|
|
|
|
SEGZONE * edge_poly, *last;
|
|
|
|
|
|
|
|
|
|
edge_poly = new SEGZONE( frame->m_Pcb );
|
|
|
|
|
last = (SEGZONE*)frame->m_Pcb->m_Zone;
|
|
|
|
|
if ( last ) while (last->Pnext ) last = (SEGZONE*)last->Pnext;
|
|
|
|
|
edge_poly->Insert(frame->m_Pcb, last);
|
|
|
|
|
|
2007-08-23 04:28:46 +00:00
|
|
|
|
edge_poly->SetLayer( frame->GetScreen()->m_Active_Layer );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
edge_poly->m_Width = 1;
|
|
|
|
|
edge_poly->m_Start = m_PreviousPos;
|
|
|
|
|
NEGATE(edge_poly->m_Start.y);
|
|
|
|
|
edge_poly->m_End = m_CurrentPos;
|
|
|
|
|
NEGATE(edge_poly->m_End.y);
|
|
|
|
|
edge_poly->m_NetCode = m_PolygonFillModeState;
|
|
|
|
|
m_PreviousPos = m_CurrentPos;
|
|
|
|
|
m_PolygonFillModeState = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 2: //code D2: exposure OFF (i.e. "move to")
|
|
|
|
|
m_PreviousPos = m_CurrentPos;
|
|
|
|
|
m_PolygonFillModeState = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else switch ( D_commande )
|
|
|
|
|
{
|
|
|
|
|
case 1: //code D01 Draw line, exposure ON
|
|
|
|
|
pt_Tool = ReturnToolDescr(m_Layer, m_Current_Tool);
|
|
|
|
|
if ( pt_Tool )
|
|
|
|
|
{
|
|
|
|
|
size = pt_Tool->m_Size;
|
|
|
|
|
dcode = pt_Tool->m_Num_Dcode;
|
|
|
|
|
shape = pt_Tool->m_Shape;
|
|
|
|
|
}
|
|
|
|
|
switch ( m_Iterpolation )
|
|
|
|
|
{
|
|
|
|
|
case GERB_INTERPOL_LINEAR_1X:
|
|
|
|
|
Append_1_Line_GERBER(dcode,
|
|
|
|
|
frame, DC,
|
|
|
|
|
m_PreviousPos, m_CurrentPos,
|
|
|
|
|
size.x);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GERB_INTERPOL_LINEAR_01X:
|
|
|
|
|
case GERB_INTERPOL_LINEAR_001X:
|
|
|
|
|
case GERB_INTERPOL_LINEAR_10X:
|
|
|
|
|
wxBell();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GERB_INTERPOL_ARC_NEG:
|
|
|
|
|
Append_1_SEG_ARC_GERBER(dcode,
|
|
|
|
|
frame, DC,
|
|
|
|
|
m_PreviousPos, m_CurrentPos, m_IJPos,
|
|
|
|
|
size.x, FALSE, m_360Arc_enbl);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GERB_INTERPOL_ARC_POS:
|
|
|
|
|
Append_1_SEG_ARC_GERBER(dcode,
|
|
|
|
|
frame, DC,
|
|
|
|
|
m_PreviousPos, m_CurrentPos, m_IJPos,
|
|
|
|
|
size.x, TRUE, m_360Arc_enbl);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
msg.Printf( wxT("Execute_DCODE_Command: interpol error (type %X)"),
|
|
|
|
|
m_Iterpolation);
|
|
|
|
|
DisplayError(frame, msg);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
m_PreviousPos = m_CurrentPos;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2: //code D2: exposure OFF (i.e. "move to")
|
|
|
|
|
m_PreviousPos = m_CurrentPos;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3: // code D3: flash aperture
|
|
|
|
|
pt_Tool = ReturnToolDescr(m_Layer, m_Current_Tool);
|
|
|
|
|
if ( pt_Tool )
|
|
|
|
|
{
|
|
|
|
|
size = pt_Tool->m_Size;
|
|
|
|
|
dcode = pt_Tool->m_Num_Dcode;
|
|
|
|
|
shape = pt_Tool->m_Shape;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (shape)
|
|
|
|
|
{
|
|
|
|
|
case GERB_LINE:
|
|
|
|
|
case GERB_CIRCLE :
|
|
|
|
|
Append_1_Flash_ROND_GERBER(dcode,
|
|
|
|
|
frame, DC,
|
|
|
|
|
m_CurrentPos,
|
|
|
|
|
size.x);
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
|
|
case GERB_OVALE :
|
|
|
|
|
Append_1_Flash_GERBER( dcode,
|
|
|
|
|
frame, DC, m_CurrentPos,
|
|
|
|
|
size,
|
|
|
|
|
OVALE);
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
|
|
case GERB_RECT:
|
|
|
|
|
Append_1_Flash_GERBER( dcode,
|
|
|
|
|
frame, DC, m_CurrentPos,
|
|
|
|
|
size,
|
|
|
|
|
RECT);
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
|
|
default: // Special (Macro) : Non implant<6E>
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
m_PreviousPos = m_CurrentPos;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|