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