KiCad PCB EDA Suite
AM_PRIMITIVE Class Reference

Struct AM_PRIMITIVE holds an aperture macro primitive as given in Table 3 of http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf. More...

#include <am_primitive.h>

Public Member Functions

 AM_PRIMITIVE (bool aGerbMetric, AM_PRIMITIVE_ID aId=AMP_UNKNOWN)
 
 ~AM_PRIMITIVE ()
 
bool IsAMPrimitiveExposureOn (const GERBER_DRAW_ITEM *aParent) const
 Function IsAMPrimitiveExposureOn. More...
 
int GetShapeDim (const GERBER_DRAW_ITEM *aParent)
 GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying the D-Code of an item due to the complexity of the shape of some primitives one cannot calculate the "size" of a shape (only a bounding box) but here, the "dimension" of the shape is the diameter of the primitive or for lines the width of the line. More...
 
void DrawBasicShape (const GERBER_DRAW_ITEM *aParent, SHAPE_POLY_SET &aShapeBuffer, wxPoint aShapePos)
 Function drawBasicShape Draw (in fact generate the actual polygonal shape of) the primitive shape of an aperture macro instance. More...
 

Public Attributes

AM_PRIMITIVE_ID primitive_id
 The primitive type. More...
 
AM_PARAMS params
 A sequence of parameters used by. More...
 
bool m_GerbMetric
 

Private Member Functions

void ConvertShapeToPolygon (const GERBER_DRAW_ITEM *aParent, std::vector< wxPoint > &aBuffer)
 Function ConvertShapeToPolygon convert a shape to an equivalent polygon. More...
 

Detailed Description

Struct AM_PRIMITIVE holds an aperture macro primitive as given in Table 3 of http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf.

Definition at line 92 of file am_primitive.h.

Constructor & Destructor Documentation

◆ AM_PRIMITIVE()

AM_PRIMITIVE::AM_PRIMITIVE ( bool  aGerbMetric,
AM_PRIMITIVE_ID  aId = AMP_UNKNOWN 
)
inline

Definition at line 100 of file am_primitive.h.

100  : AM_PRIMITIVE( bool aGerbMetric, AM_PRIMITIVE_ID aId = AMP_UNKNOWN )
101  {
102  primitive_id = aId;
103  m_GerbMetric = aGerbMetric;
104  }
bool m_GerbMetric
Definition: am_primitive.h:98
AM_PRIMITIVE(bool aGerbMetric, AM_PRIMITIVE_ID aId=AMP_UNKNOWN)
Definition: am_primitive.h:100
AM_PRIMITIVE_ID
Enum AM_PRIMITIVE_ID is the set of all "aperture macro primitives" (primitive numbers).
Definition: am_primitive.h:71
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:95

References m_GerbMetric, and primitive_id.

◆ ~AM_PRIMITIVE()

AM_PRIMITIVE::~AM_PRIMITIVE ( )
inline

Definition at line 107 of file am_primitive.h.

107 {}

Member Function Documentation

◆ ConvertShapeToPolygon()

void AM_PRIMITIVE::ConvertShapeToPolygon ( const GERBER_DRAW_ITEM aParent,
std::vector< wxPoint > &  aBuffer 
)
private

Function ConvertShapeToPolygon convert a shape to an equivalent polygon.

Function ConvertShapeToPolygon (virtual) convert a shape to an equivalent polygon.

Arcs and circles are approximated by segments Useful when a shape is not a graphic primitive (shape with hole, rotated shape ... ) and cannot be easily drawn.

Arcs and circles are approximated by segments Useful when a shape is not a graphic primitive (shape with hole, rotated shape ... ) and cannot be easily drawn. note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted because circles are very easy to draw (no rotation problem) so convert them in polygons, and draw them as polygons is not a good idea.

Definition at line 452 of file am_primitive.cpp.

454 {
455  D_CODE* tool = aParent->GetDcodeDescr();
456 
457  switch( primitive_id )
458  {
459  case AMP_CIRCLE:
460  {
461  /* Generated by an aperture macro declaration like:
462  * "1,1,0.3,0.5, 1.0*"
463  * type (1), exposure, diameter, pos.x, pos.y, <rotation>
464  * <rotation> is a optional parameter: rotation from origin.
465  * type is not stored in parameters list, so the first parameter is exposure
466  */
467  wxPoint center = mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
468  int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2;
469  wxPoint corner;
470  const int delta = 3600 / seg_per_circle; // rot angle in 0.1 degree
471 
472  for( int angle = 0; angle < 3600; angle += delta )
473  {
474  corner.x = radius;
475  corner.y = 0;
476  RotatePoint( &corner, angle );
477  corner += center;
478  aBuffer.push_back( corner );
479  }
480  }
481  break;
482 
483  case AMP_LINE2:
484  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
485  {
486  int width = scaletoIU( params[1].GetValue( tool ), m_GerbMetric );
487  wxPoint start = mapPt( params[2].GetValue( tool ),
488  params[3].GetValue( tool ), m_GerbMetric );
489  wxPoint end = mapPt( params[4].GetValue( tool ),
490  params[5].GetValue( tool ), m_GerbMetric );
491  wxPoint delta = end - start;
492  int len = KiROUND( EuclideanNorm( delta ) );
493 
494  // To build the polygon, we must create a horizontal polygon starting to "start"
495  // and rotate it to have the end point to "end"
496  wxPoint currpt;
497  currpt.y += width / 2; // Upper left
498  aBuffer.push_back( currpt );
499  currpt.x = len; // Upper right
500  aBuffer.push_back( currpt );
501  currpt.y -= width; // lower right
502  aBuffer.push_back( currpt );
503  currpt.x = 0; // lower left
504  aBuffer.push_back( currpt );
505 
506  // Rotate rectangle and move it to the actual start point
507  double angle = ArcTangente( delta.y, delta.x );
508 
509  for( unsigned ii = 0; ii < 4; ii++ )
510  {
511  RotatePoint( &aBuffer[ii], -angle );
512  aBuffer[ii] += start;
513  }
514  }
515  break;
516 
517  case AMP_LINE_CENTER:
518  {
519  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
520  wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric );
521 
522  // Build poly:
523  pos.x -= size.x / 2;
524  pos.y -= size.y / 2; // Lower left
525  aBuffer.push_back( pos );
526  pos.y += size.y; // Upper left
527  aBuffer.push_back( pos );
528  pos.x += size.x; // Upper right
529  aBuffer.push_back( pos );
530  pos.y -= size.y; // lower right
531  aBuffer.push_back( pos );
532  }
533  break;
534 
535  case AMP_LINE_LOWER_LEFT:
536  {
537  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
538  wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
539  tool ), m_GerbMetric );
540 
541  // Build poly:
542  aBuffer.push_back( lowerLeft );
543  lowerLeft.y += size.y; // Upper left
544  aBuffer.push_back( lowerLeft );
545  lowerLeft.x += size.x; // Upper right
546  aBuffer.push_back( lowerLeft );
547  lowerLeft.y -= size.y; // lower right
548  aBuffer.push_back( lowerLeft );
549  }
550  break;
551 
552  case AMP_THERMAL:
553  {
554  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
555  // rotated by 90, 180 and 270 deg.
556  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
557  int outerRadius = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2;
558  int innerRadius = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ) / 2;
559 
560  // Safety checks to guarantee no divide-by-zero
561  outerRadius = std::max( 1, outerRadius );
562  innerRadius = std::max( 1, innerRadius );
563 
564  int halfthickness = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
565  double angle_start = RAD2DECIDEG( asin( (double) halfthickness / innerRadius ) );
566 
567  // Draw shape in the first cadrant (X and Y > 0)
568  wxPoint pos, startpos;
569 
570  // Inner arc
571  startpos.x = innerRadius;
572  double angle_end = 900 - angle_start;
573  for( double angle = angle_start; angle < angle_end; angle += 100 )
574  {
575  pos = startpos;
576  RotatePoint( &pos, angle );
577  aBuffer.push_back( pos );
578  }
579 
580  // Last point
581  pos = startpos;
582  RotatePoint( &pos, angle_end );
583  aBuffer.push_back( pos );
584 
585  // outer arc
586  startpos.x = outerRadius;
587  startpos.y = 0;
588  angle_start = RAD2DECIDEG( asin( (double) halfthickness / outerRadius ) );
589  angle_end = 900 - angle_start;
590 
591  // First point, near Y axis, outer arc
592  for( double angle = angle_end; angle > angle_start; angle -= 100 )
593  {
594  pos = startpos;
595  RotatePoint( &pos, angle );
596  aBuffer.push_back( pos );
597  }
598 
599  // last point
600  pos = startpos;
601  RotatePoint( &pos, angle_start );
602  aBuffer.push_back( pos );
603 
604  aBuffer.push_back( aBuffer[0] ); // Close poly
605  }
606  break;
607 
608  case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon
609  // because circles can be drawn easily
610  {
611  int crossHairThickness = scaletoIU( params[6].GetValue( tool ), m_GerbMetric );
612  int crossHairLength = scaletoIU( params[7].GetValue( tool ), m_GerbMetric );
613 
614  // Create cross. First create 1/4 of the shape.
615  // Others point are the same, totated by 90, 180 and 270 deg
616  wxPoint pos( crossHairThickness / 2, crossHairLength / 2 );
617  aBuffer.push_back( pos );
618  pos.y = crossHairThickness / 2;
619  aBuffer.push_back( pos );
620  pos.x = -crossHairLength / 2;
621  aBuffer.push_back( pos );
622  pos.y = -crossHairThickness / 2;
623  aBuffer.push_back( pos );
624 
625  // Copy the 4 shape, rotated by 90, 180 and 270 deg
626  for( int jj = 1; jj <= 3; jj ++ )
627  {
628  for( int ii = 0; ii < 4; ii++ )
629  {
630  pos = aBuffer[ii];
631  RotatePoint( &pos, jj*900 );
632  aBuffer.push_back( pos );
633  }
634  }
635  }
636  break;
637 
638  case AMP_OUTLINE:
639  // already is a polygon. Do nothing
640  break;
641 
642  case AMP_POLYGON: // Creates a regular polygon
643  {
644  int vertexcount = KiROUND( params[1].GetValue( tool ) );
645  int radius = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
646  // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
647  if( vertexcount < 3 )
648  vertexcount = 3;
649  if( vertexcount > 10 )
650  vertexcount = 10;
651  for( int ii = 0; ii <= vertexcount; ii++ )
652  {
653  wxPoint pos( radius, 0);
654  RotatePoint( &pos, ii * 3600 / vertexcount );
655  aBuffer.push_back( pos );
656  }
657  }
658  break;
659 
660  case AMP_COMMENT:
661  case AMP_UNKNOWN:
662  case AMP_EOF:
663  break;
664  }
665 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:128
bool m_GerbMetric
Definition: am_primitive.h:98
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
double RAD2DECIDEG(double rad)
Definition: trigo.h:219
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
const int seg_per_circle
static wxPoint mapPt(double x, double y, bool isMetric)
Function mapPt translates a point from the aperture macro coordinate system to our deci-mils coordina...
D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:82
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
AM_PARAMS params
A sequence of parameters used by.
Definition: am_primitive.h:96
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:95

References AMP_CIRCLE, AMP_COMMENT, AMP_EOF, AMP_LINE2, AMP_LINE20, AMP_LINE_CENTER, AMP_LINE_LOWER_LEFT, AMP_MOIRE, AMP_OUTLINE, AMP_POLYGON, AMP_THERMAL, AMP_UNKNOWN, PNS::angle(), ArcTangente(), EuclideanNorm(), GERBER_DRAW_ITEM::GetDcodeDescr(), KiROUND(), m_GerbMetric, mapPt(), params, primitive_id, RAD2DECIDEG(), RotatePoint(), scaletoIU(), seg_per_circle, wxPoint::x, and wxPoint::y.

Referenced by DrawBasicShape().

◆ DrawBasicShape()

void AM_PRIMITIVE::DrawBasicShape ( const GERBER_DRAW_ITEM aParent,
SHAPE_POLY_SET aShapeBuffer,
wxPoint  aShapePos 
)

Function drawBasicShape Draw (in fact generate the actual polygonal shape of) the primitive shape of an aperture macro instance.

Parameters
aParent= the parent GERBER_DRAW_ITEM which is actually drawn
aShapeBuffer= a SHAPE_POLY_SET to put the shape converted to a polygon
aShapePos= the actual shape position

Definition at line 100 of file am_primitive.cpp.

103 {
104  #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \
105  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\
106  aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );\
107  aShapeBuffer.Append( polybuffer[0].x, polybuffer[0].y );}
108 
109  // Draw the primitive shape for flashed items.
110  static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation
111  polybuffer.clear();
112 
113  wxPoint curPos = aShapePos;
114  D_CODE* tool = aParent->GetDcodeDescr();
115  double rotation;
116 
117  switch( primitive_id )
118  {
119  case AMP_CIRCLE: // Circle, given diameter and position
120  {
121  /* Generated by an aperture macro declaration like:
122  * "1,1,0.3,0.5, 1.0*"
123  * type (1), exposure, diameter, pos.x, pos.y, <rotation>
124  * <rotation> is a optional parameter: rotation from origin.
125  * type is not stored in parameters list, so the first parameter is exposure
126  */
127  ConvertShapeToPolygon( aParent, polybuffer );
128 
129  // shape rotation (if any):
130  if( params.size() >= 5 )
131  {
132  rotation = params[4].GetValue( tool ) * 10.0;
133 
134  if( rotation != 0)
135  {
136  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
137  RotatePoint( &polybuffer[ii], -rotation );
138  }
139  }
140 
141 
142  // Move to current position:
143  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
144  {
145  polybuffer[ii] += curPos;
146  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
147  }
148 
150  }
151  break;
152 
153  case AMP_LINE2:
154  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
155  {
156  /* Vector Line, Primitive Code 20.
157  * A vector line is a rectangle defined by its line width, start and end points.
158  * The line ends are rectangular.
159  */
160  /* Generated by an aperture macro declaration like:
161  * "2,1,0.3,0,0, 0.5, 1.0,-135*"
162  * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
163  * type is not stored in parameters list, so the first parameter is exposure
164  */
165  ConvertShapeToPolygon( aParent, polybuffer );
166 
167  // shape rotation:
168  rotation = params[6].GetValue( tool ) * 10.0;
169 
170  if( rotation != 0)
171  {
172  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
173  RotatePoint( &polybuffer[ii], -rotation );
174  }
175 
176  // Move to current position:
177  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
178  {
179  polybuffer[ii] += curPos;
180  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
181  }
182 
184  }
185  break;
186 
187  case AMP_LINE_CENTER:
188  {
189  /* Center Line, Primitive Code 21
190  * A center line primitive is a rectangle defined by its width, height, and center point
191  */
192  /* Generated by an aperture macro declaration like:
193  * "21,1,0.3,0.03,0,0,-135*"
194  * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
195  * type is not stored in parameters list, so the first parameter is exposure
196  */
197  ConvertShapeToPolygon( aParent, polybuffer );
198 
199  // shape rotation:
200  rotation = params[5].GetValue( tool ) * 10.0;
201 
202  if( rotation != 0 )
203  {
204  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
205  RotatePoint( &polybuffer[ii], -rotation );
206  }
207 
208  // Move to current position:
209  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
210  {
211  polybuffer[ii] += curPos;
212  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
213  }
214 
216  }
217  break;
218 
219  case AMP_LINE_LOWER_LEFT:
220  {
221  /* Generated by an aperture macro declaration like:
222  * "22,1,0.3,0.03,0,0,-135*"
223  * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
224  * type is not stored in parameters list, so the first parameter is exposure
225  */
226  ConvertShapeToPolygon( aParent, polybuffer );
227 
228  // shape rotation:
229  rotation = params[5].GetValue( tool ) * 10.0;
230  if( rotation != 0)
231  {
232  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
233  RotatePoint( &polybuffer[ii], -rotation );
234  }
235 
236  // Move to current position:
237  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
238  {
239  polybuffer[ii] += curPos;
240  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
241  }
242 
244  }
245  break;
246 
247  case AMP_THERMAL:
248  {
249  /* Generated by an aperture macro declaration like:
250  * "7, 0,0,1.0,0.3,0.01,-13*"
251  * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
252  * type is not stored in parameters list, so the first parameter is center.x
253  *
254  * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always on.
255  */
256  std::vector<wxPoint> subshape_poly;
257  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric );
258  ConvertShapeToPolygon( aParent, subshape_poly );
259 
260  // shape rotation:
261  rotation = params[5].GetValue( tool ) * 10.0;
262 
263  // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
264  // We must draw 4 sub-shapes rotated by 90 deg
265  for( int ii = 0; ii < 4; ii++ )
266  {
267  polybuffer = subshape_poly;
268  double sub_rotation = rotation + 900 * ii;
269 
270  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
271  RotatePoint( &polybuffer[jj], -sub_rotation );
272 
273  // Move to current position:
274  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
275  {
276  polybuffer[jj] += curPos;
277  polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] );
278  }
279 
281  }
282  }
283  break;
284 
285  case AMP_MOIRE:
286  {
287  /* Moir�, Primitive Code 6
288  * The moir� primitive is a cross hair centered on concentric rings (annuli).
289  * Exposure is always on.
290  */
291  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
292  m_GerbMetric );
293 
294  /* Generated by an aperture macro declaration like:
295  * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
296  * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
297  * type is not stored in parameters list, so the first parameter is pos.x
298  */
299  int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric );
300  int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric );
301  int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric );
302  int numCircles = KiROUND( params[5].GetValue( tool ) );
303 
304  // Draw circles:
305  wxPoint center = aParent->GetABPosition( curPos );
306  // adjust outerDiam by this on each nested circle
307  int diamAdjust = (gap + penThickness) * 2;
308 
309  for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
310  {
311  if( outerDiam <= 0 )
312  break;
313 
314  // Note: outerDiam is the outer diameter of the ring.
315  // the ring graphic diameter is (outerDiam - penThickness)
316  if( outerDiam <= penThickness )
317  { // No room to draw a ring (no room for the hole):
318  // draw a circle instead (with no hole), with the right diameter
319  TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF );
320  }
321  else
322  TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2,
323  ARC_HIGH_DEF, penThickness );
324  }
325 
326  // Draw the cross:
327  ConvertShapeToPolygon( aParent, polybuffer );
328 
329  rotation = params[8].GetValue( tool ) * 10.0;
330  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
331  {
332  // shape rotation:
333  RotatePoint( &polybuffer[ii], -rotation );
334  // Move to current position:
335  polybuffer[ii] += curPos;
336  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
337  }
338 
340  }
341  break;
342 
343  case AMP_OUTLINE:
344  {
345  /* Outline, Primitive Code 4
346  * An outline primitive is an area enclosed by an n-point polygon defined by its start point and n
347  * subsequent points. The outline must be closed, i.e. the last point must be equal to the start
348  * point. There must be at least one subsequent point (to close the outline).
349  * The outline of the primitive is actually the contour (see 2.6) that consists of linear segments
350  * only, so it must conform to all the requirements described for contours.
351  * Warning: Make no mistake: n is the number of subsequent points, being the number of
352  * vertices of the outline or one less than the number of coordinate pairs.
353  */
354  /* Generated by an aperture macro declaration like:
355  * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
356  * type(4), exposure, corners count, corner1.x, corner.1y, ..., corner1.x, corner.1y, rotation
357  * type is not stored in parameters list, so the first parameter is exposure
358  */
359  // params[0] is the exposure and params[1] is the corners count after the first corner
360  int numCorners = (int) params[1].GetValue( tool );
361  // the shape rotation is the last param of list, after corners
362  int last_prm = params.size() - 1;
363  rotation = params[last_prm].GetValue( tool ) * 10.0;
364  wxPoint pos;
365 
366  // Read points.
367  // Note: numCorners is the polygon corner count, following the first corner
368  // * the polygon is always closed,
369  // * therefore the last XY coordinate is the same as the first
370  int prm_idx = 2; // params[2] is the first X coordinate
371  for( int i = 0; i <= numCorners; ++i )
372  {
373  pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
374  prm_idx++;
375  pos.y = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
376  prm_idx++;
377  polybuffer.push_back(pos);
378 
379  // Guard: ensure prm_idx < last_prm
380  // I saw malformed gerber files with numCorners = number
381  // of coordinates instead of number of coordinates following the first point
382  if( prm_idx >= last_prm )
383  break;
384  }
385  // rotate polygon and move it to the actual position
386  // shape rotation:
387  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
388  {
389  RotatePoint( &polybuffer[ii], -rotation );
390  }
391 
392  // Move to current position:
393  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
394  {
395  polybuffer[ii] += curPos;
396  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
397  }
398 
400  }
401  break;
402 
403  case AMP_POLYGON:
404  /* Polygon, Primitive Code 5
405  * A polygon primitive is a regular polygon defined by the number of vertices n, the center point
406  * and the diameter of the circumscribed circle
407  */
408  /* Generated by an aperture macro declaration like:
409  * "5,1,0.6,0,0,0.5,25"
410  * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
411  * type is not stored in parameters list, so the first parameter is exposure
412  */
413  curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
414  // Creates the shape:
415  ConvertShapeToPolygon( aParent, polybuffer );
416 
417  // rotate polygon and move it to the actual position
418  rotation = params[5].GetValue( tool ) * 10.0;
419  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
420  {
421  RotatePoint( &polybuffer[ii], -rotation );
422  polybuffer[ii] += curPos;
423  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
424  }
425 
427 
428  break;
429 
430  case AMP_EOF:
431  // not yet supported, waiting for you.
432  break;
433 
434  case AMP_UNKNOWN:
435  default:
436  DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
437  break;
438  }
439 }
bool m_GerbMetric
Definition: am_primitive.h:98
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
void ConvertShapeToPolygon(const GERBER_DRAW_ITEM *aParent, std::vector< wxPoint > &aBuffer)
Function ConvertShapeToPolygon convert a shape to an equivalent polygon.
wxPoint GetABPosition(const wxPoint &aXYPosition) const
Function GetABPosition returns the image position of aPosition for this object.
#define TO_POLY_SHAPE
static wxPoint mapPt(double x, double y, bool isMetric)
Function mapPt translates a point from the aperture macro coordinate system to our deci-mils coordina...
D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:82
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aError)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void TransformRingToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCentre, int aRadius, int aError, int aWidth)
Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segme...
#define DBG(x)
Definition: fctsys.h:33
AM_PARAMS params
A sequence of parameters used by.
Definition: am_primitive.h:96
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:95

References AMP_CIRCLE, AMP_EOF, AMP_LINE2, AMP_LINE20, AMP_LINE_CENTER, AMP_LINE_LOWER_LEFT, AMP_MOIRE, AMP_OUTLINE, AMP_POLYGON, AMP_THERMAL, AMP_UNKNOWN, ConvertShapeToPolygon(), DBG, GERBER_DRAW_ITEM::GetABPosition(), GERBER_DRAW_ITEM::GetDcodeDescr(), KiROUND(), m_GerbMetric, mapPt(), params, primitive_id, RotatePoint(), scaletoIU(), TO_POLY_SHAPE, TransformCircleToPolygon(), TransformRingToPolygon(), wxPoint::x, and wxPoint::y.

◆ GetShapeDim()

int AM_PRIMITIVE::GetShapeDim ( const GERBER_DRAW_ITEM aParent)

GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying the D-Code of an item due to the complexity of the shape of some primitives one cannot calculate the "size" of a shape (only a bounding box) but here, the "dimension" of the shape is the diameter of the primitive or for lines the width of the line.

GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying the D-Code of an item due to the complexity of the shape of some primitives one cannot calculate the "size" of a shape (only abounding box) but here, the "dimension" of the shape is the diameter of the primitive or for lines the width of the line.

Parameters
aParent= the parent GERBER_DRAW_ITEM which is actually drawn
Returns
a dimension, or -1 if no dim to calculate

Definition at line 677 of file am_primitive.cpp.

678 {
679  int dim = -1;
680  D_CODE* tool = aParent->GetDcodeDescr();
681 
682  switch( primitive_id )
683  {
684  case AMP_CIRCLE:
685  // params = exposure, diameter, pos.x, pos.y
686  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // Diameter
687  break;
688 
689  case AMP_LINE2:
690  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
691  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // linne width
692  break;
693 
694  case AMP_LINE_CENTER:
695  {
696  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
697  dim = std::min(size.x, size.y);
698  }
699  break;
700 
701  case AMP_LINE_LOWER_LEFT:
702  {
703  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
704  dim = std::min(size.x, size.y);
705  }
706  break;
707 
708  case AMP_THERMAL:
709  {
710  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
711  // rotated by 90, 180 and 270 deg.
712  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
713  dim = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam
714  }
715  break;
716 
717  case AMP_MOIRE: // A cross hair with n concentric circles.
718  dim = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len
719  break;
720 
721  case AMP_OUTLINE: // a free polygon :
722  // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?)
723  {
724  // exposure, corners count, corner1.x, corner.1y, ..., rotation
725  // note: corners count is the count of corners following corner1
726  int numPoints = (int) params[1].GetValue( tool );
727  // Read points. numPoints does not include the starting point, so add 1.
728  // and calculate the bounding box;
729  wxSize pos_min, pos_max, pos;
730  int prm_idx = 2; // params[2] is the first X coordinate
731  int last_prm = params.size() - 1;
732 
733  for( int i = 0; i<= numPoints; ++i )
734  {
735  pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
736  prm_idx++;
737  pos.y = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
738  prm_idx++;
739  if( i == 0 )
740  pos_min = pos_max = pos;
741  else
742  {
743  // upper right corner:
744  if( pos_min.x > pos.x )
745  pos_min.x = pos.x;
746  if( pos_min.y > pos.y )
747  pos_min.y = pos.y;
748  // lower left corner:
749  if( pos_max.x < pos.x )
750  pos_max.x = pos.x;
751  if( pos_max.y < pos.y )
752  pos_max.y = pos.y;
753  }
754 
755  // Guard: ensure prm_idx < last_prm (last prm is orientation)
756  // I saw malformed gerber files with numCorners = number
757  // of coordinates instead of number of coordinates following the first point
758  if( prm_idx >= last_prm )
759  break;
760  }
761  // calculate dim
762  wxSize size;
763  size.x = pos_max.x - pos_min.x;
764  size.y = pos_max.y - pos_min.y;
765  dim = std::min( size.x, size.y );
766  }
767  break;
768 
769  case AMP_POLYGON: // Regular polygon
770  dim = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius
771  break;
772 
773  case AMP_COMMENT:
774  case AMP_UNKNOWN:
775  case AMP_EOF:
776  break;
777  }
778  return dim;
779 }
bool m_GerbMetric
Definition: am_primitive.h:98
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
static wxPoint mapPt(double x, double y, bool isMetric)
Function mapPt translates a point from the aperture macro coordinate system to our deci-mils coordina...
D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:82
AM_PARAMS params
A sequence of parameters used by.
Definition: am_primitive.h:96
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:95

References AMP_CIRCLE, AMP_COMMENT, AMP_EOF, AMP_LINE2, AMP_LINE20, AMP_LINE_CENTER, AMP_LINE_LOWER_LEFT, AMP_MOIRE, AMP_OUTLINE, AMP_POLYGON, AMP_THERMAL, AMP_UNKNOWN, GERBER_DRAW_ITEM::GetDcodeDescr(), m_GerbMetric, mapPt(), params, primitive_id, scaletoIU(), wxPoint::x, and wxPoint::y.

◆ IsAMPrimitiveExposureOn()

bool AM_PRIMITIVE::IsAMPrimitiveExposureOn ( const GERBER_DRAW_ITEM aParent) const

Function IsAMPrimitiveExposureOn.

Returns
true if the first parameter is not 0 (it can be only 0 or 1). Some but not all primitives use the first parameter as an exposure control. Others are always ON. In a aperture macro shape, a basic primitive with exposure off is a hole in the shape it is NOT a negative shape

Definition at line 64 of file am_primitive.cpp.

65 {
66  /*
67  * Some but not all primitives use the first parameter as an exposure control.
68  * Others are always ON.
69  * In a aperture macro shape, a basic primitive with exposure off is a hole in the shape
70  * it is NOT a negative shape
71  */
72  wxASSERT( params.size() );
73 
74  switch( primitive_id )
75  {
76  case AMP_CIRCLE:
77  case AMP_LINE2:
78  case AMP_LINE20:
79  case AMP_LINE_CENTER:
81  case AMP_OUTLINE:
82  case AMP_POLYGON:
83  // All have an exposure parameter and can return a value (0 or 1)
84  return params[0].GetValue( aParent->GetDcodeDescr() ) != 0;
85  break;
86 
87  case AMP_THERMAL: // Exposure is always on
88  case AMP_MOIRE: // Exposure is always on
89  case AMP_EOF:
90  case AMP_UNKNOWN:
91  default:
92  return 1; // All have no exposure parameter and are always 0N return true
93  break;
94  }
95 }
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
AM_PARAMS params
A sequence of parameters used by.
Definition: am_primitive.h:96
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:95

References AMP_CIRCLE, AMP_EOF, AMP_LINE2, AMP_LINE20, AMP_LINE_CENTER, AMP_LINE_LOWER_LEFT, AMP_MOIRE, AMP_OUTLINE, AMP_POLYGON, AMP_THERMAL, AMP_UNKNOWN, GERBER_DRAW_ITEM::GetDcodeDescr(), params, and primitive_id.

Member Data Documentation

◆ m_GerbMetric

bool AM_PRIMITIVE::m_GerbMetric

Definition at line 98 of file am_primitive.h.

Referenced by AM_PRIMITIVE(), ConvertShapeToPolygon(), DrawBasicShape(), and GetShapeDim().

◆ params

AM_PARAMS AM_PRIMITIVE::params

A sequence of parameters used by.

Definition at line 96 of file am_primitive.h.

Referenced by ConvertShapeToPolygon(), DrawBasicShape(), GetShapeDim(), IsAMPrimitiveExposureOn(), and GERBER_FILE_IMAGE::ReadApertureMacro().

◆ primitive_id

AM_PRIMITIVE_ID AM_PRIMITIVE::primitive_id

The documentation for this class was generated from the following files: