KiCad PCB EDA Suite
am_primitive.cpp
Go to the documentation of this file.
1
5/*
6 * This program source code file is part of KiCad, a free EDA CAD application.
7 *
8 * Copyright (C) 1992-2017 Jean-Pierre Charras <jp.charras at wanadoo.fr>
9 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
10 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, you may find one here:
24 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25 * or you may search the http://www.gnu.org website for the version 2 license,
26 * or you may write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 */
29
30#include <trigo.h>
32#include <math/util.h> // for KiROUND
33
34#include <gerbview.h>
35#include <gerber_file_image.h>
36
37
41extern int scaletoIU( double aCoord, bool isMetric );
42
43
50static VECTOR2I mapPt( double x, double y, bool isMetric )
51{
52 VECTOR2I ret( scaletoIU( x, isMetric ), scaletoIU( y, isMetric ) );
53
54 return ret;
55}
56
57
59{
60 /*
61 * Some but not all primitives use the first parameter as an exposure control.
62 * Others are always ON.
63 * In a aperture macro shape, a basic primitive with exposure off is a hole in the shape
64 * it is NOT a negative shape
65 */
66 wxASSERT( m_Params.size() );
67
68 switch( m_Primitive_id )
69 {
70 case AMP_CIRCLE:
71 case AMP_LINE2:
72 case AMP_LINE20:
73 case AMP_LINE_CENTER:
75 case AMP_OUTLINE:
76 case AMP_POLYGON:
77 // All have an exposure parameter and can return a value (0 or 1)
78 return m_Params[0].GetValue( aParent->GetDcodeDescr() ) != 0;
79 break;
80
81 case AMP_THERMAL: // Exposure is always on
82 case AMP_MOIRE: // Exposure is always on
83 case AMP_EOF:
84 case AMP_UNKNOWN:
85 default:
86 return 1; // All have no exposure parameter and are always 0N return true
87 break;
88 }
89}
90
91
92// TODO(snh): Remove hard coded count
93const int seg_per_circle = 64; // Number of segments to approximate a circle
94
95
97 const VECTOR2I& aShapePos )
98{
99#define TO_POLY_SHAPE \
100 { \
101 if( polybuffer.size() > 1 ) \
102 { \
103 aShapeBuffer.NewOutline(); \
104 \
105 for( unsigned jj = 0; jj < polybuffer.size(); jj++ ) \
106 aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y ); \
107 \
108 aShapeBuffer.Append( polybuffer[0].x, polybuffer[0].y ); \
109 } \
110 }
111
112 // Draw the primitive shape for flashed items.
113 // Create a static buffer to avoid a lot of memory reallocation.
114 static std::vector<VECTOR2I> polybuffer;
115 polybuffer.clear();
116
117 VECTOR2I curPos = aShapePos;
118 D_CODE* tool = aParent->GetDcodeDescr();
119
120 switch( m_Primitive_id )
121 {
122 case AMP_CIRCLE: // Circle, given diameter and position
123 {
124 /* Generated by an aperture macro declaration like:
125 * "1,1,0.3,0.5, 1.0*"
126 * type (1), exposure, diameter, pos.x, pos.y, <rotation>
127 * <rotation> is a optional parameter: rotation from origin.
128 * type is not stored in parameters list, so the first parameter is exposure
129 */
130 ConvertShapeToPolygon( aParent, polybuffer );
131
132 // shape rotation (if any):
133 if( m_Params.size() >= 5 )
134 {
135 EDA_ANGLE rotation( m_Params[4].GetValue( tool ), DEGREES_T );
136
137 if( !rotation.IsZero() )
138 {
139 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
140 RotatePoint( polybuffer[ii], -rotation );
141 }
142 }
143
144
145 // Move to current position:
146 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
147 {
148 polybuffer[ii] += curPos;
149 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
150 }
151
153 break;
154 }
155
156 case AMP_LINE2:
157 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
158 {
159 /* Vector Line, Primitive Code 20.
160 * A vector line is a rectangle defined by its line width, start and end points.
161 * The line ends are rectangular.
162 */
163 /* Generated by an aperture macro declaration like:
164 * "2,1,0.3,0,0, 0.5, 1.0,-135*"
165 * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
166 * type is not stored in parameters list, so the first parameter is exposure
167 */
168 ConvertShapeToPolygon( aParent, polybuffer );
169
170 // shape rotation:
171 EDA_ANGLE rotation( m_Params[6].GetValue( tool ), DEGREES_T );
172
173 if( !rotation.IsZero() )
174 {
175 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
176 RotatePoint( polybuffer[ii], -rotation );
177 }
178
179 // Move to current position:
180 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
181 {
182 polybuffer[ii] += curPos;
183 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
184 }
185
187 break;
188 }
189
190 case AMP_LINE_CENTER:
191 {
192 /* Center Line, Primitive Code 21
193 * A center line primitive is a rectangle defined by its width, height, and center point
194 */
195 /* Generated by an aperture macro declaration like:
196 * "21,1,0.3,0.03,0,0,-135*"
197 * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
198 * type is not stored in parameters list, so the first parameter is exposure
199 */
200 ConvertShapeToPolygon( aParent, polybuffer );
201
202 // shape rotation:
203 EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
204
205 if( !rotation.IsZero() )
206 {
207 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
208 RotatePoint( polybuffer[ii], -rotation );
209 }
210
211 // Move to current position:
212 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
213 {
214 polybuffer[ii] += curPos;
215 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
216 }
217
219 break;
220 }
221
223 {
224 /* Generated by an aperture macro declaration like:
225 * "22,1,0.3,0.03,0,0,-135*"
226 * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
227 * type is not stored in parameters list, so the first parameter is exposure
228 */
229 ConvertShapeToPolygon( aParent, polybuffer );
230
231 // shape rotation:
232 EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
233
234 if( !rotation.IsZero() )
235 {
236 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
237 RotatePoint( polybuffer[ii], -rotation );
238 }
239
240 // Move to current position:
241 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
242 {
243 polybuffer[ii] += curPos;
244 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
245 }
246
248 break;
249 }
250
251 case AMP_THERMAL:
252 {
253 /* Generated by an aperture macro declaration like:
254 * "7, 0,0,1.0,0.3,0.01,-13*"
255 * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
256 * type is not stored in parameters list, so the first parameter is center.x
257 *
258 * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always
259 * on.
260 */
261 std::vector<VECTOR2I> subshape_poly;
262 curPos += mapPt( m_Params[0].GetValue( tool ), m_Params[1].GetValue( tool ), m_GerbMetric );
263 ConvertShapeToPolygon( aParent, subshape_poly );
264
265 // shape rotation:
266 EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
267
268 // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
269 // We must draw 4 sub-shapes rotated by 90 deg
270 for( int ii = 0; ii < 4; ii++ )
271 {
272 polybuffer = subshape_poly;
273 EDA_ANGLE sub_rotation = rotation + ANGLE_90 * ii;
274
275 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
276 RotatePoint( polybuffer[jj], -sub_rotation );
277
278 // Move to current position:
279 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
280 {
281 polybuffer[jj] += curPos;
282 polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] );
283 }
284
286 }
287 }
288 break;
289
290 case AMP_MOIRE:
291 {
292 /* Moire, Primitive Code 6
293 * The moire primitive is a cross hair centered on concentric rings (annuli).
294 * Exposure is always on.
295 */
296 curPos += mapPt( m_Params[0].GetValue( tool ), m_Params[1].GetValue( tool ),
297 m_GerbMetric );
298
299 /* Generated by an aperture macro declaration like:
300 * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
301 * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness,
302 * crosshair len, rotation. The type is not stored in parameters list, so the first
303 * parameter is pos.x.
304 */
305 int outerDiam = scaletoIU( m_Params[2].GetValue( tool ), m_GerbMetric );
306 int penThickness = scaletoIU( m_Params[3].GetValue( tool ), m_GerbMetric );
307 int gap = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric );
308 int numCircles = KiROUND( m_Params[5].GetValue( tool ) );
309
310 // Draw circles:
311 VECTOR2I center = aParent->GetABPosition( curPos );
312
313 // adjust outerDiam by this on each nested circle
314 int diamAdjust = ( gap + penThickness ) * 2;
315
316 for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
317 {
318 if( outerDiam <= 0 )
319 break;
320
321 // Note: outerDiam is the outer diameter of the ring.
322 // the ring graphic diameter is (outerDiam - penThickness)
323 if( outerDiam <= penThickness )
324 { // No room to draw a ring (no room for the hole):
325 // draw a circle instead (with no hole), with the right diameter
326 TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, ARC_HIGH_DEF,
327 ERROR_INSIDE );
328 }
329 else
330 {
331 TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2,
332 penThickness, ARC_HIGH_DEF, ERROR_INSIDE );
333 }
334 }
335
336 // Draw the cross:
337 ConvertShapeToPolygon( aParent, polybuffer );
338
339 EDA_ANGLE rotation( m_Params[8].GetValue( tool ), DEGREES_T );
340
341 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
342 {
343 // shape rotation:
344 RotatePoint( polybuffer[ii], -rotation );
345
346 // Move to current position:
347 polybuffer[ii] += curPos;
348 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
349 }
350
352 break;
353 }
354
355 case AMP_OUTLINE:
356 {
357 /* Outline, Primitive Code 4
358 * An outline primitive is an area enclosed by an n-point polygon defined by its start
359 * point and n
360 * subsequent points. The outline must be closed, i.e. the last point must be equal to
361 * the start point. There must be at least one subsequent point (to close the outline).
362 * The outline of the primitive is actually the contour (see 2.6) that consists of linear
363 * segments only, so it must conform to all the requirements described for contours.
364 * Warning: Make no mistake: n is the number of subsequent points, being the number of
365 * vertices of the outline or one less than the number of coordinate pairs.
366 */
367 /* Generated by an aperture macro declaration like:
368 * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
369 * type(4), exposure, corners count, corner1.x, corner.1y, ..., corner1.x, corner.1y,
370 * rotation
371 * type is not stored in parameters list, so the first parameter is exposure
372 */
373 // m_Params[0] is the exposure and m_Params[1] is the corners count after the first corner
374 int numCorners = (int) m_Params[1].GetValue( tool );
375
376 // the shape rotation is the last param of list, after corners
377 int last_prm = m_Params.size() - 1;
378 EDA_ANGLE rotation( m_Params[last_prm].GetValue( tool ), DEGREES_T );
379 VECTOR2I pos;
380
381 // Read points.
382 // Note: numCorners is the polygon corner count, following the first corner
383 // * the polygon is always closed,
384 // * therefore the last XY coordinate is the same as the first
385 int prm_idx = 2; // m_Params[2] is the first X coordinate
386
387 for( int i = 0; i <= numCorners; ++i )
388 {
389 pos.x = scaletoIU( m_Params[prm_idx].GetValue( tool ), m_GerbMetric );
390 prm_idx++;
391 pos.y = scaletoIU( m_Params[prm_idx].GetValue( tool ), m_GerbMetric );
392 prm_idx++;
393 polybuffer.push_back(pos);
394
395 // Guard: ensure prm_idx < last_prm
396 // I saw malformed gerber files with numCorners = number
397 // of coordinates instead of number of coordinates following the first point
398 if( prm_idx >= last_prm )
399 break;
400 }
401
402 // rotate polygon and move it to the actual position shape rotation:
403 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
404 {
405 RotatePoint( polybuffer[ii], -rotation );
406 }
407
408 // Move to current position:
409 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
410 {
411 polybuffer[ii] += curPos;
412 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
413 }
414
416 break;
417 }
418
419 case AMP_POLYGON:
420 {
421 /* Polygon, Primitive Code 5
422 * A polygon primitive is a regular polygon defined by the number of vertices n, the
423 * center point and the diameter of the circumscribed circle
424 */
425 /* Generated by an aperture macro declaration like:
426 * "5,1,0.6,0,0,0.5,25"
427 * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
428 * type is not stored in parameters list, so the first parameter is exposure
429 */
430 curPos += mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ), m_GerbMetric );
431
432 // Creates the shape:
433 ConvertShapeToPolygon( aParent, polybuffer );
434
435 // rotate polygon and move it to the actual position
436 EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
437
438 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
439 {
440 RotatePoint( polybuffer[ii], -rotation );
441 polybuffer[ii] += curPos;
442 polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
443 }
444
446
447 break;
448 }
449
450 case AMP_EOF:
451 // not yet supported, waiting for you.
452 break;
453
454 case AMP_UNKNOWN:
455 default:
456 break;
457 }
458}
459
460
462 std::vector<VECTOR2I>& aBuffer )
463{
464 D_CODE* tool = aParent->GetDcodeDescr();
465
466 switch( m_Primitive_id )
467 {
468 case AMP_CIRCLE:
469 {
470 /* Generated by an aperture macro declaration like:
471 * "1,1,0.3,0.5, 1.0*"
472 * type (1), exposure, diameter, pos.x, pos.y, <rotation>
473 * <rotation> is a optional parameter: rotation from origin.
474 * type is not stored in parameters list, so the first parameter is exposure
475 */
476 int radius = scaletoIU( m_Params[1].GetValue( tool ), m_GerbMetric ) / 2;
477
478 // A circle primitive can have a 0 size (for instance when used in roundrect macro),
479 // so skip it
480 if( radius <= 0 )
481 break;
482
483 VECTOR2I center = mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ),
484 m_GerbMetric );
485 VECTOR2I corner;
486 EDA_ANGLE delta = ANGLE_360 / seg_per_circle; // rot angle in 0.1 degree
487
489 {
490 corner.x = radius;
491 corner.y = 0;
492 RotatePoint( corner, angle );
493 corner += center;
494 aBuffer.push_back( corner );
495 }
496
497 break;
498 }
499
500 case AMP_LINE2:
501 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
502 {
503 int width = scaletoIU( m_Params[1].GetValue( tool ), m_GerbMetric );
504 VECTOR2I start =
505 mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ), m_GerbMetric );
506 VECTOR2I end =
507 mapPt( m_Params[4].GetValue( tool ), m_Params[5].GetValue( tool ), m_GerbMetric );
508 VECTOR2I delta = end - start;
509 int len = KiROUND( EuclideanNorm( delta ) );
510
511 // To build the polygon, we must create a horizontal polygon starting to "start"
512 // and rotate it to have the end point to "end"
513 VECTOR2I currpt;
514 currpt.y += width / 2; // Upper left
515 aBuffer.push_back( currpt );
516 currpt.x = len; // Upper right
517 aBuffer.push_back( currpt );
518 currpt.y -= width; // lower right
519 aBuffer.push_back( currpt );
520 currpt.x = 0; // lower left
521 aBuffer.push_back( currpt );
522
523 // Rotate rectangle and move it to the actual start point
525
526 for( unsigned ii = 0; ii < 4; ii++ )
527 {
528 RotatePoint( aBuffer[ii], -angle );
529 aBuffer[ii] += start;
530 }
531
532 break;
533 }
534
535 case AMP_LINE_CENTER:
536 {
537 VECTOR2I size =
538 mapPt( m_Params[1].GetValue( tool ), m_Params[2].GetValue( tool ), m_GerbMetric );
539 VECTOR2I pos =
540 mapPt( m_Params[3].GetValue( tool ), m_Params[4].GetValue( tool ), m_GerbMetric );
541
542 // Build poly:
543 pos.x -= size.x / 2;
544 pos.y -= size.y / 2; // Lower left
545 aBuffer.push_back( pos );
546 pos.y += size.y; // Upper left
547 aBuffer.push_back( pos );
548 pos.x += size.x; // Upper right
549 aBuffer.push_back( pos );
550 pos.y -= size.y; // lower right
551 aBuffer.push_back( pos );
552 break;
553 }
554
556 {
557 VECTOR2I size =
558 mapPt( m_Params[1].GetValue( tool ), m_Params[2].GetValue( tool ), m_GerbMetric );
559 VECTOR2I lowerLeft =
560 mapPt( m_Params[3].GetValue( tool ), m_Params[4].GetValue( tool ), m_GerbMetric );
561
562 // Build poly:
563 aBuffer.push_back( lowerLeft );
564 lowerLeft.y += size.y; // Upper left
565 aBuffer.push_back( lowerLeft );
566 lowerLeft.x += size.x; // Upper right
567 aBuffer.push_back( lowerLeft );
568 lowerLeft.y -= size.y; // lower right
569 aBuffer.push_back( lowerLeft );
570 break;
571 }
572
573 case AMP_THERMAL:
574 {
575 // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from
576 // this first rotated by 90, 180 and 270 deg.
577 // m_Params = center.x (unused here), center.y (unused here), outside diam, inside diam,
578 // crosshair thickness.
579 int outerRadius = scaletoIU( m_Params[2].GetValue( tool ), m_GerbMetric ) / 2;
580 int innerRadius = scaletoIU( m_Params[3].GetValue( tool ), m_GerbMetric ) / 2;
581
582 // Safety checks to guarantee no divide-by-zero
583 outerRadius = std::max( 1, outerRadius );
584 innerRadius = std::max( 1, innerRadius );
585
586 int halfthickness = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric ) / 2;
587 EDA_ANGLE angle_start( asin( (double) halfthickness / innerRadius ), RADIANS_T );
588
589 // Draw shape in the first quadrant (X and Y > 0)
590 VECTOR2I pos, startpos;
591
592 // Inner arc
593 startpos.x = innerRadius;
594 EDA_ANGLE angle_end = ANGLE_90 - angle_start;
595
596 for( EDA_ANGLE angle = angle_start; angle < angle_end; angle += EDA_ANGLE( 10, DEGREES_T ) )
597 {
598 pos = startpos;
599 RotatePoint( pos, angle );
600 aBuffer.push_back( pos );
601 }
602
603 // Last point
604 pos = startpos;
605 RotatePoint( pos, angle_end );
606 aBuffer.push_back( pos );
607
608 // outer arc
609 startpos.x = outerRadius;
610 startpos.y = 0;
611 angle_start = EDA_ANGLE( asin( (double) halfthickness / outerRadius ), RADIANS_T );
612 angle_end = ANGLE_90 - angle_start;
613
614 // First point, near Y axis, outer arc
615 for( EDA_ANGLE angle = angle_end; angle > angle_start; angle -= EDA_ANGLE( 10, DEGREES_T ) )
616 {
617 pos = startpos;
618 RotatePoint( pos, angle );
619 aBuffer.push_back( pos );
620 }
621
622 // last point
623 pos = startpos;
624 RotatePoint( pos, angle_start );
625 aBuffer.push_back( pos );
626
627 aBuffer.push_back( aBuffer[0] ); // Close poly
628 }
629 break;
630
631 case AMP_MOIRE:
632 {
633 // A cross hair with n concentric circles. Only the cross is built as
634 // polygon because circles can be drawn easily
635 int crossHairThickness = scaletoIU( m_Params[6].GetValue( tool ), m_GerbMetric );
636 int crossHairLength = scaletoIU( m_Params[7].GetValue( tool ), m_GerbMetric );
637
638 // Create cross. First create 1/4 of the shape.
639 // Others point are the same, rotated by 90, 180 and 270 deg
640 VECTOR2I pos( crossHairThickness / 2, crossHairLength / 2 );
641 aBuffer.push_back( pos );
642 pos.y = crossHairThickness / 2;
643 aBuffer.push_back( pos );
644 pos.x = -crossHairLength / 2;
645 aBuffer.push_back( pos );
646 pos.y = -crossHairThickness / 2;
647 aBuffer.push_back( pos );
648
649 // Copy the 4 shape, rotated by 90, 180 and 270 deg
650 for( int jj = 1; jj <= 3; jj ++ )
651 {
652 for( int ii = 0; ii < 4; ii++ )
653 {
654 pos = aBuffer[ii];
655 RotatePoint( pos, ANGLE_90 * jj );
656 aBuffer.push_back( pos );
657 }
658 }
659
660 break;
661 }
662
663 case AMP_OUTLINE:
664 // already is a polygon. Do nothing
665 break;
666
667 case AMP_POLYGON: // Creates a regular polygon
668 {
669 int vertexcount = KiROUND( m_Params[1].GetValue( tool ) );
670 int radius = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric ) / 2;
671
672 // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
673 if( vertexcount < 3 )
674 vertexcount = 3;
675
676 if( vertexcount > 10 )
677 vertexcount = 10;
678
679 for( int ii = 0; ii <= vertexcount; ii++ )
680 {
681 VECTOR2I pos( radius, 0 );
682 RotatePoint( pos, ANGLE_360 * ii / vertexcount );
683 aBuffer.push_back( pos );
684 }
685
686 break;
687 }
688
689 case AMP_COMMENT:
690 case AMP_UNKNOWN:
691 case AMP_EOF:
692 break;
693 }
694}
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.
#define TO_POLY_SHAPE
@ AMP_POLYGON
Definition: am_primitive.h:80
@ AMP_LINE_LOWER_LEFT
Definition: am_primitive.h:77
@ AMP_LINE2
Definition: am_primitive.h:74
@ AMP_CIRCLE
Definition: am_primitive.h:73
@ AMP_THERMAL
Definition: am_primitive.h:83
@ AMP_EOF
Definition: am_primitive.h:78
@ AMP_UNKNOWN
Definition: am_primitive.h:70
@ AMP_COMMENT
Definition: am_primitive.h:71
@ AMP_LINE_CENTER
Definition: am_primitive.h:76
@ AMP_MOIRE
Definition: am_primitive.h:82
@ AMP_OUTLINE
Definition: am_primitive.h:79
@ AMP_LINE20
Definition: am_primitive.h:75
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
void ConvertShapeToPolygon(const GERBER_DRAW_ITEM *aParent, std::vector< VECTOR2I > &aBuffer)
Convert a shape to an equivalent polygon.
bool IsAMPrimitiveExposureOn(const GERBER_DRAW_ITEM *aParent) const
AM_PARAMS m_Params
A sequence of parameters used by the primitive.
Definition: am_primitive.h:96
void ConvertBasicShapeToPolygon(const GERBER_DRAW_ITEM *aParent, SHAPE_POLY_SET &aShapeBuffer, const VECTOR2I &aShapePos)
Generate the polygonal shape of the primitive shape of an aperture macro instance.
AM_PRIMITIVE_ID m_Primitive_id
The primitive type.
Definition: am_primitive.h:95
bool m_GerbMetric
Definition: am_primitive.h:97
A gerber DCODE (also called Aperture) definition.
Definition: dcode.h:80
bool IsZero() const
Definition: eda_angle.h:169
D_CODE * GetDcodeDescr() const
Return the GetDcodeDescr of this object, or NULL.
VECTOR2I GetABPosition(const VECTOR2I &aXYPosition) const
Return the image position of aPosition for this object.
Represent a set of closed polygons.
void TransformRingToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arcs to multiple straight segments.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
@ RADIANS_T
Definition: eda_angle.h:32
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:418
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:414
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
@ ERROR_INSIDE
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:85