KiCad PCB EDA Suite
AM_PRIMITIVE Class Reference

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
 
int GetShapeDim (const GERBER_DRAW_ITEM *aParent)
 Calculate a value that can be used to evaluate the size of text when displaying the D-Code of an item. More...
 
void DrawBasicShape (const GERBER_DRAW_ITEM *aParent, SHAPE_POLY_SET &aShapeBuffer, const VECTOR2I &aShapePos)
 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< VECTOR2I > &aBuffer)
 Convert a shape to an equivalent polygon. More...
 

Detailed Description

An aperture macro primitive as given in Table 3 of http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf.

Definition at line 93 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 102 of file am_primitive.h.

103 {
104 primitive_id = aId;
105 m_GerbMetric = aGerbMetric;
106 }
AM_PRIMITIVE_ID primitive_id
The primitive type.
Definition: am_primitive.h:96
bool m_GerbMetric
Definition: am_primitive.h:99

References m_GerbMetric, and primitive_id.

◆ ~AM_PRIMITIVE()

AM_PRIMITIVE::~AM_PRIMITIVE ( )
inline

Definition at line 109 of file am_primitive.h.

109{}

Member Function Documentation

◆ ConvertShapeToPolygon()

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

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.

Note
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 462 of file am_primitive.cpp.

464{
465 D_CODE* tool = aParent->GetDcodeDescr();
466
467 switch( primitive_id )
468 {
469 case AMP_CIRCLE:
470 {
471 /* Generated by an aperture macro declaration like:
472 * "1,1,0.3,0.5, 1.0*"
473 * type (1), exposure, diameter, pos.x, pos.y, <rotation>
474 * <rotation> is a optional parameter: rotation from origin.
475 * type is not stored in parameters list, so the first parameter is exposure
476 */
477 int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2;
478
479 // A circle primitive can have a 0 size (for instance when used in roundrect macro),
480 // so skip it
481 if( radius <= 0 )
482 break;
483
484 VECTOR2I center = mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ),
485 m_GerbMetric );
486 VECTOR2I corner;
487 EDA_ANGLE delta = ANGLE_360 / seg_per_circle; // rot angle in 0.1 degree
488
490 {
491 corner.x = radius;
492 corner.y = 0;
493 RotatePoint( corner, angle );
494 corner += center;
495 aBuffer.push_back( corner );
496 }
497
498 break;
499 }
500
501 case AMP_LINE2:
502 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
503 {
504 int width = scaletoIU( params[1].GetValue( tool ), m_GerbMetric );
505 VECTOR2I start =
506 mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
507 VECTOR2I end =
508 mapPt( params[4].GetValue( tool ), params[5].GetValue( tool ), m_GerbMetric );
509 VECTOR2I delta = end - start;
510 int len = KiROUND( EuclideanNorm( delta ) );
511
512 // To build the polygon, we must create a horizontal polygon starting to "start"
513 // and rotate it to have the end point to "end"
514 VECTOR2I currpt;
515 currpt.y += width / 2; // Upper left
516 aBuffer.push_back( currpt );
517 currpt.x = len; // Upper right
518 aBuffer.push_back( currpt );
519 currpt.y -= width; // lower right
520 aBuffer.push_back( currpt );
521 currpt.x = 0; // lower left
522 aBuffer.push_back( currpt );
523
524 // Rotate rectangle and move it to the actual start point
526
527 for( unsigned ii = 0; ii < 4; ii++ )
528 {
529 RotatePoint( aBuffer[ii], -angle );
530 aBuffer[ii] += start;
531 }
532
533 break;
534 }
535
536 case AMP_LINE_CENTER:
537 {
538 VECTOR2I size =
539 mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
540 VECTOR2I pos =
541 mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric );
542
543 // Build poly:
544 pos.x -= size.x / 2;
545 pos.y -= size.y / 2; // Lower left
546 aBuffer.push_back( pos );
547 pos.y += size.y; // Upper left
548 aBuffer.push_back( pos );
549 pos.x += size.x; // Upper right
550 aBuffer.push_back( pos );
551 pos.y -= size.y; // lower right
552 aBuffer.push_back( pos );
553 break;
554 }
555
557 {
558 VECTOR2I size =
559 mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
560 VECTOR2I lowerLeft =
561 mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric );
562
563 // Build poly:
564 aBuffer.push_back( lowerLeft );
565 lowerLeft.y += size.y; // Upper left
566 aBuffer.push_back( lowerLeft );
567 lowerLeft.x += size.x; // Upper right
568 aBuffer.push_back( lowerLeft );
569 lowerLeft.y -= size.y; // lower right
570 aBuffer.push_back( lowerLeft );
571 break;
572 }
573
574 case AMP_THERMAL:
575 {
576 // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from
577 // this first rotated by 90, 180 and 270 deg.
578 // params = center.x (unused here), center.y (unused here), outside diam, inside diam,
579 // crosshair thickness.
580 int outerRadius = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2;
581 int innerRadius = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ) / 2;
582
583 // Safety checks to guarantee no divide-by-zero
584 outerRadius = std::max( 1, outerRadius );
585 innerRadius = std::max( 1, innerRadius );
586
587 int halfthickness = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
588 EDA_ANGLE angle_start( asin( (double) halfthickness / innerRadius ), RADIANS_T );
589
590 // Draw shape in the first quadrant (X and Y > 0)
591 VECTOR2I pos, startpos;
592
593 // Inner arc
594 startpos.x = innerRadius;
595 EDA_ANGLE angle_end = ANGLE_90 - angle_start;
596
597 for( EDA_ANGLE angle = angle_start; angle < angle_end; angle += EDA_ANGLE( 10, DEGREES_T ) )
598 {
599 pos = startpos;
600 RotatePoint( pos, angle );
601 aBuffer.push_back( pos );
602 }
603
604 // Last point
605 pos = startpos;
606 RotatePoint( pos, angle_end );
607 aBuffer.push_back( pos );
608
609 // outer arc
610 startpos.x = outerRadius;
611 startpos.y = 0;
612 angle_start = EDA_ANGLE( asin( (double) halfthickness / outerRadius ), RADIANS_T );
613 angle_end = ANGLE_90 - angle_start;
614
615 // First point, near Y axis, outer arc
616 for( EDA_ANGLE angle = angle_end; angle > angle_start; angle -= EDA_ANGLE( 10, DEGREES_T ) )
617 {
618 pos = startpos;
619 RotatePoint( pos, angle );
620 aBuffer.push_back( pos );
621 }
622
623 // last point
624 pos = startpos;
625 RotatePoint( pos, angle_start );
626 aBuffer.push_back( pos );
627
628 aBuffer.push_back( aBuffer[0] ); // Close poly
629 }
630 break;
631
632 case AMP_MOIRE:
633 {
634 // A cross hair with n concentric circles. Only the cross is built as
635 // polygon because circles can be drawn easily
636 int crossHairThickness = scaletoIU( params[6].GetValue( tool ), m_GerbMetric );
637 int crossHairLength = scaletoIU( params[7].GetValue( tool ), m_GerbMetric );
638
639 // Create cross. First create 1/4 of the shape.
640 // Others point are the same, rotated by 90, 180 and 270 deg
641 VECTOR2I pos( crossHairThickness / 2, crossHairLength / 2 );
642 aBuffer.push_back( pos );
643 pos.y = crossHairThickness / 2;
644 aBuffer.push_back( pos );
645 pos.x = -crossHairLength / 2;
646 aBuffer.push_back( pos );
647 pos.y = -crossHairThickness / 2;
648 aBuffer.push_back( pos );
649
650 // Copy the 4 shape, rotated by 90, 180 and 270 deg
651 for( int jj = 1; jj <= 3; jj ++ )
652 {
653 for( int ii = 0; ii < 4; ii++ )
654 {
655 pos = aBuffer[ii];
656 RotatePoint( pos, ANGLE_90 * jj );
657 aBuffer.push_back( pos );
658 }
659 }
660
661 break;
662 }
663
664 case AMP_OUTLINE:
665 // already is a polygon. Do nothing
666 break;
667
668 case AMP_POLYGON: // Creates a regular polygon
669 {
670 int vertexcount = KiROUND( params[1].GetValue( tool ) );
671 int radius = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
672
673 // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
674 if( vertexcount < 3 )
675 vertexcount = 3;
676
677 if( vertexcount > 10 )
678 vertexcount = 10;
679
680 for( int ii = 0; ii <= vertexcount; ii++ )
681 {
682 VECTOR2I pos( radius, 0 );
683 RotatePoint( pos, ANGLE_360 * ii / vertexcount );
684 aBuffer.push_back( pos );
685 }
686
687 break;
688 }
689
690 case AMP_COMMENT:
691 case AMP_UNKNOWN:
692 case AMP_EOF:
693 break;
694 }
695}
int scaletoIU(double aCoord, bool isMetric)
Convert a distance given in floating point to our internal units.
const int seg_per_circle
static VECTOR2I mapPt(double x, double y, bool isMetric)
Translate a point from the aperture macro coordinate system to our deci-mils coordinate system.
@ AMP_POLYGON
Definition: am_primitive.h:81
@ AMP_LINE_LOWER_LEFT
Definition: am_primitive.h:78
@ AMP_LINE2
Definition: am_primitive.h:75
@ AMP_CIRCLE
Definition: am_primitive.h:74
@ AMP_THERMAL
Definition: am_primitive.h:84
@ AMP_EOF
Definition: am_primitive.h:79
@ AMP_UNKNOWN
Definition: am_primitive.h:71
@ AMP_COMMENT
Definition: am_primitive.h:72
@ AMP_LINE_CENTER
Definition: am_primitive.h:77
@ AMP_MOIRE
Definition: am_primitive.h:83
@ AMP_OUTLINE
Definition: am_primitive.h:80
@ AMP_LINE20
Definition: am_primitive.h:76
AM_PARAMS params
A sequence of parameters used by.
Definition: am_primitive.h:97
A gerber DCODE (also called Aperture) definition.
Definition: dcode.h:81
D_CODE * GetDcodeDescr() const
Return the GetDcodeDescr of this object, or NULL.
@ RADIANS_T
Definition: eda_angle.h:32
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:429
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:425
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:423
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
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:80

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(), ANGLE_0, ANGLE_360, ANGLE_90, DEGREES_T, delta, EuclideanNorm(), GERBER_DRAW_ITEM::GetDcodeDescr(), KiROUND(), m_GerbMetric, mapPt(), params, primitive_id, RADIANS_T, RotatePoint(), scaletoIU(), seg_per_circle, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DrawBasicShape().

◆ DrawBasicShape()

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

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

Parameters
aParentis the parent GERBER_DRAW_ITEM which is actually drawn.
aShapeBufferis a SHAPE_POLY_SET to put the shape converted to a polygon.
aShapePosis the actual shape position.

Definition at line 97 of file am_primitive.cpp.

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

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, ANGLE_90, ConvertShapeToPolygon(), DEGREES_T, ERROR_INSIDE, GERBER_DRAW_ITEM::GetABPosition(), GERBER_DRAW_ITEM::GetDcodeDescr(), EDA_ANGLE::IsZero(), KiROUND(), m_GerbMetric, mapPt(), params, primitive_id, RotatePoint(), scaletoIU(), TO_POLY_SHAPE, TransformCircleToPolygon(), TransformRingToPolygon(), VECTOR2< T >::x, and VECTOR2< T >::y.

◆ GetShapeDim()

int AM_PRIMITIVE::GetShapeDim ( const GERBER_DRAW_ITEM aParent)

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.

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

Definition at line 698 of file am_primitive.cpp.

699{
700 int dim = -1;
701 D_CODE* tool = aParent->GetDcodeDescr();
702
703 switch( primitive_id )
704 {
705 case AMP_CIRCLE:
706 // params = exposure, diameter, pos.x, pos.y
707 dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // Diameter
708 break;
709
710 case AMP_LINE2:
711 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
712 dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // line width
713 break;
714
715 case AMP_LINE_CENTER:
716 {
717 VECTOR2I size =
718 mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
719 dim = std::min(size.x, size.y);
720 break;
721 }
722
724 {
725 VECTOR2I size =
726 mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
727 dim = std::min(size.x, size.y);
728 break;
729 }
730
731 case AMP_THERMAL:
732 {
733 // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from
734 // this first rotated by 90, 180 and 270 deg.
735 // params = center.x (unused here), center.y (unused here), outside diam, inside diam,
736 // crosshair thickness.
737 dim = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam
738 break;
739 }
740
741 case AMP_MOIRE: // A cross hair with n concentric circles.
742 dim = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len
743 break;
744
745 case AMP_OUTLINE: // a free polygon :
746 {
747 // dim = min side of the bounding box (this is a poor criteria, but what is a good
748 // criteria b?)
749 // exposure, corners count, corner1.x, corner.1y, ..., rotation
750 // note: corners count is the count of corners following corner1
751 int numPoints = (int) params[1].GetValue( tool );
752
753 // Read points. numPoints does not include the starting point, so add 1.
754 // and calculate the bounding box;
755 VECTOR2I pos_min, pos_max, pos;
756 int prm_idx = 2; // params[2] is the first X coordinate
757 int last_prm = params.size() - 1;
758
759 for( int i = 0; i<= numPoints; ++i )
760 {
761 pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
762 prm_idx++;
763 pos.y = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
764 prm_idx++;
765
766 if( i == 0 )
767 {
768 pos_min = pos_max = pos;
769 }
770 else
771 {
772 // upper right corner:
773 if( pos_min.x > pos.x )
774 pos_min.x = pos.x;
775
776 if( pos_min.y > pos.y )
777 pos_min.y = pos.y;
778
779 // lower left corner:
780 if( pos_max.x < pos.x )
781 pos_max.x = pos.x;
782
783 if( pos_max.y < pos.y )
784 pos_max.y = pos.y;
785 }
786
787 // Guard: ensure prm_idx < last_prm (last prm is orientation)
788 // I saw malformed gerber files with numCorners = number
789 // of coordinates instead of number of coordinates following the first point
790 if( prm_idx >= last_prm )
791 break;
792 }
793
794 // calculate dim
795 VECTOR2I size;
796 size.x = pos_max.x - pos_min.x;
797 size.y = pos_max.y - pos_min.y;
798 dim = std::min( size.x, size.y );
799 break;
800 }
801
802 case AMP_POLYGON: // Regular polygon
803 dim = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius
804 break;
805
806 case AMP_COMMENT:
807 case AMP_UNKNOWN:
808 case AMP_EOF:
809 break;
810 }
811
812 return dim;
813}

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(), VECTOR2< T >::x, and VECTOR2< T >::y.

◆ IsAMPrimitiveExposureOn()

bool AM_PRIMITIVE::IsAMPrimitiveExposureOn ( const GERBER_DRAW_ITEM aParent) const
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 59 of file am_primitive.cpp.

60{
61 /*
62 * Some but not all primitives use the first parameter as an exposure control.
63 * Others are always ON.
64 * In a aperture macro shape, a basic primitive with exposure off is a hole in the shape
65 * it is NOT a negative shape
66 */
67 wxASSERT( params.size() );
68
69 switch( primitive_id )
70 {
71 case AMP_CIRCLE:
72 case AMP_LINE2:
73 case AMP_LINE20:
74 case AMP_LINE_CENTER:
76 case AMP_OUTLINE:
77 case AMP_POLYGON:
78 // All have an exposure parameter and can return a value (0 or 1)
79 return params[0].GetValue( aParent->GetDcodeDescr() ) != 0;
80 break;
81
82 case AMP_THERMAL: // Exposure is always on
83 case AMP_MOIRE: // Exposure is always on
84 case AMP_EOF:
85 case AMP_UNKNOWN:
86 default:
87 return 1; // All have no exposure parameter and are always 0N return true
88 break;
89 }
90}

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 99 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 97 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: