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-2016 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
9  * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
10  * Copyright (C) 1992-2016 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 
97  SHAPE_POLY_SET& aShapeBuffer,
98  wxPoint aShapePos )
99 {
100  #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \
101  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\
102  aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );}
103 
104  const int seg_per_circle = 64; // Number of segments to approximate a circle
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
120  * type is not stored in parameters list, so the first parameter is exposure
121  */
122  curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
123  curPos = aParent->GetABPosition( curPos );
124  int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2;
125 
126  TransformCircleToPolygon( aShapeBuffer, curPos, radius, seg_per_circle );
127  }
128  break;
129 
130  case AMP_LINE2:
131  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
132  {
133  /* Vector Line, Primitive Code 20.
134  * A vector line is a rectangle defined by its line width, start and end points.
135  * The line ends are rectangular.
136  */
137  /* Generated by an aperture macro declaration like:
138  * "2,1,0.3,0,0, 0.5, 1.0,-135*"
139  * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
140  * type is not stored in parameters list, so the first parameter is exposure
141  */
142  ConvertShapeToPolygon( aParent, polybuffer );
143 
144  // shape rotation:
145  rotation = params[6].GetValue( tool ) * 10.0;
146  if( rotation != 0)
147  {
148  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
149  RotatePoint( &polybuffer[ii], -rotation );
150  }
151 
152  // Move to current position:
153  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
154  {
155  polybuffer[ii] += curPos;
156  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
157  }
158 
160  }
161  break;
162 
163  case AMP_LINE_CENTER:
164  {
165  /* Center Line, Primitive Code 21
166  * A center line primitive is a rectangle defined by its width, height, and center point
167  */
168  /* Generated by an aperture macro declaration like:
169  * "21,1,0.3,0.03,0,0,-135*"
170  * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
171  * type is not stored in parameters list, so the first parameter is exposure
172  */
173  ConvertShapeToPolygon( aParent, polybuffer );
174 
175  // shape rotation:
176  rotation = params[5].GetValue( tool ) * 10.0;
177 
178  if( rotation != 0 )
179  {
180  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
181  RotatePoint( &polybuffer[ii], -rotation );
182  }
183 
184  // Move to current position:
185  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
186  {
187  polybuffer[ii] += curPos;
188  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
189  }
190 
192  }
193  break;
194 
195  case AMP_LINE_LOWER_LEFT:
196  {
197  /* Generated by an aperture macro declaration like:
198  * "22,1,0.3,0.03,0,0,-135*"
199  * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
200  * type is not stored in parameters list, so the first parameter is exposure
201  */
202  ConvertShapeToPolygon( aParent, polybuffer );
203 
204  // shape rotation:
205  rotation = params[5].GetValue( tool ) * 10.0;
206  if( rotation != 0)
207  {
208  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
209  RotatePoint( &polybuffer[ii], -rotation );
210  }
211 
212  // Move to current position:
213  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
214  {
215  polybuffer[ii] += curPos;
216  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
217  }
218 
220  }
221  break;
222 
223  case AMP_THERMAL:
224  {
225  /* Generated by an aperture macro declaration like:
226  * "7, 0,0,1.0,0.3,0.01,-13*"
227  * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
228  * type is not stored in parameters list, so the first parameter is center.x
229  *
230  * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always on.
231  */
232  std::vector<wxPoint> subshape_poly;
233  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric );
234  ConvertShapeToPolygon( aParent, subshape_poly );
235 
236  // shape rotation:
237  rotation = params[5].GetValue( tool ) * 10.0;
238 
239  // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
240  // We must draw 4 sub-shapes rotated by 90 deg
241  for( int ii = 0; ii < 4; ii++ )
242  {
243  polybuffer = subshape_poly;
244  double sub_rotation = rotation + 900 * ii;
245 
246  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
247  RotatePoint( &polybuffer[jj], -sub_rotation );
248 
249  // Move to current position:
250  for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
251  {
252  polybuffer[jj] += curPos;
253  polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] );
254  }
255 
257  }
258  }
259  break;
260 
261  case AMP_MOIRE:
262  {
263  /* Moiré, Primitive Code 6
264  * The moiré primitive is a cross hair centered on concentric rings (annuli).
265  * Exposure is always on.
266  */
267  curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
268  m_GerbMetric );
269 
270  /* Generated by an aperture macro declaration like:
271  * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
272  * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
273  * type is not stored in parameters list, so the first parameter is pos.x
274  */
275  int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric );
276  int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric );
277  int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric );
278  int numCircles = KiROUND( params[5].GetValue( tool ) );
279 
280  // Draw circles:
281  wxPoint center = aParent->GetABPosition( curPos );
282  // adjust outerDiam by this on each nested circle
283  int diamAdjust = (gap + penThickness) * 2;
284 
285  for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
286  {
287  if( outerDiam <= 0 )
288  break;
289 
290  // Note: outerDiam is the outer diameter of the ring.
291  // the ring graphic diameter is (outerDiam - penThickness)
292  if( outerDiam <= penThickness )
293  { // No room to draw a ring (no room for the hole):
294  // draw a circle instead (with no hole), with the right diameter
295  TransformCircleToPolygon( aShapeBuffer, center,
296  outerDiam / 2, seg_per_circle );
297  }
298  else
299  TransformRingToPolygon( aShapeBuffer, center,
300  (outerDiam - penThickness) / 2,
301  seg_per_circle, penThickness );
302  }
303 
304  // Draw the cross:
305  ConvertShapeToPolygon( aParent, polybuffer );
306 
307  rotation = params[8].GetValue( tool ) * 10.0;
308  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
309  {
310  // shape rotation:
311  RotatePoint( &polybuffer[ii], -rotation );
312  // Move to current position:
313  polybuffer[ii] += curPos;
314  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
315  }
316 
318  }
319  break;
320 
321  case AMP_OUTLINE:
322  {
323  /* Outline, Primitive Code 4
324  * An outline primitive is an area enclosed by an n-point polygon defined by its start point and n
325  * subsequent points. The outline must be closed, i.e. the last point must be equal to the start
326  * point. There must be at least one subsequent point (to close the outline).
327  * The outline of the primitive is actually the contour (see 2.6) that consists of linear segments
328  * only, so it must conform to all the requirements described for contours.
329  * Warning: Make no mistake: n is the number of subsequent points, being the number of
330  * vertices of the outline or one less than the number of coordinate pairs.
331  */
332  /* Generated by an aperture macro declaration like:
333  * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
334  * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation
335  * type is not stored in parameters list, so the first parameter is exposure
336  */
337  int numPoints = (int) params[1].GetValue( tool );
338  rotation = params[numPoints * 2 + 4].GetValue( tool ) * 10.0;
339  wxPoint pos;
340  // Read points. numPoints does not include the starting point, so add 1.
341  for( int i = 0; i<numPoints + 1; ++i )
342  {
343  int jj = i * 2 + 2;
344  pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric );
345  pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric );
346  polybuffer.push_back(pos);
347  }
348  // rotate polygon and move it to the actual position
349  // shape rotation:
350  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
351  {
352  RotatePoint( &polybuffer[ii], -rotation );
353  }
354 
355  // Move to current position:
356  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
357  {
358  polybuffer[ii] += curPos;
359  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
360  }
361 
363  }
364  break;
365 
366  case AMP_POLYGON:
367  /* Polygon, Primitive Code 5
368  * A polygon primitive is a regular polygon defined by the number of vertices n, the center point
369  * and the diameter of the circumscribed circle
370  */
371  /* Generated by an aperture macro declaration like:
372  * "5,1,0.6,0,0,0.5,25"
373  * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
374  * type is not stored in parameters list, so the first parameter is exposure
375  */
376  curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
377  // Creates the shape:
378  ConvertShapeToPolygon( aParent, polybuffer );
379 
380  // rotate polygon and move it to the actual position
381  rotation = params[5].GetValue( tool ) * 10.0;
382  for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
383  {
384  RotatePoint( &polybuffer[ii], -rotation );
385  polybuffer[ii] += curPos;
386  polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
387  }
388 
390 
391  break;
392 
393  case AMP_EOF:
394  // not yet supported, waiting for you.
395  break;
396 
397  case AMP_UNKNOWN:
398  default:
399  DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
400  break;
401  }
402 }
403 
404 
416  std::vector<wxPoint>& aBuffer )
417 {
418  D_CODE* tool = aParent->GetDcodeDescr();
419 
420  switch( primitive_id )
421  {
422  case AMP_CIRCLE: // Circle, currently convertion not needed
423  break;
424 
425  case AMP_LINE2:
426  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
427  {
428  int width = scaletoIU( params[1].GetValue( tool ), m_GerbMetric );
429  wxPoint start = mapPt( params[2].GetValue( tool ),
430  params[3].GetValue( tool ), m_GerbMetric );
431  wxPoint end = mapPt( params[4].GetValue( tool ),
432  params[5].GetValue( tool ), m_GerbMetric );
433  wxPoint delta = end - start;
434  int len = KiROUND( EuclideanNorm( delta ) );
435 
436  // To build the polygon, we must create a horizonta polygon starting to "start"
437  // and rotate it to have it end point to "end"
438  wxPoint currpt;
439  currpt.y += width / 2; // Upper left
440  aBuffer.push_back( currpt );
441  currpt.x = len; // Upper right
442  aBuffer.push_back( currpt );
443  currpt.y -= width; // lower right
444  aBuffer.push_back( currpt );
445  currpt.x = 0; // Upper left
446  aBuffer.push_back( currpt );
447 
448  // Rotate rectangle and move it to the actual start point
449  double angle = ArcTangente( delta.y, delta.x );
450 
451  for( unsigned ii = 0; ii < 4; ii++ )
452  {
453  RotatePoint( &aBuffer[ii], -angle );
454  aBuffer[ii] += start;
455  }
456  }
457  break;
458 
459  case AMP_LINE_CENTER:
460  {
461  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
462  wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric );
463 
464  // Build poly:
465  pos.x -= size.x / 2;
466  pos.y -= size.y / 2; // Lower left
467  aBuffer.push_back( pos );
468  pos.y += size.y; // Upper left
469  aBuffer.push_back( pos );
470  pos.x += size.x; // Upper right
471  aBuffer.push_back( pos );
472  pos.y -= size.y; // lower right
473  aBuffer.push_back( pos );
474  }
475  break;
476 
477  case AMP_LINE_LOWER_LEFT:
478  {
479  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
480  wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
481  tool ), m_GerbMetric );
482 
483  // Build poly:
484  aBuffer.push_back( lowerLeft );
485  lowerLeft.y += size.y; // Upper left
486  aBuffer.push_back( lowerLeft );
487  lowerLeft.x += size.x; // Upper right
488  aBuffer.push_back( lowerLeft );
489  lowerLeft.y -= size.y; // lower right
490  aBuffer.push_back( lowerLeft );
491  }
492  break;
493 
494  case AMP_THERMAL:
495  {
496  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
497  // rotated by 90, 180 and 270 deg.
498  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
499  int outerRadius = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2;
500  int innerRadius = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ) / 2;
501  int halfthickness = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
502  double angle_start = RAD2DECIDEG( asin( (double) halfthickness / innerRadius ) );
503 
504  // Draw shape in the first cadrant (X and Y > 0)
505  wxPoint pos, startpos;
506 
507  // Inner arc
508  startpos.x = innerRadius;
509  double angle_end = 900 - angle_start;
510  for( double angle = angle_start; angle < angle_end; angle += 100 )
511  {
512  pos = startpos;
513  RotatePoint( &pos, angle );
514  aBuffer.push_back( pos );
515  }
516 
517  // Last point
518  pos = startpos;
519  RotatePoint( &pos, angle_end );
520  aBuffer.push_back( pos );
521 
522  // outer arc
523  startpos.x = outerRadius;
524  startpos.y = 0;
525  angle_start = RAD2DECIDEG( asin( (double) halfthickness / outerRadius ) );
526  angle_end = 900 - angle_start;
527 
528  // First point, near Y axis, outer arc
529  for( double angle = angle_end; angle > angle_start; angle -= 100 )
530  {
531  pos = startpos;
532  RotatePoint( &pos, angle );
533  aBuffer.push_back( pos );
534  }
535 
536  // last point
537  pos = startpos;
538  RotatePoint( &pos, angle_start );
539  aBuffer.push_back( pos );
540 
541  aBuffer.push_back( aBuffer[0] ); // Close poly
542  }
543  break;
544 
545  case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon
546  // because circles can be drawn easily
547  {
548  int crossHairThickness = scaletoIU( params[6].GetValue( tool ), m_GerbMetric );
549  int crossHairLength = scaletoIU( params[7].GetValue( tool ), m_GerbMetric );
550 
551  // Create cross. First create 1/4 of the shape.
552  // Others point are the same, totated by 90, 180 and 270 deg
553  wxPoint pos( crossHairThickness / 2, crossHairLength / 2 );
554  aBuffer.push_back( pos );
555  pos.y = crossHairThickness / 2;
556  aBuffer.push_back( pos );
557  pos.x = -crossHairLength / 2;
558  aBuffer.push_back( pos );
559  pos.y = -crossHairThickness / 2;
560  aBuffer.push_back( pos );
561 
562  // Copy the 4 shape, rotated by 90, 180 and 270 deg
563  for( int jj = 1; jj <= 3; jj ++ )
564  {
565  for( int ii = 0; ii < 4; ii++ )
566  {
567  pos = aBuffer[ii];
568  RotatePoint( &pos, jj*900 );
569  aBuffer.push_back( pos );
570  }
571  }
572  }
573  break;
574 
575  case AMP_OUTLINE:
576  // already is a polygon. Do nothing
577  break;
578 
579  case AMP_POLYGON: // Creates a regular polygon
580  {
581  int vertexcount = KiROUND( params[1].GetValue( tool ) );
582  int radius = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2;
583  // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
584  if( vertexcount < 3 )
585  vertexcount = 3;
586  if( vertexcount > 10 )
587  vertexcount = 10;
588  for( int ii = 0; ii <= vertexcount; ii++ )
589  {
590  wxPoint pos( radius, 0);
591  RotatePoint( &pos, ii * 3600 / vertexcount );
592  aBuffer.push_back( pos );
593  }
594  }
595  break;
596 
597  case AMP_COMMENT:
598  case AMP_UNKNOWN:
599  case AMP_EOF:
600  break;
601  }
602 }
603 
615 {
616  int dim = -1;
617  D_CODE* tool = aParent->GetDcodeDescr();
618 
619  switch( primitive_id )
620  {
621  case AMP_CIRCLE:
622  // params = exposure, diameter, pos.x, pos.y
623  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // Diameter
624  break;
625 
626  case AMP_LINE2:
627  case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
628  dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // linne width
629  break;
630 
631  case AMP_LINE_CENTER:
632  {
633  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
634  dim = std::min(size.x, size.y);
635  }
636  break;
637 
638  case AMP_LINE_LOWER_LEFT:
639  {
640  wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric );
641  dim = std::min(size.x, size.y);
642  }
643  break;
644 
645  case AMP_THERMAL:
646  {
647  // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
648  // rotated by 90, 180 and 270 deg.
649  // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
650  dim = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam
651  }
652  break;
653 
654  case AMP_MOIRE: // A cross hair with n concentric circles.
655  dim = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len
656  break;
657 
658  case AMP_OUTLINE: // a free polygon :
659  // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?)
660  {
661  // exposure, corners count, corner1.x, corner.1y, ..., rotation
662  int numPoints = (int) params[1].GetValue( tool );
663  // Read points. numPoints does not include the starting point, so add 1.
664  // and calculate the bounding box;
665  wxSize pos_min, pos_max, pos;
666  for( int i = 0; i<numPoints + 1; ++i )
667  {
668  int jj = i * 2 + 2;
669  pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric );
670  pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric );
671  if( i == 0 )
672  pos_min = pos_max = pos;
673  else
674  {
675  // upper right corner:
676  if( pos_min.x > pos.x )
677  pos_min.x = pos.x;
678  if( pos_min.y > pos.y )
679  pos_min.y = pos.y;
680  // lower left corner:
681  if( pos_max.x < pos.x )
682  pos_max.x = pos.x;
683  if( pos_max.y < pos.y )
684  pos_max.y = pos.y;
685  }
686  }
687  // calculate dim
688  wxSize size;
689  size.x = pos_max.x - pos_min.x;
690  size.y = pos_max.y - pos_min.y;
691  dim = std::min( size.x, size.y );
692  }
693  break;
694 
695  case AMP_POLYGON: // Regular polygon
696  dim = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius
697  break;
698 
699  case AMP_COMMENT:
700  case AMP_UNKNOWN:
701  case AMP_EOF:
702  break;
703  }
704  return dim;
705 }
706 
707 
708 /*
709  * Function DrawApertureMacroShape
710  * Draw the primitive shape for flashed items.
711  * When an item is flashed, this is the shape of the item
712  */
714  EDA_RECT* aClipBox, wxDC* aDC,
715  COLOR4D aColor,
716  wxPoint aShapePos, bool aFilledShape )
717 {
718  SHAPE_POLY_SET shapeBuffer;
719  SHAPE_POLY_SET holeBuffer;
720  bool hasHole = false;
721 
722  for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
723  prim_macro != primitives.end(); ++prim_macro )
724  {
725  if( prim_macro->IsAMPrimitiveExposureOn( aParent ) )
726  prim_macro->DrawBasicShape( aParent, shapeBuffer, aShapePos );
727  else
728  {
729  prim_macro->DrawBasicShape( aParent, holeBuffer, aShapePos );
730 
731  if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
732  {
733  shapeBuffer.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST );
734  holeBuffer.RemoveAllContours();
735  hasHole = true;
736  }
737  }
738  }
739 
740  if( shapeBuffer.OutlineCount() == 0 )
741  return;
742 
743  // If a hole is defined inside a polygon, we must fracture the polygon
744  // to be able to drawn it (i.e link holes by overlapping edges)
745  if( hasHole )
746  shapeBuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
747 
748  for( int ii = 0; ii < shapeBuffer.OutlineCount(); ii++ )
749  {
750  SHAPE_LINE_CHAIN& poly = shapeBuffer.Outline( ii );
751 
752  GRClosedPoly( aClipBox, aDC,
753  poly.PointCount(), (wxPoint*)&poly.Point( 0 ), aFilledShape, aColor, aColor );
754  }
755 }
756 
768 {
769  int dim = -1;
770  for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
771  prim_macro != primitives.end(); ++prim_macro )
772  {
773  int pdim = prim_macro->GetShapeDim( aParent );
774  if( dim < pdim )
775  dim = pdim;
776  }
777 
778  return dim;
779 }
780 
781 
792 double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const
793 {
794  // find parameter descr.
795  const AM_PARAM * param = NULL;
796  for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ )
797  {
798  if( m_localparamStack[ii].GetIndex() == aParamId )
799  {
800  param = &m_localparamStack[ii];
801  break;
802  }
803  }
804  if ( param == NULL ) // not found
805  return 0.0;
806  // Evaluate parameter
807  double value = param->GetValue( aDcode );
808  return value;
809 }
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
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