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