KiCad PCB EDA Suite
class_pad.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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <trigo.h>
33 #include <macros.h>
34 #include <msgpanel.h>
35 #include <base_units.h>
36 #include <bitmaps.h>
37 
38 #include <view/view.h>
39 #include <pcbnew.h>
40 
41 #include <class_board.h>
42 #include <class_module.h>
44 #include <convert_to_biu.h>
46 
47 
54 static wxString LayerMaskDescribe( const BOARD* aBoard, LSET aMask );
55 
56 int D_PAD::m_PadSketchModePenSize = 0; // Pen size used to draw pads in sketch mode
57 
58 D_PAD::D_PAD( MODULE* parent ) :
60 {
61  m_Size.x = m_Size.y = Mils2iu( 60 ); // Default pad size 60 mils.
62  m_Drill.x = m_Drill.y = Mils2iu( 30 ); // Default drill size 30 mils.
63  m_Orient = 0; // Pad rotation in 1/10 degrees.
64  m_LengthPadToDie = 0;
65 
66  if( m_Parent && m_Parent->Type() == PCB_MODULE_T )
67  {
69  }
70 
71  SetShape( PAD_SHAPE_CIRCLE ); // Default pad shape is PAD_CIRCLE.
72  SetAnchorPadShape( PAD_SHAPE_CIRCLE ); // Default shape for custom shaped pads
73  // is PAD_CIRCLE.
74  SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle.
75  m_Attribute = PAD_ATTRIB_STANDARD; // Default pad type is NORMAL (thru hole)
76  m_LocalClearance = 0;
80  // Parameters for round rect only:
81  m_padRoundRectRadiusScale = 0.25; // from IPC-7351C standard
82 
83  m_ZoneConnection = PAD_ZONE_CONN_INHERITED; // Use parent setting by default
84  m_ThermalWidth = 0; // Use parent setting by default
85  m_ThermalGap = 0; // Use parent setting by default
86 
88 
89  // Set layers mask to default for a standard thru hole pad.
91 
92  SetSubRatsnest( 0 ); // used in ratsnest calculations
93 
94  m_boundingRadius = -1;
95 }
96 
97 
99 {
100  static LSET saved = LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask );
101  return saved;
102 }
103 
104 
106 {
107  static LSET saved( 3, F_Cu, F_Paste, F_Mask );
108  return saved;
109 }
110 
111 
113 {
114  static LSET saved( 2, F_Cu, F_Mask );
115  return saved;
116 }
117 
118 
120 {
121  static LSET saved = LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask );
122  return saved;
123 }
124 
125 
127 {
128  static LSET saved = LSET( 1, F_Paste );
129  return saved;
130 }
131 
132 
133 bool D_PAD::IsFlipped() const
134 {
135  if( GetParent() && GetParent()->GetLayer() == B_Cu )
136  return true;
137  return false;
138 }
139 
141 {
142  int x, y;
143  int radius;
144 
145  switch( GetShape() )
146  {
147  case PAD_SHAPE_CIRCLE:
148  radius = m_Size.x / 2;
149  break;
150 
151  case PAD_SHAPE_OVAL:
152  radius = std::max( m_Size.x, m_Size.y ) / 2;
153  break;
154 
155  case PAD_SHAPE_RECT:
156  radius = 1 + KiROUND( EuclideanNorm( m_Size ) / 2 );
157  break;
158 
159  case PAD_SHAPE_TRAPEZOID:
160  x = m_Size.x + std::abs( m_DeltaSize.y ); // Remember: m_DeltaSize.y is the m_Size.x change
161  y = m_Size.y + std::abs( m_DeltaSize.x ); // Remember: m_DeltaSize.x is the m_Size.y change
162  radius = 1 + KiROUND( hypot( x, y ) / 2 );
163  break;
164 
165  case PAD_SHAPE_ROUNDRECT:
166  radius = GetRoundRectCornerRadius();
167  x = m_Size.x >> 1;
168  y = m_Size.y >> 1;
169  radius += 1 + KiROUND( EuclideanNorm( wxSize( x - radius, y - radius )));
170  break;
171 
172  case PAD_SHAPE_CUSTOM:
173  radius = 0;
174 
175  for( int cnt = 0; cnt < m_customShapeAsPolygon.OutlineCount(); ++cnt )
176  {
177  const SHAPE_LINE_CHAIN& poly = m_customShapeAsPolygon.COutline( cnt );
178  for( int ii = 0; ii < poly.PointCount(); ++ii )
179  {
180  int dist = KiROUND( poly.CPoint( ii ).EuclideanNorm() );
181  radius = std::max( radius, dist );
182  }
183  }
184 
185  radius += 1;
186  break;
187 
188  default:
189  radius = 0;
190  }
191 
192  return radius;
193 }
194 
195 
196 int D_PAD::GetRoundRectCornerRadius( const wxSize& aSize ) const
197 {
198  // radius of rounded corners, usually 25% of shorter pad edge for now
199  int r = aSize.x > aSize.y ? aSize.y : aSize.x;
200  r = int( r * m_padRoundRectRadiusScale );
201 
202  return r;
203 }
204 
205 
206 void D_PAD::SetRoundRectCornerRadius( double aRadius )
207 {
208  int min_r = std::min( m_Size.x, m_Size.y );
209 
210  if( min_r > 0 )
211  SetRoundRectRadiusRatio( aRadius / min_r );
212 }
213 
214 
216 {
217  EDA_RECT area;
218  wxPoint quadrant1, quadrant2, quadrant3, quadrant4;
219  int x, y, r, dx, dy;
220 
221  wxPoint center = ShapePos();
222  wxPoint endPoint;
223 
224  EDA_RECT endRect;
225 
226  switch( GetShape() )
227  {
228  case PAD_SHAPE_CIRCLE:
229  area.SetOrigin( center );
230  area.Inflate( m_Size.x / 2 );
231  break;
232 
233  case PAD_SHAPE_OVAL:
234  /* To get the BoundingBox of an oval pad:
235  * a) If the pad is ROUND, see method for PAD_SHAPE_CIRCLE above
236  * OTHERWISE:
237  * b) Construct EDA_RECT for portion between circular ends
238  * c) Rotate that EDA_RECT
239  * d) Add the circular ends to the EDA_RECT
240  */
241 
242  // Test if the shape is circular
243  if( m_Size.x == m_Size.y )
244  {
245  area.SetOrigin( center );
246  area.Inflate( m_Size.x / 2 );
247  break;
248  }
249 
250  if( m_Size.x > m_Size.y )
251  {
252  // Pad is horizontal
253  dx = ( m_Size.x - m_Size.y ) / 2;
254  dy = m_Size.y / 2;
255 
256  // Location of end-points
257  x = dx;
258  y = 0;
259  r = dy;
260  }
261  else
262  {
263  // Pad is vertical
264  dx = m_Size.x / 2;
265  dy = ( m_Size.y - m_Size.x ) / 2;
266 
267  x = 0;
268  y = dy;
269  r = dx;
270  }
271 
272  // Construct the center rectangle and rotate
273  area.SetOrigin( center );
274  area.Inflate( dx, dy );
275  area = area.GetBoundingBoxRotated( center, m_Orient );
276 
277  endPoint = wxPoint( x, y );
278  RotatePoint( &endPoint, m_Orient );
279 
280  // Add points at each quadrant of circular regions
281  endRect.SetOrigin( center + endPoint );
282  endRect.Inflate( r );
283 
284  area.Merge( endRect );
285 
286  endRect.SetSize( 0, 0 );
287  endRect.SetOrigin( center - endPoint );
288  endRect.Inflate( r );
289 
290  area.Merge( endRect );
291 
292  break;
293 
294  case PAD_SHAPE_RECT:
295  case PAD_SHAPE_ROUNDRECT:
296  // Use two opposite corners and track their rotation
297  // (use symmetry for other points)
298  quadrant1.x = m_Size.x/2;
299  quadrant1.y = m_Size.y/2;
300  quadrant2.x = -m_Size.x/2;
301  quadrant2.y = m_Size.y/2;
302 
303  RotatePoint( &quadrant1, m_Orient );
304  RotatePoint( &quadrant2, m_Orient );
305  dx = std::max( std::abs( quadrant1.x ) , std::abs( quadrant2.x ) );
306  dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y ) );
307 
308  // Set the bbox
309  area.SetOrigin( ShapePos() );
310  area.Inflate( dx, dy );
311  break;
312 
313  case PAD_SHAPE_TRAPEZOID:
314  // Use the four corners and track their rotation
315  // (Trapezoids will not be symmetric)
316 
317  quadrant1.x = (m_Size.x + m_DeltaSize.y)/2;
318  quadrant1.y = (m_Size.y - m_DeltaSize.x)/2;
319 
320  quadrant2.x = -(m_Size.x + m_DeltaSize.y)/2;
321  quadrant2.y = (m_Size.y + m_DeltaSize.x)/2;
322 
323  quadrant3.x = -(m_Size.x - m_DeltaSize.y)/2;
324  quadrant3.y = -(m_Size.y + m_DeltaSize.x)/2;
325 
326  quadrant4.x = (m_Size.x - m_DeltaSize.y)/2;
327  quadrant4.y = -(m_Size.y - m_DeltaSize.x)/2;
328 
329  RotatePoint( &quadrant1, m_Orient );
330  RotatePoint( &quadrant2, m_Orient );
331  RotatePoint( &quadrant3, m_Orient );
332  RotatePoint( &quadrant4, m_Orient );
333 
334  x = std::min( quadrant1.x, std::min( quadrant2.x, std::min( quadrant3.x, quadrant4.x) ) );
335  y = std::min( quadrant1.y, std::min( quadrant2.y, std::min( quadrant3.y, quadrant4.y) ) );
336  dx = std::max( quadrant1.x, std::max( quadrant2.x, std::max( quadrant3.x, quadrant4.x) ) );
337  dy = std::max( quadrant1.y, std::max( quadrant2.y, std::max( quadrant3.y, quadrant4.y) ) );
338 
339  area.SetOrigin( ShapePos().x + x, ShapePos().y + y );
340  area.SetSize( dx-x, dy-y );
341  break;
342 
343  case PAD_SHAPE_CUSTOM:
344  {
346  // Move shape to actual position
348  quadrant1 = m_Pos;
349  quadrant2 = m_Pos;
350 
351  for( int cnt = 0; cnt < polySet.OutlineCount(); ++cnt )
352  {
353  const SHAPE_LINE_CHAIN& poly = polySet.COutline( cnt );
354 
355  for( int ii = 0; ii < poly.PointCount(); ++ii )
356  {
357  quadrant1.x = std::min( quadrant1.x, poly.CPoint( ii ).x );
358  quadrant1.y = std::min( quadrant1.y, poly.CPoint( ii ).y );
359  quadrant2.x = std::max( quadrant2.x, poly.CPoint( ii ).x );
360  quadrant2.y = std::max( quadrant2.y, poly.CPoint( ii ).y );
361  }
362  }
363 
364  area.SetOrigin( quadrant1 );
365  area.SetEnd( quadrant2 );
366  }
367  break;
368 
369  default:
370  break;
371  }
372 
373  return area;
374 }
375 
376 
378 {
379  MODULE* module = (MODULE*) m_Parent;
380 
381  m_Pos = m_Pos0;
382 
383  if( module == NULL )
384  return;
385 
386  double angle = module->GetOrientation();
387 
388  RotatePoint( &m_Pos.x, &m_Pos.y, angle );
389  m_Pos += module->GetPosition();
390 }
391 
392 
394 {
395  MODULE* module = (MODULE*) m_Parent;
396 
397  if( module == NULL )
398  {
399  m_Pos0 = m_Pos;
400  return;
401  }
402 
403  m_Pos0 = m_Pos - module->GetPosition();
404  RotatePoint( &m_Pos0.x, &m_Pos0.y, -module->GetOrientation() );
405 }
406 
407 
408 void D_PAD::SetAttribute( PAD_ATTR_T aAttribute )
409 {
410  m_Attribute = aAttribute;
411 
412  if( aAttribute == PAD_ATTRIB_SMD )
413  m_Drill = wxSize( 0, 0 );
414 }
415 
416 
417 void D_PAD::SetOrientation( double aAngle )
418 {
419  NORMALIZE_ANGLE_POS( aAngle );
420  m_Orient = aAngle;
421 }
422 
423 
424 void D_PAD::Flip( const wxPoint& aCentre )
425 {
426  int y = GetPosition().y;
427  MIRROR( y, aCentre.y ); // invert about x axis.
428  SetY( y );
429 
430  MIRROR( m_Pos0.y, 0 );
431  MIRROR( m_Offset.y, 0 );
432  MIRROR( m_DeltaSize.y, 0 );
433 
435 
436  // flip pads layers
437  // PADS items are currently on all copper layers, or
438  // currently, only on Front or Back layers.
439  // So the copper layers count is not taken in account
441 
442  // Flip the basic shapes, in custom pads
443  FlipPrimitives();
444 
445  // m_boundingRadius = -1; the shape has not been changed
446 }
447 
448 
449 // Flip the basic shapes, in custom pads
451 {
452  // Flip custom shapes
453  for( unsigned ii = 0; ii < m_basicShapes.size(); ++ii )
454  {
455  PAD_CS_PRIMITIVE& primitive = m_basicShapes[ii];
456 
457  MIRROR( primitive.m_Start.y, 0 );
458  MIRROR( primitive.m_End.y, 0 );
459  primitive.m_ArcAngle = -primitive.m_ArcAngle;
460 
461  switch( primitive.m_Shape )
462  {
463  case S_POLYGON: // polygon
464  for( unsigned jj = 0; jj < primitive.m_Poly.size(); jj++ )
465  MIRROR( primitive.m_Poly[jj].y, 0 );
466  break;
467 
468  default:
469  break;
470  }
471  }
472 
473  // Flip local coordinates in merged Polygon
474  for( int cnt = 0; cnt < m_customShapeAsPolygon.OutlineCount(); ++cnt )
475  {
477 
478  for( int ii = 0; ii < poly.PointCount(); ++ii )
479  MIRROR( poly.Point( ii ).y, 0 );
480  }
481 }
482 
483 
485 {
486  // Mirror custom shapes
487  for( unsigned ii = 0; ii < m_basicShapes.size(); ++ii )
488  {
489  PAD_CS_PRIMITIVE& primitive = m_basicShapes[ii];
490 
491  MIRROR( primitive.m_Start.x, aX );
492  MIRROR( primitive.m_End.x, aX );
493  primitive.m_ArcAngle = -primitive.m_ArcAngle;
494 
495  switch( primitive.m_Shape )
496  {
497  case S_POLYGON: // polygon
498  for( unsigned jj = 0; jj < primitive.m_Poly.size(); jj++ )
499  MIRROR( primitive.m_Poly[jj].x, aX );
500  break;
501 
502  default:
503  break;
504  }
505  }
506 
507  // Mirror the local coordinates in merged Polygon
508  for( int cnt = 0; cnt < m_customShapeAsPolygon.OutlineCount(); ++cnt )
509  {
511 
512  for( int ii = 0; ii < poly.PointCount(); ++ii )
513  MIRROR( poly.Point( ii ).x, aX );
514  }
515 }
516 
517 
519 {
520  // Parameters stored in config are only significant parameters
521  // for a template.
522  // So not all parameters are stored, just few.
523  aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadDrill" ),
524  &m_Drill.x,
525  Millimeter2iu( 0.6 ),
526  Millimeter2iu( 0.1 ), Millimeter2iu( 10.0 ),
527  NULL, MM_PER_IU ) );
528 
529  aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadDrillOvalY" ),
530  &m_Drill.y,
531  Millimeter2iu( 0.6 ),
532  Millimeter2iu( 0.1 ), Millimeter2iu( 10.0 ),
533  NULL, MM_PER_IU ) );
534 
535  aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeH" ),
536  &m_Size.x,
537  Millimeter2iu( 1.4 ),
538  Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
539  NULL, MM_PER_IU ) );
540 
541  aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeV" ),
542  &m_Size.y,
543  Millimeter2iu( 1.4 ),
544  Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
545  NULL, MM_PER_IU ) );
546 }
547 
548 
549 // Returns the position of the pad.
550 wxPoint D_PAD::ShapePos() const
551 {
552  if( m_Offset.x == 0 && m_Offset.y == 0 )
553  return m_Pos;
554 
555  wxPoint loc_offset = m_Offset;
556 
557  RotatePoint( &loc_offset, m_Orient );
558 
559  wxPoint shape_pos = m_Pos + loc_offset;
560 
561  return shape_pos;
562 }
563 
564 
565 bool D_PAD::IncrementPadName( bool aSkipUnconnectable, bool aFillSequenceGaps )
566 {
567  bool skip = aSkipUnconnectable && ( GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED );
568 
569  if( !skip )
570  SetName( GetParent()->GetNextPadName( aFillSequenceGaps ) );
571 
572  return !skip;
573 }
574 
575 
576 void D_PAD::CopyNetlistSettings( D_PAD* aPad, bool aCopyLocalSettings )
577 {
578  // Don't do anything foolish like trying to copy to yourself.
579  wxCHECK_RET( aPad != NULL && aPad != this, wxT( "Cannot copy to NULL or yourself." ) );
580 
581  aPad->SetNetCode( GetNetCode() );
582 
583  if( aCopyLocalSettings )
584  {
591  aPad->SetThermalGap( m_ThermalGap );
592  }
593 }
594 
595 
597 {
598  // A pad can have specific clearance parameters that
599  // overrides its NETCLASS clearance value
600  int clearance = m_LocalClearance;
601 
602  if( clearance == 0 )
603  {
604  // If local clearance is 0, use the parent footprint clearance value
605  if( GetParent() && GetParent()->GetLocalClearance() )
606  clearance = GetParent()->GetLocalClearance();
607  }
608 
609  if( clearance == 0 ) // If the parent footprint clearance value = 0, use NETCLASS value
610  return BOARD_CONNECTED_ITEM::GetClearance( aItem );
611 
612  // We have a specific clearance.
613  // if aItem, return the biggest clearance
614  if( aItem )
615  {
616  int hisClearance = aItem->GetClearance();
617  return std::max( hisClearance, clearance );
618  }
619 
620  // Return the specific clearance.
621  return clearance;
622 }
623 
624 
625 // Mask margins handling:
626 
628 {
629  // The pad inherits the margin only to calculate a default shape,
630  // therefore only if it is also a copper layer
631  // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
632  // defined by the pad settings only
633  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
634 
635  if( !isOnCopperLayer )
636  return 0;
637 
638  int margin = m_LocalSolderMaskMargin;
639 
640  MODULE* module = GetParent();
641 
642  if( module )
643  {
644  if( margin == 0 )
645  {
646  if( module->GetLocalSolderMaskMargin() )
647  margin = module->GetLocalSolderMaskMargin();
648  }
649 
650  if( margin == 0 )
651  {
652  BOARD* brd = GetBoard();
653  if( brd )
654  {
655  margin = brd->GetDesignSettings().m_SolderMaskMargin;
656  }
657  }
658  }
659 
660  // ensure mask have a size always >= 0
661  if( margin < 0 )
662  {
663  int minsize = -std::min( m_Size.x, m_Size.y ) / 2;
664 
665  if( margin < minsize )
666  margin = minsize;
667  }
668 
669  return margin;
670 }
671 
672 
674 {
675  // The pad inherits the margin only to calculate a default shape,
676  // therefore only if it is also a copper layer.
677  // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
678  // defined by the pad settings only
679  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
680 
681  if( !isOnCopperLayer )
682  return wxSize( 0, 0 );
683 
684  int margin = m_LocalSolderPasteMargin;
685  double mratio = m_LocalSolderPasteMarginRatio;
686 
687  MODULE* module = GetParent();
688 
689  if( module )
690  {
691  if( margin == 0 )
692  margin = module->GetLocalSolderPasteMargin();
693 
694  auto brd = GetBoard();
695 
696  if( margin == 0 && brd )
697  {
698  margin = brd->GetDesignSettings().m_SolderPasteMargin;
699  }
700 
701  if( mratio == 0.0 )
702  mratio = module->GetLocalSolderPasteMarginRatio();
703 
704  if( mratio == 0.0 && brd )
705  {
706  mratio = brd->GetDesignSettings().m_SolderPasteMarginRatio;
707  }
708  }
709 
710  wxSize pad_margin;
711  pad_margin.x = margin + KiROUND( m_Size.x * mratio );
712  pad_margin.y = margin + KiROUND( m_Size.y * mratio );
713 
714  // ensure mask have a size always >= 0
715  if( pad_margin.x < -m_Size.x / 2 )
716  pad_margin.x = -m_Size.x / 2;
717 
718  if( pad_margin.y < -m_Size.y / 2 )
719  pad_margin.y = -m_Size.y / 2;
720 
721  return pad_margin;
722 }
723 
724 
726 {
727  MODULE* module = GetParent();
728 
729  if( m_ZoneConnection == PAD_ZONE_CONN_INHERITED && module )
730  return module->GetZoneConnection();
731  else
732  return m_ZoneConnection;
733 }
734 
735 
737 {
738  MODULE* module = GetParent();
739 
740  if( m_ThermalWidth == 0 && module )
741  return module->GetThermalWidth();
742  else
743  return m_ThermalWidth;
744 }
745 
746 
748 {
749  MODULE* module = GetParent();
750 
751  if( m_ThermalGap == 0 && module )
752  return module->GetThermalGap();
753  else
754  return m_ThermalGap;
755 }
756 
757 
758 void D_PAD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM>& aList )
759 {
760  MODULE* module;
761  wxString msg;
762  BOARD* board;
763 
764  module = (MODULE*) m_Parent;
765 
766  if( module )
767  {
768  aList.push_back( MSG_PANEL_ITEM( _( "Footprint" ), module->GetReference(), DARKCYAN ) );
769  aList.push_back( MSG_PANEL_ITEM( _( "Pad" ), m_name, BROWN ) );
770  }
771 
772  aList.push_back( MSG_PANEL_ITEM( _( "Net" ), GetNetname(), DARKCYAN ) );
773 
774  board = GetBoard();
775 
776  aList.push_back( MSG_PANEL_ITEM( _( "Layer" ),
777  LayerMaskDescribe( board, m_layerMask ), DARKGREEN ) );
778 
779  aList.push_back( MSG_PANEL_ITEM( ShowPadShape(), ShowPadAttr(), DARKGREEN ) );
780 
781  msg = MessageTextFromValue( aUnits, m_Size.x, true );
782  aList.push_back( MSG_PANEL_ITEM( _( "Width" ), msg, RED ) );
783 
784  msg = MessageTextFromValue( aUnits, m_Size.y, true );
785  aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, RED ) );
786 
787  msg = MessageTextFromValue( aUnits, m_Drill.x, true );
788 
790  {
791  aList.push_back( MSG_PANEL_ITEM( _( "Drill" ), msg, RED ) );
792  }
793  else
794  {
795  msg = MessageTextFromValue( aUnits, m_Drill.x, true )
796  + wxT( "/" )
797  + MessageTextFromValue( aUnits, m_Drill.y, true );
798  aList.push_back( MSG_PANEL_ITEM( _( "Drill X / Y" ), msg, RED ) );
799  }
800 
801  double module_orient_degrees = module ? module->GetOrientationDegrees() : 0;
802 
803  if( module_orient_degrees != 0.0 )
804  msg.Printf( wxT( "%3.1f(+%3.1f)" ),
805  GetOrientationDegrees() - module_orient_degrees,
806  module_orient_degrees );
807  else
808  msg.Printf( wxT( "%3.1f" ), GetOrientationDegrees() );
809 
810  aList.push_back( MSG_PANEL_ITEM( _( "Angle" ), msg, LIGHTBLUE ) );
811 
812  msg = MessageTextFromValue( aUnits, m_Pos.x )
813  + wxT( ", " )
814  + MessageTextFromValue( aUnits, m_Pos.y );
815  aList.push_back( MSG_PANEL_ITEM( _( "Position" ), msg, LIGHTBLUE ) );
816 
817  if( GetPadToDieLength() )
818  {
819  msg = MessageTextFromValue( aUnits, GetPadToDieLength(), true );
820  aList.push_back( MSG_PANEL_ITEM( _( "Length in package" ), msg, CYAN ) );
821  }
822 }
823 
824 
825 void D_PAD::GetOblongDrillGeometry( wxPoint& aStartPoint,
826  wxPoint& aEndPoint, int& aWidth ) const
827 {
828  // calculates the start point, end point and width
829  // of an equivalent segment which have the same position and width as the hole
830  int delta_cx, delta_cy;
831 
832  wxSize halfsize = GetDrillSize();
833  halfsize.x /= 2;
834  halfsize.y /= 2;
835 
836  if( m_Drill.x > m_Drill.y ) // horizontal
837  {
838  delta_cx = halfsize.x - halfsize.y;
839  delta_cy = 0;
840  aWidth = m_Drill.y;
841  }
842  else // vertical
843  {
844  delta_cx = 0;
845  delta_cy = halfsize.y - halfsize.x;
846  aWidth = m_Drill.x;
847  }
848 
849  RotatePoint( &delta_cx, &delta_cy, m_Orient );
850 
851  aStartPoint.x = delta_cx;
852  aStartPoint.y = delta_cy;
853 
854  aEndPoint.x = - delta_cx;
855  aEndPoint.y = - delta_cy;
856 }
857 
858 
859 bool D_PAD::HitTest( const wxPoint& aPosition ) const
860 {
861  int dx, dy;
862 
863  wxPoint shape_pos = ShapePos();
864 
865  wxPoint delta = aPosition - shape_pos;
866 
867  // first test: a test point must be inside a minimum sized bounding circle.
868  int radius = GetBoundingRadius();
869 
870  if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) )
871  return false;
872 
873  dx = m_Size.x >> 1; // dx also is the radius for rounded pads
874  dy = m_Size.y >> 1;
875 
876  switch( GetShape() )
877  {
878  case PAD_SHAPE_CIRCLE:
879  if( KiROUND( EuclideanNorm( delta ) ) <= dx )
880  return true;
881 
882  break;
883 
884  case PAD_SHAPE_TRAPEZOID:
885  {
886  wxPoint poly[4];
887  BuildPadPolygon( poly, wxSize(0,0), 0 );
888  RotatePoint( &delta, -m_Orient );
889 
890  return TestPointInsidePolygon( poly, 4, delta );
891  }
892 
893  case PAD_SHAPE_OVAL:
894  {
895  RotatePoint( &delta, -m_Orient );
896  // An oval pad has the same shape as a segment with rounded ends
897  // After rotation, the test point is relative to an horizontal pad
898  int dist;
899  wxPoint offset;
900  if( dy > dx ) // shape is a vertical oval
901  {
902  offset.y = dy - dx;
903  dist = dx;
904  }
905  else //if( dy <= dx ) shape is an horizontal oval
906  {
907  offset.x = dy - dx;
908  dist = dy;
909  }
910  return TestSegmentHit( delta, - offset, offset, dist );
911  }
912  break;
913 
914  case PAD_SHAPE_RECT:
915  RotatePoint( &delta, -m_Orient );
916 
917  if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) )
918  return true;
919 
920  break;
921 
922  case PAD_SHAPE_ROUNDRECT:
923  {
924  // Check for hit in polygon
925  SHAPE_POLY_SET outline;
926  const int segmentToCircleCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
927  TransformRoundRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient,
928  GetRoundRectCornerRadius(), segmentToCircleCount );
929 
930  const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 );
931  return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta );
932  }
933  break;
934 
935  case PAD_SHAPE_CUSTOM:
936  // Check for hit in polygon
937  RotatePoint( &delta, -m_Orient );
938 
940  {
942  return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta );
943  }
944  break;
945  }
946 
947  return false;
948 }
949 
950 
951 bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
952 {
953  EDA_RECT arect = aRect;
954  arect.Normalize();
955  arect.Inflate( aAccuracy );
956 
957  wxPoint shapePos = ShapePos();
958 
959  EDA_RECT shapeRect;
960 
961  int r;
962 
963  EDA_RECT bb = GetBoundingBox();
964 
965  wxPoint endCenter;
966  int radius;
967 
968  if( !arect.Intersects( bb ) )
969  return false;
970 
971  // This covers total containment for all test cases
972  if( arect.Contains( bb ) )
973  return true;
974 
975  switch( GetShape() )
976  {
977  case PAD_SHAPE_CIRCLE:
978  return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() );
979 
980  case PAD_SHAPE_RECT:
981  shapeRect.SetOrigin( shapePos );
982  shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 );
983  return arect.Intersects( shapeRect, m_Orient );
984 
985  case PAD_SHAPE_OVAL:
986  // Circlular test if dimensions are equal
987  if( m_Size.x == m_Size.y )
988  return arect.IntersectsCircle( shapePos, GetBoundingRadius() );
989 
990  shapeRect.SetOrigin( shapePos );
991 
992  // Horizontal dimension is greater
993  if( m_Size.x > m_Size.y )
994  {
995  radius = m_Size.y / 2;
996 
997  shapeRect.Inflate( m_Size.x / 2 - radius, radius );
998 
999  endCenter = wxPoint( m_Size.x / 2 - radius, 0 );
1000  RotatePoint( &endCenter, m_Orient );
1001 
1002  // Test circular ends
1003  if( arect.IntersectsCircle( shapePos + endCenter, radius ) ||
1004  arect.IntersectsCircle( shapePos - endCenter, radius ) )
1005  {
1006  return true;
1007  }
1008  }
1009  else
1010  {
1011  radius = m_Size.x / 2;
1012 
1013  shapeRect.Inflate( radius, m_Size.y / 2 - radius );
1014 
1015  endCenter = wxPoint( 0, m_Size.y / 2 - radius );
1016  RotatePoint( &endCenter, m_Orient );
1017 
1018  // Test circular ends
1019  if( arect.IntersectsCircle( shapePos + endCenter, radius ) ||
1020  arect.IntersectsCircle( shapePos - endCenter, radius ) )
1021  {
1022  return true;
1023  }
1024  }
1025 
1026  // Test rectangular portion between rounded ends
1027  if( arect.Intersects( shapeRect, m_Orient ) )
1028  {
1029  return true;
1030  }
1031 
1032  break;
1033 
1034  case PAD_SHAPE_TRAPEZOID:
1035  /* Trapezoid intersection tests:
1036  * A) Any points of rect inside trapezoid
1037  * B) Any points of trapezoid inside rect
1038  * C) Any sides of trapezoid cross rect
1039  */
1040  {
1041 
1042  wxPoint poly[4];
1043  BuildPadPolygon( poly, wxSize( 0, 0 ), 0 );
1044 
1045  wxPoint corners[4];
1046 
1047  corners[0] = wxPoint( arect.GetLeft(), arect.GetTop() );
1048  corners[1] = wxPoint( arect.GetRight(), arect.GetTop() );
1049  corners[2] = wxPoint( arect.GetRight(), arect.GetBottom() );
1050  corners[3] = wxPoint( arect.GetLeft(), arect.GetBottom() );
1051 
1052  for( int i=0; i<4; i++ )
1053  {
1054  RotatePoint( &poly[i], m_Orient );
1055  poly[i] += shapePos;
1056  }
1057 
1058  for( int ii=0; ii<4; ii++ )
1059  {
1060  if( TestPointInsidePolygon( poly, 4, corners[ii] ) )
1061  {
1062  return true;
1063  }
1064 
1065  if( arect.Contains( poly[ii] ) )
1066  {
1067  return true;
1068  }
1069 
1070  if( arect.Intersects( poly[ii], poly[(ii+1) % 4] ) )
1071  {
1072  return true;
1073  }
1074  }
1075 
1076  return false;
1077  }
1078 
1079  case PAD_SHAPE_ROUNDRECT:
1080  /* RoundRect intersection can be broken up into simple tests:
1081  * a) Test intersection of horizontal rect
1082  * b) Test intersection of vertical rect
1083  * c) Test intersection of each corner
1084  */
1085 
1086 
1088 
1089  /* Test A - intersection of horizontal rect */
1090  shapeRect.SetSize( 0, 0 );
1091  shapeRect.SetOrigin( shapePos );
1092  shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 - r );
1093 
1094  // Short-circuit test for zero width or height
1095  if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 &&
1096  arect.Intersects( shapeRect, m_Orient ) )
1097  {
1098  return true;
1099  }
1100 
1101  /* Test B - intersection of vertical rect */
1102  shapeRect.SetSize( 0, 0 );
1103  shapeRect.SetOrigin( shapePos );
1104  shapeRect.Inflate( m_Size.x / 2 - r, m_Size.y / 2 );
1105 
1106  // Short-circuit test for zero width or height
1107  if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 &&
1108  arect.Intersects( shapeRect, m_Orient ) )
1109  {
1110  return true;
1111  }
1112 
1113  /* Test C - intersection of each corner */
1114 
1115  endCenter = wxPoint( m_Size.x / 2 - r, m_Size.y / 2 - r );
1116  RotatePoint( &endCenter, m_Orient );
1117 
1118  if( arect.IntersectsCircle( shapePos + endCenter, r ) ||
1119  arect.IntersectsCircle( shapePos - endCenter, r ) )
1120  {
1121  return true;
1122  }
1123 
1124  endCenter = wxPoint( m_Size.x / 2 - r, -m_Size.y / 2 + r );
1125  RotatePoint( &endCenter, m_Orient );
1126 
1127  if( arect.IntersectsCircle( shapePos + endCenter, r ) ||
1128  arect.IntersectsCircle( shapePos - endCenter, r ) )
1129  {
1130  return true;
1131  }
1132 
1133  break;
1134 
1135  default:
1136  break;
1137  }
1138 
1139  return false;
1140 }
1141 
1142 int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
1143 {
1144  int diff;
1145 
1146  if( ( diff = padref->GetShape() - padcmp->GetShape() ) != 0 )
1147  return diff;
1148 
1149  if( ( diff = padref->GetDrillShape() - padcmp->GetDrillShape() ) != 0)
1150  return diff;
1151 
1152  if( ( diff = padref->m_Drill.x - padcmp->m_Drill.x ) != 0 )
1153  return diff;
1154 
1155  if( ( diff = padref->m_Drill.y - padcmp->m_Drill.y ) != 0 )
1156  return diff;
1157 
1158  if( ( diff = padref->m_Size.x - padcmp->m_Size.x ) != 0 )
1159  return diff;
1160 
1161  if( ( diff = padref->m_Size.y - padcmp->m_Size.y ) != 0 )
1162  return diff;
1163 
1164  if( ( diff = padref->m_Offset.x - padcmp->m_Offset.x ) != 0 )
1165  return diff;
1166 
1167  if( ( diff = padref->m_Offset.y - padcmp->m_Offset.y ) != 0 )
1168  return diff;
1169 
1170  if( ( diff = padref->m_DeltaSize.x - padcmp->m_DeltaSize.x ) != 0 )
1171  return diff;
1172 
1173  if( ( diff = padref->m_DeltaSize.y - padcmp->m_DeltaSize.y ) != 0 )
1174  return diff;
1175 
1176 // TODO: test custom shapes
1177 
1178  // Dick: specctra_export needs this
1179  // Lorenzo: gencad also needs it to implement padstacks!
1180 
1181 #if __cplusplus >= 201103L
1182  long long d = padref->m_layerMask.to_ullong() - padcmp->m_layerMask.to_ullong();
1183  if( d < 0 )
1184  return -1;
1185  else if( d > 0 )
1186  return 1;
1187 
1188  return 0;
1189 #else
1190  // these strings are not typically constructed, since we don't get here often.
1191  std::string s1 = padref->m_layerMask.to_string();
1192  std::string s2 = padcmp->m_layerMask.to_string();
1193  return s1.compare( s2 );
1194 #endif
1195 }
1196 
1197 
1198 void D_PAD::Rotate( const wxPoint& aRotCentre, double aAngle )
1199 {
1200  RotatePoint( &m_Pos, aRotCentre, aAngle );
1201 
1202  m_Orient = NormalizeAngle360Min( m_Orient + aAngle );
1203 
1204  SetLocalCoord();
1205 }
1206 
1207 
1208 wxString D_PAD::ShowPadShape() const
1209 {
1210  switch( GetShape() )
1211  {
1212  case PAD_SHAPE_CIRCLE:
1213  return _( "Circle" );
1214 
1215  case PAD_SHAPE_OVAL:
1216  return _( "Oval" );
1217 
1218  case PAD_SHAPE_RECT:
1219  return _( "Rect" );
1220 
1221  case PAD_SHAPE_TRAPEZOID:
1222  return _( "Trap" );
1223 
1224  case PAD_SHAPE_ROUNDRECT:
1225  return _( "Roundrect" );
1226 
1227  case PAD_SHAPE_CUSTOM:
1228  return _( "CustomShape" );
1229 
1230  default:
1231  return wxT( "???" );
1232  }
1233 }
1234 
1235 
1236 wxString D_PAD::ShowPadAttr() const
1237 {
1238  switch( GetAttribute() )
1239  {
1240  case PAD_ATTRIB_STANDARD:
1241  return _( "Std" );
1242 
1243  case PAD_ATTRIB_SMD:
1244  return _( "SMD" );
1245 
1246  case PAD_ATTRIB_CONN:
1247  return _( "Conn" );
1248 
1250  return _( "Not Plated" );
1251 
1252  default:
1253  return wxT( "???" );
1254  }
1255 }
1256 
1257 
1258 wxString D_PAD::GetSelectMenuText( EDA_UNITS_T aUnits ) const
1259 {
1260  if( GetName().IsEmpty() )
1261  {
1262  return wxString::Format( _( "Pad of %s on %s" ),
1263  GetParent()->GetReference(),
1265  }
1266  else
1267  {
1268  return wxString::Format( _( "Pad %s of %s on %s" ),
1269  GetName(),
1270  GetParent()->GetReference(),
1272  }
1273 }
1274 
1275 
1277 {
1278  return pad_xpm;
1279 }
1280 
1281 
1283 {
1284  return new D_PAD( *this );
1285 }
1286 
1287 
1289 {
1290  return( m_Attribute == PAD_ATTRIB_STANDARD
1291  && m_Drill.x >= m_Size.x && m_Drill.y >= m_Size.y );
1292 }
1293 
1294 
1295 void D_PAD::ViewGetLayers( int aLayers[], int& aCount ) const
1296 {
1297  aCount = 0;
1298 
1299  // These 2 types of pads contain a hole
1301  aLayers[aCount++] = LAYER_PADS_PLATEDHOLES;
1302 
1304  aLayers[aCount++] = LAYER_NON_PLATEDHOLES;
1305 
1306  if( IsOnLayer( F_Cu ) && IsOnLayer( B_Cu ) )
1307  {
1308  // Multi layer pad
1309  aLayers[aCount++] = LAYER_PADS_TH;
1310  aLayers[aCount++] = LAYER_PADS_NETNAMES;
1311  }
1312  else if( IsOnLayer( F_Cu ) )
1313  {
1314  aLayers[aCount++] = LAYER_PAD_FR;
1315  aLayers[aCount++] = LAYER_PAD_FR_NETNAMES;
1316  }
1317  else if( IsOnLayer( B_Cu ) )
1318  {
1319  aLayers[aCount++] = LAYER_PAD_BK;
1320  aLayers[aCount++] = LAYER_PAD_BK_NETNAMES;
1321  }
1322 
1323  // Check non-copper layers. This list should include all the layers that the
1324  // footprint editor allows a pad to be placed on.
1325  static const PCB_LAYER_ID layers_mech[] = { F_Mask, B_Mask, F_Paste, B_Paste,
1327 
1328  for( PCB_LAYER_ID each_layer : layers_mech )
1329  {
1330  if( IsOnLayer( each_layer ) )
1331  aLayers[aCount++] = each_layer;
1332  }
1333 
1334 #ifdef __WXDEBUG__
1335  if( aCount == 0 ) // Should not occur
1336  {
1337  wxString msg;
1338  msg.Printf( wxT( "footprint %s, pad %s: could not find valid layer for pad" ),
1339  GetParent() ? GetParent()->GetReference() : "<null>",
1340  GetName().IsEmpty() ? "(unnamed)" : GetName() );
1341  wxLogWarning( msg );
1342  }
1343 #endif
1344 }
1345 
1346 
1347 unsigned int D_PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1348 {
1349  if( aView->GetPrintMode() > 0 ) // In printing mode the pad is always drawable
1350  return 0;
1351 
1352  const int HIDE = std::numeric_limits<unsigned int>::max();
1353  BOARD* board = GetBoard();
1354 
1355  // Handle Render tab switches
1357  && !aView->IsLayerVisible( LAYER_PADS_TH ) )
1358  return HIDE;
1359 
1360  if( !IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1361  return HIDE;
1362 
1363  if( IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1364  return HIDE;
1365 
1366  if( IsFrontLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_FR ) )
1367  return HIDE;
1368 
1369  if( IsBackLayer( ( PCB_LAYER_ID )aLayer ) && !aView->IsLayerVisible( LAYER_PAD_BK ) )
1370  return HIDE;
1371 
1372  // Only draw the pad if at least one of the layers it crosses is being displayed
1373  if( board && !( board->GetVisibleLayers() & GetLayerSet() ).any() )
1374  return HIDE;
1375 
1376  // Netnames will be shown only if zoom is appropriate
1377  if( IsNetnameLayer( aLayer ) )
1378  {
1379  int divisor = std::max( m_Size.x, m_Size.y );
1380 
1381  // Pad sizes can be zero briefly when someone is typing a number like "0.5"
1382  // in the pad properties dialog
1383  if( divisor == 0 )
1384  return HIDE;
1385 
1386  return ( Millimeter2iu( 10 ) / divisor );
1387  }
1388 
1389  // Other layers are shown without any conditions
1390  return 0;
1391 }
1392 
1393 
1394 const BOX2I D_PAD::ViewBBox() const
1395 {
1396  // Bounding box includes soldermask too
1397  int solderMaskMargin = GetSolderMaskMargin();
1398  VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() );
1399  EDA_RECT bbox = GetBoundingBox();
1400 
1401  // Look for the biggest possible bounding box
1402  int xMargin = std::max( solderMaskMargin, solderPasteMargin.x );
1403  int yMargin = std::max( solderMaskMargin, solderPasteMargin.y );
1404 
1405  return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ),
1406  VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) );
1407 }
1408 
1409 
1410 wxString LayerMaskDescribe( const BOARD *aBoard, LSET aMask )
1411 {
1412  // Try to be smart and useful. Check all copper first.
1413  if( aMask[F_Cu] && aMask[B_Cu] )
1414  return _( "All copper layers" );
1415 
1416  // Check for copper.
1417  auto layer = aBoard->GetEnabledLayers().AllCuMask() & aMask;
1418 
1419  for( int i = 0; i < 2; i++ )
1420  {
1422  {
1423  if( layer[ bit ] )
1424  {
1425  wxString layerInfo = aBoard->GetLayerName( static_cast<PCB_LAYER_ID>( bit ) );
1426 
1427  if( aMask.count() > 1 )
1428  layerInfo << _( " and others" );
1429 
1430  return layerInfo;
1431  }
1432  }
1433 
1434  // No copper; check for technicals.
1435  layer = aBoard->GetEnabledLayers().AllTechMask() & aMask;
1436  }
1437 
1438  // No copper, no technicals: no layer
1439  return _( "no layers" );
1440 }
1441 
1442 
1443 void D_PAD::ImportSettingsFromMaster( const D_PAD& aMasterPad )
1444 {
1445  SetShape( aMasterPad.GetShape() );
1446  SetLayerSet( aMasterPad.GetLayerSet() );
1447  SetAttribute( aMasterPad.GetAttribute() );
1448 
1449  // The pad orientation, for historical reasons is the
1450  // pad rotation + parent rotation.
1451  // So we have to manage this parent rotation
1452  double pad_rot = aMasterPad.GetOrientation();
1453 
1454  if( aMasterPad.GetParent() )
1455  pad_rot -= aMasterPad.GetParent()->GetOrientation();
1456 
1457  if( GetParent() )
1458  pad_rot += GetParent()->GetOrientation();
1459 
1460  SetOrientation( pad_rot );
1461 
1462  SetSize( aMasterPad.GetSize() );
1463  SetDelta( wxSize( 0, 0 ) );
1464  SetOffset( aMasterPad.GetOffset() );
1465  SetDrillSize( aMasterPad.GetDrillSize() );
1466  SetDrillShape( aMasterPad.GetDrillShape() );
1468 
1469  switch( aMasterPad.GetShape() )
1470  {
1471  case PAD_SHAPE_TRAPEZOID:
1472  SetDelta( aMasterPad.GetDelta() );
1473  break;
1474 
1475  case PAD_SHAPE_CIRCLE:
1476  // ensure size.y == size.x
1477  SetSize( wxSize( GetSize().x, GetSize().x ) );
1478  break;
1479 
1480  default:
1481  ;
1482  }
1483 
1484  switch( aMasterPad.GetAttribute() )
1485  {
1486  case PAD_ATTRIB_SMD:
1487  case PAD_ATTRIB_CONN:
1488  // These pads do not have hole (they are expected to be only on one
1489  // external copper layer)
1490  SetDrillSize( wxSize( 0, 0 ) );
1491  break;
1492 
1493  default:
1494  ;
1495  }
1496 
1497  // copy also local settings:
1498  SetLocalClearance( aMasterPad.GetLocalClearance() );
1502 
1503  SetZoneConnection( aMasterPad.GetZoneConnection() );
1504  SetThermalWidth( aMasterPad.GetThermalWidth() );
1505  SetThermalGap( aMasterPad.GetThermalGap() );
1506 
1507  // Add or remove custom pad shapes:
1508  SetPrimitives( aMasterPad.GetPrimitives() );
1509  SetAnchorPadShape( aMasterPad.GetAnchorPadShape() );
1511 }
1512 
1514 {
1515  assert( aImage->Type() == PCB_PAD_T );
1516 
1517  std::swap( *((MODULE*) this), *((MODULE*) aImage) );
1518 }
int m_LocalClearance
Local clearance.
Definition: class_pad.h:876
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
int m_ThermalGap
Definition: class_pad.h:889
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
int m_LocalSolderMaskMargin
Local mask margins: when 0, the parent footprint design values are used.
Definition: class_pad.h:880
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
Definition: class_pad.cpp:1276
bool IncrementPadName(bool aSkipUnconnectable, bool aFillSequenceGaps)
Function IncrementPadName.
Definition: class_pad.cpp:565
static int m_PadSketchModePenSize
Pen size used to draw pads in sketch mode (mode used to print pads on silkscreen layer) ...
Definition: class_pad.h:136
int m_SolderMaskMargin
Solder mask margin.
double m_padRoundRectRadiusScale
scaling factor from smallest m_Size coord to corner radius, default 0.25
Definition: class_pad.h:836
A list of parameters type.
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:421
double GetOrientation() const
Definition: class_module.h:188
int m_boundingRadius
radius of the circle containing the pad shape
Definition: class_pad.h:795
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: class_pad.cpp:1282
BOX2< VECTOR2I > BOX2I
Definition: box2.h:520
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:171
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint BACK and FRONT copper layers, mask, paste, solder layers are swapped internal layers are flipped only if the copper layers count is known.
Definition: lset.cpp:521
std::vector< PAD_CS_PRIMITIVE > m_basicShapes
for free shape pads: a list of basic shapes, in local coordinates, orient 0, coordinates relative to ...
Definition: class_pad.h:810
int GetNetCode() const
Function GetNetCode.
int OutlineCount() const
Returns the number of outlines in the set
static LSET StandardMask()
layer set for a through hole pad
Definition: class_pad.cpp:98
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
void FlipPrimitives()
Flip the basic shapes, in custom pads.
Definition: class_pad.cpp:450
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
PNG memory record (file in memory).
Definition: bitmap_types.h:43
static const int dist[10][10]
Definition: ar_matrix.cpp:320
bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
Definition: class_pad.cpp:859
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:65
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
Definition: class_pad.cpp:1198
PAD_ATTR_T
Enum PAD_ATTR_T is the set of pad shapes, used with D_PAD::{Set,Get}Attribute() The double name is fo...
Definition: pad_shapes.h:58
int m_LocalSolderPasteMargin
Local solder paste margin absolute value.
Definition: class_pad.h:881
multilayer pads, usually with holes
bool MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon=NULL, int aCircleToSegmentsCount=ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF)
Merge all basic shapes, converted to a polygon in one polygon, in m_customShapeAsPolygon.
Implementation of conversion functions that require both schematic and board internal units...
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: class_pad.cpp:119
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
PAD_SHAPE_T GetAnchorPadShape() const
Function GetAnchorPadShape.
Definition: class_pad.h:226
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: class_pad.cpp:105
int GetTop() const
Definition: eda_rect.h:121
handle color for not plated holes (holes, not pads)
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it&#39;s a back layer.
Class BOARD to handle a board.
D_PAD(MODULE *parent)
Definition: class_pad.cpp:58
void TransformRoundRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, int aCircleToSegmentsCount)
Function TransformRoundRectToPolygon convert a rectangle with rounded corners to a polygon Convert ar...
void GetOblongDrillGeometry(wxPoint &aStartPoint, wxPoint &aEndPoint, int &aWidth) const
Function GetOblongDrillGeometry calculates the start point, end point and width of an equivalent segm...
Definition: class_pad.cpp:825
int GetLeft() const
Definition: eda_rect.h:120
double GetOrientationDegrees() const
Definition: class_pad.h:390
wxPoint m_Start
angle of an arc, from its starting point, in 0.1 deg
Definition: class_pad.h:100
ZoneConnection
How pads are covered by copper in zone.
Definition: zones.h:50
polygon (not yet used for tracks, but could be in microwave apps)
bool IsFlipped() const
Definition: class_pad.cpp:133
wxSize m_Size
X and Y size ( relative to orient 0)
Definition: class_pad.h:832
int GetPadToDieLength() const
Definition: class_pad.h:419
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:61
bool TestPointInsidePolygon(const wxPoint *aPolysList, int aCount, const wxPoint &aRefPoint)
Function TestPointInsidePolygon (overlaid) same as previous, but mainly use wxPoint.
int GetWidth() const
Definition: eda_rect.h:117
show modules on back
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
bool IntersectsCircle(const wxPoint &aCenter, const int aRadius) const
Function IntersectsCircle tests for a common area between a circle and this rectangle.
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:124
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
void SetSubRatsnest(int aSubRatsnest)
Definition: class_pad.h:666
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:274
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:241
void SetRoundRectRadiusRatio(double aRadiusScale)
has meaning only for rounded rect pads Set the scaling factor between the smaller Y or Y size and the...
Definition: class_pad.h:653
wxString ShowPadAttr() const
Function ShowPadAttr.
Definition: class_pad.cpp:1236
static LSET AllTechMask()
Function AllTechMask returns a mask holding all technical layers (no CU layer) on both side...
Definition: lset.cpp:746
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
int GetThermalGap() const
Definition: class_pad.cpp:747
int GetLocalSolderMaskMargin() const
Definition: class_module.h:204
int PointCount() const
Function PointCount()
#define abs(a)
Definition: auxiliary.h:84
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
Configuration parameter - Integer Class with unit conversion.
smd pads, back layer
int GetLocalClearance() const
Definition: class_pad.h:424
bool Contains(const wxPoint &aPoint) const
Function Contains.
static const int delta[8][2]
Definition: solve.cpp:112
void SetLocalCoord()
Set relative coordinates.
Definition: class_pad.cpp:393
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:412
This file contains miscellaneous commonly used macros and functions.
int GetBottom() const
Definition: eda_rect.h:122
show modules on front
wxString MessageTextFromValue(EDA_UNITS_T aUnits, int aValue, bool aUseMils)
Definition: base_units.cpp:125
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:114
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
class MODULE, a footprint
Definition: typeinfo.h:89
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:253
int GetSolderMaskMargin() const
Function GetSolderMaskMargin.
Definition: class_pad.cpp:627
PCB_LAYER_ID
A quick note on layer IDs:
wxString m_name
Definition: class_pad.h:797
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers. ...
Definition: class_pad.cpp:1394
Class LSET is a set of PCB_LAYER_IDs.
const std::vector< PAD_CS_PRIMITIVE > & GetPrimitives() const
Accessor to the basic shape list.
Definition: class_pad.h:336
std::vector< wxPoint > m_Poly
is also the start point of the arc
Definition: class_pad.h:102
int GetLocalClearance() const
Definition: class_module.h:207
VECTOR2< double > VECTOR2D
Definition: vector2d.h:586
void SetZoneConnection(ZoneConnection aType)
Definition: class_pad.h:496
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12)...
Definition: class_pad.h:182
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
wxString ShowPadShape() const
Function ShowPadShape.
Definition: class_pad.cpp:1208
void SetEnd(int x, int y)
Definition: eda_rect.h:134
static int Compare(const D_PAD *padref, const D_PAD *padcmp)
Function Compare compares two pads and return 0 if they are equal.
Definition: class_pad.cpp:1142
const EDA_RECT GetBoundingBoxRotated(wxPoint aRotCenter, double aAngle)
Function GetBoundingBoxRotated.
const wxPoint & GetOffset() const
Definition: class_pad.h:278
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:395
int GetThermalWidth() const
Definition: class_pad.cpp:736
Helper class to handle a primitive (basic shape: polygon, segment, circle or arc) to build a custom p...
Definition: class_pad.h:91
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:409
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
int GetRight() const
Definition: eda_rect.h:119
Definition: colors.h:59
CUST_PAD_SHAPE_IN_ZONE m_customShapeClearanceArea
How to build the custom shape in zone, to create the clearance area: CUST_PAD_SHAPE_IN_ZONE_OUTLINE =...
Definition: class_pad.h:823
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
void SetThermalWidth(int aWidth)
Definition: class_pad.h:499
const wxString & GetName() const
Definition: class_pad.h:190
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:619
double GetOrientationDegrees() const
Definition: class_module.h:189
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
int m_ThermalWidth
Definition: class_pad.h:888
void SetRoundRectCornerRadius(double aRadius)
Set the rounded rectangle radius ratio based on a given radius.
Definition: class_pad.cpp:206
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on...
Definition: class_pad.cpp:1295
Definition: colors.h:60
SHAPE_POLY_SET m_customShapeAsPolygon
for free shape pads: the set of basic shapes, merged as one polygon, in local coordinates, orient 0, coordinates relative to m_Pos
Definition: class_pad.h:815
void ImportSettingsFromMaster(const D_PAD &aMasterPad)
Imports the pad settings from aMasterPad.
Definition: class_pad.cpp:1443
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
Definition: class_pad.cpp:1347
const wxSize & GetDelta() const
Definition: class_pad.h:272
const wxString & GetNetname() const
Function GetNetname.
void SetDrawCoord()
Set absolute coordinates.
Definition: class_pad.cpp:377
wxSize m_DeltaSize
delta on rectangular shapes
Definition: class_pad.h:862
wxPoint m_End
is also the center of the circle and arc
Definition: class_pad.h:101
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:62
STROKE_T m_Shape
Definition: class_pad.h:94
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:408
int GetHeight() const
Definition: eda_rect.h:118
int GetLocalSolderPasteMargin() const
Definition: class_module.h:210
void SetLocalClearance(int aClearance)
Definition: class_pad.h:425
MODULE * GetParent() const
Definition: class_pad.h:162
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_pad.h:431
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it&#39;s a front layer.
void Normalize()
Function Normalize ensures that the height ant width are positive.
LSET m_layerMask
Bitwise layer :1= copper layer, 15= cmp, 2..14 = internal layers 16 .
Definition: class_pad.h:858
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: class_pad.cpp:1513
int GetPrintMode()
Definition: view.h:703
void SetSize(const wxSize &size)
Definition: eda_rect.h:126
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:408
double GetLocalSolderPasteMarginRatio() const
Definition: class_module.h:213
void SetY(int y)
Definition: class_pad.h:259
smd pads, front layer
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void SetDrillShape(PAD_DRILL_SHAPE_T aDrillShape)
Definition: class_pad.h:393
wxSize GetSolderPasteMargin() const
Function GetSolderPasteMargin.
Definition: class_pad.cpp:673
wxPoint m_Pos0
Initial Pad position (i.e.
Definition: class_pad.h:864
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:422
void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
Definition: class_pad.cpp:424
Class SHAPE_LINE_CHAIN.
int m_LengthPadToDie
Length net from pad to die, inside the package.
Definition: class_pad.h:871
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const
Function GetClearance returns the clearance in internal units.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:389
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
size_t i
Definition: json11.cpp:597
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
wxPoint ShapePos() const
Definition: class_pad.cpp:550
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Usual pad.
Definition: pad_shapes.h:60
static long bit[8][9]
Definition: solve.cpp:826
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:217
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:538
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:417
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:641
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: class_pad.cpp:1258
PAD_ATTR_T m_Attribute
PAD_ATTRIB_NORMAL, PAD_ATTRIB_SMD, PAD_ATTRIB_CONN, PAD_ATTRIB_HOLE_NOT_PLATED.
Definition: class_pad.h:867
VECTOR2I & Point(int aIndex)
Function Point()
int boundingRadius() const
Function boundingRadius returns a calculated radius of a bounding circle for this pad...
Definition: class_pad.cpp:140
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_pad.h:428
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: class_pad.cpp:112
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:292
wxSize m_Drill
Drill diam (drill shape = PAD_CIRCLE) or drill size (shape = OVAL) for drill shape = PAD_CIRCLE...
Definition: class_pad.h:828
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
Module description (excepted pads)
double m_Orient
in 1/10 degrees
Definition: class_pad.h:869
static LSET ApertureMask()
layer set for an aperture pad
Definition: class_pad.cpp:126
double m_LocalSolderPasteMarginRatio
Local solder mask margin ratio value of pad size The final margin is the sum of these 2 values...
Definition: class_pad.h:883
wxPoint m_Offset
m_Offset is useful only for oblong and rect pads (it can be used for other shapes, but without any interest).
Definition: class_pad.h:856
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:61
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Function TestSegmentHit test for hit on line segment i.e.
Definition: trigo.cpp:122
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:725
const wxSize & GetSize() const
Definition: class_pad.h:269
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:670
const wxPoint GetPosition() const override
Definition: class_pad.h:220
int GetThermalWidth() const
Definition: class_module.h:220
T NormalizeAngle360Min(T Angle)
Normalize angle to be > -360.0 and < 360.0 Angle equal to -360 or +360 are set to 0...
Definition: trigo.h:222
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:427
Message panel definition file.
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:277
bool PadShouldBeNPTH() const
A pad whose hole is the same size as the pad is a NPTH.
Definition: class_pad.cpp:1288
#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF
Definition: pcbnew.h:42
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
void SetThermalGap(int aGap)
Definition: class_pad.h:502
static wxString GetNextPadName(wxString aPadName)
const wxPoint GetPosition() const override
Definition: class_module.h:183
int GetThermalGap() const
Definition: class_module.h:223
void MirrorXPrimitives(int aX)
Mirror the primitives about a coordinate.
Definition: class_pad.cpp:484
bool SetPrimitives(const std::vector< PAD_CS_PRIMITIVE > &aPrimitivesList)
Import to the basic shape list.
void CopyNetlistSettings(D_PAD *aPad, bool aCopyLocalSettings)
Function CopyNetlistSettings copies the netlist settings to aPad, and the net name.
Definition: class_pad.cpp:576
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Definition: class_pad.cpp:215
EDA_UNITS_T
Definition: common.h:160
static wxString LayerMaskDescribe(const BOARD *aBoard, LSET aMask)
Helper function Return a string (to be shown to the user) describing a layer mask.
Definition: class_pad.cpp:1410
double m_ArcAngle
radius of a circle
Definition: class_pad.h:99
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:430
Additional netnames layers (not associated with a PCB layer)
ZoneConnection GetZoneConnection() const
Definition: class_module.h:217
ZoneConnection m_ZoneConnection
how the connection to zone is made: no connection, thermal relief ...
Definition: class_pad.h:886
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:271
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it&#39;s internal state for displ...
Definition: class_pad.cpp:758
const wxSize GetSize() const
Definition: eda_rect.h:101
bool IsNetnameLayer(LAYER_NUM aLayer)
Function IsNetnameLayer tests whether a layer is a netname layer.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
#define min(a, b)
Definition: auxiliary.h:85
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:427
wxPoint m_Pos
pad Position on board
Definition: class_pad.h:800
void AppendConfigs(PARAM_CFG_ARRAY *aResult)
Function AppendConfigs appends to aResult the configuration setting accessors which will later allow ...
Definition: class_pad.cpp:518
Definition: colors.h:62