KiCad PCB EDA Suite
class_aperture_macro.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 <dick@softplc.com>
10  * Copyright (C) 1992-2017 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 <fctsys.h>
31 #include <common.h>
32 #include <macros.h>
33 #include <trigo.h>
35 #include <gr_basic.h>
36 
37 #include <gerbview.h>
39 
40 
41 
46 extern int scaletoIU( double aCoord, bool isMetric ); // defined it rs274d_read_XY_and_IJ_coordiantes.cpp
47 
54 static wxPoint mapPt( double x, double y, bool isMetric )
55 {
56  wxPoint ret( scaletoIU( x, isMetric ), scaletoIU( y, isMetric ) );
57 
58  return ret;
59 }
60 
61 
63 {
64  /*
65  * Some but not all primitives use the first parameter as an exposure control.
66  * Others are always ON.
67  * In a aperture macro shape, a basic primitive with exposure off is a hole in the shape
68  * it is NOT a negative shape
69  */
70  wxASSERT( params.size() && params[0].IsImmediate() );
71 
72  switch( primitive_id )
73  {
74  case AMP_CIRCLE:
75  case AMP_LINE2:
76  case AMP_LINE20:
77  case AMP_LINE_CENTER:
79  case AMP_OUTLINE:
80  case AMP_POLYGON:
81  // All have an exposure parameter and can return a value (0 or 1)
82  return params[0].GetValue( aParent->GetDcodeDescr() ) != 0;
83  break;
84 
85  case AMP_THERMAL: // Exposure is always on
86  case AMP_MOIRE: // Exposure is always on
87  case AMP_EOF:
88  case AMP_UNKNOWN:
89  default:
90  return 1; // All have no exposure parameter and are always 0N return true
91  break;
92  }
93 }
94 
95 const int seg_per_circle = 64; // Number of segments to approximate a circle
96 
98  SHAPE_POLY_SET& aShapeBuffer,
99  wxPoint aShapePos )
100 {
101  #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \
102  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\
103  aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );}
104 
105  // Draw the primitive shape for flashed items.
106  static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation
107  polybuffer.clear();
108 
109  wxPoint curPos = aShapePos;
110  D_CODE* tool = aParent->GetDcodeDescr();
111  double rotation;
112 
113  switch( primitive_id )
114  {
115  case AMP_CIRCLE: // Circle, given diameter and position
116  {
117  /* Generated by an aperture macro declaration like:
118  * "1,1,0.3,0.5, 1.0*"
119  * type (1), exposure, diameter, pos.x, pos.y, <rotation>
120  * <rotation> is a optional parameter: rotation from origin.
121  * type is not stored in parameters list, so the first parameter is exposure
122  */
123  ConvertShapeToPolygon( aParent, polybuffer );
124 
125  // shape rotation (if any):
126  if( params.size() >= 5 )
127  {
128  rotation = params[4].GetValue( tool ) * 10.0;
129 
130  if( rotation != 0)
131  {
132  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
133  RotatePoint( &polybuffer[ii], -rotation );
134  }
135  }
136 
137 
138  // Move to current position:
139  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
140  {
141  polybuffer[ii] += curPos;
142  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
143  }
144 
146  }
147  break;
148 
149  case AMP_LINE2:
150  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
151  {
152  /* Vector Line, Primitive Code 20.
153  * A vector line is a rectangle defined by its line width, start and end points.
154  * The line ends are rectangular.
155  */
156  /* Generated by an aperture macro declaration like:
157  * "2,1,0.3,0,0, 0.5, 1.0,-135*"
158  * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
159  * type is not stored in parameters list, so the first parameter is exposure
160  */
161  ConvertShapeToPolygon( aParent, polybuffer );
162 
163  // shape rotation:
164  rotation = params[6].GetValue( tool ) * 10.0;
165 
166  if( rotation != 0)
167  {
168  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
169  RotatePoint( &polybuffer[ii], -rotation );
170  }
171 
172  // Move to current position:
173  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
174  {
175  polybuffer[ii] += curPos;
176  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
177  }
178 
180  }
181  break;
182 
183  case AMP_LINE_CENTER:
184  {
185  /* Center Line, Primitive Code 21
186  * A center line primitive is a rectangle defined by its width, height, and center point
187  */
188  /* Generated by an aperture macro declaration like:
189  * "21,1,0.3,0.03,0,0,-135*"
190  * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
191  * type is not stored in parameters list, so the first parameter is exposure
192  */
193  ConvertShapeToPolygon( aParent, polybuffer );
194 
195  // shape rotation:
196  rotation = params[5].GetValue( tool ) * 10.0;
197 
198  if( rotation != 0 )
199  {
200  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
201  RotatePoint( &polybuffer[ii], -rotation );
202  }
203 
204  // Move to current position:
205  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
206  {
207  polybuffer[ii] += curPos;
208  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
209  }
210 
212  }
213  break;
214 
215  case AMP_LINE_LOWER_LEFT:
216  {
217  /* Generated by an aperture macro declaration like:
218  * "22,1,0.3,0.03,0,0,-135*"
219  * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
220  * type is not stored in parameters list, so the first parameter is exposure
221  */
222  ConvertShapeToPolygon( aParent, polybuffer );
223 
224  // shape rotation:
225  rotation = params[5].GetValue( tool ) * 10.0;
226  if( rotation != 0)
227  {
228  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
229  RotatePoint( &polybuffer[ii], -rotation );
230  }
231 
232  // Move to current position:
233  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
234  {
235  polybuffer[ii] += curPos;
236  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
237  }
238 
240  }
241  break;
242 
243  case AMP_THERMAL:
244  {
245  /* Generated by an aperture macro declaration like:
246  * "7, 0,0,1.0,0.3,0.01,-13*"
247  * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
248  * type is not stored in parameters list, so the first parameter is center.x
249  *
250  * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always on.
251  */
252  std::vector<wxPoint> subshape_poly;
253  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric );
254  ConvertShapeToPolygon( aParent, subshape_poly );
255 
256  // shape rotation:
257  rotation = params[5].GetValue( tool ) * 10.0;
258 
259  // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
260  // We must draw 4 sub-shapes rotated by 90 deg
261  for( int ii = 0; ii < 4; ii++ )
262  {
263  polybuffer = subshape_poly;
264  double sub_rotation = rotation + 900 * ii;
265 
266  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
267  RotatePoint( &polybuffer[jj], -sub_rotation );
268 
269  // Move to current position:
270  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
271  {
272  polybuffer[jj] += curPos;
273  polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] );
274  }
275 
277  }
278  }
279  break;
280 
281  case AMP_MOIRE:
282  {
283  /* Moiré, Primitive Code 6
284  * The moiré primitive is a cross hair centered on concentric rings (annuli).
285  * Exposure is always on.
286  */
287  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
288  m_GerbMetric );
289 
290  /* Generated by an aperture macro declaration like:
291  * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
292  * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
293  * type is not stored in parameters list, so the first parameter is pos.x
294  */
295  int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric );
296  int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric );
297  int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric );
298  int numCircles = KiROUND( params[5].GetValue( tool ) );
299 
300  // Draw circles:
301  wxPoint center = aParent->GetABPosition( curPos );
302  // adjust outerDiam by this on each nested circle
303  int diamAdjust = (gap + penThickness) * 2;
304 
305  for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
306  {
307  if( outerDiam <= 0 )
308  break;
309 
310  // Note: outerDiam is the outer diameter of the ring.
311  // the ring graphic diameter is (outerDiam - penThickness)
312  if( outerDiam <= penThickness )
313  { // No room to draw a ring (no room for the hole):
314  // draw a circle instead (with no hole), with the right diameter
315  TransformCircleToPolygon( aShapeBuffer, center,
316  outerDiam / 2, seg_per_circle );
317  }
318  else
319  TransformRingToPolygon( aShapeBuffer, center,
320  (outerDiam - penThickness) / 2,
321  seg_per_circle, penThickness );
322  }
323 
324  // Draw the cross:
325  ConvertShapeToPolygon( aParent, polybuffer );
326 
327  rotation = params[8].GetValue( tool ) * 10.0;
328  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
329  {
330  // shape rotation:
331  RotatePoint( &polybuffer[ii], -rotation );
332  // Move to current position:
333  polybuffer[ii] += curPos;
334  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
335  }
336 
338  }
339  break;
340 
341  case AMP_OUTLINE:
342  {
343  /* Outline, Primitive Code 4
344  * An outline primitive is an area enclosed by an n-point polygon defined by its start point and n
345  * subsequent points. The outline must be closed, i.e. the last point must be equal to the start
346  * point. There must be at least one subsequent point (to close the outline).
347  * The outline of the primitive is actually the contour (see 2.6) that consists of linear segments
348  * only, so it must conform to all the requirements described for contours.
349  * Warning: Make no mistake: n is the number of subsequent points, being the number of
350  * vertices of the outline or one less than the number of coordinate pairs.
351  */
352  /* Generated by an aperture macro declaration like:
353  * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
354  * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation
355  * type is not stored in parameters list, so the first parameter is exposure
356  */
357  int numPoints = (int) params[1].GetValue( tool );
358  rotation = params[numPoints * 2 + 4].GetValue( tool ) * 10.0;
359  wxPoint pos;
360  // Read points. numPoints does not include the starting point, so add 1.
361  for( int i = 0; i<numPoints + 1; ++i )
362  {
363  int jj = i * 2 + 2;
364  pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric );
365  pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric );
366  polybuffer.push_back(pos);
367  }
368  // rotate polygon and move it to the actual position
369  // shape rotation:
370  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
371  {
372  RotatePoint( &polybuffer[ii], -rotation );
373  }
374 
375  // Move to current position:
376  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
377  {
378  polybuffer[ii] += curPos;
379  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
380  }
381 
383  }
384  break;
385 
386  case AMP_POLYGON:
387  /* Polygon, Primitive Code 5
388  * A polygon primitive is a regular polygon defined by the number of vertices n, the center point
389  * and the diameter of the circumscribed circle
390  */
391  /* Generated by an aperture macro declaration like:
392  * "5,1,0.6,0,0,0.5,25"
393  * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
394  * type is not stored in parameters list, so the first parameter is exposure
395  */
396  curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
397  // Creates the shape:
398  ConvertShapeToPolygon( aParent, polybuffer );
399 
400  // rotate polygon and move it to the actual position
401  rotation = params[5].GetValue( tool ) * 10.0;
402  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
403  {
404  RotatePoint( &polybuffer[ii], -rotation );
405  polybuffer[ii] += curPos;
406  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
407  }
408 
410 
411  break;
412 
413  case AMP_EOF:
414  // not yet supported, waiting for you.
415  break;
416 
417  case AMP_UNKNOWN:
418  default:
419  DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
420  break;
421  }
422 }
423 
424 
436  std::vector<wxPoint>& aBuffer )
437 {
438  D_CODE* tool = aParent->GetDcodeDescr();
439 
440  switch( primitive_id )
441  {
442  case AMP_CIRCLE:
443  {
444  /* Generated by an aperture macro declaration like:
445  * "1,1,0.3,0.5, 1.0*"
446  * type (1), exposure, diameter, pos.x, pos.y, <rotation>
447  * <rotation> is a optional parameter: rotation from origin.
448  * type is not stored in parameters list, so the first parameter is exposure
449  */
450  wxPoint center = mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
451  int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2;
452  wxPoint corner;
453  const int delta = 3600 / seg_per_circle; // rot angle in 0.1 degree
454 
455  for( int angle = 0; angle < 3600; angle += delta )
456  {
457  corner.x = radius;
458  corner.y = 0;
459  RotatePoint( &corner, angle );
460  corner += center;
461  aBuffer.push_back( corner );
462  }
463  }
464  break;
465 
466  case AMP_LINE2:
467  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
468  {
469  int width = scaletoIU( params[1].GetValue( tool ), m_GerbMetric );
470  wxPoint start = mapPt( params[2].GetValue( tool ),
471  params[3].GetValue( tool ), m_GerbMetric );
472  wxPoint end = mapPt( params[4].GetValue( tool ),
473  params[5].GetValue( tool ), m_GerbMetric );
474  wxPoint delta = end - start;
475  int len = KiROUND( EuclideanNorm( delta ) );
476 
477  // To build the polygon, we must create a horizontal polygon starting to "start"
478  // and rotate it to have the end point to "end"
479  wxPoint currpt;
480  currpt.y += width / 2; // Upper left
481  aBuffer.push_back( currpt );
482  currpt.x = len; // Upper right
483  aBuffer.push_back( currpt );
484  currpt.y -= width; // lower right
485  aBuffer.push_back( currpt );
486  currpt.x = 0; // lower left
487  aBuffer.push_back( currpt );
488 
489  // Rotate rectangle and move it to the actual start point
490  double angle = ArcTangente( delta.y, delta.x );
491 
492  for( unsigned ii = 0; ii < 4; ii++ )
493  {
494  RotatePoint( &aBuffer[ii], -angle );
495  aBuffer[ii] += start;
496  }
497  }
498  break;
499 
500  case AMP_LINE_CENTER:
501  {
502  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
503  wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric );
504 
505  // Build poly:
506  pos.x -= size.x / 2;
507  pos.y -= size.y / 2; // Lower left
508  aBuffer.push_back( pos );
509  pos.y += size.y; // Upper left
510  aBuffer.push_back( pos );
511  pos.x += size.x; // Upper right
512  aBuffer.push_back( pos );
513  pos.y -= size.y; // lower right
514  aBuffer.push_back( pos );
515  }
516  break;
517 
518  case AMP_LINE_LOWER_LEFT:
519  {
520  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
521  wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
522  tool ), m_GerbMetric );
523 
524  // Build poly:
525  aBuffer.push_back( lowerLeft );
526  lowerLeft.y += size.y; // Upper left
527  aBuffer.push_back( lowerLeft );
528  lowerLeft.x += size.x; // Upper right
529  aBuffer.push_back( lowerLeft );
530  lowerLeft.y -= size.y; // lower right
531  aBuffer.push_back( lowerLeft );
532  }
533  break;
534 
535  case AMP_THERMAL:
536  {
537  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
538  // rotated by 90, 180 and 270 deg.
539  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
540  int outerRadius = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2;
541  int innerRadius = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ) / 2;
542  int halfthickness = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
543  double angle_start = RAD2DECIDEG( asin( (double) halfthickness / innerRadius ) );
544 
545  // Draw shape in the first cadrant (X and Y > 0)
546  wxPoint pos, startpos;
547 
548  // Inner arc
549  startpos.x = innerRadius;
550  double angle_end = 900 - angle_start;
551  for( double angle = angle_start; angle < angle_end; angle += 100 )
552  {
553  pos = startpos;
554  RotatePoint( &pos, angle );
555  aBuffer.push_back( pos );
556  }
557 
558  // Last point
559  pos = startpos;
560  RotatePoint( &pos, angle_end );
561  aBuffer.push_back( pos );
562 
563  // outer arc
564  startpos.x = outerRadius;
565  startpos.y = 0;
566  angle_start = RAD2DECIDEG( asin( (double) halfthickness / outerRadius ) );
567  angle_end = 900 - angle_start;
568 
569  // First point, near Y axis, outer arc
570  for( double angle = angle_end; angle > angle_start; angle -= 100 )
571  {
572  pos = startpos;
573  RotatePoint( &pos, angle );
574  aBuffer.push_back( pos );
575  }
576 
577  // last point
578  pos = startpos;
579  RotatePoint( &pos, angle_start );
580  aBuffer.push_back( pos );
581 
582  aBuffer.push_back( aBuffer[0] ); // Close poly
583  }
584  break;
585 
586  case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon
587  // because circles can be drawn easily
588  {
589  int crossHairThickness = scaletoIU( params[6].GetValue( tool ), m_GerbMetric );
590  int crossHairLength = scaletoIU( params[7].GetValue( tool ), m_GerbMetric );
591 
592  // Create cross. First create 1/4 of the shape.
593  // Others point are the same, totated by 90, 180 and 270 deg
594  wxPoint 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, jj*900 );
610  aBuffer.push_back( pos );
611  }
612  }
613  }
614  break;
615 
616  case AMP_OUTLINE:
617  // already is a polygon. Do nothing
618  break;
619 
620  case AMP_POLYGON: // Creates a regular polygon
621  {
622  int vertexcount = KiROUND( params[1].GetValue( tool ) );
623  int radius = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
624  // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
625  if( vertexcount < 3 )
626  vertexcount = 3;
627  if( vertexcount > 10 )
628  vertexcount = 10;
629  for( int ii = 0; ii <= vertexcount; ii++ )
630  {
631  wxPoint pos( radius, 0);
632  RotatePoint( &pos, ii * 3600 / vertexcount );
633  aBuffer.push_back( pos );
634  }
635  }
636  break;
637 
638  case AMP_COMMENT:
639  case AMP_UNKNOWN:
640  case AMP_EOF:
641  break;
642  }
643 }
644 
656 {
657  int dim = -1;
658  D_CODE* tool = aParent->GetDcodeDescr();
659 
660  switch( primitive_id )
661  {
662  case AMP_CIRCLE:
663  // params = exposure, diameter, pos.x, pos.y
664  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // Diameter
665  break;
666 
667  case AMP_LINE2:
668  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
669  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // linne width
670  break;
671 
672  case AMP_LINE_CENTER:
673  {
674  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
675  dim = std::min(size.x, size.y);
676  }
677  break;
678 
679  case AMP_LINE_LOWER_LEFT:
680  {
681  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
682  dim = std::min(size.x, size.y);
683  }
684  break;
685 
686  case AMP_THERMAL:
687  {
688  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
689  // rotated by 90, 180 and 270 deg.
690  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
691  dim = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam
692  }
693  break;
694 
695  case AMP_MOIRE: // A cross hair with n concentric circles.
696  dim = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len
697  break;
698 
699  case AMP_OUTLINE: // a free polygon :
700  // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?)
701  {
702  // exposure, corners count, corner1.x, corner.1y, ..., rotation
703  int numPoints = (int) params[1].GetValue( tool );
704  // Read points. numPoints does not include the starting point, so add 1.
705  // and calculate the bounding box;
706  wxSize pos_min, pos_max, pos;
707  for( int i = 0; i<numPoints + 1; ++i )
708  {
709  int jj = i * 2 + 2;
710  pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric );
711  pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric );
712  if( i == 0 )
713  pos_min = pos_max = pos;
714  else
715  {
716  // upper right corner:
717  if( pos_min.x > pos.x )
718  pos_min.x = pos.x;
719  if( pos_min.y > pos.y )
720  pos_min.y = pos.y;
721  // lower left corner:
722  if( pos_max.x < pos.x )
723  pos_max.x = pos.x;
724  if( pos_max.y < pos.y )
725  pos_max.y = pos.y;
726  }
727  }
728  // calculate dim
729  wxSize size;
730  size.x = pos_max.x - pos_min.x;
731  size.y = pos_max.y - pos_min.y;
732  dim = std::min( size.x, size.y );
733  }
734  break;
735 
736  case AMP_POLYGON: // Regular polygon
737  dim = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius
738  break;
739 
740  case AMP_COMMENT:
741  case AMP_UNKNOWN:
742  case AMP_EOF:
743  break;
744  }
745  return dim;
746 }
747 
748 
749 /*
750  * Function DrawApertureMacroShape
751  * Draw the primitive shape for flashed items.
752  * When an item is flashed, this is the shape of the item
753  */
755  EDA_RECT* aClipBox, wxDC* aDC,
756  COLOR4D aColor,
757  wxPoint aShapePos, bool aFilledShape )
758 {
759  SHAPE_POLY_SET shapeBuffer;
760  SHAPE_POLY_SET holeBuffer;
761  bool hasHole = false;
762 
763  for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
764  prim_macro != primitives.end(); ++prim_macro )
765  {
766  if( prim_macro->IsAMPrimitiveExposureOn( aParent ) )
767  prim_macro->DrawBasicShape( aParent, shapeBuffer, aShapePos );
768  else
769  {
770  prim_macro->DrawBasicShape( aParent, holeBuffer, aShapePos );
771 
772  if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
773  {
774  shapeBuffer.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
775  holeBuffer.RemoveAllContours();
776  hasHole = true;
777  }
778  }
779  }
780 
781  if( shapeBuffer.OutlineCount() == 0 )
782  return;
783 
784  // If a hole is defined inside a polygon, we must fracture the polygon
785  // to be able to drawn it (i.e link holes by overlapping edges)
786  if( hasHole )
787  shapeBuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
788 
789  for( int ii = 0; ii < shapeBuffer.OutlineCount(); ii++ )
790  {
791  SHAPE_LINE_CHAIN& poly = shapeBuffer.Outline( ii );
792 
793  GRClosedPoly( aClipBox, aDC,
794  poly.PointCount(), (wxPoint*)&poly.Point( 0 ), aFilledShape, aColor, aColor );
795  }
796 }
797 
809 {
810  int dim = -1;
811  for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
812  prim_macro != primitives.end(); ++prim_macro )
813  {
814  int pdim = prim_macro->GetShapeDim( aParent );
815  if( dim < pdim )
816  dim = pdim;
817  }
818 
819  return dim;
820 }
821 
822 
833 double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const
834 {
835  // find parameter descr.
836  const AM_PARAM * param = NULL;
837 
838  for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ )
839  {
840  if( m_localparamStack[ii].GetIndex() == aParamId )
841  {
842  param = &m_localparamStack[ii];
843  break;
844  }
845  }
846 
847  if ( param == NULL ) // not found
848  return 0.0;
849 
850  // Evaluate parameter
851  double value = param->GetValue( aDcode );
852 
853  return value;
854 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:104
#define TO_POLY_SHAPE
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
static wxPoint mapPt(double x, double y, bool isMetric)
Function mapPt translates a point from the aperture macro coordinate system to our deci-mils coordina...
D_CODE * GetDcodeDescr()
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
void TransformCircleToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines...
int PointCount() const
Function PointCount()
void DrawApertureMacroShape(GERBER_DRAW_ITEM *aParent, EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape)
Function DrawApertureMacroShape Draw the primitive shape for flashed items.
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying the D-Cod...
double RAD2DECIDEG(double rad)
Definition: trigo.h:196
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int OutlineCount() const
Returns the number of outlines in the set
void DrawBasicShape(GERBER_DRAW_ITEM *aParent, SHAPE_POLY_SET &aShapeBuffer, wxPoint aShapePos)
Function drawBasicShape Draw (in fact generate the actual polygonal shape of) the primitive shape of ...
void GRClosedPoly(EDA_RECT *ClipBox, wxDC *DC, int n, wxPoint Points[], bool Fill, COLOR4D Color, COLOR4D BgColor)
Function GRClosedPoly draws a closed polygon onto the drawing context aDC and optionally fills and/or...
Definition: gr_basic.cpp:777
static const int delta[8][2]
Definition: solve.cpp:112
This file contains miscellaneous commonly used macros and functions.
bool IsAMPrimitiveExposureOn(GERBER_DRAW_ITEM *aParent) const
Function IsAMPrimitiveExposureOn.
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
const int seg_per_circle
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
Class AM_PARAM holds a parameter value for an "aperture macro" as defined within standard RS274X...
double GetValue(const D_CODE *aDcode) const
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
double GetLocalParam(const D_CODE *aDcode, unsigned aParamId) const
function GetLocalParam Usually, parameters are defined inside the aperture primitive using immediate ...
void TransformRingToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCentre, int aRadius, int aCircleToSegmentsCount, int aWidth)
Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segme...
void ConvertShapeToPolygon(GERBER_DRAW_ITEM *aParent, std::vector< wxPoint > &aBuffer)
Function ConvertShapeToPolygon convert a shape to an equivalent polygon.
AM_PRIMITIVES primitives
A sequence of AM_PRIMITIVEs.
Class D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:81
Class SHAPE_LINE_CHAIN.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
Class EDA_RECT handles the component boundary box.
The common library.
VECTOR2I & Point(int aIndex)
Function Point()
#define DBG(x)
Definition: fctsys.h:33
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp ...
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
Function GetShapeDim Calculate a value that can be used to evaluate the size of text when displaying ...
wxPoint GetABPosition(const wxPoint &aXYPosition) const
Function GetABPosition returns the image position of aPosition for this object.
AM_PARAMS params
A sequence of parameters used by.
#define min(a, b)
Definition: auxiliary.h:85
AM_PRIMITIVE_ID primitive_id
The primitive type.
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39