KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 *
8 * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#include <iterator>
29
30#include <wx/log.h>
31
32#include <drc/drc_rtree.h>
34#include <board_commit.h>
35#include <board.h>
36#include <core/arraydim.h>
37#include <core/kicad_algo.h>
40#include <footprint.h>
41#include <pcb_base_frame.h>
42#include <pcb_track.h>
43#include <pcb_marker.h>
44#include <pcb_group.h>
45#include <pcb_generator.h>
46#include <pcb_target.h>
47#include <pcb_shape.h>
48#include <pcb_text.h>
49#include <pcb_textbox.h>
50#include <pcb_table.h>
51#include <pcb_dimension.h>
52#include <pgm_base.h>
53#include <pcbnew_settings.h>
54#include <progress_reporter.h>
55#include <project.h>
60#include <reporter.h>
61#include <tool/tool_manager.h>
63#include <string_utils.h>
64#include <core/thread_pool.h>
65#include <zone.h>
66
67// This is an odd place for this, but CvPcb won't link if it's in board_item.cpp like I first
68// tried it.
70
71
74 m_LegacyDesignSettingsLoaded( false ),
75 m_LegacyCopperEdgeClearanceLoaded( false ),
76 m_LegacyNetclassesLoaded( false ),
77 m_boardUse( BOARD_USE::NORMAL ),
78 m_timeStamp( 1 ),
79 m_paper( PAGE_INFO::A4 ),
80 m_project( nullptr ),
81 m_userUnits( EDA_UNITS::MILLIMETRES ),
82 m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
83 m_NetInfo( this )
84{
85 // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
86 // A too large value do not allow safely connecting 2 shapes like very short segments.
88
89 // we have not loaded a board yet, assume latest until then.
90 m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
91
92 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
93 {
95
96 if( IsCopperLayer( layer ) )
97 m_layers[layer].m_type = LT_SIGNAL;
98 else
100 }
101
102 // Creates a zone to show sloder mask bridges created by a min web value
103 // it it just to show them
104 m_SolderMaskBridges = new ZONE( this );
105 m_SolderMaskBridges->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER );
107 int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
109 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
110 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
111 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, +infinity ) );
112 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, -infinity ) );
114
116
117 // Initialize default netclass.
118 bds.m_NetSettings->m_DefaultNetClass = std::make_shared<NETCLASS>( NETCLASS::Default );
119 bds.m_NetSettings->m_DefaultNetClass->SetDescription( _( "This is the default net class." ) );
120
121 bds.UseCustomTrackViaSize( false );
122
123 // Initialize ratsnest
124 m_connectivity.reset( new CONNECTIVITY_DATA() );
125
126 // Set flag bits on these that will only be cleared if these are loaded from a legacy file
127 m_LegacyVisibleLayers.reset().set( Rescue );
129}
130
131
133{
134 // Untangle group parents before doing any deleting
135 for( PCB_GROUP* group : m_groups )
136 {
137 for( BOARD_ITEM* item : group->GetItems() )
138 item->SetParentGroup( nullptr );
139 }
140
141 for( PCB_GENERATOR* generator : m_generators )
142 {
143 for( BOARD_ITEM* item : generator->GetItems() )
144 item->SetParentGroup( nullptr );
145 }
146
147 // Clean up the owned elements
149
150 for( ZONE* zone : m_zones )
151 delete zone;
152
153 m_zones.clear();
154
155 delete m_SolderMaskBridges;
156
157 for( FOOTPRINT* footprint : m_footprints )
158 delete footprint;
159
160 m_footprints.clear();
161
162 for( PCB_TRACK* t : m_tracks )
163 delete t;
164
165 m_tracks.clear();
166
167 for( BOARD_ITEM* d : m_drawings )
168 delete d;
169
170 m_drawings.clear();
171
172 for( PCB_GROUP* g : m_groups )
173 delete g;
174
175 m_groups.clear();
176
177 for( PCB_GENERATOR* g : m_generators )
178 delete g;
179
180 m_generators.clear();
181}
182
183
185{
186 if( !GetConnectivity()->Build( this, aReporter ) )
187 return false;
188
190 return true;
191}
192
193
194void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly )
195{
196 if( m_project )
197 ClearProject();
198
199 m_project = aProject;
200
201 if( aProject && !aReferenceOnly )
202 {
203 PROJECT_FILE& project = aProject->GetProjectFile();
204
205 // Link the design settings object to the project file
206 project.m_BoardSettings = &GetDesignSettings();
207
208 // Set parent, which also will load the values from JSON stored in the project if we don't
209 // have legacy design settings loaded already
210 project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
211
212 // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
213 // list at this point. If we loaded anything into it from a legacy board file then we
214 // want to transfer it over to the project netclasses list.
216 {
217 std::shared_ptr<NET_SETTINGS> legacySettings = GetDesignSettings().m_NetSettings;
218 std::shared_ptr<NET_SETTINGS>& projectSettings = project.NetSettings();
219
220 projectSettings->m_DefaultNetClass = legacySettings->m_DefaultNetClass;
221 projectSettings->m_NetClasses = legacySettings->m_NetClasses;
222 projectSettings->m_NetClassPatternAssignments =
223 std::move( legacySettings->m_NetClassPatternAssignments );
224 projectSettings->m_NetClassPatternAssignmentCache.clear();
225 }
226
227 // Now update the DesignSettings' netclass pointer to point into the project.
228 GetDesignSettings().m_NetSettings = project.NetSettings();
229 }
230}
231
232
234{
235 if( !m_project )
236 return;
237
239
240 // Owned by the BOARD
241 if( project.m_BoardSettings )
242 {
243 project.ReleaseNestedSettings( project.m_BoardSettings );
244 project.m_BoardSettings = nullptr;
245 }
246
248 GetDesignSettings().SetParent( nullptr );
249 m_project = nullptr;
250}
251
252
254{
255 m_timeStamp++;
256
257 if( !m_IntersectsAreaCache.empty()
258 || !m_EnclosedByAreaCache.empty()
262 || !m_LayerExpressionCache.empty()
263 || !m_ZoneBBoxCache.empty()
265 {
266 std::unique_lock<std::mutex> cacheLock( m_CachesMutex );
267
268 m_IntersectsAreaCache.clear();
269 m_EnclosedByAreaCache.clear();
274
275 m_ZoneBBoxCache.clear();
276
277 m_CopperItemRTreeCache = nullptr;
278
279 // These are always regenerated before use, but still probably safer to clear them
280 // while we're here.
283 m_DRCZones.clear();
284 m_DRCCopperZones.clear();
287 }
288}
289
290
292{
293 std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
294
295 for( PCB_MARKER* marker : GetBoard()->Markers() )
296 {
297 if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
298 {
299 const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
300 m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
301 m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
302 }
303 }
304
305 GetConnectivity()->RunOnUnconnectedEdges(
306 [&]( CN_EDGE& aEdge )
307 {
308 if( aEdge.GetSourceNode() && aEdge.GetTargetNode()
309 && !aEdge.GetSourceNode()->Dirty() && !aEdge.GetTargetNode()->Dirty() )
310 {
311 std::pair<KIID, KIID> ids = { aEdge.GetSourceNode()->Parent()->m_Uuid,
312 aEdge.GetTargetNode()->Parent()->m_Uuid };
313
314 aEdge.SetVisible( m_ratsnestExclusions.count( ids ) == 0 );
315 }
316
317 return true;
318 } );
319}
320
321
322std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
323{
324 for( PCB_MARKER* marker : GetBoard()->Markers() )
325 {
326 wxString serialized = marker->Serialize();
327 std::set<wxString>::iterator it = m_designSettings->m_DrcExclusions.find( serialized );
328
329 if( it != m_designSettings->m_DrcExclusions.end() )
330 {
331 marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] );
332 m_designSettings->m_DrcExclusions.erase( it );
333 }
334 }
335
336 std::vector<PCB_MARKER*> newMarkers;
337
338 if( aCreateMarkers )
339 {
340 for( const wxString& serialized : m_designSettings->m_DrcExclusions )
341 {
342 PCB_MARKER* marker = PCB_MARKER::Deserialize( serialized );
343
344 if( !marker )
345 continue;
346
347 // Check to see if items still exist
348 for( const KIID& guid : marker->GetRCItem()->GetIDs() )
349 {
351 {
352 delete marker;
353 marker = nullptr;
354 break;
355 }
356 }
357
358 if( marker )
359 {
360 marker->SetExcluded( true, m_designSettings->m_DrcExclusionComments[serialized] );
361 newMarkers.push_back( marker );
362 }
363 }
364 }
365
366 m_designSettings->m_DrcExclusions.clear();
367
368 return newMarkers;
369}
370
371
372void BOARD::GetContextualTextVars( wxArrayString* aVars ) const
373{
374 auto add =
375 [&]( const wxString& aVar )
376 {
377 if( !alg::contains( *aVars, aVar ) )
378 aVars->push_back( aVar );
379 };
380
381 add( wxT( "LAYER" ) );
382 add( wxT( "FILENAME" ) );
383 add( wxT( "FILEPATH" ) );
384 add( wxT( "PROJECTNAME" ) );
385
387
388 if( GetProject() )
389 {
390 for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
391 add( entry.first );
392 }
393}
394
395
396bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
397{
398 if( token->Contains( ':' ) )
399 {
400 wxString remainder;
401 wxString ref = token->BeforeFirst( ':', &remainder );
402 BOARD_ITEM* refItem = GetItem( KIID( ref ) );
403
404 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
405 {
406 FOOTPRINT* refFP = static_cast<FOOTPRINT*>( refItem );
407
408 if( refFP->ResolveTextVar( &remainder, aDepth + 1 ) )
409 {
410 *token = remainder;
411 return true;
412 }
413 }
414 }
415
416 if( token->IsSameAs( wxT( "FILENAME" ) ) )
417 {
418 wxFileName fn( GetFileName() );
419 *token = fn.GetFullName();
420 return true;
421 }
422 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
423 {
424 wxFileName fn( GetFileName() );
425 *token = fn.GetFullPath();
426 return true;
427 }
428 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) && GetProject() )
429 {
430 *token = GetProject()->GetProjectName();
431 return true;
432 }
433
434 wxString var = *token;
435
436 if( GetTitleBlock().TextVarResolver( token, m_project ) )
437 {
438 return true;
439 }
440 else if( m_properties.count( var ) )
441 {
442 *token = m_properties.at( var );
443 return true;
444 }
445
446 if( GetProject() && GetProject()->TextVarResolver( token ) )
447 return true;
448
449 return false;
450}
451
452
454{
455 return ZeroOffset;
456}
457
458
459void BOARD::SetPosition( const VECTOR2I& aPos )
460{
461 wxLogWarning( wxT( "This should not be called on the BOARD object") );
462}
463
464
465void BOARD::Move( const VECTOR2I& aMoveVector ) // overload
466{
467 INSPECTOR_FUNC inspector =
468 [&] ( EDA_ITEM* item, void* testData )
469 {
470 if( BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item ) )
471 {
472 // aMoveVector was snapshotted, don't need "data".
473 // Only move the top level group
474 if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() )
475 board_item->Move( aMoveVector );
476 }
477
478 return INSPECT_RESULT::CONTINUE;
479 };
480
481 Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems );
482}
483
484
485TRACKS BOARD::TracksInNet( int aNetCode )
486{
487 TRACKS ret;
488
489 INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
490 {
491 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
492
493 if( t->GetNetCode() == aNetCode )
494 ret.push_back( t );
495
496 return INSPECT_RESULT::CONTINUE;
497 };
498
499 // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
500 // appends all in aNetCode to ret.
501 Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
502
503 return ret;
504}
505
506
507bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
508{
509 if( unsigned( aIndex ) < arrayDim( m_layers ) )
510 {
511 m_layers[ aIndex ] = aLayer;
512 return true;
513 }
514
515 return false;
516}
517
518
519PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
520{
521 // Check the BOARD physical layer names.
522 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
523 {
524 if ( m_layers[ layer ].m_name == aLayerName || m_layers[ layer ].m_userName == aLayerName )
525 return ToLAYER_ID( layer );
526 }
527
528 // Otherwise fall back to the system standard layer names for virtual layers.
529 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
530 {
531 if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
532 return ToLAYER_ID( layer );
533 }
534
535 return UNDEFINED_LAYER;
536}
537
538
539const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
540{
541 // All layer names are stored in the BOARD.
542 if( IsLayerEnabled( aLayer ) )
543 {
544 // Standard names were set in BOARD::BOARD() but they may be over-ridden by
545 // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
546 // if it was set. Otherwise return the Standard English layer name.
547 if( !m_layers[aLayer].m_userName.IsEmpty() )
548 return m_layers[aLayer].m_userName;
549 }
550
551 return GetStandardLayerName( aLayer );
552}
553
554
555bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
556{
557 wxCHECK( !aLayerName.IsEmpty(), false );
558
559 // no quote chars in the name allowed
560 if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
561 return false;
562
563 if( IsLayerEnabled( aLayer ) )
564 {
565 m_layers[aLayer].m_userName = aLayerName;
566 return true;
567 }
568
569 return false;
570}
571
572
574{
575 if( !IsCopperLayer( aLayer ) )
576 return LT_SIGNAL;
577
578 if( IsLayerEnabled( aLayer ) )
579 return m_layers[aLayer].m_type;
580
581 return LT_SIGNAL;
582}
583
584
585bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
586{
587 if( !IsCopperLayer( aLayer ) )
588 return false;
589
590 if( IsLayerEnabled( aLayer ) )
591 {
592 m_layers[aLayer].m_type = aLayerType;
593 return true;
594 }
595
596 return false;
597}
598
599
600const char* LAYER::ShowType( LAYER_T aType )
601{
602 switch( aType )
603 {
604 default:
605 case LT_SIGNAL: return "signal";
606 case LT_POWER: return "power";
607 case LT_MIXED: return "mixed";
608 case LT_JUMPER: return "jumper";
609 }
610}
611
612
613LAYER_T LAYER::ParseType( const char* aType )
614{
615 if( strcmp( aType, "signal" ) == 0 )
616 return LT_SIGNAL;
617 else if( strcmp( aType, "power" ) == 0 )
618 return LT_POWER;
619 else if( strcmp( aType, "mixed" ) == 0 )
620 return LT_MIXED;
621 else if( strcmp( aType, "jumper" ) == 0 )
622 return LT_JUMPER;
623 else
624 return LT_UNDEFINED;
625}
626
627
629{
631}
632
633
635{
637}
638
639
640int BOARD::LayerDepth( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer ) const
641{
642 if( aStartLayer > aEndLayer )
643 std::swap( aStartLayer, aEndLayer );
644
645 if( aEndLayer == B_Cu )
646 aEndLayer = ToLAYER_ID( F_Cu + GetCopperLayerCount() - 1 );
647
648 return aEndLayer - aStartLayer;
649}
650
651
653{
655}
656
657
659{
660 // If there is no project, assume layer is visible always
661 return GetDesignSettings().IsLayerEnabled( aLayer )
663}
664
665
667{
669}
670
671
673{
674 GetDesignSettings().SetEnabledLayers( aLayerSet );
675}
676
677
679{
680 return GetDesignSettings().IsLayerEnabled( aLayer );
681}
682
683
685{
686 if( m_project )
688}
689
690
692{
693 // Call SetElementVisibility for each item
694 // to ensure specific calculations that can be needed by some items,
695 // just changing the visibility flags could be not sufficient.
696 for( size_t i = 0; i < aSet.size(); i++ )
697 SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
698}
699
700
702{
703 SetVisibleLayers( LSET().set() );
704
705 // Call SetElementVisibility for each item,
706 // to ensure specific calculations that can be needed by some items
708 SetElementVisibility( ii, true );
709}
710
711
713{
715}
716
717
719{
721}
722
723
724void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
725{
726 if( m_project )
728
729 switch( aLayer )
730 {
731 case LAYER_RATSNEST:
732 {
733 // because we have a tool to show/hide ratsnest relative to a pad or a footprint
734 // so the hide/show option is a per item selection
735
736 for( PCB_TRACK* track : Tracks() )
737 track->SetLocalRatsnestVisible( isEnabled );
738
739 for( FOOTPRINT* footprint : Footprints() )
740 {
741 for( PAD* pad : footprint->Pads() )
742 pad->SetLocalRatsnestVisible( isEnabled );
743 }
744
745 for( ZONE* zone : Zones() )
746 zone->SetLocalRatsnestVisible( isEnabled );
747
748 break;
749 }
750
751 default:
752 ;
753 }
754}
755
756
758{
759 switch( aLayer )
760 {
763 default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true;
764 }
765}
766
767
768
770{
771 return *m_designSettings;
772}
773
774
776{
777 int worstClearance = m_designSettings->GetBiggestClearanceValue();
778
779 for( ZONE* zone : m_zones )
780 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
781
782 for( FOOTPRINT* footprint : m_footprints )
783 {
784 for( PAD* pad : footprint->Pads() )
785 {
786 std::optional<int> override = pad->GetClearanceOverrides( nullptr );
787
788 if( override.has_value() )
789 worstClearance = std::max( worstClearance, override.value() );
790 }
791
792 for( ZONE* zone : footprint->Zones() )
793 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
794 }
795
796 return worstClearance;
797}
798
799
800void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<ZONE*>& aZones )
801{
802 std::vector<ZONE*> zones = aZones;
803
804 if( zones.empty() )
805 zones = m_zones;
806
807 if( zones.empty() )
808 return;
809
810 if( aReporter )
811 aReporter->Report( _( "Tessellating copper zones..." ) );
812
814 std::vector<std::future<size_t>> returns;
815
816 returns.reserve( zones.size() );
817
818 auto cache_zones = [aReporter]( ZONE* aZone ) -> size_t
819 {
820 if( aReporter && aReporter->IsCancelled() )
821 return 0;
822
823 aZone->CacheTriangulation();
824
825 if( aReporter )
826 aReporter->AdvanceProgress();
827
828 return 1;
829 };
830
831 for( ZONE* zone : zones )
832 returns.emplace_back( tp.submit( cache_zones, zone ) );
833
834 // Finalize the triangulation threads
835 for( const std::future<size_t>& ret : returns )
836 {
837 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
838
839 while( status != std::future_status::ready )
840 {
841 if( aReporter )
842 aReporter->KeepRefreshing();
843
844 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
845 }
846 }
847}
848
849
850void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
851{
852 if( aBoardItem == nullptr )
853 {
854 wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem nullptr" ) );
855 return;
856 }
857
858 switch( aBoardItem->Type() )
859 {
860 case PCB_NETINFO_T:
861 m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
862 break;
863
864 // this one uses a vector
865 case PCB_MARKER_T:
866 m_markers.push_back( (PCB_MARKER*) aBoardItem );
867 break;
868
869 // this one uses a vector
870 case PCB_GROUP_T:
871 m_groups.push_back( (PCB_GROUP*) aBoardItem );
872 break;
873
874 // this one uses a vector
875 case PCB_GENERATOR_T:
876 m_generators.push_back( (PCB_GENERATOR*) aBoardItem );
877 break;
878
879 // this one uses a vector
880 case PCB_ZONE_T:
881 m_zones.push_back( (ZONE*) aBoardItem );
882 break;
883
884 case PCB_TRACE_T:
885 case PCB_VIA_T:
886 case PCB_ARC_T:
887
888 // N.B. This inserts a small memory leak as we lose the
889 if( !IsCopperLayer( aBoardItem->GetLayer() ) )
890 {
891 wxFAIL_MSG( wxT( "BOARD::Add() Cannot place Track on non-copper layer" ) );
892 return;
893 }
894
895 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
896 m_tracks.push_back( static_cast<PCB_TRACK*>( aBoardItem ) );
897 else
898 m_tracks.push_front( static_cast<PCB_TRACK*>( aBoardItem ) );
899
900 break;
901
902 case PCB_FOOTPRINT_T:
903 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
904 m_footprints.push_back( static_cast<FOOTPRINT*>( aBoardItem ) );
905 else
906 m_footprints.push_front( static_cast<FOOTPRINT*>( aBoardItem ) );
907
908 break;
909
911 case PCB_DIM_CENTER_T:
912 case PCB_DIM_RADIAL_T:
914 case PCB_DIM_LEADER_T:
915 case PCB_SHAPE_T:
917 case PCB_FIELD_T:
918 case PCB_TEXT_T:
919 case PCB_TEXTBOX_T:
920 case PCB_TABLE_T:
921 case PCB_TARGET_T:
922 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
923 m_drawings.push_back( aBoardItem );
924 else
925 m_drawings.push_front( aBoardItem );
926
927 break;
928
929 // other types may use linked list
930 default:
931 {
932 wxString msg;
933 msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
934 aBoardItem->Type() );
935 wxFAIL_MSG( msg );
936 return;
937 }
938 break;
939 }
940
941 aBoardItem->SetParent( this );
942 aBoardItem->ClearEditFlags();
943
944 if( !aSkipConnectivity )
945 m_connectivity->Add( aBoardItem );
946
947 if( aMode != ADD_MODE::BULK_INSERT && aMode != ADD_MODE::BULK_APPEND )
948 {
950 }
951}
952
953
954void BOARD::FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems )
955{
957}
958
959
960void BOARD::FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems )
961{
963}
964
965
966void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
967{
968 // find these calls and fix them! Don't send me no stinking' nullptr.
969 wxASSERT( aBoardItem );
970
971 switch( aBoardItem->Type() )
972 {
973 case PCB_NETINFO_T:
974 {
975 NETINFO_ITEM* netItem = static_cast<NETINFO_ITEM*>( aBoardItem );
977
978 for( BOARD_CONNECTED_ITEM* boardItem : AllConnectedItems() )
979 {
980 if( boardItem->GetNet() == netItem )
981 boardItem->SetNet( unconnected );
982 }
983
984 m_NetInfo.RemoveNet( netItem );
985 break;
986 }
987
988 case PCB_MARKER_T:
989 alg::delete_matching( m_markers, aBoardItem );
990 break;
991
992 case PCB_GROUP_T:
993 alg::delete_matching( m_groups, aBoardItem );
994 break;
995
996 case PCB_ZONE_T:
997 alg::delete_matching( m_zones, aBoardItem );
998 break;
999
1000 case PCB_GENERATOR_T:
1001 alg::delete_matching( m_generators, aBoardItem );
1002 break;
1003
1004 case PCB_FOOTPRINT_T:
1005 alg::delete_matching( m_footprints, aBoardItem );
1006 break;
1007
1008 case PCB_TRACE_T:
1009 case PCB_ARC_T:
1010 case PCB_VIA_T:
1011 alg::delete_matching( m_tracks, aBoardItem );
1012 break;
1013
1014 case PCB_DIM_ALIGNED_T:
1015 case PCB_DIM_CENTER_T:
1016 case PCB_DIM_RADIAL_T:
1018 case PCB_DIM_LEADER_T:
1019 case PCB_SHAPE_T:
1021 case PCB_FIELD_T:
1022 case PCB_TEXT_T:
1023 case PCB_TEXTBOX_T:
1024 case PCB_TABLE_T:
1025 case PCB_TARGET_T:
1026 alg::delete_matching( m_drawings, aBoardItem );
1027 break;
1028
1029 // other types may use linked list
1030 default:
1031 wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
1032 }
1033
1034 aBoardItem->SetFlags( STRUCT_DELETED );
1035
1036 PCB_GROUP* parentGroup = aBoardItem->GetParentGroup();
1037
1038 if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
1039 parentGroup->RemoveItem( aBoardItem );
1040
1041 m_connectivity->Remove( aBoardItem );
1042
1043 if( aRemoveMode != REMOVE_MODE::BULK )
1045}
1046
1047
1048wxString BOARD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1049{
1050 return wxString::Format( _( "PCB" ) );
1051}
1052
1053
1055{
1056 INSPECTOR_FUNC inspector =
1057 [&]( EDA_ITEM* descendant, void* aTestData )
1058 {
1059 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( descendant );
1060
1061 if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC )
1062 {
1063 dimension->UpdateUnits();
1064
1065 if( aView )
1066 aView->Update( dimension );
1067 }
1068
1069 return INSPECT_RESULT::CONTINUE;
1070 };
1071
1072 aItem->Visit( inspector, nullptr, { PCB_DIM_ALIGNED_T,
1076 PCB_DIM_RADIAL_T } );
1077}
1078
1079
1081{
1082 // the vector does not know how to delete the PCB_MARKER, it holds pointers
1083 for( PCB_MARKER* marker : m_markers )
1084 delete marker;
1085
1086 m_markers.clear();
1087}
1088
1089
1090void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
1091{
1092 // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
1093 MARKERS remaining;
1094
1095 for( PCB_MARKER* marker : m_markers )
1096 {
1097 if( ( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION && aExclusions )
1098 || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) )
1099 {
1100 delete marker;
1101 }
1102 else
1103 {
1104 remaining.push_back( marker );
1105 }
1106 }
1107
1108 m_markers = remaining;
1109}
1110
1111
1113{
1114 for( FOOTPRINT* footprint : m_footprints )
1115 delete footprint;
1116
1117 m_footprints.clear();
1118}
1119
1120
1121BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
1122{
1123 if( aID == niluuid )
1124 return nullptr;
1125
1126 for( PCB_TRACK* track : Tracks() )
1127 {
1128 if( track->m_Uuid == aID )
1129 return track;
1130 }
1131
1132 for( FOOTPRINT* footprint : Footprints() )
1133 {
1134 if( footprint->m_Uuid == aID )
1135 return footprint;
1136
1137 for( PAD* pad : footprint->Pads() )
1138 {
1139 if( pad->m_Uuid == aID )
1140 return pad;
1141 }
1142
1143 for( PCB_FIELD* field : footprint->Fields() )
1144 {
1145 if( field->m_Uuid == aID )
1146 return field;
1147 }
1148
1149 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1150 {
1151 if( drawing->m_Uuid == aID )
1152 return drawing;
1153 }
1154
1155 for( BOARD_ITEM* zone : footprint->Zones() )
1156 {
1157 if( zone->m_Uuid == aID )
1158 return zone;
1159 }
1160
1161 for( PCB_GROUP* group : footprint->Groups() )
1162 {
1163 if( group->m_Uuid == aID )
1164 return group;
1165 }
1166 }
1167
1168 for( ZONE* zone : Zones() )
1169 {
1170 if( zone->m_Uuid == aID )
1171 return zone;
1172 }
1173
1174 for( BOARD_ITEM* drawing : Drawings() )
1175 {
1176 if( drawing->Type() == PCB_TABLE_T )
1177 {
1178 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( drawing )->GetCells() )
1179 {
1180 if( cell->m_Uuid == aID )
1181 return drawing;
1182 }
1183 }
1184
1185 if( drawing->m_Uuid == aID )
1186 return drawing;
1187 }
1188
1189 for( PCB_MARKER* marker : m_markers )
1190 {
1191 if( marker->m_Uuid == aID )
1192 return marker;
1193 }
1194
1195 for( PCB_GROUP* group : m_groups )
1196 {
1197 if( group->m_Uuid == aID )
1198 return group;
1199 }
1200
1201 for( PCB_GENERATOR* generator : m_generators )
1202 {
1203 if( generator->m_Uuid == aID )
1204 return generator;
1205 }
1206
1207
1208 for( NETINFO_ITEM* netInfo : m_NetInfo )
1209 {
1210 if( netInfo->m_Uuid == aID )
1211 return netInfo;
1212 }
1213
1214 if( m_Uuid == aID )
1215 return const_cast<BOARD*>( this );
1216
1217 // Not found; weak reference has been deleted.
1219}
1220
1221
1222void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1223{
1224 // the board itself
1225 aMap[ m_Uuid ] = this;
1226
1227 for( PCB_TRACK* track : Tracks() )
1228 aMap[ track->m_Uuid ] = track;
1229
1230 for( FOOTPRINT* footprint : Footprints() )
1231 {
1232 aMap[ footprint->m_Uuid ] = footprint;
1233
1234 for( PAD* pad : footprint->Pads() )
1235 aMap[ pad->m_Uuid ] = pad;
1236
1237 aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference();
1238 aMap[ footprint->Value().m_Uuid ] = &footprint->Value();
1239
1240 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1241 aMap[ drawing->m_Uuid ] = drawing;
1242 }
1243
1244 for( ZONE* zone : Zones() )
1245 aMap[ zone->m_Uuid ] = zone;
1246
1247 for( BOARD_ITEM* drawing : Drawings() )
1248 aMap[ drawing->m_Uuid ] = drawing;
1249
1250 for( PCB_MARKER* marker : m_markers )
1251 aMap[ marker->m_Uuid ] = marker;
1252
1253 for( PCB_GROUP* group : m_groups )
1254 aMap[ group->m_Uuid ] = group;
1255
1256 for( PCB_GENERATOR* generator : m_generators )
1257 aMap[ generator->m_Uuid ] = generator;
1258}
1259
1260
1261wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
1262{
1263 wxString newbuf;
1264 size_t sourceLen = aSource.length();
1265
1266 for( size_t i = 0; i < sourceLen; ++i )
1267 {
1268 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1269 {
1270 wxString token;
1271 bool isCrossRef = false;
1272
1273 for( i = i + 2; i < sourceLen; ++i )
1274 {
1275 if( aSource[i] == '}' )
1276 break;
1277
1278 if( aSource[i] == ':' )
1279 isCrossRef = true;
1280
1281 token.append( aSource[i] );
1282 }
1283
1284 if( isCrossRef )
1285 {
1286 wxString remainder;
1287 wxString ref = token.BeforeFirst( ':', &remainder );
1288
1289 for( const FOOTPRINT* footprint : Footprints() )
1290 {
1291 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
1292 {
1293 wxString test( remainder );
1294
1295 if( footprint->ResolveTextVar( &test ) )
1296 token = footprint->m_Uuid.AsString() + wxT( ":" ) + remainder;
1297
1298 break;
1299 }
1300 }
1301 }
1302
1303 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1304 }
1305 else
1306 {
1307 newbuf.append( aSource[i] );
1308 }
1309 }
1310
1311 return newbuf;
1312}
1313
1314
1315wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
1316{
1317 wxString newbuf;
1318 size_t sourceLen = aSource.length();
1319
1320 for( size_t i = 0; i < sourceLen; ++i )
1321 {
1322 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1323 {
1324 wxString token;
1325 bool isCrossRef = false;
1326
1327 for( i = i + 2; i < sourceLen; ++i )
1328 {
1329 if( aSource[i] == '}' )
1330 break;
1331
1332 if( aSource[i] == ':' )
1333 isCrossRef = true;
1334
1335 token.append( aSource[i] );
1336 }
1337
1338 if( isCrossRef )
1339 {
1340 wxString remainder;
1341 wxString ref = token.BeforeFirst( ':', &remainder );
1342 BOARD_ITEM* refItem = GetItem( KIID( ref ) );
1343
1344 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
1345 {
1346 token = static_cast<FOOTPRINT*>( refItem )->GetReference() + wxT( ":" )
1347 + remainder;
1348 }
1349 }
1350
1351 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1352 }
1353 else
1354 {
1355 newbuf.append( aSource[i] );
1356 }
1357 }
1358
1359 return newbuf;
1360}
1361
1362
1363unsigned BOARD::GetNodesCount( int aNet ) const
1364{
1365 unsigned retval = 0;
1366
1367 for( FOOTPRINT* footprint : Footprints() )
1368 {
1369 for( PAD* pad : footprint->Pads() )
1370 {
1371 if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1372 retval++;
1373 }
1374 }
1375
1376 return retval;
1377}
1378
1379
1380BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1381{
1382 BOX2I bbox;
1383 LSET visible = GetVisibleLayers();
1384 bool showHiddenText = IsElementVisible( LAYER_HIDDEN_TEXT );
1385
1386 if( PgmOrNull() && PgmOrNull()->m_Printing )
1387 showHiddenText = false;
1388
1389 // If the board is just showing a footprint, we want all footprint layers
1390 // included in the bounding box
1391 if( IsFootprintHolder() )
1392 visible.set();
1393
1394 if( aBoardEdgesOnly )
1395 visible.set( Edge_Cuts );
1396
1397 // Check shapes, dimensions, texts, and fiducials
1398 for( BOARD_ITEM* item : m_drawings )
1399 {
1400 if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
1401 continue;
1402
1403 if( ( item->GetLayerSet() & visible ).any() )
1404 bbox.Merge( item->GetBoundingBox() );
1405 }
1406
1407 // Check footprints
1408 for( FOOTPRINT* footprint : m_footprints )
1409 {
1410 if( !( footprint->GetLayerSet() & visible ).any() )
1411 continue;
1412
1413 if( aBoardEdgesOnly )
1414 {
1415 for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
1416 {
1417 if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_SHAPE_T )
1418 bbox.Merge( edge->GetBoundingBox() );
1419 }
1420 }
1421 else
1422 {
1423 bbox.Merge( footprint->GetBoundingBox( true, showHiddenText ) );
1424 }
1425 }
1426
1427 if( !aBoardEdgesOnly )
1428 {
1429 // Check tracks
1430 for( PCB_TRACK* track : m_tracks )
1431 {
1432 if( ( track->GetLayerSet() & visible ).any() )
1433 bbox.Merge( track->GetBoundingBox() );
1434 }
1435
1436 // Check zones
1437 for( ZONE* aZone : m_zones )
1438 {
1439 if( ( aZone->GetLayerSet() & visible ).any() )
1440 bbox.Merge( aZone->GetBoundingBox() );
1441 }
1442 }
1443
1444 return bbox;
1445}
1446
1447
1448void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1449{
1450 int padCount = 0;
1451 int viaCount = 0;
1452 int trackSegmentCount = 0;
1453 std::set<int> netCodes;
1454 int unconnected = GetConnectivity()->GetUnconnectedCount( true );
1455
1456 for( PCB_TRACK* item : m_tracks )
1457 {
1458 if( item->Type() == PCB_VIA_T )
1459 viaCount++;
1460 else
1461 trackSegmentCount++;
1462
1463 if( item->GetNetCode() > 0 )
1464 netCodes.insert( item->GetNetCode() );
1465 }
1466
1467 for( FOOTPRINT* footprint : Footprints() )
1468 {
1469 for( PAD* pad : footprint->Pads() )
1470 {
1471 padCount++;
1472
1473 if( pad->GetNetCode() > 0 )
1474 netCodes.insert( pad->GetNetCode() );
1475 }
1476 }
1477
1478 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%d" ), padCount ) );
1479 aList.emplace_back( _( "Vias" ), wxString::Format( wxT( "%d" ), viaCount ) );
1480 aList.emplace_back( _( "Track Segments" ), wxString::Format( wxT( "%d" ), trackSegmentCount ) );
1481 aList.emplace_back( _( "Nets" ), wxString::Format( wxT( "%d" ), (int) netCodes.size() ) );
1482 aList.emplace_back( _( "Unrouted" ), wxString::Format( wxT( "%d" ), unconnected ) );
1483}
1484
1485
1486INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData,
1487 const std::vector<KICAD_T>& scanTypes )
1488{
1489#if 0 && defined(DEBUG)
1490 std::cout << GetClass().mb_str() << ' ';
1491#endif
1492
1493 bool footprintsScanned = false;
1494 bool drawingsScanned = false;
1495 bool tracksScanned = false;
1496
1497 for( KICAD_T scanType : scanTypes )
1498 {
1499 switch( scanType )
1500 {
1501 case PCB_T:
1502 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
1503 return INSPECT_RESULT::QUIT;
1504
1505 break;
1506
1507 /*
1508 * Instances of the requested KICAD_T live in a list, either one that I manage, or one
1509 * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
1510 * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
1511 */
1512
1513 case PCB_FOOTPRINT_T:
1514 case PCB_PAD_T:
1515 case PCB_SHAPE_T:
1517 case PCB_FIELD_T:
1518 case PCB_TEXT_T:
1519 case PCB_TEXTBOX_T:
1520 case PCB_TABLE_T:
1521 case PCB_TABLECELL_T:
1522 case PCB_DIM_ALIGNED_T:
1523 case PCB_DIM_CENTER_T:
1524 case PCB_DIM_RADIAL_T:
1526 case PCB_DIM_LEADER_T:
1527 case PCB_TARGET_T:
1528 if( !footprintsScanned )
1529 {
1530 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1531 == INSPECT_RESULT::QUIT )
1532 {
1533 return INSPECT_RESULT::QUIT;
1534 }
1535
1536 footprintsScanned = true;
1537 }
1538
1539 if( !drawingsScanned )
1540 {
1541 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, scanTypes )
1542 == INSPECT_RESULT::QUIT )
1543 {
1544 return INSPECT_RESULT::QUIT;
1545 }
1546
1547 drawingsScanned = true;
1548 }
1549
1550 break;
1551
1552 case PCB_VIA_T:
1553 case PCB_TRACE_T:
1554 case PCB_ARC_T:
1555 if( !tracksScanned )
1556 {
1557 if( IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, scanTypes )
1558 == INSPECT_RESULT::QUIT )
1559 {
1560 return INSPECT_RESULT::QUIT;
1561 }
1562
1563 tracksScanned = true;
1564 }
1565
1566 break;
1567
1568 case PCB_MARKER_T:
1569 for( PCB_MARKER* marker : m_markers )
1570 {
1571 if( marker->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
1572 return INSPECT_RESULT::QUIT;
1573 }
1574
1575 break;
1576
1577 case PCB_ZONE_T:
1578 if( !footprintsScanned )
1579 {
1580 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1581 == INSPECT_RESULT::QUIT )
1582 {
1583 return INSPECT_RESULT::QUIT;
1584 }
1585
1586 footprintsScanned = true;
1587 }
1588
1589 for( ZONE* zone : m_zones)
1590 {
1591 if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
1592 return INSPECT_RESULT::QUIT;
1593 }
1594
1595 break;
1596
1597 case PCB_GENERATOR_T:
1598 if( !footprintsScanned )
1599 {
1600 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1601 == INSPECT_RESULT::QUIT )
1602 {
1603 return INSPECT_RESULT::QUIT;
1604 }
1605
1606 footprintsScanned = true;
1607 }
1608
1609 if( IterateForward<PCB_GENERATOR*>( m_generators, inspector, testData, { scanType } )
1610 == INSPECT_RESULT::QUIT )
1611 {
1612 return INSPECT_RESULT::QUIT;
1613 }
1614
1615 break;
1616
1617 case PCB_GROUP_T:
1618 if( IterateForward<PCB_GROUP*>( m_groups, inspector, testData, { scanType } )
1619 == INSPECT_RESULT::QUIT )
1620 {
1621 return INSPECT_RESULT::QUIT;
1622 }
1623
1624 break;
1625
1626 default:
1627 break;
1628 }
1629 }
1630
1631 return INSPECT_RESULT::CONTINUE;
1632}
1633
1634
1635NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1636{
1637 // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1638 // zero is reserved for "no connection" and is not actually a net.
1639 // nullptr is returned for non valid netcodes
1640
1641 wxASSERT( m_NetInfo.GetNetCount() > 0 );
1642
1643 if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1645 else
1646 return m_NetInfo.GetNetItem( aNetcode );
1647}
1648
1649
1650NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1651{
1652 return m_NetInfo.GetNetItem( aNetname );
1653}
1654
1655
1656int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
1657{
1658 int rv = 0;
1659 int count = 0;
1660
1661 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1662 {
1663 int ch = *it;
1664
1665 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
1666 {
1667 continue;
1668 }
1669 else if( ch == '+' )
1670 {
1671 aComplementNet = wxT( "-" );
1672 rv = 1;
1673 }
1674 else if( ch == '-' )
1675 {
1676 aComplementNet = wxT( "+" );
1677 rv = -1;
1678 }
1679 else if( ch == 'N' )
1680 {
1681 aComplementNet = wxT( "P" );
1682 rv = -1;
1683 }
1684 else if ( ch == 'P' )
1685 {
1686 aComplementNet = wxT( "N" );
1687 rv = 1;
1688 }
1689 else
1690 {
1691 break;
1692 }
1693 }
1694
1695 if( rv != 0 && count >= 1 )
1696 {
1697 aComplementNet = aNetName.Left( aNetName.length() - count )
1698 + aComplementNet
1699 + aNetName.Right( count - 1 );
1700 }
1701
1702 return rv;
1703}
1704
1705
1707{
1708 if( aNet )
1709 {
1710 wxString refName = aNet->GetNetname();
1711 wxString coupledNetName;
1712
1713 if( MatchDpSuffix( refName, coupledNetName ) )
1714 return FindNet( coupledNetName );
1715 }
1716
1717 return nullptr;
1718}
1719
1720
1721FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
1722{
1723 for( FOOTPRINT* footprint : m_footprints )
1724 {
1725 if( aReference == footprint->GetReference() )
1726 return footprint;
1727 }
1728
1729 return nullptr;
1730}
1731
1732
1734{
1735 for( FOOTPRINT* footprint : m_footprints )
1736 {
1737 if( footprint->GetPath() == aPath )
1738 return footprint;
1739 }
1740
1741 return nullptr;
1742}
1743
1744
1746{
1747 std::set<wxString> names;
1748
1749 for( const NETINFO_ITEM* net : m_NetInfo )
1750 {
1751 if( !net->GetNetname().IsEmpty() )
1752 names.insert( net->GetNetname() );
1753 }
1754
1755 return names;
1756}
1757
1758
1760{
1761 wxCHECK( m_project, /*void*/ );
1762
1763 if( !m_project->IsNullProject() )
1765}
1766
1767
1768void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
1769{
1770 if( !m_project )
1771 return;
1772
1774 std::shared_ptr<NETCLASS>& defaultNetClass = bds.m_NetSettings->m_DefaultNetClass;
1775
1776 for( NETINFO_ITEM* net : m_NetInfo )
1777 net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) );
1778
1779 if( aResetTrackAndViaSizes )
1780 {
1781 // Set initial values for custom track width & via size to match the default
1782 // netclass settings
1783 bds.UseCustomTrackViaSize( false );
1784 bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
1785 bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
1786 bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
1787 bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
1788 bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
1789 bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
1790 }
1791
1793}
1794
1795
1797{
1798 int error_count = 0;
1799
1800 for( ZONE* zone : Zones() )
1801 {
1802 if( !zone->IsOnCopperLayer() )
1803 {
1804 zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
1805 continue;
1806 }
1807
1808 if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1809 {
1810 const NETINFO_ITEM* net = zone->GetNet();
1811
1812 if( net )
1813 {
1814 zone->SetNetCode( net->GetNetCode() );
1815 }
1816 else
1817 {
1818 error_count++;
1819
1820 // keep Net Name and set m_NetCode to -1 : error flag.
1821 zone->SetNetCode( -1 );
1822 }
1823 }
1824 }
1825
1826 return error_count;
1827}
1828
1829
1830PAD* BOARD::GetPad( const VECTOR2I& aPosition, LSET aLayerSet ) const
1831{
1832 if( !aLayerSet.any() )
1833 aLayerSet = LSET::AllCuMask();
1834
1835 for( FOOTPRINT* footprint : m_footprints )
1836 {
1837 PAD* pad = nullptr;
1838
1839 if( footprint->HitTest( aPosition ) )
1840 pad = footprint->GetPad( aPosition, aLayerSet );
1841
1842 if( pad )
1843 return pad;
1844 }
1845
1846 return nullptr;
1847}
1848
1849
1850PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
1851{
1852 const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
1853
1854 LSET lset( aTrace->GetLayer() );
1855
1856 return GetPad( aPosition, lset );
1857}
1858
1859
1860PAD* BOARD::GetPadFast( const VECTOR2I& aPosition, LSET aLayerSet ) const
1861{
1862 for( FOOTPRINT* footprint : Footprints() )
1863 {
1864 for( PAD* pad : footprint->Pads() )
1865 {
1866 if( pad->GetPosition() != aPosition )
1867 continue;
1868
1869 // Pad found, it must be on the correct layer
1870 if( ( pad->GetLayerSet() & aLayerSet ).any() )
1871 return pad;
1872 }
1873 }
1874
1875 return nullptr;
1876}
1877
1878
1879PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, LSET aLayerSet ) const
1880{
1881 // Search aPadList for aPosition
1882 // aPadList is sorted by X then Y values, and a fast binary search is used
1883 int idxmax = aPadList.size() - 1;
1884
1885 int delta = aPadList.size();
1886
1887 int idx = 0; // Starting index is the beginning of list
1888
1889 while( delta )
1890 {
1891 // Calculate half size of remaining interval to test.
1892 // Ensure the computed value is not truncated (too small)
1893 if( (delta & 1) && ( delta > 1 ) )
1894 delta++;
1895
1896 delta /= 2;
1897
1898 PAD* pad = aPadList[idx];
1899
1900 if( pad->GetPosition() == aPosition ) // candidate found
1901 {
1902 // The pad must match the layer mask:
1903 if( ( aLayerSet & pad->GetLayerSet() ).any() )
1904 return pad;
1905
1906 // More than one pad can be at aPosition
1907 // search for a pad at aPosition that matched this mask
1908
1909 // search next
1910 for( int ii = idx+1; ii <= idxmax; ii++ )
1911 {
1912 pad = aPadList[ii];
1913
1914 if( pad->GetPosition() != aPosition )
1915 break;
1916
1917 if( ( aLayerSet & pad->GetLayerSet() ).any() )
1918 return pad;
1919 }
1920 // search previous
1921 for( int ii = idx - 1 ;ii >=0; ii-- )
1922 {
1923 pad = aPadList[ii];
1924
1925 if( pad->GetPosition() != aPosition )
1926 break;
1927
1928 if( ( aLayerSet & pad->GetLayerSet() ).any() )
1929 return pad;
1930 }
1931
1932 // Not found:
1933 return nullptr;
1934 }
1935
1936 if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1937 {
1938 if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1939 {
1940 idx += delta;
1941
1942 if( idx > idxmax )
1943 idx = idxmax;
1944 }
1945 else // Must search before this item
1946 {
1947 idx -= delta;
1948
1949 if( idx < 0 )
1950 idx = 0;
1951 }
1952 }
1953 else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1954 {
1955 idx += delta;
1956
1957 if( idx > idxmax )
1958 idx = idxmax;
1959 }
1960 else // Must search before this item
1961 {
1962 idx -= delta;
1963
1964 if( idx < 0 )
1965 idx = 0;
1966 }
1967 }
1968
1969 return nullptr;
1970}
1971
1972
1978bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH )
1979{
1980 if( aLH->GetPosition().x == aRH->GetPosition().x )
1981 return aLH->GetPosition().y < aRH->GetPosition().y;
1982
1983 return aLH->GetPosition().x < aRH->GetPosition().x;
1984}
1985
1986
1987void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
1988{
1989 for( FOOTPRINT* footprint : Footprints() )
1990 {
1991 for( PAD* pad : footprint->Pads( ) )
1992 {
1993 if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1994 aVector.push_back( pad );
1995 }
1996 }
1997
1998 std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1999}
2000
2001
2002std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
2003{
2004 int count = 0;
2005 double length = 0.0;
2006 double package_length = 0.0;
2007
2008 auto connectivity = GetBoard()->GetConnectivity();
2011
2012 for( BOARD_CONNECTED_ITEM* item : connectivity->GetConnectedItems(
2013 static_cast<const BOARD_CONNECTED_ITEM*>( &aTrack ),
2014 { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T } ) )
2015 {
2016 count++;
2017
2018 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
2019 {
2020 if( track->Type() == PCB_VIA_T && useHeight )
2021 {
2022 PCB_VIA* via = static_cast<PCB_VIA*>( track );
2023 length += stackup.GetLayerDistance( via->TopLayer(), via->BottomLayer() );
2024 continue;
2025 }
2026 else if( track->Type() == PCB_ARC_T )
2027 {
2028 // Note: we don't apply the clip-to-pad optimization if an arc ends in a pad
2029 // Room for future improvement.
2030 length += track->GetLength();
2031 continue;
2032 }
2033
2034 bool inPad = false;
2035 SEG trackSeg( track->GetStart(), track->GetEnd() );
2036 double segLen = trackSeg.Length();
2037 double segInPadLen = 0;
2038
2039 for( auto pad_it : connectivity->GetConnectedPads( item ) )
2040 {
2041 PAD* pad = static_cast<PAD*>( pad_it );
2042
2043 bool hitStart = pad->HitTest( track->GetStart(), track->GetWidth() / 2 );
2044 bool hitEnd = pad->HitTest( track->GetEnd(), track->GetWidth() / 2 );
2045
2046 if( hitStart && hitEnd )
2047 {
2048 inPad = true;
2049 break;
2050 }
2051 else if( hitStart || hitEnd )
2052 {
2053 VECTOR2I loc;
2054
2055 // We may not collide even if we passed the bounding-box hit test
2056 if( pad->GetEffectivePolygon( ERROR_INSIDE )->Collide( trackSeg, 0, nullptr, &loc ) )
2057 {
2058 // Part 1: length of the seg to the intersection with the pad poly
2059 if( hitStart )
2060 trackSeg.A = loc;
2061 else
2062 trackSeg.B = loc;
2063
2064 segLen = trackSeg.Length();
2065
2066 // Part 2: length from the intersection to the pad anchor
2067 segInPadLen += ( loc - pad->GetPosition() ).EuclideanNorm();
2068 }
2069 }
2070 }
2071
2072 if( !inPad )
2073 length += segLen + segInPadLen;
2074 }
2075 else if( PAD* pad = dynamic_cast<PAD*>( item ) )
2076 {
2077 package_length += pad->GetPadToDieLength();
2078 }
2079 }
2080
2081 return std::make_tuple( count, length, package_length );
2082}
2083
2084
2085FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer,
2086 bool aVisibleOnly, bool aIgnoreLocked ) const
2087{
2088 FOOTPRINT* footprint = nullptr;
2089 FOOTPRINT* alt_footprint = nullptr;
2090 int min_dim = 0x7FFFFFFF;
2091 int alt_min_dim = 0x7FFFFFFF;
2092 bool current_layer_back = IsBackLayer( aActiveLayer );
2093
2094 for( FOOTPRINT* candidate : m_footprints )
2095 {
2096 // is the ref point within the footprint's bounds?
2097 if( !candidate->HitTest( aPosition ) )
2098 continue;
2099
2100 // if caller wants to ignore locked footprints, and this one is locked, skip it.
2101 if( aIgnoreLocked && candidate->IsLocked() )
2102 continue;
2103
2104 PCB_LAYER_ID layer = candidate->GetLayer();
2105
2106 // Filter non visible footprints if requested
2107 if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
2108 {
2109 BOX2I bb = candidate->GetBoundingBox( false, false );
2110
2111 int offx = bb.GetX() + bb.GetWidth() / 2;
2112 int offy = bb.GetY() + bb.GetHeight() / 2;
2113
2114 // off x & offy point to the middle of the box.
2115 int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2116 ( aPosition.y - offy ) * ( aPosition.y - offy );
2117
2118 if( current_layer_back == IsBackLayer( layer ) )
2119 {
2120 if( dist <= min_dim )
2121 {
2122 // better footprint shown on the active side
2123 footprint = candidate;
2124 min_dim = dist;
2125 }
2126 }
2127 else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
2128 {
2129 if( dist <= alt_min_dim )
2130 {
2131 // better footprint shown on the other side
2132 alt_footprint = candidate;
2133 alt_min_dim = dist;
2134 }
2135 }
2136 }
2137 }
2138
2139 if( footprint )
2140 return footprint;
2141
2142 if( alt_footprint)
2143 return alt_footprint;
2144
2145 return nullptr;
2146}
2147
2148
2149std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
2150{
2151 std::list<ZONE*> zones;
2152
2153 for( ZONE* zone : Zones() )
2154 zones.push_back( zone );
2155
2156 if( aIncludeZonesInFootprints )
2157 {
2158 for( FOOTPRINT* footprint : m_footprints )
2159 {
2160 for( ZONE* zone : footprint->Zones() )
2161 zones.push_back( zone );
2162 }
2163 }
2164
2165 return zones;
2166}
2167
2168
2169ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer,
2170 VECTOR2I aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch )
2171{
2172 ZONE* new_area = new ZONE( this );
2173
2174 new_area->SetNetCode( aNetcode );
2175 new_area->SetLayer( aLayer );
2176
2177 m_zones.push_back( new_area );
2178
2179 new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
2180
2181 // Add the first corner to the new zone
2182 new_area->AppendCorner( aStartPointPosition, -1 );
2183
2184 if( aNewZonesList )
2185 {
2186 ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
2187 aNewZonesList->PushItem( picker );
2188 }
2189
2190 return new_area;
2191}
2192
2193
2195 OUTLINE_ERROR_HANDLER* aErrorHandler,
2196 bool aAllowUseArcsInPolygons,
2197 bool aIncludeNPTHAsOutlines )
2198{
2199 // max dist from one endPt to next startPt: use the current value
2200 int chainingEpsilon = GetOutlinesChainingEpsilon();
2201
2202 bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
2203 chainingEpsilon, aErrorHandler,
2204 aAllowUseArcsInPolygons );
2205
2206 // Now add NPTH oval holes as holes in outlines if required
2207 if( aIncludeNPTHAsOutlines )
2208 {
2209 for( FOOTPRINT* fp : Footprints() )
2210 {
2211 for( PAD* pad : fp->Pads() )
2212 {
2213 if( pad->GetAttribute () != PAD_ATTRIB::NPTH )
2214 continue;
2215
2216 SHAPE_POLY_SET hole;
2217 pad->TransformHoleToPolygon( hole, 0, GetDesignSettings().m_MaxError, ERROR_INSIDE );
2218
2219 // Add this pad hole to the main outline
2220 // But we can have more than one main outline (i.e. more than one board), so
2221 // search the right main outline i.e. the outline that contains the pad hole
2222 SHAPE_LINE_CHAIN& pad_hole = hole.Outline( 0 );
2223 const VECTOR2I holePt = pad_hole.CPoint( 0 );
2224
2225 for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj )
2226 {
2227 if( aOutlines.Outline( jj ).PointInside( holePt ) )
2228 {
2229 aOutlines.AddHole( pad_hole, jj );
2230 break;
2231 }
2232 }
2233 }
2234 }
2235 }
2236
2237 // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2239
2240 return success;
2241}
2242
2243
2244const std::vector<PAD*> BOARD::GetPads() const
2245{
2246 std::vector<PAD*> allPads;
2247
2248 for( FOOTPRINT* footprint : Footprints() )
2249 {
2250 for( PAD* pad : footprint->Pads() )
2251 allPads.push_back( pad );
2252 }
2253
2254 return allPads;
2255}
2256
2257
2258const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
2259{
2260 std::vector<BOARD_CONNECTED_ITEM*> items;
2261
2262 for( PCB_TRACK* track : Tracks() )
2263 items.push_back( track );
2264
2265 for( FOOTPRINT* footprint : Footprints() )
2266 {
2267 for( PAD* pad : footprint->Pads() )
2268 items.push_back( pad );
2269 }
2270
2271 for( ZONE* zone : Zones() )
2272 items.push_back( zone );
2273
2274 for( BOARD_ITEM* item : Drawings() )
2275 {
2276 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2277 items.push_back( bci );
2278 }
2279
2280 return items;
2281}
2282
2283
2284void BOARD::MapNets( const BOARD* aDestBoard )
2285{
2287 {
2288 NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
2289
2290 if( netInfo )
2291 item->SetNet( netInfo );
2292 else
2293 item->SetNetCode( 0 );
2294 }
2295}
2296
2297
2299{
2300 for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
2301 {
2302 if( FindNet( item->GetNetCode() ) == nullptr )
2303 item->SetNetCode( NETINFO_LIST::ORPHANED );
2304 }
2305}
2306
2307
2309{
2310 if( !alg::contains( m_listeners, aListener ) )
2311 m_listeners.push_back( aListener );
2312}
2313
2314
2316{
2317 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
2318
2319 if( i != m_listeners.end() )
2320 {
2321 std::iter_swap( i, m_listeners.end() - 1 );
2322 m_listeners.pop_back();
2323 }
2324}
2325
2326
2328{
2329 m_listeners.clear();
2330}
2331
2332
2334{
2336}
2337
2338
2339void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
2340{
2342}
2343
2344
2346{
2348}
2349
2350
2352{
2355
2357}
2358
2359
2360void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
2361{
2362 if( !m_highLight.m_netCodes.count( aNetCode ) )
2363 {
2364 if( !aMulti )
2365 m_highLight.m_netCodes.clear();
2366
2367 m_highLight.m_netCodes.insert( aNetCode );
2369 }
2370}
2371
2372
2373void BOARD::HighLightON( bool aValue )
2374{
2375 if( m_highLight.m_highLightOn != aValue )
2376 {
2377 m_highLight.m_highLightOn = aValue;
2379 }
2380}
2381
2382
2383wxString BOARD::GroupsSanityCheck( bool repair )
2384{
2385 if( repair )
2386 {
2387 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
2388 {};
2389
2390 return wxEmptyString;
2391 }
2392 return GroupsSanityCheckInternal( repair );
2393}
2394
2395
2397{
2398 // Cycle detection
2399 //
2400 // Each group has at most one parent group.
2401 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
2402 // If we ever see a group that we've already marked, that's a cycle.
2403 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
2404 //
2405 // Algorithm below is linear in the # of groups because each group is visited only once.
2406 // There may be extra time taken due to the container access calls and iterators.
2407 //
2408 // Groups we know are cycle free
2409 std::unordered_set<PCB_GROUP*> knownCycleFreeGroups;
2410 // Groups in the current chain we're exploring.
2411 std::unordered_set<PCB_GROUP*> currentChainGroups;
2412 // Groups we haven't checked yet.
2413 std::unordered_set<PCB_GROUP*> toCheckGroups;
2414
2415 // Initialize set of groups and generators to check that could participate in a cycle.
2416 for( PCB_GROUP* group : Groups() )
2417 toCheckGroups.insert( group );
2418
2419 for( PCB_GENERATOR* gen : Generators() )
2420 toCheckGroups.insert( gen );
2421
2422 while( !toCheckGroups.empty() )
2423 {
2424 currentChainGroups.clear();
2425 PCB_GROUP* group = *toCheckGroups.begin();
2426
2427 while( true )
2428 {
2429 if( currentChainGroups.find( group ) != currentChainGroups.end() )
2430 {
2431 if( repair )
2432 Remove( group );
2433
2434 return "Cycle detected in group membership";
2435 }
2436 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
2437 {
2438 // Parent is a group we know does not lead to a cycle
2439 break;
2440 }
2441
2442 currentChainGroups.insert( group );
2443 // We haven't visited currIdx yet, so it must be in toCheckGroups
2444 toCheckGroups.erase( group );
2445
2446 group = group->GetParentGroup();
2447
2448 if( !group )
2449 {
2450 // end of chain and no cycles found in this chain
2451 break;
2452 }
2453 }
2454
2455 // No cycles found in chain, so add it to set of groups we know don't participate
2456 // in a cycle.
2457 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
2458 }
2459
2460 // Success
2461 return "";
2462}
2463
2464
2466{
2467 bool hasGroup = false;
2468 bool hasMember = false;
2469
2470 for( EDA_ITEM* item : selection )
2471 {
2472 if( BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item ) )
2473 {
2474 if( board_item->Type() == PCB_GROUP_T )
2475 hasGroup = true;
2476
2477 if( board_item->GetParentGroup() )
2478 hasMember = true;
2479 }
2480 }
2481
2482 GroupLegalOpsField legalOps;
2483
2484 legalOps.create = true;
2485 legalOps.removeItems = hasMember;
2486 legalOps.ungroup = hasGroup;
2487
2488 return legalOps;
2489}
2490
2491
2493{
2494 if( a->Type() != b->Type() )
2495 return a->Type() < b->Type();
2496
2497 if( a->GetLayer() != b->GetLayer() )
2498 return a->GetLayer() < b->GetLayer();
2499
2500 if( a->GetPosition().x != b->GetPosition().x )
2501 return a->GetPosition().x < b->GetPosition().x;
2502
2503 if( a->GetPosition().y != b->GetPosition().y )
2504 return a->GetPosition().y < b->GetPosition().y;
2505
2506 if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards
2507 return a->m_Uuid < b->m_Uuid;
2508
2509 return a < b;
2510}
2511
2512
2514 const BOARD_ITEM* aSecond ) const
2515{
2516 if( aFirst->Type() != aSecond->Type() )
2517 return aFirst->Type() < aSecond->Type();
2518
2519 if( aFirst->GetLayer() != aSecond->GetLayer() )
2520 return aFirst->GetLayer() < aSecond->GetLayer();
2521
2522 if( aFirst->Type() == PCB_SHAPE_T )
2523 {
2524 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aFirst );
2525 const PCB_SHAPE* other = static_cast<const PCB_SHAPE*>( aSecond );
2526 return shape->Compare( other );
2527 }
2528 else if( aFirst->Type() == PCB_TEXT_T || aFirst->Type() == PCB_FIELD_T )
2529 {
2530 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aFirst );
2531 const PCB_TEXT* other = static_cast<const PCB_TEXT*>( aSecond );
2532 return text->Compare( other );
2533 }
2534 else if( aFirst->Type() == PCB_TEXTBOX_T )
2535 {
2536 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aFirst );
2537 const PCB_TEXTBOX* other = static_cast<const PCB_TEXTBOX*>( aSecond );
2538
2539 return textbox->PCB_SHAPE::Compare( other ) && textbox->EDA_TEXT::Compare( other );
2540 }
2541 else if( aFirst->Type() == PCB_TABLE_T )
2542 {
2543 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aFirst );
2544 const PCB_TABLE* other = static_cast<const PCB_TABLE*>( aSecond );
2545
2546 return PCB_TABLE::Compare( table, other );
2547 }
2548
2549 return aFirst->m_Uuid < aSecond->m_Uuid;
2550}
2551
2552
2554 SHAPE_POLY_SET& aOutlines ) const
2555{
2556 int maxError = GetDesignSettings().m_MaxError;
2557
2558 // convert tracks and vias:
2559 for( const PCB_TRACK* track : m_tracks )
2560 {
2561 if( !track->IsOnLayer( aLayer ) )
2562 continue;
2563
2564 track->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2565 }
2566
2567 // convert pads and other copper items in footprints
2568 for( const FOOTPRINT* footprint : m_footprints )
2569 {
2570 footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2571
2572 footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE,
2573 true, /* include text */
2574 true, /* include shapes */
2575 false /* include private items */ );
2576
2577 for( const ZONE* zone : footprint->Zones() )
2578 {
2579 if( zone->GetLayerSet().test( aLayer ) )
2580 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
2581 }
2582 }
2583
2584 // convert copper zones
2585 for( const ZONE* zone : Zones() )
2586 {
2587 if( zone->GetLayerSet().test( aLayer ) )
2588 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
2589 }
2590
2591 // convert graphic items on copper layers (texts)
2592 for( const BOARD_ITEM* item : m_drawings )
2593 {
2594 if( !item->IsOnLayer( aLayer ) )
2595 continue;
2596
2597 switch( item->Type() )
2598 {
2599 case PCB_SHAPE_T:
2600 {
2601 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
2602 shape->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2603 break;
2604 }
2605
2606 case PCB_FIELD_T:
2607 case PCB_TEXT_T:
2608 {
2609 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
2610 text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2611 break;
2612 }
2613
2614 case PCB_TEXTBOX_T:
2615 {
2616 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
2617
2618 // border
2619 textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError,
2620 ERROR_INSIDE );
2621 // text
2622 textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2623 break;
2624 }
2625
2626 case PCB_TABLE_T:
2627 {
2628 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
2629
2630 table->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2631 break;
2632 }
2633
2634 case PCB_DIM_ALIGNED_T:
2635 case PCB_DIM_CENTER_T:
2636 case PCB_DIM_RADIAL_T:
2638 case PCB_DIM_LEADER_T:
2639 {
2640 const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
2641
2642 dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2643 dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2644 break;
2645 }
2646
2647 default:
2648 break;
2649 }
2650 }
2651}
2652
2653
2655{
2656 BOARD_ITEM_SET items;
2657
2658 std::copy( m_tracks.begin(), m_tracks.end(), std::inserter( items, items.end() ) );
2659 std::copy( m_zones.begin(), m_zones.end(), std::inserter( items, items.end() ) );
2660 std::copy( m_footprints.begin(), m_footprints.end(), std::inserter( items, items.end() ) );
2661 std::copy( m_drawings.begin(), m_drawings.end(), std::inserter( items, items.end() ) );
2662 std::copy( m_markers.begin(), m_markers.end(), std::inserter( items, items.end() ) );
2663 std::copy( m_groups.begin(), m_groups.end(), std::inserter( items, items.end() ) );
2664
2665 return items;
2666}
2667
2668
2669bool BOARD::operator==( const BOARD_ITEM& aItem ) const
2670{
2671 if( aItem.Type() != Type() )
2672 return false;
2673
2674 const BOARD& other = static_cast<const BOARD&>( aItem );
2675
2676 if( *m_designSettings != *other.m_designSettings )
2677 return false;
2678
2679 if( m_NetInfo.GetNetCount() != other.m_NetInfo.GetNetCount() )
2680 return false;
2681
2682 const NETNAMES_MAP& thisNetNames = m_NetInfo.NetsByName();
2683 const NETNAMES_MAP& otherNetNames = other.m_NetInfo.NetsByName();
2684
2685 for( auto it1 = thisNetNames.begin(), it2 = otherNetNames.begin();
2686 it1 != thisNetNames.end() && it2 != otherNetNames.end(); ++it1, ++it2 )
2687 {
2688 // We only compare the names in order here, not the index values
2689 // as the index values are auto-generated and the names are not.
2690 if( it1->first != it2->first )
2691 return false;
2692 }
2693
2694 if( m_properties.size() != other.m_properties.size() )
2695 return false;
2696
2697 for( auto it1 = m_properties.begin(), it2 = other.m_properties.begin();
2698 it1 != m_properties.end() && it2 != other.m_properties.end(); ++it1, ++it2 )
2699 {
2700 if( *it1 != *it2 )
2701 return false;
2702 }
2703
2705 return false;
2706
2708 return false;
2709
2710 if( m_paper.GetSizeMils() != other.m_paper.GetSizeMils() )
2711 return false;
2712
2713 if( m_paper.GetPaperId() != other.m_paper.GetPaperId() )
2714 return false;
2715
2717 return false;
2718
2719 for( int ii = 0; !m_titles.GetComment( ii ).empty(); ++ii )
2720 {
2721 if( m_titles.GetComment( ii ) != other.m_titles.GetComment( ii ) )
2722 return false;
2723 }
2724
2725 wxArrayString ourVars;
2726 m_titles.GetContextualTextVars( &ourVars );
2727
2728 wxArrayString otherVars;
2729 other.m_titles.GetContextualTextVars( &otherVars );
2730
2731 if( ourVars != otherVars )
2732 return false;
2733
2734 return true;
2735}
2736
2737
2739{
2740 m_designSettings->m_DrcExclusions.clear();
2741 m_designSettings->m_DrcExclusionComments.clear();
2742
2743 for( PCB_MARKER* marker : m_markers )
2744 {
2745 if( marker->IsExcluded() )
2746 {
2747 wxString serialized = marker->Serialize();
2748 m_designSettings->m_DrcExclusions.insert( serialized );
2749 m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment();
2750 }
2751 }
2752}
@ NORMAL
Use all material properties from model file.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
bool sortPadsByXthenYCoord(PAD *const &aLH, PAD *const &aRH)
Used by #GetSortedPadListByXCoord to sort a pad list by X coordinate value.
Definition: board.cpp:1978
#define DEFAULT_CHAINING_EPSILON_MM
Definition: board.h:68
BOARD_USE
Flags to specify how the board is being used.
Definition: board.h:266
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition: board.h:149
@ LT_POWER
Definition: board.h:152
@ LT_MIXED
Definition: board.h:153
@ LT_UNDEFINED
Definition: board.h:150
@ LT_JUMPER
Definition: board.h:154
@ LT_SIGNAL
Definition: board.h:151
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
Definition: board.h:260
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
Container for design settings for a BOARD object.
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetCustomTrackWidth(int aWidth)
Sets custom width for track (i.e.
void SetEnabledLayers(LSET aMask)
Change the bit-mask of enabled layers to aMask.
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
void SetCustomViaSize(int aSize)
Set custom size for via diameter (i.e.
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
bool IsLayerEnabled(PCB_LAYER_ID aLayerId) const
Test whether a given layer aLayerId is enabled.
BOARD_STACKUP & GetStackupDescriptor()
void SetCustomViaDrill(int aDrill)
Sets custom size for via drill (i.e.
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
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:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:226
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
static VECTOR2I ZeroOffset
A value of wxPoint(0,0) which can be passed to the Draw() functions.
Definition: board_item.h:169
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:103
virtual void OnBoardNetSettingsChanged(BOARD &aBoard)
Definition: board.h:250
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:247
virtual void OnBoardRatsnestChanged(BOARD &aBoard)
Definition: board.h:254
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:252
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:251
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:248
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:246
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition: board.h:253
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:249
Manage layers needed to make a physical board.
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:276
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: board.cpp:1486
ZONE * m_SolderMaskBridges
Definition: board.h:1246
void GetContextualTextVars(wxArrayString *aVars) const
Definition: board.cpp:372
bool IsFootprintLayerVisible(PCB_LAYER_ID aLayer) const
Expect either of the two layers on which a footprint can reside, and returns whether that layer is vi...
Definition: board.cpp:757
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaCache
Definition: board.h:1235
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition: board.h:1247
GENERATORS m_generators
Definition: board.h:1280
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:2194
void OnItemChanged(BOARD_ITEM *aItem)
Notify the board and its listeners that an item on the board has been modified in some way.
Definition: board.cpp:2333
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:359
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition: board.h:306
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:652
void SetPosition(const VECTOR2I &aPos) override
Definition: board.cpp:459
std::map< wxString, wxString > m_properties
Definition: board.h:1290
int m_fileFormatVersionAtLoad
Definition: board.h:1287
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1706
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:666
std::vector< ZONE * > m_DRCCopperZones
Definition: board.h:1243
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:850
TITLE_BLOCK m_titles
Definition: board.h:1294
GAL_SET m_LegacyVisibleItems
Definition: board.h:356
PAD * GetPadFast(const VECTOR2I &aPosition, LSET aLayerMask) const
Return pad found at aPosition on aLayerMask using the fast search method.
Definition: board.cpp:1860
LAYER m_layers[PCB_LAYER_ID_COUNT]
Definition: board.h:1282
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition: board.h:747
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition: board.cpp:2258
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:718
int m_outlinesChainingEpsilon
the max distance between 2 end point to see them connected when building the board outlines
Definition: board.h:1267
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition: board.cpp:1745
PAGE_INFO m_paper
Definition: board.h:1293
void MapNets(const BOARD *aDestBoard)
Map all nets in the given board to nets with the same name (if any) in the destination board.
Definition: board.cpp:2284
void RemoveAllListeners()
Remove all listeners.
Definition: board.cpp:2327
FOOTPRINTS m_footprints
Definition: board.h:1276
std::unique_ptr< BOARD_DESIGN_SETTINGS > m_designSettings
All of the board design settings are stored as a JSON object inside the project file.
Definition: board.h:1309
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:672
void AddListener(BOARD_LISTENER *aListener)
Add a listener to the board to receive calls whenever something on the board has been modified.
Definition: board.cpp:2308
void UpdateUserUnits(BOARD_ITEM *aItem, KIGFX::VIEW *aView)
Update any references within aItem (or its descendants) to the user units.
Definition: board.cpp:1054
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition: board.h:349
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition: board.cpp:712
ZONES & Zones()
Definition: board.h:324
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2360
HIGH_LIGHT_INFO m_highLight
Definition: board.h:1284
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition: board.cpp:507
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1635
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1121
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition: board.h:1257
void SanitizeNetcodes()
Definition: board.cpp:2298
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: board.cpp:1048
ZONE * AddArea(PICKED_ITEMS_LIST *aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, VECTOR2I aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch)
Add an empty copper area to board areas list.
Definition: board.cpp:2169
~BOARD()
Definition: board.cpp:132
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:184
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:678
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:573
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:2738
DRAWINGS m_drawings
Definition: board.h:1275
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition: board.cpp:1796
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1768
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2351
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:555
GENERATORS & Generators()
Definition: board.h:327
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition: board.cpp:2149
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
Definition: board.cpp:2553
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:396
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition: board.cpp:2244
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: board.cpp:465
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:656
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1380
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition: board.cpp:775
ZONES m_zones
Definition: board.h:1279
FOOTPRINTS & Footprints()
Definition: board.h:318
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition: board.cpp:519
HIGH_LIGHT_INFO m_highLightPrevious
Definition: board.h:1285
NETINFO_LIST m_NetInfo
Definition: board.h:1317
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:355
void SetVisibleAlls()
Change the bit-mask of visible element categories and layers.
Definition: board.cpp:701
GroupLegalOpsField GroupLegalOps(const PCB_SELECTION &selection) const
Check which selection tool group operations are legal given the selection.
Definition: board.cpp:2465
int GetCopperLayerCount() const
Definition: board.cpp:628
int m_timeStamp
Definition: board.h:1271
std::vector< BOARD_LISTENER * > m_listeners
Definition: board.h:1319
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsCourtyardCache
Definition: board.h:1231
void IncrementTimeStamp()
Definition: board.cpp:253
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1656
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsFCourtyardCache
Definition: board.h:1232
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: board.h:1291
const BOARD_ITEM_SET GetItemSet()
Definition: board.cpp:2654
int m_DRCMaxPhysicalClearance
Definition: board.h:1245
GROUPS & Groups()
The groups must maintain the following invariants.
Definition: board.h:343
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition: board.cpp:1733
void FinalizeBulkRemove(std::vector< BOARD_ITEM * > &aRemovedItems)
Must be used if Remove() is used using a BULK_x REMOVE_MODE to generate a change event for listeners.
Definition: board.cpp:960
std::unordered_map< wxString, LSET > m_LayerExpressionCache
Definition: board.h:1236
wxString GroupsSanityCheckInternal(bool repair)
Definition: board.cpp:2396
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition: board.cpp:2345
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1261
TRACKS & Tracks()
Definition: board.h:315
wxString GetClass() const override
Return the class name.
Definition: board.h:958
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:684
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition: board.h:363
void SetCopperLayerCount(int aCount)
Definition: board.cpp:634
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition: board.h:1239
MARKERS & Markers()
Definition: board.h:330
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsBCourtyardCache
Definition: board.h:1233
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition: board.cpp:485
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:194
PROJECT * m_project
Definition: board.h:1296
FOOTPRINT * GetFootprint(const VECTOR2I &aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly, bool aIgnoreLocked=false) const
Get a footprint by its bounding rectangle at aPosition on aLayer.
Definition: board.cpp:2085
const wxString & GetFileName() const
Definition: board.h:313
bool operator==(const BOARD_ITEM &aOther) const override
Definition: board.cpp:2669
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition: board.cpp:322
DRAWINGS & Drawings()
Definition: board.h:321
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition: board.cpp:1721
unsigned GetNodesCount(int aNet=-1) const
Definition: board.cpp:1363
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:1222
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:724
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition: board.h:1238
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:585
int GetOutlinesChainingEpsilon()
Definition: board.h:700
void GetSortedPadListByXthenYCoord(std::vector< PAD * > &aVector, int aNetCode=-1) const
First empties then fills the vector with all pads and sorts them by increasing x coordinate,...
Definition: board.cpp:1987
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:658
int m_DRCMaxClearance
Definition: board.h:1244
void ClearProject()
Definition: board.cpp:233
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition: board.h:1237
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
Definition: board.cpp:954
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition: board.cpp:640
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition: board.cpp:1112
PROJECT * GetProject() const
Definition: board.h:457
std::tuple< int, double, double > GetTrackLength(const PCB_TRACK &aTrack) const
Return data on the length and number of track segments connected to a given track.
Definition: board.cpp:2002
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: board.cpp:1448
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition: board.cpp:2383
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:769
std::vector< ZONE * > m_DRCZones
Definition: board.h:1242
PAD * GetPad(const VECTOR2I &aPosition, LSET aLayerMask) const
Find a pad aPosition on aLayer.
Definition: board.cpp:1830
BOARD()
Definition: board.cpp:72
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:291
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1315
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:1759
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition: board.cpp:2315
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:1080
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:966
GROUPS m_groups
Definition: board.h:1278
MARKERS m_markers
Definition: board.h:1274
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsAreaCache
Definition: board.h:1234
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2373
TRACKS m_tracks
Definition: board.h:1277
std::mutex m_CachesMutex
Definition: board.h:1230
void OnItemsChanged(std::vector< BOARD_ITEM * > &aItems)
Notify the board and its listeners that an item on the board has been modified in some way.
Definition: board.cpp:2339
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:441
VECTOR2I GetPosition() const override
Definition: board.cpp:453
void CacheTriangulation(PROGRESS_REPORTER *aReporter=nullptr, const std::vector< ZONE * > &aZones={})
Definition: board.cpp:800
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:691
coord_type GetHeight() const
Definition: box2.h:189
coord_type GetY() const
Definition: box2.h:182
coord_type GetWidth() const
Definition: box2.h:188
coord_type GetX() const
Definition: box2.h:181
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:589
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
std::shared_ptr< const CN_ANCHOR > GetSourceNode() const
void SetVisible(bool aVisible)
std::shared_ptr< const CN_ANCHOR > GetTargetNode() const
static DELETED_BOARD_ITEM * GetInstance()
Definition: board_item.h:427
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:239
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:123
const KIID m_Uuid
Definition: eda_item.h:482
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes)
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: eda_item.cpp:91
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
void ClearEditFlags()
Definition: eda_item.h:137
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:126
int Compare(const EDA_SHAPE *aOther) const
Definition: eda_shape.cpp:1629
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
Definition: footprint.cpp:643
Helper for storing and iterating over GAL_LAYER_IDs.
Definition: layer_ids.h:306
GAL_SET & set()
Definition: layer_ids.h:322
static const std::vector< KICAD_T > BoardLevelItems
A scan list for all primary board items, omitting items which are subordinate to a FOOTPRINT,...
Definition: collectors.h:237
static const std::vector< KICAD_T > Tracks
A scan list for only TRACKs and ARCs.
Definition: collectors.h:257
void Clear()
Definition: board.h:220
std::set< int > m_netCodes
Definition: board.h:217
bool m_highLightOn
Definition: board.h:218
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1619
Definition: kiid.h:49
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:573
static LSET AllLayersMask()
Definition: lset.cpp:898
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:863
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:112
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition: marker_base.h:99
void SetParent(JSON_SETTINGS *aParent, bool aLoadFromFile=true)
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:46
Handle the data for a net.
Definition: netinfo.h:56
const wxString & GetNetname() const
Definition: netinfo.h:114
void SetNetCode(int aNetCode)
Definition: netinfo.h:109
int GetNetCode() const
Definition: netinfo.h:108
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:375
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:379
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:383
unsigned GetNetCount() const
Definition: netinfo.h:365
void RemoveNet(NETINFO_ITEM *aNet)
Remove a net from the net list.
NETINFO_ITEM * GetNetItem(int aNetCode) const
void AppendNet(NETINFO_ITEM *aNewElement)
Add aNewElement to the end of the net list.
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition: netinfo.h:368
Definition: pad.h:59
VECTOR2I GetPosition() const override
Definition: pad.h:198
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:59
const VECTOR2D & GetSizeMils() const
Definition: page_info.h:144
wxPrintOrientation GetWxOrientation() const
Definition: page_info.h:127
static double GetCustomHeightMils()
Definition: page_info.h:196
wxPaperSize GetPaperId() const
Definition: page_info.h:132
static double GetCustomWidthMils()
Definition: page_info.h:191
Abstract dimension API.
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.
DIM_UNITS_MODE GetUnitsMode() const
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:51
virtual bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:95
static PCB_MARKER * Deserialize(const wxString &data)
Definition: pcb_marker.cpp:140
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:568
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
Definition: pcb_table.cpp:213
static int Compare(const PCB_TABLE *aTable, const PCB_TABLE *aOther)
Definition: pcb_table.cpp:289
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
Definition: pcb_text.cpp:460
const VECTOR2I & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: pcb_track.h:122
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:70
LSET m_VisibleLayers
Board settings.
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
Container for project specific data.
Definition: project.h:62
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:147
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:172
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:84
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:153
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Length() const
Return the length (this).
Definition: seg.h:326
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
const wxString & GetComment(int aIdx) const
Definition: title_block.h:107
static void GetContextualTextVars(wxArrayString *aVars)
Definition: title_block.cpp:74
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
void SetMinThickness(int aMinThickness)
Definition: zone.h:270
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:260
SHAPE_POLY_SET * Outline()
Definition: zone.h:336
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition: zone.h:605
void SetLayerSet(LSET aLayerSet) override
Definition: zone.cpp:266
bool AppendCorner(VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: zone.cpp:800
wxString GetTextVars(const wxString &aSource)
Returns any variables unexpanded, e.g.
Definition: common.cpp:115
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const VECTOR2I &pt)> OUTLINE_ERROR_HANDLER
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:160
#define _(s)
INSPECT_RESULT
Definition: eda_item.h:42
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:78
std::function< INSPECT_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Used to inspect and possibly collect the (search) results of iterating over a list or tree of KICAD_T...
Definition: eda_item.h:75
#define STRUCT_DELETED
flag indication structures to be erased
EDA_UNITS
Definition: eda_units.h:46
@ ERROR_INSIDE
KIID niluuid(0)
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition: layer_ids.h:976
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:879
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition: layer_ids.h:193
@ GAL_LAYER_ID_START
Definition: layer_ids.h:194
@ LAYER_FOOTPRINTS_FR
show footprints on front
Definition: layer_ids.h:211
@ GAL_LAYER_ID_BITMASK_END
This is the end of the layers used for visibility bit masks in legacy board files.
Definition: layer_ids.h:229
@ LAYER_HIDDEN_TEXT
text marked as invisible
Definition: layer_ids.h:203
@ LAYER_RATSNEST
Definition: layer_ids.h:207
@ LAYER_FOOTPRINTS_BK
show footprints on back
Definition: layer_ids.h:212
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Edge_Cuts
Definition: layer_ids.h:114
@ B_Mask
Definition: layer_ids.h:107
@ B_Cu
Definition: layer_ids.h:96
@ F_Mask
Definition: layer_ids.h:108
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ Rescue
Definition: layer_ids.h:134
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:138
@ F_Cu
Definition: layer_ids.h:65
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition: layer_ids.h:271
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:1022
void delete_matching(_Container &__c, _Value __value)
Covers for the horrifically named std::remove and std::remove_if (neither of which remove anything).
Definition: kicad_algo.h:165
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:100
Class to handle a set of BOARD_ITEMs.
ENDPOINT_T
Definition: pcb_track.h:57
see class PGM_BASE
Class that computes missing connections on a PCB.
@ RPT_SEVERITY_EXCLUSION
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition: board.cpp:2513
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition: board.cpp:2492
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
Container to hold information pertinent to a layer of a BOARD.
Definition: board.h:162
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
Definition: board.cpp:613
LAYER_T m_type
The type of the layer.
Definition: board.h:190
static const char * ShowType(LAYER_T aType)
Convert a LAYER_T enum to a string representation of the layer type.
Definition: board.cpp:600
wxString m_name
The canonical name of the layer.
Definition: board.h:188
wxString m_userName
The user defined name of the layer.
Definition: board.h:189
constexpr int delta
static thread_pool * tp
Definition: thread_pool.cpp:30
BS::thread_pool thread_pool
Definition: thread_pool.h:30
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:32
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:128
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_T
Definition: typeinfo.h:82
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition: typeinfo.h:91
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:99
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition: typeinfo.h:95
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:101
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition: typeinfo.h:94
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:109
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:49