KiCad PCB EDA Suite
class_gerber_draw_item.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 1992-2017 <Jean-Pierre Charras>
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
29 #include <fctsys.h>
30 #include <gr_basic.h>
31 #include <common.h>
32 #include <trigo.h>
33 #include <class_drawpanel.h>
34 #include <msgpanel.h>
35 #include <gerbview_frame.h>
37 
38 #include <class_gerber_draw_item.h>
41 
42 
45 {
46  m_GerberImageFile = aGerberImageFile;
48  m_Flashed = false;
49  m_DCode = 0;
50  m_UnitsMetric = false;
51  m_LayerNegative = false;
52  m_swapAxis = false;
53  m_mirrorA = false;
54  m_mirrorB = false;
55  m_drawScale.x = m_drawScale.y = 1.0;
56  m_lyrRotation = 0;
57 
58  if( m_GerberImageFile )
60 }
61 
62 
64 {
65 }
66 
67 
69 {
70  m_netAttributes = aNetAttributes;
71 
74  m_GerberImageFile->m_ComponentsList.insert( std::make_pair( m_netAttributes.m_Cmpref, 0 ) );
75 
77  m_GerberImageFile->m_NetnamesList.insert( std::make_pair( m_netAttributes.m_Netname, 0 ) );
78 }
79 
80 
82 {
83  // returns the layer this item is on, or 0 if the m_GerberImageFile is NULL.
85 }
86 
87 
88 bool GERBER_DRAW_ITEM::GetTextD_CodePrms( int& aSize, wxPoint& aPos, double& aOrientation )
89 {
90  // calculate the best size and orientation of the D_Code text
91 
92  if( m_DCode <= 0 )
93  return false; // No D_Code for this item
94 
95  if( m_Flashed || m_Shape == GBR_ARC )
96  {
97  aPos = m_Start;
98  }
99  else // it is a line:
100  {
101  aPos = ( m_Start + m_End) / 2;
102  }
103 
104  aPos = GetABPosition( aPos );
105 
106  int size; // the best size for the text
107 
108  if( GetDcodeDescr() )
109  size = GetDcodeDescr()->GetShapeDim( this );
110  else
111  size = std::min( m_Size.x, m_Size.y );
112 
113  aOrientation = TEXT_ANGLE_HORIZ;
114 
115  if( m_Flashed )
116  {
117  // A reasonable size for text is min_dim/3 because most of time this text has 3 chars.
118  aSize = size / 3;
119  }
120  else // this item is a line
121  {
123 
124  aOrientation = RAD2DECIDEG( atan2( (double)delta.y, (double)delta.x ) );
125  NORMALIZE_ANGLE_90( aOrientation );
126 
127  // A reasonable size for text is size/2 because text needs margin below and above it.
128  // a margin = size/4 seems good, expecting the line len is large enough to show 3 chars,
129  // that is the case most of time.
130  aSize = size / 2;
131  }
132 
133  return true;
134 }
135 
136 
137 bool GERBER_DRAW_ITEM::GetTextD_CodePrms( double& aSize, VECTOR2D& aPos, double& aOrientation )
138 {
139  // aOrientation is returned in radians
140  int size;
141  wxPoint pos;
142 
143  if( ! GetTextD_CodePrms( size, pos, aOrientation ) )
144  return false;
145 
146  aPos = pos;
147  aSize = (double) size;
148  aOrientation = DECIDEG2RAD( aOrientation );
149 
150  return true;
151 }
152 
153 
155 {
156  /* Note: RS274Xrevd_e is obscure about the order of transforms:
157  * For instance: Rotation must be made after or before mirroring ?
158  * Note: if something is changed here, GetYXPosition must reflect changes
159  */
160  wxPoint abPos = aXYPosition + m_GerberImageFile->m_ImageJustifyOffset;
161 
162  if( m_swapAxis )
163  std::swap( abPos.x, abPos.y );
164 
166  abPos.x = KiROUND( abPos.x * m_drawScale.x );
167  abPos.y = KiROUND( abPos.y * m_drawScale.y );
168  double rotation = m_lyrRotation * 10 + m_GerberImageFile->m_ImageRotation * 10;
169 
170  if( rotation )
171  RotatePoint( &abPos, -rotation );
172 
173  // Negate A axis if mirrored
174  if( m_mirrorA )
175  abPos.x = -abPos.x;
176 
177  // abPos.y must be negated when no mirror, because draw axis is top to bottom
178  if( !m_mirrorB )
179  abPos.y = -abPos.y;
180  return abPos;
181 }
182 
183 
185 {
186  // do the inverse transform made by GetABPosition
187  wxPoint xyPos = aABPosition;
188 
189  if( m_mirrorA )
190  xyPos.x = -xyPos.x;
191 
192  if( !m_mirrorB )
193  xyPos.y = -xyPos.y;
194 
195  double rotation = m_lyrRotation * 10 + m_GerberImageFile->m_ImageRotation * 10;
196 
197  if( rotation )
198  RotatePoint( &xyPos, rotation );
199 
200  xyPos.x = KiROUND( xyPos.x / m_drawScale.x );
201  xyPos.y = KiROUND( xyPos.y / m_drawScale.y );
203 
204  if( m_swapAxis )
205  std::swap( xyPos.x, xyPos.y );
206 
207  return xyPos - m_GerberImageFile->m_ImageJustifyOffset;
208 }
209 
210 
212 {
214  m_swapAxis = m_GerberImageFile->m_SwapAxis; // false if A = X, B = Y;
215 
216  // true if A =Y, B = Y
217  m_mirrorA = m_GerberImageFile->m_MirrorA; // true: mirror / axe A
218  m_mirrorB = m_GerberImageFile->m_MirrorB; // true: mirror / axe B
219  m_drawScale = m_GerberImageFile->m_Scale; // A and B scaling factor
220  m_layerOffset = m_GerberImageFile->m_Offset; // Offset from OF command
221 
222  // Rotation from RO command:
225 }
226 
227 
229 {
230  switch( m_Shape )
231  {
232  case GBR_SEGMENT:
233  return _( "Line" );
234 
235  case GBR_ARC:
236  return _( "Arc" );
237 
238  case GBR_CIRCLE:
239  return _( "Circle" );
240 
241  case GBR_SPOT_OVAL:
242  return wxT( "spot_oval" );
243 
244  case GBR_SPOT_CIRCLE:
245  return wxT( "spot_circle" );
246 
247  case GBR_SPOT_RECT:
248  return wxT( "spot_rect" );
249 
250  case GBR_SPOT_POLY:
251  return wxT( "spot_poly" );
252 
253  case GBR_POLYGON:
254  return wxT( "polygon" );
255 
256  case GBR_SPOT_MACRO:
257  {
258  wxString name = wxT( "apt_macro" );
259  D_CODE* dcode = GetDcodeDescr();
260 
261  if( dcode && dcode->GetMacro() )
262  name << wxT(" ") << dcode->GetMacro()->name;
263 
264  return name;
265  }
266 
267  default:
268  return wxT( "??" );
269  }
270 }
271 
272 
274 {
275  if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) )
276  return NULL;
277 
278  if( m_GerberImageFile == NULL )
279  return NULL;
280 
282 }
283 
284 
286 {
287  // return a rectangle which is (pos,dim) in nature. therefore the +1
288  EDA_RECT bbox( m_Start, wxSize( 1, 1 ) );
289  D_CODE* code = GetDcodeDescr();
290 
291  // TODO(JE) GERBER_DRAW_ITEM maybe should actually be a number of subclasses.
292  // Until/unless that is changed, we need to do different things depending on
293  // what is actually being represented by this GERBER_DRAW_ITEM.
294 
295  switch( m_Shape )
296  {
297  case GBR_POLYGON:
298  {
299  auto bb = m_Polygon.BBox();
300  bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 );
301  bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y );
302  break;
303  }
304 
305  case GBR_CIRCLE:
306  {
307  double radius = GetLineLength( m_Start, m_End );
308  bbox.Inflate( radius, radius );
309  break;
310  }
311 
312  case GBR_ARC:
313  {
314  // Note: using a larger-than-necessary BB to simplify computation
315  double radius = GetLineLength( m_Start, m_ArcCentre );
316  bbox.Move( m_ArcCentre - m_Start );
317  bbox.Inflate( radius + m_Size.x, radius + m_Size.x );
318  break;
319  }
320 
321  case GBR_SPOT_CIRCLE:
322  {
323  int radius = code->m_Size.x >> 1;
324  bbox.Inflate( radius, radius );
325  break;
326  }
327 
328  case GBR_SPOT_RECT:
329  {
330  bbox.Inflate( code->m_Size.x / 2, code->m_Size.y / 2 );
331  break;
332  }
333 
334  case GBR_SPOT_OVAL:
335  {
336  bbox.Inflate( code->m_Size.x, code->m_Size.y );
337  break;
338  }
339 
340  case GBR_SPOT_POLY:
341  {
342  if( code->m_Polygon.OutlineCount() == 0 )
343  code->ConvertShapeToPolygon();
344 
345  bbox.Inflate( code->m_Polygon.BBox().GetWidth() / 2, code->m_Polygon.BBox().GetHeight() / 2 );
346  break;
347  }
348  case GBR_SPOT_MACRO:
349  {
350  // Update the shape drawings and the bounding box coordiantes:
351  code->GetMacro()->GetApertureMacroShape( this, m_Start );
352  // now the bounding box is valid:
353  bbox = code->GetMacro()->GetBoundingBox();
354  break;
355  }
356 
357  case GBR_SEGMENT:
358  {
359  if( code && code->m_Shape == APT_RECT )
360  {
361  if( m_Polygon.OutlineCount() > 0 )
362  {
363  auto bb = m_Polygon.BBox();
364  bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 );
365  bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y );
366  }
367  }
368  else
369  {
370  int radius = ( m_Size.x + 1 ) / 2;
371 
372  int ymax = std::max( m_Start.y, m_End.y ) + radius;
373  int xmax = std::max( m_Start.x, m_End.x ) + radius;
374 
375  int ymin = std::min( m_Start.y, m_End.y ) - radius;
376  int xmin = std::min( m_Start.x, m_End.x ) - radius;
377 
378  bbox = EDA_RECT( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) );
379  }
380 
381  break;
382  }
383  default:
384  wxASSERT_MSG( false, wxT( "GERBER_DRAW_ITEM shape is unknown!" ) );
385  break;
386  }
387 
388  // calculate the corners coordinates in current gerber axis orientations
389  wxPoint org = GetABPosition( bbox.GetOrigin() );
390  wxPoint end = GetABPosition( bbox.GetEnd() );
391 
392  // Set the corners position:
393  bbox.SetOrigin( org );
394  bbox.SetEnd( end );
395  bbox.Normalize();
396 
397  return bbox;
398 }
399 
400 
401 void GERBER_DRAW_ITEM::MoveAB( const wxPoint& aMoveVector )
402 {
403  wxPoint xymove = GetXYPosition( aMoveVector );
404 
405  m_Start += xymove;
406  m_End += xymove;
407  m_ArcCentre += xymove;
408 
409  if( m_Polygon.OutlineCount() > 0 )
410  {
411  for( auto it = m_Polygon.Iterate( 0 ); it; ++it )
412  *it += xymove;
413  }
414 }
415 
416 
417 void GERBER_DRAW_ITEM::MoveXY( const wxPoint& aMoveVector )
418 {
419  m_Start += aMoveVector;
420  m_End += aMoveVector;
421  m_ArcCentre += aMoveVector;
422 
423  if( m_Polygon.OutlineCount() > 0 )
424  {
425  for( auto it = m_Polygon.Iterate( 0 ); it; ++it )
426  *it += aMoveVector;
427  }
428 }
429 
430 
432 {
434 
435  // if isClear is true, this item has negative shape
436  return isClear;
437 }
438 
439 
440 void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
441  const wxPoint& aOffset, GBR_DISPLAY_OPTIONS* aDrawOptions )
442 {
443  // used when a D_CODE is not found. default D_CODE to draw a flashed item
444  static D_CODE dummyD_CODE( 0 );
445  bool isFilled;
446  int radius;
447  int halfPenWidth;
448  static bool show_err;
449  D_CODE* d_codeDescr = GetDcodeDescr();
450 
451  if( d_codeDescr == NULL )
452  d_codeDescr = &dummyD_CODE;
453 
455 
456  if( ( aDrawMode & GR_HIGHLIGHT ) && !( aDrawMode & GR_AND ) )
457  color.SetToLegacyHighlightColor();
458 
459  /* isDark is true if flash is positive and should use a drawing
460  * color other than the background color, else use the background color
461  * when drawing so that an erasure happens.
462  */
464 
465  if( !isDark )
466  {
467  // draw in background color ("negative" color)
468  color = aDrawOptions->m_NegativeDrawColor;
469  }
470 
471  GRSetDrawMode( aDC, aDrawMode );
472 
473  isFilled = aDrawOptions->m_DisplayLinesFill;
474 
475  switch( m_Shape )
476  {
477  case GBR_POLYGON:
478  isFilled = aDrawOptions->m_DisplayPolygonsFill;
479 
480  if( !isDark )
481  isFilled = true;
482 
483  DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled );
484  break;
485 
486  case GBR_CIRCLE:
487  radius = KiROUND( GetLineLength( m_Start, m_End ) );
488 
489  halfPenWidth = m_Size.x >> 1;
490 
491  if( !isFilled )
492  {
493  // draw the border of the pen's path using two circles, each as narrow as possible
494  GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
495  radius - halfPenWidth, 0, color );
496  GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
497  radius + halfPenWidth, 0, color );
498  }
499  else // Filled mode
500  {
501  GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
502  radius, m_Size.x, color );
503  }
504  break;
505 
506  case GBR_ARC:
507  // Currently, arcs plotted with a rectangular aperture are not supported.
508  // a round pen only is expected.
509 
510 #if 0 // for arc debug only
511  GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
513  GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_End ),
515 #endif
516 
517  if( !isFilled )
518  {
519  GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
521  0, color );
522  }
523  else
524  {
525  GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
527  m_Size.x, color );
528  }
529 
530  break;
531 
532  case GBR_SPOT_CIRCLE:
533  case GBR_SPOT_RECT:
534  case GBR_SPOT_OVAL:
535  case GBR_SPOT_POLY:
536  case GBR_SPOT_MACRO:
537  isFilled = aDrawOptions->m_DisplayFlashedItemsFill;
538  d_codeDescr->DrawFlashedShape( this, aPanel->GetClipBox(), aDC, color,
539  m_Start, isFilled );
540  break;
541 
542  case GBR_SEGMENT:
543  /* Plot a line from m_Start to m_End.
544  * Usually, a round pen is used, but some gerber files use a rectangular pen
545  * In fact, any aperture can be used to plot a line.
546  * currently: only a square pen is handled (I believe using a polygon gives a strange plot).
547  */
548  if( d_codeDescr->m_Shape == APT_RECT )
549  {
550  if( m_Polygon.OutlineCount() == 0 )
552 
553  DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled );
554  }
555  else
556  {
557  if( !isFilled )
558  {
559  GRCSegm( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
560  GetABPosition( m_End ), m_Size.x, color );
561  }
562  else
563  {
564  GRFilledSegment( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
565  GetABPosition( m_End ), m_Size.x, color );
566  }
567  }
568 
569  break;
570 
571  default:
572  if( !show_err )
573  {
574  wxMessageBox( wxT( "Trace_Segment() type error" ) );
575  show_err = true;
576  }
577 
578  break;
579  }
580 }
581 
582 
584 {
587 
588  wxPoint start = m_Start;
589  wxPoint end = m_End;
590 
591  // make calculations more easy if ensure start.x < end.x
592  // (only 2 quadrants to consider)
593  if( start.x > end.x )
594  std::swap( start, end );
595 
596  // calculate values relative to start point:
597  wxPoint delta = end - start;
598 
599  // calculate corners for the first quadrant only (delta.x and delta.y > 0 )
600  // currently, delta.x already is > 0.
601  // make delta.y > 0
602  bool change = delta.y < 0;
603 
604  if( change )
605  delta.y = -delta.y;
606 
607  // Now create the full polygon.
608  // Due to previous changes, the shape is always something like
609  // 3 4
610  // 2 5
611  // 1 6
612  wxPoint corner;
613  corner.x -= m_Size.x/2;
614  corner.y -= m_Size.y/2;
615  wxPoint close = corner;
616  m_Polygon.Append( VECTOR2I( corner ) ); // Lower left corner, start point (1)
617  corner.y += m_Size.y;
618  m_Polygon.Append( VECTOR2I( corner ) ); // upper left corner, start point (2)
619 
620  if( delta.x || delta.y)
621  {
622  corner += delta;
623  m_Polygon.Append( VECTOR2I( corner ) ); // upper left corner, end point (3)
624  }
625 
626  corner.x += m_Size.x;
627  m_Polygon.Append( VECTOR2I( corner ) ); // upper right corner, end point (4)
628  corner.y -= m_Size.y;
629  m_Polygon.Append( VECTOR2I( corner ) ); // lower right corner, end point (5)
630 
631  if( delta.x || delta.y )
632  {
633  corner -= delta;
634  m_Polygon.Append( VECTOR2I( corner ) ); // lower left corner, start point (6)
635  }
636 
637  m_Polygon.Append( VECTOR2I( close ) ); // close the shape
638 
639  // Create final polygon:
640  for( auto it = m_Polygon.Iterate( 0 ); it; ++it )
641  {
642  if( change )
643  ( *it ).y = -( *it ).y;
644 
645  *it += start;
646  }
647 }
648 
649 
651  wxDC* aDC,
652  COLOR4D aColor,
653  const wxPoint& aOffset,
654  bool aFilledShape )
655 {
656  std::vector<wxPoint> points;
657  SHAPE_LINE_CHAIN& poly = m_Polygon.Outline( 0 );
658  int pointCount = poly.PointCount() - 1;
659 
660  points.reserve( pointCount );
661 
662  for( int ii = 0; ii < pointCount; ii++ )
663  {
664  wxPoint p( poly.Point( ii ).x, poly.Point( ii ).y );
665  points[ii] = p + aOffset;
666  points[ii] = GetABPosition( points[ii] );
667  }
668 
669  GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilledShape, aColor, aColor );
670 }
671 
672 
673 void GERBER_DRAW_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
674 {
675  wxString msg;
676  wxString text;
677 
678  msg = ShowGBRShape();
679  aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
680 
681  // Display D_Code value with its attributes:
682  msg.Printf( _( "D Code %d" ), m_DCode );
683  D_CODE* apertDescr = GetDcodeDescr();
684 
685  if( !apertDescr || apertDescr->m_AperFunction.IsEmpty() )
686  text = _( "No attribute" );
687  else
688  text = apertDescr->m_AperFunction;
689 
690  aList.push_back( MSG_PANEL_ITEM( msg, text, RED ) );
691 
692  // Display graphic layer name
694  aList.push_back( MSG_PANEL_ITEM( _( "Graphic Layer" ), msg, DARKGREEN ) );
695 
696  // Display item rotation
697  // The full rotation is Image rotation + m_lyrRotation
698  // but m_lyrRotation is specific to this object
699  // so we display only this parameter
700  msg.Printf( wxT( "%f" ), m_lyrRotation );
701  aList.push_back( MSG_PANEL_ITEM( _( "Rotation" ), msg, BLUE ) );
702 
703  // Display item polarity (item specific)
704  msg = m_LayerNegative ? _("Clear") : _("Dark");
705  aList.push_back( MSG_PANEL_ITEM( _( "Polarity" ), msg, BLUE ) );
706 
707  // Display mirroring (item specific)
708  msg.Printf( wxT( "A:%s B:%s" ),
709  m_mirrorA ? _("Yes") : _("No"),
710  m_mirrorB ? _("Yes") : _("No"));
711  aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), msg, DARKRED ) );
712 
713  // Display AB axis swap (item specific)
714  msg = m_swapAxis ? wxT( "A=Y B=X" ) : wxT( "A=X B=Y" );
715  aList.push_back( MSG_PANEL_ITEM( _( "AB axis" ), msg, DARKRED ) );
716 
717  // Display net info, if exists
719  return;
720 
721  // Build full net info:
722  wxString net_msg;
723  wxString cmp_pad_msg;
724 
726  {
727  net_msg = _( "Net:" );
728  net_msg << " ";
729 
730  if( m_netAttributes.m_Netname.IsEmpty() )
731  net_msg << "<no net name>";
732  else
733  net_msg << m_netAttributes.m_Netname;
734  }
735 
737  {
738  cmp_pad_msg.Printf( _( "Cmp: %s; Pad: %s" ),
741  }
742 
744  {
745  cmp_pad_msg = _( "Cmp:" );
746  cmp_pad_msg << " " << m_netAttributes.m_Cmpref;
747  }
748 
749  aList.push_back( MSG_PANEL_ITEM( net_msg, cmp_pad_msg, DARKCYAN ) );
750 }
751 
752 
753 bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
754 {
755  // calculate aRefPos in XY gerber axis:
756  wxPoint ref_pos = GetXYPosition( aRefPos );
757 
758  SHAPE_POLY_SET poly;
759 
760  switch( m_Shape )
761  {
762  case GBR_POLYGON:
763  poly = m_Polygon;
764  return poly.Contains( VECTOR2I( ref_pos ), 0 );
765 
766  case GBR_SPOT_POLY:
767  poly = GetDcodeDescr()->m_Polygon;
768  poly.Move( m_Start );
769  return poly.Contains( VECTOR2I( ref_pos ), 0 );
770 
771  case GBR_SPOT_RECT:
772  case GBR_ARC:
773  return GetBoundingBox().Contains( aRefPos );
774 
775  case GBR_SPOT_MACRO:
776  // Aperture macro polygons are already in absolute coordinates
777  auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
778  for( int i = 0; i < p->OutlineCount(); ++i )
779  {
780  if( p->Contains( VECTOR2I( aRefPos ), i ) )
781  return true;
782  }
783  return false;
784  }
785 
786  // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
787  int radius = std::min( m_Size.x, m_Size.y ) >> 1;
788 
789  if( m_Flashed )
790  return HitTestPoints( m_Start, ref_pos, radius );
791  else
792  return TestSegmentHit( ref_pos, m_Start, m_End, radius );
793 }
794 
795 
796 bool GERBER_DRAW_ITEM::HitTest( const EDA_RECT& aRefArea ) const
797 {
798  wxPoint pos = GetABPosition( m_Start );
799 
800  if( aRefArea.Contains( pos ) )
801  return true;
802 
803  pos = GetABPosition( m_End );
804 
805  if( aRefArea.Contains( pos ) )
806  return true;
807 
808  return false;
809 }
810 
811 
812 #if defined(DEBUG)
813 
814 void GERBER_DRAW_ITEM::Show( int nestLevel, std::ostream& os ) const
815 {
816  NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
817 
818  " shape=\"" << m_Shape << '"' <<
819  " addr=\"" << std::hex << this << std::dec << '"' <<
820  " layer=\"" << GetLayer() << '"' <<
821  " size=\"" << m_Size << '"' <<
822  " flags=\"" << m_Flags << '"' <<
823  " status=\"" << GetStatus() << '"' <<
824  "<start" << m_Start << "/>" <<
825  "<end" << m_End << "/>";
826 
827  os << "</" << GetClass().Lower().mb_str() << ">\n";
828 }
829 
830 #endif
831 
832 
833 void GERBER_DRAW_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const
834 {
835  aCount = 2;
836 
837  aLayers[0] = GERBER_DRAW_LAYER( GetLayer() );
838  aLayers[1] = GERBER_DCODE_LAYER( aLayers[0] );
839 }
840 
841 
843 {
844  EDA_RECT bbox = GetBoundingBox();
845  return BOX2I( VECTOR2I( bbox.GetOrigin() ),
846  VECTOR2I( bbox.GetSize() ) );
847 }
848 
849 
850 unsigned int GERBER_DRAW_ITEM::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
851 {
852  // DCodes will be shown only if zoom is appropriate:
853  // Returns the level of detail of the item.
854  // A level of detail (LOD) is the minimal VIEW scale that
855  // is sufficient for an item to be shown on a given layer.
856  if( IsDCodeLayer( aLayer ) )
857  {
858  int size = 0;
859 
860  switch( m_Shape )
861  {
862  case GBR_SPOT_MACRO:
864  break;
865 
866  case GBR_ARC:
867  size = GetLineLength( m_Start, m_ArcCentre );
868  break;
869 
870  default:
871  size = m_Size.x;
872  }
873 
874  // the level of details is chosen experimentally, to show
875  // only a readable text:
876  const int level = Millimeter2iu( 500 );
877  return ( level / ( size + 1 ) );
878  }
879 
880  // Other layers are shown without any conditions
881  return 0;
882 }
883 
884 
885 SEARCH_RESULT GERBER_DRAW_ITEM::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
886 {
887  KICAD_T stype = *scanTypes;
888 
889  // If caller wants to inspect my type
890  if( stype == Type() )
891  {
892  if( SEARCH_QUIT == inspector( this, testData ) )
893  return SEARCH_QUIT;
894  }
895 
896  return SEARCH_CONTINUE;
897 }
898 
899 
901 {
902  wxString text, layerName;
903 
905 
906  text.Printf( _( "%s (D%d) on layer %d: %s" ), ShowGBRShape(), m_DCode,
907  GetLayer() + 1, layerName );
908 
909  return text;
910 }
Definition: colors.h:57
COLOR4D GetPositiveDrawColor() const
void SetLayerParameters()
Function SetLayerParameters Initialize parameters from Image and Layer parameters found in the gerber...
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: common.h:90
void DrawGbrPoly(EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, const wxPoint &aOffset, bool aFilledShape)
Function DrawGbrPoly a helper function used to draw the polygon stored in m_PolyCorners.
bool m_DisplayPolygonsFill
Option to draw polygons (filled/sketch)
BOX2< VECTOR2I > BOX2I
Definition: box2.h:468
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
bool IsDCodeLayer(int aLayer)
wxString name
The name of the aperture macro.
wxString GetClass() const override
Function GetClass returns the class name.
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
D_CODE * GetDCODE(int aDCODE) const
Function GetDCODE returns a pointer to the D_CODE within this GERBER for the given aDCODE...
void MoveAB(const wxPoint &aMoveVector)
Function MoveAB move this object.
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:296
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
print info associated to a component (TO.C attribute)
wxSize m_Size
Horizontal and vertical dimensions.
Definition: dcode.h:94
const wxString GetDisplayName(int aIdx, bool aNameOnly=false)
bool HasNegativeItems()
Function HasNegativeItems.
void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
int PointCount() const
Function PointCount()
bool Contains(const wxPoint &aPoint) const
Function Contains.
APERTURE_T m_Shape
shape ( Line, rectangle, circle , oval .. )
Definition: dcode.h:95
virtual const BOX2I ViewBBox() const override
Class GERBER_FILE_IMAGE holds the Image data and parameters for one gerber file and layer parameters ...
double RAD2DECIDEG(double rad)
Definition: trigo.h:204
GERBER_DRAW_ITEM(GERBER_FILE_IMAGE *aGerberparams)
wxString m_Cmpref
the component reference parent of the data
void SetOrigin(const wxPoint &pos)
void GRCSegm(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, int aPenSize, COLOR4D Color)
Definition: gr_basic.cpp:488
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
ITERATOR Iterate(int aFirst, int aLast, bool aIterateHoles=false)
Function Iterate returns an object to iterate through the points of the polygons between aFirst and a...
int OutlineCount() const
Returns the number of outlines in the set
this class handle info which can be added in a gerber file as attribute of an obtect the GBR_INFO_TYP...
STATUS_FLAGS GetStatus() const
Definition: base_struct.h:264
VECTOR2< int > VECTOR2I
Definition: vector2d.h:589
SHAPE_POLY_SET m_Polygon
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
>
void NORMALIZE_ANGLE_90(T &Angle)
Definition: trigo.h:299
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:784
static const int delta[8][2]
Definition: solve.cpp:112
Definition: dcode.h:52
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
Definition: colors.h:54
bool m_DisplayLinesFill
Option to draw line items (filled/sketch)
virtual wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
coord_type GetWidth() const
Definition: box2.h:185
#define LAST_DCODE
Definition: dcode.h:72
#define GERBER_DCODE_LAYER(x)
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:118
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
const wxPoint & GetOrigin() const
COLOR4D m_NegativeDrawColor
The color used to draw negative objects, usually the background color, but not always, when negative objects must be visible.
int GetLayer() const
Function GetLayer returns the layer this item is on.
wxString m_Padname
for a flashed pad: the pad name ((TO.P attribute)
SHAPE_POLY_SET * GetApertureMacroShape(const GERBER_DRAW_ITEM *aParent, wxPoint aShapePos)
Function GetApertureMacroShape Calculate the primitive shape for flashed items.
wxString ShowGBRShape() const
void Move(const VECTOR2I &aVector) override
#define FIRST_DCODE
Definition: dcode.h:71
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
void SetEnd(int x, int y)
bool m_DisplayFlashedItemsFill
Option to draw flashed items (filled/sketch)
static GERBER_FILE_IMAGE_LIST & GetImagesList()
GBR_NETLIST_METADATA m_netAttributes
the string given by a TO attribute set in aperture (dcode).
bool GetTextD_CodePrms(int &aSize, wxPoint &aPos, double &aOrientation)
Returns the best size and orientation to display the D_Code on screen.
wxString m_Netname
for items associated to a net: the netname
EDA_RECT * GetClipBox()
Definition: colors.h:60
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:358
int NewOutline()
Creates a new empty polygon in the set and returns its index
void ConvertSegmentToPolygon()
Function ConvertSegmentToPolygon convert a line to an equivalent polygon.
std::map< wxString, int > m_NetnamesList
const wxPoint GetEnd() const
wxString m_AperFunction
the aperture attribute (created by a TA.AperFunction command) attached to the D_CODE ...
Definition: dcode.h:105
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, GR_DRAWMODE aDrawMode, const wxPoint &aOffset, GBR_DISPLAY_OPTIONS *aDrawOptions)
void Normalize()
Function Normalize ensures that the height ant width are positive.
coord_type GetHeight() const
Definition: box2.h:186
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Class D_CODE holds a gerber DCODE (also called Aperture) definition.
Definition: dcode.h:82
#define max(a, b)
Definition: auxiliary.h:86
void DrawFlashedShape(GERBER_DRAW_ITEM *aParent, EDA_RECT *aClipBox, wxDC *aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape)
Function DrawFlashedShape Draw the dcode shape for flashed items.
Definition: dcode.cpp:154
Class SHAPE_LINE_CHAIN.
EDA_RECT GetBoundingBox() const
Returns the bounding box of the shape.
void GRFilledSegment(EDA_RECT *aClipBox, wxDC *aDC, wxPoint aStart, wxPoint aEnd, int aWidth, COLOR4D aColor)
Definition: gr_basic.cpp:599
void GRCircle(EDA_RECT *ClipBox, wxDC *DC, int xc, int yc, int r, int width, COLOR4D Color)
Definition: gr_basic.cpp:828
bool HitTestPoints(const wxPoint &pointA, const wxPoint &pointB, double threshold)
Test, if two points are near each other.
Definition: trigo.h:150
STATUS_FLAGS m_Flags
Flag bits for editing and other uses.
Definition: base_struct.h:189
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
Class EDA_RECT handles the component boundary box.
double DECIDEG2RAD(double deg)
Definition: trigo.h:203
SHAPE_POLY_SET m_Polygon
Definition: dcode.h:107
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
The common library.
int GetWidth() const
const char * name
APERTURE_MACRO * GetMacro() const
Definition: dcode.h:157
print info associated to a flashed pad (TO.P attribute)
VECTOR2I & Point(int aIndex)
Function Point()
#define GERBER_DRAW_LAYER(x)
void ConvertShapeToPolygon()
Function ConvertShapeToPolygon convert a shape to an equivalent polygon.
Definition: dcode.cpp:303
bool HitTest(const wxPoint &aRefPos) const override
Function HitTest tests if the given wxPoint is within the bounds of this object.
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
Class VIEW.
Definition: view.h:58
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Function TestSegmentHit test for hit on line segment i.e.
Definition: trigo.cpp:142
SEARCH_RESULT
Definition: base_struct.h:82
void MoveXY(const wxPoint &aMoveVector)
Function MoveXY move this object.
Message panel definition file.
wxPoint GetXYPosition(const wxPoint &aABPosition) const
Function GetXYPosition returns the image position of aPosition for this object.
const wxSize & GetSize() const
wxPoint GetABPosition(const wxPoint &aXYPosition) const
Function GetABPosition returns the image position of aPosition for this object.
print info associated to a net (TO.N attribute)
const BOX2I BBox(int aClearance=0) const override
Function BBox()
int GetShapeDim(GERBER_DRAW_ITEM *aParent)
Function GetShapeDim calculates a value that can be used to evaluate the size of text when displaying...
Definition: dcode.cpp:123
GERBER_FILE_IMAGE * m_GerberImageFile
std::map< wxString, int > m_ComponentsList
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1) const
Returns true if a given subpolygon contains the point aP.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
GERBER_LAYER & GetLayerParams()
Function GetLayerParams.
#define min(a, b)
Definition: auxiliary.h:85
int m_NetAttribType
the type of net info (used to define the gerber string to create)
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) ...
void GRArc1(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int xc, int yc, COLOR4D Color)
Definition: gr_basic.cpp:872
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39