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