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-2023 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>
52#include <wx/log.h>
53
54#include <memory>
55#include <macros.h>
56#include "kiface_base.h"
57#include "pcbnew_settings.h"
58
61
62
63PAD::PAD( FOOTPRINT* parent ) :
65{
66 m_size.x = m_size.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 60 ); // Default pad size 60 mils.
67 m_drill.x = m_drill.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 30 ); // Default drill size 30 mils.
70
73
74 SetShape( PAD_SHAPE::CIRCLE ); // Default pad shape is PAD_CIRCLE.
75 SetAnchorPadShape( PAD_SHAPE::CIRCLE ); // Default shape for custom shaped pads
76 // is PAD_CIRCLE.
77 SetDrillShape( PAD_DRILL_SHAPE_CIRCLE ); // Default pad drill shape is a circle.
78 m_attribute = PAD_ATTRIB::PTH; // Default pad type is plated through hole
79 SetProperty( PAD_PROP::NONE ); // no special fabrication property
84
85 // Parameters for round rect only:
86 m_roundedCornerScale = 0.25; // from IPC-7351C standard
87
88 // Parameters for chamfered rect only:
89 m_chamferScale = 0.2; // Size of chamfer: ratio of smallest of X,Y size
90 m_chamferPositions = RECT_NO_CHAMFER; // No chamfered corner
91
92 m_zoneConnection = ZONE_CONNECTION::INHERITED; // Use parent setting by default
93 m_thermalSpokeWidth = 0; // Use parent setting by default
94 m_thermalSpokeAngle = ANGLE_45; // Default for circular pads
95 m_thermalGap = 0; // Use parent setting by default
96
98
99 // Set layers mask to default for a standard thru hole pad.
101
102 SetSubRatsnest( 0 ); // used in ratsnest calculations
103
104 SetDirty();
108
110}
111
112
113PAD::PAD( const PAD& aOther ) :
114 BOARD_CONNECTED_ITEM( aOther.GetParent(), PCB_PAD_T )
115{
116 PAD::operator=( aOther );
117
118 const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
119}
120
121
122PAD& PAD::operator=( const PAD &aOther )
123{
125
126 ImportSettingsFrom( aOther );
128 SetPosition( aOther.GetPosition() );
129 SetPos0( aOther.GetPos0() );
130 SetNumber( aOther.GetNumber() );
131 SetPinType( aOther.GetPinType() );
132 SetPinFunction( aOther.GetPinFunction() );
133 SetSubRatsnest( aOther.GetSubRatsnest() );
137
138 return *this;
139}
140
141
143{
144 // Aperture pads don't get a number
145 if( IsAperturePad() )
146 return false;
147
148 // NPTH pads don't get numbers
150 return false;
151
152 return true;
153}
154
155
156bool PAD::IsLocked() const
157{
158 if( GetParent() && GetParent()->IsLocked() )
159 return true;
160
161 return BOARD_ITEM::IsLocked();
162};
163
164
165bool PAD::SharesNetTieGroup( const PAD* aOther ) const
166{
167 FOOTPRINT* parentFp = static_cast<FOOTPRINT*>( GetParentFootprint() );
168
169 if( parentFp && parentFp->IsNetTie() && aOther->GetParentFootprint() == parentFp )
170 {
171 std::map<wxString, int> padToNetTieGroupMap = parentFp->MapPadNumbersToNetTieGroups();
172 int thisNetTieGroup = padToNetTieGroupMap[ GetNumber() ];
173 int otherNetTieGroup = padToNetTieGroupMap[ aOther->GetNumber() ];
174
175 return thisNetTieGroup >= 0 && thisNetTieGroup == otherNetTieGroup;
176 }
177
178 return false;
179}
180
181
183{
184 return GetShortNetname().StartsWith( wxT( "unconnected-(" ) )
185 && ( m_pinType == wxT( "no_connect" ) || m_pinType.EndsWith( wxT( "+no_connect" ) ) );
186}
187
188
189bool PAD::IsFreePad() const
190{
191 return GetShortNetname().StartsWith( wxT( "unconnected-(" ) )
192 && m_pinType == wxT( "free" );
193}
194
195
197{
198 static LSET saved = LSET::AllCuMask() | LSET( 2, F_Mask, B_Mask );
199 return saved;
200}
201
202
204{
205 static LSET saved( 3, F_Cu, F_Paste, F_Mask );
206 return saved;
207}
208
209
211{
212 static LSET saved( 2, F_Cu, F_Mask );
213 return saved;
214}
215
216
218{
219 static LSET saved = LSET( 4, F_Cu, B_Cu, F_Mask, B_Mask );
220 return saved;
221}
222
223
225{
226 static LSET saved( 1, F_Paste );
227 return saved;
228}
229
230
231bool PAD::IsFlipped() const
232{
233 FOOTPRINT* parent = GetParent();
234
235 return ( parent && parent->GetLayer() == B_Cu );
236}
237
238
240{
241 return BOARD_ITEM::GetLayer();
242}
243
244
246{
248 return m_layer;
249 else
250 return GetLayerSet().Seq().front();
251
252}
253
254
255bool PAD::FlashLayer( LSET aLayers ) const
256{
257 for( PCB_LAYER_ID layer : aLayers.Seq() )
258 {
259 if( FlashLayer( layer ) )
260 return true;
261 }
262
263 return false;
264}
265
266
267bool PAD::FlashLayer( int aLayer, bool aOnlyCheckIfPermitted ) const
268{
269 if( aLayer == UNDEFINED_LAYER )
270 return true;
271
272 if( !IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) ) )
273 return false;
274
275 if( GetAttribute() == PAD_ATTRIB::NPTH && IsCopperLayer( aLayer ) )
276 {
278 {
279 if( GetOffset() == VECTOR2I( 0, 0 ) && GetDrillSize().x >= GetSize().x )
280 return false;
281 }
283 {
284 if( GetOffset() == VECTOR2I( 0, 0 )
285 && GetDrillSize().x >= GetSize().x && GetDrillSize().y >= GetSize().y )
286 {
287 return false;
288 }
289 }
290 }
291
292 if( LSET::FrontBoardTechMask().test( aLayer ) )
293 aLayer = F_Cu;
294 else if( LSET::BackBoardTechMask().test( aLayer ) )
295 aLayer = B_Cu;
296
297 if( GetAttribute() == PAD_ATTRIB::PTH && IsCopperLayer( aLayer ) )
298 {
301 return true;
302
304 return true;
305
306 // Plated through hole pads need copper on the top/bottom layers for proper soldering
307 // Unless the user has removed them in the pad dialog
308 if( m_keepTopBottomLayer && ( aLayer == F_Cu || aLayer == B_Cu ) )
309 return true;
310
311 if( const BOARD* board = GetBoard() )
312 {
313 // Must be static to keep from raising its ugly head in performance profiles
314 static std::initializer_list<KICAD_T> types = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
315 PCB_PAD_T };
316
317 if( m_zoneLayerOverrides[ aLayer ] == ZLO_FORCE_FLASHED )
318 return true;
319 else if( aOnlyCheckIfPermitted )
320 return true;
321 else
322 return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types );
323 }
324 }
325
326 return true;
327}
328
329
331{
332 return KiROUND( std::min( m_size.x, m_size.y ) * m_roundedCornerScale );
333}
334
335
336void PAD::SetRoundRectCornerRadius( double aRadius )
337{
338 int min_r = std::min( m_size.x, m_size.y );
339
340 if( min_r > 0 )
341 SetRoundRectRadiusRatio( aRadius / min_r );
342}
343
344
345void PAD::SetRoundRectRadiusRatio( double aRadiusScale )
346{
347 m_roundedCornerScale = std::max( 0.0, std::min( aRadiusScale, 0.5 ) );
348
349 SetDirty();
350}
351
352
353void PAD::SetChamferRectRatio( double aChamferScale )
354{
355 m_chamferScale = std::max( 0.0, std::min( aChamferScale, 0.5 ) );
356
357 SetDirty();
358}
359
360
361const std::shared_ptr<SHAPE_POLY_SET>& PAD::GetEffectivePolygon() const
362{
363 if( m_polyDirty )
365
366 return m_effectivePolygon;
367}
368
369
370std::shared_ptr<SHAPE> PAD::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING flashPTHPads ) const
371{
372 if( aLayer == Edge_Cuts )
373 {
375 return GetEffectiveHoleShape();
376 else
377 return std::make_shared<SHAPE_NULL>();
378 }
379
381 {
382 bool flash;
383
384 if( flashPTHPads == FLASHING::NEVER_FLASHED )
385 flash = false;
386 else if( flashPTHPads == FLASHING::ALWAYS_FLASHED )
387 flash = true;
388 else
389 flash = FlashLayer( aLayer );
390
391 if( !flash )
392 {
394 return GetEffectiveHoleShape();
395 else
396 return std::make_shared<SHAPE_NULL>();
397 }
398 }
399
400 if( m_shapesDirty )
401 BuildEffectiveShapes( aLayer );
402
403 return m_effectiveShape;
404}
405
406
407std::shared_ptr<SHAPE_SEGMENT> PAD::GetEffectiveHoleShape() const
408{
409 if( m_shapesDirty )
411
413}
414
415
417{
418 if( m_polyDirty )
420
422}
423
424
426{
427 std::lock_guard<std::mutex> RAII_lock( m_shapesBuildingLock );
428
429 // If we had to wait for the lock then we were probably waiting for someone else to
430 // finish rebuilding the shapes. So check to see if they're clean now.
431 if( !m_shapesDirty )
432 return;
433
434 const BOARD* board = GetBoard();
435 int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
436
437 m_effectiveShape = std::make_shared<SHAPE_COMPOUND>();
438 m_effectiveHoleShape = nullptr;
439
440 auto add = [this]( SHAPE* aShape )
441 {
442 m_effectiveShape->AddShape( aShape );
443 };
444
445 VECTOR2I shapePos = ShapePos(); // Fetch only once; rotation involves trig
446 PAD_SHAPE effectiveShape = GetShape();
447
448 if( GetShape() == PAD_SHAPE::CUSTOM )
449 effectiveShape = GetAnchorPadShape();
450
451 switch( effectiveShape )
452 {
454 add( new SHAPE_CIRCLE( shapePos, m_size.x / 2 ) );
455 break;
456
457 case PAD_SHAPE::OVAL:
458 if( m_size.x == m_size.y ) // the oval pad is in fact a circle
459 {
460 add( new SHAPE_CIRCLE( shapePos, m_size.x / 2 ) );
461 }
462 else
463 {
464 VECTOR2I half_size = m_size / 2;
465 int half_width = std::min( half_size.x, half_size.y );
466 VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width );
467 RotatePoint( half_len, m_orient );
468 add( new SHAPE_SEGMENT( shapePos - half_len, shapePos + half_len, half_width * 2 ) );
469 }
470
471 break;
472
473 case PAD_SHAPE::RECT:
476 {
477 int r = ( effectiveShape == PAD_SHAPE::ROUNDRECT ) ? GetRoundRectCornerRadius() : 0;
478 VECTOR2I half_size( m_size.x / 2, m_size.y / 2 );
479 VECTOR2I trap_delta( 0, 0 );
480
481 if( r )
482 {
483 half_size -= VECTOR2I( r, r );
484
485 // Avoid degenerated shapes (0 length segments) that always create issues
486 // For roundrect pad very near a circle, use only a circle
487 const int min_len = pcbIUScale.mmToIU( 0.0001);
488
489 if( half_size.x < min_len && half_size.y < min_len )
490 {
491 add( new SHAPE_CIRCLE( shapePos, r ) );
492 break;
493 }
494 }
495 else if( effectiveShape == PAD_SHAPE::TRAPEZOID )
496 {
497 trap_delta = m_deltaSize / 2;
498 }
499
500 SHAPE_LINE_CHAIN corners;
501
502 corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
503 corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
504 corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
505 corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
506
507 corners.Rotate( m_orient );
508 corners.Move( shapePos );
509
510 // GAL renders rectangles faster than 4-point polygons so it's worth checking if our
511 // body shape is a rectangle.
512 if( corners.PointCount() == 4
513 &&
514 ( ( corners.CPoint( 0 ).y == corners.CPoint( 1 ).y
515 && corners.CPoint( 1 ).x == corners.CPoint( 2 ).x
516 && corners.CPoint( 2 ).y == corners.CPoint( 3 ).y
517 && corners.CPoint( 3 ).x == corners.CPoint( 0 ).x )
518 ||
519 ( corners.CPoint( 0 ).x == corners.CPoint( 1 ).x
520 && corners.CPoint( 1 ).y == corners.CPoint( 2 ).y
521 && corners.CPoint( 2 ).x == corners.CPoint( 3 ).x
522 && corners.CPoint( 3 ).y == corners.CPoint( 0 ).y )
523 )
524 )
525 {
526 int width = std::abs( corners.CPoint( 2 ).x - corners.CPoint( 0 ).x );
527 int height = std::abs( corners.CPoint( 2 ).y - corners.CPoint( 0 ).y );
528 VECTOR2I pos( std::min( corners.CPoint( 2 ).x, corners.CPoint( 0 ).x ),
529 std::min( corners.CPoint( 2 ).y, corners.CPoint( 0 ).y ) );
530
531 add( new SHAPE_RECT( pos, width, height ) );
532 }
533 else
534 {
535 add( new SHAPE_SIMPLE( corners ) );
536 }
537
538 if( r )
539 {
540 add( new SHAPE_SEGMENT( corners.CPoint( 0 ), corners.CPoint( 1 ), r * 2 ) );
541 add( new SHAPE_SEGMENT( corners.CPoint( 1 ), corners.CPoint( 2 ), r * 2 ) );
542 add( new SHAPE_SEGMENT( corners.CPoint( 2 ), corners.CPoint( 3 ), r * 2 ) );
543 add( new SHAPE_SEGMENT( corners.CPoint( 3 ), corners.CPoint( 0 ), r * 2 ) );
544 }
545 }
546 break;
547
549 {
550 SHAPE_POLY_SET outline;
551
554 GetChamferPositions(), 0, maxError, ERROR_INSIDE );
555
556 add( new SHAPE_SIMPLE( outline.COutline( 0 ) ) );
557 }
558 break;
559
560 default:
561 wxFAIL_MSG( wxT( "PAD::buildEffectiveShapes: Unsupported pad shape: " )
562 + PAD_SHAPE_T_asString( effectiveShape ) );
563 break;
564 }
565
566 if( GetShape() == PAD_SHAPE::CUSTOM )
567 {
568 for( const std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives )
569 {
570 for( SHAPE* shape : primitive->MakeEffectiveShapes() )
571 {
572 shape->Rotate( m_orient );
573 shape->Move( shapePos );
574 add( shape );
575 }
576 }
577 }
578
580
581 // Hole shape
582 VECTOR2I half_size = m_drill / 2;
583 int half_width = std::min( half_size.x, half_size.y );
584 VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width );
585
586 RotatePoint( half_len, m_orient );
587
588 m_effectiveHoleShape = std::make_shared<SHAPE_SEGMENT>( m_pos - half_len, m_pos + half_len,
589 half_width * 2 );
591
592 // All done
593 m_shapesDirty = false;
594}
595
596
598{
599 std::lock_guard<std::mutex> RAII_lock( m_polyBuildingLock );
600
601 // If we had to wait for the lock then we were probably waiting for someone else to
602 // finish rebuilding the shapes. So check to see if they're clean now.
603 if( !m_polyDirty )
604 return;
605
606 const BOARD* board = GetBoard();
607 int maxError = board ? board->GetDesignSettings().m_MaxError : ARC_HIGH_DEF;
608
609 // Polygon
610 m_effectivePolygon = std::make_shared<SHAPE_POLY_SET>();
612
613 // Bounding radius
614 //
615 // PADSTACKS TODO: these will both need to cycle through all layers to get the largest
616 // values....
618
619 for( int cnt = 0; cnt < m_effectivePolygon->OutlineCount(); ++cnt )
620 {
621 const SHAPE_LINE_CHAIN& poly = m_effectivePolygon->COutline( cnt );
622
623 for( int ii = 0; ii < poly.PointCount(); ++ii )
624 {
625 int dist = KiROUND( ( poly.CPoint( ii ) - m_pos ).EuclideanNorm() );
627 }
628 }
629
630 // All done
631 m_polyDirty = false;
632}
633
634
636{
637 if( m_shapesDirty )
639
641}
642
643
645{
646 FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
647
648 m_pos = m_pos0;
649
650 if( parentFootprint == nullptr )
651 return;
652
653 RotatePoint( &m_pos.x, &m_pos.y, parentFootprint->GetOrientation() );
654 m_pos += parentFootprint->GetPosition();
655
656 SetDirty();
657}
658
659
661{
662 FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
663
664 if( parentFootprint == nullptr )
665 {
666 m_pos0 = m_pos;
667 return;
668 }
669
670 m_pos0 = m_pos - parentFootprint->GetPosition();
671 RotatePoint( &m_pos0.x, &m_pos0.y, -parentFootprint->GetOrientation() );
672}
673
674
676{
677 m_attribute = aAttribute;
678
679 if( aAttribute == PAD_ATTRIB::SMD )
680 m_drill = VECTOR2I( 0, 0 );
681
682 SetDirty();
683}
684
685
686void PAD::SetProperty( PAD_PROP aProperty )
687{
688 m_property = aProperty;
689
690 SetDirty();
691}
692
693
694void PAD::SetOrientation( const EDA_ANGLE& aAngle )
695{
696 m_orient = aAngle;
698
699 SetDirty();
700}
701
702
703void PAD::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
704{
705 if( aFlipLeftRight )
706 {
707 MIRROR( m_pos.x, aCentre.x );
708 MIRROR( m_pos0.x, 0 );
709 MIRROR( m_offset.x, 0 );
710 MIRROR( m_deltaSize.x, 0 );
711 }
712 else
713 {
714 MIRROR( m_pos.y, aCentre.y );
715 MIRROR( m_pos0.y, 0 );
716 MIRROR( m_offset.y, 0 );
717 MIRROR( m_deltaSize.y, 0 );
718 }
719
721
722 auto mirrorBitFlags = []( int& aBitfield, int a, int b )
723 {
724 bool temp = aBitfield & a;
725
726 if( aBitfield & b )
727 aBitfield |= a;
728 else
729 aBitfield &= ~a;
730
731 if( temp )
732 aBitfield |= b;
733 else
734 aBitfield &= ~b;
735 };
736
737 if( aFlipLeftRight )
738 {
741 }
742 else
743 {
746 }
747
748 // flip pads layers
749 // PADS items are currently on all copper layers, or
750 // currently, only on Front or Back layers.
751 // So the copper layers count is not taken in account
753
754 // Flip the basic shapes, in custom pads
755 FlipPrimitives( aFlipLeftRight );
756
757 SetDirty();
758}
759
760
761void PAD::FlipPrimitives( bool aFlipLeftRight )
762{
763 for( std::shared_ptr<PCB_SHAPE>& primitive : m_editPrimitives )
764 primitive->Flip( VECTOR2I( 0, 0 ), aFlipLeftRight );
765
766 SetDirty();
767}
768
769
771{
772 if( m_offset.x == 0 && m_offset.y == 0 )
773 return m_pos;
774
775 VECTOR2I loc_offset = m_offset;
776
777 RotatePoint( loc_offset, m_orient );
778
779 VECTOR2I shape_pos = m_pos + loc_offset;
780
781 return shape_pos;
782}
783
784
785int PAD::GetLocalClearanceOverrides( wxString* aSource ) const
786{
787 // A pad can have specific clearance that overrides its NETCLASS clearance value
788 if( GetLocalClearance() )
789 return GetLocalClearance( aSource );
790
791 // A footprint can have a specific clearance value
793 return GetParent()->GetLocalClearance( aSource );
794
795 return 0;
796}
797
798
799int PAD::GetLocalClearance( wxString* aSource ) const
800{
801 if( aSource )
802 *aSource = _( "pad" );
803
804 return m_localClearance;
805}
806
807
808int PAD::GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource ) const
809{
811
812 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
813 {
815
817 c = bds.m_DRCEngine->EvalRules( HOLE_CLEARANCE_CONSTRAINT, this, nullptr, aLayer );
818 else
819 c = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, this, nullptr, aLayer );
820 }
821
822 if( c.Value().HasMin() )
823 {
824 if( aSource )
825 *aSource = c.GetName();
826
827 return c.Value().Min();
828 }
829
830 return 0;
831}
832
833
835{
836 // The pad inherits the margin only to calculate a default shape,
837 // therefore only if it is also a copper layer
838 // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
839 // defined by the pad settings only
840 bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
841
842 if( !isOnCopperLayer )
843 return 0;
844
845 int margin = m_localSolderMaskMargin;
846
847 FOOTPRINT* parentFootprint = GetParent();
848
849 if( parentFootprint )
850 {
851 if( margin == 0 )
852 {
853 if( parentFootprint->GetLocalSolderMaskMargin() )
854 margin = parentFootprint->GetLocalSolderMaskMargin();
855 }
856
857 if( margin == 0 )
858 {
859 const BOARD* brd = GetBoard();
860
861 if( brd )
863 }
864 }
865
866 // ensure mask have a size always >= 0
867 if( margin < 0 )
868 {
869 int minsize = -std::min( m_size.x, m_size.y ) / 2;
870
871 if( margin < minsize )
872 margin = minsize;
873 }
874
875 return margin;
876}
877
878
880{
881 // The pad inherits the margin only to calculate a default shape,
882 // therefore only if it is also a copper layer.
883 // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
884 // defined by the pad settings only
885 bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
886
887 if( !isOnCopperLayer )
888 return VECTOR2I( 0, 0 );
889
890 int margin = m_localSolderPasteMargin;
891 double mratio = m_localSolderPasteMarginRatio;
892
893 FOOTPRINT* parentFootprint = GetParent();
894
895 if( parentFootprint )
896 {
897 if( margin == 0 )
898 margin = parentFootprint->GetLocalSolderPasteMargin();
899
900 auto brd = GetBoard();
901
902 if( margin == 0 && brd )
903 margin = brd->GetDesignSettings().m_SolderPasteMargin;
904
905 if( mratio == 0.0 )
906 mratio = parentFootprint->GetLocalSolderPasteMarginRatio();
907
908 if( mratio == 0.0 && brd )
909 {
910 mratio = brd->GetDesignSettings().m_SolderPasteMarginRatio;
911 }
912 }
913
914 VECTOR2I pad_margin;
915 pad_margin.x = margin + KiROUND( m_size.x * mratio );
916 pad_margin.y = margin + KiROUND( m_size.y * mratio );
917
918 // ensure mask have a size always >= 0
919 if( pad_margin.x < -m_size.x / 2 )
920 pad_margin.x = -m_size.x / 2;
921
922 if( pad_margin.y < -m_size.y / 2 )
923 pad_margin.y = -m_size.y / 2;
924
925 return pad_margin;
926}
927
928
930{
932 *aSource = _( "pad" );
933
934 return m_zoneConnection;
935}
936
937
938int PAD::GetLocalSpokeWidthOverride( wxString* aSource ) const
939{
940 if( m_thermalSpokeWidth > 0 && aSource )
941 *aSource = _( "pad" );
942
943 return m_thermalSpokeWidth;
944}
945
946
947int PAD::GetLocalThermalGapOverride( wxString* aSource ) const
948{
949 if( m_thermalGap > 0 && aSource )
950 *aSource = _( "pad" );
951
952 return m_thermalGap;
953}
954
955
956void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
957{
958 wxString msg;
959 FOOTPRINT* parentFootprint = static_cast<FOOTPRINT*>( m_parent );
960
961 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
962 {
963 if( parentFootprint )
964 aList.emplace_back( _( "Footprint" ), parentFootprint->GetReference() );
965 }
966
967 aList.emplace_back( _( "Pad" ), m_number );
968
969 if( !GetPinFunction().IsEmpty() )
970 aList.emplace_back( _( "Pin Name" ), GetPinFunction() );
971
972 if( !GetPinType().IsEmpty() )
973 aList.emplace_back( _( "Pin Type" ), GetPinType() );
974
975 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
976 {
977 aList.emplace_back( _( "Net" ), UnescapeString( GetNetname() ) );
978
979 aList.emplace_back( _( "Resolved Netclass" ),
980 UnescapeString( GetEffectiveNetClass()->GetName() ) );
981
982 if( IsLocked() )
983 aList.emplace_back( _( "Status" ), _( "Locked" ) );
984 }
985
987 aList.emplace_back( _( "Layer" ), layerMaskDescribe() );
988
989 // Show the pad shape, attribute and property
990 wxString props = ShowPadAttr();
991
992 if( GetProperty() != PAD_PROP::NONE )
993 props += ',';
994
995 switch( GetProperty() )
996 {
997 case PAD_PROP::NONE: break;
998 case PAD_PROP::BGA: props += _( "BGA" ); break;
999 case PAD_PROP::FIDUCIAL_GLBL: props += _( "Fiducial global" ); break;
1000 case PAD_PROP::FIDUCIAL_LOCAL: props += _( "Fiducial local" ); break;
1001 case PAD_PROP::TESTPOINT: props += _( "Test point" ); break;
1002 case PAD_PROP::HEATSINK: props += _( "Heat sink" ); break;
1003 case PAD_PROP::CASTELLATED: props += _( "Castellated" ); break;
1004 }
1005
1006 aList.emplace_back( ShowPadShape(), props );
1007
1009 && m_size.x == m_size.y )
1010 {
1011 aList.emplace_back( _( "Diameter" ), aFrame->MessageTextFromValue( m_size.x ) );
1012 }
1013 else
1014 {
1015 aList.emplace_back( _( "Width" ), aFrame->MessageTextFromValue( m_size.x ) );
1016 aList.emplace_back( _( "Height" ), aFrame->MessageTextFromValue( m_size.y ) );
1017 }
1018
1019 EDA_ANGLE fp_orient = parentFootprint ? parentFootprint->GetOrientation() : ANGLE_0;
1020 EDA_ANGLE pad_orient = GetOrientation() - fp_orient;
1021 pad_orient.Normalize180();
1022
1023 if( !fp_orient.IsZero() )
1024 msg.Printf( wxT( "%g(+ %g)" ), pad_orient.AsDegrees(), fp_orient.AsDegrees() );
1025 else
1026 msg.Printf( wxT( "%g" ), GetOrientation().AsDegrees() );
1027
1028 aList.emplace_back( _( "Rotation" ), msg );
1029
1030 if( GetPadToDieLength() )
1031 {
1032 aList.emplace_back( _( "Length in Package" ),
1034 }
1035
1036 if( m_drill.x > 0 || m_drill.y > 0 )
1037 {
1039 {
1040 aList.emplace_back( _( "Hole" ),
1041 wxString::Format( wxT( "%s" ),
1042 aFrame->MessageTextFromValue( m_drill.x ) ) );
1043 }
1044 else
1045 {
1046 aList.emplace_back( _( "Hole X / Y" ),
1047 wxString::Format( wxT( "%s / %s" ),
1048 aFrame->MessageTextFromValue( m_drill.x ),
1049 aFrame->MessageTextFromValue( m_drill.y ) ) );
1050 }
1051 }
1052
1053 wxString source;
1054 int clearance = GetOwnClearance( UNDEFINED_LAYER, &source );
1055
1056 if( !source.IsEmpty() )
1057 {
1058 aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
1059 aFrame->MessageTextFromValue( clearance ) ),
1060 wxString::Format( _( "(from %s)" ),
1061 source ) );
1062 }
1063#if 0
1064 // useful for debug only
1065 aList.emplace_back( wxT( "UUID" ), m_Uuid.AsString() );
1066#endif
1067}
1068
1069
1070bool PAD::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1071{
1072 VECTOR2I delta = aPosition - GetPosition();
1073 int boundingRadius = GetBoundingRadius() + aAccuracy;
1074
1075 if( delta.SquaredEuclideanNorm() > SEG::Square( boundingRadius ) )
1076 return false;
1077
1078 return GetEffectivePolygon()->Contains( aPosition, -1, aAccuracy );
1079}
1080
1081
1082bool PAD::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1083{
1084 BOX2I arect = aRect;
1085 arect.Normalize();
1086 arect.Inflate( aAccuracy );
1087
1088 BOX2I bbox = GetBoundingBox();
1089
1090 if( aContained )
1091 {
1092 return arect.Contains( bbox );
1093 }
1094 else
1095 {
1096 // Fast test: if aRect is outside the polygon bounding box,
1097 // rectangles cannot intersect
1098 if( !arect.Intersects( bbox ) )
1099 return false;
1100
1101 const std::shared_ptr<SHAPE_POLY_SET>& poly = GetEffectivePolygon();
1102
1103 int count = poly->TotalVertices();
1104
1105 for( int ii = 0; ii < count; ii++ )
1106 {
1107 VECTOR2I vertex = poly->CVertex( ii );
1108 VECTOR2I vertexNext = poly->CVertex( ( ii + 1 ) % count );
1109
1110 // Test if the point is within aRect
1111 if( arect.Contains( vertex ) )
1112 return true;
1113
1114 // Test if this edge intersects aRect
1115 if( arect.Intersects( vertex, vertexNext ) )
1116 return true;
1117 }
1118
1119 return false;
1120 }
1121}
1122
1123
1124int PAD::Compare( const PAD* aPadRef, const PAD* aPadCmp )
1125{
1126 int diff;
1127
1128 if( ( diff = static_cast<int>( aPadRef->GetShape() ) -
1129 static_cast<int>( aPadCmp->GetShape() ) ) != 0 )
1130 return diff;
1131
1132 if( ( diff = static_cast<int>( aPadRef->m_attribute ) -
1133 static_cast<int>( aPadCmp->m_attribute ) ) != 0 )
1134 return diff;
1135
1136 if( ( diff = aPadRef->m_drillShape - aPadCmp->m_drillShape ) != 0 )
1137 return diff;
1138
1139 if( ( diff = aPadRef->m_drill.x - aPadCmp->m_drill.x ) != 0 )
1140 return diff;
1141
1142 if( ( diff = aPadRef->m_drill.y - aPadCmp->m_drill.y ) != 0 )
1143 return diff;
1144
1145 if( ( diff = aPadRef->m_size.x - aPadCmp->m_size.x ) != 0 )
1146 return diff;
1147
1148 if( ( diff = aPadRef->m_size.y - aPadCmp->m_size.y ) != 0 )
1149 return diff;
1150
1151 if( ( diff = aPadRef->m_offset.x - aPadCmp->m_offset.x ) != 0 )
1152 return diff;
1153
1154 if( ( diff = aPadRef->m_offset.y - aPadCmp->m_offset.y ) != 0 )
1155 return diff;
1156
1157 if( ( diff = aPadRef->m_deltaSize.x - aPadCmp->m_deltaSize.x ) != 0 )
1158 return diff;
1159
1160 if( ( diff = aPadRef->m_deltaSize.y - aPadCmp->m_deltaSize.y ) != 0 )
1161 return diff;
1162
1163 if( ( diff = aPadRef->m_roundedCornerScale - aPadCmp->m_roundedCornerScale ) != 0 )
1164 return diff;
1165
1166 if( ( diff = aPadRef->m_chamferPositions - aPadCmp->m_chamferPositions ) != 0 )
1167 return diff;
1168
1169 if( ( diff = aPadRef->m_chamferScale - aPadCmp->m_chamferScale ) != 0 )
1170 return diff;
1171
1172 if( ( diff = static_cast<int>( aPadRef->m_editPrimitives.size() ) -
1173 static_cast<int>( aPadCmp->m_editPrimitives.size() ) ) != 0 )
1174 return diff;
1175
1176 // @todo: Compare custom pad primitives for pads that have the same number of primitives
1177 // here. Currently there is no compare function for PCB_SHAPE objects.
1178
1179 // Dick: specctra_export needs this
1180 // Lorenzo: gencad also needs it to implement padstacks!
1181
1182#if __cplusplus >= 201103L
1183 long long d = aPadRef->m_layerMask.to_ullong() - aPadCmp->m_layerMask.to_ullong();
1184
1185 if( d < 0 )
1186 return -1;
1187 else if( d > 0 )
1188 return 1;
1189
1190 return 0;
1191#else
1192 // these strings are not typically constructed, since we don't get here often.
1193 std::string s1 = aPadRef->m_layerMask.to_string();
1194 std::string s2 = aPadCmp->m_layerMask.to_string();
1195 return s1.compare( s2 );
1196#endif
1197}
1198
1199
1200void PAD::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1201{
1202 RotatePoint( m_pos, aRotCentre, aAngle );
1203
1204 m_orient += aAngle;
1206
1207 SetLocalCoord();
1208
1209 SetDirty();
1210}
1211
1212
1213wxString PAD::ShowPadShape() const
1214{
1215 switch( GetShape() )
1216 {
1217 case PAD_SHAPE::CIRCLE: return _( "Circle" );
1218 case PAD_SHAPE::OVAL: return _( "Oval" );
1219 case PAD_SHAPE::RECT: return _( "Rect" );
1220 case PAD_SHAPE::TRAPEZOID: return _( "Trap" );
1221 case PAD_SHAPE::ROUNDRECT: return _( "Roundrect" );
1222 case PAD_SHAPE::CHAMFERED_RECT: return _( "Chamferedrect" );
1223 case PAD_SHAPE::CUSTOM: return _( "CustomShape" );
1224 default: return wxT( "???" );
1225 }
1226}
1227
1228
1229wxString PAD::ShowPadAttr() const
1230{
1231 switch( GetAttribute() )
1232 {
1233 case PAD_ATTRIB::PTH: return _( "PTH" );
1234 case PAD_ATTRIB::SMD: return _( "SMD" );
1235 case PAD_ATTRIB::CONN: return _( "Conn" );
1236 case PAD_ATTRIB::NPTH: return _( "NPTH" );
1237 default: return wxT( "???" );
1238 }
1239}
1240
1241
1242wxString PAD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1243{
1244 if( GetNumber().IsEmpty() )
1245 {
1247 {
1248 return wxString::Format( _( "Pad %s of %s on %s" ),
1249 GetNetnameMsg(),
1250 GetParent()->GetReference(),
1252 }
1253 else if( GetAttribute() == PAD_ATTRIB::NPTH )
1254 {
1255 return wxString::Format( _( "NPTH pad of %s" ), GetParent()->GetReference() );
1256 }
1257 else
1258 {
1259 return wxString::Format( _( "PTH pad %s of %s" ),
1260 GetNetnameMsg(),
1261 GetParent()->GetReference() );
1262 }
1263 }
1264 else
1265 {
1267 {
1268 return wxString::Format( _( "Pad %s %s of %s on %s" ),
1269 GetNumber(),
1270 GetNetnameMsg(),
1271 GetParent()->GetReference(),
1273 }
1274 else if( GetAttribute() == PAD_ATTRIB::NPTH )
1275 {
1276 return wxString::Format( _( "NPTH of %s" ), GetParent()->GetReference() );
1277 }
1278 else
1279 {
1280 return wxString::Format( _( "PTH pad %s %s of %s" ),
1281 GetNumber(),
1282 GetNetnameMsg(),
1283 GetParent()->GetReference() );
1284 }
1285 }
1286}
1287
1288
1290{
1291 return BITMAPS::pad;
1292}
1293
1294
1296{
1297 return new PAD( *this );
1298}
1299
1300
1301void PAD::ViewGetLayers( int aLayers[], int& aCount ) const
1302{
1303 aCount = 0;
1304
1305 // These 2 types of pads contain a hole
1307 {
1308 aLayers[aCount++] = LAYER_PAD_PLATEDHOLES;
1309 aLayers[aCount++] = LAYER_PAD_HOLEWALLS;
1310 }
1311
1313 aLayers[aCount++] = LAYER_NON_PLATEDHOLES;
1314
1315 if( IsOnLayer( F_Cu ) && IsOnLayer( B_Cu ) )
1316 {
1317 // Multi layer pad
1318 aLayers[aCount++] = LAYER_PADS_TH;
1319 aLayers[aCount++] = LAYER_PAD_NETNAMES;
1320 }
1321 else if( IsOnLayer( F_Cu ) )
1322 {
1323 aLayers[aCount++] = LAYER_PAD_FR;
1324
1325 // Is this a PTH pad that has only front copper? If so, we need to also display the
1326 // net name on the PTH netname layer so that it isn't blocked by the drill hole.
1328 aLayers[aCount++] = LAYER_PAD_NETNAMES;
1329 else
1330 aLayers[aCount++] = LAYER_PAD_FR_NETNAMES;
1331 }
1332 else if( IsOnLayer( B_Cu ) )
1333 {
1334 aLayers[aCount++] = LAYER_PAD_BK;
1335
1336 // Is this a PTH pad that has only back copper? If so, we need to also display the
1337 // net name on the PTH netname layer so that it isn't blocked by the drill hole.
1339 aLayers[aCount++] = LAYER_PAD_NETNAMES;
1340 else
1341 aLayers[aCount++] = LAYER_PAD_BK_NETNAMES;
1342 }
1343 else
1344 {
1345 // Internal layers only. (Not yet supported in GUI, but is being used by Python
1346 // footprint generators and will be needed anyway once pad stacks are supported.)
1347 for ( int internal = In1_Cu; internal < In30_Cu; ++internal )
1348 {
1349 if( IsOnLayer( (PCB_LAYER_ID) internal ) )
1350 aLayers[aCount++] = internal;
1351 }
1352 }
1353
1354 // Check non-copper layers. This list should include all the layers that the
1355 // footprint editor allows a pad to be placed on.
1356 static const PCB_LAYER_ID layers_mech[] = { F_Mask, B_Mask, F_Paste, B_Paste,
1358
1359 for( PCB_LAYER_ID each_layer : layers_mech )
1360 {
1361 if( IsOnLayer( each_layer ) )
1362 aLayers[aCount++] = each_layer;
1363 }
1364
1365#ifdef DEBUG
1366 if( aCount == 0 ) // Should not occur
1367 {
1368 wxString msg;
1369 msg.Printf( wxT( "footprint %s, pad %s: could not find valid layer for pad" ),
1370 GetParent() ? GetParent()->GetReference() : wxString( wxT( "<null>" ) ),
1371 GetNumber().IsEmpty() ? wxString(wxT( "(unnumbered)" ) ) : GetNumber() );
1372 wxLogDebug( msg );
1373 }
1374#endif
1375}
1376
1377
1378double PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1379{
1380 constexpr double HIDE = std::numeric_limits<double>::max();
1381
1382 PCB_PAINTER* painter = static_cast<PCB_PAINTER*>( aView->GetPainter() );
1383 PCB_RENDER_SETTINGS* renderSettings = painter->GetSettings();
1384 const BOARD* board = GetBoard();
1385
1386 // Meta control for hiding all pads
1387 if( !aView->IsLayerVisible( LAYER_PADS ) )
1388 return HIDE;
1389
1390 // Handle Render tab switches
1392 && !aView->IsLayerVisible( LAYER_PADS_TH ) )
1393 {
1394 return HIDE;
1395 }
1396
1397 if( !IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
1398 return HIDE;
1399
1400 if( IsFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
1401 return HIDE;
1402
1403 if( IsFrontLayer( (PCB_LAYER_ID) aLayer ) && !aView->IsLayerVisible( LAYER_PAD_FR ) )
1404 return HIDE;
1405
1406 if( IsBackLayer( (PCB_LAYER_ID) aLayer ) && !aView->IsLayerVisible( LAYER_PAD_BK ) )
1407 return HIDE;
1408
1409 LSET visible = board->GetVisibleLayers() & board->GetEnabledLayers();
1410
1411 if( IsHoleLayer( aLayer ) )
1412 {
1413 if( !( visible & LSET::PhysicalLayersMask() ).any() )
1414 return HIDE;
1415 }
1416 else if( IsNetnameLayer( aLayer ) )
1417 {
1418 if( renderSettings->GetHighContrast() )
1419 {
1420 // Hide netnames unless pad is flashed to a high-contrast layer
1421 if( !FlashLayer( renderSettings->GetPrimaryHighContrastLayer() ) )
1422 return HIDE;
1423 }
1424 else
1425 {
1426 // Hide netnames unless pad is flashed to a visible layer
1427 if( !FlashLayer( visible ) )
1428 return HIDE;
1429 }
1430
1431 // Netnames will be shown only if zoom is appropriate
1432 int divisor = std::min( GetBoundingBox().GetWidth(), GetBoundingBox().GetHeight() );
1433
1434 // Pad sizes can be zero briefly when someone is typing a number like "0.5" in the pad
1435 // properties dialog
1436 if( divisor == 0 )
1437 return HIDE;
1438
1439 return ( double ) pcbIUScale.mmToIU( 5 ) / divisor;
1440 }
1441
1442 // Passed all tests; show.
1443 return 0.0;
1444}
1445
1446
1448{
1449 // Bounding box includes soldermask too. Remember mask and/or paste margins can be < 0
1450 int solderMaskMargin = std::max( GetSolderMaskExpansion(), 0 );
1451 VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() );
1452 BOX2I bbox = GetBoundingBox();
1453 int clearance = 0;
1454
1455 // If we're drawing clearance lines then get the biggest possible clearance
1456 if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
1457 {
1458 if( cfg && cfg->m_Display.m_PadClearance && GetBoard() )
1460 }
1461
1462 // Look for the biggest possible bounding box
1463 int xMargin = std::max( solderMaskMargin, solderPasteMargin.x ) + clearance;
1464 int yMargin = std::max( solderMaskMargin, solderPasteMargin.y ) + clearance;
1465
1466 return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ),
1467 VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) );
1468}
1469
1470
1472{
1473 return dyn_cast<FOOTPRINT*>( m_parent );
1474}
1475
1476
1477void PAD::ImportSettingsFrom( const PAD& aMasterPad )
1478{
1479 SetShape( aMasterPad.GetShape() );
1480 SetLayerSet( aMasterPad.GetLayerSet() );
1481 SetAttribute( aMasterPad.GetAttribute() );
1482 SetProperty( aMasterPad.GetProperty() );
1483
1484 // I am not sure the m_LengthPadToDie should be imported, because this is a parameter
1485 // really specific to a given pad (JPC).
1486#if 0
1487 SetPadToDieLength( aMasterPad.GetPadToDieLength() );
1488#endif
1489
1490 // The pad orientation, for historical reasons is the pad rotation + parent rotation.
1491 EDA_ANGLE pad_rot = aMasterPad.GetOrientation();
1492
1493 if( aMasterPad.GetParent() )
1494 pad_rot -= aMasterPad.GetParent()->GetOrientation();
1495
1496 if( GetParent() )
1497 pad_rot += GetParent()->GetOrientation();
1498
1499 SetOrientation( pad_rot );
1500
1502 SetKeepTopBottom( aMasterPad.GetKeepTopBottom() );
1503
1504 SetSize( aMasterPad.GetSize() );
1505 SetDelta( VECTOR2I( 0, 0 ) );
1506 SetOffset( aMasterPad.GetOffset() );
1507 SetDrillSize( aMasterPad.GetDrillSize() );
1508 SetDrillShape( aMasterPad.GetDrillShape() );
1512
1513 switch( aMasterPad.GetShape() )
1514 {
1516 SetDelta( aMasterPad.GetDelta() );
1517 break;
1518
1519 case PAD_SHAPE::CIRCLE:
1520 // ensure size.y == size.x
1521 SetSize( VECTOR2I( GetSize().x, GetSize().x ) );
1522 break;
1523
1524 default:
1525 ;
1526 }
1527
1528 switch( aMasterPad.GetAttribute() )
1529 {
1530 case PAD_ATTRIB::SMD:
1531 case PAD_ATTRIB::CONN:
1532 // These pads do not have a hole (they are expected to be on one external copper layer)
1533 SetDrillSize( VECTOR2I( 0, 0 ) );
1534 break;
1535
1536 default:
1537 ;
1538 }
1539
1540 // copy also local settings:
1541 SetLocalClearance( aMasterPad.GetLocalClearance() );
1545
1546 SetZoneConnection( aMasterPad.GetZoneConnection() );
1549 SetThermalGap( aMasterPad.GetThermalGap() );
1550
1552
1553 // Add or remove custom pad shapes:
1554 ReplacePrimitives( aMasterPad.GetPrimitives() );
1555 SetAnchorPadShape( aMasterPad.GetAnchorPadShape() );
1556
1557 SetDirty();
1558}
1559
1560
1562{
1563 assert( aImage->Type() == PCB_PAD_T );
1564
1565 std::swap( *this, *static_cast<PAD*>( aImage ) );
1566}
1567
1568
1569bool PAD::TransformHoleToPolygon( SHAPE_POLY_SET& aBuffer, int aClearance, int aError,
1570 ERROR_LOC aErrorLoc ) const
1571{
1572 VECTOR2I drillsize = GetDrillSize();
1573
1574 if( !drillsize.x || !drillsize.y )
1575 return false;
1576
1577 std::shared_ptr<SHAPE_SEGMENT> slot = GetEffectiveHoleShape();
1578
1579 TransformOvalToPolygon( aBuffer, slot->GetSeg().A, slot->GetSeg().B,
1580 slot->GetWidth() + aClearance * 2, aError, aErrorLoc );
1581
1582 return true;
1583}
1584
1585
1586void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
1587 int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
1588{
1589 wxASSERT_MSG( !ignoreLineWidth, wxT( "IgnoreLineWidth has no meaning for pads." ) );
1590
1591 // minimal segment count to approximate a circle to create the polygonal pad shape
1592 // This minimal value is mainly for very small pads, like SM0402.
1593 // Most of time pads are using the segment count given by aError value.
1594 const int pad_min_seg_per_circle_count = 16;
1595 int dx = m_size.x / 2;
1596 int dy = m_size.y / 2;
1597
1598 VECTOR2I padShapePos = ShapePos(); // Note: for pad having a shape offset, the pad
1599 // position is NOT the shape position
1600
1601 switch( GetShape() )
1602 {
1603 case PAD_SHAPE::CIRCLE:
1604 case PAD_SHAPE::OVAL:
1605 // Note: dx == dy is not guaranteed for circle pads in legacy boards
1606 if( dx == dy || ( GetShape() == PAD_SHAPE::CIRCLE ) )
1607 {
1608 TransformCircleToPolygon( aBuffer, padShapePos, dx + aClearance, aError, aErrorLoc,
1609 pad_min_seg_per_circle_count );
1610 }
1611 else
1612 {
1613 int half_width = std::min( dx, dy );
1614 VECTOR2I delta( dx - half_width, dy - half_width );
1615
1617
1618 TransformOvalToPolygon( aBuffer, padShapePos - delta, padShapePos + delta,
1619 ( half_width + aClearance ) * 2, aError, aErrorLoc,
1620 pad_min_seg_per_circle_count );
1621 }
1622
1623 break;
1624
1626 case PAD_SHAPE::RECT:
1627 {
1628 int ddx = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.x / 2 : 0;
1629 int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.y / 2 : 0;
1630
1631 SHAPE_POLY_SET outline;
1632 TransformTrapezoidToPolygon( outline, padShapePos, m_size, m_orient, ddx, ddy, aClearance,
1633 aError, aErrorLoc );
1634 aBuffer.Append( outline );
1635 break;
1636 }
1637
1640 {
1641 bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT;
1642
1643 SHAPE_POLY_SET outline;
1646 doChamfer ? GetChamferRectRatio() : 0,
1647 doChamfer ? GetChamferPositions() : 0,
1648 aClearance, aError, aErrorLoc );
1649 aBuffer.Append( outline );
1650 break;
1651 }
1652
1653 case PAD_SHAPE::CUSTOM:
1654 {
1655 SHAPE_POLY_SET outline;
1656 MergePrimitivesAsPolygon( &outline, aErrorLoc );
1657 outline.Rotate( m_orient );
1658 outline.Move( VECTOR2I( m_pos ) );
1659
1660 if( aClearance )
1661 {
1662 int numSegs = std::max( GetArcToSegmentCount( aClearance, aError, FULL_CIRCLE ),
1663 pad_min_seg_per_circle_count );
1664 int clearance = aClearance;
1665
1666 if( aErrorLoc == ERROR_OUTSIDE )
1667 {
1668 int actual_error = CircleToEndSegmentDeltaRadius( clearance, numSegs );
1669 clearance += GetCircleToPolyCorrection( actual_error );
1670 }
1671
1672 outline.Inflate( clearance, numSegs );
1674 }
1675
1676 aBuffer.Append( outline );
1677 break;
1678 }
1679
1680 default:
1681 wxFAIL_MSG( wxT( "PAD::TransformShapeToPolygon no implementation for " )
1683 break;
1684 }
1685}
1686
1687
1689{
1690 if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( m_parent ) )
1691 return fp->GetReference();
1692
1693 return m_parent->m_Uuid.AsString();
1694}
1695
1696
1697static struct PAD_DESC
1698{
1700 {
1702 .Map( PAD_ATTRIB::PTH, _HKI( "Through-hole" ) )
1703 .Map( PAD_ATTRIB::SMD, _HKI( "SMD" ) )
1704 .Map( PAD_ATTRIB::CONN, _HKI( "Edge connector" ) )
1705 .Map( PAD_ATTRIB::NPTH, _HKI( "NPTH, mechanical" ) );
1706
1708 .Map( PAD_SHAPE::CIRCLE, _HKI( "Circle" ) )
1709 .Map( PAD_SHAPE::RECT, _HKI( "Rectangle" ) )
1710 .Map( PAD_SHAPE::OVAL, _HKI( "Oval" ) )
1711 .Map( PAD_SHAPE::TRAPEZOID, _HKI( "Trapezoid" ) )
1712 .Map( PAD_SHAPE::ROUNDRECT, _HKI( "Rounded rectangle" ) )
1713 .Map( PAD_SHAPE::CHAMFERED_RECT, _HKI( "Chamfered rectangle" ) )
1714 .Map( PAD_SHAPE::CUSTOM, _HKI( "Custom" ) );
1715
1717 .Map( PAD_PROP::NONE, _HKI( "None" ) )
1718 .Map( PAD_PROP::BGA, _HKI( "BGA pad" ) )
1719 .Map( PAD_PROP::FIDUCIAL_GLBL, _HKI( "Fiducial, global to board" ) )
1720 .Map( PAD_PROP::FIDUCIAL_LOCAL, _HKI( "Fiducial, local to footprint" ) )
1721 .Map( PAD_PROP::TESTPOINT, _HKI( "Test point pad" ) )
1722 .Map( PAD_PROP::HEATSINK, _HKI( "Heatsink pad" ) )
1723 .Map( PAD_PROP::CASTELLATED, _HKI( "Castellated pad" ) );
1724
1726
1727 if( zcMap.Choices().GetCount() == 0 )
1728 {
1730 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
1731 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
1732 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
1733 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
1734 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
1735 }
1736
1738 REGISTER_TYPE( PAD );
1740
1741 propMgr.Mask( TYPE_HASH( PAD ), TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ) );
1742
1743 propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Orientation" ),
1746
1747 auto isCopperPad =
1748 []( INSPECTABLE* aItem ) -> bool
1749 {
1750 if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
1751 return pad->GetAttribute() != PAD_ATTRIB::NPTH;
1752
1753 return false;
1754 };
1755
1756 auto padCanHaveHole =
1757 []( INSPECTABLE* aItem ) -> bool
1758 {
1759 if( PAD* pad = dynamic_cast<PAD*>( aItem ) )
1760 {
1761 return pad->GetAttribute() == PAD_ATTRIB::PTH
1762 || pad->GetAttribute() == PAD_ATTRIB::NPTH;
1763 }
1764
1765 return false;
1766 };
1767
1769 _HKI( "Net" ), isCopperPad );
1771 _HKI( "Net Class" ), isCopperPad );
1772
1773 const wxString groupPad = _HKI( "Pad Properties" );
1774
1775 auto padType = new PROPERTY_ENUM<PAD, PAD_ATTRIB>( _HKI( "Pad Type" ),
1777 propMgr.AddProperty( padType, groupPad );
1778
1779 auto shape = new PROPERTY_ENUM<PAD, PAD_SHAPE>( _HKI( "Shape" ),
1781 propMgr.AddProperty( shape, groupPad );
1782
1783 propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Parent" ),
1784 NO_SETTER( PAD, wxString ), &PAD::GetParentAsString ), groupPad )
1786
1787 auto padNumber = new PROPERTY<PAD, wxString>( _HKI( "Pad Number" ),
1789 padNumber->SetAvailableFunc( isCopperPad );
1790 propMgr.AddProperty( padNumber, groupPad );
1791
1792 propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pin Name" ),
1793 NO_SETTER( PAD, wxString ), &PAD::GetPinFunction ), groupPad )
1795 propMgr.AddProperty( new PROPERTY<PAD, wxString>( _HKI( "Pin Type" ),
1796 NO_SETTER( PAD, wxString ), &PAD::GetPinType ), groupPad )
1798
1799 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size X" ),
1801 PROPERTY_DISPLAY::PT_SIZE ), groupPad );
1802 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Size Y" ),
1804 PROPERTY_DISPLAY::PT_SIZE ), groupPad );
1805
1806 auto roundRadiusRatio = new PROPERTY<PAD, double>( _HKI( "Round Radius Ratio" ),
1808 roundRadiusRatio->SetAvailableFunc(
1809 [=]( INSPECTABLE* aItem ) -> bool
1810 {
1811 return aItem->Get( shape ) == static_cast<int>( PAD_SHAPE::ROUNDRECT );
1812 } );
1813 propMgr.AddProperty( roundRadiusRatio, groupPad );
1814
1815 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Hole Size X" ),
1817 PROPERTY_DISPLAY::PT_SIZE ), groupPad )
1818 .SetWriteableFunc( padCanHaveHole )
1820
1821 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Hole Size Y" ),
1823 PROPERTY_DISPLAY::PT_SIZE ), groupPad )
1824 .SetWriteableFunc( padCanHaveHole )
1826
1827 propMgr.AddProperty( new PROPERTY_ENUM<PAD, PAD_PROP>( _HKI( "Fabrication Property" ),
1828 &PAD::SetProperty, &PAD::GetProperty ), groupPad );
1829
1830 auto padToDie = new PROPERTY<PAD, int>( _HKI( "Pad To Die Length" ),
1833 padToDie->SetAvailableFunc( isCopperPad );
1834 propMgr.AddProperty( padToDie, groupPad );
1835
1836 const wxString groupOverrides = _HKI( "Overrides" );
1837
1838 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Clearance Override" ),
1840 PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
1841
1842 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Soldermask Margin Override" ),
1844 PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
1845
1846 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Solderpaste Margin Override" ),
1848 PROPERTY_DISPLAY::PT_SIZE ), groupOverrides );
1849
1850 propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Solderpaste Margin Ratio Override" ),
1852 groupOverrides );
1853
1855 _HKI( "Zone Connection Style" ),
1856 &PAD::SetZoneConnection, &PAD::GetZoneConnection ), groupOverrides );
1857
1858 constexpr int minZoneWidth = pcbIUScale.mmToIU( ZONE_THICKNESS_MIN_VALUE_MM );
1859
1860 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Spoke Width" ),
1862 PROPERTY_DISPLAY::PT_SIZE ), groupOverrides )
1863 .SetValidator( PROPERTY_VALIDATORS::RangeIntValidator<minZoneWidth, INT_MAX> );
1864
1865 propMgr.AddProperty( new PROPERTY<PAD, double>( _HKI( "Thermal Relief Spoke Angle" ),
1867 PROPERTY_DISPLAY::PT_DEGREE ), groupOverrides );
1868
1869 propMgr.AddProperty( new PROPERTY<PAD, int>( _HKI( "Thermal Relief Gap" ),
1871 PROPERTY_DISPLAY::PT_SIZE ), groupOverrides )
1873
1874 // TODO delta, drill shape offset, layer set
1875 }
1877
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
@ ZLO_NONE
Definition: board_item.h:58
@ ZLO_FORCE_FLASHED
Definition: board_item.h:59
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:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
PCB_LAYER_ID m_layer
Definition: board_item.h:341
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
BOARD_ITEM_CONTAINER * GetParentFootprint() const
Definition: board_item.cpp:239
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:269
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:601
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
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:149
MINOPTMAX< int > & Value()
Definition: drc_rule.h:142
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:288
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
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:629
static ENUM_MAP< T > & Instance()
Definition: property.h:623
ENUM_MAP & Undefined(T aValue)
Definition: property.h:636
wxPGChoices & Choices()
Definition: property.h:672
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
int GetLocalClearance() const
Definition: footprint.h:230
double GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:244
std::map< wxString, int > MapPadNumbersToNetTieGroups() const
Definition: footprint.cpp:2302
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:200
int GetLocalSolderPasteMargin() const
Definition: footprint.h:241
bool IsNetTie() const
Definition: footprint.h:257
const wxString & GetReference() const
Definition: footprint.h:519
VECTOR2I GetPosition() const override
Definition: footprint.h:188
int GetLocalSolderMaskMargin() const
Definition: footprint.h:227
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:158
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:163
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:257
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
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:60
PAD_DRILL_SHAPE_T m_drillShape
Definition: pad.h:811
int GetLocalClearance(wxString *aSource) const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:799
bool IsAperturePad() const
Definition: pad.h:408
void SetAttribute(PAD_ATTRIB aAttribute)
Definition: pad.cpp:675
int GetOwnClearance(PCB_LAYER_ID aLayer, wxString *aSource=nullptr) const override
Return an item's "own" clearance in internal units.
Definition: pad.cpp:808
void SetLayerSet(LSET aLayers) override
Definition: pad.h:397
int m_localClearance
Definition: pad.h:865
PAD(FOOTPRINT *parent)
Definition: pad.cpp:63
virtual void swapData(BOARD_ITEM *aImage) override
Definition: pad.cpp:1561
PAD_PROP GetProperty() const
Definition: pad.h:404
bool GetRemoveUnconnected() const
Definition: pad.h:610
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: pad.h:384
void SetPinType(const wxString &aType)
Set the pad electrical type.
Definition: pad.h:152
int m_localSolderMaskMargin
Definition: pad.h:866
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:398
CUST_PAD_SHAPE_IN_ZONE m_customShapeClearanceArea
Definition: pad.h:803
int GetSizeX() const
Definition: pad.h:260
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
Definition: pad.cpp:267
VECTOR2I m_size
Definition: pad.h:809
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:956
double m_localSolderPasteMarginRatio
Definition: pad.h:868
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
Definition: pad.cpp:635
VECTOR2I m_drill
Definition: pad.h:808
int GetSolderMaskExpansion() const
Definition: pad.cpp:834
int m_chamferPositions
Definition: pad.h:817
VECTOR2I m_offset
Definition: pad.h:829
int GetDrillSizeY() const
Definition: pad.h:272
const wxString & GetPinType() const
Definition: pad.h:153
const VECTOR2I & GetDrillSize() const
Definition: pad.h:268
PAD_ATTRIB GetAttribute() const
Definition: pad.h:401
void SetLocalSolderPasteMargin(int aMargin)
Definition: pad.h:424
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:196
static int Compare(const PAD *aPadRef, const PAD *aPadCmp)
Compare two pads and return 0 if they are equal.
Definition: pad.cpp:1124
VECTOR2I m_deltaSize
Definition: pad.h:834
ZONE_CONNECTION GetZoneConnection() const
Definition: pad.h:523
void SetRemoveUnconnected(bool aSet)
Set the unconnected removal property.
Definition: pad.h:609
const wxString & GetPinFunction() const
Definition: pad.h:147
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:425
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:1586
std::mutex m_shapesBuildingLock
Definition: pad.h:788
void SetThermalGap(int aGap)
Definition: pad.h:554
bool CanHaveNumber() const
Indicates whether or not the pad can have a number.
Definition: pad.cpp:142
void SetThermalSpokeAngle(const EDA_ANGLE &aAngle)
The orientation of the thermal spokes.
Definition: pad.h:541
wxString m_pinType
Definition: pad.h:773
double m_roundedCornerScale
Definition: pad.h:813
const wxString & GetNumber() const
Definition: pad.h:136
EDA_ANGLE m_orient
Definition: pad.h:845
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:761
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:426
int GetRoundRectCornerRadius() const
Definition: pad.cpp:330
std::vector< std::shared_ptr< PCB_SHAPE > > m_editPrimitives
Definition: pad.h:784
PAD & operator=(const PAD &aOther)
Definition: pad.cpp:122
std::shared_ptr< SHAPE_SEGMENT > m_effectiveHoleShape
Definition: pad.h:791
bool IsOnLayer(PCB_LAYER_ID aLayer, bool aIncludeCourtyards=false) const override
Test to see if this object is on the given layer.
Definition: pad.h:631
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: pad.cpp:1242
bool IsLocked() const override
Definition: pad.cpp:156
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:1569
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: pad.h:383
VECTOR2I GetPosition() const override
Definition: pad.h:203
void SetProperty(PAD_PROP aProperty)
Definition: pad.cpp:686
void SetThermalSpokeAngleDegrees(double aAngle)
Definition: pad.h:545
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:331
EDA_ANGLE GetThermalSpokeAngle() const
Definition: pad.h:542
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:274
PAD_ATTRIB m_attribute
Definition: pad.h:841
PCB_LAYER_ID GetPrincipalLayer() const
Definition: pad.cpp:245
void SetChamferRectRatio(double aChamferScale)
Has meaning only for chamfered rectangular pads.
Definition: pad.cpp:353
void SetDirty()
Definition: pad.h:391
const VECTOR2I & GetOffset() const
Definition: pad.h:275
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
Definition: pad.cpp:217
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pad.cpp:1295
double GetOrientationDegrees() const
Definition: pad.h:378
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pad.cpp:1200
void SetRoundRectCornerRadius(double aRadius)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:336
bool IsNoConnectPad() const
Definition: pad.cpp:182
int GetDrillSizeX() const
Definition: pad.h:270
void SetLocalClearance(int aClearance)
Definition: pad.h:421
PAD_PROP m_property
Definition: pad.h:843
void SetKeepTopBottom(bool aSet)
Set whether we keep the top and bottom connections even if they are not connected.
Definition: pad.h:615
VECTOR2I ShapePos() const
Definition: pad.cpp:770
int m_localSolderPasteMargin
Definition: pad.h:867
void SetNumber(const wxString &aNumber)
Set the pad number (note that it can be alphanumeric, such as the array reference "AA12").
Definition: pad.h:135
int GetLocalThermalGapOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:947
wxString ShowPadAttr() const
Definition: pad.cpp:1229
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: pad.h:522
wxString ShowPadShape() const
Definition: pad.cpp:1213
int m_effectiveBoundingRadius
Definition: pad.h:796
int GetLocalSolderMaskMargin() const
Definition: pad.h:416
LSET m_layerMask
Definition: pad.h:831
bool GetKeepTopBottom() const
Definition: pad.h:616
int m_thermalGap
Definition: pad.h:875
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: pad.h:213
void ImportSettingsFrom(const PAD &aMasterPad)
Import the pad settings from aMasterPad.
Definition: pad.cpp:1477
FOOTPRINT * GetParent() const
Definition: pad.cpp:1471
ZONE_CONNECTION m_zoneConnection
Definition: pad.h:871
void SetDelta(const VECTOR2I &aSize)
Definition: pad.h:264
void SetLocalCoord()
< Set relative coordinates.
Definition: pad.cpp:660
void SetDrillSizeX(const int aX)
Definition: pad.h:269
void SetPosition(const VECTOR2I &aPos) override
Definition: pad.h:197
int m_thermalSpokeWidth
Definition: pad.h:872
VECTOR2I m_pos
Definition: pad.h:775
const VECTOR2I & GetDelta() const
Definition: pad.h:265
static LSET ConnSMDMask()
layer set for a SMD pad on Front layer used for edge board connectors
Definition: pad.cpp:210
void SetDrillSize(const VECTOR2I &aSize)
Definition: pad.h:267
bool IsFreePad() const
Definition: pad.cpp:189
int GetLocalClearance() const
Definition: pad.h:420
PAD_SHAPE GetShape() const
Definition: pad.h:195
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:371
void Flip(const VECTOR2I &VECTOR2I, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: pad.cpp:703
VECTOR2I GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
Definition: pad.cpp:879
static LSET ApertureMask()
layer set for an aperture pad
Definition: pad.cpp:224
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pad.cpp:1447
bool m_shapesDirty
Definition: pad.h:787
std::mutex m_polyBuildingLock
Definition: pad.h:794
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:203
double m_chamferScale
Definition: pad.h:815
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon() const
Definition: pad.cpp:361
int GetLocalClearanceOverrides(wxString *aSource) const override
Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
Definition: pad.cpp:785
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: pad.h:427
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:186
int GetSizeY() const
Definition: pad.h:262
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pad.cpp:239
wxString GetParentAsString() const
Definition: pad.cpp:1688
int GetThermalSpokeWidth() const
Definition: pad.h:532
void SetPinFunction(const wxString &aName)
Set the pad function (pin name in schematic)
Definition: pad.h:146
int GetLocalSolderPasteMargin() const
Definition: pad.h:423
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:1070
void BuildEffectivePolygon() const
Definition: pad.cpp:597
void SetPos0(const VECTOR2I &aPos)
Definition: pad.h:251
int GetBoundingRadius() const
Return the radius of a minimum sized circle which fully encloses this pad.
Definition: pad.cpp:416
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:223
void SetRoundRectRadiusRatio(double aRadiusScale)
Has meaning only for rounded rectangle pads.
Definition: pad.cpp:345
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:234
std::array< ZONE_LAYER_OVERRIDE, MAX_CU_LAYERS > m_zoneLayerOverrides
Definition: pad.h:878
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
Definition: pad.cpp:694
void SetDrawCoord()
Definition: pad.cpp:644
ZONE_CONNECTION GetLocalZoneConnectionOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:929
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: pad.cpp:1289
int GetChamferPositions() const
Definition: pad.h:595
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:1301
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:771
bool m_removeUnconnectedLayer
< If true, the pad copper is removed for layers that are not connected.
Definition: pad.h:850
void SetLocalSolderMaskMargin(int aMargin)
Definition: pad.h:417
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:370
int GetSubRatsnest() const
Definition: pad.h:600
void SetSizeX(const int aX)
Definition: pad.h:259
bool m_keepTopBottomLayer
Definition: pad.h:853
int m_lengthPadToDie
Definition: pad.h:847
void SetThermalSpokeWidth(int aWidth)
Set the width of the thermal spokes connecting the pad to a zone.
Definition: pad.h:531
void SetSize(const VECTOR2I &aSize)
Definition: pad.h:257
void SetDrillSizeY(const int aY)
Definition: pad.h:271
double GetThermalSpokeAngleDegrees() const
Definition: pad.h:549
double GetRoundRectRadiusRatio() const
Definition: pad.h:576
int GetThermalGap() const
Definition: pad.h:555
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
Definition: pad.cpp:407
void SetOrientationDegrees(double aOrientation)
Definition: pad.h:374
const VECTOR2I & GetPos0() const
Definition: pad.h:252
bool SharesNetTieGroup(const PAD *aOther) const
Definition: pad.cpp:165
const VECTOR2I & GetSize() const
Definition: pad.h:258
VECTOR2I m_pos0
Definition: pad.h:838
EDA_ANGLE m_thermalSpokeAngle
Definition: pad.h:873
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: pad.cpp:1378
bool m_polyDirty
Definition: pad.h:793
void SetSubRatsnest(int aSubRatsnest)
Definition: pad.h:601
std::shared_ptr< SHAPE_COMPOUND > m_effectiveShape
Definition: pad.h:790
void SetChamferPositions(int aPositions)
Has meaning only for chamfered rectangular pads.
Definition: pad.h:594
int GetLocalSpokeWidthOverride(wxString *aSource=nullptr) const
Definition: pad.cpp:938
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:208
double GetChamferRectRatio() const
Definition: pad.h:585
void SetPadToDieLength(int aLength)
Definition: pad.h:413
bool IsFlipped() const
Definition: pad.cpp:231
void SetSizeY(const int aY)
Definition: pad.h:261
int GetPadToDieLength() const
Definition: pad.h:414
BOX2I m_effectiveBoundingBox
Definition: pad.h:789
std::shared_ptr< SHAPE_POLY_SET > m_effectivePolygon
Definition: pad.h:795
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:252
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition: property.h:307
PROPERTY_BASE & SetIsHiddenFromLibraryEditors(bool aIsHidden=true)
Definition: property.h:298
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:74
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
static VALIDATOR_RESULT PositiveIntValidator(const wxAny &&aValue, EDA_ITEM *aItem)
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 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:124
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:47
@ HOLE_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:48
#define _(s)
static constexpr EDA_ANGLE & ANGLE_45
Definition: eda_angle.h:430
static constexpr EDA_ANGLE & FULL_CIRCLE
Definition: eda_angle.h:427
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
#define PCB_EDIT_FRAME_NAME
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:901
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:924
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:827
@ 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:991
bool IsHoleLayer(int aLayer)
Definition: layer_ids.h:866
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:122
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
ENUM_TO_WXANY(PAD_ATTRIB)
static struct PAD_DESC _PAD_DESC
@ CUST_PAD_SHAPE_IN_ZONE_OUTLINE
Definition: pad.h:45
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:63
#define NO_SETTER(owner, type)
Definition: property.h:734
@ PT_DEGREE
Angle expressed in degrees.
Definition: property.h:58
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:56
#define REGISTER_TYPE(x)
Definition: property_mgr.h:328
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:1699
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:589
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:49
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper
#define ZONE_THICKNESS_MIN_VALUE_MM
Definition: zones.h:36