KiCad PCB EDA Suite
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 <[email protected]>
6  * Copyright (C) 1992-2021 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 
26 #include <base_units.h>
27 #include <bitmaps.h>
28 #include <core/mirror.h>
29 #include <math/util.h> // for KiROUND
30 #include <eda_draw_frame.h>
31 #include <geometry/shape_circle.h>
33 #include <geometry/shape_null.h>
34 #include <geometry/shape_rect.h>
35 #include <geometry/shape_segment.h>
36 #include <geometry/shape_simple.h>
37 #include <string_utils.h>
38 #include <i18n_utility.h>
39 #include <view/view.h>
40 #include <board.h>
41 #include <board_connected_item.h>
42 #include <board_design_settings.h>
43 #include <footprint.h>
44 #include <pad.h>
45 #include <pcb_shape.h>
47 #include <convert_to_biu.h>
49 #include <widgets/msgpanel.h>
50 #include <pcb_painter.h>
51 #include <wx/log.h>
52 
53 #include <memory>
54 #include <macros.h>
55 
56 using KIGFX::PCB_PAINTER;
58 
59 
60 PAD::PAD( FOOTPRINT* parent ) :
62 {
63  m_size.x = m_size.y = Mils2iu( 60 ); // Default pad size 60 mils.
64  m_drill.x = m_drill.y = Mils2iu( 30 ); // Default drill size 30 mils.
65  m_orient = 0; // Pad rotation in 1/10 degrees.
66  m_lengthPadToDie = 0;
67 
68  if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
70 
71  SetShape( PAD_SHAPE::CIRCLE ); // Default pad shape is PAD_CIRCLE.
72  SetAnchorPadShape( PAD_SHAPE::CIRCLE ); // Default shape for custom shaped pads
73  // is PAD_CIRCLE.
74  SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle.
75  m_attribute = PAD_ATTRIB::PTH; // Default pad type is plated through hole
76  SetProperty( PAD_PROP::NONE ); // no special fabrication property
77  m_localClearance = 0;
81 
82  // Parameters for round rect only:
83  m_roundedCornerScale = 0.25; // from IPC-7351C standard
84 
85  // Parameters for chamfered rect only:
86  m_chamferScale = 0.2; // Size of chamfer: ratio of smallest of X,Y size
87  m_chamferPositions = RECT_NO_CHAMFER; // No chamfered corner
88 
89  m_zoneConnection = ZONE_CONNECTION::INHERITED; // Use parent setting by default
90  m_thermalWidth = 0; // Use parent setting by default
91  m_thermalGap = 0; // Use parent setting by default
92 
94 
95  // Set layers mask to default for a standard thru hole pad.
96  m_layerMask = PTHMask();
97 
98  SetSubRatsnest( 0 ); // used in ratsnest calculations
99 
100  SetDirty();
102  m_removeUnconnectedLayer = false;
103  m_keepTopBottomLayer = true;
104 }
105 
106 
107 PAD::PAD( const PAD& aOther ) :
108  BOARD_CONNECTED_ITEM( aOther.GetParent(), PCB_PAD_T )
109 {
110  PAD::operator=( aOther );
111 
112  const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
113 }
114 
115 
116 PAD& PAD::operator=( const PAD &aOther )
117 {
119 
120  ImportSettingsFrom( aOther );
122  SetPosition( aOther.GetPosition() );
123  SetPos0( aOther.GetPos0() );
124  SetNumber( aOther.GetNumber() );
125  SetPinType( aOther.GetPinType() );
126  SetPinFunction( aOther.GetPinFunction() );
127  SetSubRatsnest( aOther.GetSubRatsnest() );
131 
132  return *this;
133 }
134 
135 
136 bool PAD::CanHaveNumber() const
137 {
138  // Aperture pads don't get a number
139  if( IsAperturePad() )
140  return false;
141 
142  // NPTH pads don't get numbers
143  if( GetAttribute() == PAD_ATTRIB::NPTH )
144  return false;
145 
146  return true;
147 }
148 
149 
150 bool PAD::IsLocked() const
151 {
152  if( GetParent() && GetParent()->IsLocked() )
153  return true;
154 
155  return BOARD_ITEM::IsLocked();
156 };
157 
158 
160 {
161  static LSET saved = LSET::AllCuMask() | LSET( 2, F_Mask, B_Mask );
162  return saved;
163 }
164 
165 
167 {
168  static LSET saved( 3, F_Cu, F_Paste, F_Mask );
169  return saved;
170 }
171 
172 
174 {
175  static LSET saved( 2, F_Cu, F_Mask );
176  return saved;
177 }
178 
179 
181 {
182  static LSET saved = LSET( 4, F_Cu, B_Cu, F_Mask, B_Mask );
183  return saved;
184 }
185 
186 
188 {
189  static LSET saved( 1, F_Paste );
190  return saved;
191 }
192 
193 
194 bool PAD::IsFlipped() const
195 {
196  if( GetParent() && GetParent()->GetLayer() == B_Cu )
197  return true;
198  return false;
199 }
200 
201 
202 bool PAD::FlashLayer( LSET aLayers ) const
203 {
204  for( PCB_LAYER_ID layer : aLayers.Seq() )
205  {
206  if( FlashLayer( layer ) )
207  return true;
208  }
209 
210  return false;
211 }
212 
213 
214 bool PAD::FlashLayer( int aLayer ) const
215 {
216  std::vector<KICAD_T> types
218 
219  if( aLayer != UNDEFINED_LAYER && !IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) ) )
220  return false;
221 
222  if( aLayer == UNDEFINED_LAYER )
223  return true;
224 
225  if( GetAttribute() == PAD_ATTRIB::NPTH && IsCopperLayer( aLayer ) )
226  {
228  {
229  if( GetOffset() == wxPoint( 0, 0 ) && GetDrillSize().x >= GetSize().x )
230  return false;
231  }
233  {
234  if( GetOffset() == wxPoint( 0, 0 )
235  && GetDrillSize().x >= GetSize().x && GetDrillSize().y >= GetSize().y )
236  {
237  return false;
238  }
239  }
240  }
241 
242  if( LSET::FrontBoardTechMask().test( aLayer ) )
243  aLayer = F_Cu;
244  else if( LSET::BackBoardTechMask().test( aLayer ) )
245  aLayer = B_Cu;
246 
247  if( GetAttribute() == PAD_ATTRIB::PTH && IsCopperLayer( aLayer ) )
248  {
251  return true;
252 
254  return true;
255 
256  // Plated through hole pads need copper on the top/bottom layers for proper soldering
257  // Unless the user has removed them in the pad dialog
258  if( m_keepTopBottomLayer && ( aLayer == F_Cu || aLayer == B_Cu ) )
259  return true;
260 
261  if( const BOARD* board = GetBoard() )
262  return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types, true );
263  }
264 
265  return true;
266 }
267 
268 
270 {
271  return KiROUND( std::min( m_size.x, m_size.y ) * m_roundedCornerScale );
272 }
273 
274 
275 void PAD::SetRoundRectCornerRadius( double aRadius )
276 {
277  int min_r = std::min( m_size.x, m_size.y );
278 
279  if( min_r > 0 )
280  SetRoundRectRadiusRatio( aRadius / min_r );
281 }
282 
283 
284 void PAD::SetRoundRectRadiusRatio( double aRadiusScale )
285 {
286  m_roundedCornerScale = std::max( 0.0, std::min( aRadiusScale, 0.5 ) );
287 
288  SetDirty();
289 }
290 
291 
292 void PAD::SetChamferRectRatio( double aChamferScale )
293 {
294  m_chamferScale = std::max( 0.0, std::min( aChamferScale, 0.5 ) );
295 
296  SetDirty();
297 }
298 
299 
300 const std::shared_ptr<SHAPE_POLY_SET>& PAD::GetEffectivePolygon() const
301 {
302  if( m_polyDirty )
304 
305  return m_effectivePolygon;
306 }
307 
308 
309 std::shared_ptr<SHAPE> PAD::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
310 {
311  if( ( GetAttribute() == PAD_ATTRIB::PTH && aFlash == FLASHING::NEVER_FLASHED )
312  || ( aLayer != UNDEFINED_LAYER && !FlashLayer( aLayer ) ) )
313  {
314  if( GetAttribute() == PAD_ATTRIB::PTH )
315  {
317 
318  // Note: drill size represents finish size, which means the actual holes size is the
319  // plating thickness larger.
320  auto hole = static_cast<SHAPE_SEGMENT*>( GetEffectiveHoleShape()->Clone() );
321  hole->SetWidth( hole->GetWidth() + bds.GetHolePlatingThickness() );
322  return std::make_shared<SHAPE_SEGMENT>( *hole );
323  }
324 
325  return std::make_shared<SHAPE_NULL>();
326  }
327 
328 
329  if( m_shapesDirty )
330  BuildEffectiveShapes( aLayer );
331 
332  return m_effectiveShape;
333 }
334 
335 
337 {
338  if( m_shapesDirty )
340 
341  return m_effectiveHoleShape.get();
342 }
343 
344 
346 {
347  if( m_polyDirty )
349 
351 }
352 
353 
355 {
356  std::lock_guard<std::mutex> RAII_lock( m_shapesBuildingLock );
357 
358  // If we had to wait for the lock then we were probably waiting for someone else to
359  // finish rebuilding the shapes. So check to see if they're clean now.
360  if( !m_shapesDirty )
361  return;
362 
363  const BOARD* board = GetBoard();
364  int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
365 
366  m_effectiveShape = std::make_shared<SHAPE_COMPOUND>();
367  m_effectiveHoleShape = nullptr;
368 
369  auto add = [this]( SHAPE* aShape )
370  {
371  m_effectiveShape->AddShape( aShape );
372  };
373 
374  wxPoint shapePos = ShapePos(); // Fetch only once; rotation involves trig
375  PAD_SHAPE effectiveShape = GetShape();
376 
377  if( GetShape() == PAD_SHAPE::CUSTOM )
378  effectiveShape = GetAnchorPadShape();
379 
380  switch( effectiveShape )
381  {
382  case PAD_SHAPE::CIRCLE:
383  add( new SHAPE_CIRCLE( shapePos, m_size.x / 2 ) );
384  break;
385 
386  case PAD_SHAPE::OVAL:
387  if( m_size.x == m_size.y ) // the oval pad is in fact a circle
388  {
389  add( new SHAPE_CIRCLE( shapePos, m_size.x / 2 ) );
390  }
391  else
392  {
393  wxSize half_size = m_size / 2;
394  int half_width = std::min( half_size.x, half_size.y );
395  wxPoint half_len( half_size.x - half_width, half_size.y - half_width );
396  RotatePoint( &half_len, m_orient );
397  add( new SHAPE_SEGMENT( shapePos - half_len, shapePos + half_len, half_width * 2 ) );
398  }
399 
400  break;
401 
402  case PAD_SHAPE::RECT:
405  {
406  int r = ( effectiveShape == PAD_SHAPE::ROUNDRECT ) ? GetRoundRectCornerRadius() : 0;
407  wxPoint half_size( m_size.x / 2, m_size.y / 2 );
408  wxSize trap_delta( 0, 0 );
409 
410  if( r )
411  {
412  half_size -= wxPoint( r, r );
413 
414  // Avoid degenerated shapes (0 length segments) that always create issues
415  // For roundrect pad very near a circle, use only a circle
416  const int min_len = Millimeter2iu( 0.0001);
417 
418  if( half_size.x < min_len && half_size.y < min_len )
419  {
420  add( new SHAPE_CIRCLE( shapePos, r ) );
421  break;
422  }
423  }
424  else if( effectiveShape == PAD_SHAPE::TRAPEZOID )
425  {
426  trap_delta = m_deltaSize / 2;
427  }
428 
429  SHAPE_LINE_CHAIN corners;
430 
431  corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
432  corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
433  corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
434  corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
435 
436  corners.Rotate( -DECIDEG2RAD( m_orient ) );
437  corners.Move( shapePos );
438 
439  // GAL renders rectangles faster than 4-point polygons so it's worth checking if our
440  // body shape is a rectangle.
441  if( corners.PointCount() == 4
442  &&
443  ( ( corners.CPoint( 0 ).y == corners.CPoint( 1 ).y
444  && corners.CPoint( 1 ).x == corners.CPoint( 2 ).x
445  && corners.CPoint( 2 ).y == corners.CPoint( 3 ).y
446  && corners.CPoint( 3 ).x == corners.CPoint( 0 ).x )
447  ||
448  ( corners.CPoint( 0 ).x == corners.CPoint( 1 ).x
449  && corners.CPoint( 1 ).y == corners.CPoint( 2 ).y
450  && corners.CPoint( 2 ).x == corners.CPoint( 3 ).x
451  && corners.CPoint( 3 ).y == corners.CPoint( 0 ).y )
452  )
453  )
454  {
455  int width = std::abs( corners.CPoint( 2 ).x - corners.CPoint( 0 ).x );
456  int height = std::abs( corners.CPoint( 2 ).y - corners.CPoint( 0 ).y );
457  VECTOR2I pos( std::min( corners.CPoint( 2 ).x, corners.CPoint( 0 ).x ),
458  std::min( corners.CPoint( 2 ).y, corners.CPoint( 0 ).y ) );
459 
460  add( new SHAPE_RECT( pos, width, height ) );
461  }
462  else
463  {
464  add( new SHAPE_SIMPLE( corners ) );
465  }
466 
467  if( r )
468  {
469  add( new SHAPE_SEGMENT( corners.CPoint( 0 ), corners.CPoint( 1 ), r * 2 ) );
470  add( new SHAPE_SEGMENT( corners.CPoint( 1 ), corners.CPoint( 2 ), r * 2 ) );
471  add( new SHAPE_SEGMENT( corners.CPoint( 2 ), corners.CPoint( 3 ), r * 2 ) );
472  add( new SHAPE_SEGMENT( corners.CPoint( 3 ), corners.CPoint( 0 ), r * 2 ) );
473  }
474  }
475  break;
476 
478  {
479  SHAPE_POLY_SET outline;
480 
483  GetChamferPositions(), 0, maxError, ERROR_INSIDE );
484 
485  add( new SHAPE_SIMPLE( outline.COutline( 0 ) ) );
486  }
487  break;
488 
489  default:
490  wxFAIL_MSG( wxT( "PAD::buildEffectiveShapes: Unsupported pad shape: " )
491  + PAD_SHAPE_T_asString( effectiveShape ) );
492  break;
493  }
494 
495  if( GetShape() == PAD_SHAPE::CUSTOM )
496  {
497  for( const std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives )
498  {
499  for( SHAPE* shape : primitive->MakeEffectiveShapes() )
500  {
501  shape->Rotate( -DECIDEG2RAD( m_orient ) );
502  shape->Move( shapePos );
503  add( shape );
504  }
505  }
506  }
507 
508  BOX2I bbox = m_effectiveShape->BBox();
509  m_effectiveBoundingBox = EDA_RECT( (wxPoint) bbox.GetPosition(),
510  wxSize( bbox.GetWidth(), bbox.GetHeight() ) );
511 
512  // Hole shape
513  wxSize half_size = m_drill / 2;
514  int half_width = std::min( half_size.x, half_size.y );
515  wxPoint half_len( half_size.x - half_width, half_size.y - half_width );
516 
517  RotatePoint( &half_len, m_orient );
518 
519  m_effectiveHoleShape = std::make_shared<SHAPE_SEGMENT>( m_pos - half_len, m_pos + half_len,
520  half_width * 2 );
521  bbox = m_effectiveHoleShape->BBox();
523  wxSize( bbox.GetWidth(), bbox.GetHeight() ) ) );
524 
525  // All done
526  m_shapesDirty = false;
527 }
528 
529 
531 {
532  std::lock_guard<std::mutex> RAII_lock( m_polyBuildingLock );
533 
534  // If we had to wait for the lock then we were probably waiting for someone else to
535  // finish rebuilding the shapes. So check to see if they're clean now.
536  if( !m_polyDirty )
537  return;
538 
539  const BOARD* board = GetBoard();
540  int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
541 
542  // Polygon
543  m_effectivePolygon = std::make_shared<SHAPE_POLY_SET>();
545  ERROR_INSIDE );
546 
547  // Bounding radius
548  //
549  // PADSTACKS TODO: these will both need to cycle through all layers to get the largest
550  // values....
552 
553  for( int cnt = 0; cnt < m_effectivePolygon->OutlineCount(); ++cnt )
554  {
555  const SHAPE_LINE_CHAIN& poly = m_effectivePolygon->COutline( cnt );
556 
557  for( int ii = 0; ii < poly.PointCount(); ++ii )
558  {
559  int dist = KiROUND( ( poly.CPoint( ii ) - m_pos ).EuclideanNorm() );
561  }
562  }
563 
564  // All done
565  m_polyDirty = false;
566 }
567 
568 
570 {
571  if( m_shapesDirty )
573 
574  return m_effectiveBoundingBox;
575 }
576 
577 
579 {
580  FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
581 
582  m_pos = m_pos0;
583 
584  if( parentFootprint == nullptr )
585  return;
586 
587  double angle = parentFootprint->GetOrientation();
588 
589  RotatePoint( &m_pos.x, &m_pos.y, angle );
590  m_pos += parentFootprint->GetPosition();
591 
592  SetDirty();
593 }
594 
595 
597 {
598  FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
599 
600  if( parentFootprint == nullptr )
601  {
602  m_pos0 = m_pos;
603  return;
604  }
605 
606  m_pos0 = m_pos - parentFootprint->GetPosition();
607  RotatePoint( &m_pos0.x, &m_pos0.y, -parentFootprint->GetOrientation() );
608 }
609 
610 
611 void PAD::SetAttribute( PAD_ATTRIB aAttribute )
612 {
613  m_attribute = aAttribute;
614 
615  if( aAttribute == PAD_ATTRIB::SMD )
616  m_drill = wxSize( 0, 0 );
617 
618  SetDirty();
619 }
620 
621 
622 void PAD::SetProperty( PAD_PROP aProperty )
623 {
624  m_property = aProperty;
625 
626  SetDirty();
627 }
628 
629 
630 void PAD::SetOrientation( double aAngle )
631 {
632  NORMALIZE_ANGLE_POS( aAngle );
633  m_orient = aAngle;
634 
635  SetDirty();
636 }
637 
638 
639 void PAD::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
640 {
641  if( aFlipLeftRight )
642  {
643  MIRROR( m_pos.x, aCentre.x );
644  MIRROR( m_pos0.x, 0 );
645  MIRROR( m_offset.x, 0 );
646  MIRROR( m_deltaSize.x, 0 );
647  }
648  else
649  {
650  MIRROR( m_pos.y, aCentre.y );
651  MIRROR( m_pos0.y, 0 );
652  MIRROR( m_offset.y, 0 );
653  MIRROR( m_deltaSize.y, 0 );
654  }
655 
657 
658  auto mirrorBitFlags = []( int& aBitfield, int a, int b )
659  {
660  bool temp = aBitfield & a;
661 
662  if( aBitfield & b )
663  aBitfield |= a;
664  else
665  aBitfield &= ~a;
666 
667  if( temp )
668  aBitfield |= b;
669  else
670  aBitfield &= ~b;
671  };
672 
673  if( aFlipLeftRight )
674  {
677  }
678  else
679  {
682  }
683 
684  // flip pads layers
685  // PADS items are currently on all copper layers, or
686  // currently, only on Front or Back layers.
687  // So the copper layers count is not taken in account
689 
690  // Flip the basic shapes, in custom pads
691  FlipPrimitives( aFlipLeftRight );
692 
693  SetDirty();
694 }
695 
696 
697 void PAD::FlipPrimitives( bool aFlipLeftRight )
698 {
699  for( std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives )
700  primitive->Flip( wxPoint( 0, 0 ), aFlipLeftRight );
701 
702  SetDirty();
703 }
704 
705 
706 wxPoint PAD::ShapePos() const
707 {
708  if( m_offset.x == 0 && m_offset.y == 0 )
709  return m_pos;
710 
711  wxPoint loc_offset = m_offset;
712 
713  RotatePoint( &loc_offset, m_orient );
714 
715  wxPoint shape_pos = m_pos + loc_offset;
716 
717  return shape_pos;
718 }
719 
720 
721 int PAD::GetLocalClearanceOverrides( wxString* aSource ) const
722 {
723  // A pad can have specific clearance that overrides its NETCLASS clearance value
724  if( GetLocalClearance() )
725  return GetLocalClearance( aSource );
726 
727  // A footprint can have a specific clearance value
728  if( GetParent() && GetParent()->GetLocalClearance() )
729  return GetParent()->GetLocalClearance( aSource );
730 
731  return 0;
732 }
733 
734 
735 int PAD::GetLocalClearance( wxString* aSource ) const
736 {
737  if( aSource )
738  *aSource = _( "pad" );
739 
740  return m_localClearance;
741 }
742 
743 
745 {
746  // The pad inherits the margin only to calculate a default shape,
747  // therefore only if it is also a copper layer
748  // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
749  // defined by the pad settings only
750  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
751 
752  if( !isOnCopperLayer )
753  return 0;
754 
755  int margin = m_localSolderMaskMargin;
756 
757  FOOTPRINT* parentFootprint = GetParent();
758 
759  if( parentFootprint )
760  {
761  if( margin == 0 )
762  {
763  if( parentFootprint->GetLocalSolderMaskMargin() )
764  margin = parentFootprint->GetLocalSolderMaskMargin();
765  }
766 
767  if( margin == 0 )
768  {
769  const BOARD* brd = GetBoard();
770 
771  if( brd )
772  margin = brd->GetDesignSettings().m_SolderMaskMargin;
773  }
774  }
775 
776  // ensure mask have a size always >= 0
777  if( margin < 0 )
778  {
779  int minsize = -std::min( m_size.x, m_size.y ) / 2;
780 
781  if( margin < minsize )
782  margin = minsize;
783  }
784 
785  return margin;
786 }
787 
788 
790 {
791  // The pad inherits the margin only to calculate a default shape,
792  // therefore only if it is also a copper layer.
793  // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
794  // defined by the pad settings only
795  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
796 
797  if( !isOnCopperLayer )
798  return wxSize( 0, 0 );
799 
800  int margin = m_localSolderPasteMargin;
801  double mratio = m_localSolderPasteMarginRatio;
802 
803  FOOTPRINT* parentFootprint = GetParent();
804 
805  if( parentFootprint )
806  {
807  if( margin == 0 )
808  margin = parentFootprint->GetLocalSolderPasteMargin();
809 
810  auto brd = GetBoard();
811 
812  if( margin == 0 && brd )
813  margin = brd->GetDesignSettings().m_SolderPasteMargin;
814 
815  if( mratio == 0.0 )
816  mratio = parentFootprint->GetLocalSolderPasteMarginRatio();
817 
818  if( mratio == 0.0 && brd )
819  {
820  mratio = brd->GetDesignSettings().m_SolderPasteMarginRatio;
821  }
822  }
823 
824  wxSize pad_margin;
825  pad_margin.x = margin + KiROUND( m_size.x * mratio );
826  pad_margin.y = margin + KiROUND( m_size.y * mratio );
827 
828  // ensure mask have a size always >= 0
829  if( pad_margin.x < -m_size.x / 2 )
830  pad_margin.x = -m_size.x / 2;
831 
832  if( pad_margin.y < -m_size.y / 2 )
833  pad_margin.y = -m_size.y / 2;
834 
835  return pad_margin;
836 }
837 
838 
840 {
841  FOOTPRINT* parentFootprint = GetParent();
842 
843  if( m_zoneConnection == ZONE_CONNECTION::INHERITED && parentFootprint )
844  {
845  if( aSource )
846  *aSource = _( "parent footprint" );
847 
848  return parentFootprint->GetZoneConnection();
849  }
850  else
851  {
852  if( aSource )
853  *aSource = _( "pad" );
854 
855  return m_zoneConnection;
856  }
857 }
858 
859 
860 int PAD::GetEffectiveThermalSpokeWidth( wxString* aSource ) const
861 {
862  FOOTPRINT* parentFootprint = GetParent();
863 
864  if( m_thermalWidth == 0 && parentFootprint )
865  {
866  if( aSource )
867  *aSource = _( "parent footprint" );
868 
869  return parentFootprint->GetThermalWidth();
870  }
871 
872  if( aSource )
873  *aSource = _( "pad" );
874 
875  return m_thermalWidth;
876 }
877 
878 
879 int PAD::GetEffectiveThermalGap( wxString* aSource ) const
880 {
881  FOOTPRINT* parentFootprint = GetParent();
882 
883  if( m_thermalGap == 0 && parentFootprint )
884  {
885  if( aSource )
886  *aSource = _( "parent footprint" );
887 
888  return parentFootprint->GetThermalGap();
889  }
890 
891  if( aSource )
892  *aSource = _( "pad" );
893 
894  return m_thermalGap;
895 }
896 
897 
898 void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
899 {
900  EDA_UNITS units = aFrame->GetUserUnits();
901  wxString msg;
902  FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
903 
904  if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
905  {
906  if( parentFootprint )
907  aList.emplace_back( _( "Footprint" ), parentFootprint->GetReference() );
908  }
909 
910  aList.emplace_back( _( "Pad" ), m_number );
911 
912  if( !GetPinFunction().IsEmpty() )
913  aList.emplace_back( _( "Pin Name" ), GetPinFunction() );
914 
915  if( !GetPinType().IsEmpty() )
916  aList.emplace_back( _( "Pin Type" ), GetPinType() );
917 
918  if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
919  {
920  aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
921 
922  aList.emplace_back( _( "Net Class" ), UnescapeString( GetNetClass()->GetName() ) );
923 
924  if( IsLocked() )
925  aList.emplace_back( _( "Status" ), _( "Locked" ) );
926  }
927 
929  aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
930 
931  // Show the pad shape, attribute and property
932  wxString props = ShowPadAttr();
933 
934  if( GetProperty() != PAD_PROP::NONE )
935  props += ',';
936 
937  switch( GetProperty() )
938  {
939  case PAD_PROP::NONE: break;
940  case PAD_PROP::BGA: props += _( "BGA" ); break;
941  case PAD_PROP::FIDUCIAL_GLBL: props += _( "Fiducial global" ); break;
942  case PAD_PROP::FIDUCIAL_LOCAL: props += _( "Fiducial local" ); break;
943  case PAD_PROP::TESTPOINT: props += _( "Test point" ); break;
944  case PAD_PROP::HEATSINK: props += _( "Heat sink" ); break;
945  case PAD_PROP::CASTELLATED: props += _( "Castellated" ); break;
946  }
947 
948  aList.emplace_back( ShowPadShape(), props );
949 
950  if( ( GetShape() == PAD_SHAPE::CIRCLE || GetShape() == PAD_SHAPE::OVAL ) &&
951  m_size.x == m_size.y )
952  {
953  aList.emplace_back( _( "Diameter" ), MessageTextFromValue( units, m_size.x ) );
954  }
955  else
956  {
957  aList.emplace_back( _( "Width" ), MessageTextFromValue( units, m_size.x ) );
958  aList.emplace_back( _( "Height" ), MessageTextFromValue( units, m_size.y ) );
959  }
960 
961  double fp_orient_degrees = parentFootprint ? parentFootprint->GetOrientationDegrees() : 0;
962  double pad_orient_degrees = GetOrientationDegrees() - fp_orient_degrees;
963  pad_orient_degrees = NormalizeAngleDegrees( pad_orient_degrees, -180.0, +180.0 );
964 
965  if( fp_orient_degrees != 0.0 )
966  msg.Printf( wxT( "%g(+ %g)" ), pad_orient_degrees, fp_orient_degrees );
967  else
968  msg.Printf( wxT( "%g" ), GetOrientationDegrees() );
969 
970  aList.emplace_back( _( "Rotation" ), msg );
971 
972  if( GetPadToDieLength() )
973  {
974  msg = MessageTextFromValue(units, GetPadToDieLength() );
975  aList.emplace_back( _( "Length in Package" ), msg );
976  }
977 
978  if( m_drill.x > 0 || m_drill.y > 0 )
979  {
981  {
982  aList.emplace_back( _( "Hole" ),
983  wxString::Format( wxT( "%s" ),
984  MessageTextFromValue( units, m_drill.x ) ) );
985  }
986  else
987  {
988  aList.emplace_back( _( "Hole X / Y" ),
989  wxString::Format( wxT( "%s / %s" ),
990  MessageTextFromValue( units, m_drill.x ),
991  MessageTextFromValue( units, m_drill.y ) ) );
992  }
993  }
994 
995  wxString source;
996  int clearance = GetOwnClearance( GetLayer(), &source );
997 
998  if( !source.IsEmpty() )
999  {
1000  aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
1001  MessageTextFromValue( units, clearance ) ),
1002  wxString::Format( _( "(from %s)" ),
1003  source ) );
1004  }
1005 #if 0
1006  // useful for debug only
1007  aList.emplace_back( wxT( "UUID" ), m_Uuid.AsString() );
1008 #endif
1009 }
1010 
1011 
1012 bool PAD::HitTest( const wxPoint& aPosition, int aAccuracy ) const
1013 {
1014  VECTOR2I delta = aPosition - GetPosition();
1015  int boundingRadius = GetBoundingRadius() + aAccuracy;
1016 
1017  if( delta.SquaredEuclideanNorm() > SEG::Square( boundingRadius ) )
1018  return false;
1019 
1020  return GetEffectivePolygon()->Contains( aPosition, -1, aAccuracy );
1021 }
1022 
1023 
1024 bool PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
1025 {
1026  EDA_RECT arect = aRect;
1027  arect.Normalize();
1028  arect.Inflate( aAccuracy );
1029 
1030  EDA_RECT bbox = GetBoundingBox();
1031 
1032  if( aContained )
1033  {
1034  return arect.Contains( bbox );
1035  }
1036  else
1037  {
1038  // Fast test: if aRect is outside the polygon bounding box,
1039  // rectangles cannot intersect
1040  if( !arect.Intersects( bbox ) )
1041  return false;
1042 
1043  const std::shared_ptr<SHAPE_POLY_SET>& poly = GetEffectivePolygon();
1044 
1045  int count = poly->TotalVertices();
1046 
1047  for( int ii = 0; ii < count; ii++ )
1048  {
1049  auto vertex = poly->CVertex( ii );
1050  auto vertexNext = poly->CVertex(( ii + 1 ) % count );
1051 
1052  // Test if the point is within aRect
1053  if( arect.Contains( ( wxPoint ) vertex ) )
1054  return true;
1055 
1056  // Test if this edge intersects aRect
1057  if( arect.Intersects( ( wxPoint ) vertex, ( wxPoint ) vertexNext ) )
1058  return true;
1059  }
1060 
1061  return false;
1062  }
1063 }
1064 
1065 
1066 int PAD::Compare( const PAD* aPadRef, const PAD* aPadCmp )
1067 {
1068  int diff;
1069 
1070  if( ( diff = static_cast<int>( aPadRef->GetShape() ) -
1071  static_cast<int>( aPadCmp->GetShape() ) ) != 0 )
1072  return diff;
1073 
1074  if( ( diff = static_cast<int>( aPadRef->m_attribute ) -
1075  static_cast<int>( aPadCmp->m_attribute ) ) != 0 )
1076  return diff;
1077 
1078  if( ( diff = aPadRef->m_drillShape - aPadCmp->m_drillShape ) != 0 )
1079  return diff;
1080 
1081  if( ( diff = aPadRef->m_drill.x - aPadCmp->m_drill.x ) != 0 )
1082  return diff;
1083 
1084  if( ( diff = aPadRef->m_drill.y - aPadCmp->m_drill.y ) != 0 )
1085  return diff;
1086 
1087  if( ( diff = aPadRef->m_size.x - aPadCmp->m_size.x ) != 0 )
1088  return diff;
1089 
1090  if( ( diff = aPadRef->m_size.y - aPadCmp->m_size.y ) != 0 )
1091  return diff;
1092 
1093  if( ( diff = aPadRef->m_offset.x - aPadCmp->m_offset.x ) != 0 )
1094  return diff;
1095 
1096  if( ( diff = aPadRef->m_offset.y - aPadCmp->m_offset.y ) != 0 )
1097  return diff;
1098 
1099  if( ( diff = aPadRef->m_deltaSize.x - aPadCmp->m_deltaSize.x ) != 0 )
1100  return diff;
1101 
1102  if( ( diff = aPadRef->m_deltaSize.y - aPadCmp->m_deltaSize.y ) != 0 )
1103  return diff;
1104 
1105  if( ( diff = aPadRef->m_roundedCornerScale - aPadCmp->m_roundedCornerScale ) != 0 )
1106  return diff;
1107 
1108  if( ( diff = aPadRef->m_chamferPositions - aPadCmp->m_chamferPositions ) != 0 )
1109  return diff;
1110 
1111  if( ( diff = aPadRef->m_chamferScale - aPadCmp->m_chamferScale ) != 0 )
1112  return diff;
1113 
1114  if( ( diff = static_cast<int>( aPadRef->m_editPrimitives.size() ) -
1115  static_cast<int>( aPadCmp->m_editPrimitives.size() ) ) != 0 )
1116  return diff;
1117 
1118  // @todo: Compare custom pad primitives for pads that have the same number of primitives
1119  // here. Currently there is no compare function for PCB_SHAPE objects.
1120 
1121  // Dick: specctra_export needs this
1122  // Lorenzo: gencad also needs it to implement padstacks!
1123 
1124 #if __cplusplus >= 201103L
1125  long long d = aPadRef->m_layerMask.to_ullong() - aPadCmp->m_layerMask.to_ullong();
1126 
1127  if( d < 0 )
1128  return -1;
1129  else if( d > 0 )
1130  return 1;
1131 
1132  return 0;
1133 #else
1134  // these strings are not typically constructed, since we don't get here often.
1135  std::string s1 = aPadRef->m_layerMask.to_string();
1136  std::string s2 = aPadCmp->m_layerMask.to_string();
1137  return s1.compare( s2 );
1138 #endif
1139 }
1140 
1141 
1142 void PAD::Rotate( const wxPoint& aRotCentre, double aAngle )
1143 {
1144  RotatePoint( &m_pos, aRotCentre, aAngle );
1145 
1146  m_orient = NormalizeAngle360Min( m_orient + aAngle );
1147 
1148  SetLocalCoord();
1149 
1150  SetDirty();
1151 }
1152 
1153 
1154 wxString PAD::ShowPadShape() const
1155 {
1156  switch( GetShape() )
1157  {
1158  case PAD_SHAPE::CIRCLE: return _( "Circle" );
1159  case PAD_SHAPE::OVAL: return _( "Oval" );
1160  case PAD_SHAPE::RECT: return _( "Rect" );
1161  case PAD_SHAPE::TRAPEZOID: return _( "Trap" );
1162  case PAD_SHAPE::ROUNDRECT: return _( "Roundrect" );
1163  case PAD_SHAPE::CHAMFERED_RECT: return _( "Chamferedrect" );
1164  case PAD_SHAPE::CUSTOM: return _( "CustomShape" );
1165  default: return wxT( "???" );
1166  }
1167 }
1168 
1169 
1170 wxString PAD::ShowPadAttr() const
1171 {
1172  switch( GetAttribute() )
1173  {
1174  case PAD_ATTRIB::PTH: return _( "PTH" );
1175  case PAD_ATTRIB::SMD: return _( "SMD" );
1176  case PAD_ATTRIB::CONN: return _( "Conn" );
1177  case PAD_ATTRIB::NPTH: return _( "NPTH" );
1178  default: return wxT( "???" );
1179  }
1180 }
1181 
1182 
1183 wxString PAD::GetSelectMenuText( EDA_UNITS aUnits ) const
1184 {
1185  if( GetNumber().IsEmpty() )
1186  {
1188  {
1189  return wxString::Format( _( "Pad %s of %s on %s" ),
1190  GetNetnameMsg(),
1191  GetParent()->GetReference(),
1192  layerMaskDescribe() );
1193  }
1195  {
1196  return wxString::Format( _( "Through hole pad %s of %s" ),
1197  wxT( "(" ) + _( "NPTH, Mechanical" ) + wxT( ")" ),
1198  GetParent()->GetReference() );
1199  }
1200  else
1201  {
1202  return wxString::Format( _( "Through hole pad %s of %s" ),
1203  GetNetnameMsg(),
1204  GetParent()->GetReference() );
1205  }
1206  }
1207  else
1208  {
1210  {
1211  return wxString::Format( _( "Pad %s %s of %s on %s" ),
1212  GetNumber(),
1213  GetNetnameMsg(),
1214  GetParent()->GetReference(),
1215  layerMaskDescribe() );
1216  }
1218  {
1219  return wxString::Format( _( "Through hole pad %s of %s" ),
1220  wxT( "(" ) + _( "NPTH, Mechanical" ) + wxT( ")" ),
1221  GetParent()->GetReference() );
1222  }
1223  else
1224  {
1225  return wxString::Format( _( "Through hole pad %s %s of %s" ),
1226  GetNumber(),
1227  GetNetnameMsg(),
1228  GetParent()->GetReference() );
1229  }
1230  }
1231 }
1232 
1233 
1235 {
1236  return BITMAPS::pad;
1237 }
1238 
1239 
1241 {
1242  return new PAD( *this );
1243 }
1244 
1245 
1246 void PAD::ViewGetLayers( int aLayers[], int& aCount ) const
1247 {
1248  aCount = 0;
1249 
1250  // These 2 types of pads contain a hole
1251  if( m_attribute == PAD_ATTRIB::PTH )
1252  {
1253  aLayers[aCount++] = LAYER_PAD_PLATEDHOLES;
1254  aLayers[aCount++] = LAYER_PAD_HOLEWALLS;
1255  }
1256 
1257  if( m_attribute == PAD_ATTRIB::NPTH )
1258  aLayers[aCount++] = LAYER_NON_PLATEDHOLES;
1259 
1260  if( IsOnLayer( F_Cu ) && IsOnLayer( B_Cu ) )
1261  {
1262  // Multi layer pad
1263  aLayers[aCount++] = LAYER_PADS_TH;
1264  aLayers[aCount++] = LAYER_PAD_NETNAMES;
1265  }
1266  else if( IsOnLayer( F_Cu ) )
1267  {
1268  aLayers[aCount++] = LAYER_PAD_FR;
1269 
1270  // Is this a PTH pad that has only front copper? If so, we need to also display the
1271  // net name on the PTH netname layer so that it isn't blocked by the drill hole.
1272  if( m_attribute == PAD_ATTRIB::PTH )
1273  aLayers[aCount++] = LAYER_PAD_NETNAMES;
1274  else
1275  aLayers[aCount++] = LAYER_PAD_FR_NETNAMES;
1276  }
1277  else if( IsOnLayer( B_Cu ) )
1278  {
1279  aLayers[aCount++] = LAYER_PAD_BK;
1280 
1281  // Is this a PTH pad that has only back copper? If so, we need to also display the
1282  // net name on the PTH netname layer so that it isn't blocked by the drill hole.
1283  if( m_attribute == PAD_ATTRIB::PTH )
1284  aLayers[aCount++] = LAYER_PAD_NETNAMES;
1285  else
1286  aLayers[aCount++] = LAYER_PAD_BK_NETNAMES;
1287  }
1288  else
1289  {
1290  // Internal layers only. (Not yet supported in GUI, but is being used by Python
1291  // footprint generators and will be needed anyway once pad stacks are supported.)
1292  for ( int internal = In1_Cu; internal < In30_Cu; ++internal )
1293  {
1294  if( IsOnLayer( (PCB_LAYER_ID) internal ) )
1295  aLayers[aCount++] = internal;
1296  }
1297  }
1298 
1299  // Check non-copper layers. This list should include all the layers that the
1300  // footprint editor allows a pad to be placed on.
1301  static const PCB_LAYER_ID layers_mech[] = { F_Mask, B_Mask, F_Paste, B_Paste,
1303 
1304  for( PCB_LAYER_ID each_layer : layers_mech )
1305  {
1306  if( IsOnLayer( each_layer ) )
1307  aLayers[aCount++] = each_layer;
1308  }
1309 
1310 #ifdef DEBUG
1311  if( aCount == 0 ) // Should not occur
1312  {
1313  wxString msg;
1314  msg.Printf( wxT( "footprint %s, pad %s: could not find valid layer for pad" ),
1315  GetParent() ? GetParent()->GetReference() : wxT( "<null>" ),
1316  GetNumber().IsEmpty() ? wxT( "(unnumbered)" ) : GetNumber() );
1317  wxLogDebug( msg );
1318  }
1319 #endif
1320 }
1321 
1322 
1323 double PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1324 {
1325  constexpr double HIDE = std::numeric_limits<double>::max();
1326 
1327  PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1328  PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1329  const BOARD* board = GetBoard();
1330  LSET visible = LSET::AllLayersMask();
1331 
1332  // Meta control for hiding all pads
1333  if( !aView->IsLayerVisible( LAYER_PADS ) )
1334  return HIDE;
1335 
1336  // Handle board visibility
1337  if( board )
1338  visible &= board->GetEnabledLayers();
1339 
1340  // Handle view visibility
1341  for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
1342  {
1343  if( !aView->IsLayerVisible( layer ) )
1344  visible.set( layer, false );
1345  }
1346 
1347  // Handle Render tab switches
1349  && !aView->IsLayerVisible( LAYER_PADS_TH ) )
1350  {
1351  return HIDE;
1352  }
1353 
1354  if( !IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1355  return HIDE;
1356 
1357  if( IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1358  return HIDE;
1359 
1360  if( IsFrontLayer( (PCB_LAYER_ID) aLayer ) && !aView->IsLayerVisible( LAYER_PAD_FR ) )
1361  return HIDE;
1362 
1363  if( IsBackLayer( (PCB_LAYER_ID) aLayer ) && !aView->IsLayerVisible( LAYER_PAD_BK ) )
1364  return HIDE;
1365 
1366  if( aLayer == LAYER_PADS_TH )
1367  {
1368  if( !FlashLayer( visible ) )
1369  return HIDE;
1370  }
1371  else if( IsHoleLayer( aLayer ) )
1372  {
1373  if( !( visible & LSET::PhysicalLayersMask() ).any() )
1374  return HIDE;
1375  }
1376  else if( IsNetnameLayer( aLayer ) )
1377  {
1378  if( renderSettings->GetHighContrast() )
1379  {
1380  // Hide netnames unless pad is flashed to a high-contrast layer
1381  if( !FlashLayer( renderSettings->GetPrimaryHighContrastLayer() ) )
1382  return HIDE;
1383  }
1384  else
1385  {
1386  // Hide netnames unless pad is flashed to a visible layer
1387  if( !FlashLayer( visible ) )
1388  return HIDE;
1389  }
1390 
1391  // Netnames will be shown only if zoom is appropriate
1392  int divisor = std::min( GetBoundingBox().GetWidth(), GetBoundingBox().GetHeight() );
1393 
1394  // Pad sizes can be zero briefly when someone is typing a number like "0.5"
1395  // in the pad properties dialog
1396  if( divisor == 0 )
1397  return HIDE;
1398 
1399  return ( double ) Millimeter2iu( 5 ) / divisor;
1400  }
1401 
1402  if( aLayer == LAYER_PADS_TH
1403  && GetShape() != PAD_SHAPE::CUSTOM
1404  && GetSizeX() <= GetDrillSizeX()
1405  && GetSizeY() <= GetDrillSizeY() )
1406  {
1407  // Don't tweak the drawing code with a degenerate pad
1408  return HIDE;
1409  }
1410 
1411  // Passed all tests; show.
1412  return 0.0;
1413 }
1414 
1415 
1416 const BOX2I PAD::ViewBBox() const
1417 {
1418  // Bounding box includes soldermask too. Remember mask and/or paste
1419  // margins can be < 0
1420  int solderMaskMargin = std::max( GetSolderMaskMargin(), 0 );
1421  VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() );
1422  EDA_RECT bbox = GetBoundingBox();
1423 
1424  // get the biggest possible clearance
1425  int clearance = 0;
1426 
1427  for( PCB_LAYER_ID layer : GetLayerSet().Seq() )
1428  clearance = std::max( clearance, GetOwnClearance( layer ) );
1429 
1430  // Look for the biggest possible bounding box
1431  int xMargin = std::max( solderMaskMargin, solderPasteMargin.x ) + clearance;
1432  int yMargin = std::max( solderMaskMargin, solderPasteMargin.y ) + clearance;
1433 
1434  return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ),
1435  VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) );
1436 }
1437 
1438 
1440 {
1441  return dynamic_cast<FOOTPRINT*>( m_parent );
1442 }
1443 
1444 
1445 void PAD::ImportSettingsFrom( const PAD& aMasterPad )
1446 {
1447  SetShape( aMasterPad.GetShape() );
1448  SetLayerSet( aMasterPad.GetLayerSet() );
1449  SetAttribute( aMasterPad.GetAttribute() );
1450  SetProperty( aMasterPad.GetProperty() );
1451 
1452  // I am not sure the m_LengthPadToDie must be imported, because this is
1453  // a parameter really specific to a given pad (JPC).
1454  // So this is currently non imported
1455 #if 0
1456  SetPadToDieLength( aMasterPad.GetPadToDieLength() );
1457 #endif
1458 
1459  // The pad orientation, for historical reasons is the
1460  // pad rotation + parent rotation.
1461  // So we have to manage this parent rotation
1462  double pad_rot = aMasterPad.GetOrientation();
1463 
1464  if( aMasterPad.GetParent() )
1465  pad_rot -= aMasterPad.GetParent()->GetOrientation();
1466 
1467  if( GetParent() )
1468  pad_rot += GetParent()->GetOrientation();
1469 
1470  SetOrientation( pad_rot );
1471 
1472  SetSize( aMasterPad.GetSize() );
1473  SetDelta( wxSize( 0, 0 ) );
1474  SetOffset( aMasterPad.GetOffset() );
1475  SetDrillSize( aMasterPad.GetDrillSize() );
1476  SetDrillShape( aMasterPad.GetDrillShape() );
1478  SetChamferRectRatio( aMasterPad.GetChamferRectRatio() );
1479  SetChamferPositions( aMasterPad.GetChamferPositions() );
1480 
1481  switch( aMasterPad.GetShape() )
1482  {
1483  case PAD_SHAPE::TRAPEZOID:
1484  SetDelta( aMasterPad.GetDelta() );
1485  break;
1486 
1487  case PAD_SHAPE::CIRCLE:
1488  // ensure size.y == size.x
1489  SetSize( wxSize( GetSize().x, GetSize().x ) );
1490  break;
1491 
1492  default:
1493  ;
1494  }
1495 
1496  switch( aMasterPad.GetAttribute() )
1497  {
1498  case PAD_ATTRIB::SMD:
1499  case PAD_ATTRIB::CONN:
1500  // These pads do not have hole (they are expected to be only on one
1501  // external copper layer)
1502  SetDrillSize( wxSize( 0, 0 ) );
1503  break;
1504 
1505  default:
1506  ;
1507  }
1508 
1509  // copy also local settings:
1510  SetLocalClearance( aMasterPad.GetLocalClearance() );
1514 
1517  SetThermalGap( aMasterPad.GetThermalGap() );
1518 
1520 
1521  // Add or remove custom pad shapes:
1522  ReplacePrimitives( aMasterPad.GetPrimitives() );
1523  SetAnchorPadShape( aMasterPad.GetAnchorPadShape() );
1524 
1525  SetDirty();
1526 }
1527 
1528 
1529 void PAD::SwapData( BOARD_ITEM* aImage )
1530 {
1531  assert( aImage->Type() == PCB_PAD_T );
1532 
1533  std::swap( *((PAD*) this), *((PAD*) aImage) );
1534 }
1535 
1536 
1537 bool PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
1538  int aError, ERROR_LOC aErrorLoc ) const
1539 {
1540  wxSize drillsize = GetDrillSize();
1541 
1542  if( !drillsize.x || !drillsize.y )
1543  return false;
1544 
1545  const SHAPE_SEGMENT* seg = GetEffectiveHoleShape();
1546 
1547  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B,
1548  seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc );
1549 
1550  return true;
1551 }
1552 
1553 
1555  PCB_LAYER_ID aLayer, int aClearanceValue,
1556  int aError, ERROR_LOC aErrorLoc,
1557  bool ignoreLineWidth ) const
1558 {
1559  wxASSERT_MSG( !ignoreLineWidth, wxT( "IgnoreLineWidth has no meaning for pads." ) );
1560 
1561  // minimal segment count to approximate a circle to create the polygonal pad shape
1562  // This minimal value is mainly for very small pads, like SM0402.
1563  // Most of time pads are using the segment count given by aError value.
1564  const int pad_min_seg_per_circle_count = 16;
1565  double angle = m_orient;
1566  int dx = m_size.x / 2;
1567  int dy = m_size.y / 2;
1568 
1569  wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset,
1570  // the pad position is NOT the shape position
1571 
1572  switch( GetShape() )
1573  {
1574  case PAD_SHAPE::CIRCLE:
1575  case PAD_SHAPE::OVAL:
1576  // Note: dx == dy is not guaranteed for circle pads in legacy boards
1577  if( dx == dy || ( GetShape() == PAD_SHAPE::CIRCLE ) )
1578  {
1579  TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError,
1580  aErrorLoc, pad_min_seg_per_circle_count );
1581  }
1582  else
1583  {
1584  int half_width = std::min( dx, dy );
1585  wxPoint delta( dx - half_width, dy - half_width );
1586 
1587  RotatePoint( &delta, angle );
1588 
1589  TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta,
1590  ( half_width + aClearanceValue ) * 2, aError, aErrorLoc,
1591  pad_min_seg_per_circle_count );
1592  }
1593 
1594  break;
1595 
1596  case PAD_SHAPE::TRAPEZOID:
1597  case PAD_SHAPE::RECT:
1598  {
1599  int ddx = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.x / 2 : 0;
1600  int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.y / 2 : 0;
1601 
1602  SHAPE_POLY_SET outline;
1603  TransformTrapezoidToPolygon( outline, padShapePos, m_size, angle, ddx, ddy,
1604  aClearanceValue, aError, aErrorLoc );
1605  aCornerBuffer.Append( outline );
1606  break;
1607  }
1608 
1610  case PAD_SHAPE::ROUNDRECT:
1611  {
1612  bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT;
1613 
1614  SHAPE_POLY_SET outline;
1615  TransformRoundChamferedRectToPolygon( outline, padShapePos, m_size, angle,
1617  doChamfer ? GetChamferRectRatio() : 0,
1618  doChamfer ? GetChamferPositions() : 0,
1619  aClearanceValue, aError, aErrorLoc );
1620  aCornerBuffer.Append( outline );
1621  break;
1622  }
1623 
1624  case PAD_SHAPE::CUSTOM:
1625  {
1626  SHAPE_POLY_SET outline;
1627  MergePrimitivesAsPolygon( &outline, aErrorLoc );
1628  outline.Rotate( -DECIDEG2RAD( m_orient ) );
1629  outline.Move( VECTOR2I( m_pos ) );
1630 
1631  if( aClearanceValue )
1632  {
1633  int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
1634  pad_min_seg_per_circle_count );
1635  int clearance = aClearanceValue;
1636 
1637  if( aErrorLoc == ERROR_OUTSIDE )
1638  {
1639  int actual_error = CircleToEndSegmentDeltaRadius( clearance, numSegs );
1640  clearance += GetCircleToPolyCorrection( actual_error );
1641  }
1642 
1643  outline.Inflate( clearance, numSegs );
1644  outline.Simplify( SHAPE_POLY_SET::PM_FAST );
1645  outline.Fracture( SHAPE_POLY_SET::PM_FAST );
1646  }
1647 
1648  aCornerBuffer.Append( outline );
1649  break;
1650  }
1651 
1652  default:
1653  wxFAIL_MSG( wxT( "PAD::TransformShapeWithClearanceToPolygon no implementation for " )
1654  + PAD_SHAPE_T_asString( GetShape() ) );
1655  break;
1656  }
1657 }
1658 
1659 
1660 static struct PAD_DESC
1661 {
1663  {
1665  .Map( PAD_ATTRIB::PTH, _HKI( "Through-hole" ) )
1666  .Map( PAD_ATTRIB::SMD, _HKI( "SMD" ) )
1667  .Map( PAD_ATTRIB::CONN, _HKI( "Edge connector" ) )
1668  .Map( PAD_ATTRIB::NPTH, _HKI( "NPTH, mechanical" ) );
1669 
1671  .Map( PAD_SHAPE::CIRCLE, _HKI( "Circle" ) )
1672  .Map( PAD_SHAPE::RECT, _HKI( "Rectangle" ) )
1673  .Map( PAD_SHAPE::OVAL, _HKI( "Oval" ) )
1674  .Map( PAD_SHAPE::TRAPEZOID, _HKI( "Trapezoid" ) )
1675  .Map( PAD_SHAPE::ROUNDRECT, _HKI( "Rounded rectangle" ) )
1676  .Map( PAD_SHAPE::CHAMFERED_RECT, _HKI( "Chamfered rectangle" ) )
1677  .Map( PAD_SHAPE::CUSTOM, _HKI( "Custom" ) );
1678 
1680  .Map( PAD_PROP::NONE, _HKI( "None" ) )
1681  .Map( PAD_PROP::BGA, _HKI( "BGA pad" ) )
1682  .Map( PAD_PROP::FIDUCIAL_GLBL, _HKI( "Fiducial, global to board" ) )
1683  .Map( PAD_PROP::FIDUCIAL_LOCAL, _HKI( "Fiducial, local to footprint" ) )
1684  .Map( PAD_PROP::TESTPOINT, _HKI( "Test point pad" ) )
1685  .Map( PAD_PROP::HEATSINK, _HKI( "Heatsink pad" ) )
1686  .Map( PAD_PROP::CASTELLATED, _HKI( "Castellated pad" ) );
1687 
1689  REGISTER_TYPE( PAD );
1691 
1692  auto padType = new PROPERTY_ENUM<PAD, PAD_ATTRIB>( _HKI( "Pad Type" ),
1694  propMgr.AddProperty( padType );
1695 
1696  auto shape = new PROPERTY_ENUM<PAD, PAD_SHAPE>( _HKI( "Shape" ),
1698  propMgr.AddProperty( shape );
1699 
1700  propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pad Number" ),
1702  propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pin Name" ),
1704  propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pin Type" ),
1706  propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Orientation" ),
1709  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size X" ),
1712  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size Y" ),
1715  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Hole Size X" ),
1718  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Hole Size Y" ),
1721  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Pad To Die Length" ),
1724  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Soldermask Margin Override" ),
1727  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Solderpaste Margin Override" ),
1730  propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Solderpaste Margin Ratio Override" ),
1732  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Width" ),
1735  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Gap" ),
1738  propMgr.AddProperty( new PROPERTY_ENUM<PAD, PAD_PROP>( _HKI( "Fabrication Property" ),
1740 
1741  auto roundRadiusRatio = new PROPERTY<PAD, double>( _HKI( "Round Radius Ratio" ),
1743  roundRadiusRatio->SetAvailableFunc(
1744  [=]( INSPECTABLE* aItem ) -> bool
1745  {
1746  return aItem->Get( shape ) == static_cast<int>( PAD_SHAPE::ROUNDRECT );
1747  } );
1748  propMgr.AddProperty( roundRadiusRatio );
1749 
1750  propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Clearance Override" ),
1753  propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Parent" ),
1754  NO_SETTER( PAD, wxString ), &PAD::GetParentAsString ) );
1755 
1756  // TODO delta, drill shape offset, layer set, zone connection
1757  }
1758 } _PAD_DESC;
1759 
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
bool TransformHoleWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aInflateValue, int aError, ERROR_LOC aErrorLoc) const
Build the corner list of the polygonal drill shape in the board coordinate system.
Definition: pad.cpp:1537
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:759
Display value expressed in degrees.
Definition: property.h:54
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pad.cpp:1234
static LSET FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
Definition: lset.cpp:822
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
int GetLocalSolderMaskMargin() const
Definition: pad.h:386
void FlipPrimitives(bool aFlipLeftRight)
Flip (mirror) the primitives left to right or top to bottom, around the anchor position in custom pad...
Definition: pad.cpp:697
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:478
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:104
smd pads, front layer
Definition: layer_ids.h:209
void SetOffset(const wxPoint &aOffset)
Definition: pad.h:249
const int GetSizeY() const
Definition: pad.h:237
BOX2< VECTOR2I > BOX2I
Definition: box2.h:506
int GetLocalClearance() const
Definition: pad.h:390
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:41
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:65
bool m_shapesDirty
Definition: pad.h:694
#define TYPE_HASH(x)
Definition: property.h:59
LSET FlipLayerMask(LSET aMask, int aCopperLayersCount)
Calculate the mask layer when flipping a footprint.
Definition: lset.cpp:576
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:173
static struct PAD_DESC _PAD_DESC
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:397
int m_chamferPositions
Definition: pad.h:724
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:611
const int GetDrillSizeX() const
Definition: pad.h:245
void Merge(const EDA_RECT &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: eda_rect.cpp:432
std::mutex m_shapesBuildingLock
Definition: pad.h:695
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
std::mutex m_polyBuildingLock
Definition: pad.h:701
int GetLocalSolderPasteMargin() const
Definition: pad.h:393
double GetRoundRectRadiusRatio() const
Definition: pad.h:524
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: pad.cpp:1246
void SetLocalClearance(int aClearance)
Definition: pad.h:391
Implementation of conversion functions that require both schematic and board internal units.
wxSize m_deltaSize
Definition: pad.h:741
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
int m_effectiveBoundingRadius
Definition: pad.h:703
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:491
void SetDrillSizeY(const int aY)
Definition: pad.h:246
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:237
PAD_PROP GetProperty() const
Definition: pad.h:374
wxSize m_drill
Definition: pad.h:715
int GetHolePlatingThickness() const
Pad & via drills are finish size.
int GetLocalClearanceOverrides(wxString *aSource) const override
Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:721
virtual NETCLASS * GetNetClass() const
Return the NETCLASS for this item.
smd pads, back layer
Definition: layer_ids.h:210
double m_roundedCornerScale
Definition: pad.h:720
LSET m_layerMask
Definition: pad.h:738
void Move(const VECTOR2I &aVector) override
Like smd, does not appear on the solder paste layer (default)
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: pad.cpp:1012
void SetOrientationDegrees(double aOrientation)
Set orientation in degrees.
Definition: pad.h:343
Additional netnames layers (not associated with a PCB layer)
Definition: layer_ids.h:172
Smd pad, appears on the solder paste layer (default)
bool IsLocked() const override
Definition: pad.cpp:150
void SetSubRatsnest(int aSubRatsnest)
Definition: pad.h:549
static ENUM_MAP< T > & Instance()
Definition: property.h:510
double GetOrientation() const
Definition: footprint.h:191
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
Definition: pad.h:568
void SetSizeX(const int aX)
Definition: pad.h:234
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pad.cpp:336
wxString AsString() const
Definition: kiid.cpp:236
class PAD, a pad in a footprint
Definition: typeinfo.h:89
void SetPinType(const wxString &aType)
Set the pad electrical type.
Definition: pad.h:145
show footprints on back
Definition: layer_ids.h:216
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE >> &aPrimitivesList)
Clear the current custom shape primitives list and import a new list.
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:467
wxPoint m_pos
Definition: pad.h:682
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void SetSize(const wxSize &aSize)
Definition: pad.h:232
int GetEffectiveThermalGap(wxString *aSource=nullptr) const
Return the effective thermal gap having resolved any inheritance.
Definition: pad.cpp:879
void SetDelta(const wxSize &aSize)
Definition: pad.h:239
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:290
wxPoint m_pos0
Definition: pad.h:745
The base class for create windows for drawing purpose.
bool IsAperturePad() const
Definition: pad.h:378
VECTOR2< int > VECTOR2I
Definition: vector2d.h:622
a test point pad
#define NO_SETTER(owner, type)
Definition: property.h:621
virtual bool IsLocked() const
Definition: board_item.cpp:64
int PointCount() const
Return the number of points (vertices) in this line chain.
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
std::shared_ptr< SHAPE_COMPOUND > m_effectiveShape
Definition: pad.h:697
static SEG::ecoord Square(int a)
Definition: seg.h:122
Contains methods for drawing PCB-specific items.
Definition: pcb_painter.h:241
int GetThermalGap() const
Definition: pad.h:500
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
wxString ShowPadShape() const
Definition: pad.cpp:1154
#define REGISTER_TYPE(x)
Definition: property_mgr.h:248
double m_localSolderPasteMarginRatio
Definition: pad.h:775
bool Contains(const wxPoint &aPoint) const
Definition: eda_rect.cpp:57
bool IsFlipped() const
Definition: pad.cpp:194
int m_localSolderPasteMargin
Definition: pad.h:774
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:208
const SEG & GetSeg() const
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
EDA_RECT m_effectiveBoundingBox
Definition: pad.h:696
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
Plated through hole pad.
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
This file contains miscellaneous commonly used macros and functions.
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
int m_localSolderMaskMargin
Definition: pad.h:773
void SetPadToDieLength(int aLength)
Definition: pad.h:383
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:622
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
void ImportSettingsFrom(const PAD &aMasterPad)
Import the pad settings from aMasterPad.
Definition: pad.cpp:1445
std::shared_ptr< SHAPE_SEGMENT > m_effectiveHoleShape
Definition: pad.h:698
a pad used as heat sink, usually in SMD footprints
int GetEffectiveThermalSpokeWidth(wxString *aSource=nullptr) const
Return the effective thermal spoke width having resolved any inheritance.
Definition: pad.cpp:860
bool m_keepTopBottomLayer
Definition: pad.h:760
PCB specific render settings.
Definition: pcb_painter.h:64
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pad.cpp:1323
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:387
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape() DO NOT REORDER, legacy_plugin is dependent on ...
Definition: pad_shapes.h:33
int m_localClearance
Definition: pad.h:772
const wxPoint & GetOffset() const
Definition: pad.h:250
std::shared_ptr< SHAPE_POLY_SET > m_effectivePolygon
Definition: pad.h:702
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: pad.cpp:309
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: pad.cpp:898
void SetDrillSizeX(const int aX)
Definition: pad.h:244
const wxSize & GetDrillSize() const
Definition: pad.h:243
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: pad.cpp:1529
virtual wxString layerMaskDescribe() const
Return a string (to be shown to the user) describing a layer mask.
Definition: board_item.cpp:87
wxPoint ShapePos() const
Definition: pad.cpp:706
like PAD_PTH, but not plated
double m_chamferScale
Definition: pad.h:722
bool IsHoleLayer(LAYER_NUM aLayer)
Definition: layer_ids.h:847
Display value expressed in distance units (mm/inch)
Definition: property.h:53
bool FlashLayer(int aLayer) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:214
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:516
handle color for not plated holes (holes, not pads)
Definition: layer_ids.h:204
int m_thermalGap
Definition: pad.h:780
int GetThermalSpokeWidth() const
Definition: pad.h:492
double GetOrientation() const
Return the rotation angle of the pad in a variety of units (the basic call returns tenths of degrees)...
Definition: pad.h:349
VECTOR2< double > VECTOR2D
Definition: vector2d.h:621
void Move(const VECTOR2I &aVector) override
void SetPos0(const wxPoint &aPos)
Definition: pad.h:226
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:907
void SetLocalCoord()
< Set relative coordinates.
Definition: pad.cpp:596
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
Definition: pcb_painter.h:247
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:639
void SetThermalGap(int aGap)
Definition: pad.h:499
Represent a set of closed polygons.
int m_thermalWidth
Definition: pad.h:779
const wxPoint GetOrigin() const
Definition: eda_rect.h:110
coord_type GetWidth() const
Definition: box2.h:180
void SetDrillSize(const wxSize &aSize)
Definition: pad.h:242
const wxSize & GetSize() const
Definition: pad.h:233
wxAny Get(PROPERTY_BASE *aProperty)
Definition: inspectable.h:86
ZONE_CONNECTION GetEffectiveZoneConnection(wxString *aSource=nullptr) const
Return the zone connection in effect (either locally overridden or overridden in the parent footprint...
Definition: pad.cpp:839
Smd pad, used in BGA footprints.
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aCornerBuffer, const wxPoint &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1416
void TransformTrapezoidToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aDeltaX, int aDeltaY, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle or trapezoid to a polygon.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
show footprints on front
Definition: layer_ids.h:215
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:159
const EDA_RECT GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:569
const wxString & GetNumber() const
Definition: pad.h:129
double m_orient
Definition: pad.h:752
int GetLocalClearance() const
Definition: footprint.h:213
const wxString & GetPinType() const
Definition: pad.h:146
PAD_SHAPE GetShape() const
Definition: pad.h:170
const wxString & GetReference() const
Definition: footprint.h:466
a fiducial (usually a smd) local to the parent footprint
#define _(s)
PAD & operator=(const PAD &aOther)
Definition: pad.cpp:116
static LSET AllLayersMask()
Definition: lset.cpp:796
void Simplify(POLYGON_MODE aFastMode)
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:368
class ZONE, a copper pour area
Definition: typeinfo.h:105
An abstract shape on 2D plane.
Definition: shape.h:116
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:476
void SetDrawCoord()
Definition: pad.cpp:578
ZONE_CONNECTION m_zoneConnection
Definition: pad.h:778
int GetCircleToPolyCorrection(int aMaxError)
void SetPinFunction(const wxString &aName)
Set the pad function (pin name in schematic)
Definition: pad.h:139
void BuildEffectivePolygon() const
Definition: pad.cpp:530
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: pad.h:198
E_SERIE r
Definition: eserie.cpp:41
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition: layer_ids.h:884
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:35
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:284
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:79
int GetThermalWidth() const
Definition: footprint.h:234
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:243
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:735
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:353
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:808
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:153
wxString UnescapeString(const wxString &aSource)
void BuildEffectiveShapes(PCB_LAYER_ID aLayer) const
Rebuild the effective shape cache (and bounding box and radius) for the pad and clears the dirty bit.
Definition: pad.cpp:354
double GetLocalSolderPasteMarginRatio() const
Definition: pad.h:396
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
wxString GetNetnameMsg() const
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:275
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
const KIID m_Uuid
Definition: eda_item.h:474
const Vec & GetPosition() const
Definition: box2.h:177
Some functions to handle hotkeys in KiCad.
int GetRoundRectCornerRadius() const
Definition: pad.cpp:269
const wxSize & GetDelta() const
Definition: pad.h:240
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxSize m_size
Definition: pad.h:716
int GetSolderMaskMargin() const
Definition: pad.cpp:744
FOOTPRINT * GetParent() const
Definition: pad.cpp:1439
void Rotate(double aAngle, const VECTOR2I &aCenter=VECTOR2I(0, 0)) override
Rotate all vertices by a given angle.
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:542
static int Compare(const PAD *aPadRef, const PAD *aPadCmp)
Compare two pads and return 0 if they are equal.
Definition: pad.cpp:1066
EDA_UNITS
Definition: eda_units.h:38
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
PAD_DRILL_SHAPE_T m_drillShape
Definition: pad.h:718
wxPoint m_offset
Definition: pad.h:736
const wxPoint & GetPos0() const
Definition: pad.h:227
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:858
double GetOrientationDegrees() const
Definition: footprint.h:192
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1554
void SetSizeY(const int aY)
Definition: pad.h:236
int GetBoundingRadius() const
Return the radius of a minimum sized circle which fully encloses this pad.
Definition: pad.cpp:345
int GetLocalSolderMaskMargin() const
Definition: footprint.h:210
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:187
void SetLayerSet(LSET aLayers) override
Definition: pad.h:367
bool m_removeUnconnectedLayer
< If true, the pad copper is removed for layers that are not connected.
Definition: pad.h:757
PAD_DESC()
Definition: pad.cpp:1662
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:188
multilayer pads, usually with holes
Definition: layer_ids.h:220
a fiducial (usually a smd) for the full board
double GetChamferRectRatio() const
Definition: pad.h:533
std::vector< std::shared_ptr< PCB_SHAPE > > m_editPrimitives
Definition: pad.h:691
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:32
wxSize GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition: pad.cpp:789
int GetSubRatsnest() const
Definition: pad.h:548
PAD_PROP
Ghe set of pad properties used in Gerber files (Draw files, and P&P files) to define some properties ...
Definition: pad_shapes.h:95
wxPoint GetPosition() const override
Definition: pad.h:178
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:394
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:354
no special fabrication property
ENUM_TO_WXANY(PAD_ATTRIB)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
const int GetDrillSizeY() const
Definition: pad.h:247
static LSET BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
Definition: lset.cpp:809
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsNetnameLayer(LAYER_NUM aLayer)
Test whether a layer is a netname layer.
Definition: layer_ids.h:976
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
PAD_ATTRIB GetAttribute() const
Definition: pad.h:371
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:128
double GetOrientationDegrees() const
Definition: pad.h:350
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Definition: layer_ids.h:71
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetPosition(const wxPoint &aPos) override
Definition: pad.h:172
void AddProperty(PROPERTY_BASE *aProperty)
Register a property.
void SetDirty()
Definition: pad.h:361
class ZONE, managed by a footprint
Definition: typeinfo.h:94
VECTOR2I A
Definition: seg.h:48
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pad.cpp:1240
Handle the component boundary box.
Definition: eda_rect.h:42
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
const int GetSizeX() const
Definition: pad.h:235
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aStart, const wxPoint &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
static std::string PAD_SHAPE_T_asString(PAD_SHAPE a)
Definition: pad_shapes.h:47
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon() const
Definition: pad.cpp:300
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
coord_type GetHeight() const
Definition: box2.h:181
wxPoint GetPosition() const override
Definition: footprint.h:187
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: pad.cpp:1183
double NormalizeAngleDegrees(double Angle, double aMin, double aMax)
Normalize angle to be aMin < angle <= aMax angle is in degrees.
Definition: trigo.h:327
virtual int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const
Return an item's "own" clearance in internal units.
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
double GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:227
bool Intersects(const EDA_RECT &aRect) const
Test for a common area between rectangles.
Definition: eda_rect.cpp:150
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:161
int GetChamferPositions() const
Definition: pad.h:543
wxString GetParentAsString() const
Definition: pad.h:107
int m_lengthPadToDie
Definition: pad.h:754
constexpr int delta
to draw pad holes (plated)
Definition: layer_ids.h:221
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:36
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:62
PAD_ATTRIB m_attribute
Definition: pad.h:748
a pad with a castellated through hole
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
wxString ShowPadAttr() const
Definition: pad.cpp:1170
ZONE_CONNECTION GetZoneConnection() const
Definition: footprint.h:231
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:180
#define PCB_EDIT_FRAME_NAME
CUST_PAD_SHAPE_IN_ZONE m_customShapeClearanceArea
Definition: pad.h:710
wxString m_number
Definition: pad.h:678
int GetLocalSolderPasteMargin() const
Definition: footprint.h:224
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
Definition: pad.h:57
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:292
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:254
Message panel definition file.
int GetWidth() const
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:166
static constexpr int Millimeter2iu(double mm)
#define _HKI(x)
int GetPadToDieLength() const
Definition: pad.h:384
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:143
PAD(FOOTPRINT *parent)
Definition: pad.cpp:60
const wxString & GetPinFunction() const
Definition: pad.h:140
bool m_polyDirty
Definition: pad.h:700
int GetThermalGap() const
Definition: footprint.h:237
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:301
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:183
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void SetOrientation(double aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:630
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
const wxSize GetSize() const
Definition: eda_rect.h:100
PAD_PROP m_property
Definition: pad.h:750
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:209
Container for design settings for a BOARD object.
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:405
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate this object.
Definition: pad.cpp:1142
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
bool CanHaveNumber() const
Indicates whether or not the pad can have a number.
Definition: pad.cpp:136
VECTOR2I B
Definition: seg.h:49