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