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