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