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 <trigo.h>
34 #include <gerbview_frame.h>
35 #include <gerber_file_image.h>
36 #include <convert_to_biu.h>
38 
39 #define DCODE_DEFAULT_SIZE Millimeter2iu( 0.1 )
40 
41 /* Format Gerber: NOTES:
42  * Tools and D_CODES
43  * tool number (identification of shapes)
44  * 1 to 999
45  *
46  * D_CODES:
47  * D01 ... D9 = command codes:
48  * D01 = activating light (pen down) while moving
49  * D02 = light extinction (pen up) while moving
50  * D03 = Flash
51  * D04 to D09 = non used
52  * D10 ... D999 = Identification Tool (Shape id)
53  *
54  * For tools defining a shape):
55  * DCode min = D10
56  * DCode max = 999
57  */
58 
59 
60 /***************/
61 /* Class DCODE */
62 /***************/
63 
64 
65 D_CODE::D_CODE( int num_dcode )
66 {
67  m_Num_Dcode = num_dcode;
69 }
70 
71 
73 {
74 }
75 
76 
78 {
82  m_Drill.x = m_Drill.y = 0;
84  m_InUse = false;
85  m_Defined = false;
86  m_Macro = NULL;
87  m_Rotation = 0.0;
88  m_EdgesCount = 0;
90 }
91 
92 
93 const wxChar* D_CODE::ShowApertureType( APERTURE_T aType )
94 {
95  const wxChar* ret;
96 
97  switch( aType )
98  {
99  case APT_CIRCLE:
100  ret = wxT( "Round" ); break;
101 
102  case APT_RECT:
103  ret = wxT( "Rect" ); break;
104 
105  case APT_OVAL:
106  ret = wxT( "Oval" ); break;
107 
108  case APT_POLYGON:
109  ret = wxT( "Poly" ); break;
110 
111  case APT_MACRO:
112  ret = wxT( "Macro" ); break;
113 
114  default:
115  ret = wxT( "???" ); break;
116  }
117 
118  return ret;
119 }
120 
122 {
123  int dim = -1;
124  switch( m_Shape )
125  {
126  case APT_CIRCLE:
127  dim = m_Size.x;
128  break;
129 
130  case APT_RECT:
131  case APT_OVAL:
132  dim = std::min( m_Size.x, m_Size.y );
133  break;
134 
135  case APT_POLYGON:
136  dim = std::min( m_Size.x, m_Size.y );
137  break;
138 
139  case APT_MACRO:
140  if( m_Macro )
141  dim = m_Macro->GetShapeDim( aParent );
142  break;
143 
144  default:
145  break;
146  }
147 
148  return dim;
149 }
150 
151 
153  EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor,
154  wxPoint aShapePos, bool aFilledShape )
155 {
156  int radius;
157 
158  switch( m_Shape )
159  {
160  case APT_MACRO:
161  GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor,
162  aShapePos, aFilledShape);
163  break;
164 
165  case APT_CIRCLE:
166  radius = m_Size.x >> 1;
167  if( !aFilledShape )
168  GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor );
169  else
171  {
172  GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
173  radius, aColor );
174  }
175  else if( m_DrillShape == APT_DEF_ROUND_HOLE ) // round hole in shape
176  {
177  int width = (m_Size.x - m_Drill.x ) / 2;
178  GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
179  radius - (width / 2), width, aColor );
180  }
181  else // rectangular hole
182  {
183  if( m_Polygon.OutlineCount() == 0 )
185 
186  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
187  }
188  break;
189 
190  case APT_RECT:
191  {
192  wxPoint start;
193  start.x = aShapePos.x - m_Size.x / 2;
194  start.y = aShapePos.y - m_Size.y / 2;
195  wxPoint end = start + m_Size;
196  start = aParent->GetABPosition( start );
197  end = aParent->GetABPosition( end );
198 
199  if( !aFilledShape )
200  {
201  GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor );
202  }
203  else if( m_DrillShape == APT_DEF_NO_HOLE )
204  {
205  GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor );
206  }
207  else
208  {
209  if( m_Polygon.OutlineCount() == 0 )
211 
212  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
213  }
214  }
215  break;
216 
217  case APT_OVAL:
218  {
219  wxPoint start = aShapePos;
220  wxPoint end = aShapePos;
221 
222  if( m_Size.x > m_Size.y ) // horizontal oval
223  {
224  int delta = (m_Size.x - m_Size.y) / 2;
225  start.x -= delta;
226  end.x += delta;
227  radius = m_Size.y; // Width in fact
228  }
229  else // vertical oval
230  {
231  int delta = (m_Size.y - m_Size.x) / 2;
232  start.y -= delta;
233  end.y += delta;
234  radius = m_Size.x; // Width in fact
235  }
236 
237  start = aParent->GetABPosition( start );
238  end = aParent->GetABPosition( end );
239 
240  if( !aFilledShape )
241  {
242  GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
243  }
244  else if( m_DrillShape == APT_DEF_NO_HOLE )
245  {
246  GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
247  }
248  else
249  {
250  if( m_Polygon.OutlineCount() == 0 )
252 
253  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
254  }
255  }
256  break;
257 
258  case APT_POLYGON:
259  if( m_Polygon.OutlineCount() == 0 )
261 
262  DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
263  break;
264  }
265 }
266 
267 
269  EDA_RECT* aClipBox, wxDC* aDC,
270  COLOR4D aColor, bool aFilled,
271  const wxPoint& aPosition )
272 {
273  if( m_Polygon.OutlineCount() == 0 )
274  return;
275 
276  int pointCount = m_Polygon.VertexCount();
277  std::vector<wxPoint> points;
278  points.reserve( pointCount );
279 
280  for( int ii = 0; ii < pointCount; ii++ )
281  {
282  wxPoint p( m_Polygon.CVertex( ii ).x, m_Polygon.CVertex( ii ).y );
283  points[ii] = p + aPosition;
284  points[ii] = aParent->GetABPosition( points[ii] );
285  }
286 
287  GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilled, aColor, aColor );
288 }
289 
290 // TODO(snh): Remove the hard-coded count
291 #define SEGS_CNT 64 // number of segments to approximate a circle
292 
293 
294 // A helper function for D_CODE::ConvertShapeToPolygon(). Add a hole to a polygon
295 static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon,
296  APERTURE_DEF_HOLETYPE aHoleShape,
297  wxSize aSize,
298  wxPoint aAnchorPos );
299 
300 
302 {
303  wxPoint initialpos;
304  wxPoint currpos;
305 
307 
308  switch( m_Shape )
309  {
310  case APT_CIRCLE: // creates only a circle with rectangular hole
311  TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, ARC_HIGH_DEF );
313  break;
314 
315  case APT_RECT:
317  currpos.x = m_Size.x / 2;
318  currpos.y = m_Size.y / 2;
319  initialpos = currpos;
320  m_Polygon.Append( VECTOR2I( currpos ) );
321  currpos.x -= m_Size.x;
322  m_Polygon.Append( VECTOR2I( currpos ) );
323  currpos.y -= m_Size.y;
324  m_Polygon.Append( VECTOR2I( currpos ) );
325  currpos.x += m_Size.x;
326  m_Polygon.Append( VECTOR2I( currpos ) );
327  currpos.y += m_Size.y;
328  m_Polygon.Append( VECTOR2I( currpos ) ); // close polygon
329  m_Polygon.Append( VECTOR2I( initialpos ) );
330 
332  break;
333 
334  case APT_OVAL:
335  {
337  int delta, radius;
338 
339  // we create an horizontal oval shape. then rotate if needed
340  if( m_Size.x > m_Size.y ) // horizontal oval
341  {
342  delta = (m_Size.x - m_Size.y) / 2;
343  radius = m_Size.y / 2;
344  }
345  else // vertical oval
346  {
347  delta = (m_Size.y - m_Size.x) / 2;
348  radius = m_Size.x / 2;
349  }
350 
351  currpos.y = radius;
352  initialpos = currpos;
353  m_Polygon.Append( VECTOR2I( currpos ) );
354 
355  // build the right arc of the shape
356  unsigned ii = 0;
357 
358  for( ; ii <= SEGS_CNT / 2; ii++ )
359  {
360  currpos = initialpos;
361  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
362  currpos.x += delta;
363  m_Polygon.Append( VECTOR2I( currpos ) );
364  }
365 
366  // build the left arc of the shape
367  for( ii = SEGS_CNT / 2; ii <= SEGS_CNT; ii++ )
368  {
369  currpos = initialpos;
370  RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT );
371  currpos.x -= delta;
372  m_Polygon.Append( VECTOR2I( currpos ) );
373  }
374 
375  m_Polygon.Append( VECTOR2I( initialpos ) ); // close outline
376 
377  if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
378  m_Polygon.Rotate( -M_PI / 2 );
379 
381  }
382  break;
383 
384  case APT_POLYGON:
386  currpos.x = m_Size.x >> 1; // first point is on X axis
387  initialpos = currpos;
388 
389  // rs274x said: m_EdgesCount = 3 ... 12
390  if( m_EdgesCount < 3 )
391  m_EdgesCount = 3;
392 
393  if( m_EdgesCount > 12 )
394  m_EdgesCount = 12;
395 
396  for( int ii = 0; ii < m_EdgesCount; ii++ )
397  {
398  currpos = initialpos;
399  RotatePoint( &currpos, ii * 3600.0 / m_EdgesCount );
400  m_Polygon.Append( VECTOR2I( currpos ) );
401  }
402 
404 
405  if( m_Rotation ) // rotate polygonal shape:
406  {
407  double angle = m_Rotation * M_PI / 180;
408  m_Polygon.Rotate( angle, VECTOR2I( 0, 0 ) );
409  }
410 
411  break;
412 
413  case APT_MACRO:
414 
415  // TODO
416  break;
417  }
418 }
419 
420 
421 // The helper function for D_CODE::ConvertShapeToPolygon().
422 // Add a hole to a polygon
423 static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon,
424  APERTURE_DEF_HOLETYPE aHoleShape,
425  wxSize aSize,
426  wxPoint aAnchorPos )
427 {
428  wxPoint currpos;
429  SHAPE_POLY_SET holeBuffer;
430 
431  if( aHoleShape == APT_DEF_ROUND_HOLE )
432  {
433  TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, ARC_HIGH_DEF );
434  }
435  else if( aHoleShape == APT_DEF_RECT_HOLE )
436  {
437  holeBuffer.NewOutline();
438  currpos.x = aSize.x / 2;
439  currpos.y = aSize.y / 2;
440  holeBuffer.Append( VECTOR2I( currpos ) ); // link to hole and begin hole
441  currpos.x -= aSize.x;
442  holeBuffer.Append( VECTOR2I( currpos ) );
443  currpos.y -= aSize.y;
444  holeBuffer.Append( VECTOR2I( currpos ) );
445  currpos.x += aSize.x;
446  holeBuffer.Append( VECTOR2I( currpos ) );
447  currpos.y += aSize.y;
448  holeBuffer.Append( VECTOR2I( currpos ) ); // close hole
449  }
450 
451  aPolygon->BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
452  aPolygon->Fracture( SHAPE_POLY_SET::PM_FAST );
453 }
int OutlineCount() const
Returns the number of outlines in the set
static void addHoleToPolygon(SHAPE_POLY_SET *aPolygon, APERTURE_DEF_HOLETYPE aHoleShape, wxSize aSize, wxPoint aAnchorPos)
Definition: dcode.cpp:423
wxSize m_Size
Horizontal and vertical dimensions.
Definition: dcode.h:94
Definition: dcode.h:53
bool m_InUse
false if the aperure (previously defined) is not used to draw something
Definition: dcode.h:102
APERTURE_T m_Shape
shape ( Line, rectangle, circle , oval .. )
Definition: dcode.h:95
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.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
double m_Rotation
shape rotation in degrees
Definition: dcode.h:99
APERTURE_MACRO * m_Macro
no ownership, points to
Definition: dcode.h:85
void GRFilledRect(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:884
wxSize m_Drill
dimension of the hole (if any) (draill file)
Definition: dcode.h:97
int VertexCount(int aOutline=-1, int aHole=-1) const
Returns the number of vertices in a given outline/hole
#define DCODE_DEFAULT_SIZE
Definition: dcode.cpp:39
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:312
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
void GRFilledCircle(EDA_RECT *ClipBox, wxDC *DC, int x, int y, int r, int width, COLOR4D Color, COLOR4D BgColor)
Definition: gr_basic.cpp:619
Definition: dcode.h:52
APERTURE_DEF_HOLETYPE
Definition: dcode.h:62
bool m_Defined
false if the aperture is not defined in the header
Definition: dcode.h:104
D_CODE(int num_dcode)
Definition: dcode.cpp:65
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:844
wxPoint GetABPosition(const wxPoint &aXYPosition) const
Function GetABPosition returns the image position of aPosition for this object.
#define NULL
SHAPE_POLY_SET.
void GRFillCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:415
APERTURE_T
Enum APERTURE_T is the set of all gerber aperture types allowed, according to page 16 of http://gerbv...
Definition: dcode.h:50
int m_Num_Dcode
D code value ( >= 10 )
Definition: dcode.h:96
#define SEGS_CNT
Definition: dcode.cpp:291
static const wxChar * ShowApertureType(APERTURE_T aType)
Function ShowApertureType returns a character string telling what type of aperture type aType is.
Definition: dcode.cpp:93
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:268
int NewOutline()
Creates a new empty polygon in the set and returns its index
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
APERTURE_DEF_HOLETYPE m_DrillShape
shape of the hole (0 = no hole, round = 1, rect = 2) */
Definition: dcode.h:98
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:152
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:596
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aError)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
SHAPE_POLY_SET m_Polygon
Definition: dcode.h:107
int m_EdgesCount
in aperture definition Polygon only: number of edges for the polygon
Definition: dcode.h:100
The common library.
APERTURE_MACRO * GetMacro() const
Definition: dcode.h:157
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
void ConvertShapeToPolygon()
Function ConvertShapeToPolygon convert a shape to an equivalent polygon.
Definition: dcode.cpp:301
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
Function GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying ...
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, const 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:552
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:121
~D_CODE()
Definition: dcode.cpp:72
void Clear_D_CODE_Data()
Definition: dcode.cpp:77
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99