From d696ee8cd5d45319b2accc2ddae45e6184a5151e Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 28 Sep 2010 21:34:16 +0200 Subject: [PATCH] Gerbview: added support og regular polygon aperure definition. --- CHANGELOG.txt | 3 +- gerbview/class_gerber_draw_item.cpp | 6 +- gerbview/class_gerber_draw_item.h | 3 +- gerbview/dcode.cpp | 219 +++++++++++++++------------- gerbview/dcode.h | 113 ++++++++------ gerbview/rs274d.cpp | 3 + gerbview/rs274x.cpp | 69 +++++++-- 7 files changed, 248 insertions(+), 168 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 601af8914a..29d9d4dd2f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -12,12 +12,11 @@ email address. graphics items are now specific to gerbview (added a GERBER_DRAW_ITEM class) and do not use tracks from pcbnew. 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) Aperture definition type Polygon is not yet handle. Polygons are correctly drawn. TODO: - Draw functions for aperture definition type Polygon. Draw functions for aperture macros. Work in progress. diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 43ab9508ec..6a680df124 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -106,10 +106,13 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape() case GBR_SPOT_RECT: return wxT( "spot_rect" ); + case GBR_SPOT_POLY: + return wxT( "spot_poly" ); + case GBR_POLYGON: return wxT( "polygon" ); - case GBR_MACRO: + case GBR_SPOT_MACRO: return wxT( "apt_macro" ); // TODO: add aperture macro name 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_RECT: case GBR_SPOT_OVAL: + case GBR_SPOT_POLY: isFilled = DisplayOpt.DisplayPadFill ? true : false; d_codeDescr->DrawFlashedShape( &panel->m_ClipBox, DC, color, m_Start, isFilled ); diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index b5878d0df5..1d30606ba4 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -40,7 +40,8 @@ enum Gbr_Basic_Shapes { GBR_SPOT_CIRCLE, // flashed shape: round shape (can have hole) GBR_SPOT_RECT, // flashed shape: rectangular shape can have hole) 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 }; diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index 57e6df2b84..f4bc08b464 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -56,11 +56,12 @@ void D_CODE::Clear_D_CODE_Data() m_Size.y = DEFAULT_SIZE; m_Shape = APT_CIRCLE; m_Drill.x = m_Drill.y = 0; - m_DrillShape = 0; + m_DrillShape = APT_DEF_NO_HOLE; m_InUse = FALSE; m_Defined = FALSE; - m_Macro = 0; + m_Macro = NULL; 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 // gerber files use it - case APT_CIRCLE: /* spot round (for GERBER) */ + case APT_CIRCLE: /* spot round */ gerb_item->m_Shape = GBR_SPOT_CIRCLE; break; - case APT_OVAL: /* spot oval (for GERBER)*/ + case APT_OVAL: /* spot oval*/ gerb_item->m_Shape = GBR_SPOT_OVAL; break; - default: /* spot rect (for GERBER)*/ + case APT_RECT: /* spot rect*/ gerb_item->m_Shape = GBR_SPOT_RECT; 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 ) { + + case APT_MACRO: // TODO: current a round shape case APT_CIRCLE: radius = m_Size.x >> 1; if( !aFilledShape ) GRCircle( aClipBox, aDC, aShapePos.x, aShapePos.y, radius, aColor ); else - if( m_DrillShape == 0 ) + if( m_DrillShape == APT_DEF_NO_HOLE ) 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; 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; case APT_LINE: + // not used for flashed items break; case APT_RECT: { wxPoint start; - start.x = aShapePos.x - m_Size.x/2; - start.y = aShapePos.y - m_Size.y/2; + start.x = aShapePos.x - m_Size.x / 2; + start.y = aShapePos.y - m_Size.y / 2; wxPoint end = start + m_Size; 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 ); } - else if( m_DrillShape == 0 ) + else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor ); @@ -327,7 +343,7 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos ); } } - break; + break; 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, end.x, end.y, radius, aColor ); } - else if( m_DrillShape == 0 ) + else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); @@ -371,10 +387,6 @@ void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, ConvertShapeToPolygon(); DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos ); 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& aBuffer, + APERTURE_DEF_HOLETYPE aHoleShape, + wxSize aSize, + wxPoint aAnchorPos ); + /** function ConvertShapeToPolygon * convert a shape to an equivalent polygon. * Arcs and circles are approximated by segments @@ -411,7 +432,6 @@ void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, */ void D_CODE::ConvertShapeToPolygon() { - #define SEGS_CNT 32 // number of segments to approximate a circle wxPoint initialpos; wxPoint currpos;; m_PolyCorners.clear(); @@ -427,41 +447,18 @@ void D_CODE::ConvertShapeToPolygon() RotatePoint( &currpos, ii * 3600 / SEGS_CNT ); m_PolyCorners.push_back( currpos ); } - if( m_DrillShape == 1 ) - { - 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 - } + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); break; case APT_LINE: + // Not used for flashed shapes break; case APT_RECT: - currpos.x = m_Size.x / 2; - currpos.y = m_Size.y / 2; + currpos.x = m_Size.x / 2; + currpos.y = m_Size.y / 2; initialpos = currpos; m_PolyCorners.push_back( currpos ); currpos.x -= m_Size.x; @@ -471,33 +468,9 @@ void D_CODE::ConvertShapeToPolygon() currpos.x += m_Size.x; m_PolyCorners.push_back( currpos ); currpos.y += m_Size.y; - m_PolyCorners.push_back( currpos ); // close polygon - if( m_DrillShape == 1 ) // build a round hole - { - 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 - } + m_PolyCorners.push_back( currpos ); // close polygon + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); break; case APT_OVAL: @@ -507,7 +480,7 @@ void D_CODE::ConvertShapeToPolygon() // we create an horizontal oval shape. then rotate if needed 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; } else // vertical oval @@ -537,47 +510,85 @@ void D_CODE::ConvertShapeToPolygon() currpos.x -= delta; m_PolyCorners.push_back( currpos ); } + 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++ ) RotatePoint( &m_PolyCorners[jj], 900 ); } - if( m_DrillShape == 1 ) // build a round hole - { - 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 - } + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); } - break; + break; 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; - + case APT_MACRO: + // TODO break; } } + +// The helper function for D_CODE::ConvertShapeToPolygon(). +// Add a hole to a polygon +static void addHoleToPolygon( std::vector& 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 + } +} diff --git a/gerbview/dcode.h b/gerbview/dcode.h index 4ab2484145..edcd044581 100644 --- a/gerbview/dcode.h +++ b/gerbview/dcode.h @@ -16,20 +16,30 @@ * is the set of all gerber aperture types allowed, according to page 16 of * http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf */ -enum APERTURE_T -{ - APT_CIRCLE = 'C', - APT_LINE = 'L', - APT_RECT = 'R', - APT_OVAL = '0', +enum APERTURE_T { + APT_CIRCLE = 'C', + APT_LINE = 'L', + APT_RECT = 'R', + APT_OVAL = '0', 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 LAST_DCODE 999 // dcodes values are from 10 to 999 -#define TOOLS_MAX_COUNT (LAST_DCODE+1) +/* define min and max values for D Codes values. + * note: values >= 0 and > FIRST_DCODE can be used for specila purposes + */ +#define FIRST_DCODE 10 +#define LAST_DCODE 999 +#define TOOLS_MAX_COUNT (LAST_DCODE + 1) class D_CODE; @@ -46,17 +56,19 @@ class DCODE_PARAM { public: DCODE_PARAM() : - index(-1), - value(0.0) + index( -1 ), + value( 0.0 ) {} - double GetValue( const D_CODE* aDcode ) const; + 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 @@ -69,16 +81,18 @@ public: return (unsigned) index; } + void SetIndex( int aIndex ) { index = aIndex; } + 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 // 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. }; @@ -88,22 +102,21 @@ private: * is the set of all "aperture macro primitives" (primitive numbers). See * Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf */ -enum AM_PRIMITIVE_ID -{ - AMP_CIRCLE = 1, - AMP_LINE2 = 2, +enum AM_PRIMITIVE_ID { + AMP_CIRCLE = 1, + AMP_LINE2 = 2, AMP_LINE20 = 20, AMP_LINE_CENTER = 21, AMP_LINE_LOWER_LEFT = 22, - AMP_EOF = 3, + AMP_EOF = 3, AMP_OUTLINE = 4, AMP_POLYGON = 5, - AMP_MOIRE = 6, + AMP_MOIRE = 6, AMP_THERMAL = 7, }; -typedef std::vector DCODE_PARAMS; +typedef std::vector DCODE_PARAMS; /** * Struct AM_PRIMITIVE @@ -112,8 +125,8 @@ typedef std::vector DCODE_PARAMS; */ struct AM_PRIMITIVE { - AM_PRIMITIVE_ID primitive_id; ///< The primitive type - DCODE_PARAMS params; ///< A sequence of parameters used by + AM_PRIMITIVE_ID primitive_id; ///< The primitive type + DCODE_PARAMS params; ///< A sequence of parameters used by // the primitive /** @@ -130,7 +143,7 @@ struct AM_PRIMITIVE }; -typedef std::vector AM_PRIMITIVES; +typedef std::vector AM_PRIMITIVES; /** * Struct APERTURE_MACRO @@ -138,8 +151,8 @@ typedef std::vector AM_PRIMITIVES; */ struct APERTURE_MACRO { - wxString name; ///< The name of the aperture macro - AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs + wxString name; ///< The name of the aperture macro + AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs }; @@ -151,7 +164,7 @@ struct APERTURE_MACRO struct APERTURE_MACRO_less_than { // 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 } @@ -163,8 +176,8 @@ struct APERTURE_MACRO_less_than * is a sorted collection of APERTURE_MACROS whose key is the name field in * the APERTURE_MACRO. */ -typedef std::set APERTURE_MACRO_SET; -typedef std::pair APERTURE_MACRO_SET_PAIR; +typedef std::set APERTURE_MACRO_SET; +typedef std::pair APERTURE_MACRO_SET_PAIR; /** @@ -182,7 +195,7 @@ class D_CODE * parameters used only when this D_CODE holds a reference to an aperture * macro, and these parameters would customize the macro. */ - DCODE_PARAMS m_am_params; + DCODE_PARAMS m_am_params; std::vector m_PolyCorners; /* Polygon used to draw AMP_POLYGON shape and some other * complex shapes which are converted to polygon @@ -190,15 +203,16 @@ class D_CODE */ public: - wxSize m_Size; /* Horizontal and vertical dimensions. */ - APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */ - int m_Num_Dcode; /* D code ( >= 10 ) */ - wxSize m_Drill; /* dimension of the hole (if any) */ - int m_DrillShape; /* shape of the hole (round = 1, rect = 2) */ - double m_Rotation; /* shape rotation in degrees */ - bool m_InUse; /* FALSE if not used */ - bool m_Defined; /* FALSE if not defined */ - wxString m_SpecialDescr; + wxSize m_Size; /* Horizontal and vertical dimensions. */ + APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */ + int m_Num_Dcode; /* D code ( >= 10 ) */ + wxSize m_Drill; /* dimension of the hole (if any) */ + APERTURE_DEF_HOLETYPE m_DrillShape; /* shape of the hole (0 = no hole, round = 1, rect = 2) */ + double m_Rotation; /* shape rotation in degrees */ + int m_EdgesCount; /* in apeture definition Polygon only: number of edges for the polygon */ + bool m_InUse; /* FALSE if not used */ + bool m_Defined; /* FALSE if not defined */ + wxString m_SpecialDescr; public: D_CODE( int num_dcode ); @@ -214,10 +228,13 @@ public: m_am_params.push_back( param ); } + void SetMacro( APERTURE_MACRO* aMacro ) { m_Macro = aMacro; } + + APERTURE_MACRO* GetMacro() { return m_Macro; } /** @@ -231,8 +248,8 @@ public: * Draw the dcode shape for flashed items. * When an item is flashed, the DCode shape is the shape of the item */ - void DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, - wxPoint aShapePos, bool aFilledShape ); + void DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, + wxPoint aShapePos, bool aFilledShape ); /** function DrawFlashedPolygon * 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 * polygons (shapes with holes, some rotated shapes) */ - void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor, - bool aFilled, const wxPoint& aPosition ); + void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor, + bool aFilled, const wxPoint& aPosition ); /** function ConvertShapeToPolygon * convert a shape to an equivalent polygon. @@ -249,8 +266,7 @@ public: * Useful when a shape is not a graphic primitive (shape with hole, * 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. unsigned ndx = GetIndex() - 1; - wxASSERT(aDcode); + 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() ); + wxASSERT( GetIndex() - 1 < aDcode->m_am_params.size() ); return 0.0; } } diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp index dc6dbfe407..b5f62fe824 100644 --- a/gerbview/rs274d.cpp +++ b/gerbview/rs274d.cpp @@ -1095,6 +1095,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, switch( aperture ) { + case APT_POLYGON: // flashed regular polygon case APT_CIRCLE: gbritem = new GERBER_DRAW_ITEM( pcb ); pcb->m_Drawings.Append( gbritem ); @@ -1102,6 +1103,8 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, fillRoundFlashGBRITEM( gbritem, dcode, activeLayer, m_CurrentPos, size.x, !(m_LayerNegative ^ m_ImageNegative) ); + if( aperture == APT_POLYGON ) + gbritem->m_Shape = GBR_SPOT_POLY; break; case APT_OVAL: diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index b60f65209d..06e80acfec 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -360,10 +360,13 @@ bool GERBER::ExecuteRS274XCommand( int command, break; case AP_DEFINITION: - - // input example: %ADD30R,0.081800X0.101500*% - // at this point, text points to 2nd 'D' - + /* input example: %ADD30R,0.081800X0.101500*% + * Aperture definition has 4 options: C, R, O, P + * (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' ) { ok = FALSE; @@ -391,7 +394,7 @@ bool GERBER::ExecuteRS274XCommand( int command, dcode->m_Size.x = dcode->m_Size.y = wxRound( ReadDouble( text ) * conv_scale ); - switch( stdAperture ) + switch( stdAperture ) // Aperture desceiption has optional parameters. Read them { case 'C': // Circle dcode->m_Shape = APT_CIRCLE; @@ -403,7 +406,7 @@ bool GERBER::ExecuteRS274XCommand( int command, text++; dcode->m_Drill.x = dcode->m_Drill.y = wxRound( ReadDouble( text ) * conv_scale ); - dcode->m_DrillShape = 1; + dcode->m_DrillShape = APT_DEF_ROUND_HOLE; } while( *text == ' ' ) @@ -415,7 +418,7 @@ bool GERBER::ExecuteRS274XCommand( int command, dcode->m_Drill.y = wxRound( ReadDouble( text ) * conv_scale ); - dcode->m_DrillShape = 2; + dcode->m_DrillShape = APT_DEF_RECT_HOLE; } dcode->m_Defined = TRUE; break; @@ -442,7 +445,7 @@ bool GERBER::ExecuteRS274XCommand( int command, text++; dcode->m_Drill.x = dcode->m_Drill.y = wxRound( ReadDouble( text ) * conv_scale ); - dcode->m_DrillShape = 1; + dcode->m_DrillShape = APT_DEF_ROUND_HOLE; } while( *text == ' ' ) @@ -453,14 +456,56 @@ bool GERBER::ExecuteRS274XCommand( int command, text++; dcode->m_Drill.y = wxRound( ReadDouble( text ) * conv_scale ); - dcode->m_DrillShape = 2; + dcode->m_DrillShape = APT_DEF_RECT_HOLE; } dcode->m_Defined = TRUE; break; - case 'P': // Polygon - dcode->m_Shape = APT_POLYGON; - dcode->m_Defined = TRUE; + case 'P': + /* Regular polygon: a command line like %ADD12P,0.040X10X25X0.025X0.025X0.0150*% + * params are: , X, X, X, X + */ + 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; } }