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