KiCad PCB EDA Suite
footprint.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2015 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <core/mirror.h>
28#include <confirm.h>
29#include <refdes_utils.h>
30#include <bitmaps.h>
31#include <unordered_set>
32#include <string_utils.h>
33#include <pcb_edit_frame.h>
34#include <board.h>
36#include <fp_shape.h>
37#include <macros.h>
38#include <pad.h>
39#include <pcb_marker.h>
40#include <pcb_group.h>
41#include <pcb_track.h>
42#include <pcb_dimension.h>
43#include <pcb_bitmap.h>
44#include <footprint.h>
45#include <zone.h>
46#include <view/view.h>
47#include <i18n_utility.h>
48#include <drc/drc_item.h>
53#include "fp_textbox.h"
55
58 m_boundingBoxCacheTimeStamp( 0 ),
59 m_visibleBBoxCacheTimeStamp( 0 ),
60 m_textExcludedBBoxCacheTimeStamp( 0 ),
61 m_hullCacheTimeStamp( 0 ),
62 m_initial_comments( nullptr ),
63 m_courtyard_cache_timestamp( 0 )
64{
65 m_attributes = 0;
66 m_layer = F_Cu;
69 m_arflag = 0;
70 m_link = 0;
78
79 // These are special and mandatory text fields
82
83 m_3D_Drawings.clear();
84}
85
86
87FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
88 BOARD_ITEM_CONTAINER( aFootprint )
89{
90 m_pos = aFootprint.m_pos;
91 m_fpid = aFootprint.m_fpid;
92 m_attributes = aFootprint.m_attributes;
93 m_fpStatus = aFootprint.m_fpStatus;
94 m_orient = aFootprint.m_orient;
95 m_lastEditTime = aFootprint.m_lastEditTime;
96 m_link = aFootprint.m_link;
97 m_path = aFootprint.m_path;
98
105 m_cachedHull = aFootprint.m_cachedHull;
107
115
116 std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
117
118 // Copy reference and value.
119 m_reference = new FP_TEXT( *aFootprint.m_reference );
120 m_reference->SetParent( this );
121 ptrMap[ aFootprint.m_reference ] = m_reference;
122
123 m_value = new FP_TEXT( *aFootprint.m_value );
124 m_value->SetParent( this );
125 ptrMap[ aFootprint.m_value ] = m_value;
126
127 // Copy pads
128 for( PAD* pad : aFootprint.Pads() )
129 {
130 PAD* newPad = static_cast<PAD*>( pad->Clone() );
131 ptrMap[ pad ] = newPad;
132 Add( newPad, ADD_MODE::APPEND ); // Append to ensure indexes are identical
133 }
134
135 // Copy zones
136 for( FP_ZONE* zone : aFootprint.Zones() )
137 {
138 FP_ZONE* newZone = static_cast<FP_ZONE*>( zone->Clone() );
139 ptrMap[ zone ] = newZone;
140 Add( newZone, ADD_MODE::APPEND ); // Append to ensure indexes are identical
141
142 // Ensure the net info is OK and especially uses the net info list
143 // living in the current board
144 // Needed when copying a fp from fp editor that has its own board
145 // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
146 newZone->SetNetCode( -1 );
147 }
148
149 // Copy drawings
150 for( BOARD_ITEM* item : aFootprint.GraphicalItems() )
151 {
152 BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
153 ptrMap[ item ] = newItem;
154 Add( newItem, ADD_MODE::APPEND ); // Append to ensure indexes are identical
155 }
156
157 // Copy groups
158 for( PCB_GROUP* group : aFootprint.Groups() )
159 {
160 PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
161 ptrMap[ group ] = newGroup;
162 Add( newGroup, ADD_MODE::APPEND ); // Append to ensure indexes are identical
163 }
164
165 // Rebuild groups
166 for( PCB_GROUP* group : aFootprint.Groups() )
167 {
168 PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( ptrMap[ group ] );
169
170 newGroup->GetItems().clear();
171
172 for( BOARD_ITEM* member : group->GetItems() )
173 {
174 if( ptrMap.count( member ) )
175 newGroup->AddItem( ptrMap[ member ] );
176 }
177 }
178
179 // Copy auxiliary data
180 m_3D_Drawings = aFootprint.m_3D_Drawings;
181 m_doc = aFootprint.m_doc;
182 m_keywords = aFootprint.m_keywords;
183 m_properties = aFootprint.m_properties;
184 m_privateLayers = aFootprint.m_privateLayers;
185
186 m_arflag = 0;
187
189 new wxArrayString( *aFootprint.m_initial_comments ) : nullptr;
190}
191
192
194 BOARD_ITEM_CONTAINER( aFootprint )
195{
196 *this = std::move( aFootprint );
197}
198
199
201{
202 // Untangle group parents before doing any deleting
203 for( PCB_GROUP* group : m_fp_groups )
204 {
205 for( BOARD_ITEM* item : group->GetItems() )
206 item->SetParentGroup( nullptr );
207 }
208
209 // Clean up the owned elements
210 delete m_reference;
211 delete m_value;
212 delete m_initial_comments;
213
214 for( PAD* p : m_pads )
215 delete p;
216
217 m_pads.clear();
218
219 for( FP_ZONE* zone : m_fp_zones )
220 delete zone;
221
222 m_fp_zones.clear();
223
224 for( PCB_GROUP* group : m_fp_groups )
225 delete group;
226
227 m_fp_groups.clear();
228
229 for( BOARD_ITEM* d : m_drawings )
230 delete d;
231
232 m_drawings.clear();
233
234 if( BOARD* board = GetBoard() )
235 board->IncrementTimeStamp();
236}
237
238
240{
241 // replace null UUIDs if any by a valid uuid
242 std::vector< BOARD_ITEM* > item_list;
243
244 item_list.push_back( m_reference );
245 item_list.push_back( m_value );
246
247 for( PAD* pad : m_pads )
248 item_list.push_back( pad );
249
250 for( BOARD_ITEM* gr_item : m_drawings )
251 item_list.push_back( gr_item );
252
253 // Note: one cannot fix null UUIDs inside the group, but it should not happen
254 // because null uuids can be found in old footprints, therefore without group
255 for( PCB_GROUP* group : m_fp_groups )
256 item_list.push_back( group );
257
258 // Probably notneeded, because old fp do not have zones. But just in case.
259 for( FP_ZONE* zone : m_fp_zones )
260 item_list.push_back( zone );
261
262 bool changed = false;
263
264 for( BOARD_ITEM* item : item_list )
265 {
266 if( item->m_Uuid == niluuid )
267 {
268 const_cast<KIID&>( item->m_Uuid ) = KIID();
269 changed = true;
270 }
271 }
272
273 return changed;
274}
275
276
278{
279 BOARD_ITEM::operator=( aOther );
280
281 m_pos = aOther.m_pos;
282 m_fpid = aOther.m_fpid;
283 m_attributes = aOther.m_attributes;
284 m_fpStatus = aOther.m_fpStatus;
285 m_orient = aOther.m_orient;
286 m_lastEditTime = aOther.m_lastEditTime;
287 m_link = aOther.m_link;
288 m_path = aOther.m_path;
289
290 m_cachedBoundingBox = aOther.m_cachedBoundingBox;
291 m_boundingBoxCacheTimeStamp = aOther.m_boundingBoxCacheTimeStamp;
292 m_cachedVisibleBBox = aOther.m_cachedVisibleBBox;
293 m_visibleBBoxCacheTimeStamp = aOther.m_visibleBBoxCacheTimeStamp;
294 m_cachedTextExcludedBBox = aOther.m_cachedTextExcludedBBox;
295 m_textExcludedBBoxCacheTimeStamp = aOther.m_textExcludedBBoxCacheTimeStamp;
296 m_cachedHull = aOther.m_cachedHull;
297 m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
298
299 m_localClearance = aOther.m_localClearance;
300 m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
301 m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
302 m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
303 m_zoneConnection = aOther.m_zoneConnection;
304 m_netTiePadGroups = aOther.m_netTiePadGroups;
305
306 // Move reference and value
307 m_reference = aOther.m_reference;
308 m_reference->SetParent( this );
309 m_value = aOther.m_value;
310 m_value->SetParent( this );
311
312
313 // Move the pads
314 m_pads.clear();
315
316 for( PAD* pad : aOther.Pads() )
317 Add( pad );
318
319 aOther.Pads().clear();
320
321 // Move the zones
322 m_fp_zones.clear();
323
324 for( FP_ZONE* item : aOther.Zones() )
325 {
326 Add( item );
327
328 // Ensure the net info is OK and especially uses the net info list
329 // living in the current board
330 // Needed when copying a fp from fp editor that has its own board
331 // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
332 item->SetNetCode( -1 );
333 }
334
335 aOther.Zones().clear();
336
337 // Move the drawings
338 m_drawings.clear();
339
340 for( BOARD_ITEM* item : aOther.GraphicalItems() )
341 Add( item );
342
343 aOther.GraphicalItems().clear();
344
345 // Move the groups
346 m_fp_groups.clear();
347
348 for( PCB_GROUP* group : aOther.Groups() )
349 Add( group );
350
351 aOther.Groups().clear();
352
353 // Copy auxiliary data
354 m_3D_Drawings = aOther.m_3D_Drawings;
355 m_doc = aOther.m_doc;
356 m_keywords = aOther.m_keywords;
357 m_properties = aOther.m_properties;
358 m_privateLayers = aOther.m_privateLayers;
359
360 m_initial_comments = aOther.m_initial_comments;
361
362 // Clear the other item's containers since this is a move
363 aOther.Pads().clear();
364 aOther.Zones().clear();
365 aOther.GraphicalItems().clear();
366 aOther.m_value = nullptr;
367 aOther.m_reference = nullptr;
368 aOther.m_initial_comments = nullptr;
369
370 return *this;
371}
372
373
375{
376 BOARD_ITEM::operator=( aOther );
377
378 m_pos = aOther.m_pos;
379 m_fpid = aOther.m_fpid;
380 m_attributes = aOther.m_attributes;
381 m_fpStatus = aOther.m_fpStatus;
382 m_orient = aOther.m_orient;
384 m_link = aOther.m_link;
385 m_path = aOther.m_path;
386
393 m_cachedHull = aOther.m_cachedHull;
395
402
403 // Copy reference and value
404 *m_reference = *aOther.m_reference;
405 m_reference->SetParent( this );
406 *m_value = *aOther.m_value;
407 m_value->SetParent( this );
408
409 std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
410
411 // Copy pads
412 m_pads.clear();
413
414 for( PAD* pad : aOther.Pads() )
415 {
416 PAD* newPad = new PAD( *pad );
417 ptrMap[ pad ] = newPad;
418 Add( newPad );
419 }
420
421 // Copy zones
422 m_fp_zones.clear();
423
424 for( FP_ZONE* zone : aOther.Zones() )
425 {
426 FP_ZONE* newZone = static_cast<FP_ZONE*>( zone->Clone() );
427 ptrMap[ zone ] = newZone;
428 Add( newZone );
429
430 // Ensure the net info is OK and especially uses the net info list
431 // living in the current board
432 // Needed when copying a fp from fp editor that has its own board
433 // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
434 newZone->SetNetCode( -1 );
435 }
436
437 // Copy drawings
438 m_drawings.clear();
439
440 for( BOARD_ITEM* item : aOther.GraphicalItems() )
441 {
442 BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
443 ptrMap[ item ] = newItem;
444 Add( newItem );
445 }
446
447 // Copy groups
448 m_fp_groups.clear();
449
450 for( PCB_GROUP* group : aOther.Groups() )
451 {
452 PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
453 newGroup->GetItems().clear();
454
455 for( BOARD_ITEM* member : group->GetItems() )
456 newGroup->AddItem( ptrMap[ member ] );
457
458 Add( newGroup );
459 }
460
461 // Copy auxiliary data
463 m_doc = aOther.m_doc;
464 m_keywords = aOther.m_keywords;
465 m_properties = aOther.m_properties;
467
469 new wxArrayString( *aOther.m_initial_comments ) : nullptr;
470
471 return *this;
472}
473
474
476{
477 return HasFlag( COURTYARD_CONFLICT );
478}
479
480
481void FOOTPRINT::GetContextualTextVars( wxArrayString* aVars ) const
482{
483 aVars->push_back( wxT( "REFERENCE" ) );
484 aVars->push_back( wxT( "VALUE" ) );
485 aVars->push_back( wxT( "LAYER" ) );
486 aVars->push_back( wxT( "FOOTPRINT_LIBRARY" ) );
487 aVars->push_back( wxT( "FOOTPRINT_NAME" ) );
488 aVars->push_back( wxT( "NET_NAME(<pad_number>)" ) );
489 aVars->push_back( wxT( "NET_CLASS(<pad_number>)" ) );
490 aVars->push_back( wxT( "PIN_NAME(<pad_number>)" ) );
491}
492
493
494bool FOOTPRINT::ResolveTextVar( wxString* token, int aDepth ) const
495{
496 if( GetBoard() && GetBoard()->GetBoardUse() == BOARD_USE::FPHOLDER )
497 return false;
498
499 if( token->IsSameAs( wxT( "REFERENCE" ) ) )
500 {
501 *token = m_reference->GetShownText( aDepth + 1 );
502 return true;
503 }
504 else if( token->IsSameAs( wxT( "VALUE" ) ) )
505 {
506 *token = m_value->GetShownText( aDepth + 1 );
507 return true;
508 }
509 else if( token->IsSameAs( wxT( "LAYER" ) ) )
510 {
511 *token = GetLayerName();
512 return true;
513 }
514 else if( token->IsSameAs( wxT( "FOOTPRINT_LIBRARY" ) ) )
515 {
516 *token = m_fpid.GetLibNickname();
517 return true;
518 }
519 else if( token->IsSameAs( wxT( "FOOTPRINT_NAME" ) ) )
520 {
521 *token = m_fpid.GetLibItemName();
522 return true;
523 }
524 else if( token->StartsWith( wxT( "NET_NAME(" ) )
525 || token->StartsWith( wxT( "NET_CLASS(" ) )
526 || token->StartsWith( wxT( "PIN_NAME(" ) ) )
527 {
528 wxString padNumber = token->AfterFirst( '(' );
529 padNumber = padNumber.BeforeLast( ')' );
530
531 for( PAD* pad : Pads() )
532 {
533 if( pad->GetNumber() == padNumber )
534 {
535 if( token->StartsWith( wxT( "NET_NAME" ) ) )
536 *token = pad->GetNetname();
537 else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
538 *token = pad->GetNetClassName();
539 else
540 *token = pad->GetPinFunction();
541
542 return true;
543 }
544 }
545 }
546 else if( m_properties.count( *token ) )
547 {
548 *token = m_properties.at( *token );
549 return true;
550 }
551
552 if( GetBoard() && GetBoard()->ResolveTextVar( token, aDepth + 1 ) )
553 return true;
554
555 return false;
556}
557
558
560{
561 // Force the ORPHANED dummy net info for all pads.
562 // ORPHANED dummy net does not depend on a board
563 for( PAD* pad : m_pads )
564 pad->SetNetCode( NETINFO_LIST::ORPHANED );
565}
566
567
568void FOOTPRINT::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
569{
570 switch( aBoardItem->Type() )
571 {
572 case PCB_FP_TEXT_T:
573 // Only user text can be added this way.
574 wxASSERT( static_cast<FP_TEXT*>( aBoardItem )->GetType() == FP_TEXT::TEXT_is_DIVERS );
576
582 case PCB_FP_SHAPE_T:
583 case PCB_FP_TEXTBOX_T:
584 case PCB_BITMAP_T:
585 if( aMode == ADD_MODE::APPEND )
586 m_drawings.push_back( aBoardItem );
587 else
588 m_drawings.push_front( aBoardItem );
589 break;
590
591 case PCB_PAD_T:
592 if( aMode == ADD_MODE::APPEND )
593 m_pads.push_back( static_cast<PAD*>( aBoardItem ) );
594 else
595 m_pads.push_front( static_cast<PAD*>( aBoardItem ) );
596 break;
597
598 case PCB_FP_ZONE_T:
599 if( aMode == ADD_MODE::APPEND )
600 m_fp_zones.push_back( static_cast<FP_ZONE*>( aBoardItem ) );
601 else
602 m_fp_zones.insert( m_fp_zones.begin(), static_cast<FP_ZONE*>( aBoardItem ) );
603 break;
604
605 case PCB_GROUP_T:
606 if( aMode == ADD_MODE::APPEND )
607 m_fp_groups.push_back( static_cast<PCB_GROUP*>( aBoardItem ) );
608 else
609 m_fp_groups.insert( m_fp_groups.begin(), static_cast<PCB_GROUP*>( aBoardItem ) );
610 break;
611
612 default:
613 {
614 wxString msg;
615 msg.Printf( wxT( "FOOTPRINT::Add() needs work: BOARD_ITEM type (%d) not handled" ),
616 aBoardItem->Type() );
617 wxFAIL_MSG( msg );
618
619 return;
620 }
621 }
622
623 aBoardItem->ClearEditFlags();
624 aBoardItem->SetParent( this );
625}
626
627
628void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
629{
630 switch( aBoardItem->Type() )
631 {
632 case PCB_FP_TEXT_T:
633 // Only user text can be removed this way.
634 wxCHECK_RET( static_cast<FP_TEXT*>( aBoardItem )->GetType() == FP_TEXT::TEXT_is_DIVERS,
635 wxT( "Please report this bug: Invalid remove operation on required text" ) );
637
643 case PCB_FP_SHAPE_T:
644 case PCB_FP_TEXTBOX_T:
645 case PCB_BITMAP_T:
646 for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
647 {
648 if( *it == aBoardItem )
649 {
650 m_drawings.erase( it );
651 break;
652 }
653 }
654
655 break;
656
657 case PCB_PAD_T:
658 for( auto it = m_pads.begin(); it != m_pads.end(); ++it )
659 {
660 if( *it == static_cast<PAD*>( aBoardItem ) )
661 {
662 m_pads.erase( it );
663 break;
664 }
665 }
666
667 break;
668
669 case PCB_FP_ZONE_T:
670 for( auto it = m_fp_zones.begin(); it != m_fp_zones.end(); ++it )
671 {
672 if( *it == static_cast<FP_ZONE*>( aBoardItem ) )
673 {
674 m_fp_zones.erase( it );
675 break;
676 }
677 }
678
679 break;
680
681 case PCB_GROUP_T:
682 for( auto it = m_fp_groups.begin(); it != m_fp_groups.end(); ++it )
683 {
684 if( *it == static_cast<PCB_GROUP*>( aBoardItem ) )
685 {
686 m_fp_groups.erase( it );
687 break;
688 }
689 }
690
691 break;
692
693 default:
694 {
695 wxString msg;
696 msg.Printf( wxT( "FOOTPRINT::Remove() needs work: BOARD_ITEM type (%d) not handled" ),
697 aBoardItem->Type() );
698 wxFAIL_MSG( msg );
699 }
700 }
701
702 aBoardItem->SetFlags( STRUCT_DELETED );
703
704 PCB_GROUP* parentGroup = aBoardItem->GetParentGroup();
705
706 if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
707 parentGroup->RemoveItem( aBoardItem );
708}
709
710
711double FOOTPRINT::GetArea( int aPadding ) const
712{
713 BOX2I bbox = GetBoundingBox( false, false );
714
715 double w = std::abs( static_cast<double>( bbox.GetWidth() ) ) + aPadding;
716 double h = std::abs( static_cast<double>( bbox.GetHeight() ) ) + aPadding;
717 return w * h;
718}
719
720
722{
723 int smd_count = 0;
724 int tht_count = 0;
725
726 for( PAD* pad : m_pads )
727 {
728 switch( pad->GetProperty() )
729 {
732 continue;
733
736 continue;
737
738 case PAD_PROP::NONE:
739 case PAD_PROP::BGA:
741 break;
742 }
743
744 switch( pad->GetAttribute() )
745 {
746 case PAD_ATTRIB::PTH:
747 tht_count++;
748 break;
749
750 case PAD_ATTRIB::SMD:
751 if( pad->IsOnCopperLayer() )
752 smd_count++;
753
754 break;
755
756 default:
757 break;
758 }
759 }
760
761 if( smd_count > 0 )
762 return FP_SMD;
763
764 if( tht_count > 0 )
765 return FP_THROUGH_HOLE;
766
767 return 0;
768}
769
770
772{
773 if( ( m_attributes & FP_SMD ) == FP_SMD )
774 return _( "SMD" );
775
777 return _( "Through hole" );
778
779 return _( "Other" );
780}
781
782
784{
785 BOX2I bbox;
786
787 // We want the bounding box of the footprint pads at rot 0, not flipped
788 // Create such a image:
789 FOOTPRINT dummy( *this );
790
791 dummy.SetPosition( VECTOR2I( 0, 0 ) );
792 dummy.SetOrientation( ANGLE_0 );
793
794 if( dummy.IsFlipped() )
795 dummy.Flip( VECTOR2I( 0, 0 ), false );
796
797 for( PAD* pad : dummy.Pads() )
798 bbox.Merge( pad->GetBoundingBox() );
799
800 dummy.SetParent( nullptr );
801
802 return bbox;
803}
804
805
807{
808 return GetBoundingBox( true, true );
809}
810
811
812const BOX2I FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const
813{
814 const BOARD* board = GetBoard();
815 bool isFPEdit = board && board->IsFootprintHolder();
816
817 if( board )
818 {
819 if( aIncludeText && aIncludeInvisibleText )
820 {
822 return m_cachedBoundingBox;
823 }
824 else if( aIncludeText )
825 {
827 return m_cachedVisibleBBox;
828 }
829 else
830 {
833 }
834 }
835
836 BOX2I bbox( m_pos );
837 bbox.Inflate( pcbIUScale.mmToIU( 0.25 ) ); // Give a min size to the bbox
838
839 for( BOARD_ITEM* item : m_drawings )
840 {
841 if( m_privateLayers.test( item->GetLayer() ) && !isFPEdit )
842 continue;
843
844 // We want the bitmap bounding box just in the footprint editor
845 // so it will start with the correct initial zoom
846 if( item->Type() == PCB_BITMAP_T && !isFPEdit )
847 continue;
848
849 // Handle text separately
850 if( item->Type() == PCB_FP_TEXT_T )
851 continue;
852
853 // Treat dimension objects as text
854 if( !aIncludeText
855 && ( item->Type() == PCB_FP_DIM_ALIGNED_T || item->Type() == PCB_FP_DIM_CENTER_T
856 || item->Type() == PCB_FP_DIM_LEADER_T || item->Type() == PCB_FP_DIM_ORTHOGONAL_T
857 || item->Type() == PCB_FP_DIM_RADIAL_T ) )
858 continue;
859
860 bbox.Merge( item->GetBoundingBox() );
861 }
862
863 for( PAD* pad : m_pads )
864 bbox.Merge( pad->GetBoundingBox() );
865
866 for( FP_ZONE* zone : m_fp_zones )
867 bbox.Merge( zone->GetBoundingBox() );
868
869 bool noDrawItems = ( m_drawings.empty() && m_pads.empty() && m_fp_zones.empty() );
870
871 // Groups do not contribute to the rect, only their members
872 if( aIncludeText || noDrawItems )
873 {
874 for( BOARD_ITEM* item : m_drawings )
875 {
876 if( !isFPEdit && m_privateLayers.test( item->GetLayer() ) )
877 continue;
878
879 // Only FP_TEXT items are independently selectable; FP_TEXTBOX items go in with
880 // other graphic items above.
881 if( item->Type() == PCB_FP_TEXT_T )
882 bbox.Merge( item->GetBoundingBox() );
883 }
884
885 // This can be further optimized when aIncludeInvisibleText is true, but currently
886 // leaving this as is until it's determined there is a noticeable speed hit.
887 bool valueLayerIsVisible = true;
888 bool refLayerIsVisible = true;
889
890 if( board )
891 {
892 // The first "&&" conditional handles the user turning layers off as well as layers
893 // not being present in the current PCB stackup. Values, references, and all
894 // footprint text can also be turned off via the GAL meta-layers, so the 2nd and
895 // 3rd "&&" conditionals handle that.
896 valueLayerIsVisible = board->IsLayerVisible( m_value->GetLayer() )
898 && board->IsElementVisible( LAYER_MOD_TEXT );
899
900 refLayerIsVisible = board->IsLayerVisible( m_reference->GetLayer() )
902 && board->IsElementVisible( LAYER_MOD_TEXT );
903 }
904
905
906 if( ( m_value->IsVisible() && valueLayerIsVisible )
907 || aIncludeInvisibleText
908 || noDrawItems )
909 {
910 bbox.Merge( m_value->GetBoundingBox() );
911 }
912
913 if( ( m_reference->IsVisible() && refLayerIsVisible )
914 || aIncludeInvisibleText
915 || noDrawItems )
916 {
918 }
919 }
920
921 if( board )
922 {
923 if( ( aIncludeText && aIncludeInvisibleText ) || noDrawItems )
924 {
926 m_cachedBoundingBox = bbox;
927 }
928 else if( aIncludeText )
929 {
931 m_cachedVisibleBBox = bbox;
932 }
933 else
934 {
937 }
938 }
939
940 return bbox;
941}
942
943
945{
946 const BOARD* board = GetBoard();
947 bool isFPEdit = board && board->IsFootprintHolder();
948
949 if( board )
950 {
951 if( m_hullCacheTimeStamp >= board->GetTimeStamp() )
952 return m_cachedHull;
953 }
954
955 SHAPE_POLY_SET rawPolys;
956 SHAPE_POLY_SET hull;
957
958 for( BOARD_ITEM* item : m_drawings )
959 {
960 if( !isFPEdit && m_privateLayers.test( item->GetLayer() ) )
961 continue;
962
963 if( item->Type() != PCB_FP_TEXT_T && item->Type() != PCB_BITMAP_T )
964 {
965 item->TransformShapeToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
967 }
968
969 // We intentionally exclude footprint text from the bounding hull.
970 }
971
972 for( PAD* pad : m_pads )
973 {
974 pad->TransformShapeToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF, ERROR_OUTSIDE );
975 // In case hole is larger than pad
976 pad->TransformHoleToPolygon( rawPolys, 0, ARC_LOW_DEF, ERROR_OUTSIDE );
977 }
978
979 for( FP_ZONE* zone : m_fp_zones )
980 {
981 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
982 {
983 const SHAPE_POLY_SET& layerPoly = *zone->GetFilledPolysList( layer );
984
985 for( int ii = 0; ii < layerPoly.OutlineCount(); ii++ )
986 {
987 const SHAPE_LINE_CHAIN& poly = layerPoly.COutline( ii );
988 rawPolys.AddOutline( poly );
989 }
990 }
991 }
992
993 // If there are some graphic items, build the actual hull.
994 // However if no items, create a minimal polygon (can happen if a footprint
995 // is created with no item: it contains only 2 texts.
996 if( rawPolys.OutlineCount() == 0 )
997 {
998 // generate a small dummy rectangular outline around the anchor
999 const int halfsize = pcbIUScale.mmToIU( 1.0 );
1000
1001 rawPolys.NewOutline();
1002
1003 // add a square:
1004 rawPolys.Append( GetPosition().x - halfsize, GetPosition().y - halfsize );
1005 rawPolys.Append( GetPosition().x + halfsize, GetPosition().y - halfsize );
1006 rawPolys.Append( GetPosition().x + halfsize, GetPosition().y + halfsize );
1007 rawPolys.Append( GetPosition().x - halfsize, GetPosition().y + halfsize );
1008 }
1009
1010 std::vector<VECTOR2I> convex_hull;
1011 BuildConvexHull( convex_hull, rawPolys );
1012
1015
1016 for( const VECTOR2I& pt : convex_hull )
1017 m_cachedHull.Append( pt );
1018
1019 if( board )
1021
1022 return m_cachedHull;
1023}
1024
1025
1026void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1027{
1028 wxString msg, msg2;
1029
1030 aList.emplace_back( m_reference->GetShownText(), m_value->GetShownText() );
1031
1032 if( aFrame->IsType( FRAME_FOOTPRINT_VIEWER )
1034 || aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) )
1035 {
1036 size_t padCount = GetPadCount( DO_NOT_INCLUDE_NPTH );
1037
1038 aList.emplace_back( _( "Library" ), GetFPID().GetLibNickname().wx_str() );
1039
1040 aList.emplace_back( _( "Footprint Name" ), GetFPID().GetLibItemName().wx_str() );
1041
1042 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%zu" ), padCount ) );
1043
1044 aList.emplace_back( wxString::Format( _( "Doc: %s" ), GetDescription() ),
1045 wxString::Format( _( "Keywords: %s" ), GetKeywords() ) );
1046
1047 return;
1048 }
1049
1050 // aFrame is the board editor:
1051 aList.emplace_back( _( "Board Side" ), IsFlipped() ? _( "Back (Flipped)" ) : _( "Front" ) );
1052
1053 auto addToken = []( wxString* aStr, const wxString& aAttr )
1054 {
1055 if( !aStr->IsEmpty() )
1056 *aStr += wxT( ", " );
1057
1058 *aStr += aAttr;
1059 };
1060
1061 wxString status;
1062 wxString attrs;
1063
1064 if( IsLocked() )
1065 addToken( &status, _( "Locked" ) );
1066
1067 if( m_fpStatus & FP_is_PLACED )
1068 addToken( &status, _( "autoplaced" ) );
1069
1071 addToken( &attrs, _( "not in schematic" ) );
1072
1074 addToken( &attrs, _( "exclude from pos files" ) );
1075
1077 addToken( &attrs, _( "exclude from BOM" ) );
1078
1079 aList.emplace_back( _( "Status: " ) + status, _( "Attributes:" ) + wxS( " " ) + attrs );
1080
1081 aList.emplace_back( _( "Rotation" ), wxString::Format( wxT( "%.4g" ),
1082 GetOrientation().AsDegrees() ) );
1083
1084 msg.Printf( _( "Footprint: %s" ), m_fpid.GetUniStringLibId() );
1085 msg2.Printf( _( "3D-Shape: %s" ), m_3D_Drawings.empty() ? _( "<none>" )
1086 : m_3D_Drawings.front().m_Filename );
1087 aList.emplace_back( msg, msg2 );
1088
1089 msg.Printf( _( "Doc: %s" ), m_doc );
1090 msg2.Printf( _( "Keywords: %s" ), m_keywords );
1091 aList.emplace_back( msg, msg2 );
1092}
1093
1094
1095bool FOOTPRINT::IsOnLayer( PCB_LAYER_ID aLayer, bool aIncludeCourtyards ) const
1096{
1097 static const LSET courtyardLayers( 2, B_CrtYd, F_CrtYd );
1098
1099 if( aIncludeCourtyards && courtyardLayers[aLayer] )
1100 return !GetCourtyard( aLayer ).IsEmpty();
1101
1102 // If we have any pads, fall back on normal checking
1103 if( !m_pads.empty() )
1104 return m_layer == aLayer;
1105
1106 // No pads? Check if this entire footprint exists on the given layer
1107 for( FP_ZONE* zone : m_fp_zones )
1108 {
1109 if( !zone->IsOnLayer( aLayer ) )
1110 return false;
1111 }
1112
1113 for( BOARD_ITEM* item : m_drawings )
1114 {
1115 if( !item->IsOnLayer( aLayer ) )
1116 return false;
1117 }
1118
1119 return true;
1120}
1121
1122
1123bool FOOTPRINT::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
1124{
1125 BOX2I rect = GetBoundingBox( false, false );
1126 return rect.Inflate( aAccuracy ).Contains( aPosition );
1127}
1128
1129
1130bool FOOTPRINT::HitTestAccurate( const VECTOR2I& aPosition, int aAccuracy ) const
1131{
1132 return GetBoundingHull().Collide( aPosition, aAccuracy );
1133}
1134
1135
1136bool FOOTPRINT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
1137{
1138 BOX2I arect = aRect;
1139 arect.Inflate( aAccuracy );
1140
1141 if( aContained )
1142 {
1143 return arect.Contains( GetBoundingBox( false, false ) );
1144 }
1145 else
1146 {
1147 // If the rect does not intersect the bounding box, skip any tests
1148 if( !aRect.Intersects( GetBoundingBox( false, false ) ) )
1149 return false;
1150
1151 // The empty footprint dummy rectangle intersects the selection area.
1152 if( m_pads.empty() && m_fp_zones.empty() && m_drawings.empty() )
1153 return GetBoundingBox( true, false ).Intersects( arect );
1154
1155 // Determine if any elements in the FOOTPRINT intersect the rect
1156 for( PAD* pad : m_pads )
1157 {
1158 if( pad->HitTest( arect, false, 0 ) )
1159 return true;
1160 }
1161
1162 for( FP_ZONE* zone : m_fp_zones )
1163 {
1164 if( zone->HitTest( arect, false, 0 ) )
1165 return true;
1166 }
1167
1168 for( BOARD_ITEM* item : m_drawings )
1169 {
1170 // Text items are selectable on their own, and are therefore excluded from this
1171 // test. TextBox items are NOT selectable on their own, and so MUST be included
1172 // here. Bitmaps aren't selectable since they aren't displayed.
1173 if( item->Type() != PCB_FP_TEXT_T && item->Type() != PCB_FP_TEXT_T
1174 && item->HitTest( arect, false, 0 ) )
1175 {
1176 return true;
1177 }
1178 }
1179
1180 // Groups are not hit-tested; only their members
1181
1182 // No items were hit
1183 return false;
1184 }
1185}
1186
1187
1188PAD* FOOTPRINT::FindPadByNumber( const wxString& aPadNumber, PAD* aSearchAfterMe ) const
1189{
1190 bool can_select = aSearchAfterMe ? false : true;
1191
1192 for( PAD* pad : m_pads )
1193 {
1194 if( !can_select && pad == aSearchAfterMe )
1195 {
1196 can_select = true;
1197 continue;
1198 }
1199
1200 if( can_select && pad->GetNumber() == aPadNumber )
1201 return pad;
1202 }
1203
1204 return nullptr;
1205}
1206
1207
1208PAD* FOOTPRINT::GetPad( const VECTOR2I& aPosition, LSET aLayerMask )
1209{
1210 for( PAD* pad : m_pads )
1211 {
1212 // ... and on the correct layer.
1213 if( !( pad->GetLayerSet() & aLayerMask ).any() )
1214 continue;
1215
1216 if( pad->HitTest( aPosition ) )
1217 return pad;
1218 }
1219
1220 return nullptr;
1221}
1222
1223
1224unsigned FOOTPRINT::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
1225{
1226 if( aIncludeNPTH )
1227 return m_pads.size();
1228
1229 unsigned cnt = 0;
1230
1231 for( PAD* pad : m_pads )
1232 {
1233 if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
1234 continue;
1235
1236 cnt++;
1237 }
1238
1239 return cnt;
1240}
1241
1242
1243unsigned FOOTPRINT::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
1244{
1245 std::set<wxString> usedNumbers;
1246
1247 // Create a set of used pad numbers
1248 for( PAD* pad : m_pads )
1249 {
1250 // Skip pads not on copper layers (used to build complex
1251 // solder paste shapes for instance)
1252 if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() )
1253 continue;
1254
1255 // Skip pads with no name, because they are usually "mechanical"
1256 // pads, not "electrical" pads
1257 if( pad->GetNumber().IsEmpty() )
1258 continue;
1259
1260 if( !aIncludeNPTH )
1261 {
1262 // skip NPTH
1263 if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
1264 continue;
1265 }
1266
1267 usedNumbers.insert( pad->GetNumber() );
1268 }
1269
1270 return usedNumbers.size();
1271}
1272
1273
1275{
1276 if( nullptr == a3DModel )
1277 return;
1278
1279 if( !a3DModel->m_Filename.empty() )
1280 m_3D_Drawings.push_back( *a3DModel );
1281}
1282
1283
1284// see footprint.h
1285INSPECT_RESULT FOOTPRINT::Visit( INSPECTOR inspector, void* testData,
1286 const std::vector<KICAD_T>& aScanTypes )
1287{
1288#if 0 && defined(DEBUG)
1289 std::cout << GetClass().mb_str() << ' ';
1290#endif
1291
1292 bool drawingsScanned = false;
1293
1294 for( KICAD_T scanType : aScanTypes )
1295 {
1296 switch( scanType )
1297 {
1298 case PCB_FOOTPRINT_T:
1299 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
1300 return INSPECT_RESULT::QUIT;
1301
1302 break;
1303
1304 case PCB_PAD_T:
1305 if( IterateForward<PAD*>( m_pads, inspector, testData, { scanType } )
1307 {
1308 return INSPECT_RESULT::QUIT;
1309 }
1310
1311 break;
1312
1313 case PCB_FP_ZONE_T:
1314 if( IterateForward<FP_ZONE*>( m_fp_zones, inspector, testData, { scanType } )
1316 {
1317 return INSPECT_RESULT::QUIT;
1318 }
1319
1320 break;
1321
1322 case PCB_FP_TEXT_T:
1323 if( inspector( m_reference, testData ) == INSPECT_RESULT::QUIT )
1324 return INSPECT_RESULT::QUIT;
1325
1326 if( inspector( m_value, testData ) == INSPECT_RESULT::QUIT )
1327 return INSPECT_RESULT::QUIT;
1328
1329 // Intentionally fall through since m_Drawings can hold PCB_FP_TEXT_T also
1331
1337 case PCB_FP_SHAPE_T:
1338 case PCB_FP_TEXTBOX_T:
1339 if( !drawingsScanned )
1340 {
1341 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, aScanTypes )
1343 {
1344 return INSPECT_RESULT::QUIT;
1345 }
1346
1347 drawingsScanned = true;
1348 }
1349
1350 break;
1351
1352 case PCB_GROUP_T:
1353 if( IterateForward<PCB_GROUP*>( m_fp_groups, inspector, testData, { scanType } )
1355 {
1356 return INSPECT_RESULT::QUIT;
1357 }
1358
1359 break;
1360
1361 default:
1362 break;
1363 }
1364 }
1365
1367}
1368
1369
1370wxString FOOTPRINT::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1371{
1372 wxString reference = GetReference();
1373
1374 if( reference.IsEmpty() )
1375 reference = _( "<no reference designator>" );
1376
1377 return wxString::Format( _( "Footprint %s" ), reference );
1378}
1379
1380
1382{
1383 return BITMAPS::module;
1384}
1385
1386
1388{
1389 return new FOOTPRINT( *this );
1390}
1391
1392
1393void FOOTPRINT::RunOnChildren( const std::function<void ( BOARD_ITEM*)>& aFunction ) const
1394{
1395 try
1396 {
1397 for( PAD* pad : m_pads )
1398 aFunction( static_cast<BOARD_ITEM*>( pad ) );
1399
1400 for( FP_ZONE* zone : m_fp_zones )
1401 aFunction( static_cast<FP_ZONE*>( zone ) );
1402
1403 for( PCB_GROUP* group : m_fp_groups )
1404 aFunction( static_cast<PCB_GROUP*>( group ) );
1405
1406 for( BOARD_ITEM* drawing : m_drawings )
1407 aFunction( static_cast<BOARD_ITEM*>( drawing ) );
1408
1409 aFunction( static_cast<BOARD_ITEM*>( m_reference ) );
1410 aFunction( static_cast<BOARD_ITEM*>( m_value ) );
1411 }
1412 catch( std::bad_function_call& )
1413 {
1414 wxFAIL_MSG( wxT( "Error running FOOTPRINT::RunOnChildren" ) );
1415 }
1416}
1417
1418
1419void FOOTPRINT::ViewGetLayers( int aLayers[], int& aCount ) const
1420{
1421 aCount = 2;
1422 aLayers[0] = LAYER_ANCHOR;
1423
1424 switch( m_layer )
1425 {
1426 default:
1427 wxASSERT_MSG( false, wxT( "Illegal layer" ) ); // do you really have footprints placed
1428 // on other layers?
1430
1431 case F_Cu:
1432 aLayers[1] = LAYER_MOD_FR;
1433 break;
1434
1435 case B_Cu:
1436 aLayers[1] = LAYER_MOD_BK;
1437 break;
1438 }
1439
1440 if( IsLocked() )
1441 aLayers[ aCount++ ] = LAYER_LOCKED_ITEM_SHADOW;
1442
1443 if( IsConflicting() )
1444 aLayers[ aCount++ ] = LAYER_CONFLICTS_SHADOW;
1445
1446 // If there are no pads, and only drawings on a silkscreen layer, then report the silkscreen
1447 // layer as well so that the component can be edited with the silkscreen layer
1448 bool f_silk = false, b_silk = false, non_silk = false;
1449
1450 for( BOARD_ITEM* item : m_drawings )
1451 {
1452 if( item->GetLayer() == F_SilkS )
1453 f_silk = true;
1454 else if( item->GetLayer() == B_SilkS )
1455 b_silk = true;
1456 else
1457 non_silk = true;
1458 }
1459
1460 if( ( f_silk || b_silk ) && !non_silk && m_pads.empty() )
1461 {
1462 if( f_silk )
1463 aLayers[ aCount++ ] = F_SilkS;
1464
1465 if( b_silk )
1466 aLayers[ aCount++ ] = B_SilkS;
1467 }
1468}
1469
1470
1471double FOOTPRINT::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1472{
1473 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
1474 {
1475 // The locked shadow shape is shown only if the footprint itself is visible
1476 if( ( m_layer == F_Cu ) && aView->IsLayerVisible( LAYER_MOD_FR ) )
1477 return 0.0;
1478
1479 if( ( m_layer == B_Cu ) && aView->IsLayerVisible( LAYER_MOD_BK ) )
1480 return 0.0;
1481
1482 return std::numeric_limits<double>::max();
1483 }
1484
1485 if( aLayer == LAYER_CONFLICTS_SHADOW && IsConflicting() )
1486 {
1487 // The locked shadow shape is shown only if the footprint itself is visible
1488 if( ( m_layer == F_Cu ) && aView->IsLayerVisible( LAYER_MOD_FR ) )
1489 return 0.0;
1490
1491 if( ( m_layer == B_Cu ) && aView->IsLayerVisible( LAYER_MOD_BK ) )
1492 return 0.0;
1493
1494 return std::numeric_limits<double>::max();
1495 }
1496
1497 int layer = ( m_layer == F_Cu ) ? LAYER_MOD_FR :
1499
1500 // Currently this is only pertinent for the anchor layer; everything else is drawn from the
1501 // children.
1502 // The "good" value is experimentally chosen.
1503 #define MINIMAL_ZOOM_LEVEL_FOR_VISIBILITY 1.5
1504
1505 if( aView->IsLayerVisible( layer ) )
1507
1508 return std::numeric_limits<double>::max();
1509}
1510
1511
1513{
1514 BOX2I area = GetBoundingBox( true, true );
1515
1516 // Add the Clearance shape size: (shape around the pads when the clearance is shown. Not
1517 // optimized, but the draw cost is small (perhaps smaller than optimization).
1518 const BOARD* board = GetBoard();
1519
1520 if( board )
1521 {
1522 int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
1523 area.Inflate( biggest_clearance );
1524 }
1525
1526 return area;
1527}
1528
1529
1530bool FOOTPRINT::IsLibNameValid( const wxString & aName )
1531{
1532 const wxChar * invalids = StringLibNameInvalidChars( false );
1533
1534 if( aName.find_first_of( invalids ) != std::string::npos )
1535 return false;
1536
1537 return true;
1538}
1539
1540
1541const wxChar* FOOTPRINT::StringLibNameInvalidChars( bool aUserReadable )
1542{
1543 // This list of characters is also duplicated in validators.cpp and
1544 // lib_id.cpp
1545 // TODO: Unify forbidden character lists - Warning, invalid filename characters are not the same
1546 // as invalid LIB_ID characters. We will need to separate the FP filenames from FP names before this
1547 // can be unified
1548 static const wxChar invalidChars[] = wxT("%$<>\t\n\r\"\\/:");
1549 static const wxChar invalidCharsReadable[] = wxT("% $ < > 'tab' 'return' 'line feed' \\ \" / :");
1550
1551 if( aUserReadable )
1552 return invalidCharsReadable;
1553 else
1554 return invalidChars;
1555}
1556
1557
1558void FOOTPRINT::Move( const VECTOR2I& aMoveVector )
1559{
1560 VECTOR2I newpos = m_pos + aMoveVector;
1561 SetPosition( newpos );
1562}
1563
1564
1565void FOOTPRINT::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1566{
1567 EDA_ANGLE orientation = GetOrientation();
1568 EDA_ANGLE newOrientation = orientation + aAngle;
1569 VECTOR2I newpos = m_pos;
1570 RotatePoint( newpos, aRotCentre, aAngle );
1571 SetPosition( newpos );
1572 SetOrientation( newOrientation );
1573
1574 m_reference->KeepUpright( orientation, newOrientation );
1575 m_value->KeepUpright( orientation, newOrientation );
1576
1577 for( BOARD_ITEM* item : m_drawings )
1578 {
1579 if( item->Type() == PCB_FP_TEXT_T )
1580 static_cast<FP_TEXT*>( item )->KeepUpright( orientation, newOrientation );
1581 }
1582
1588}
1589
1590
1592{
1593 wxASSERT( aLayer == F_Cu || aLayer == B_Cu );
1594
1595 if( aLayer != GetLayer() )
1596 Flip( GetPosition(), true );
1597}
1598
1599
1600void FOOTPRINT::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
1601{
1602 // Move footprint to its final position:
1603 VECTOR2I finalPos = m_pos;
1604
1605 // Now Flip the footprint.
1606 // Flipping a footprint is a specific transform: it is not mirrored like a text.
1607 // We have to change the side, and ensure the footprint rotation is modified according to the
1608 // transform, because this parameter is used in pick and place files, and when updating the
1609 // footprint from library.
1610 // When flipped around the X axis (Y coordinates changed) orientation is negated
1611 // When flipped around the Y axis (X coordinates changed) orientation is 180 - old orient.
1612 // Because it is specific to a footprint, we flip around the X axis, and after rotate 180 deg
1613
1614 MIRROR( finalPos.y, aCentre.y );
1615
1616 SetPosition( finalPos );
1617
1618 // Flip layer
1620
1621 // Reverse mirror orientation.
1622 m_orient = -m_orient;
1624
1625 // Mirror pads to other side of board.
1626 for( PAD* pad : m_pads )
1627 pad->Flip( m_pos, false );
1628
1629 // Mirror zones to other side of board.
1630 for( ZONE* zone : m_fp_zones )
1631 zone->Flip( m_pos, false );
1632
1633 // Mirror reference and value.
1634 m_reference->Flip( m_pos, false );
1635 m_value->Flip( m_pos, false );
1636
1637 // Reverse mirror footprint graphics and texts.
1638 for( BOARD_ITEM* item : m_drawings )
1639 {
1640 switch( item->Type() )
1641 {
1642 case PCB_FP_SHAPE_T:
1643 static_cast<FP_SHAPE*>( item )->Flip( m_pos, false );
1644 break;
1645
1646 case PCB_FP_TEXT_T:
1647 static_cast<FP_TEXT*>( item )->Flip( m_pos, false );
1648 break;
1649
1650 case PCB_FP_TEXTBOX_T:
1651 static_cast<FP_TEXTBOX*>( item )->Flip( m_pos, false );
1652 break;
1653
1654 case PCB_BITMAP_T:
1655 static_cast<PCB_BITMAP*>( item )->Flip( m_pos, false );
1656 break;
1657
1663 static_cast<PCB_DIMENSION_BASE*>( item )->Flip( m_pos, false );
1664 break;
1665
1666 default:
1667 wxMessageBox( wxString::Format( wxT( "FOOTPRINT::Flip() error: Unknown Draw Type %d" ),
1668 (int)item->Type() ) );
1669 break;
1670 }
1671 }
1672
1673 // Now rotate 180 deg if required
1674 if( aFlipLeftRight )
1675 Rotate( aCentre, ANGLE_180 );
1676
1681
1682 m_cachedHull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
1683
1685}
1686
1687
1689{
1690 VECTOR2I delta = aPos - m_pos;
1691
1692 m_pos += delta;
1693
1694 m_reference->EDA_TEXT::Offset( delta );
1695 m_value->EDA_TEXT::Offset( delta );
1696
1697 for( PAD* pad : m_pads )
1698 pad->SetPosition( pad->GetPosition() + delta );
1699
1700 for( ZONE* zone : m_fp_zones )
1701 zone->Move( delta );
1702
1703 for( BOARD_ITEM* item : m_drawings )
1704 {
1705 switch( item->Type() )
1706 {
1707 case PCB_FP_SHAPE_T:
1708 case PCB_FP_TEXTBOX_T:
1709 {
1710 FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
1711 shape->SetDrawCoord();
1712 break;
1713 }
1714
1715 case PCB_FP_TEXT_T:
1716 {
1717 FP_TEXT* text = static_cast<FP_TEXT*>( item );
1718 text->EDA_TEXT::Offset( delta );
1719 break;
1720 }
1721
1727 case PCB_BITMAP_T:
1728 item->Move( delta );
1729 break;
1730
1731 default:
1732 wxMessageBox( wxT( "Draw type undefined." ) );
1733 break;
1734 }
1735 }
1736
1743}
1744
1745
1746void FOOTPRINT::MoveAnchorPosition( const VECTOR2I& aMoveVector )
1747{
1748 /*
1749 * Move the reference point of the footprint
1750 * the footprints elements (pads, outlines, edges .. ) are moved
1751 * but:
1752 * - the footprint position is not modified.
1753 * - the relative (local) coordinates of these items are modified
1754 * - Draw coordinates are updated
1755 */
1756
1757 // Update (move) the relative coordinates relative to the new anchor point.
1758 VECTOR2I moveVector = aMoveVector;
1759 RotatePoint( moveVector, -GetOrientation() );
1760
1761 // Update of the reference and value.
1762 m_reference->SetPos0( m_reference->GetPos0() + moveVector );
1764 m_value->SetPos0( m_value->GetPos0() + moveVector );
1766
1767 // Update the pad local coordinates.
1768 for( PAD* pad : m_pads )
1769 {
1770 pad->SetPos0( pad->GetPos0() + moveVector );
1771 pad->SetDrawCoord();
1772 }
1773
1774 // Update the draw element coordinates.
1775 for( BOARD_ITEM* item : GraphicalItems() )
1776 {
1777 switch( item->Type() )
1778 {
1779 case PCB_FP_SHAPE_T:
1780 case PCB_FP_TEXTBOX_T:
1781 {
1782 FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
1783 shape->Move( moveVector );
1784 break;
1785 }
1786
1787 case PCB_FP_TEXT_T:
1788 {
1789 FP_TEXT* text = static_cast<FP_TEXT*>( item );
1790 text->SetPos0( text->GetPos0() + moveVector );
1791 text->SetDrawCoord();
1792 break;
1793 }
1794
1795 default:
1796 break;
1797 }
1798 }
1799
1800 // Update the keepout zones
1801 for( ZONE* zone : Zones() )
1802 {
1803 zone->Move( moveVector );
1804 }
1805
1806 // Update the 3D models
1807 for( FP_3DMODEL& model : Models() )
1808 {
1809 model.m_Offset.x += pcbIUScale.IUTomm( moveVector.x );
1810 model.m_Offset.y -= pcbIUScale.IUTomm( moveVector.y );
1811 }
1812
1813 m_cachedBoundingBox.Move( moveVector );
1814 m_cachedVisibleBBox.Move( moveVector );
1815 m_cachedTextExcludedBBox.Move( moveVector );
1816 m_cachedHull.Move( moveVector );
1817}
1818
1819
1820void FOOTPRINT::SetOrientation( const EDA_ANGLE& aNewAngle )
1821{
1822 EDA_ANGLE angleChange = aNewAngle - m_orient; // change in rotation
1823
1824 m_orient = aNewAngle;
1826
1827 for( PAD* pad : m_pads )
1828 {
1829 pad->SetOrientation( pad->GetOrientation() + angleChange );
1830 pad->SetDrawCoord();
1831 }
1832
1833 for( ZONE* zone : m_fp_zones )
1834 zone->Rotate( GetPosition(), angleChange );
1835
1836 for( BOARD_ITEM* item : m_drawings )
1837 {
1838 if( PCB_DIMENSION_BASE* dimension = dynamic_cast<PCB_DIMENSION_BASE*>( item ) )
1839 dimension->Rotate( GetPosition(), angleChange );
1840 }
1841
1842 // Update of the reference and value.
1845
1846 // Displace contours and text of the footprint.
1847 for( BOARD_ITEM* item : m_drawings )
1848 {
1849 switch( item->Type() )
1850 {
1851 case PCB_FP_SHAPE_T:
1852 case PCB_FP_TEXTBOX_T:
1853 static_cast<FP_SHAPE*>( item )->SetDrawCoord();
1854 break;
1855
1856 case PCB_FP_TEXT_T:
1857 static_cast<FP_TEXT*>( item )->SetDrawCoord();
1858 break;
1859
1860 default:
1861 break;
1862 }
1863 }
1864
1869
1870 m_cachedHull.Rotate( angleChange, GetPosition() );
1871}
1872
1873
1875{
1876 FOOTPRINT* dupe = static_cast<FOOTPRINT*>( BOARD_ITEM::Duplicate() );
1877
1878 dupe->RunOnChildren( [&]( BOARD_ITEM* child )
1879 {
1880 const_cast<KIID&>( child->m_Uuid ) = KIID();
1881 });
1882
1883 return dupe;
1884}
1885
1886
1887BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootprint )
1888{
1889 BOARD_ITEM* new_item = nullptr;
1890 FP_ZONE* new_zone = nullptr;
1891
1892 switch( aItem->Type() )
1893 {
1894 case PCB_PAD_T:
1895 {
1896 PAD* new_pad = new PAD( *static_cast<const PAD*>( aItem ) );
1897 const_cast<KIID&>( new_pad->m_Uuid ) = KIID();
1898
1899 if( aAddToFootprint )
1900 m_pads.push_back( new_pad );
1901
1902 new_item = new_pad;
1903 break;
1904 }
1905
1906 case PCB_FP_ZONE_T:
1907 {
1908 new_zone = new FP_ZONE( *static_cast<const FP_ZONE*>( aItem ) );
1909 const_cast<KIID&>( new_zone->m_Uuid ) = KIID();
1910
1911 if( aAddToFootprint )
1912 m_fp_zones.push_back( new_zone );
1913
1914 new_item = new_zone;
1915 break;
1916 }
1917
1918 case PCB_FP_TEXT_T:
1919 {
1920 FP_TEXT* new_text = new FP_TEXT( *static_cast<const FP_TEXT*>( aItem ) );
1921 const_cast<KIID&>( new_text->m_Uuid ) = KIID();
1922
1923 if( new_text->GetType() == FP_TEXT::TEXT_is_REFERENCE )
1924 {
1925 new_text->SetText( wxT( "${REFERENCE}" ) );
1926 new_text->SetType( FP_TEXT::TEXT_is_DIVERS );
1927 }
1928 else if( new_text->GetType() == FP_TEXT::TEXT_is_VALUE )
1929 {
1930 new_text->SetText( wxT( "${VALUE}" ) );
1931 new_text->SetType( FP_TEXT::TEXT_is_DIVERS );
1932 }
1933
1934 if( aAddToFootprint )
1935 Add( new_text );
1936
1937 new_item = new_text;
1938
1939 break;
1940 }
1941
1942 case PCB_FP_SHAPE_T:
1943 {
1944 FP_SHAPE* new_shape = new FP_SHAPE( *static_cast<const FP_SHAPE*>( aItem ) );
1945 const_cast<KIID&>( new_shape->m_Uuid ) = KIID();
1946
1947 if( aAddToFootprint )
1948 Add( new_shape );
1949
1950 new_item = new_shape;
1951 break;
1952 }
1953
1954 case PCB_FP_TEXTBOX_T:
1955 {
1956 FP_TEXTBOX* new_textbox = new FP_TEXTBOX( *static_cast<const FP_TEXTBOX*>( aItem ) );
1957 const_cast<KIID&>( new_textbox->m_Uuid ) = KIID();
1958
1959 if( aAddToFootprint )
1960 Add( new_textbox );
1961
1962 new_item = new_textbox;
1963 break;
1964 }
1965
1971 {
1972 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( aItem->Duplicate() );
1973
1974 if( aAddToFootprint )
1975 Add( dimension );
1976
1977 new_item = dimension;
1978 break;
1979 }
1980
1981 case PCB_GROUP_T:
1982 new_item = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
1983 break;
1984
1985 case PCB_FOOTPRINT_T:
1986 // Ignore the footprint itself
1987 break;
1988
1989 default:
1990 // Un-handled item for duplication
1991 wxFAIL_MSG( wxT( "Duplication not supported for items of class " ) + aItem->GetClass() );
1992 break;
1993 }
1994
1995 return new_item;
1996}
1997
1998
1999wxString FOOTPRINT::GetNextPadNumber( const wxString& aLastPadNumber ) const
2000{
2001 std::set<wxString> usedNumbers;
2002
2003 // Create a set of used pad numbers
2004 for( PAD* pad : m_pads )
2005 usedNumbers.insert( pad->GetNumber() );
2006
2007 // Pad numbers aren't technically reference designators, but the formatting is close enough
2008 // for these to give us what we need.
2009 wxString prefix = UTIL::GetRefDesPrefix( aLastPadNumber );
2010 int num = GetTrailingInt( aLastPadNumber );
2011
2012 while( usedNumbers.count( wxString::Format( wxT( "%s%d" ), prefix, num ) ) )
2013 num++;
2014
2015 return wxString::Format( wxT( "%s%d" ), prefix, num );
2016}
2017
2018
2020{
2021 const wxString& refdes = GetReference();
2022
2023 SetReference( wxString::Format( wxT( "%s%i" ),
2024 UTIL::GetRefDesPrefix( refdes ),
2025 GetTrailingInt( refdes ) + aDelta ) );
2026}
2027
2028
2029// Calculate the area of a PolySet, polygons with hole are allowed.
2030static double polygonArea( SHAPE_POLY_SET& aPolySet )
2031{
2032 // Ensure all outlines are closed, before calculating the SHAPE_POLY_SET area
2033 for( int ii = 0; ii < aPolySet.OutlineCount(); ii++ )
2034 {
2035 SHAPE_LINE_CHAIN& outline = aPolySet.Outline( ii );
2036 outline.SetClosed( true );
2037
2038 for( int jj = 0; jj < aPolySet.HoleCount( ii ); jj++ )
2039 aPolySet.Hole( ii, jj ).SetClosed( true );
2040 }
2041
2042 return aPolySet.Area();
2043}
2044
2045
2046double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLECTOR& aCollector )
2047{
2048 int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
2049 SHAPE_POLY_SET poly;
2050
2051 if( aItem->Type() == PCB_MARKER_T )
2052 {
2053 const PCB_MARKER* marker = static_cast<const PCB_MARKER*>( aItem );
2054 SHAPE_LINE_CHAIN markerShape;
2055
2056 marker->ShapeToPolygon( markerShape );
2057 return markerShape.Area();
2058 }
2059 else if( aItem->Type() == PCB_GROUP_T )
2060 {
2061 double combinedArea = 0.0;
2062
2063 for( BOARD_ITEM* member : static_cast<const PCB_GROUP*>( aItem )->GetItems() )
2064 combinedArea += GetCoverageArea( member, aCollector );
2065
2066 return combinedArea;
2067 }
2068 if( aItem->Type() == PCB_FOOTPRINT_T )
2069 {
2070 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
2071
2072 poly = footprint->GetBoundingHull();
2073 }
2074 else if( aItem->Type() == PCB_FP_TEXT_T )
2075 {
2076 const FP_TEXT* text = static_cast<const FP_TEXT*>( aItem );
2077
2078 text->TransformTextToPolySet( poly, UNDEFINED_LAYER, textMargin, ARC_LOW_DEF, ERROR_OUTSIDE );
2079 }
2080 else if( aItem->Type() == PCB_FP_TEXTBOX_T )
2081 {
2082 const FP_TEXTBOX* tb = static_cast<const FP_TEXTBOX*>( aItem );
2083
2085 }
2086 else if( aItem->Type() == PCB_SHAPE_T )
2087 {
2088 // Approximate "linear" shapes with just their width squared, as we don't want to consider
2089 // a linear shape as being much bigger than another for purposes of selection filtering
2090 // just because it happens to be really long.
2091
2092 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
2093
2094 switch( shape->GetShape() )
2095 {
2096 case SHAPE_T::SEGMENT:
2097 case SHAPE_T::ARC:
2098 case SHAPE_T::BEZIER:
2099 return shape->GetWidth() * shape->GetWidth();
2100
2101 case SHAPE_T::RECT:
2102 case SHAPE_T::CIRCLE:
2103 case SHAPE_T::POLY:
2104 {
2105 if( !shape->IsFilled() )
2106 return shape->GetWidth() * shape->GetWidth();
2107
2109 }
2110
2111 default:
2113 }
2114 }
2115 else if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_ARC_T )
2116 {
2117 double width = static_cast<const PCB_TRACK*>( aItem )->GetWidth();
2118 return width * width;
2119 }
2120 else
2121 {
2123 }
2124
2125 return polygonArea( poly );
2126}
2127
2128
2129double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
2130{
2131 int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
2132
2133 SHAPE_POLY_SET footprintRegion( GetBoundingHull() );
2134 SHAPE_POLY_SET coveredRegion;
2135
2137
2138 TransformFPShapesToPolySet( coveredRegion, UNDEFINED_LAYER, textMargin, ARC_LOW_DEF,
2140 true, /* include text */
2141 false, /* include shapes */
2142 false /* include private items */ );
2143
2144 for( int i = 0; i < aCollector.GetCount(); ++i )
2145 {
2146 const BOARD_ITEM* item = aCollector[i];
2147
2148 switch( item->Type() )
2149 {
2150 case PCB_FP_TEXT_T:
2151 case PCB_FP_TEXTBOX_T:
2152 case PCB_FP_SHAPE_T:
2153 if( item->GetParent() != this )
2154 {
2155 item->TransformShapeToPolygon( coveredRegion, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
2156 ERROR_OUTSIDE );
2157 }
2158 break;
2159
2160 case PCB_TEXT_T:
2161 case PCB_TEXTBOX_T:
2162 case PCB_SHAPE_T:
2163 case PCB_TRACE_T:
2164 case PCB_ARC_T:
2165 case PCB_VIA_T:
2166 item->TransformShapeToPolygon( coveredRegion, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
2167 ERROR_OUTSIDE );
2168 break;
2169
2170 case PCB_FOOTPRINT_T:
2171 if( item != this )
2172 {
2173 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( item );
2174 coveredRegion.AddOutline( footprint->GetBoundingHull().Outline( 0 ) );
2175 }
2176 break;
2177
2178 default:
2179 break;
2180 }
2181 }
2182
2183 double footprintRegionArea = polygonArea( footprintRegion );
2184 double uncoveredRegionArea = footprintRegionArea - polygonArea( coveredRegion );
2185 double coveredArea = footprintRegionArea - uncoveredRegionArea;
2186 double ratio = ( coveredArea / footprintRegionArea );
2187
2188 // Test for negative ratio (should not occur).
2189 // better to be conservative (this will result in the disambiguate dialog)
2190 if( ratio < 0.0 )
2191 return 1.0;
2192
2193 return std::min( ratio, 1.0 );
2194}
2195
2196
2197std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
2198{
2199 std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
2200
2201 // There are several possible interpretations here:
2202 // 1) the bounding box (without or without invisible items)
2203 // 2) just the pads and "edges" (ie: non-text graphic items)
2204 // 3) the courtyard
2205
2206 // We'll go with (2) for now, unless the caller is clearly looking for (3)
2207
2208 if( aLayer == F_CrtYd || aLayer == B_CrtYd )
2209 {
2210 const SHAPE_POLY_SET& courtyard = GetCourtyard( aLayer );
2211
2212 if( courtyard.OutlineCount() == 0 ) // malformed/empty polygon
2213 return shape;
2214
2215 shape->AddShape( new SHAPE_SIMPLE( courtyard.COutline( 0 ) ) );
2216 }
2217 else
2218 {
2219 for( PAD* pad : Pads() )
2220 shape->AddShape( pad->GetEffectiveShape( aLayer, aFlash )->Clone() );
2221
2222 for( BOARD_ITEM* item : GraphicalItems() )
2223 {
2224 if( item->Type() == PCB_FP_SHAPE_T )
2225 shape->AddShape( item->GetEffectiveShape( aLayer, aFlash )->Clone() );
2226 }
2227 }
2228
2229 return shape;
2230}
2231
2232
2234{
2235 if( GetBoard() && GetBoard()->GetTimeStamp() > m_courtyard_cache_timestamp )
2236 const_cast<FOOTPRINT*>( this )->BuildCourtyardCaches();
2237
2238 if( IsBackLayer( aLayer ) )
2240 else
2242}
2243
2244
2246{
2250
2252
2253 // Build the courtyard area from graphic items on the courtyard.
2254 // Only PCB_FP_SHAPE_T have meaning, graphic texts are ignored.
2255 // Collect items:
2256 std::vector<PCB_SHAPE*> list_front;
2257 std::vector<PCB_SHAPE*> list_back;
2258
2259 for( BOARD_ITEM* item : GraphicalItems() )
2260 {
2261 if( item->GetLayer() == B_CrtYd && item->Type() == PCB_FP_SHAPE_T )
2262 list_back.push_back( static_cast<PCB_SHAPE*>( item ) );
2263
2264 if( item->GetLayer() == F_CrtYd && item->Type() == PCB_FP_SHAPE_T )
2265 list_front.push_back( static_cast<PCB_SHAPE*>( item ) );
2266 }
2267
2268 if( !list_front.size() && !list_back.size() )
2269 return;
2270
2271 int errorMax = pcbIUScale.mmToIU( 0.02 ); // max error for polygonization
2272 int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ); // max dist from one endPt to next startPt
2273
2274 if( ConvertOutlineToPolygon( list_front, m_courtyard_cache_front, errorMax, chainingEpsilon,
2275 true, aErrorHandler ) )
2276 {
2277 // Touching courtyards, or courtyards -at- the clearance distance are legal.
2279
2281 }
2282 else
2283 {
2285 }
2286
2287 if( ConvertOutlineToPolygon( list_back, m_courtyard_cache_back, errorMax, chainingEpsilon,
2288 true, aErrorHandler ) )
2289 {
2290 // Touching courtyards, or courtyards -at- the clearance distance are legal.
2292
2294 }
2295 else
2296 {
2298 }
2299}
2300
2301
2302std::map<wxString, int> FOOTPRINT::MapPadNumbersToNetTieGroups() const
2303{
2304 std::map<wxString, int> padNumberToGroupIdxMap;
2305
2306 for( const PAD* pad : m_pads )
2307 padNumberToGroupIdxMap[ pad->GetNumber() ] = -1;
2308
2309 auto processPad =
2310 [&]( wxString aPad, int aGroup )
2311 {
2312 aPad.Trim( true ).Trim( false );
2313
2314 if( !aPad.IsEmpty() )
2315 padNumberToGroupIdxMap[ aPad ] = aGroup;
2316 };
2317
2318 for( int ii = 0; ii < (int) m_netTiePadGroups.size(); ++ii )
2319 {
2320 wxString group( m_netTiePadGroups[ ii ] );
2321 bool esc = false;
2322 wxString pad;
2323
2324 for( wxUniCharRef ch : group )
2325 {
2326 if( esc )
2327 {
2328 esc = false;
2329 pad.Append( ch );
2330 continue;
2331 }
2332
2333 switch( static_cast<unsigned char>( ch ) )
2334 {
2335 case '\\':
2336 esc = true;
2337 break;
2338
2339 case ',':
2340 processPad( pad, ii );
2341 pad.Clear();
2342 break;
2343
2344 default:
2345 pad.Append( ch );
2346 break;
2347 }
2348 }
2349
2350 processPad( pad, ii );
2351 }
2352
2353 return padNumberToGroupIdxMap;
2354}
2355
2356
2357std::vector<PAD*> FOOTPRINT::GetNetTiePads( PAD* aPad ) const
2358{
2359 // First build a map from pad numbers to allowed-shorting-group indexes. This ends up being
2360 // something like O(3n), but it still beats O(n^2) for large numbers of pads.
2361
2362 std::map<wxString, int> padToNetTieGroupMap = MapPadNumbersToNetTieGroups();
2363 int groupIdx = padToNetTieGroupMap[ aPad->GetNumber() ];
2364 std::vector<PAD*> otherPads;
2365
2366 if( groupIdx >= 0 )
2367 {
2368 for( PAD* pad : m_pads )
2369 {
2370 if( padToNetTieGroupMap[ pad->GetNumber() ] == groupIdx )
2371 otherPads.push_back( pad );
2372 }
2373 }
2374
2375 return otherPads;
2376}
2377
2378
2379void FOOTPRINT::CheckFootprintAttributes( const std::function<void( const wxString& )>& aErrorHandler )
2380{
2381 int likelyAttr = ( GetLikelyAttribute() & ( FP_SMD | FP_THROUGH_HOLE ) );
2382 int setAttr = ( GetAttributes() & ( FP_SMD | FP_THROUGH_HOLE ) );
2383
2384 if( setAttr && likelyAttr && setAttr != likelyAttr )
2385 {
2386 wxString msg;
2387
2388 switch( likelyAttr )
2389 {
2390 case FP_THROUGH_HOLE:
2391 msg.Printf( _( "(expected 'Through hole'; actual '%s')" ), GetTypeName() );
2392 break;
2393 case FP_SMD:
2394 msg.Printf( _( "(expected 'SMD'; actual '%s')" ), GetTypeName() );
2395 break;
2396 }
2397
2398 if( aErrorHandler )
2399 (aErrorHandler)( msg );
2400 }
2401}
2402
2403
2404void FOOTPRINT::CheckPads( const std::function<void( const PAD*, int,
2405 const wxString& )>& aErrorHandler )
2406{
2407 if( aErrorHandler == nullptr )
2408 return;
2409
2410 for( PAD* pad: Pads() )
2411 {
2412 if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
2413 {
2414 if( pad->GetDrillSizeX() < 1 || pad->GetDrillSizeY() < 1 )
2415 (aErrorHandler)( pad, DRCE_PAD_TH_WITH_NO_HOLE, wxEmptyString );
2416 }
2417
2418 if( pad->GetAttribute() == PAD_ATTRIB::PTH )
2419 {
2420 if( !pad->IsOnCopperLayer() )
2421 {
2422 (aErrorHandler)( pad, DRCE_PADSTACK, _( "(PTH pad has no copper layers)" ) );
2423 }
2424 else
2425 {
2426 LSET lset = pad->GetLayerSet() & LSET::AllCuMask();
2427 PCB_LAYER_ID layer = lset.Seq().at( 0 );
2428 SHAPE_POLY_SET padOutline;
2429
2430 pad->TransformShapeToPolygon( padOutline, layer, 0, ARC_HIGH_DEF, ERROR_INSIDE );
2431
2432 std::shared_ptr<SHAPE_SEGMENT> hole = pad->GetEffectiveHoleShape();
2433 SHAPE_POLY_SET holeOutline;
2434
2435 TransformOvalToPolygon( holeOutline, hole->GetSeg().A, hole->GetSeg().B,
2436 hole->GetWidth(), ARC_HIGH_DEF, ERROR_INSIDE );
2437
2438 padOutline.BooleanSubtract( holeOutline, SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
2439
2440 if( padOutline.IsEmpty() )
2441 aErrorHandler( pad, DRCE_PADSTACK, _( "(PTH pad's hole leaves no copper)" ) );
2442 }
2443 }
2444
2445 if( pad->GetAttribute() == PAD_ATTRIB::SMD )
2446 {
2447 if( pad->IsOnLayer( F_Cu ) && pad->IsOnLayer( B_Cu ) )
2448 {
2449 aErrorHandler( pad, DRCE_PADSTACK,
2450 _( "(SMD pad appears on both front and back copper)" ) );
2451 }
2452 else if( pad->IsOnLayer( F_Cu ) )
2453 {
2454 if( pad->IsOnLayer( B_Mask ) )
2455 {
2456 aErrorHandler( pad, DRCE_PADSTACK,
2457 _( "(SMD pad copper and mask layers don't match)" ) );
2458 }
2459 else if( pad->IsOnLayer( B_Paste ) )
2460 {
2461 aErrorHandler( pad, DRCE_PADSTACK,
2462 _( "(SMD pad copper and paste layers don't match)" ) );
2463 }
2464 }
2465 else if( pad->IsOnLayer( B_Cu ) )
2466 {
2467 if( pad->IsOnLayer( F_Mask ) )
2468 {
2469 aErrorHandler( pad, DRCE_PADSTACK,
2470 _( "(SMD pad copper and mask layers don't match)" ) );
2471 }
2472 else if( pad->IsOnLayer( F_Paste ) )
2473 {
2474 aErrorHandler( pad, DRCE_PADSTACK,
2475 _( "(SMD pad copper and paste layers don't match)" ) );
2476 }
2477 }
2478 }
2479 }
2480}
2481
2482
2483void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const PAD*,
2484 const VECTOR2I& )>& aErrorHandler )
2485{
2486 std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
2487
2488 for( PAD* pad : Pads() )
2489 {
2490 std::vector<PAD*> netTiePads = GetNetTiePads( pad );
2491
2492 for( PAD* other : Pads() )
2493 {
2494 if( other == pad || pad->SameLogicalPadAs( other ) )
2495 continue;
2496
2497 if( alg::contains( netTiePads, other ) )
2498 continue;
2499
2500 if( !( ( pad->GetLayerSet() & other->GetLayerSet() ) & LSET::AllCuMask() ).any() )
2501 continue;
2502
2503 // store canonical order so we don't collide in both directions (a:b and b:a)
2504 PAD* a = pad;
2505 PAD* b = other;
2506
2507 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
2508 std::swap( a, b );
2509
2510 if( checkedPairs.find( { a, b } ) == checkedPairs.end() )
2511 {
2512 checkedPairs[ { a, b } ] = 1;
2513
2514 if( pad->GetBoundingBox().Intersects( other->GetBoundingBox() ) )
2515 {
2516 VECTOR2I pos;
2517 SHAPE* padShape = pad->GetEffectiveShape().get();
2518 SHAPE* otherShape = other->GetEffectiveShape().get();
2519
2520 if( padShape->Collide( otherShape, 0, nullptr, &pos ) )
2521 aErrorHandler( pad, other, pos );
2522 }
2523 }
2524 }
2525 }
2526}
2527
2528
2529void FOOTPRINT::CheckNetTies( const std::function<void( const BOARD_ITEM* aItem,
2530 const BOARD_ITEM* bItem,
2531 const BOARD_ITEM* cItem,
2532 const VECTOR2I& )>& aErrorHandler )
2533{
2534 // First build a map from pad numbers to allowed-shorting-group indexes. This ends up being
2535 // something like O(3n), but it still beats O(n^2) for large numbers of pads.
2536
2537 std::map<wxString, int> padNumberToGroupIdxMap = MapPadNumbersToNetTieGroups();
2538
2539 // Now collect all the footprint items which are on copper layers
2540
2541 std::vector<BOARD_ITEM*> copperItems;
2542
2543 for( BOARD_ITEM* item : m_drawings )
2544 {
2545 if( item->IsOnCopperLayer() )
2546 copperItems.push_back( item );
2547 }
2548
2549 for( ZONE* zone : m_fp_zones )
2550 {
2551 if( !zone->GetIsRuleArea() && zone->IsOnCopperLayer() )
2552 copperItems.push_back( zone );
2553 }
2554
2556 copperItems.push_back( m_reference );
2557
2558 if( m_value->IsOnCopperLayer() )
2559 copperItems.push_back( m_value );
2560
2561 for( PCB_LAYER_ID layer : { F_Cu, In1_Cu, B_Cu } )
2562 {
2563 // Next, build a polygon-set for the copper on this layer. We don't really care about
2564 // nets here, we just want to end up with a set of outlines describing the distinct
2565 // copper polygons of the footprint.
2566
2567 SHAPE_POLY_SET copperOutlines;
2568 std::map<int, std::vector<const PAD*>> outlineIdxToPadsMap;
2569
2570 for( BOARD_ITEM* item : copperItems )
2571 {
2572 if( item->IsOnLayer( layer ) )
2573 {
2574 item->TransformShapeToPolygon( copperOutlines, layer, 0, ARC_HIGH_DEF,
2575 ERROR_OUTSIDE );
2576 }
2577 }
2578
2579 copperOutlines.Simplify( SHAPE_POLY_SET::PM_FAST );
2580
2581 // Index each pad to the outline in the set that it is part of.
2582
2583 for( const PAD* pad : m_pads )
2584 {
2585 for( int ii = 0; ii < copperOutlines.OutlineCount(); ++ii )
2586 {
2587 if( pad->GetEffectiveShape( layer )->Collide( &copperOutlines.Outline( ii ), 0 ) )
2588 outlineIdxToPadsMap[ ii ].emplace_back( pad );
2589 }
2590 }
2591
2592 // Finally, ensure that each outline which contains multiple pads has all its pads
2593 // listed in an allowed-shorting group.
2594
2595 for( const auto& [ outlineIdx, pads ] : outlineIdxToPadsMap )
2596 {
2597 if( pads.size() > 1 )
2598 {
2599 const PAD* firstPad = pads[0];
2600 int firstGroupIdx = padNumberToGroupIdxMap[ firstPad->GetNumber() ];
2601
2602 for( size_t ii = 1; ii < pads.size(); ++ii )
2603 {
2604 const PAD* thisPad = pads[ii];
2605 int thisGroupIdx = padNumberToGroupIdxMap[ thisPad->GetNumber() ];
2606
2607 if( thisGroupIdx < 0 || thisGroupIdx != firstGroupIdx )
2608 {
2609 BOARD_ITEM* shortingItem = nullptr;
2610 VECTOR2I pos = ( firstPad->GetPosition() + thisPad->GetPosition() ) / 2;
2611
2612 pos = copperOutlines.Outline( outlineIdx ).NearestPoint( pos );
2613
2614 for( BOARD_ITEM* item : copperItems )
2615 {
2616 if( item->HitTest( pos, 1 ) )
2617 {
2618 shortingItem = item;
2619 break;
2620 }
2621 }
2622
2623 if( shortingItem )
2624 aErrorHandler( shortingItem, firstPad, thisPad, pos );
2625 else
2626 aErrorHandler( firstPad, thisPad, nullptr, pos );
2627 }
2628 }
2629 }
2630 }
2631 }
2632}
2633
2634
2635void FOOTPRINT::CheckNetTiePadGroups( const std::function<void( const wxString& )>& aErrorHandler )
2636{
2637 std::set<wxString> padNumbers;
2638 wxString msg;
2639
2640 auto ret = MapPadNumbersToNetTieGroups();
2641
2642 for( auto [ padNumber, _ ] : ret )
2643 {
2644 const PAD* pad = FindPadByNumber( padNumber );
2645
2646 if( !pad )
2647 {
2648 msg.Printf( _( "(net-tie pad group contains unknown pad number %s)" ), padNumber );
2649 aErrorHandler( msg );
2650 }
2651 else if( !padNumbers.insert( pad->GetNumber() ).second )
2652 {
2653 msg.Printf( _( "(pad %s appears in more than one net-tie pad group)" ), padNumber );
2654 aErrorHandler( msg );
2655 }
2656 }
2657}
2658
2659
2661{
2662 wxASSERT( aImage->Type() == PCB_FOOTPRINT_T );
2663
2664 std::swap( *this, *static_cast<FOOTPRINT*>( aImage ) );
2665}
2666
2667
2669{
2670 for( PAD* pad : Pads() )
2671 {
2672 if( pad->GetAttribute() != PAD_ATTRIB::SMD )
2673 return true;
2674 }
2675
2676 return false;
2677}
2678
2679
2680#define TEST( a, b ) { if( a != b ) return a < b; }
2681#define TEST_PT( a, b ) { if( a.x != b.x ) return a.x < b.x; if( a.y != b.y ) return a.y < b.y; }
2682
2683
2684bool FOOTPRINT::cmp_drawings::operator()( const BOARD_ITEM* itemA, const BOARD_ITEM* itemB ) const
2685{
2686 TEST( itemA->Type(), itemB->Type() );
2687 TEST( itemA->GetLayer(), itemB->GetLayer() );
2688
2689 if( itemA->Type() == PCB_FP_SHAPE_T )
2690 {
2691 const FP_SHAPE* dwgA = static_cast<const FP_SHAPE*>( itemA );
2692 const FP_SHAPE* dwgB = static_cast<const FP_SHAPE*>( itemB );
2693
2694 TEST( dwgA->GetShape(), dwgB->GetShape() );
2695
2696 TEST_PT( dwgA->GetStart0(), dwgB->GetStart0() );
2697 TEST_PT( dwgA->GetEnd0(), dwgB->GetEnd0() );
2698
2699 if( dwgA->GetShape() == SHAPE_T::ARC )
2700 {
2701 TEST_PT( dwgA->GetCenter0(), dwgB->GetCenter0() );
2702 }
2703 else if( dwgA->GetShape() == SHAPE_T::BEZIER )
2704 {
2705 TEST_PT( dwgA->GetBezierC1_0(), dwgB->GetBezierC1_0() );
2706 TEST_PT( dwgA->GetBezierC2_0(), dwgB->GetBezierC2_0() );
2707 }
2708 else if( dwgA->GetShape() == SHAPE_T::POLY )
2709 {
2711
2712 for( int ii = 0; ii < dwgA->GetPolyShape().TotalVertices(); ++ii )
2713 TEST_PT( dwgA->GetPolyShape().CVertex( ii ), dwgB->GetPolyShape().CVertex( ii ) );
2714 }
2715
2716 TEST( dwgA->GetWidth(), dwgB->GetWidth() );
2717 }
2718
2719 TEST( itemA->m_Uuid, itemB->m_Uuid ); // should be always the case for valid boards
2720
2721 return itemA < itemB;
2722}
2723
2724
2725bool FOOTPRINT::cmp_pads::operator()( const PAD* aFirst, const PAD* aSecond ) const
2726{
2727 if( aFirst->GetNumber() != aSecond->GetNumber() )
2728 return StrNumCmp( aFirst->GetNumber(), aSecond->GetNumber() ) < 0;
2729
2730 TEST_PT( aFirst->GetPos0(), aSecond->GetPos0() );
2731 TEST_PT( aFirst->GetSize(), aSecond->GetSize() );
2732 TEST( aFirst->GetShape(), aSecond->GetShape() );
2733 TEST( aFirst->GetLayerSet().Seq(), aSecond->GetLayerSet().Seq() );
2734
2735 TEST( aFirst->m_Uuid, aSecond->m_Uuid ); // should be always the case for valid boards
2736
2737 return aFirst < aSecond;
2738}
2739
2740
2741bool FOOTPRINT::cmp_zones::operator()( const FP_ZONE* aFirst, const FP_ZONE* aSecond ) const
2742{
2743 TEST( aFirst->GetAssignedPriority(), aSecond->GetAssignedPriority() );
2744 TEST( aFirst->GetLayerSet().Seq(), aSecond->GetLayerSet().Seq() );
2745
2746 TEST( aFirst->Outline()->TotalVertices(), aSecond->Outline()->TotalVertices() );
2747
2748 for( int ii = 0; ii < aFirst->Outline()->TotalVertices(); ++ii )
2749 TEST_PT( aFirst->Outline()->CVertex( ii ), aSecond->Outline()->CVertex( ii ) );
2750
2751 TEST( aFirst->m_Uuid, aSecond->m_Uuid ); // should be always the case for valid boards
2752
2753 return aFirst < aSecond;
2754}
2755
2756
2757#undef TEST
2758
2759
2761 int aClearance, int aMaxError, ERROR_LOC aErrorLoc,
2762 bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
2763 bool aSkipNonPlatedPads ) const
2764{
2765 for( const PAD* pad : m_pads )
2766 {
2767 if( !pad->FlashLayer( aLayer ) )
2768 continue;
2769
2770 VECTOR2I clearance( aClearance, aClearance );
2771
2772 switch( aLayer )
2773 {
2774 case F_Cu:
2775 if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
2776 continue;
2777
2778 if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
2779 continue;
2780
2781 break;
2782
2783 case B_Cu:
2784 if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
2785 continue;
2786
2787 if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
2788 continue;
2789
2790 break;
2791
2792 case F_Mask:
2793 case B_Mask:
2794 clearance.x += pad->GetSolderMaskExpansion();
2795 clearance.y += pad->GetSolderMaskExpansion();
2796 break;
2797
2798 case F_Paste:
2799 case B_Paste:
2800 clearance += pad->GetSolderPasteMargin();
2801 break;
2802
2803 default:
2804 break;
2805 }
2806
2807 // Our standard TransformShapeToPolygon() routines can't handle differing x:y clearance
2808 // values (which get generated when a relative paste margin is used with an oblong pad).
2809 // So we apply this huge hack and fake a larger pad to run the transform on.
2810 // Of course being a hack it falls down when dealing with custom shape pads (where the
2811 // size is only the size of the anchor), so for those we punt and just use clearance.x.
2812
2813 if( ( clearance.x < 0 || clearance.x != clearance.y )
2814 && pad->GetShape() != PAD_SHAPE::CUSTOM )
2815 {
2816 VECTOR2I dummySize = pad->GetSize() + clearance + clearance;
2817
2818 if( dummySize.x <= 0 || dummySize.y <= 0 )
2819 continue;
2820
2821 PAD dummy( *pad );
2822 dummy.SetSize( dummySize );
2823 dummy.TransformShapeToPolygon( aBuffer, aLayer, 0, aMaxError, aErrorLoc );
2824 }
2825 else
2826 {
2827 pad->TransformShapeToPolygon( aBuffer, aLayer, clearance.x, aMaxError, aErrorLoc );
2828 }
2829 }
2830}
2831
2832
2834 int aClearance, int aError, ERROR_LOC aErrorLoc,
2835 bool aIncludeText, bool aIncludeShapes,
2836 bool aIncludePrivateItems ) const
2837{
2838 std::vector<FP_TEXT*> texts; // List of FP_TEXT to convert
2839
2840 for( BOARD_ITEM* item : GraphicalItems() )
2841 {
2842 if( GetPrivateLayers().test( item->GetLayer() ) && !aIncludePrivateItems )
2843 continue;
2844
2845 if( item->Type() == PCB_FP_TEXT_T && aIncludeText )
2846 {
2847 FP_TEXT* text = static_cast<FP_TEXT*>( item );
2848
2849 if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer && text->IsVisible() )
2850 texts.push_back( text );
2851 }
2852
2853 if( item->Type() == PCB_FP_TEXTBOX_T && aIncludeText )
2854 {
2855 FP_TEXTBOX* textbox = static_cast<FP_TEXTBOX*>( item );
2856
2857 if( aLayer != UNDEFINED_LAYER && textbox->GetLayer() == aLayer && textbox->IsVisible() )
2858 textbox->TransformShapeToPolygon( aBuffer, aLayer, 0, aError, aErrorLoc );
2859 }
2860
2861 if( item->Type() == PCB_FP_SHAPE_T && aIncludeShapes )
2862 {
2863 const FP_SHAPE* outline = static_cast<FP_SHAPE*>( item );
2864
2865 if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer )
2866 outline->TransformShapeToPolygon( aBuffer, aLayer, 0, aError, aErrorLoc );
2867 }
2868 }
2869
2870 if( aIncludeText )
2871 {
2872 if( Reference().GetLayer() == aLayer && Reference().IsVisible() )
2873 texts.push_back( &Reference() );
2874
2875 if( Value().GetLayer() == aLayer && Value().IsVisible() )
2876 texts.push_back( &Value() );
2877 }
2878
2879 for( const FP_TEXT* text : texts )
2880 text->TransformTextToPolySet( aBuffer, aLayer, aClearance, aError, aErrorLoc );
2881}
2882
2883
2884static struct FOOTPRINT_DESC
2885{
2887 {
2889
2890 if( zcMap.Choices().GetCount() == 0 )
2891 {
2893 zcMap.Map( ZONE_CONNECTION::INHERITED, _HKI( "Inherited" ) )
2894 .Map( ZONE_CONNECTION::NONE, _HKI( "None" ) )
2895 .Map( ZONE_CONNECTION::THERMAL, _HKI( "Thermal reliefs" ) )
2896 .Map( ZONE_CONNECTION::FULL, _HKI( "Solid" ) )
2897 .Map( ZONE_CONNECTION::THT_THERMAL, _HKI( "Thermal reliefs for PTH" ) );
2898 }
2899
2901
2902 if( layerEnum.Choices().GetCount() == 0 )
2903 {
2904 layerEnum.Undefined( UNDEFINED_LAYER );
2905
2906 for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
2907 layerEnum.Map( *seq, LSET::Name( *seq ) );
2908 }
2909
2910 wxPGChoices fpLayers; // footprints might be placed only on F.Cu & B.Cu
2911 fpLayers.Add( LSET::Name( F_Cu ), F_Cu );
2912 fpLayers.Add( LSET::Name( B_Cu ), B_Cu );
2913
2920
2921 auto layer = new PROPERTY_ENUM<FOOTPRINT, PCB_LAYER_ID>( _HKI( "Layer" ),
2923 layer->SetChoices( fpLayers );
2924 propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ), layer );
2925
2926 propMgr.AddProperty( new PROPERTY<FOOTPRINT, double>( _HKI( "Orientation" ),
2929
2930 const wxString groupFootprint = _HKI( "Footprint Properties" );
2931
2932 propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Reference" ),
2934 groupFootprint );
2935 propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Value" ),
2937 groupFootprint );
2938
2939 propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Library link" ),
2941 groupFootprint );
2942 propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Description" ),
2944 groupFootprint );
2945 propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Keywords" ),
2947 groupFootprint );
2948
2949 const wxString groupAttributes = _HKI( "Fabrication Attributes" );
2950
2951 propMgr.AddProperty( new PROPERTY<FOOTPRINT, bool>( _HKI( "Not in schematic" ),
2952 &FOOTPRINT::SetBoardOnly, &FOOTPRINT::IsBoardOnly ), groupAttributes );
2953 propMgr.AddProperty( new PROPERTY<FOOTPRINT, bool>( _HKI( "Exclude from position files" ),
2955 groupAttributes );
2956 propMgr.AddProperty( new PROPERTY<FOOTPRINT, bool>( _HKI( "Exclude from bill of materials" ),
2958 groupAttributes );
2959
2960 const wxString groupOverrides = _HKI( "Overrides" );
2961
2963 _HKI( "Exempt from courtyard requirement" ),
2965 groupOverrides );
2966 propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Clearance Override" ),
2969 groupOverrides );
2970 propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Solderpaste Margin Override" ),
2973 groupOverrides );
2975 _HKI( "Solderpaste Margin Ratio Override" ),
2978 groupOverrides );
2980 _HKI( "Zone Connection Style" ),
2982 groupOverrides );
2983 }
constexpr int ARC_HIGH_DEF
Definition: base_units.h:121
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
constexpr int ARC_LOW_DEF
Definition: base_units.h:120
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:84
PCB_LAYER_ID m_layer
Definition: board_item.h:341
virtual void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
Definition: board_item.cpp:196
virtual BOARD_ITEM * Duplicate() const
Create a copy of this BOARD_ITEM.
Definition: board_item.cpp:184
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:226
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:43
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:175
virtual bool IsOnCopperLayer() const
Definition: board_item.h:135
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:94
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition: board.h:299
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:653
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:593
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
int GetTimeStamp() const
Definition: board.h:292
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:111
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
virtual double OnePixelInIU() const =0
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
EDA_ANGLE Normalize180()
Definition: eda_angle.h:288
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:240
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:139
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:141
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition: eda_item.h:143
virtual wxString GetClass() const =0
Return the class name.
void ClearEditFlags()
Definition: eda_item.h:158
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:142
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:247
bool IsFilled() const
Definition: eda_shape.h:90
SHAPE_T GetShape() const
Definition: eda_shape.h:113
int GetWidth() const
Definition: eda_shape.h:109
virtual bool IsVisible() const
Definition: eda_text.h:136
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:165
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:629
static ENUM_MAP< T > & Instance()
Definition: property.h:623
ENUM_MAP & Undefined(T aValue)
Definition: property.h:636
wxPGChoices & Choices()
Definition: property.h:672
bool FixUuids()
Old footprints do not always have a valid UUID (some can be set to null uuid) However null UUIDs,...
Definition: footprint.cpp:239
void CheckShortingPads(const std::function< void(const PAD *, const PAD *, const VECTOR2I &)> &aErrorHandler)
Check for overlapping, different-numbered, non-net-tie pads.
Definition: footprint.cpp:2483
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1688
LIB_ID m_fpid
Definition: footprint.h:837
KIID_PATH m_path
Definition: footprint.h:873
bool IsBoardOnly() const
Definition: footprint.h:583
BOX2I m_cachedTextExcludedBBox
Definition: footprint.h:856
void CheckPads(const std::function< void(const PAD *, int, const wxString &)> &aErrorHandler)
Run non-board-specific DRC checks on footprint's pads.
Definition: footprint.cpp:2404
std::vector< PAD * > GetNetTiePads(PAD *aPad) const
Definition: footprint.cpp:2357
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
Definition: footprint.cpp:494
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:628
ZONE_CONNECTION m_zoneConnection
Definition: footprint.h:865
BOX2I m_cachedBoundingBox
Definition: footprint.h:852
static double GetCoverageArea(const BOARD_ITEM *aItem, const GENERAL_COLLECTOR &aCollector)
Return the initial comments block or NULL if none, without transfer of ownership.
Definition: footprint.cpp:2046
bool IsExcludedFromBOM() const
Definition: footprint.h:601
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:1820
FP_ZONES m_fp_zones
Definition: footprint.h:830
static bool IsLibNameValid(const wxString &aName)
Test for validity of a name of a footprint to be used in a footprint library ( no spaces,...
Definition: footprint.cpp:1530
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
Return the number of pads.
Definition: footprint.cpp:1224
bool IsOnLayer(PCB_LAYER_ID aLayer, bool aIncludeCourtyards=false) const override
A special IsOnLayer for footprints: return true if the footprint contains only items on the given lay...
Definition: footprint.cpp:1095
void CheckNetTies(const std::function< void(const BOARD_ITEM *aItem, const BOARD_ITEM *bItem, const BOARD_ITEM *cItem, const VECTOR2I &)> &aErrorHandler)
Check for un-allowed shorting of pads in net-tie footprints.
Definition: footprint.cpp:2529
void SetExcludedFromBOM(bool aExclude=true)
Definition: footprint.h:602
int m_fpStatus
Definition: footprint.h:839
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: footprint.cpp:1471
SHAPE_POLY_SET m_cachedHull
Definition: footprint.h:858
int GetLocalClearance() const
Definition: footprint.h:230
void SetAllowMissingCourtyard(bool aAllow=true)
Definition: footprint.h:611
int m_localSolderPasteMargin
Definition: footprint.h:868
int m_attributes
Definition: footprint.h:838
std::vector< FP_3DMODEL > m_3D_Drawings
Definition: footprint.h:879
double CoverageRatio(const GENERAL_COLLECTOR &aCollector) const
Calculate the ratio of total area of the footprint pads and graphical items to the area of the footpr...
Definition: footprint.cpp:2129
BOARD_ITEM * DuplicateItem(const BOARD_ITEM *aItem, bool aAddToFootprint=false)
Duplicate a given item within the footprint, optionally adding it to the board.
Definition: footprint.cpp:1887
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: footprint.cpp:2197
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: footprint.cpp:1381
double m_localSolderPasteMarginRatio
Definition: footprint.h:869
void TransformPadsToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aSkipNPTHPadsWihNoCopper=false, bool aSkipPlatedPads=false, bool aSkipNonPlatedPads=false) const
Generate pads shapes on layer aLayer as polygons and adds these polygons to aBuffer.
Definition: footprint.cpp:2760
wxArrayString * m_initial_comments
Definition: footprint.h:881
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: footprint.cpp:1387
wxString GetDescription() const
Definition: footprint.h:218
BOX2I m_cachedVisibleBBox
Definition: footprint.h:854
double GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:244
BOX2I GetFpPadsLocalBbox() const
Return the bounding box containing pads when the footprint is on the front side, orientation 0,...
Definition: footprint.cpp:783
int m_visibleBBoxCacheTimeStamp
Definition: footprint.h:855
std::map< wxString, wxString > m_properties
Definition: footprint.h:880
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: footprint.cpp:1565
void SetExcludedFromPosFiles(bool aExclude=true)
Definition: footprint.h:593
int m_localClearance
Definition: footprint.h:866
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: footprint.h:245
void SetOrientationDegrees(double aOrientation)
Definition: footprint.h:203
FP_GROUPS & Groups()
Definition: footprint.h:179
std::map< wxString, int > MapPadNumbersToNetTieGroups() const
Definition: footprint.cpp:2302
void MoveAnchorPosition(const VECTOR2I &aMoveVector)
Move the reference point of the footprint.
Definition: footprint.cpp:1746
FOOTPRINT & operator=(const FOOTPRINT &aOther)
Definition: footprint.cpp:374
int m_arflag
Definition: footprint.h:875
double GetOrientationDegrees() const
Definition: footprint.h:207
BOARD_ITEM * Duplicate() const override
Create a copy of this BOARD_ITEM.
Definition: footprint.cpp:1874
void SetLocalSolderPasteMargin(int aMargin)
Definition: footprint.h:242
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: footprint.cpp:1285
int GetAttributes() const
Definition: footprint.h:250
int m_localSolderMaskMargin
Definition: footprint.h:867
FOOTPRINT(BOARD *parent)
Definition: footprint.cpp:56
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:200
LSET GetPrivateLayers() const
Definition: footprint.h:120
wxString GetFPIDAsString() const
Definition: footprint.h:215
wxString GetValueAsString() const
Definition: footprint.h:561
bool AllowMissingCourtyard() const
Definition: footprint.h:610
bool IsFlipped() const
Definition: footprint.h:324
PADS & Pads()
Definition: footprint.h:170
SHAPE_POLY_SET GetBoundingHull() const
Return a bounding polygon for the shapes and pads in the footprint.
Definition: footprint.cpp:944
int GetLocalSolderPasteMargin() const
Definition: footprint.h:241
void TransformFPShapesToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIncludeText=true, bool aIncludeShapes=true, bool aIncludePrivateItems=false) const
Generate shapes of graphic items (outlines) on layer aLayer as polygons and adds these polygons to aB...
Definition: footprint.cpp:2833
wxString GetTypeName() const
Get the type of footprint.
Definition: footprint.cpp:771
DRAWINGS m_drawings
Definition: footprint.h:828
SHAPE_POLY_SET m_courtyard_cache_back
Definition: footprint.h:885
int m_textExcludedBBoxCacheTimeStamp
Definition: footprint.h:857
void SetLocalClearance(int aClearance)
Definition: footprint.h:231
const LIB_ID & GetFPID() const
Definition: footprint.h:212
void SetReference(const wxString &aReference)
Definition: footprint.h:528
bool IsLocked() const override
Definition: footprint.h:340
bool IsExcludedFromPosFiles() const
Definition: footprint.h:592
void SetLayerAndFlip(PCB_LAYER_ID aLayer)
Used as Layer property setter – performs a flip if necessary to set the footprint layer.
Definition: footprint.cpp:1591
int m_hullCacheTimeStamp
Definition: footprint.h:859
unsigned GetUniquePadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
Return the number of unique non-blank pads.
Definition: footprint.cpp:1243
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: footprint.cpp:1512
LSET m_privateLayers
Definition: footprint.h:877
int GetLikelyAttribute() const
Returns the most likely attribute based on pads Either FP_THROUGH_HOLE/FP_SMD/OTHER(0)
Definition: footprint.cpp:721
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: footprint.cpp:1558
VECTOR2I m_pos
Definition: footprint.h:834
std::vector< wxString > m_netTiePadGroups
Definition: footprint.h:863
PAD * GetPad(const VECTOR2I &aPosition, LSET aLayerMask=LSET::AllLayersMask())
Get a pad at aPosition on aLayerMask in the footprint.
Definition: footprint.cpp:1208
void Add3DModel(FP_3DMODEL *a3DModel)
Add a3DModel definition to the end of the 3D model list.
Definition: footprint.cpp:1274
void SetValue(const wxString &aValue)
Definition: footprint.h:555
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: footprint.cpp:1026
wxString GetReferenceAsString() const
Definition: footprint.h:534
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:567
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars for this footprint.
Definition: footprint.cpp:481
SHAPE_POLY_SET m_courtyard_cache_front
Definition: footprint.h:884
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:568
wxString m_keywords
Definition: footprint.h:872
void ClearAllNets()
Clear (i.e.
Definition: footprint.cpp:559
void SetZoneConnection(ZONE_CONNECTION aType)
Definition: footprint.h:247
bool HasThroughHolePads() const
Definition: footprint.cpp:2668
void BuildCourtyardCaches(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:2245
EDA_ANGLE m_orient
Definition: footprint.h:833
bool HitTestAccurate(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if a point is inside the bounding polygon of the footprint.
Definition: footprint.cpp:1130
wxString GetClass() const override
Return the class name.
Definition: footprint.h:702
void IncrementReference(int aDelta)
Bump the current reference by aDelta.
Definition: footprint.cpp:2019
KIID m_link
Definition: footprint.h:876
bool IsConflicting() const
Definition: footprint.cpp:475
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:184
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const
Invoke a function on all BOARD_ITEMs that belong to the footprint (pads, drawings,...
Definition: footprint.cpp:1393
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
Definition: footprint.cpp:1541
void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: footprint.cpp:1600
double GetArea(int aPadding=0) const
Definition: footprint.cpp:711
FP_TEXT * m_value
Definition: footprint.h:836
ZONE_CONNECTION GetZoneConnection() const
Definition: footprint.h:248
const wxString & GetReference() const
Definition: footprint.h:519
void CheckNetTiePadGroups(const std::function< void(const wxString &)> &aErrorHandler)
Sanity check net-tie pad groups.
Definition: footprint.cpp:2635
void SetBoardOnly(bool aIsBoardOnly=true)
Definition: footprint.h:584
timestamp_t m_lastEditTime
Definition: footprint.h:874
const SHAPE_POLY_SET & GetCourtyard(PCB_LAYER_ID aLayer) const
Used in DRC to test the courtyard area (a complex polygon).
Definition: footprint.cpp:2233
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: footprint.cpp:1419
int m_fileFormatVersionAtLoad
Definition: footprint.h:840
wxString m_doc
Definition: footprint.h:871
FP_ZONES & Zones()
Definition: footprint.h:176
wxString GetKeywords() const
Definition: footprint.h:221
void CheckFootprintAttributes(const std::function< void(const wxString &)> &aErrorHandler)
Test if footprint attributes for type (SMD/Through hole/Other) match the expected type based on the p...
Definition: footprint.cpp:2379
PADS m_pads
Definition: footprint.h:829
virtual void swapData(BOARD_ITEM *aImage) override
Definition: footprint.cpp:2660
wxString GetNextPadNumber(const wxString &aLastPadName) const
Return the next available pad number in the footprint.
Definition: footprint.cpp:1999
int m_courtyard_cache_timestamp
Definition: footprint.h:886
int m_boundingBoxCacheTimeStamp
Definition: footprint.h:853
VECTOR2I GetPosition() const override
Definition: footprint.h:188
DRAWINGS & GraphicalItems()
Definition: footprint.h:173
FP_GROUPS m_fp_groups
Definition: footprint.h:831
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: footprint.cpp:1123
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: footprint.cpp:1370
FP_TEXT & Reference()
Definition: footprint.h:568
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1188
FP_TEXT * m_reference
Definition: footprint.h:835
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:806
wxString m_Filename
The 3D shape filename in 3D library.
Definition: footprint.h:95
const VECTOR2I & GetBezierC1_0() const
Definition: fp_shape.h:98
const VECTOR2I & GetEnd0() const
Definition: fp_shape.h:95
const VECTOR2I & GetBezierC2_0() const
Definition: fp_shape.h:101
virtual void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
Definition: fp_shape.cpp:80
VECTOR2I GetCenter0() const
Definition: fp_shape.cpp:144
const VECTOR2I & GetStart0() const
Definition: fp_shape.h:92
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: fp_shape.cpp:355
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
Definition: fp_textbox.cpp:504
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc) const
Definition: fp_textbox.cpp:464
const BOX2I GetBoundingBox() const override
Set absolute coordinates.
Definition: fp_text.cpp:235
const VECTOR2I & GetPos0() const
Definition: fp_text.h:124
void SetType(TEXT_TYPE aType)
Definition: fp_text.h:119
void SetDrawCoord()
Set relative coordinates.
Definition: fp_text.cpp:203
@ TEXT_is_REFERENCE
Definition: fp_text.h:49
@ TEXT_is_DIVERS
Definition: fp_text.h:51
@ TEXT_is_VALUE
Definition: fp_text.h:50
void KeepUpright(const EDA_ANGLE &aOldOrientation, const EDA_ANGLE &aNewOrientation)
Called when rotating the parent footprint.
Definition: fp_text.cpp:101
void SetPos0(const VECTOR2I &aPos)
Definition: fp_text.h:123
void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip entity during footprint flip.
Definition: fp_text.cpp:137
virtual wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:415
TEXT_TYPE GetType() const
Definition: fp_text.h:120
A specialization of ZONE for use in footprints.
Definition: zone.h:916
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:204
const COLLECTORS_GUIDE * GetGuide() const
Definition: collectors.h:295
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
Definition: kiid.h:48
wxString GetUniStringLibId() const
Definition: lib_id.h:148
const UTF8 & GetLibItemName() const
Definition: lib_id.h:102
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
static LSET AllLayersMask()
Definition: lset.cpp:808
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 AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
void ShapeToPolygon(SHAPE_LINE_CHAIN &aPolygon, int aScale=-1) const
Return the shape polygon in internal units in a SHAPE_LINE_CHAIN the coordinates are relatives to the...
static const int ORPHANED
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:391
Definition: pad.h:60
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:398
const wxString & GetNumber() const
Definition: pad.h:136
VECTOR2I GetPosition() const override
Definition: pad.h:203
PAD_SHAPE GetShape() const
Definition: pad.h:195
const VECTOR2I & GetPos0() const
Definition: pad.h:252
const VECTOR2I & GetSize() const
Definition: pad.h:258
Object to handle a bitmap image that can be inserted in a PCB.
Definition: pcb_bitmap.h:42
Abstract dimension API.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:95
bool AddItem(BOARD_ITEM *aItem)
Add item to group.
Definition: pcb_group.cpp:80
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
Definition: pcb_shape.cpp:390
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.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
PROPERTY_BASE & ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew, const wxString &aGroup=wxEmptyString)
Replace an existing property for a specific type.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
double Area(bool aAbsolute=true) const
Return the area of this chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
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 BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
double Area()
Count the number of arc shapes present.
bool IsEmpty() const
void CacheTriangulation(bool aPartition=true, bool aSimplify=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
int TotalVertices() const
Delete aIdx-th polygon from the set.
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
void Simplify(POLYGON_MODE aFastMode)
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
SHAPE_LINE_CHAIN & Outline(int aIndex)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
int NewOutline()
Creates a new hole in a given outline.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the aGlobalIndex-th vertex in the poly set.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void Move(const VECTOR2I &aVector) override
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
Definition: shape_simple.h:42
An abstract shape on 2D plane.
Definition: shape.h:124
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition: shape.h:179
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
SHAPE_POLY_SET * Outline()
Definition: zone.h:318
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:122
unsigned GetAssignedPriority() const
Definition: zone.h:112
This file is part of the common library.
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.
bool ConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aShapeList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler)
Function ConvertOutlineToPolygon Build a polygon (with holes) from a PCB_SHAPE list,...
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const VECTOR2I &pt)> OUTLINE_ERROR_HANDLER
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
Definition: convex_hull.cpp:87
#define _HKI(x)
@ DRCE_PADSTACK
Definition: drc_item.h:59
@ DRCE_PAD_TH_WITH_NO_HOLE
Definition: drc_item.h:78
#define _(s)
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:433
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
INSPECT_RESULT
Definition: eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:78
#define COURTYARD_CONFLICT
temporary set when moving footprints having courtyard overlapping
#define MALFORMED_F_COURTYARD
#define MALFORMED_B_COURTYARD
#define STRUCT_DELETED
flag indication structures to be erased
#define MALFORMED_COURTYARDS
#define MINIMAL_ZOOM_LEVEL_FOR_VISIBILITY
#define TEST_PT(a, b)
Definition: footprint.cpp:2681
#define TEST(a, b)
Definition: footprint.cpp:2680
static struct FOOTPRINT_DESC _FOOTPRINT_DESC
static double polygonArea(SHAPE_POLY_SET &aPolySet)
Definition: footprint.cpp:2030
INCLUDE_NPTH_T
Definition: footprint.h:56
@ DO_NOT_INCLUDE_NPTH
Definition: footprint.h:57
@ FP_SMD
Definition: footprint.h:69
@ FP_EXCLUDE_FROM_POS_FILES
Definition: footprint.h:70
@ FP_BOARD_ONLY
Definition: footprint.h:72
@ FP_EXCLUDE_FROM_BOM
Definition: footprint.h:71
@ FP_THROUGH_HOLE
Definition: footprint.h:68
#define FP_is_PLACED
In autoplace: footprint automatically placed.
Definition: footprint.h:335
#define FP_PADS_are_LOCKED
Definition: footprint.h:337
@ FRAME_FOOTPRINT_VIEWER_MODAL
Definition: frame_type.h:43
@ FRAME_FOOTPRINT_VIEWER
Definition: frame_type.h:42
@ FRAME_FOOTPRINT_EDITOR
Definition: frame_type.h:41
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.
KIID niluuid(0)
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:147
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:924
@ LAYER_LOCKED_ITEM_SHADOW
shadow layer for locked items
Definition: layer_ids.h:239
@ LAYER_CONFLICTS_SHADOW
shadow layer for items flagged conficting
Definition: layer_ids.h:241
@ LAYER_MOD_TEXT
Definition: layer_ids.h:198
@ LAYER_MOD_FR
show footprints on front
Definition: layer_ids.h:208
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:201
@ LAYER_MOD_VALUES
show footprints values (when texts are visible)
Definition: layer_ids.h:210
@ LAYER_MOD_BK
show footprints on back
Definition: layer_ids.h:209
@ LAYER_MOD_REFERENCES
show footprints references (when texts are visible)
Definition: layer_ids.h:211
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_CrtYd
Definition: layer_ids.h:117
@ F_Paste
Definition: layer_ids.h:101
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ In1_Cu
Definition: layer_ids.h:65
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:544
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:99
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:418
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ FIDUCIAL_LOCAL
a fiducial (usually a smd) local to the parent footprint
@ FIDUCIAL_GLBL
a fiducial (usually a smd) for the full board
@ HEATSINK
a pad used as heat sink, usually in SMD footprints
@ NONE
no special fabrication property
@ TESTPOINT
a test point pad
@ CASTELLATED
a pad with a castellated through hole
@ BGA
Smd pad, used in BGA footprints.
#define TYPE_HASH(x)
Definition: property.h:63
#define NO_SETTER(owner, type)
Definition: property.h:734
@ PT_DEGREE
Angle expressed in degrees.
Definition: property.h:58
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:56
#define REGISTER_TYPE(x)
Definition: property_mgr.h:328
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Collection of utility functions for component reference designators (refdes)
std::vector< FAB_LAYER_COLOR > dummy
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
int GetTrailingInt(const wxString &aStr)
Gets the trailing int, if any, from a string.
constexpr double IUTomm(int iu) const
Definition: base_units.h:87
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
bool operator()(const BOARD_ITEM *itemA, const BOARD_ITEM *itemB) const
Definition: footprint.cpp:2684
bool operator()(const PAD *aFirst, const PAD *aSecond) const
Definition: footprint.cpp:2725
bool operator()(const FP_ZONE *aFirst, const FP_ZONE *aSecond) const
Definition: footprint.cpp:2741
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_FP_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:95
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:115
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_FP_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:97
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:104
@ PCB_FP_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:99
@ PCB_FP_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:96
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
@ PCB_BITMAP_T
class PCB_BITMAP, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_FP_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:98
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ NONE
Pads are not covered.
@ FULL
pads are covered by copper