Gerbview: added support og regular polygon aperure definition.

This commit is contained in:
jean-pierre charras 2010-09-28 21:34:16 +02:00
parent 6417db152a
commit d696ee8cd5
7 changed files with 248 additions and 168 deletions

View File

@ -12,12 +12,11 @@ email address.
graphics items are now specific to gerbview (added a GERBER_DRAW_ITEM class) graphics items are now specific to gerbview (added a GERBER_DRAW_ITEM class)
and do not use tracks from pcbnew. and do not use tracks from pcbnew.
The way used to draw them is also new. The way used to draw them is also new.
Apertures are now correctly drawn for round, oval and rectangular shapes Apertures are now correctly drawn for round, oval, rectangular and regular polygon shapes
(with or without holes) (with or without holes)
Aperture definition type Polygon is not yet handle. Aperture definition type Polygon is not yet handle.
Polygons are correctly drawn. Polygons are correctly drawn.
TODO: TODO:
Draw functions for aperture definition type Polygon.
Draw functions for aperture macros. Draw functions for aperture macros.
Work in progress. Work in progress.

View File

@ -106,10 +106,13 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape()
case GBR_SPOT_RECT: case GBR_SPOT_RECT:
return wxT( "spot_rect" ); return wxT( "spot_rect" );
case GBR_SPOT_POLY:
return wxT( "spot_poly" );
case GBR_POLYGON: case GBR_POLYGON:
return wxT( "polygon" ); return wxT( "polygon" );
case GBR_MACRO: case GBR_SPOT_MACRO:
return wxT( "apt_macro" ); // TODO: add aperture macro name return wxT( "apt_macro" ); // TODO: add aperture macro name
default: default:
@ -276,6 +279,7 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
case GBR_SPOT_CIRCLE: case GBR_SPOT_CIRCLE:
case GBR_SPOT_RECT: case GBR_SPOT_RECT:
case GBR_SPOT_OVAL: case GBR_SPOT_OVAL:
case GBR_SPOT_POLY:
isFilled = DisplayOpt.DisplayPadFill ? true : false; isFilled = DisplayOpt.DisplayPadFill ? true : false;
d_codeDescr->DrawFlashedShape( &panel->m_ClipBox, DC, color, d_codeDescr->DrawFlashedShape( &panel->m_ClipBox, DC, color,
m_Start, isFilled ); m_Start, isFilled );

View File

@ -40,7 +40,8 @@ enum Gbr_Basic_Shapes {
GBR_SPOT_CIRCLE, // flashed shape: round shape (can have hole) GBR_SPOT_CIRCLE, // flashed shape: round shape (can have hole)
GBR_SPOT_RECT, // flashed shape: rectangular shape can have hole) GBR_SPOT_RECT, // flashed shape: rectangular shape can have hole)
GBR_SPOT_OVAL, // flashed shape: oval shape GBR_SPOT_OVAL, // flashed shape: oval shape
GBR_MACRO, // complex shape described by a macro GBR_SPOT_POLY, // flashed shape: regulat polygon, 3 to 12 edges
GBR_SPOT_MACRO, // complex shape described by a macro
GBR_LAST // last value for this list GBR_LAST // last value for this list
}; };

View File

@ -56,11 +56,12 @@ void D_CODE::Clear_D_CODE_Data()
m_Size.y = DEFAULT_SIZE; m_Size.y = DEFAULT_SIZE;
m_Shape = APT_CIRCLE; m_Shape = APT_CIRCLE;
m_Drill.x = m_Drill.y = 0; m_Drill.x = m_Drill.y = 0;
m_DrillShape = 0; m_DrillShape = APT_DEF_NO_HOLE;
m_InUse = FALSE; m_InUse = FALSE;
m_Defined = FALSE; m_Defined = FALSE;
m_Macro = 0; m_Macro = NULL;
m_Rotation = 0.0; m_Rotation = 0.0;
m_EdgesCount = 0;
} }
@ -252,17 +253,29 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
{ {
case APT_LINE: // might not appears here, but some broken case APT_LINE: // might not appears here, but some broken
// gerber files use it // gerber files use it
case APT_CIRCLE: /* spot round (for GERBER) */ case APT_CIRCLE: /* spot round */
gerb_item->m_Shape = GBR_SPOT_CIRCLE; gerb_item->m_Shape = GBR_SPOT_CIRCLE;
break; break;
case APT_OVAL: /* spot oval (for GERBER)*/ case APT_OVAL: /* spot oval*/
gerb_item->m_Shape = GBR_SPOT_OVAL; gerb_item->m_Shape = GBR_SPOT_OVAL;
break; break;
default: /* spot rect (for GERBER)*/ case APT_RECT: /* spot rect*/
gerb_item->m_Shape = GBR_SPOT_RECT; gerb_item->m_Shape = GBR_SPOT_RECT;
break; break;
case APT_POLYGON: /* spot regular polyg 3 to 1é edges */
gerb_item->m_Shape = GBR_SPOT_POLY;
break;
case APT_MACRO: /* spot defined by a macro */
gerb_item->m_Shape = GBR_SPOT_MACRO;
break;
default:
wxMessageBox( wxT("WinEDA_GerberFrame::CopyDCodesSizeToItems() error" ) );
break;
} }
} }
} }
@ -280,14 +293,16 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
switch( m_Shape ) switch( m_Shape )
{ {
case APT_MACRO: // TODO: current a round shape
case APT_CIRCLE: case APT_CIRCLE:
radius = m_Size.x >> 1; radius = m_Size.x >> 1;
if( !aFilledShape ) if( !aFilledShape )
GRCircle( aClipBox, aDC, aShapePos.x, aShapePos.y, radius, aColor ); GRCircle( aClipBox, aDC, aShapePos.x, aShapePos.y, radius, aColor );
else else
if( m_DrillShape == 0 ) if( m_DrillShape == APT_DEF_NO_HOLE )
GRFilledCircle( aClipBox, aDC, aShapePos, radius, aColor ); GRFilledCircle( aClipBox, aDC, aShapePos, radius, aColor );
else if( m_DrillShape == 1 ) // round hole else if( APT_DEF_ROUND_HOLE == 1 ) // round hole in shape
{ {
int width = (m_Size.x - m_Drill.x ) / 2; int width = (m_Size.x - m_Drill.x ) / 2;
GRCircle( aClipBox, aDC, aShapePos, radius - (width / 2), width, aColor ); GRCircle( aClipBox, aDC, aShapePos, radius - (width / 2), width, aColor );
@ -301,21 +316,22 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
break; break;
case APT_LINE: case APT_LINE:
// not used for flashed items // not used for flashed items
break; break;
case APT_RECT: case APT_RECT:
{ {
wxPoint start; wxPoint start;
start.x = aShapePos.x - m_Size.x/2; start.x = aShapePos.x - m_Size.x / 2;
start.y = aShapePos.y - m_Size.y/2; start.y = aShapePos.y - m_Size.y / 2;
wxPoint end = start + m_Size; wxPoint end = start + m_Size;
if( !aFilledShape ) if( !aFilledShape )
{ {
GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y , GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y,
0, aColor ); 0, aColor );
} }
else if( m_DrillShape == 0 ) else if( m_DrillShape == APT_DEF_NO_HOLE )
{ {
GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y,
0, aColor, aColor ); 0, aColor, aColor );
@ -327,7 +343,7 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos ); DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
} }
} }
break; break;
case APT_OVAL: case APT_OVAL:
{ {
@ -352,7 +368,7 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
GRCSegm( aClipBox, aDC, start.x, start.y, GRCSegm( aClipBox, aDC, start.x, start.y,
end.x, end.y, radius, aColor ); end.x, end.y, radius, aColor );
} }
else if( m_DrillShape == 0 ) else if( m_DrillShape == APT_DEF_NO_HOLE )
{ {
GRFillCSegm( aClipBox, aDC, start.x, GRFillCSegm( aClipBox, aDC, start.x,
start.y, end.x, end.y, radius, aColor ); start.y, end.x, end.y, radius, aColor );
@ -371,10 +387,6 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
ConvertShapeToPolygon(); ConvertShapeToPolygon();
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos ); DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
break; break;
case APT_MACRO:
// TODO
break;
} }
} }
@ -403,6 +415,15 @@ void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC,
} }
#define SEGS_CNT 32 // number of segments to approximate a circle
// A helper function for D_CODE::ConvertShapeToPolygon().
// Add a hole to a polygon
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
APERTURE_DEF_HOLETYPE aHoleShape,
wxSize aSize,
wxPoint aAnchorPos );
/** function ConvertShapeToPolygon /** function ConvertShapeToPolygon
* convert a shape to an equivalent polygon. * convert a shape to an equivalent polygon.
* Arcs and circles are approximated by segments * Arcs and circles are approximated by segments
@ -411,7 +432,6 @@ void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC,
*/ */
void D_CODE::ConvertShapeToPolygon() void D_CODE::ConvertShapeToPolygon()
{ {
#define SEGS_CNT 32 // number of segments to approximate a circle
wxPoint initialpos; wxPoint initialpos;
wxPoint currpos;; wxPoint currpos;;
m_PolyCorners.clear(); m_PolyCorners.clear();
@ -427,41 +447,18 @@ void D_CODE::ConvertShapeToPolygon()
RotatePoint( &currpos, ii * 3600 / SEGS_CNT ); RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos ); m_PolyCorners.push_back( currpos );
} }
if( m_DrillShape == 1 )
{ addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
for( unsigned ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = m_Drill.x / 2;
currpos.y = 0;
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
break; break;
case APT_LINE: case APT_LINE:
// Not used for flashed shapes // Not used for flashed shapes
break; break;
case APT_RECT: case APT_RECT:
currpos.x = m_Size.x / 2; currpos.x = m_Size.x / 2;
currpos.y = m_Size.y / 2; currpos.y = m_Size.y / 2;
initialpos = currpos; initialpos = currpos;
m_PolyCorners.push_back( currpos ); m_PolyCorners.push_back( currpos );
currpos.x -= m_Size.x; currpos.x -= m_Size.x;
@ -471,33 +468,9 @@ void D_CODE::ConvertShapeToPolygon()
currpos.x += m_Size.x; currpos.x += m_Size.x;
m_PolyCorners.push_back( currpos ); m_PolyCorners.push_back( currpos );
currpos.y += m_Size.y; currpos.y += m_Size.y;
m_PolyCorners.push_back( currpos ); // close polygon m_PolyCorners.push_back( currpos ); // close polygon
if( m_DrillShape == 1 ) // build a round hole
{ addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
for( int ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = 0;
currpos.y = m_Drill.x / 2; // m_Drill.x / 2 is the radius of the hole
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
break; break;
case APT_OVAL: case APT_OVAL:
@ -507,7 +480,7 @@ void D_CODE::ConvertShapeToPolygon()
// we create an horizontal oval shape. then rotate if needed // we create an horizontal oval shape. then rotate if needed
if( m_Size.x > m_Size.y ) // horizontal oval if( m_Size.x > m_Size.y ) // horizontal oval
{ {
delta = (m_Size.x - m_Size.y) / 2; delta = (m_Size.x - m_Size.y) / 2;
radius = m_Size.y / 2; radius = m_Size.y / 2;
} }
else // vertical oval else // vertical oval
@ -537,47 +510,85 @@ void D_CODE::ConvertShapeToPolygon()
currpos.x -= delta; currpos.x -= delta;
m_PolyCorners.push_back( currpos ); m_PolyCorners.push_back( currpos );
} }
m_PolyCorners.push_back( initialpos ); // close outline m_PolyCorners.push_back( initialpos ); // close outline
if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon. if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
{ {
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
RotatePoint( &m_PolyCorners[jj], 900 ); RotatePoint( &m_PolyCorners[jj], 900 );
} }
if( m_DrillShape == 1 ) // build a round hole
{ addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
for( ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = 0;
currpos.y = m_Drill.x / 2; // m_Drill.x / 2 is the radius of the hole
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
} }
break; break;
case APT_POLYGON: case APT_POLYGON:
// TODO currpos.x = m_Size.x >> 1; // first point is on X axis
initialpos = currpos;
// rs274x said: m_EdgesCount = 3 ... 12
if( m_EdgesCount < 3 )
m_EdgesCount = 3;
if( m_EdgesCount > 12 )
m_EdgesCount = 12;
for( int ii = 0; ii <= m_EdgesCount; ii++ )
{
currpos = initialpos;
RotatePoint( &currpos, ii * 3600 / m_EdgesCount );
m_PolyCorners.push_back( currpos );
}
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
if( m_Rotation ) // vertical oval, rotate polygon.
{
int angle = wxRound( m_Rotation*10 );
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
{
// Remember the Y axis is from top to bottom when draw items.
RotatePoint( &m_PolyCorners[jj], -angle );
NEGATE(m_PolyCorners[jj].y);
}
}
break; break;
case APT_MACRO: case APT_MACRO:
// TODO // TODO
break; break;
} }
} }
// The helper function for D_CODE::ConvertShapeToPolygon().
// Add a hole to a polygon
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
APERTURE_DEF_HOLETYPE aHoleShape,
wxSize aSize,
wxPoint aAnchorPos )
{
wxPoint currpos;
if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole
{
for( int ii = 0; ii <= SEGS_CNT; ii++ )
{
currpos.x = 0;
currpos.y = aSize.x / 2; // aSize.x / 2 is the radius of the hole
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
aBuffer.push_back( currpos );
}
aBuffer.push_back( aAnchorPos ); // link to outline
}
if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole
{
currpos.x = aSize.x / 2;
currpos.y = aSize.y / 2;
aBuffer.push_back( currpos ); // link to hole and begin hole
currpos.x -= aSize.x;
aBuffer.push_back( currpos );
currpos.y -= aSize.y;
aBuffer.push_back( currpos );
currpos.x += aSize.x;
aBuffer.push_back( currpos );
currpos.y += aSize.y;
aBuffer.push_back( currpos ); // close hole
aBuffer.push_back( aAnchorPos ); // link to outline
}
}

View File

@ -16,20 +16,30 @@
* is the set of all gerber aperture types allowed, according to page 16 of * is the set of all gerber aperture types allowed, according to page 16 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf * http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/ */
enum APERTURE_T enum APERTURE_T {
{ APT_CIRCLE = 'C',
APT_CIRCLE = 'C', APT_LINE = 'L',
APT_LINE = 'L', APT_RECT = 'R',
APT_RECT = 'R', APT_OVAL = '0',
APT_OVAL = '0',
APT_POLYGON = 'P', APT_POLYGON = 'P',
APT_MACRO = 'M' APT_MACRO = 'M'
}; };
// In aperture definition, round, oval and rectangular flashed shapes
// can have a hole (ropund or rectangular)
// this option is stored in .m_DrillShape D_CODE member
enum APERTURE_DEF_HOLETYPE {
APT_DEF_NO_HOLE = 0,
APT_DEF_ROUND_HOLE,
APT_DEF_RECT_HOLE
};
#define FIRST_DCODE 10 /* define min and max values for D Codes values.
#define LAST_DCODE 999 // dcodes values are from 10 to 999 * note: values >= 0 and > FIRST_DCODE can be used for specila purposes
#define TOOLS_MAX_COUNT (LAST_DCODE+1) */
#define FIRST_DCODE 10
#define LAST_DCODE 999
#define TOOLS_MAX_COUNT (LAST_DCODE + 1)
class D_CODE; class D_CODE;
@ -46,17 +56,19 @@ class DCODE_PARAM
{ {
public: public:
DCODE_PARAM() : DCODE_PARAM() :
index(-1), index( -1 ),
value(0.0) value( 0.0 )
{} {}
double GetValue( const D_CODE* aDcode ) const; double GetValue( const D_CODE* aDcode ) const;
void SetValue( double aValue ) void SetValue( double aValue )
{ {
value = aValue; value = aValue;
index = -1; index = -1;
} }
/** /**
* Function IsImmediate * Function IsImmediate
* tests if this DCODE_PARAM holds an immediate parameter or is a pointer * tests if this DCODE_PARAM holds an immediate parameter or is a pointer
@ -69,16 +81,18 @@ public:
return (unsigned) index; return (unsigned) index;
} }
void SetIndex( int aIndex ) void SetIndex( int aIndex )
{ {
index = aIndex; index = aIndex;
} }
private: private:
int index; ///< if -1, then \a value field is an immediate value, int index; ///< if -1, then \a value field is an immediate value,
// else this is an index into parent's // else this is an index into parent's
// D_CODE.m_am_params. // D_CODE.m_am_params.
double value; ///< if IsImmediate()==true then use the value, else double value; ///< if IsImmediate()==true then use the value, else
// not used. // not used.
}; };
@ -88,22 +102,21 @@ private:
* is the set of all "aperture macro primitives" (primitive numbers). See * is the set of all "aperture macro primitives" (primitive numbers). See
* Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf * Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/ */
enum AM_PRIMITIVE_ID enum AM_PRIMITIVE_ID {
{ AMP_CIRCLE = 1,
AMP_CIRCLE = 1, AMP_LINE2 = 2,
AMP_LINE2 = 2,
AMP_LINE20 = 20, AMP_LINE20 = 20,
AMP_LINE_CENTER = 21, AMP_LINE_CENTER = 21,
AMP_LINE_LOWER_LEFT = 22, AMP_LINE_LOWER_LEFT = 22,
AMP_EOF = 3, AMP_EOF = 3,
AMP_OUTLINE = 4, AMP_OUTLINE = 4,
AMP_POLYGON = 5, AMP_POLYGON = 5,
AMP_MOIRE = 6, AMP_MOIRE = 6,
AMP_THERMAL = 7, AMP_THERMAL = 7,
}; };
typedef std::vector<DCODE_PARAM> DCODE_PARAMS; typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
/** /**
* Struct AM_PRIMITIVE * Struct AM_PRIMITIVE
@ -112,8 +125,8 @@ typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
*/ */
struct AM_PRIMITIVE struct AM_PRIMITIVE
{ {
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 DCODE_PARAMS params; ///< A sequence of parameters used by
// the primitive // the primitive
/** /**
@ -130,7 +143,7 @@ struct AM_PRIMITIVE
}; };
typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES; typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES;
/** /**
* Struct APERTURE_MACRO * Struct APERTURE_MACRO
@ -138,8 +151,8 @@ typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES;
*/ */
struct APERTURE_MACRO struct APERTURE_MACRO
{ {
wxString name; ///< The name of the aperture macro wxString name; ///< The name of the aperture macro
AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs
}; };
@ -151,7 +164,7 @@ struct APERTURE_MACRO
struct APERTURE_MACRO_less_than struct APERTURE_MACRO_less_than
{ {
// a "less than" test on two APERTURE_MACROs (.name wxStrings) // a "less than" test on two APERTURE_MACROs (.name wxStrings)
bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2) const bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2 ) const
{ {
return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare
} }
@ -163,8 +176,8 @@ struct APERTURE_MACRO_less_than
* is a sorted collection of APERTURE_MACROS whose key is the name field in * is a sorted collection of APERTURE_MACROS whose key is the name field in
* the APERTURE_MACRO. * the APERTURE_MACRO.
*/ */
typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET; typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET;
typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR; typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR;
/** /**
@ -182,7 +195,7 @@ class D_CODE
* 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; DCODE_PARAMS m_am_params;
std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw AMP_POLYGON shape and some other std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw AMP_POLYGON shape and some other
* complex shapes which are converted to polygon * complex shapes which are converted to polygon
@ -190,15 +203,16 @@ class D_CODE
*/ */
public: public:
wxSize m_Size; /* Horizontal and vertical dimensions. */ wxSize m_Size; /* Horizontal and vertical dimensions. */
APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */ APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */
int m_Num_Dcode; /* D code ( >= 10 ) */ int m_Num_Dcode; /* D code ( >= 10 ) */
wxSize m_Drill; /* dimension of the hole (if any) */ wxSize m_Drill; /* dimension of the hole (if any) */
int m_DrillShape; /* shape of the hole (round = 1, rect = 2) */ APERTURE_DEF_HOLETYPE m_DrillShape; /* shape of the hole (0 = no hole, round = 1, rect = 2) */
double m_Rotation; /* shape rotation in degrees */ double m_Rotation; /* shape rotation in degrees */
bool m_InUse; /* FALSE if not used */ int m_EdgesCount; /* in apeture definition Polygon only: number of edges for the polygon */
bool m_Defined; /* FALSE if not defined */ bool m_InUse; /* FALSE if not used */
wxString m_SpecialDescr; bool m_Defined; /* FALSE if not defined */
wxString m_SpecialDescr;
public: public:
D_CODE( int num_dcode ); D_CODE( int num_dcode );
@ -214,10 +228,13 @@ public:
m_am_params.push_back( param ); m_am_params.push_back( param );
} }
void SetMacro( APERTURE_MACRO* aMacro ) void SetMacro( APERTURE_MACRO* aMacro )
{ {
m_Macro = aMacro; m_Macro = aMacro;
} }
APERTURE_MACRO* GetMacro() { return m_Macro; } APERTURE_MACRO* GetMacro() { return m_Macro; }
/** /**
@ -231,8 +248,8 @@ public:
* Draw the dcode shape for flashed items. * Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item * When an item is flashed, the DCode shape is the shape of the item
*/ */
void DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, void DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
wxPoint aShapePos, bool aFilledShape ); wxPoint aShapePos, bool aFilledShape );
/** function DrawFlashedPolygon /** function DrawFlashedPolygon
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners * a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
@ -240,8 +257,8 @@ public:
* APT_POLYGON is always a polygon, but some complex shapes are also converted to * APT_POLYGON is always a polygon, but some complex shapes are also converted to
* polygons (shapes with holes, some rotated shapes) * polygons (shapes with holes, some rotated shapes)
*/ */
void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor, void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
bool aFilled, const wxPoint& aPosition ); bool aFilled, const wxPoint& aPosition );
/** function ConvertShapeToPolygon /** function ConvertShapeToPolygon
* convert a shape to an equivalent polygon. * convert a shape to an equivalent polygon.
@ -249,8 +266,7 @@ public:
* Useful when a shape is not a graphic primitive (shape with hole, * Useful when a shape is not a graphic primitive (shape with hole,
* rotated shape ... ) and cannot be easily drawn. * rotated shape ... ) and cannot be easily drawn.
*/ */
void ConvertShapeToPolygon( ); void ConvertShapeToPolygon();
}; };
@ -262,13 +278,14 @@ inline double DCODE_PARAM::GetValue( const D_CODE* aDcode ) const
{ {
// the first one was numbered 1, not zero, as in $1, see page 19 of spec. // the first one was numbered 1, not zero, as in $1, see page 19 of spec.
unsigned ndx = GetIndex() - 1; unsigned ndx = GetIndex() - 1;
wxASSERT(aDcode); wxASSERT( aDcode );
// get the parameter from the aDcode // get the parameter from the aDcode
if( ndx < aDcode->m_am_params.size() ) if( ndx < aDcode->m_am_params.size() )
return aDcode->m_am_params[ndx].GetValue( NULL ); return aDcode->m_am_params[ndx].GetValue( NULL );
else else
{ {
wxASSERT( GetIndex()-1 < aDcode->m_am_params.size() ); wxASSERT( GetIndex() - 1 < aDcode->m_am_params.size() );
return 0.0; return 0.0;
} }
} }

View File

@ -1095,6 +1095,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
switch( aperture ) switch( aperture )
{ {
case APT_POLYGON: // flashed regular polygon
case APT_CIRCLE: case APT_CIRCLE:
gbritem = new GERBER_DRAW_ITEM( pcb ); gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem ); pcb->m_Drawings.Append( gbritem );
@ -1102,6 +1103,8 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer, fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size.x, m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) ); !(m_LayerNegative ^ m_ImageNegative) );
if( aperture == APT_POLYGON )
gbritem->m_Shape = GBR_SPOT_POLY;
break; break;
case APT_OVAL: case APT_OVAL:

View File

@ -360,10 +360,13 @@ bool GERBER::ExecuteRS274XCommand( int command,
break; break;
case AP_DEFINITION: case AP_DEFINITION:
/* input example: %ADD30R,0.081800X0.101500*%
// input example: %ADD30R,0.081800X0.101500*% * Aperture definition has 4 options: C, R, O, P
// at this point, text points to 2nd 'D' * (Circle, Rect, Oval, regular Polygon)
* and shapes can have a hole (round or rectangular).
* All optional parameters values start by X
* at this point, text points to 2nd 'D'
*/
if( *text++ != 'D' ) if( *text++ != 'D' )
{ {
ok = FALSE; ok = FALSE;
@ -391,7 +394,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
dcode->m_Size.x = dcode->m_Size.y = dcode->m_Size.x = dcode->m_Size.y =
wxRound( ReadDouble( text ) * conv_scale ); wxRound( ReadDouble( text ) * conv_scale );
switch( stdAperture ) switch( stdAperture ) // Aperture desceiption has optional parameters. Read them
{ {
case 'C': // Circle case 'C': // Circle
dcode->m_Shape = APT_CIRCLE; dcode->m_Shape = APT_CIRCLE;
@ -403,7 +406,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
text++; text++;
dcode->m_Drill.x = dcode->m_Drill.y = dcode->m_Drill.x = dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale ); wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = 1; dcode->m_DrillShape = APT_DEF_ROUND_HOLE;
} }
while( *text == ' ' ) while( *text == ' ' )
@ -415,7 +418,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
dcode->m_Drill.y = dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale ); wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = 2; dcode->m_DrillShape = APT_DEF_RECT_HOLE;
} }
dcode->m_Defined = TRUE; dcode->m_Defined = TRUE;
break; break;
@ -442,7 +445,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
text++; text++;
dcode->m_Drill.x = dcode->m_Drill.y = dcode->m_Drill.x = dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale ); wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = 1; dcode->m_DrillShape = APT_DEF_ROUND_HOLE;
} }
while( *text == ' ' ) while( *text == ' ' )
@ -453,14 +456,56 @@ bool GERBER::ExecuteRS274XCommand( int command,
text++; text++;
dcode->m_Drill.y = dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale ); wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = 2; dcode->m_DrillShape = APT_DEF_RECT_HOLE;
} }
dcode->m_Defined = TRUE; dcode->m_Defined = TRUE;
break; break;
case 'P': // Polygon case 'P':
dcode->m_Shape = APT_POLYGON; /* Regular polygon: a command line like %ADD12P,0.040X10X25X0.025X0.025X0.0150*%
dcode->m_Defined = TRUE; * params are: <diameter>, X<edge count>, X<Rotation>, X<X hole dim>, X<Y hole dim>
*/
dcode->m_Shape = APT_POLYGON;
while( *text == ' ' )
text++;
if( *text == 'X' )
{
text++;
dcode->m_EdgesCount = ReadInt( text );
}
while( *text == ' ' )
text++;
if( *text == 'X' )
{
text++;
dcode->m_Rotation = ReadDouble( text );
}
while( *text == ' ' )
text++;
if( *text == 'X' )
{
text++;
dcode->m_Drill.x = dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = APT_DEF_ROUND_HOLE;
}
while( *text == ' ' )
text++;
if( *text == 'X' )
{
text++;
dcode->m_Drill.y =
wxRound( ReadDouble( text ) * conv_scale );
dcode->m_DrillShape = APT_DEF_RECT_HOLE;
}
dcode->m_Defined = TRUE;
break; break;
} }
} }