KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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].GetValueFromMacro( aApertMacro ) != 0;
79 break;
80
81 case AMP_THERMAL: // Exposure is always on
82 case AMP_MOIRE: // Exposure is always on
83 case AMP_UNKNOWN:
84 default:
85 return 1; // All have no exposure parameter and are always 0N return true
86 break;
87 }
88}
89
90
92 SHAPE_POLY_SET& aShapeBuffer )
93{
94 // Draw the primitive shape for flashed items.
95 // Note: rotation of primitives inside a macro must be always done around the macro origin.
96 // Create a static buffer to avoid a lot of memory reallocation.
97 static std::vector<VECTOR2I> polybuffer;
98 polybuffer.clear();
99
100 aApertMacro->EvalLocalParams( *this );
101
102 switch( m_Primitive_id )
103 {
104 case AMP_CIRCLE: // Circle, given diameter and position
105 {
106 /* Generated by an aperture macro declaration like:
107 * "1,1,0.3,0.5, 1.0*"
108 * type (1), exposure, diameter, pos.x, pos.y, <rotation>
109 * <rotation> is a optional parameter: rotation from origin.
110 * type is not stored in parameters list, so the first parameter is exposure
111 */
112 ConvertShapeToPolygon( aApertMacro, polybuffer );
113
114 // shape rotation (if any):
115 if( m_Params.size() >= 5 )
116 {
117 EDA_ANGLE rotation( m_Params[4].GetValueFromMacro( aApertMacro ), DEGREES_T );
118
119 if( !rotation.IsZero() )
120 {
121 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
122 RotatePoint( polybuffer[ii], -rotation );
123 }
124 }
125
126 break;
127 }
128
129 case AMP_LINE2:
130 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
131 {
132 /* Vector Line, Primitive Code 20.
133 * A vector line is a rectangle defined by its line width, start and end points.
134 * The line ends are rectangular.
135 */
136 /* Generated by an aperture macro declaration like:
137 * "2,1,0.3,0,0, 0.5, 1.0,-135*"
138 * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
139 * type is not stored in parameters list, so the first parameter is exposure
140 */
141 ConvertShapeToPolygon( aApertMacro, polybuffer );
142
143 // shape rotation:
144 EDA_ANGLE rotation( m_Params[6].GetValueFromMacro( aApertMacro ), DEGREES_T );
145
146 if( !rotation.IsZero() )
147 {
148 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
149 RotatePoint( polybuffer[ii], -rotation );
150 }
151
152 break;
153 }
154
155 case AMP_LINE_CENTER:
156 {
157 /* Center Line, Primitive Code 21
158 * A center line primitive is a rectangle defined by its width, height, and center point
159 */
160 /* Generated by an aperture macro declaration like:
161 * "21,1,0.3,0.03,0,0,-135*"
162 * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
163 * type is not stored in parameters list, so the first parameter is exposure
164 */
165 ConvertShapeToPolygon( aApertMacro, polybuffer );
166
167 // shape rotation:
168 EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
169
170 if( !rotation.IsZero() )
171 {
172 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
173 RotatePoint( polybuffer[ii], -rotation );
174 }
175
176 break;
177 }
178
180 {
181 /* Generated by an aperture macro declaration like:
182 * "22,1,0.3,0.03,0,0,-135*"
183 * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
184 * type is not stored in parameters list, so the first parameter is exposure
185 */
186 ConvertShapeToPolygon( aApertMacro, polybuffer );
187
188 // shape rotation:
189 EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
190
191 if( !rotation.IsZero() )
192 {
193 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
194 RotatePoint( polybuffer[ii], -rotation );
195 }
196 break;
197 }
198
199 case AMP_THERMAL:
200 {
201 /* Generated by an aperture macro declaration like:
202 * "7, 0,0,1.0,0.3,0.01,-13*"
203 * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
204 * type is not stored in parameters list, so the first parameter is center.x
205 *
206 * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always
207 * on.
208 */
209 std::vector<VECTOR2I> subshape_poly;
210 VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
211 m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
212 ConvertShapeToPolygon( aApertMacro, subshape_poly );
213
214 // shape rotation:
215 EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
216
217 // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
218 // We must draw 4 sub-shapes rotated by 90 deg
219 for( int ii = 0; ii < 4; ii++ )
220 {
221 polybuffer = subshape_poly;
222 EDA_ANGLE sub_rotation = ANGLE_90 * ii;
223
224 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
225 RotatePoint( polybuffer[jj], -sub_rotation );
226
227 // Move to center position given by the tool, and rotate the full shape around
228 // the center position (origin of the macro):
229 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
230 {
231 polybuffer[jj] += center;
232 RotatePoint( polybuffer[jj], -rotation );
233 }
234
235 aShapeBuffer.NewOutline();
236
237 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
238 aShapeBuffer.Append( polybuffer[jj] );
239
240 aShapeBuffer.Append( polybuffer[0] );
241 }
242 }
243 break;
244
245 case AMP_MOIRE:
246 {
247 /* Moire, Primitive Code 6
248 * The moire primitive is a cross hair centered on concentric rings (annuli).
249 * Exposure is always on.
250 */
251
252 /* Generated by an aperture macro declaration like:
253 * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
254 * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness,
255 * crosshair len, rotation. The type is not stored in parameters list, so the first
256 * parameter is pos.x.
257 */
258 int outerDiam = scaletoIU( m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
259 int penThickness = scaletoIU( m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric );
260 int gap = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
261 int numCircles = KiROUND( m_Params[5].GetValueFromMacro( aApertMacro ) );
262
263 // Adjust the allowed approx error to convert arcs to segments:
264 int arc_to_seg_error = gerbIUScale.mmToIU( 0.005 ); // Allow 5 microns
265
266 // Draw circles @ position pos.x, pos.y given by the tool:
267 VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
268 m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
269
270 EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
271
272 // adjust outerDiam by this on each nested circle
273 int diamAdjust = ( gap + penThickness ) * 2;
274
275 for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
276 {
277 if( outerDiam <= 0 )
278 break;
279
280 // calculate the rotated position of the center:
281 VECTOR2I circle_center = center;
282 RotatePoint( circle_center, -rotation );
283
284 // Note: outerDiam is the outer diameter of the ring.
285 // the ring graphic diameter is (outerDiam - penThickness)
286 if( outerDiam <= penThickness )
287 { // No room to draw a ring (no room for the hole):
288 // draw a circle instead (with no hole), with the right diameter
289 TransformCircleToPolygon( aShapeBuffer, circle_center, outerDiam / 2, arc_to_seg_error,
290 ERROR_INSIDE );
291 }
292 else
293 {
294 TransformRingToPolygon( aShapeBuffer, circle_center, ( outerDiam - penThickness ) / 2,
295 penThickness, arc_to_seg_error, ERROR_INSIDE );
296 }
297 }
298
299 // Draw the cross:
300 ConvertShapeToPolygon( aApertMacro, polybuffer );
301
302 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
303 {
304 // move crossair shape to center and rotate shape:
305 polybuffer[ii] += center;
306 RotatePoint( polybuffer[ii], -rotation );
307 }
308
309 break;
310 }
311
312 case AMP_OUTLINE:
313 {
314 /* Outline, Primitive Code 4
315 * An outline primitive is an area enclosed by an n-point polygon defined by its start
316 * point and n
317 * subsequent points. The outline must be closed, i.e. the last point must be equal to
318 * the start point. There must be at least one subsequent point (to close the outline).
319 * The outline of the primitive is actually the contour (see 2.6) that consists of linear
320 * segments only, so it must conform to all the requirements described for contours.
321 * Warning: Make no mistake: n is the number of subsequent points, being the number of
322 * vertices of the outline or one less than the number of coordinate pairs.
323 */
324 /* Generated by an aperture macro declaration like:
325 * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
326 * type(4), exposure, corners count, corner1.x, corner.1y, ..., corner1.x, corner.1y,
327 * rotation
328 * type is not stored in parameters list, so the first parameter is exposure
329 */
330 // m_Params[0] is the exposure and m_Params[1] is the corners count after the first corner
331 int numCorners = (int) m_Params[1].GetValueFromMacro( aApertMacro );
332
333 // the shape rotation is the last param of list, after corners
334 int last_prm = m_Params.size() - 1;
335 EDA_ANGLE rotation( m_Params[last_prm].GetValueFromMacro( aApertMacro ), DEGREES_T );
336 VECTOR2I pos;
337
338 // Read points.
339 // Note: numCorners is the polygon corner count, following the first corner
340 // * the polygon is always closed,
341 // * therefore the last XY coordinate is the same as the first
342 int prm_idx = 2; // m_Params[2] is the first X coordinate
343
344 for( int i = 0; i <= numCorners; ++i )
345 {
346 pos.x = scaletoIU( m_Params[prm_idx].GetValueFromMacro( aApertMacro ), m_GerbMetric );
347 prm_idx++;
348 pos.y = scaletoIU( m_Params[prm_idx].GetValueFromMacro( aApertMacro ), m_GerbMetric );
349 prm_idx++;
350 polybuffer.push_back(pos);
351
352 // Guard: ensure prm_idx < last_prm
353 // I saw malformed gerber files with numCorners = number
354 // of coordinates instead of number of coordinates following the first point
355 if( prm_idx >= last_prm )
356 break;
357 }
358
359 // rotate polygon and move it to the actual position shape rotation:
360 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
361 {
362 RotatePoint( polybuffer[ii], -rotation );
363 }
364
365 break;
366 }
367
368 case AMP_POLYGON:
369 {
370 /* Polygon, Primitive Code 5
371 * A polygon primitive is a regular polygon defined by the number of vertices n, the
372 * center point and the diameter of the circumscribed circle
373 */
374 /* Generated by an aperture macro declaration like:
375 * "5,1,0.6,0,0,0.5,25"
376 * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
377 * type is not stored in parameters list, so the first parameter is exposure
378 */
379 VECTOR2I curPos( mapPt( m_Params[2].GetValueFromMacro( aApertMacro ),
380 m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
381
382 // Creates the shape:
383 ConvertShapeToPolygon( aApertMacro, polybuffer );
384
385 // move and rotate polygonal shape
386 EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
387
388 for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
389 {
390 polybuffer[ii] += curPos;
391 RotatePoint( polybuffer[ii], -rotation );
392 }
393
394 break;
395 }
396
397 case AMP_COMMENT:
398 case AMP_UNKNOWN:
399 break;
400 }
401
402 if( polybuffer.size() > 1 ) // a valid polygon has more than 1 corner
403 {
404 aShapeBuffer.NewOutline();
405
406 for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
407 aShapeBuffer.Append( polybuffer[jj] );
408
409 // Close the shape:
410 aShapeBuffer.Append( polybuffer[0] );
411 }
412}
413
414
416 std::vector<VECTOR2I>& aBuffer )
417{
418 switch( m_Primitive_id )
419 {
420 case AMP_CIRCLE:
421 {
422 /* Generated by an aperture macro declaration like:
423 * "1,1,0.3,0.5, 1.0*"
424 * type (1), exposure, diameter, pos.x, pos.y, <rotation>
425 * <rotation> is a optional parameter: rotation from origin.
426 * type is not stored in parameters list, so the first parameter is exposure
427 */
428 int radius = scaletoIU( m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
429
430 // A circle primitive can have a 0 size (for instance when used in roundrect macro),
431 // so skip it
432 if( radius <= 0 )
433 break;
434
435 VECTOR2I center = mapPt( m_Params[2].GetValueFromMacro( aApertMacro ), m_Params[3].GetValueFromMacro( aApertMacro ),
436 m_GerbMetric );
437 VECTOR2I corner;
438
439 const int seg_per_circle = 64; // Number of segments to approximate a circle
440 EDA_ANGLE delta = ANGLE_360 / seg_per_circle;
441
442 for( EDA_ANGLE angle = ANGLE_0; angle < ANGLE_360; angle += delta )
443 {
444 corner.x = radius;
445 corner.y = 0;
446 RotatePoint( corner, angle );
447 corner += center;
448 aBuffer.push_back( corner );
449 }
450
451 break;
452 }
453
454 case AMP_LINE2:
455 case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
456 {
457 int width = scaletoIU( m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric );
458 VECTOR2I start =
459 mapPt( m_Params[2].GetValueFromMacro( aApertMacro ), m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric );
460 VECTOR2I end =
461 mapPt( m_Params[4].GetValueFromMacro( aApertMacro ), m_Params[5].GetValueFromMacro( aApertMacro ), m_GerbMetric );
462 VECTOR2I delta = end - start;
463 int len = delta.EuclideanNorm();
464
465 // To build the polygon, we must create a horizontal polygon starting to "start"
466 // and rotate it to have the end point to "end"
467 VECTOR2I currpt;
468 currpt.y += width / 2; // Upper left
469 aBuffer.push_back( currpt );
470 currpt.x = len; // Upper right
471 aBuffer.push_back( currpt );
472 currpt.y -= width; // lower right
473 aBuffer.push_back( currpt );
474 currpt.x = 0; // lower left
475 aBuffer.push_back( currpt );
476
477 // Rotate rectangle and move it to the actual start point
478 EDA_ANGLE angle( delta );
479
480 for( unsigned ii = 0; ii < 4; ii++ )
481 {
482 RotatePoint( aBuffer[ii], -angle );
483 aBuffer[ii] += start;
484 }
485
486 break;
487 }
488
489 case AMP_LINE_CENTER:
490 {
491 VECTOR2I size =
492 mapPt( m_Params[1].GetValueFromMacro( aApertMacro ), m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
493 VECTOR2I pos =
494 mapPt( m_Params[3].GetValueFromMacro( aApertMacro ), m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
495
496 // Build poly:
497 pos.x -= size.x / 2;
498 pos.y -= size.y / 2; // Lower left
499 aBuffer.push_back( pos );
500 pos.y += size.y; // Upper left
501 aBuffer.push_back( pos );
502 pos.x += size.x; // Upper right
503 aBuffer.push_back( pos );
504 pos.y -= size.y; // lower right
505 aBuffer.push_back( pos );
506 break;
507 }
508
510 {
511 VECTOR2I size =
512 mapPt( m_Params[1].GetValueFromMacro( aApertMacro ), m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
513 VECTOR2I lowerLeft =
514 mapPt( m_Params[3].GetValueFromMacro( aApertMacro ), m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
515
516 // Build poly:
517 aBuffer.push_back( lowerLeft );
518 lowerLeft.y += size.y; // Upper left
519 aBuffer.push_back( lowerLeft );
520 lowerLeft.x += size.x; // Upper right
521 aBuffer.push_back( lowerLeft );
522 lowerLeft.y -= size.y; // lower right
523 aBuffer.push_back( lowerLeft );
524 break;
525 }
526
527 case AMP_THERMAL:
528 {
529 // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from
530 // this first rotated by 90, 180 and 270 deg.
531 // m_Params = center.x (unused here), center.y (unused here), outside diam, inside diam,
532 // crosshair thickness.
533 int outerRadius = scaletoIU( m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
534 int innerRadius = scaletoIU( m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
535
536 // Safety checks to guarantee no divide-by-zero
537 outerRadius = std::max( 1, outerRadius );
538 innerRadius = std::max( 1, innerRadius );
539
540 int halfthickness = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
541 EDA_ANGLE angle_start( asin( (double) halfthickness / innerRadius ), RADIANS_T );
542
543 // Draw shape in the first quadrant (X and Y > 0)
544 VECTOR2I pos, startpos;
545
546 // Inner arc
547 startpos.x = innerRadius;
548 EDA_ANGLE angle_end = ANGLE_90 - angle_start;
549
550 for( EDA_ANGLE angle = angle_start; angle < angle_end; angle += EDA_ANGLE( 10, DEGREES_T ) )
551 {
552 pos = startpos;
553 RotatePoint( pos, angle );
554 aBuffer.push_back( pos );
555 }
556
557 // Last point
558 pos = startpos;
559 RotatePoint( pos, angle_end );
560 aBuffer.push_back( pos );
561
562 // outer arc
563 startpos.x = outerRadius;
564 startpos.y = 0;
565 angle_start = EDA_ANGLE( asin( (double) halfthickness / outerRadius ), RADIANS_T );
566 angle_end = ANGLE_90 - angle_start;
567
568 // First point, near Y axis, outer arc
569 for( EDA_ANGLE angle = angle_end; angle > angle_start; angle -= EDA_ANGLE( 10, DEGREES_T ) )
570 {
571 pos = startpos;
572 RotatePoint( pos, angle );
573 aBuffer.push_back( pos );
574 }
575
576 // last point
577 pos = startpos;
578 RotatePoint( pos, angle_start );
579 aBuffer.push_back( pos );
580
581 aBuffer.push_back( aBuffer[0] ); // Close poly
582 }
583 break;
584
585 case AMP_MOIRE:
586 {
587 // A cross hair with n concentric circles. Only the cross is built as
588 // polygon because circles can be drawn easily
589 int crossHairThickness = scaletoIU( m_Params[6].GetValueFromMacro( aApertMacro ), m_GerbMetric );
590 int crossHairLength = scaletoIU( m_Params[7].GetValueFromMacro( aApertMacro ), m_GerbMetric );
591
592 // Create cross. First create 1/4 of the shape.
593 // Others point are the same, rotated by 90, 180 and 270 deg
594 VECTOR2I pos( crossHairThickness / 2, crossHairLength / 2 );
595 aBuffer.push_back( pos );
596 pos.y = crossHairThickness / 2;
597 aBuffer.push_back( pos );
598 pos.x = -crossHairLength / 2;
599 aBuffer.push_back( pos );
600 pos.y = -crossHairThickness / 2;
601 aBuffer.push_back( pos );
602
603 // Copy the 4 shape, rotated by 90, 180 and 270 deg
604 for( int jj = 1; jj <= 3; jj ++ )
605 {
606 for( int ii = 0; ii < 4; ii++ )
607 {
608 pos = aBuffer[ii];
609 RotatePoint( pos, ANGLE_90 * jj );
610 aBuffer.push_back( pos );
611 }
612 }
613
614 break;
615 }
616
617 case AMP_OUTLINE:
618 // already is a polygon. Do nothing
619 break;
620
621 case AMP_POLYGON: // Creates a regular polygon
622 {
623 int vertexcount = KiROUND( m_Params[1].GetValueFromMacro( aApertMacro ) );
624 int radius = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
625
626 // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
627 if( vertexcount < 3 )
628 vertexcount = 3;
629
630 if( vertexcount > 10 )
631 vertexcount = 10;
632
633 for( int ii = 0; ii <= vertexcount; ii++ )
634 {
635 VECTOR2I pos( radius, 0 );
636 RotatePoint( pos, ANGLE_360 * ii / vertexcount );
637 aBuffer.push_back( pos );
638 }
639
640 break;
641 }
642
643 case AMP_COMMENT:
644 case AMP_UNKNOWN:
645 break;
646 }
647}
int scaletoIU(double aCoord, bool isMetric)
Convert a distance given in floating point to our internal units.
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:79
@ 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:82
@ 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:81
@ AMP_OUTLINE
Definition: am_primitive.h:78
@ AMP_LINE20
Definition: am_primitive.h:75
@ ERROR_INSIDE
Definition: approximation.h:34
constexpr EDA_IU_SCALE gerbIUScale
Definition: base_units.h:107
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
void ConvertBasicShapeToPolygon(APERTURE_MACRO *aApertMacro, SHAPE_POLY_SET &aShapeBuffer)
Generate the polygonal shape of the primitive shape of an aperture macro instance.
bool IsAMPrimitiveExposureOn(APERTURE_MACRO *aApertMacro) const
void ConvertShapeToPolygon(APERTURE_MACRO *aApertMacroe, std::vector< VECTOR2I > &aBuffer)
Convert a shape to an equivalent polygon.
AM_PARAMS m_Params
A sequence of parameters used by the primitive.
Definition: am_primitive.h:95
AM_PRIMITIVE_ID m_Primitive_id
The primitive type.
Definition: am_primitive.h:94
bool m_GerbMetric
Definition: am_primitive.h:96
Support the "aperture macro" defined within standard RS274X.
void EvalLocalParams(const AM_PRIMITIVE &aPrimitive)
Evaluate m_localParamValues from current m_paramLevelEval to aPrimitive m_LocalParamLevel if m_paramL...
bool IsZero() const
Definition: eda_angle.h:133
Represent a set of closed polygons.
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)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
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.
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
@ RADIANS_T
Definition: eda_angle.h:32
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_360
Definition: eda_angle.h:407
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229