KiCad PCB EDA Suite
dcode.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <common.h>
33 #include <class_drawpanel.h>
34 #include <trigo.h>
35 
36 #include <gerbview_frame.h>
38 #include <convert_to_biu.h>
39 
40 #define DCODE_DEFAULT_SIZE Millimeter2iu( 0.1 )
41 
42 /* Format Gerber: NOTES:
43  * Tools and D_CODES
44  * tool number (identification of shapes)
45  * 1 to 999
46  *
47  * D_CODES:
48  * D01 ... D9 = command codes:
49  * D01 = activating light (pen down) while moving
50  * D02 = light extinction (pen up) while moving
51  * D03 = Flash
52  * D04 to D09 = non used
53  * D10 ... D999 = Identification Tool (Shape id)
54  *
55  * For tools defining a shape):
56  * DCode min = D10
57  * DCode max = 999
58  */
59 
60 
61 /***************/
62 /* Class DCODE */
63 /***************/
64 
65 
66 D_CODE::D_CODE( int num_dcode )
67 {
68  m_Num_Dcode = num_dcode;
70 }
71 
72 
74 {
75 }
76 
77 
79 {
83  m_Drill.x = m_Drill.y = 0;
85  m_InUse = false;
86  m_Defined = false;
87  m_Macro = NULL;
88  m_Rotation = 0.0;
89  m_EdgesCount = 0;
90  m_PolyCorners.clear();
91 }
92 
93 
94 const wxChar* D_CODE::ShowApertureType( APERTURE_T aType )
95 {
96  const wxChar* ret;
97 
98  switch( aType )
99  {
100  case APT_CIRCLE:
101  ret = wxT( "Round" ); break;
102 
103  case APT_RECT:
104  ret = wxT( "Rect" ); break;
105 
106  case APT_OVAL:
107  ret = wxT( "Oval" ); break;
108 
109  case APT_POLYGON:
110  ret = wxT( "Poly" ); break;
111 
112  case APT_MACRO:
113  ret = wxT( "Macro" ); break;
114 
115  default:
116  ret = wxT( "???" ); break;
117  }
118 
119  return ret;
120 }
121 
123 {
124  int dim = -1;
125  switch( m_Shape )
126  {
127  case APT_CIRCLE:
128  dim = m_Size.x;
129  break;
130 
131  case APT_RECT:
132  case APT_OVAL:
133  dim = std::min( m_Size.x, m_Size.y );
134  break;
135 
136  case APT_POLYGON:
137  dim = std::min( m_Size.x, m_Size.y );
138  break;
139 
140  case APT_MACRO:
141  if( m_Macro )
142  dim = m_Macro->GetShapeDim( aParent );
143  break;
144 
145  default:
146  break;
147  }
148 
149  return dim;
150 }
151 
152 
154  EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor,
155  wxPoint aShapePos, bool aFilledShape )
156 {
157  int radius;
158 
159  switch( m_Shape )
160  {
161  case APT_MACRO:
162  GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor,
163  aShapePos, aFilledShape);
164  break;
165 
166  case APT_CIRCLE:
167  radius = m_Size.x >> 1;
168  if( !aFilledShape )
169  GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor );
170  else
172  {
173  GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
174  radius, aColor );
175  }
176  else if( APT_DEF_ROUND_HOLE == 1 ) // round hole in shape
177  {
178  int width = (m_Size.x - m_Drill.x ) / 2;
179  GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
180  radius - (width / 2), width, aColor );
181  }
182  else // rectangular hole
183  {
184  if( m_PolyCorners.size() == 0 )
186 
187  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
188  }
189  break;
190 
191  case APT_RECT:
192  {
193  wxPoint start;
194  start.x = aShapePos.x - m_Size.x / 2;
195  start.y = aShapePos.y - m_Size.y / 2;
196  wxPoint end = start + m_Size;
197  start = aParent->GetABPosition( start );
198  end = aParent->GetABPosition( end );
199 
200  if( !aFilledShape )
201  {
202  GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor );
203  }
204  else if( m_DrillShape == APT_DEF_NO_HOLE )
205  {
206  GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor );
207  }
208  else
209  {
210  if( m_PolyCorners.size() == 0 )
212 
213  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
214  }
215  }
216  break;
217 
218  case APT_OVAL:
219  {
220  wxPoint start = aShapePos;
221  wxPoint end = aShapePos;
222 
223  if( m_Size.x > m_Size.y ) // horizontal oval
224  {
225  int delta = (m_Size.x - m_Size.y) / 2;
226  start.x -= delta;
227  end.x += delta;
228  radius = m_Size.y;
229  }
230  else // horizontal oval
231  {
232  int delta = (m_Size.y - m_Size.x) / 2;
233  start.y -= delta;
234  end.y += delta;
235  radius = m_Size.x;
236  }
237 
238  start = aParent->GetABPosition( start );
239  end = aParent->GetABPosition( end );
240 
241  if( !aFilledShape )
242  {
243  GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
244  }
245  else if( m_DrillShape == APT_DEF_NO_HOLE )
246  {
247  GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
248  }
249  else
250  {
251  if( m_PolyCorners.size() == 0 )
253 
254  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
255  }
256  }
257  break;
258 
259  case APT_POLYGON:
260  if( m_PolyCorners.size() == 0 )
262 
263  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
264  break;
265  }
266 }
267 
268 
270  EDA_RECT* aClipBox, wxDC* aDC,
271  COLOR4D aColor, bool aFilled,
272  const wxPoint& aPosition )
273 {
274  if( m_PolyCorners.size() == 0 )
275  return;
276 
277  std::vector<wxPoint> points;
278  points = m_PolyCorners;
279 
280  for( unsigned ii = 0; ii < points.size(); ii++ )
281  {
282  points[ii] += aPosition;
283  points[ii] = aParent->GetABPosition( points[ii] );
284  }
285 
286  GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilled, aColor, aColor );
287 }
288 
289 
290 #define SEGS_CNT 32 // number of segments to approximate a circle
291 
292 
293 // A helper function for D_CODE::ConvertShapeToPolygon(). Add a hole to a polygon
294 static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
295  APERTURE_DEF_HOLETYPE aHoleShape,
296  wxSize aSize,
297  wxPoint aAnchorPos );
298 
299 
301 {
302  wxPoint initialpos;
303  wxPoint currpos;
304 
305  m_PolyCorners.clear();
306 
307  switch( m_Shape )
308  {
309  case APT_CIRCLE: // creates only a circle with rectangular hole
310  currpos.x = m_Size.x >> 1;
311  initialpos = currpos;
312 
313  for( unsigned ii = 0; ii <= SEGS_CNT; ii++ )
314  {
315  currpos = initialpos;
316  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
317  m_PolyCorners.push_back( currpos );
318  }
319 
321  break;
322 
323  case APT_RECT:
324  currpos.x = m_Size.x / 2;
325  currpos.y = m_Size.y / 2;
326  initialpos = currpos;
327  m_PolyCorners.push_back( currpos );
328  currpos.x -= m_Size.x;
329  m_PolyCorners.push_back( currpos );
330  currpos.y -= m_Size.y;
331  m_PolyCorners.push_back( currpos );
332  currpos.x += m_Size.x;
333  m_PolyCorners.push_back( currpos );
334  currpos.y += m_Size.y;
335  m_PolyCorners.push_back( currpos ); // close polygon
336 
338  break;
339 
340  case APT_OVAL:
341  {
342  int delta, radius;
343 
344  // we create an horizontal oval shape. then rotate if needed
345  if( m_Size.x > m_Size.y ) // horizontal oval
346  {
347  delta = (m_Size.x - m_Size.y) / 2;
348  radius = m_Size.y / 2;
349  }
350  else // vertical oval
351  {
352  delta = (m_Size.y - m_Size.x) / 2;
353  radius = m_Size.x / 2;
354  }
355 
356  currpos.y = radius;
357  initialpos = currpos;
358  m_PolyCorners.push_back( currpos );
359 
360  // build the right arc of the shape
361  unsigned ii = 0;
362 
363  for( ; ii <= SEGS_CNT / 2; ii++ )
364  {
365  currpos = initialpos;
366  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
367  currpos.x += delta;
368  m_PolyCorners.push_back( currpos );
369  }
370 
371  // build the left arc of the shape
372  for( ii = SEGS_CNT / 2; ii <= SEGS_CNT; ii++ )
373  {
374  currpos = initialpos;
375  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
376  currpos.x -= delta;
377  m_PolyCorners.push_back( currpos );
378  }
379 
380  m_PolyCorners.push_back( initialpos ); // close outline
381 
382  if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
383  {
384  for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
385  RotatePoint( &m_PolyCorners[jj], 900 );
386  }
387 
389  }
390  break;
391 
392  case APT_POLYGON:
393  currpos.x = m_Size.x >> 1; // first point is on X axis
394  initialpos = currpos;
395 
396  // rs274x said: m_EdgesCount = 3 ... 12
397  if( m_EdgesCount < 3 )
398  m_EdgesCount = 3;
399 
400  if( m_EdgesCount > 12 )
401  m_EdgesCount = 12;
402 
403  for( int ii = 0; ii <= m_EdgesCount; ii++ )
404  {
405  currpos = initialpos;
406  RotatePoint( &currpos, ii * 3600.0 / m_EdgesCount );
407  m_PolyCorners.push_back( currpos );
408  }
409 
411 
412  if( m_Rotation ) // vertical oval, rotate polygon.
413  {
414  int angle = KiROUND( m_Rotation * 10 );
415 
416  for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
417  {
418  RotatePoint( &m_PolyCorners[jj], -angle );
419  }
420  }
421 
422  break;
423 
424  case APT_MACRO:
425 
426  // TODO
427  break;
428  }
429 }
430 
431 
432 // The helper function for D_CODE::ConvertShapeToPolygon().
433 // Add a hole to a polygon
434 static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
435  APERTURE_DEF_HOLETYPE aHoleShape,
436  wxSize aSize,
437  wxPoint aAnchorPos )
438 {
439  wxPoint currpos;
440 
441  if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole
442  {
443  for( int ii = 0; ii <= SEGS_CNT; ii++ )
444  {
445  currpos.x = 0;
446  currpos.y = aSize.x / 2; // aSize.x / 2 is the radius of the hole
447  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
448  aBuffer.push_back( currpos );
449  }
450 
451  aBuffer.push_back( aAnchorPos ); // link to outline
452  }
453 
454  if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole
455  {
456  currpos.x = aSize.x / 2;
457  currpos.y = aSize.y / 2;
458  aBuffer.push_back( currpos ); // link to hole and begin hole
459  currpos.x -= aSize.x;
460  aBuffer.push_back( currpos );
461  currpos.y -= aSize.y;
462  aBuffer.push_back( currpos );
463  currpos.x += aSize.x;
464  aBuffer.push_back( currpos );
465  currpos.y += aSize.y;
466  aBuffer.push_back( currpos ); // close hole
467  aBuffer.push_back( aAnchorPos ); // link to outline
468  }
469 }
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
wxSize m_Size
Horizontal and vertical dimensions.
Definition: dcode.h:98
Definition: dcode.h:52
bool m_InUse
false if the aperure (previously defined) is not used to draw something
Definition: dcode.h:106
APERTURE_T m_Shape
shape ( Line, rectangle, circle , oval .. )
Definition: dcode.h:99
void DrawApertureMacroShape(GERBER_DRAW_ITEM *aParent, EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape)
Function DrawApertureMacroShape Draw the primitive shape for flashed items.
double m_Rotation
shape rotation in degrees
Definition: dcode.h:103
APERTURE_MACRO * m_Macro
no ownership, points to
Definition: dcode.h:84
void GRFilledRect(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:1117
wxSize m_Drill
dimension of the hole (if any) (draill file)
Definition: dcode.h:101
#define DCODE_DEFAULT_SIZE
Definition: dcode.cpp:40
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:481
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:833
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, COLOR4D Color, COLOR4D BgColor)
Function GRClosedPoly draws a closed polygon onto the drawing context aDC and optionally fills and/or...
Definition: gr_basic.cpp:777
static const int delta[8][2]
Definition: solve.cpp:112
Definition: dcode.h:51
APERTURE_DEF_HOLETYPE
Definition: dcode.h:61
bool m_Defined
false if the aperture is not defined in the header
Definition: dcode.h:108
D_CODE(int num_dcode)
Definition: dcode.cpp:66
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1077
std::vector< wxPoint > m_PolyCorners
Definition: dcode.h:92
void GRFillCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:584
APERTURE_T
Enum APERTURE_T is the set of all gerber aperture types allowed, according to page 16 of http://gerbv...
Definition: dcode.h:49
int m_Num_Dcode
D code value ( >= 10 )
Definition: dcode.h:100
#define SEGS_CNT
Definition: dcode.cpp:290
static const wxChar * ShowApertureType(APERTURE_T aType)
Function ShowApertureType returns a character string telling what type of aperture type aType is...
Definition: dcode.cpp:94
void DrawFlashedPolygon(GERBER_DRAW_ITEM *aParent, EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, bool aFilled, const wxPoint &aPosition)
Function DrawFlashedPolygon a helper function used to draw the polygon stored ion m_PolyCorners Draw ...
Definition: dcode.cpp:269
APERTURE_DEF_HOLETYPE m_DrillShape
shape of the hole (0 = no hole, round = 1, rect = 2) */
Definition: dcode.h:102
void DrawFlashedShape(GERBER_DRAW_ITEM *aParent, EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape)
Function DrawFlashedShape Draw the dcode shape for flashed items.
Definition: dcode.cpp:153
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:791
Class EDA_RECT handles the component boundary box.
int m_EdgesCount
in aperture definition Polygon only: number of edges for the polygon
Definition: dcode.h:104
The common library.
static void addHoleToPolygon(std::vector< wxPoint > &aBuffer, APERTURE_DEF_HOLETYPE aHoleShape, wxSize aSize, wxPoint aAnchorPos)
Definition: dcode.cpp:434
APERTURE_MACRO * GetMacro() const
Definition: dcode.h:158
void ConvertShapeToPolygon()
Function ConvertShapeToPolygon convert a shape to an equivalent polygon.
Definition: dcode.cpp:300
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
Function GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying ...
wxPoint GetABPosition(const wxPoint &aXYPosition) const
Function GetABPosition returns the image position of aPosition for this object.
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
Function GetShapeDim calculates a value that can be used to evaluate the size of text when displaying...
Definition: dcode.cpp:122
~D_CODE()
Definition: dcode.cpp:73
void Clear_D_CODE_Data()
Definition: dcode.cpp:78
#define min(a, b)
Definition: auxiliary.h:85
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39