preparing Gerbview enhancements

This commit is contained in:
jean-pierre charras 2010-11-30 21:41:35 +01:00
parent 8c7017aa57
commit 6396c2ebc8
7 changed files with 360 additions and 173 deletions

View File

@ -23,6 +23,7 @@ set(DIALOGS_SRCS
set(GERBVIEW_SRCS set(GERBVIEW_SRCS
block.cpp block.cpp
class_am_param.cpp
class_aperture_macro.cpp class_aperture_macro.cpp
class_GERBER.cpp class_GERBER.cpp
class_gerber_draw_item.cpp class_gerber_draw_item.cpp

View File

@ -0,0 +1,98 @@
/*****************/
/* am_param.cpp */
/*****************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "class_am_param.h"
extern int ReadInt( char*& text, bool aSkipSeparator = true );
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
/*Class AM_PARAM
* holds a parameter for an "aperture macro" as defined within
* standard RS274X. The \a value field can be a constant, i.e. "immediate"
* parameter or it may not be used if this param is going to defer to the
* referencing aperture macro. In that case, the \a index field is an index
* into the aperture macro's parameters.
*/
double AM_PARAM::GetValue( const D_CODE* aDcode ) const
{
if( IsImmediate() )
return value;
else
{
// the first one was numbered 1, not zero, as in $1, see page 19 of spec.
unsigned ndx = GetIndex();
wxASSERT( aDcode );
// get the parameter from the aDcode
if( ndx <= aDcode->GetParamCount() )
return aDcode->GetParam( ndx );
else
{
wxASSERT( GetIndex() <= aDcode->GetParamCount() );
return 0.0;
}
}
}
/**
* Function ReadParam
* Read one aperture macro parameter
* a parameter can be:
* a number
* a reference to an aperture definition parameter value: $1 ot $3 ...
* a parameter definition can be complex and have operators between numbers and/or other parameter
* like $1+3 or $2x2..
* Parameters are separated by a comma ( of finish by *)
* @param aText = pointer to the parameter to read. Will be modified to point to the next field
* @return true if a param is read, or false
*/
bool AM_PARAM::ReadParam( char*& aText )
{
bool found = false;
if( *aText == '$' ) // value defined later, in aperture description
{
++aText;
SetIndex( ReadInt( aText, false ) );
found = true;
}
else
{
SetValue( ReadDouble( aText, false ) );
found = true;
}
// Skip extra characters and separator
while( *aText && (*aText != ',') && (*aText != '*') )
aText++;
if( *aText == ',' )
aText++;
return found;
}

174
gerbview/class_am_param.h Normal file
View File

@ -0,0 +1,174 @@
/*****************/
/* am_param.h */
/*****************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _AM_PARAM_H_
#define _AM_PARAM_H_
/*
An aperture macro defines a complex shape and is a list of aperture primitives.
Each aperture primitive defines a simple shape (circle, rect, regular polygon...)
Inside a given aperture primitive, a fixed list of parameters defines info
about the shape: size, thickness, number of vertex ...
Each parameter can be an immediate value or a defered value.
When value is defered, it is defined when the aperture macro is instancied by
an ADD macro command
Actual values of a parmeter can also be the result of an arithmetic operation.
Here is some examples:
An immediate value:
3.5
A deferend value:
$2 means: replace me by the second value given in the ADD command
Actual value as arithmetic calculation:
$2/2+1
Note also a defered parameter can be defined in aperture macro,
but outside aperture primitives. Example
%AMRECTHERM*
$4=$3/2* parameter $4 is half value of parameter $3
21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0*
For the aperture primitive, parameters $1 to $3 will be defined in ADD command,
and $4 is defined inside the macro
Some examples of aperture macro definition
A simple definition, no parameters:
%AMMOIRE10*
6,0,0,0.350000,0.005,0.050,3,0.005,0.400000,0.0*%
Example of instanciation:
%ADD19THERM19*%
A simple definition, one parameter:
%AMCIRCLE*
1,1,$1,0,0*
Example of instanciation:
%ADD11CIRCLE,.5*%
A definition, with parameters and arithmetic operations:
%AMVECTOR*
2,1,$1,0,0,$2+1,$3,-135*%
Example of instanciation:
%ADD12VECTOR,0.05X0X0*%
A more complicated aperture macro definition, with parameters and arihmetic operations:
%AMRNDREC*
0 this is a comment*
21,1,$1+$1,$2+$2-$3-$3,0,0,0*
21,1,$1+$1-$3-$3,$2+$2,0,0,0*
1,1,$3+$3,$1-$3,$2-$3*
1,1,$3+$3,$3-$1,$2-$3*
1,1,$3+$3,$1-$3,$3-$2*
1,1,$3+$3,$3-$1,$3-$2*%
Example of instanciation:
A more complicated sample of aperture macro definition:
G04 Rectangular Thermal Macro, params: W/2, H/2, T/2 *
%AMRECTHERM*
$4=$3/2*
21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0*
21,1,$1-$3,$2-$3,0-$1/2-$4,$2/2+$4,0*
21,1,$1-$3,$2-$3,$1/2+$4,0-$2/2-$4,0*
21,1,$1-$3,$2-$3,$1/2+$4,$2/2+$4,0*%
Example of instanciation:
%ADD28RECTHERM,0.035591X0.041496X0.005000*%
*/
#include <vector>
#include "dcode.h"
/**
* Class AM_PARAM
* holds a parameter for an "aperture macro" as defined within
* standard RS274X. The \a value field can be a constant, i.e. "immediate"
* parameter or it may not be used if this param is going to defer to the
* referencing aperture macro. In that case, the \a index field is an index
* into the aperture macro's parameters.
*/
class AM_PARAM
{
public:
AM_PARAM() :
index( -1 ),
value( 0.0 )
{}
double GetValue( const D_CODE* aDcode ) const;
void SetValue( double aValue )
{
value = aValue;
index = -1;
}
/**
* Function IsImmediate
* tests if this AM_PARAM holds an immediate parameter or is a pointer
* into a parameter held by an owning D_CODE.
*/
bool IsImmediate() const { return index == -1; }
unsigned GetIndex() const
{
return (unsigned) index;
}
void SetIndex( int aIndex )
{
index = aIndex;
}
/**
* Function ReadParam
* Read one aperture macro parameter
* a parameter can be:
* a number
* a reference to an aperture definition parameter value: $1 ot $3 ...
* a parameter definition can be complex and have operators between numbers and/or other parameter
* like $1+3 or $2x2..
* Parameters are separated by a comma ( of finish by *)
* @param aText = pointer to the parameter to read. Will be modified to point to the next field
* @return true if a param is read, or false
*/
bool ReadParam( char*& aText );
private:
int index; ///< if -1, then \a value field is an immediate value,
// else this is an index into parent's
// D_CODE.m_am_params.
double value; ///< if IsImmediate()==true then use the value, else
// not used.
};
typedef std::vector<AM_PARAM> AM_PARAMS;
#endif // _AM_PARAM_H_

View File

@ -34,6 +34,7 @@
#include <set> #include <set>
#include "base_struct.h" #include "base_struct.h"
#include "class_am_param.h"
/** /**
@ -68,7 +69,7 @@ class AM_PRIMITIVE
{ {
public: public:
AM_PRIMITIVE_ID primitive_id; ///< The primitive type AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by AM_PARAMS params; ///< A sequence of parameters used by
// the primitive // the primitive
bool m_GerbMetric; // units for this primitive: bool m_GerbMetric; // units for this primitive:
// false = Inches, true = metric // false = Inches, true = metric

View File

@ -31,7 +31,7 @@
#define _DCODE_H_ #define _DCODE_H_
#include <vector> #include <vector>
#include <set> //#include <set>
#include "base_struct.h" #include "base_struct.h"
class GERBER_DRAW_ITEM; class GERBER_DRAW_ITEM;
@ -67,62 +67,6 @@ enum APERTURE_DEF_HOLETYPE {
#define TOOLS_MAX_COUNT (LAST_DCODE + 1) #define TOOLS_MAX_COUNT (LAST_DCODE + 1)
class APERTURE_MACRO; class APERTURE_MACRO;
class D_CODE;
/**
* Class DCODE_PARAM
* holds a parameter for a DCODE or an "aperture macro" as defined within
* standard RS274X. The \a value field can be a constant, i.e. "immediate"
* parameter or it may not be used if this param is going to defer to the
* referencing aperture macro. In that case, the \a index field is an index
* into the aperture macro's parameters.
*/
class DCODE_PARAM
{
public:
DCODE_PARAM() :
index( -1 ),
value( 0.0 )
{}
double GetValue( const D_CODE* aDcode ) const;
void SetValue( double aValue )
{
value = aValue;
index = -1;
}
/**
* Function IsImmediate
* tests if this DCODE_PARAM holds an immediate parameter or is a pointer
* into a parameter held by an owning D_CODE.
*/
bool IsImmediate() const { return index == -1; }
unsigned GetIndex() const
{
return (unsigned) index;
}
void SetIndex( int aIndex )
{
index = aIndex;
}
private:
int index; ///< if -1, then \a value field is an immediate value,
// else this is an index into parent's
// D_CODE.m_am_params.
double value; ///< if IsImmediate()==true then use the value, else
// not used.
};
typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
/** /**
@ -131,16 +75,14 @@ typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
*/ */
class D_CODE class D_CODE
{ {
friend class DCODE_PARAM; private:
APERTURE_MACRO* m_Macro; ///< no ownership, points to APERTURE_MACRO* m_Macro; ///< no ownership, points to
// GERBER.m_aperture_macros element // GERBER.m_aperture_macros element
/** /**
* parameters used only when this D_CODE holds a reference to an aperture * parameters used only when this D_CODE holds a reference to an aperture
* macro, and these parameters would customize the macro. * macro, and these parameters would customize the macro.
*/ */
DCODE_PARAMS m_am_params; std::vector<double> m_am_params;
std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw APT_POLYGON shape and some other std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw APT_POLYGON shape and some other
* complex shapes which are converted to polygon * complex shapes which are converted to polygon
@ -164,13 +106,37 @@ public:
~D_CODE(); ~D_CODE();
void Clear_D_CODE_Data(); void Clear_D_CODE_Data();
/**
* AppendParam()
* Add a parameter to the D_CODE parameter list.
* used to customize the corresponding aperture macro
*/
void AppendParam( double aValue ) void AppendParam( double aValue )
{ {
DCODE_PARAM param; m_am_params.push_back( aValue );
}
param.SetValue( aValue ); /**
* GetParamCount()
* Returns the number of parameters stored in parameter list.
*/
unsigned GetParamCount() const
{
return m_am_params.size();
}
m_am_params.push_back( param ); /**
* GetParam()
* Returns a parameter stored in parameter list.
* @param aIdx = index of parameter
*/
double GetParam( unsigned aIdx ) const
{
wxASSERT( aIdx <= m_am_params.size() );
if( aIdx <= m_am_params.size() )
return m_am_params[aIdx - 1];
else
return 0;
} }
@ -245,26 +211,4 @@ public:
}; };
inline double DCODE_PARAM::GetValue( const D_CODE* aDcode ) const
{
if( IsImmediate() )
return value;
else
{
// the first one was numbered 1, not zero, as in $1, see page 19 of spec.
unsigned ndx = GetIndex() - 1;
wxASSERT( aDcode );
// get the parameter from the aDcode
if( ndx < aDcode->m_am_params.size() )
return aDcode->m_am_params[ndx].GetValue( NULL );
else
{
wxASSERT( GetIndex() - 1 < aDcode->m_am_params.size() );
return 0.0;
}
}
}
#endif // ifndef _DCODE_H_ #endif // ifndef _DCODE_H_

View File

@ -201,3 +201,48 @@ wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text )
m_IJPos = pos; m_IJPos = pos;
return pos; return pos;
} }
// Helper functions:
/**
* Function ReadInt
* reads an int from an ASCII character buffer. If there is a comma after the
* int, then skip over that.
* @param text A reference to a character pointer from which bytes are read
* and the pointer is advanced for each byte read.
* @param aSkipSeparator = true (default) to skip comma
* @return int - The int read in.
*/
int ReadInt( char*& text, bool aSkipSeparator = true )
{
int ret = (int) strtol( text, &text, 10 );
if( *text == ',' || isspace( *text ) )
if( aSkipSeparator )
++text;
return ret;
}
/**
* Function ReadDouble
* reads a double from an ASCII character buffer. If there is a comma after
* the double, then skip over that.
* @param text A reference to a character pointer from which the ASCII double
* is read from and the pointer advanced for each character read.
* @param aSkipSeparator = true (default) to skip comma
* @return double
*/
double ReadDouble( char*& text, bool aSkipSeparator = true )
{
double ret = strtod( text, &text );
if( *text == ',' || isspace( *text ) )
if( aSkipSeparator )
++text;
return ret;
}

View File

@ -5,14 +5,14 @@
#include "fctsys.h" #include "fctsys.h"
#include "common.h" #include "common.h"
//#include "macros.h"
#include "gerbview.h" #include "gerbview.h"
#include "class_GERBER.h" #include "class_GERBER.h"
#define CODE( x, y ) ( ( (x) << 8 ) + (y) ) extern int ReadInt( char*& text, bool aSkipSeparator = true );
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
// Helper function to read a primitive macro param (TODO: make it DCODE_PARAM function)
static bool ReadMacroParam( DCODE_PARAM& aParam, char*& aText ); #define CODE( x, y ) ( ( (x) << 8 ) + (y) )
// See rs274xrevd_e.pdf, table 1: RS-274X parameters order of entry // See rs274xrevd_e.pdf, table 1: RS-274X parameters order of entry
// in gerber files, when a coordinate is given (like X78Y600 or I0J80): // in gerber files, when a coordinate is given (like X78Y600 or I0J80):
@ -92,48 +92,6 @@ static int ReadXCommand( char*& text )
} }
/**
* Function ReadInt
* reads an int from an ASCII character buffer. If there is a comma after the
* int, then skip over that.
* @param text A reference to a character pointer from which bytes are read
* and the pointer is advanced for each byte read.
* @param aSkipSeparator = true (default) to skip comma
* @return int - The int read in.
*/
static int ReadInt( char*& text, bool aSkipSeparator = true )
{
int ret = (int) strtol( text, &text, 10 );
if( *text == ',' || isspace( *text ) )
if( aSkipSeparator )
++text;
return ret;
}
/**
* Function ReadDouble
* reads a double from an ASCII character buffer. If there is a comma after
* the double, then skip over that.
* @param text A reference to a character pointer from which the ASCII double
* is read from and the pointer advanced for each character read.
* @param aSkipSeparator = true (default) to skip comma
* @return double
*/
static double ReadDouble( char*& text, bool aSkipSeparator = true )
{
double ret = strtod( text, &text );
if( *text == ',' || isspace( *text ) )
if( aSkipSeparator )
++text;
return ret;
}
bool GERBER_IMAGE::ReadRS274XCommand( char buff[GERBER_BUFZ], char*& text ) bool GERBER_IMAGE::ReadRS274XCommand( char buff[GERBER_BUFZ], char*& text )
{ {
bool ok = true; bool ok = true;
@ -952,14 +910,14 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
int i; int i;
for( i = 0; i < paramCount && *text && *text != '*'; ++i ) for( i = 0; i < paramCount && *text && *text != '*'; ++i )
{ {
prim.params.push_back( DCODE_PARAM() ); prim.params.push_back( AM_PARAM() );
DCODE_PARAM& param = prim.params.back(); AM_PARAM& param = prim.params.back();
text = GetNextLine( buff, text, gerber_file ); text = GetNextLine( buff, text, gerber_file );
if( text == NULL) // End of File if( text == NULL) // End of File
return false; return false;
ReadMacroParam( param, text ); param.ReadParam( text );
} }
if( i < paramCount ) if( i < paramCount )
@ -984,14 +942,14 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
for( int i = 0; i < paramCount && *text != '*'; ++i ) for( int i = 0; i < paramCount && *text != '*'; ++i )
{ {
prim.params.push_back( DCODE_PARAM() ); prim.params.push_back( AM_PARAM() );
DCODE_PARAM& param = prim.params.back(); AM_PARAM& param = prim.params.back();
text = GetNextLine( buff, text, gerber_file ); text = GetNextLine( buff, text, gerber_file );
if( text == NULL ) // End of File if( text == NULL ) // End of File
return false; return false;
ReadMacroParam( param, text ); param.ReadParam( text );
} }
} }
@ -1003,37 +961,3 @@ bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ],
return true; return true;
} }
/**
* Function ReadMacroParam
* Read one aperture macro parameter
* a parameter can be:
* a number
* a reference to an aperture definition parameter value: $1 ot $3 ...
* a parameter definition can be complex and have operators between numbers and/or other parameter
* like $1+3 or $2x2..
* Parameters are separated by a comma ( of finish by *)
* Return if a param is read, or false
*/
static bool ReadMacroParam( DCODE_PARAM& aParam, char*& aText )
{
bool found = false;
if( *aText == '$' ) // value defined later, in aperture description
{
++aText;
aParam.SetIndex( ReadInt( aText, false ) );
found = true;
}
else
{
aParam.SetValue( ReadDouble( aText, false ) );
found = true;
}
// Skip extra characters and separator
while( *aText && (*aText != ',') && (*aText != '*') )
aText++;
if( *aText == ',' )
aText++;
return found;
}