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