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 The 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#include <algorithm>
30
31#include <wx/log.h>
32
33#include <drc/drc_rtree.h>
35#include <board_commit.h>
36#include <board.h>
37#include <core/arraydim.h>
38#include <core/kicad_algo.h>
41#include <footprint.h>
42#include <font/outline_font.h>
44#include <lset.h>
45#include <pcb_base_frame.h>
46#include <pcb_track.h>
47#include <pcb_marker.h>
48#include <pcb_group.h>
49#include <pcb_generator.h>
50#include <pcb_point.h>
51#include <pcb_target.h>
52#include <pcb_shape.h>
53#include <pcb_text.h>
54#include <pcb_textbox.h>
55#include <pcb_table.h>
56#include <pcb_dimension.h>
57#include <pgm_base.h>
58#include <pcbnew_settings.h>
59#include <progress_reporter.h>
60#include <project.h>
66#include <reporter.h>
67#include <tool/tool_manager.h>
69#include <string_utils.h>
70#include <thread_pool.h>
71#include <zone.h>
72#include <mutex>
73#include <pcb_board_outline.h>
74
75// This is an odd place for this, but CvPcb won't link if it's in board_item.cpp like I first
76// tried it.
78
79
86 m_timeStamp( 1 ),
88 m_project( nullptr ),
90 m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
91 m_NetInfo( this ),
92 m_embedFonts( false ),
93 m_embeddedFilesDelegate( nullptr ),
95 m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) )
96{
97 // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
98 // A too large value do not allow safely connecting 2 shapes like very short segments.
100
103 m_boardOutline = new PCB_BOARD_OUTLINE( this );
104
105 // we have not loaded a board yet, assume latest until then.
106 m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
107
108 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
109 {
110 m_layers[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
111
112 if( IsCopperLayer( layer ) )
113 m_layers[layer].m_type = LT_SIGNAL;
114 else if( layer >= User_1 && layer & 1 )
115 m_layers[layer].m_type = LT_AUX;
116 else
117 m_layers[layer].m_type = LT_UNDEFINED;
118 }
119
121
122 // Creates a zone to show sloder mask bridges created by a min web value
123 // it it just to show them
124 m_SolderMaskBridges = new ZONE( this );
126 m_SolderMaskBridges->SetLayerSet( LSET().set( F_Mask ).set( B_Mask ) );
127 int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
128 m_SolderMaskBridges->Outline()->NewOutline();
129 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
130 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
131 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, +infinity ) );
132 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, -infinity ) );
133 m_SolderMaskBridges->SetMinThickness( 0 );
134
136
137 // Initialize default netclass.
138 bds.m_NetSettings->SetDefaultNetclass( std::make_shared<NETCLASS>( NETCLASS::Default ) );
140 _( "This is the default net class." ) );
141
142 bds.UseCustomTrackViaSize( false );
143
144 // Initialize ratsnest
145 m_connectivity.reset( new CONNECTIVITY_DATA() );
146
147 // Set flag bits on these that will only be cleared if these are loaded from a legacy file
148 m_LegacyVisibleLayers.reset().set( Rescue );
150}
151
152
154{
155 m_itemByIdCache.clear();
156
157 // Clean up the owned elements
159
160 delete m_SolderMaskBridges;
161
162 BOARD_ITEM_SET ownedItems = GetItemSet();
163
164 m_zones.clear();
165 m_footprints.clear();
166 m_tracks.clear();
167 m_drawings.clear();
168 m_groups.clear();
169 m_points.clear();
170
171 // Generators not currently returned by GetItemSet
172 for( PCB_GENERATOR* g : m_generators )
173 ownedItems.insert( g );
174
175 delete m_boardOutline;
176 m_generators.clear();
177
178 // Delete the owned items after clearing the containers, because some item dtors
179 // cause call chains that query the containers
180 for( BOARD_ITEM* item : ownedItems )
181 delete item;
182
183 // Remove any listeners
185}
186
187
189{
190 if( !GetConnectivity()->Build( this, aReporter ) )
191 return false;
192
194 return true;
195}
196
197
198void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly )
199{
200 if( m_project )
201 ClearProject();
202
203 m_project = aProject;
204
205 if( aProject && !aReferenceOnly )
206 {
207 PROJECT_FILE& project = aProject->GetProjectFile();
208
209 // Link the design settings object to the project file
210 project.m_BoardSettings = &GetDesignSettings();
211
212 // Set parent, which also will load the values from JSON stored in the project if we don't
213 // have legacy design settings loaded already
214 project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
215
216 // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
217 // list at this point. If we loaded anything into it from a legacy board file then we
218 // want to transfer it over to the project netclasses list.
220 {
221 std::shared_ptr<NET_SETTINGS> legacySettings = GetDesignSettings().m_NetSettings;
222 std::shared_ptr<NET_SETTINGS>& projectSettings = project.NetSettings();
223
224 projectSettings->SetDefaultNetclass( legacySettings->GetDefaultNetclass() );
225 projectSettings->SetNetclasses( legacySettings->GetNetclasses() );
226 projectSettings->SetNetclassPatternAssignments(
227 std::move( legacySettings->GetNetclassPatternAssignments() ) );
228 }
229
230 // Now update the DesignSettings' netclass pointer to point into the project.
231 GetDesignSettings().m_NetSettings = project.NetSettings();
232 }
233}
234
235
237{
238 if( !m_project )
239 return;
240
241 PROJECT_FILE& project = m_project->GetProjectFile();
242
243 // Owned by the BOARD
244 if( project.m_BoardSettings )
245 {
246 project.ReleaseNestedSettings( project.m_BoardSettings );
247 project.m_BoardSettings = nullptr;
248 }
249
251 GetDesignSettings().SetParent( nullptr );
252 m_project = nullptr;
253}
254
255
257{
258 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
259
260 m_timeStamp++;
261
262 if( !m_IntersectsAreaCache.empty()
263 || !m_EnclosedByAreaCache.empty()
267 || !m_LayerExpressionCache.empty()
268 || !m_ZoneBBoxCache.empty()
270 || m_maxClearanceValue.has_value()
271 || !m_itemByIdCache.empty() )
272 {
273 m_IntersectsAreaCache.clear();
274 m_EnclosedByAreaCache.clear();
279
280 m_ZoneBBoxCache.clear();
281
282 m_CopperItemRTreeCache = nullptr;
283
284 // These are always regenerated before use, but still probably safer to clear them
285 // while we're here.
288 m_DRCZones.clear();
289 m_DRCCopperZones.clear();
292
293 m_maxClearanceValue.reset();
294
295 m_itemByIdCache.clear();
296 }
297}
298
299
301{
302 std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
303
304 for( PCB_MARKER* marker : GetBoard()->Markers() )
305 {
306 if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
307 {
308 const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
309 m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
310 m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
311 }
312 }
313
315 [&]( CN_EDGE& aEdge )
316 {
317 if( aEdge.GetSourceNode() && aEdge.GetTargetNode()
318 && !aEdge.GetSourceNode()->Dirty() && !aEdge.GetTargetNode()->Dirty() )
319 {
320 std::pair<KIID, KIID> ids = { aEdge.GetSourceNode()->Parent()->m_Uuid,
321 aEdge.GetTargetNode()->Parent()->m_Uuid };
322
323 aEdge.SetVisible( m_ratsnestExclusions.count( ids ) == 0 );
324 }
325
326 return true;
327 } );
328}
329
330
332{
333 m_designSettings->m_DrcExclusions.clear();
334 m_designSettings->m_DrcExclusionComments.clear();
335
336 for( PCB_MARKER* marker : m_markers )
337 {
338 if( marker->IsExcluded() )
339 {
340 wxString serialized = marker->SerializeToString();
341 m_designSettings->m_DrcExclusions.insert( serialized );
342 m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment();
343 }
344 }
345
346 if( m_project )
347 {
348 if( PROJECT_FILE* projectFile = &m_project->GetProjectFile() )
349 {
350 if( BOARD_DESIGN_SETTINGS* prjSettings = projectFile->m_BoardSettings )
351 {
352 prjSettings->m_DrcExclusions = m_designSettings->m_DrcExclusions;
353 prjSettings->m_DrcExclusionComments = m_designSettings->m_DrcExclusionComments;
354 }
355 }
356 }
357}
358
359std::set<wxString>::iterator FindByFirstNFields( std::set<wxString>& strSet, const wxString& searchStr, char delimiter,
360 int n )
361{
362 wxString searchPrefix = searchStr;
363
364 // Extract first n fields from the search string
365 int delimiterCount = 0;
366 size_t pos = 0;
367
368 while( pos < searchPrefix.length() && delimiterCount < n )
369 {
370 if( searchPrefix[pos] == delimiter )
371 delimiterCount++;
372
373 pos++;
374 }
375
376 if( delimiterCount == n )
377 searchPrefix = searchPrefix.Left( pos - 1 ); // Exclude the nth delimiter
378
379 for( auto it = strSet.begin(); it != strSet.end(); ++it )
380 {
381 if( it->StartsWith( searchPrefix + delimiter ) || *it == searchPrefix )
382 return it;
383 }
384
385 return strSet.end();
386}
387
388std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
389{
390 std::set<wxString> exclusions = m_designSettings->m_DrcExclusions;
391 std::map<wxString, wxString> comments = m_designSettings->m_DrcExclusionComments;
392
393 m_designSettings->m_DrcExclusions.clear();
394 m_designSettings->m_DrcExclusionComments.clear();
395
396 for( PCB_MARKER* marker : GetBoard()->Markers() )
397 {
398 std::set<wxString>::iterator it;
399 wxString serialized = marker->SerializeToString();
400 wxString matchedExclusion;
401
402 if( !serialized.Contains( "unconnected_items" ) )
403 {
404 it = exclusions.find( serialized );
405
406 if( it != exclusions.end() )
407 matchedExclusion = *it;
408 }
409 else
410 {
411 const int numberOfFieldsExcludingIds = 3;
412 const char delimiter = '|';
413 it = FindByFirstNFields( exclusions, serialized, delimiter, numberOfFieldsExcludingIds );
414
415 if( it != exclusions.end() )
416 matchedExclusion = *it;
417 }
418
419 if( it != exclusions.end() )
420 {
421 marker->SetExcluded( true, comments[matchedExclusion] );
422
423 // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS
424 m_designSettings->m_DrcExclusions.insert( matchedExclusion );
425 m_designSettings->m_DrcExclusionComments[matchedExclusion] = comments[matchedExclusion];
426
427 exclusions.erase( it );
428 }
429 }
430
431 std::vector<PCB_MARKER*> newMarkers;
432
433 if( aCreateMarkers )
434 {
435 for( const wxString& serialized : exclusions )
436 {
437 PCB_MARKER* marker = PCB_MARKER::DeserializeFromString( serialized );
438
439 if( !marker )
440 continue;
441
442 std::vector<KIID> ids = marker->GetRCItem()->GetIDs();
443
444 int uuidCount = 0;
445
446 for( const KIID& uuid : ids )
447 {
448 if( uuidCount < 1 || uuid != niluuid )
449 {
450 if( !ResolveItem( uuid, true ) )
451 {
452 delete marker;
453 marker = nullptr;
454 break;
455 }
456 }
457 uuidCount++;
458 }
459
460 if( marker )
461 {
462 marker->SetExcluded( true, comments[ serialized ] );
463 newMarkers.push_back( marker );
464
465 // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS
466 m_designSettings->m_DrcExclusions.insert( serialized );
467 m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ];
468 }
469 }
470 }
471
472 return newMarkers;
473}
474
475
476void BOARD::GetContextualTextVars( wxArrayString* aVars ) const
477{
478 auto add =
479 [&]( const wxString& aVar )
480 {
481 if( !alg::contains( *aVars, aVar ) )
482 aVars->push_back( aVar );
483 };
484
485 add( wxT( "LAYER" ) );
486 add( wxT( "FILENAME" ) );
487 add( wxT( "FILEPATH" ) );
488 add( wxT( "PROJECTNAME" ) );
489 add( wxT( "DRC_ERROR <message_text>" ) );
490 add( wxT( "DRC_WARNING <message_text>" ) );
491
493
494 if( GetProject() )
495 {
496 for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
497 add( entry.first );
498 }
499}
500
501
502bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
503{
504 if( token->Contains( ':' ) )
505 {
506 wxString remainder;
507 wxString ref = token->BeforeFirst( ':', &remainder );
508 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
509
510 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
511 {
512 FOOTPRINT* refFP = static_cast<FOOTPRINT*>( refItem );
513
514 if( refFP->ResolveTextVar( &remainder, aDepth + 1 ) )
515 {
516 *token = std::move( remainder );
517 return true;
518 }
519 }
520 }
521
522 if( token->IsSameAs( wxT( "FILENAME" ) ) )
523 {
524 wxFileName fn( GetFileName() );
525 *token = fn.GetFullName();
526 return true;
527 }
528 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
529 {
530 wxFileName fn( GetFileName() );
531 *token = fn.GetFullPath();
532 return true;
533 }
534 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) && GetProject() )
535 {
536 *token = GetProject()->GetProjectName();
537 return true;
538 }
539
540 wxString var = *token;
541
542 if( m_properties.count( var ) )
543 {
544 *token = m_properties.at( var );
545 return true;
546 }
547 else if( GetTitleBlock().TextVarResolver( token, m_project ) )
548 {
549 return true;
550 }
551
552 if( GetProject() && GetProject()->TextVarResolver( token ) )
553 return true;
554
555 return false;
556}
557
558
559bool BOARD::IsEmpty() const
560{
561 return m_drawings.empty() && m_footprints.empty() && m_tracks.empty() && m_zones.empty() && m_points.empty();
562}
563
564
566{
567 return ZeroOffset;
568}
569
570
571void BOARD::SetPosition( const VECTOR2I& aPos )
572{
573 wxLogWarning( wxT( "This should not be called on the BOARD object") );
574}
575
576
577void BOARD::Move( const VECTOR2I& aMoveVector ) // overload
578{
579 INSPECTOR_FUNC inspector =
580 [&] ( EDA_ITEM* item, void* testData )
581 {
582 if( item->IsBOARD_ITEM() )
583 {
584 BOARD_ITEM* board_item = static_cast<BOARD_ITEM*>( item );
585
586 // aMoveVector was snapshotted, don't need "data".
587 // Only move the top level group
588 if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() )
589 board_item->Move( aMoveVector );
590 }
591
593 };
594
595 Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems );
596}
597
598
599void BOARD::RunOnChildren( const std::function<void( BOARD_ITEM* )>& aFunction, RECURSE_MODE aMode ) const
600{
601 try
602 {
603 for( PCB_TRACK* track : m_tracks )
604 aFunction( track );
605
606 for( ZONE* zone : m_zones )
607 aFunction( zone );
608
609 for( PCB_MARKER* marker : m_markers )
610 aFunction( marker );
611
612 for( PCB_GROUP* group : m_groups )
613 aFunction( group );
614
615 for( PCB_POINT* point : m_points )
616 aFunction( point );
617
618 for( FOOTPRINT* footprint : m_footprints )
619 {
620 aFunction( footprint );
621
622 if( aMode == RECURSE_MODE::RECURSE )
623 footprint->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
624 }
625
626 for( BOARD_ITEM* drawing : m_drawings )
627 {
628 aFunction( drawing );
629
630 if( aMode == RECURSE_MODE::RECURSE )
631 drawing->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
632 }
633 }
634 catch( std::bad_function_call& )
635 {
636 wxFAIL_MSG( wxT( "Error running BOARD::RunOnChildren" ) );
637 }
638}
639
640
642{
643 TRACKS ret;
644
645 INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
646 {
647 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
648
649 if( t->GetNetCode() == aNetCode )
650 ret.push_back( t );
651
653 };
654
655 // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
656 // appends all in aNetCode to ret.
657 Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
658
659 return ret;
660}
661
662
663bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
664{
665 m_layers[ aIndex ] = aLayer;
667 return true;
668}
669
670
671PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
672{
673 // Check the BOARD physical layer names.
674 for( auto& [ layer_id, layer ] : m_layers )
675 {
676 if( layer.m_name == aLayerName || layer.m_userName == aLayerName )
677 return ToLAYER_ID( layer_id );
678 }
679
680 // Otherwise fall back to the system standard layer names for virtual layers.
681 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
682 {
683 if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
684 return ToLAYER_ID( layer );
685 }
686
687 return UNDEFINED_LAYER;
688}
689
690
691const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
692{
693 // All layer names are stored in the BOARD.
694 if( IsLayerEnabled( aLayer ) )
695 {
696 auto it = m_layers.find( aLayer );
697
698 // Standard names were set in BOARD::BOARD() but they may be over-ridden by
699 // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
700 // if it was set. Otherwise return the Standard English layer name.
701 if( it != m_layers.end() && !it->second.m_userName.IsEmpty() )
702 return it->second.m_userName;
703 }
704
705 return GetStandardLayerName( aLayer );
706}
707
708
709bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
710{
711 if( aLayerName.IsEmpty() )
712 {
713 // If the name is empty, we clear the user name.
714 m_layers[aLayer].m_userName.clear();
715 }
716 else
717 {
718 // no quote chars in the name allowed
719 if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
720 return false;
721
722 if( IsLayerEnabled( aLayer ) )
723 {
724 m_layers[aLayer].m_userName = aLayerName;
726 return true;
727 }
728 }
729
730 return false;
731}
732
733
735{
736 return ::IsFrontLayer( aLayer ) || GetLayerType( aLayer ) == LT_FRONT;
737}
738
739
741{
742 return ::IsBackLayer( aLayer ) || GetLayerType( aLayer ) == LT_BACK;
743}
744
745
747{
748 if( IsLayerEnabled( aLayer ) )
749 {
750 auto it = m_layers.find( aLayer );
751
752 if( it != m_layers.end() )
753 return it->second.m_type;
754 }
755
756 if( aLayer >= User_1 && !IsCopperLayer( aLayer ) )
757 return LT_AUX;
758 else if( IsCopperLayer( aLayer ) )
759 return LT_SIGNAL;
760 else
761 return LT_UNDEFINED;
762}
763
764
765bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
766{
767 if( IsLayerEnabled( aLayer ) )
768 {
769 m_layers[aLayer].m_type = aLayerType;
771 return true;
772 }
773
774 return false;
775}
776
777
778const char* LAYER::ShowType( LAYER_T aType )
779{
780 switch( aType )
781 {
782 default:
783 case LT_SIGNAL: return "signal";
784 case LT_POWER: return "power";
785 case LT_MIXED: return "mixed";
786 case LT_JUMPER: return "jumper";
787 case LT_AUX: return "auxiliary";
788 case LT_FRONT: return "front";
789 case LT_BACK: return "back";
790 }
791}
792
793
794LAYER_T LAYER::ParseType( const char* aType )
795{
796 if( strcmp( aType, "signal" ) == 0 ) return LT_SIGNAL;
797 else if( strcmp( aType, "power" ) == 0 ) return LT_POWER;
798 else if( strcmp( aType, "mixed" ) == 0 ) return LT_MIXED;
799 else if( strcmp( aType, "jumper" ) == 0 ) return LT_JUMPER;
800 else if( strcmp( aType, "auxiliary" ) == 0 ) return LT_AUX;
801 else if( strcmp( aType, "front" ) == 0 ) return LT_FRONT;
802 else if( strcmp( aType, "back" ) == 0 ) return LT_BACK;
803 else return LT_UNDEFINED;
804}
805
806
808{
809 for( int layer = F_Cu; layer < PCB_LAYER_ID_COUNT; ++layer )
810 m_layers[layer].m_opposite = ::FlipLayer( ToLAYER_ID( layer ), GetCopperLayerCount() );
811
812 // Match up similary-named front/back user layers
813 for( int layer = User_1; layer <= PCB_LAYER_ID_COUNT; layer += 2 )
814 {
815 if( m_layers[layer].m_opposite != layer ) // already paired
816 continue;
817
818 if( m_layers[layer].m_type != LT_FRONT && m_layers[layer].m_type != LT_BACK )
819 continue;
820
821 wxString principalName = m_layers[layer].m_userName.AfterFirst( '.' );
822
823 for( int ii = layer + 2; ii <= PCB_LAYER_ID_COUNT; ii += 2 )
824 {
825 if( m_layers[ii].m_opposite != ii ) // already paired
826 continue;
827
828 if( m_layers[ii].m_type != LT_FRONT && m_layers[ii].m_type != LT_BACK )
829 continue;
830
831 if( m_layers[layer].m_type == m_layers[ii].m_type )
832 continue;
833
834 wxString candidate = m_layers[ii].m_userName.AfterFirst( '.' );
835
836 if( !candidate.IsEmpty() && candidate == principalName )
837 {
838 m_layers[layer].m_opposite = ii;
839 m_layers[ii].m_opposite = layer;
840 break;
841 }
842 }
843 }
844
845 // Match up non-custom-named consecutive front/back user layer pairs
846 for( int layer = User_1; layer < PCB_LAYER_ID_COUNT - 2; layer += 2 )
847 {
848 int next = layer + 2;
849
850 // ignore already-matched layers
851 if( m_layers[layer].m_opposite != layer || m_layers[next].m_opposite != next )
852 continue;
853
854 // ignore layer pairs that aren't consecutive front/back
855 if( m_layers[layer].m_type != LT_FRONT || m_layers[next].m_type != LT_BACK )
856 continue;
857
858 if( m_layers[layer].m_userName != m_layers[layer].m_name
859 && m_layers[next].m_userName != m_layers[next].m_name )
860 {
861 m_layers[layer].m_opposite = next;
862 m_layers[next].m_opposite = layer;
863 }
864 }
865}
866
867
869{
870 auto it = m_layers.find( aLayer );
871 return it == m_layers.end() ? aLayer : ToLAYER_ID( it->second.m_opposite );
872}
873
874
879
880
882{
884}
885
886
891
892
894{
896}
897
899{
900 int imax = GetCopperLayerCount();
901
902 // layers IDs are F_Cu, B_Cu, and even IDs values (imax values)
903 if( imax <= 2 ) // at least 2 layers are expected
904 return B_Cu;
905
906 // For a 4 layer, last ID is In2_Cu = 6 (IDs are 0, 2, 4, 6)
907 return static_cast<PCB_LAYER_ID>( (imax-1) * 2 );
908}
909
910
911int BOARD::LayerDepth( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer ) const
912{
913 if( aStartLayer > aEndLayer )
914 std::swap( aStartLayer, aEndLayer );
915
916 if( aEndLayer == B_Cu )
917 aEndLayer = ToLAYER_ID( F_Cu + GetCopperLayerCount() - 1 );
918
919 return aEndLayer - aStartLayer;
920}
921
922
924{
926}
927
928
930{
931 // If there is no project, assume layer is visible always
932 return GetDesignSettings().IsLayerEnabled( aLayer )
933 && ( !m_project || m_project->GetLocalSettings().m_VisibleLayers[aLayer] );
934}
935
936
938{
939 return m_project ? m_project->GetLocalSettings().m_VisibleLayers : LSET::AllLayersMask();
940}
941
942
943void BOARD::SetEnabledLayers( const LSET& aLayerSet )
944{
945 GetDesignSettings().SetEnabledLayers( aLayerSet );
946}
947
948
950{
951 return GetDesignSettings().IsLayerEnabled( aLayer );
952}
953
954
955void BOARD::SetVisibleLayers( const LSET& aLayerSet )
956{
957 if( m_project )
958 m_project->GetLocalSettings().m_VisibleLayers = aLayerSet;
959}
960
961
963{
964 // Call SetElementVisibility for each item
965 // to ensure specific calculations that can be needed by some items,
966 // just changing the visibility flags could be not sufficient.
967 for( size_t i = 0; i < aSet.size(); i++ )
968 SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
969}
970
971
973{
974 SetVisibleLayers( LSET().set() );
975
976 // Call SetElementVisibility for each item,
977 // to ensure specific calculations that can be needed by some items
979 SetElementVisibility( ii, true );
980}
981
982
984{
985 return m_project ? m_project->GetLocalSettings().m_VisibleItems : GAL_SET::DefaultVisible();
986}
987
988
990{
991 return !m_project || m_project->GetLocalSettings().m_VisibleItems[aLayer - GAL_LAYER_ID_START];
992}
993
994
995void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
996{
997 if( m_project )
998 m_project->GetLocalSettings().m_VisibleItems.set( aLayer - GAL_LAYER_ID_START, isEnabled );
999
1000 switch( aLayer )
1001 {
1002 case LAYER_RATSNEST:
1003 {
1004 // because we have a tool to show/hide ratsnest relative to a pad or a footprint
1005 // so the hide/show option is a per item selection
1006
1007 for( PCB_TRACK* track : Tracks() )
1008 track->SetLocalRatsnestVisible( isEnabled );
1009
1010 for( FOOTPRINT* footprint : Footprints() )
1011 {
1012 for( PAD* pad : footprint->Pads() )
1013 pad->SetLocalRatsnestVisible( isEnabled );
1014 }
1015
1016 for( ZONE* zone : Zones() )
1017 zone->SetLocalRatsnestVisible( isEnabled );
1018
1019 break;
1020 }
1021
1022 default:
1023 ;
1024 }
1025}
1026
1027
1029{
1030 switch( aLayer )
1031 {
1034 default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true;
1035 }
1036}
1037
1038
1039
1044
1045
1047{
1048 *m_designSettings = aSettings;
1049}
1050
1051
1053{
1054 if( !m_maxClearanceValue.has_value() )
1055 {
1056 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
1057
1058 int worstClearance = m_designSettings->GetBiggestClearanceValue();
1059
1060 for( ZONE* zone : m_zones )
1061 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1062
1063 for( FOOTPRINT* footprint : m_footprints )
1064 {
1065 for( PAD* pad : footprint->Pads() )
1066 {
1067 std::optional<int> override = pad->GetClearanceOverrides( nullptr );
1068
1069 if( override.has_value() )
1070 worstClearance = std::max( worstClearance, override.value() );
1071 }
1072
1073 for( ZONE* zone : footprint->Zones() )
1074 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1075 }
1076
1077 m_maxClearanceValue = worstClearance;
1078 }
1079
1080 return m_maxClearanceValue.value_or( 0 );
1081};
1082
1083
1084void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<ZONE*>& aZones )
1085{
1086 std::vector<ZONE*> zones = aZones;
1087
1088 if( zones.empty() )
1089 zones = m_zones;
1090
1091 if( zones.empty() )
1092 return;
1093
1094 if( aReporter )
1095 aReporter->Report( _( "Tessellating copper zones..." ) );
1096
1098 std::vector<std::future<size_t>> returns;
1099
1100 returns.reserve( zones.size() );
1101
1102 auto cache_zones =
1103 [aReporter]( ZONE* aZone ) -> size_t
1104 {
1105 if( aReporter && aReporter->IsCancelled() )
1106 return 0;
1107
1108 aZone->CacheTriangulation();
1109
1110 if( aReporter )
1111 aReporter->AdvanceProgress();
1112
1113 return 1;
1114 };
1115
1116 for( ZONE* zone : zones )
1117 returns.emplace_back( tp.submit_task( [cache_zones, zone] { return cache_zones( zone ); } ) );
1118
1119 // Finalize the triangulation threads
1120 for( const std::future<size_t>& ret : returns )
1121 {
1122 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1123
1124 while( status != std::future_status::ready )
1125 {
1126 if( aReporter )
1127 aReporter->KeepRefreshing();
1128
1129 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1130 }
1131 }
1132}
1133
1134
1135void BOARD::RunOnNestedEmbeddedFiles( const std::function<void( EMBEDDED_FILES* )>& aFunction )
1136{
1137 for( FOOTPRINT* footprint : m_footprints )
1138 aFunction( footprint->GetEmbeddedFiles() );
1139}
1140
1141
1143{
1145 [&]( EMBEDDED_FILES* nested )
1146 {
1147 for( auto& [filename, embeddedFile] : nested->EmbeddedFileMap() )
1148 {
1150
1151 if( file )
1152 {
1153 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1154 embeddedFile->decompressedData = file->decompressedData;
1155 embeddedFile->data_hash = file->data_hash;
1156 embeddedFile->is_valid = file->is_valid;
1157 }
1158 }
1159 } );
1160}
1161
1162
1163void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
1164{
1165 if( aBoardItem == nullptr )
1166 {
1167 wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem nullptr" ) );
1168 return;
1169 }
1170
1171 m_itemByIdCache.insert( { aBoardItem->m_Uuid, aBoardItem } );
1172
1173 switch( aBoardItem->Type() )
1174 {
1175 case PCB_NETINFO_T:
1176 m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
1177 break;
1178
1179 // this one uses a vector
1180 case PCB_MARKER_T:
1181 m_markers.push_back( (PCB_MARKER*) aBoardItem );
1182 break;
1183
1184 // this one uses a vector
1185 case PCB_GROUP_T:
1186 m_groups.push_back( (PCB_GROUP*) aBoardItem );
1187 break;
1188
1189 // this one uses a vector
1190 case PCB_GENERATOR_T:
1191 m_generators.push_back( (PCB_GENERATOR*) aBoardItem );
1192 break;
1193
1194 // this one uses a vector
1195 case PCB_ZONE_T:
1196 m_zones.push_back( (ZONE*) aBoardItem );
1197 break;
1198
1199 case PCB_VIA_T:
1200 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1201 m_tracks.push_back( static_cast<PCB_VIA*>( aBoardItem ) );
1202 else
1203 m_tracks.push_front( static_cast<PCB_VIA*>( aBoardItem ) );
1204
1205 break;
1206
1207
1208 case PCB_TRACE_T:
1209 case PCB_ARC_T:
1210 if( !IsCopperLayer( aBoardItem->GetLayer() ) )
1211 {
1212 // The only current known source of these is SWIG (KICAD-BY7, et al).
1213 // N.B. This inserts a small memory leak as we lose the track/via/arc.
1214 wxFAIL_MSG( wxString::Format( "BOARD::Add() Cannot place Track on non-copper layer: %d = %s",
1215 static_cast<int>( aBoardItem->GetLayer() ),
1216 GetLayerName( aBoardItem->GetLayer() ) ) );
1217 return;
1218 }
1219
1220 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1221 m_tracks.push_back( static_cast<PCB_TRACK*>( aBoardItem ) );
1222 else
1223 m_tracks.push_front( static_cast<PCB_TRACK*>( aBoardItem ) );
1224
1225 break;
1226
1227 case PCB_FOOTPRINT_T:
1228 {
1229 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aBoardItem );
1230
1231 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1232 m_footprints.push_back( footprint );
1233 else
1234 m_footprints.push_front( footprint );
1235
1236 footprint->RunOnChildren( [&]( BOARD_ITEM* aChild )
1237 {
1238 m_itemByIdCache.insert( { aChild->m_Uuid, aChild } );
1239 },
1241 break;
1242 }
1243
1244 case PCB_DIM_ALIGNED_T:
1245 case PCB_DIM_CENTER_T:
1246 case PCB_DIM_RADIAL_T:
1248 case PCB_DIM_LEADER_T:
1249 case PCB_SHAPE_T:
1251 case PCB_FIELD_T:
1252 case PCB_TEXT_T:
1253 case PCB_TEXTBOX_T:
1254 case PCB_TABLE_T:
1255 case PCB_TARGET_T:
1256 {
1257 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1258 m_drawings.push_back( aBoardItem );
1259 else
1260 m_drawings.push_front( aBoardItem );
1261
1262 if( aBoardItem->Type() == PCB_TABLE_T )
1263 {
1264 PCB_TABLE* table = static_cast<PCB_TABLE*>( aBoardItem );
1265
1266 table->RunOnChildren( [&]( BOARD_ITEM* aChild )
1267 {
1268 m_itemByIdCache.insert( { aChild->m_Uuid, aChild } );
1269 },
1271 }
1272
1273 break;
1274 }
1275
1276 case PCB_POINT_T:
1277 // These aren't graphics as they have no physical presence
1278 m_points.push_back( static_cast<PCB_POINT*>( aBoardItem ) );
1279 break;
1280
1281 case PCB_TABLECELL_T:
1282 // Handled by parent table
1283 break;
1284
1285 default:
1286 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Add() item type %s not handled" ),
1287 aBoardItem->GetClass() ) );
1288 return;
1289 }
1290
1291 aBoardItem->SetParent( this );
1292 aBoardItem->ClearEditFlags();
1293
1294 if( !aSkipConnectivity )
1295 m_connectivity->Add( aBoardItem );
1296
1297 if( aMode != ADD_MODE::BULK_INSERT && aMode != ADD_MODE::BULK_APPEND )
1299}
1300
1301
1302void BOARD::FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems )
1303{
1305}
1306
1307
1308void BOARD::FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems )
1309{
1310 InvokeListeners( &BOARD_LISTENER::OnBoardItemsRemoved, *this, aRemovedItems );
1311}
1312
1313
1315{
1316 for( int ii = (int) m_zones.size() - 1; ii >= 0; --ii )
1317 {
1318 ZONE* zone = m_zones[ii];
1319
1320 if( zone->IsTeardropArea() && zone->HasFlag( STRUCT_DELETED ) )
1321 {
1322 m_itemByIdCache.erase( zone->m_Uuid );
1323 m_zones.erase( m_zones.begin() + ii );
1324 m_connectivity->Remove( zone );
1325 aCommit.Removed( zone );
1326 }
1327 }
1328}
1329
1330
1331void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
1332{
1333 // find these calls and fix them! Don't send me no stinking' nullptr.
1334 wxASSERT( aBoardItem );
1335
1336 m_itemByIdCache.erase( aBoardItem->m_Uuid );
1337
1338 switch( aBoardItem->Type() )
1339 {
1340 case PCB_NETINFO_T:
1341 {
1342 NETINFO_ITEM* netItem = static_cast<NETINFO_ITEM*>( aBoardItem );
1343 NETINFO_ITEM* unconnected = m_NetInfo.GetNetItem( NETINFO_LIST::UNCONNECTED );
1344
1345 for( BOARD_CONNECTED_ITEM* boardItem : AllConnectedItems() )
1346 {
1347 if( boardItem->GetNet() == netItem )
1348 boardItem->SetNet( unconnected );
1349 }
1350
1351 m_NetInfo.RemoveNet( netItem );
1352 break;
1353 }
1354
1355 case PCB_MARKER_T:
1356 std::erase( m_markers, aBoardItem );
1357 break;
1358
1359 case PCB_GROUP_T:
1360 std::erase( m_groups, aBoardItem );
1361 break;
1362
1363 case PCB_ZONE_T:
1364 std::erase( m_zones, aBoardItem );
1365 break;
1366
1367 case PCB_POINT_T:
1368 std::erase( m_points, aBoardItem );
1369 break;
1370
1371 case PCB_GENERATOR_T:
1372 std::erase( m_generators, aBoardItem );
1373 break;
1374
1375 case PCB_FOOTPRINT_T:
1376 {
1377 std::erase( m_footprints, aBoardItem );
1378 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aBoardItem );
1379
1380 footprint->RunOnChildren( [&]( BOARD_ITEM* aChild )
1381 {
1382 m_itemByIdCache.erase( aChild->m_Uuid );
1383 },
1385
1386 break;
1387 }
1388
1389 case PCB_TRACE_T:
1390 case PCB_ARC_T:
1391 case PCB_VIA_T:
1392 std::erase( m_tracks, aBoardItem );
1393 break;
1394
1395 case PCB_DIM_ALIGNED_T:
1396 case PCB_DIM_CENTER_T:
1397 case PCB_DIM_RADIAL_T:
1399 case PCB_DIM_LEADER_T:
1400 case PCB_SHAPE_T:
1402 case PCB_FIELD_T:
1403 case PCB_TEXT_T:
1404 case PCB_TEXTBOX_T:
1405 case PCB_TABLE_T:
1406 case PCB_TARGET_T:
1407 {
1408 std::erase( m_drawings, aBoardItem );
1409
1410 if( aBoardItem->Type() == PCB_TABLE_T )
1411 {
1412 PCB_TABLE* table = static_cast<PCB_TABLE*>( aBoardItem );
1413
1414 table->RunOnChildren( [&]( BOARD_ITEM* aChild )
1415 {
1416 m_itemByIdCache.erase( aChild->m_Uuid );
1417 },
1419 }
1420
1421 break;
1422 }
1423
1424 case PCB_TABLECELL_T:
1425 // Handled by parent table
1426 break;
1427
1428 // other types may use linked list
1429 default:
1430 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Remove() item type %s not handled" ),
1431 aBoardItem->GetClass() ) );
1432 }
1433
1434 aBoardItem->SetFlags( STRUCT_DELETED );
1435
1436 m_connectivity->Remove( aBoardItem );
1437
1438 if( aRemoveMode != REMOVE_MODE::BULK )
1440}
1441
1442
1443void BOARD::RemoveAll( std::initializer_list<KICAD_T> aTypes )
1444{
1445 std::vector<BOARD_ITEM*> removed;
1446
1447 for( const KICAD_T& type : aTypes )
1448 {
1449 switch( type )
1450 {
1451 case PCB_NETINFO_T:
1452 for( NETINFO_ITEM* item : m_NetInfo )
1453 removed.emplace_back( item );
1454
1455 m_NetInfo.clear();
1456 break;
1457
1458 case PCB_MARKER_T:
1459 std::copy( m_markers.begin(), m_markers.end(), std::back_inserter( removed ) );
1460 m_markers.clear();
1461 break;
1462
1463 case PCB_GROUP_T:
1464 std::copy( m_groups.begin(), m_groups.end(), std::back_inserter( removed ) );
1465 m_groups.clear();
1466 break;
1467
1468 case PCB_POINT_T:
1469 std::copy( m_points.begin(), m_points.end(), std::back_inserter( removed ) );
1470 m_points.clear();
1471 break;
1472
1473 case PCB_ZONE_T:
1474 std::copy( m_zones.begin(), m_zones.end(), std::back_inserter( removed ) );
1475 m_zones.clear();
1476 break;
1477
1478 case PCB_GENERATOR_T:
1479 std::copy( m_generators.begin(), m_generators.end(), std::back_inserter( removed ) );
1480 m_generators.clear();
1481 break;
1482
1483 case PCB_FOOTPRINT_T:
1484 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( removed ) );
1485 m_footprints.clear();
1486 break;
1487
1488 case PCB_TRACE_T:
1489 std::copy( m_tracks.begin(), m_tracks.end(), std::back_inserter( removed ) );
1490 m_tracks.clear();
1491 break;
1492
1493 case PCB_ARC_T:
1494 case PCB_VIA_T:
1495 wxFAIL_MSG( wxT( "Use PCB_TRACE_T to remove all tracks, arcs, and vias" ) );
1496 break;
1497
1498 case PCB_SHAPE_T:
1499 std::copy( m_drawings.begin(), m_drawings.end(), std::back_inserter( removed ) );
1500 m_drawings.clear();
1501 break;
1502
1503 case PCB_DIM_ALIGNED_T:
1504 case PCB_DIM_CENTER_T:
1505 case PCB_DIM_RADIAL_T:
1507 case PCB_DIM_LEADER_T:
1509 case PCB_FIELD_T:
1510 case PCB_TEXT_T:
1511 case PCB_TEXTBOX_T:
1512 case PCB_TABLE_T:
1513 case PCB_TARGET_T:
1514 wxFAIL_MSG( wxT( "Use PCB_SHAPE_T to remove all graphics and text" ) );
1515 break;
1516
1517 default:
1518 wxFAIL_MSG( wxT( "BOARD::RemoveAll() needs more ::Type() support" ) );
1519 }
1520 }
1521
1523
1524 FinalizeBulkRemove( removed );
1525}
1526
1527
1528wxString BOARD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1529{
1530 return wxString::Format( _( "PCB" ) );
1531}
1532
1533
1535{
1536 INSPECTOR_FUNC inspector =
1537 [&]( EDA_ITEM* descendant, void* aTestData )
1538 {
1539 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( descendant );
1540
1541 if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC )
1542 {
1543 dimension->UpdateUnits();
1544
1545 if( aView )
1546 aView->Update( dimension );
1547 }
1548
1550 };
1551
1552 aItem->Visit( inspector, nullptr, { PCB_DIM_ALIGNED_T,
1556 PCB_DIM_RADIAL_T } );
1557}
1558
1559
1561{
1562 for( PCB_MARKER* marker : m_markers )
1563 delete marker;
1564
1565 m_markers.clear();
1567}
1568
1569
1570void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
1571{
1572 // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
1573 std::vector<PCB_MARKER*> remaining;
1574
1575 for( PCB_MARKER* marker : m_markers )
1576 {
1577 if( ( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION && aExclusions )
1578 || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) )
1579 {
1580 delete marker;
1581 }
1582 else
1583 {
1584 remaining.push_back( marker );
1585 }
1586 }
1587
1588 m_markers = std::move( remaining );
1590}
1591
1592
1594{
1595 for( FOOTPRINT* footprint : m_footprints )
1596 delete footprint;
1597
1598 m_footprints.clear();
1600}
1601
1602
1604{
1605 for( FOOTPRINT* footprint : m_footprints )
1606 footprint->SetParent( nullptr );
1607
1608 m_footprints.clear();
1610}
1611
1612
1613BOARD_ITEM* BOARD::ResolveItem( const KIID& aID, bool aAllowNullptrReturn ) const
1614{
1615 if( aID == niluuid )
1616 return nullptr;
1617
1618 if( m_itemByIdCache.count( aID ) )
1619 return m_itemByIdCache.at( aID );
1620
1621 // Main clients include highlighting, group undo/redo and DRC items. Since
1622 // everything but group undo/redo will be spread over all object types, we
1623 // might as well prioritize group undo/redo and search them first.
1624
1625 for( PCB_GROUP* group : m_groups )
1626 {
1627 if( group->m_Uuid == aID )
1628 return group;
1629 }
1630
1631 for( PCB_GENERATOR* generator : m_generators )
1632 {
1633 if( generator->m_Uuid == aID )
1634 return generator;
1635 }
1636
1637 for( PCB_TRACK* track : Tracks() )
1638 {
1639 if( track->m_Uuid == aID )
1640 return track;
1641 }
1642
1643 for( FOOTPRINT* footprint : Footprints() )
1644 {
1645 if( footprint->m_Uuid == aID )
1646 return footprint;
1647
1648 for( PAD* pad : footprint->Pads() )
1649 {
1650 if( pad->m_Uuid == aID )
1651 return pad;
1652 }
1653
1654 for( PCB_FIELD* field : footprint->GetFields() )
1655 {
1656 if( field && field->m_Uuid == aID )
1657 return field;
1658 }
1659
1660 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1661 {
1662 if( drawing->m_Uuid == aID )
1663 return drawing;
1664 }
1665
1666 for( BOARD_ITEM* zone : footprint->Zones() )
1667 {
1668 if( zone->m_Uuid == aID )
1669 return zone;
1670 }
1671
1672 for( PCB_GROUP* group : footprint->Groups() )
1673 {
1674 if( group->m_Uuid == aID )
1675 return group;
1676 }
1677 }
1678
1679 for( ZONE* zone : Zones() )
1680 {
1681 if( zone->m_Uuid == aID )
1682 return zone;
1683 }
1684
1685 for( BOARD_ITEM* drawing : Drawings() )
1686 {
1687 if( drawing->Type() == PCB_TABLE_T )
1688 {
1689 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( drawing )->GetCells() )
1690 {
1691 if( cell->m_Uuid == aID )
1692 return drawing;
1693 }
1694 }
1695
1696 if( drawing->m_Uuid == aID )
1697 return drawing;
1698 }
1699
1700 for( PCB_MARKER* marker : m_markers )
1701 {
1702 if( marker->m_Uuid == aID )
1703 return marker;
1704 }
1705
1706 for( PCB_POINT* point : m_points )
1707 {
1708 if( point->m_Uuid == aID )
1709 return point;
1710 }
1711
1712 for( NETINFO_ITEM* netInfo : m_NetInfo )
1713 {
1714 if( netInfo->m_Uuid == aID )
1715 return netInfo;
1716 }
1717
1718 if( m_Uuid == aID )
1719 return const_cast<BOARD*>( this );
1720
1721 // Not found; weak reference has been deleted.
1722 if( aAllowNullptrReturn )
1723 return nullptr;
1724
1726}
1727
1728
1729void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1730{
1731 // the board itself
1732 aMap[ m_Uuid ] = this;
1733
1734 for( PCB_TRACK* track : Tracks() )
1735 aMap[ track->m_Uuid ] = track;
1736
1737 for( FOOTPRINT* footprint : Footprints() )
1738 {
1739 aMap[ footprint->m_Uuid ] = footprint;
1740
1741 for( PAD* pad : footprint->Pads() )
1742 aMap[ pad->m_Uuid ] = pad;
1743
1744 aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference();
1745 aMap[ footprint->Value().m_Uuid ] = &footprint->Value();
1746
1747 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1748 aMap[ drawing->m_Uuid ] = drawing;
1749 }
1750
1751 for( ZONE* zone : Zones() )
1752 aMap[ zone->m_Uuid ] = zone;
1753
1754 for( BOARD_ITEM* drawing : Drawings() )
1755 aMap[ drawing->m_Uuid ] = drawing;
1756
1757 for( PCB_MARKER* marker : m_markers )
1758 aMap[ marker->m_Uuid ] = marker;
1759
1760 for( PCB_GROUP* group : m_groups )
1761 aMap[ group->m_Uuid ] = group;
1762
1763 for( PCB_POINT* point : m_points )
1764 aMap[ point->m_Uuid ] = point;
1765
1766 for( PCB_GENERATOR* generator : m_generators )
1767 aMap[ generator->m_Uuid ] = generator;
1768}
1769
1770
1771wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
1772{
1773 wxString newbuf;
1774 size_t sourceLen = aSource.length();
1775
1776 for( size_t i = 0; i < sourceLen; ++i )
1777 {
1778 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1779 {
1780 wxString token;
1781 bool isCrossRef = false;
1782
1783 for( i = i + 2; i < sourceLen; ++i )
1784 {
1785 if( aSource[i] == '}' )
1786 break;
1787
1788 if( aSource[i] == ':' )
1789 isCrossRef = true;
1790
1791 token.append( aSource[i] );
1792 }
1793
1794 if( isCrossRef )
1795 {
1796 wxString remainder;
1797 wxString ref = token.BeforeFirst( ':', &remainder );
1798
1799 for( const FOOTPRINT* footprint : Footprints() )
1800 {
1801 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
1802 {
1803 wxString test( remainder );
1804
1805 if( footprint->ResolveTextVar( &test ) )
1806 token = footprint->m_Uuid.AsString() + wxT( ":" ) + remainder;
1807
1808 break;
1809 }
1810 }
1811 }
1812
1813 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1814 }
1815 else
1816 {
1817 newbuf.append( aSource[i] );
1818 }
1819 }
1820
1821 return newbuf;
1822}
1823
1824
1825wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
1826{
1827 wxString newbuf;
1828 size_t sourceLen = aSource.length();
1829
1830 for( size_t i = 0; i < sourceLen; ++i )
1831 {
1832 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1833 {
1834 wxString token;
1835 bool isCrossRef = false;
1836
1837 for( i = i + 2; i < sourceLen; ++i )
1838 {
1839 if( aSource[i] == '}' )
1840 break;
1841
1842 if( aSource[i] == ':' )
1843 isCrossRef = true;
1844
1845 token.append( aSource[i] );
1846 }
1847
1848 if( isCrossRef )
1849 {
1850 wxString remainder;
1851 wxString ref = token.BeforeFirst( ':', &remainder );
1852 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
1853
1854 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
1855 {
1856 token = static_cast<FOOTPRINT*>( refItem )->GetReference() + wxT( ":" )
1857 + remainder;
1858 }
1859 }
1860
1861 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1862 }
1863 else
1864 {
1865 newbuf.append( aSource[i] );
1866 }
1867 }
1868
1869 return newbuf;
1870}
1871
1872
1873unsigned BOARD::GetNodesCount( int aNet ) const
1874{
1875 unsigned retval = 0;
1876
1877 for( FOOTPRINT* footprint : Footprints() )
1878 {
1879 for( PAD* pad : footprint->Pads() )
1880 {
1881 if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1882 retval++;
1883 }
1884 }
1885
1886 return retval;
1887}
1888
1889
1890BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1891{
1892 BOX2I bbox;
1893 LSET visible = GetVisibleLayers();
1894
1895 // If the board is just showing a footprint, we want all footprint layers included in the
1896 // bounding box
1897 if( IsFootprintHolder() )
1898 visible.set();
1899
1900 if( aBoardEdgesOnly )
1901 visible.set( Edge_Cuts );
1902
1903 // Check shapes, dimensions, texts, and fiducials
1904 for( BOARD_ITEM* item : m_drawings )
1905 {
1906 if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
1907 continue;
1908
1909 if( ( item->GetLayerSet() & visible ).any() )
1910 bbox.Merge( item->GetBoundingBox() );
1911 }
1912
1913 // Check footprints
1914 for( FOOTPRINT* footprint : m_footprints )
1915 {
1916 if( aBoardEdgesOnly )
1917 {
1918 for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
1919 {
1920 if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_SHAPE_T )
1921 bbox.Merge( edge->GetBoundingBox() );
1922 }
1923 }
1924 else if( ( footprint->GetLayerSet() & visible ).any() )
1925 {
1926 bbox.Merge( footprint->GetBoundingBox( true ) );
1927 }
1928 }
1929
1930 if( !aBoardEdgesOnly )
1931 {
1932 // Check tracks
1933 for( PCB_TRACK* track : m_tracks )
1934 {
1935 if( ( track->GetLayerSet() & visible ).any() )
1936 bbox.Merge( track->GetBoundingBox() );
1937 }
1938
1939 // Check zones
1940 for( ZONE* aZone : m_zones )
1941 {
1942 if( ( aZone->GetLayerSet() & visible ).any() )
1943 bbox.Merge( aZone->GetBoundingBox() );
1944 }
1945
1946 for( PCB_POINT* point : m_points )
1947 {
1948 bbox.Merge( point->GetBoundingBox() );
1949 }
1950 }
1951
1952 return bbox;
1953}
1954
1955
1956void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1957{
1958 int padCount = 0;
1959 int viaCount = 0;
1960 int trackSegmentCount = 0;
1961 std::set<int> netCodes;
1962 int unconnected = GetConnectivity()->GetUnconnectedCount( true );
1963
1964 for( PCB_TRACK* item : m_tracks )
1965 {
1966 if( item->Type() == PCB_VIA_T )
1967 viaCount++;
1968 else
1969 trackSegmentCount++;
1970
1971 if( item->GetNetCode() > 0 )
1972 netCodes.insert( item->GetNetCode() );
1973 }
1974
1975 for( FOOTPRINT* footprint : Footprints() )
1976 {
1977 for( PAD* pad : footprint->Pads() )
1978 {
1979 padCount++;
1980
1981 if( pad->GetNetCode() > 0 )
1982 netCodes.insert( pad->GetNetCode() );
1983 }
1984 }
1985
1986 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%d" ), padCount ) );
1987 aList.emplace_back( _( "Vias" ), wxString::Format( wxT( "%d" ), viaCount ) );
1988 aList.emplace_back( _( "Track Segments" ), wxString::Format( wxT( "%d" ), trackSegmentCount ) );
1989 aList.emplace_back( _( "Nets" ), wxString::Format( wxT( "%d" ), (int) netCodes.size() ) );
1990 aList.emplace_back( _( "Unrouted" ), wxString::Format( wxT( "%d" ), unconnected ) );
1991}
1992
1993
1994INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData,
1995 const std::vector<KICAD_T>& scanTypes )
1996{
1997#if 0 && defined(DEBUG)
1998 std::cout << GetClass().mb_str() << ' ';
1999#endif
2000
2001 bool footprintsScanned = false;
2002 bool drawingsScanned = false;
2003 bool tracksScanned = false;
2004
2005 for( KICAD_T scanType : scanTypes )
2006 {
2007 switch( scanType )
2008 {
2009 case PCB_T:
2010 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
2011 return INSPECT_RESULT::QUIT;
2012
2013 break;
2014
2015 /*
2016 * Instances of the requested KICAD_T live in a list, either one that I manage, or one
2017 * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
2018 * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
2019 */
2020
2021 case PCB_FOOTPRINT_T:
2022 case PCB_PAD_T:
2023 case PCB_SHAPE_T:
2025 case PCB_FIELD_T:
2026 case PCB_TEXT_T:
2027 case PCB_TEXTBOX_T:
2028 case PCB_TABLE_T:
2029 case PCB_TABLECELL_T:
2030 case PCB_DIM_ALIGNED_T:
2031 case PCB_DIM_CENTER_T:
2032 case PCB_DIM_RADIAL_T:
2034 case PCB_DIM_LEADER_T:
2035 case PCB_TARGET_T:
2036 if( !footprintsScanned )
2037 {
2038 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
2040 {
2041 return INSPECT_RESULT::QUIT;
2042 }
2043
2044 footprintsScanned = true;
2045 }
2046
2047 if( !drawingsScanned )
2048 {
2049 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, scanTypes )
2051 {
2052 return INSPECT_RESULT::QUIT;
2053 }
2054
2055 drawingsScanned = true;
2056 }
2057
2058 break;
2059
2060 case PCB_VIA_T:
2061 case PCB_TRACE_T:
2062 case PCB_ARC_T:
2063 if( !tracksScanned )
2064 {
2065 if( IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, scanTypes )
2067 {
2068 return INSPECT_RESULT::QUIT;
2069 }
2070
2071 tracksScanned = true;
2072 }
2073
2074 break;
2075
2076 case PCB_MARKER_T:
2077 for( PCB_MARKER* marker : m_markers )
2078 {
2079 if( marker->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2080 return INSPECT_RESULT::QUIT;
2081 }
2082
2083 break;
2084
2085 case PCB_POINT_T:
2086 for( PCB_POINT* point : m_points )
2087 {
2088 if( point->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2089 return INSPECT_RESULT::QUIT;
2090 }
2091
2092 break;
2093
2094 case PCB_ZONE_T:
2095 if( !footprintsScanned )
2096 {
2097 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
2099 {
2100 return INSPECT_RESULT::QUIT;
2101 }
2102
2103 footprintsScanned = true;
2104 }
2105
2106 for( ZONE* zone : m_zones)
2107 {
2108 if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2109 return INSPECT_RESULT::QUIT;
2110 }
2111
2112 break;
2113
2114 case PCB_GENERATOR_T:
2115 if( !footprintsScanned )
2116 {
2117 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
2119 {
2120 return INSPECT_RESULT::QUIT;
2121 }
2122
2123 footprintsScanned = true;
2124 }
2125
2126 if( IterateForward<PCB_GENERATOR*>( m_generators, inspector, testData, { scanType } )
2128 {
2129 return INSPECT_RESULT::QUIT;
2130 }
2131
2132 break;
2133
2134 case PCB_GROUP_T:
2135 if( IterateForward<PCB_GROUP*>( m_groups, inspector, testData, { scanType } )
2137 {
2138 return INSPECT_RESULT::QUIT;
2139 }
2140
2141 break;
2142
2143 default:
2144 break;
2145 }
2146 }
2147
2149}
2150
2151
2152NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
2153{
2154 // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
2155 // zero is reserved for "no connection" and is not actually a net.
2156 // nullptr is returned for non valid netcodes
2157
2158 if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
2160 else
2161 return m_NetInfo.GetNetItem( aNetcode );
2162}
2163
2164
2165NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
2166{
2167 return m_NetInfo.GetNetItem( aNetname );
2168}
2169
2170
2171int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
2172{
2173 int rv = 0;
2174 int count = 0;
2175
2176 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2177 {
2178 int ch = *it;
2179
2180 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
2181 {
2182 continue;
2183 }
2184 else if( ch == '+' )
2185 {
2186 aComplementNet = wxT( "-" );
2187 rv = 1;
2188 }
2189 else if( ch == '-' )
2190 {
2191 aComplementNet = wxT( "+" );
2192 rv = -1;
2193 }
2194 else if( ch == 'N' )
2195 {
2196 aComplementNet = wxT( "P" );
2197 rv = -1;
2198 }
2199 else if ( ch == 'P' )
2200 {
2201 aComplementNet = wxT( "N" );
2202 rv = 1;
2203 }
2204 else
2205 {
2206 break;
2207 }
2208 }
2209
2210 if( rv != 0 && count >= 1 )
2211 {
2212 aComplementNet = aNetName.Left( aNetName.length() - count )
2213 + aComplementNet
2214 + aNetName.Right( count - 1 );
2215 }
2216
2217 return rv;
2218}
2219
2220
2222{
2223 if( aNet )
2224 {
2225 wxString refName = aNet->GetNetname();
2226 wxString coupledNetName;
2227
2228 if( MatchDpSuffix( refName, coupledNetName ) )
2229 return FindNet( coupledNetName );
2230 }
2231
2232 return nullptr;
2233}
2234
2235
2236FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
2237{
2238 for( FOOTPRINT* footprint : m_footprints )
2239 {
2240 if( aReference == footprint->GetReference() )
2241 return footprint;
2242 }
2243
2244 return nullptr;
2245}
2246
2247
2249{
2250 for( FOOTPRINT* footprint : m_footprints )
2251 {
2252 if( footprint->GetPath() == aPath )
2253 return footprint;
2254 }
2255
2256 return nullptr;
2257}
2258
2259
2261{
2262 std::set<wxString> names;
2263
2264 for( const NETINFO_ITEM* net : m_NetInfo )
2265 {
2266 if( !net->GetNetname().IsEmpty() )
2267 names.insert( net->GetNetname() );
2268 }
2269
2270 return names;
2271}
2272
2273
2275{
2276 if( m_project && !m_project->IsNullProject() )
2277 SetProperties( m_project->GetTextVars() );
2278}
2279
2280
2282{
2283 m_lengthDelayCalc->SynchronizeTimeDomainProperties();
2284}
2285
2286
2287void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
2288{
2289 if( !m_project )
2290 return;
2291
2293 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass();
2294
2296
2297 for( NETINFO_ITEM* net : m_NetInfo )
2298 net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) );
2299
2300 if( aResetTrackAndViaSizes )
2301 {
2302 // Set initial values for custom track width & via size to match the default
2303 // netclass settings
2304 bds.UseCustomTrackViaSize( false );
2305 bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
2306 bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
2307 bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
2308 bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
2309 bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
2310 bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
2311 }
2312
2314}
2315
2316
2317bool BOARD::SynchronizeComponentClasses( const std::unordered_set<wxString>& aNewSheetPaths ) const
2318{
2319 std::shared_ptr<COMPONENT_CLASS_SETTINGS> settings =
2321
2322 return m_componentClassManager->SyncDynamicComponentClassAssignments(
2323 settings->GetComponentClassAssignments(), settings->GetEnableSheetComponentClasses(),
2324 aNewSheetPaths );
2325}
2326
2327
2329{
2330 int error_count = 0;
2331
2332 for( ZONE* zone : Zones() )
2333 {
2334 if( !zone->IsOnCopperLayer() )
2335 {
2336 zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
2337 continue;
2338 }
2339
2340 if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
2341 {
2342 const NETINFO_ITEM* net = zone->GetNet();
2343
2344 if( net )
2345 {
2346 zone->SetNetCode( net->GetNetCode() );
2347 }
2348 else
2349 {
2350 error_count++;
2351
2352 // keep Net Name and set m_NetCode to -1 : error flag.
2353 zone->SetNetCode( -1 );
2354 }
2355 }
2356 }
2357
2358 return error_count;
2359}
2360
2361
2362PAD* BOARD::GetPad( const VECTOR2I& aPosition, const LSET& aLayerSet ) const
2363{
2364 for( FOOTPRINT* footprint : m_footprints )
2365 {
2366 PAD* pad = nullptr;
2367
2368 if( footprint->HitTest( aPosition ) )
2369 pad = footprint->GetPad( aPosition, aLayerSet.any() ? aLayerSet : LSET::AllCuMask() );
2370
2371 if( pad )
2372 return pad;
2373 }
2374
2375 return nullptr;
2376}
2377
2378
2379PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
2380{
2381 const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
2382
2383 LSET lset( { aTrace->GetLayer() } );
2384
2385 return GetPad( aPosition, lset );
2386}
2387
2388
2389PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, const LSET& aLayerSet ) const
2390{
2391 // Search aPadList for aPosition
2392 // aPadList is sorted by X then Y values, and a fast binary search is used
2393 int idxmax = aPadList.size() - 1;
2394
2395 int delta = aPadList.size();
2396
2397 int idx = 0; // Starting index is the beginning of list
2398
2399 while( delta )
2400 {
2401 // Calculate half size of remaining interval to test.
2402 // Ensure the computed value is not truncated (too small)
2403 if( (delta & 1) && ( delta > 1 ) )
2404 delta++;
2405
2406 delta /= 2;
2407
2408 PAD* pad = aPadList[idx];
2409
2410 if( pad->GetPosition() == aPosition ) // candidate found
2411 {
2412 // The pad must match the layer mask:
2413 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2414 return pad;
2415
2416 // More than one pad can be at aPosition
2417 // search for a pad at aPosition that matched this mask
2418
2419 // search next
2420 for( int ii = idx+1; ii <= idxmax; ii++ )
2421 {
2422 pad = aPadList[ii];
2423
2424 if( pad->GetPosition() != aPosition )
2425 break;
2426
2427 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2428 return pad;
2429 }
2430 // search previous
2431 for( int ii = idx - 1 ;ii >=0; ii-- )
2432 {
2433 pad = aPadList[ii];
2434
2435 if( pad->GetPosition() != aPosition )
2436 break;
2437
2438 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2439 return pad;
2440 }
2441
2442 // Not found:
2443 return nullptr;
2444 }
2445
2446 if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
2447 {
2448 if( pad->GetPosition().y < aPosition.y ) // Must search after this item
2449 {
2450 idx += delta;
2451
2452 if( idx > idxmax )
2453 idx = idxmax;
2454 }
2455 else // Must search before this item
2456 {
2457 idx -= delta;
2458
2459 if( idx < 0 )
2460 idx = 0;
2461 }
2462 }
2463 else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
2464 {
2465 idx += delta;
2466
2467 if( idx > idxmax )
2468 idx = idxmax;
2469 }
2470 else // Must search before this item
2471 {
2472 idx -= delta;
2473
2474 if( idx < 0 )
2475 idx = 0;
2476 }
2477 }
2478
2479 return nullptr;
2480}
2481
2482
2488bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH )
2489{
2490 if( aLH->GetPosition().x == aRH->GetPosition().x )
2491 return aLH->GetPosition().y < aRH->GetPosition().y;
2492
2493 return aLH->GetPosition().x < aRH->GetPosition().x;
2494}
2495
2496
2497void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
2498{
2499 for( FOOTPRINT* footprint : Footprints() )
2500 {
2501 for( PAD* pad : footprint->Pads( ) )
2502 {
2503 if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
2504 aVector.push_back( pad );
2505 }
2506 }
2507
2508 std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
2509}
2510
2511
2513{
2514 if( GetDesignSettings().m_HasStackup )
2516
2517 BOARD_STACKUP stackup;
2519 return stackup;
2520}
2521
2522
2523std::tuple<int, double, double, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
2524{
2525 std::shared_ptr<CONNECTIVITY_DATA> connectivity = GetBoard()->GetConnectivity();
2526 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items;
2527
2528 for( BOARD_CONNECTED_ITEM* boardItem : connectivity->GetConnectedItems( &aTrack, EXCLUDE_ZONES ) )
2529 {
2531
2532 if( item.Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
2533 items.push_back( std::move( item ) );
2534 }
2535
2536 constexpr PATH_OPTIMISATIONS opts = {
2537 .OptimiseViaLayers = true, .MergeTracks = true, .OptimiseTracesInPads = true, .InferViaInPad = false
2538 };
2540 items, opts, nullptr, nullptr, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
2542
2543 return std::make_tuple( items.size(), details.TrackLength + details.ViaLength, details.PadToDieLength,
2544 details.TrackDelay + details.ViaDelay, details.PadToDieDelay );
2545}
2546
2547
2548FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer,
2549 bool aVisibleOnly, bool aIgnoreLocked ) const
2550{
2551 FOOTPRINT* footprint = nullptr;
2552 FOOTPRINT* alt_footprint = nullptr;
2553 int min_dim = 0x7FFFFFFF;
2554 int alt_min_dim = 0x7FFFFFFF;
2555 bool current_layer_back = IsBackLayer( aActiveLayer );
2556
2557 for( FOOTPRINT* candidate : m_footprints )
2558 {
2559 // is the ref point within the footprint's bounds?
2560 if( !candidate->HitTest( aPosition ) )
2561 continue;
2562
2563 // if caller wants to ignore locked footprints, and this one is locked, skip it.
2564 if( aIgnoreLocked && candidate->IsLocked() )
2565 continue;
2566
2567 PCB_LAYER_ID layer = candidate->GetLayer();
2568
2569 // Filter non visible footprints if requested
2570 if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
2571 {
2572 BOX2I bb = candidate->GetBoundingBox( false );
2573
2574 int offx = bb.GetX() + bb.GetWidth() / 2;
2575 int offy = bb.GetY() + bb.GetHeight() / 2;
2576
2577 // off x & offy point to the middle of the box.
2578 int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2579 ( aPosition.y - offy ) * ( aPosition.y - offy );
2580
2581 if( current_layer_back == IsBackLayer( layer ) )
2582 {
2583 if( dist <= min_dim )
2584 {
2585 // better footprint shown on the active side
2586 footprint = candidate;
2587 min_dim = dist;
2588 }
2589 }
2590 else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
2591 {
2592 if( dist <= alt_min_dim )
2593 {
2594 // better footprint shown on the other side
2595 alt_footprint = candidate;
2596 alt_min_dim = dist;
2597 }
2598 }
2599 }
2600 }
2601
2602 if( footprint )
2603 return footprint;
2604
2605 if( alt_footprint)
2606 return alt_footprint;
2607
2608 return nullptr;
2609}
2610
2611
2612std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
2613{
2614 std::list<ZONE*> zones;
2615
2616 for( ZONE* zone : Zones() )
2617 zones.push_back( zone );
2618
2619 if( aIncludeZonesInFootprints )
2620 {
2621 for( FOOTPRINT* footprint : m_footprints )
2622 {
2623 for( ZONE* zone : footprint->Zones() )
2624 zones.push_back( zone );
2625 }
2626 }
2627
2628 return zones;
2629}
2630
2631
2632ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer,
2633 VECTOR2I aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch )
2634{
2635 ZONE* new_area = new ZONE( this );
2636
2637 new_area->SetNetCode( aNetcode );
2638 new_area->SetLayer( aLayer );
2639
2640 m_zones.push_back( new_area );
2641
2642 new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
2643
2644 // Add the first corner to the new zone
2645 new_area->AppendCorner( aStartPointPosition, -1 );
2646
2647 if( aNewZonesList )
2648 {
2649 ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
2650 aNewZonesList->PushItem( picker );
2651 }
2652
2653 return new_area;
2654}
2655
2656
2658 OUTLINE_ERROR_HANDLER* aErrorHandler,
2659 bool aAllowUseArcsInPolygons,
2660 bool aIncludeNPTHAsOutlines )
2661{
2662 // max dist from one endPt to next startPt: use the current value
2663 int chainingEpsilon = GetOutlinesChainingEpsilon();
2664
2665 bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
2666 chainingEpsilon, aErrorHandler,
2667 aAllowUseArcsInPolygons );
2668
2669 // Now add NPTH oval holes as holes in outlines if required
2670 if( aIncludeNPTHAsOutlines )
2671 {
2672 for( FOOTPRINT* fp : Footprints() )
2673 {
2674 for( PAD* pad : fp->Pads() )
2675 {
2676 if( pad->GetAttribute () != PAD_ATTRIB::NPTH )
2677 continue;
2678
2679 SHAPE_POLY_SET hole;
2680 pad->TransformHoleToPolygon( hole, 0, pad->GetMaxError(), ERROR_INSIDE );
2681
2682 if( hole.OutlineCount() > 0 ) // can be not the case for malformed NPTH holes
2683 {
2684 // Add this pad hole to the main outline
2685 // But we can have more than one main outline (i.e. more than one board), so
2686 // search the right main outline i.e. the outline that contains the pad hole
2687 SHAPE_LINE_CHAIN& pad_hole = hole.Outline( 0 );
2688 const VECTOR2I holePt = pad_hole.CPoint( 0 );
2689
2690 for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj )
2691 {
2692 if( aOutlines.Outline( jj ).PointInside( holePt ) )
2693 {
2694 aOutlines.AddHole( pad_hole, jj );
2695 break;
2696 }
2697 }
2698 }
2699 }
2700 }
2701 }
2702
2703 // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2704 aOutlines.Simplify();
2705
2706 return success;
2707}
2708
2709
2711{
2713 return static_cast<EMBEDDED_FILES*>( m_embeddedFilesDelegate );
2714
2715 return static_cast<EMBEDDED_FILES*>( this );
2716}
2717
2718
2720{
2722 return static_cast<const EMBEDDED_FILES*>( m_embeddedFilesDelegate );
2723
2724 return static_cast<const EMBEDDED_FILES*>( this );
2725}
2726
2727
2728std::set<KIFONT::OUTLINE_FONT*> BOARD::GetFonts() const
2729{
2731
2732 std::set<KIFONT::OUTLINE_FONT*> fonts;
2733
2734 for( BOARD_ITEM* item : Drawings() )
2735 {
2736 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
2737 {
2738 KIFONT::FONT* font = text->GetFont();
2739
2740 if( font && font->IsOutline() )
2741 {
2742 KIFONT::OUTLINE_FONT* outlineFont = static_cast<KIFONT::OUTLINE_FONT*>( font );
2743 PERMISSION permission = outlineFont->GetEmbeddingPermission();
2744
2745 if( permission == PERMISSION::EDITABLE || permission == PERMISSION::INSTALLABLE )
2746 fonts.insert( outlineFont );
2747 }
2748 }
2749 }
2750
2751 return fonts;
2752}
2753
2754
2756{
2757 for( KIFONT::OUTLINE_FONT* font : GetFonts() )
2758 {
2759 EMBEDDED_FILES::EMBEDDED_FILE* file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
2761 }
2762}
2763
2764
2765const std::vector<PAD*> BOARD::GetPads() const
2766{
2767 std::vector<PAD*> allPads;
2768
2769 for( FOOTPRINT* footprint : Footprints() )
2770 {
2771 for( PAD* pad : footprint->Pads() )
2772 allPads.push_back( pad );
2773 }
2774
2775 return allPads;
2776}
2777
2778
2779const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
2780{
2781 std::vector<BOARD_CONNECTED_ITEM*> items;
2782
2783 for( PCB_TRACK* track : Tracks() )
2784 items.push_back( track );
2785
2786 for( FOOTPRINT* footprint : Footprints() )
2787 {
2788 for( PAD* pad : footprint->Pads() )
2789 items.push_back( pad );
2790 }
2791
2792 for( ZONE* zone : Zones() )
2793 items.push_back( zone );
2794
2795 for( BOARD_ITEM* item : Drawings() )
2796 {
2797 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2798 items.push_back( bci );
2799 }
2800
2801 return items;
2802}
2803
2804
2805void BOARD::MapNets( BOARD* aDestBoard )
2806{
2808 {
2809 NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
2810
2811 if( netInfo )
2812 item->SetNet( netInfo );
2813 else
2814 {
2815 NETINFO_ITEM* newNet = new NETINFO_ITEM( aDestBoard, item->GetNetname() );
2816 aDestBoard->Add( newNet );
2817 item->SetNet( newNet );
2818
2819 }
2820 }
2821}
2822
2823
2825{
2826 for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
2827 {
2828 if( FindNet( item->GetNetCode() ) == nullptr )
2829 item->SetNetCode( NETINFO_LIST::ORPHANED );
2830 }
2831}
2832
2833
2835{
2836 if( !alg::contains( m_listeners, aListener ) )
2837 m_listeners.push_back( aListener );
2838}
2839
2840
2842{
2843 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
2844
2845 if( i != m_listeners.end() )
2846 {
2847 std::iter_swap( i, m_listeners.end() - 1 );
2848 m_listeners.pop_back();
2849 }
2850}
2851
2852
2854{
2855 m_listeners.clear();
2856}
2857
2858
2863
2864
2865void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
2866{
2868}
2869
2870
2871void BOARD::OnItemsCompositeUpdate( std::vector<BOARD_ITEM*>& aAddedItems,
2872 std::vector<BOARD_ITEM*>& aRemovedItems,
2873 std::vector<BOARD_ITEM*>& aChangedItems )
2874{
2875 InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems,
2876 aChangedItems );
2877}
2878
2879
2884
2885
2893
2894
2895void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
2896{
2897 if( !m_highLight.m_netCodes.count( aNetCode ) )
2898 {
2899 if( !aMulti )
2900 m_highLight.m_netCodes.clear();
2901
2902 m_highLight.m_netCodes.insert( aNetCode );
2904 }
2905}
2906
2907
2908void BOARD::HighLightON( bool aValue )
2909{
2910 if( m_highLight.m_highLightOn != aValue )
2911 {
2912 m_highLight.m_highLightOn = aValue;
2914 }
2915}
2916
2917
2918wxString BOARD::GroupsSanityCheck( bool repair )
2919{
2920 if( repair )
2921 {
2922 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
2923 {};
2924
2925 return wxEmptyString;
2926 }
2927 return GroupsSanityCheckInternal( repair );
2928}
2929
2930
2932{
2933 // Cycle detection
2934 //
2935 // Each group has at most one parent group.
2936 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
2937 // If we ever see a group that we've already marked, that's a cycle.
2938 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
2939 //
2940 // Algorithm below is linear in the # of groups because each group is visited only once.
2941 // There may be extra time taken due to the container access calls and iterators.
2942 //
2943 // Groups we know are cycle free
2944 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
2945 // Groups in the current chain we're exploring.
2946 std::unordered_set<EDA_GROUP*> currentChainGroups;
2947 // Groups we haven't checked yet.
2948 std::unordered_set<EDA_GROUP*> toCheckGroups;
2949
2950 // Initialize set of groups and generators to check that could participate in a cycle.
2951 for( PCB_GROUP* group : Groups() )
2952 toCheckGroups.insert( group );
2953
2954 for( PCB_GENERATOR* gen : Generators() )
2955 toCheckGroups.insert( gen );
2956
2957 while( !toCheckGroups.empty() )
2958 {
2959 currentChainGroups.clear();
2960 EDA_GROUP* group = *toCheckGroups.begin();
2961
2962 while( true )
2963 {
2964 if( currentChainGroups.find( group ) != currentChainGroups.end() )
2965 {
2966 if( repair )
2967 Remove( static_cast<BOARD_ITEM*>( group->AsEdaItem() ) );
2968
2969 return "Cycle detected in group membership";
2970 }
2971 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
2972 {
2973 // Parent is a group we know does not lead to a cycle
2974 break;
2975 }
2976
2977 currentChainGroups.insert( group );
2978 // We haven't visited currIdx yet, so it must be in toCheckGroups
2979 toCheckGroups.erase( group );
2980
2981 group = group->AsEdaItem()->GetParentGroup();
2982
2983 if( !group )
2984 {
2985 // end of chain and no cycles found in this chain
2986 break;
2987 }
2988 }
2989
2990 // No cycles found in chain, so add it to set of groups we know don't participate
2991 // in a cycle.
2992 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
2993 }
2994
2995 // Success
2996 return "";
2997}
2998
2999
3001{
3002 if( a->Type() != b->Type() )
3003 return a->Type() < b->Type();
3004
3005 if( a->GetLayer() != b->GetLayer() )
3006 return a->GetLayer() < b->GetLayer();
3007
3008 if( a->GetPosition().x != b->GetPosition().x )
3009 return a->GetPosition().x < b->GetPosition().x;
3010
3011 if( a->GetPosition().y != b->GetPosition().y )
3012 return a->GetPosition().y < b->GetPosition().y;
3013
3014 if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards
3015 return a->m_Uuid < b->m_Uuid;
3016
3017 return a < b;
3018}
3019
3020
3022 const BOARD_ITEM* aSecond ) const
3023{
3024 if( aFirst->Type() != aSecond->Type() )
3025 return aFirst->Type() < aSecond->Type();
3026
3027 if( aFirst->GetLayer() != aSecond->GetLayer() )
3028 return aFirst->GetLayer() < aSecond->GetLayer();
3029
3030 if( aFirst->Type() == PCB_SHAPE_T )
3031 {
3032 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aFirst );
3033 const PCB_SHAPE* other = static_cast<const PCB_SHAPE*>( aSecond );
3034 return shape->Compare( other );
3035 }
3036 else if( aFirst->Type() == PCB_TEXT_T || aFirst->Type() == PCB_FIELD_T )
3037 {
3038 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aFirst );
3039 const PCB_TEXT* other = static_cast<const PCB_TEXT*>( aSecond );
3040 return text->Compare( other );
3041 }
3042 else if( aFirst->Type() == PCB_TEXTBOX_T )
3043 {
3044 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aFirst );
3045 const PCB_TEXTBOX* other = static_cast<const PCB_TEXTBOX*>( aSecond );
3046
3047 return textbox->PCB_SHAPE::Compare( other ) && textbox->EDA_TEXT::Compare( other );
3048 }
3049 else if( aFirst->Type() == PCB_TABLE_T )
3050 {
3051 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aFirst );
3052 const PCB_TABLE* other = static_cast<const PCB_TABLE*>( aSecond );
3053
3054 return PCB_TABLE::Compare( table, other );
3055 }
3056
3057 return aFirst->m_Uuid < aSecond->m_Uuid;
3058}
3059
3060
3062 SHAPE_POLY_SET& aOutlines ) const
3063{
3064 int maxError = GetDesignSettings().m_MaxError;
3065
3066 // convert tracks and vias:
3067 for( const PCB_TRACK* track : m_tracks )
3068 {
3069 if( !track->IsOnLayer( aLayer ) )
3070 continue;
3071
3072 track->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3073 }
3074
3075 // convert pads and other copper items in footprints
3076 for( const FOOTPRINT* footprint : m_footprints )
3077 {
3078 footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3079
3080 footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE,
3081 true, /* include text */
3082 true, /* include shapes */
3083 false /* include private items */ );
3084
3085 for( const ZONE* zone : footprint->Zones() )
3086 {
3087 if( zone->GetLayerSet().test( aLayer ) )
3088 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
3089 }
3090 }
3091
3092 // convert copper zones
3093 for( const ZONE* zone : Zones() )
3094 {
3095 if( zone->GetLayerSet().test( aLayer ) )
3096 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
3097 }
3098
3099 // convert graphic items on copper layers (texts)
3100 for( const BOARD_ITEM* item : m_drawings )
3101 {
3102 if( !item->IsOnLayer( aLayer ) )
3103 continue;
3104
3105 switch( item->Type() )
3106 {
3107 case PCB_SHAPE_T:
3108 {
3109 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
3110 shape->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3111 break;
3112 }
3113
3114 case PCB_FIELD_T:
3115 case PCB_TEXT_T:
3116 {
3117 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
3118 text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3119 break;
3120 }
3121
3122 case PCB_TEXTBOX_T:
3123 {
3124 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
3125
3126 // border
3127 textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError,
3128 ERROR_INSIDE );
3129 // text
3130 textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3131 break;
3132 }
3133
3134 case PCB_TABLE_T:
3135 {
3136 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
3137
3138 table->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3139 break;
3140 }
3141
3142 case PCB_DIM_ALIGNED_T:
3143 case PCB_DIM_CENTER_T:
3144 case PCB_DIM_RADIAL_T:
3146 case PCB_DIM_LEADER_T:
3147 {
3148 const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
3149
3150 dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3151 dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3152 break;
3153 }
3154
3155 default:
3156 break;
3157 }
3158 }
3159}
3160
3161
3163{
3164 BOARD_ITEM_SET items;
3165
3166 std::copy( m_tracks.begin(), m_tracks.end(), std::inserter( items, items.end() ) );
3167 std::copy( m_zones.begin(), m_zones.end(), std::inserter( items, items.end() ) );
3168 std::copy( m_footprints.begin(), m_footprints.end(), std::inserter( items, items.end() ) );
3169 std::copy( m_drawings.begin(), m_drawings.end(), std::inserter( items, items.end() ) );
3170 std::copy( m_markers.begin(), m_markers.end(), std::inserter( items, items.end() ) );
3171 std::copy( m_groups.begin(), m_groups.end(), std::inserter( items, items.end() ) );
3172 std::copy( m_points.begin(), m_points.end(), std::inserter( items, items.end() ) );
3173
3174 return items;
3175}
3176
3177
3178bool BOARD::operator==( const BOARD_ITEM& aItem ) const
3179{
3180 if( aItem.Type() != Type() )
3181 return false;
3182
3183 const BOARD& other = static_cast<const BOARD&>( aItem );
3184
3185 if( *m_designSettings != *other.m_designSettings )
3186 return false;
3187
3188 if( m_NetInfo.GetNetCount() != other.m_NetInfo.GetNetCount() )
3189 return false;
3190
3191 const NETNAMES_MAP& thisNetNames = m_NetInfo.NetsByName();
3192 const NETNAMES_MAP& otherNetNames = other.m_NetInfo.NetsByName();
3193
3194 for( auto it1 = thisNetNames.begin(), it2 = otherNetNames.begin();
3195 it1 != thisNetNames.end() && it2 != otherNetNames.end(); ++it1, ++it2 )
3196 {
3197 // We only compare the names in order here, not the index values
3198 // as the index values are auto-generated and the names are not.
3199 if( it1->first != it2->first )
3200 return false;
3201 }
3202
3203 if( m_properties.size() != other.m_properties.size() )
3204 return false;
3205
3206 for( auto it1 = m_properties.begin(), it2 = other.m_properties.begin();
3207 it1 != m_properties.end() && it2 != other.m_properties.end(); ++it1, ++it2 )
3208 {
3209 if( *it1 != *it2 )
3210 return false;
3211 }
3212
3213 if( m_paper.GetCustomHeightMils() != other.m_paper.GetCustomHeightMils() )
3214 return false;
3215
3216 if( m_paper.GetCustomWidthMils() != other.m_paper.GetCustomWidthMils() )
3217 return false;
3218
3219 if( m_paper.GetSizeMils() != other.m_paper.GetSizeMils() )
3220 return false;
3221
3222 if( m_paper.GetPaperId() != other.m_paper.GetPaperId() )
3223 return false;
3224
3225 if( m_paper.GetWxOrientation() != other.m_paper.GetWxOrientation() )
3226 return false;
3227
3228 for( int ii = 0; !m_titles.GetComment( ii ).empty(); ++ii )
3229 {
3230 if( m_titles.GetComment( ii ) != other.m_titles.GetComment( ii ) )
3231 return false;
3232 }
3233
3234 wxArrayString ourVars;
3235 m_titles.GetContextualTextVars( &ourVars );
3236
3237 wxArrayString otherVars;
3238 other.m_titles.GetContextualTextVars( &otherVars );
3239
3240 if( ourVars != otherVars )
3241 return false;
3242
3243 return true;
3244}
3245
3247{
3248 m_boardOutline->GetOutline().RemoveAllContours();
3249
3250 bool has_outline = GetBoardPolygonOutlines( m_boardOutline->GetOutline() );
3251
3252 if( has_outline )
3253 m_boardOutline->GetOutline().Fracture();
3254}
3255
3256
3258{
3259 // return the number of PTH with Press-Fit fabr attribute
3260 int count = 0;
3261
3262 for( FOOTPRINT* footprint : Footprints() )
3263 {
3264 for( PAD* pad : footprint->Pads() )
3265 {
3266 if( pad->GetProperty() == PAD_PROP::PRESSFIT )
3267 count++;
3268 }
3269 }
3270
3271 return count;
3272}
3273
3274
3276{
3277 // @return the number of PTH with Castellated fabr attribute
3278 int count = 0;
3279
3280 for( FOOTPRINT* footprint : Footprints() )
3281 {
3282 for( PAD* pad : footprint->Pads() )
3283 {
3284 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
3285 count++;
3286 }
3287 }
3288
3289 return count;
3290}
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
bool sortPadsByXthenYCoord(PAD *const &aLH, PAD *const &aRH)
Used by #GetSortedPadListByXCoord to sort a pad list by X coordinate value.
Definition board.cpp:2488
std::set< wxString >::iterator FindByFirstNFields(std::set< wxString > &strSet, const wxString &searchStr, char delimiter, int n)
Definition board.cpp:359
#define DEFAULT_CHAINING_EPSILON_MM
Definition board.h:82
BOARD_USE
Flags to specify how the board is being used.
Definition board.h:307
@ NORMAL
Definition board.h:308
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition board.h:180
@ LT_POWER
Definition board.h:183
@ LT_FRONT
Definition board.h:187
@ LT_MIXED
Definition board.h:184
@ LT_BACK
Definition board.h:188
@ LT_UNDEFINED
Definition board.h:181
@ LT_JUMPER
Definition board.h:185
@ LT_AUX
Definition board.h:186
@ LT_SIGNAL
Definition board.h:182
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
Definition board.h:301
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
BASE_SET & set(size_t pos)
Definition base_set.h:116
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.
void SetEnabledLayers(const LSET &aMask)
Change the bit-mask of enabled layers to aMask.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetCustomTrackWidth(int aWidth)
Sets custom width for track (i.e.
void SetCustomViaSize(int aSize)
Set custom size for via diameter (i.e.
const LSET & GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
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.
void SetUserDefinedLayerCount(int aNewLayerCount)
Set the number of user defined layers to aNewLayerCount.
BOARD_STACKUP & GetStackupDescriptor()
void SetCustomViaDrill(int aDrill)
Sets custom size for via drill (i.e.
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
BOARD_ITEM_CONTAINER(BOARD_ITEM *aParent, KICAD_T aType)
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:81
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition board_item.h:339
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
static VECTOR2I ZeroOffset
A value of wxPoint(0,0) which can be passed to the Draw() functions.
Definition board_item.h:181
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
virtual void OnBoardNetSettingsChanged(BOARD &aBoard)
Definition board.h:286
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition board.h:283
virtual void OnBoardRatsnestChanged(BOARD &aBoard)
Definition board.h:290
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition board.h:288
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:287
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:284
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:282
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition board.h:289
virtual void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems)
Definition board.h:291
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition board.h:285
Manage layers needed to make a physical board.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
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:1994
ZONE * m_SolderMaskBridges
Definition board.h:1384
void GetContextualTextVars(wxArrayString *aVars) const
Definition board.cpp:476
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:1028
BOARD_STACKUP GetStackupOrDefault() const
Definition board.cpp:2512
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaCache
Definition board.h:1372
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition board.h:1385
PCB_LAYER_ID GetCopperLayerStackMaxId() const
Definition board.cpp:898
GENERATORS m_generators
Definition board.h:1423
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:2657
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:2859
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:406
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition board.h:347
PAD * GetPad(const VECTOR2I &aPosition, const LSET &aLayerMask) const
Find a pad aPosition on aLayer.
Definition board.cpp:2362
int GetUserDefinedLayerCount() const
Definition board.cpp:887
void recalcOpposites()
Definition board.cpp:807
void SetPosition(const VECTOR2I &aPos) override
Definition board.cpp:571
std::map< wxString, wxString > m_properties
Definition board.h:1438
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition board.cpp:2710
int m_fileFormatVersionAtLoad
Definition board.h:1435
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition board.cpp:2221
std::vector< ZONE * > m_DRCCopperZones
Definition board.h:1381
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition board.cpp:955
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1163
void MapNets(BOARD *aDestBoard)
Map all nets in the given board to nets with the same name (if any) in the destination board.
Definition board.cpp:2805
TITLE_BLOCK m_titles
Definition board.h:1442
GAL_SET m_LegacyVisibleItems
Definition board.h:403
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1339
void RunOnNestedEmbeddedFiles(const std::function< void(EMBEDDED_FILES *)> &aFunction) override
Provide access to nested embedded files, such as symbols in schematics and footprints in boards.
Definition board.cpp:1135
const GENERATORS & Generators() const
Definition board.h:364
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition board.h:838
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition board.cpp:2779
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition board.cpp:989
int m_outlinesChainingEpsilon
the max distance between 2 end point to see them connected when building the board outlines
Definition board.h:1408
std::tuple< int, double, double, 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:2523
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition board.cpp:2260
BOARD_USE m_boardUse
What is this board being used for.
Definition board.h:1411
PAGE_INFO m_paper
Definition board.h:1441
void RemoveAllListeners()
Remove all listeners.
Definition board.cpp:2853
FOOTPRINTS m_footprints
Definition board.h:1419
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:1457
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:2834
void UpdateUserUnits(BOARD_ITEM *aItem, KIGFX::VIEW *aView)
Update any references within aItem (or its descendants) to the user units.
Definition board.cpp:1534
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition board.h:396
bool IsBackLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:740
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition board.cpp:983
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition board.cpp:2895
HIGH_LIGHT_INFO m_highLight
Definition board.h:1432
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition board.cpp:663
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition board.cpp:2152
EDA_UNITS m_userUnits
Definition board.h:1445
void UpdateBoardOutline()
Definition board.cpp:3246
const ZONES & Zones() const
Definition board.h:362
void BulkRemoveStaleTeardrops(BOARD_COMMIT &aCommit)
Remove all teardrop zones with the STRUCT_DELETED flag set.
Definition board.cpp:1314
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition board.h:1395
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aSettings)
Definition board.cpp:1046
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:937
void SanitizeNetcodes()
Definition board.cpp:2824
EMBEDDED_FILES * m_embeddedFilesDelegate
Definition board.h:1473
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:2632
bool IsFrontLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:734
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition board.h:391
~BOARD()
Definition board.cpp:153
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:188
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:949
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition board.cpp:746
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition board.cpp:331
DRAWINGS m_drawings
Definition board.h:1418
void OnItemsCompositeUpdate(std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems)
Notify the board and its listeners that items on the board have been modified in a composite operatio...
Definition board.cpp:2871
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition board.cpp:2328
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:2287
void SynchronizeTimeDomainProperties()
Ensure that all time domain properties providers are in sync with current settings.
Definition board.cpp:2281
void ResetNetHighLight()
Reset all high light data to the init state.
Definition board.cpp:2886
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition board.cpp:709
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition board.cpp:2612
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:3061
bool ResolveTextVar(wxString *token, int aDepth) const
Definition board.cpp:502
const MARKERS & Markers() const
Definition board.h:370
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:868
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition board.cpp:2765
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition board.cpp:577
TITLE_BLOCK & GetTitleBlock()
Definition board.h:747
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition board.cpp:1890
void FixupEmbeddedData()
After loading a file from disk, the footprints do not yet contain the full data for their embedded fi...
Definition board.cpp:1142
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition board.cpp:1052
ZONES m_zones
Definition board.h:1422
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition board.cpp:671
HIGH_LIGHT_INFO m_highLightPrevious
Definition board.h:1433
NETINFO_LIST m_NetInfo
Definition board.h:1465
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:402
void SetVisibleAlls()
Change the bit-mask of visible element categories and layers.
Definition board.cpp:972
int GetCopperLayerCount() const
Definition board.cpp:875
int m_timeStamp
Definition board.h:1412
std::vector< BOARD_LISTENER * > m_listeners
Definition board.h:1467
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsCourtyardCache
Definition board.h:1368
void IncrementTimeStamp()
Definition board.cpp:256
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition board.cpp:2171
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsFCourtyardCache
Definition board.h:1369
PCB_POINTS m_points
Definition board.h:1425
std::unique_ptr< LENGTH_DELAY_CALCULATION > m_lengthDelayCalc
Definition board.h:1476
const FOOTPRINTS & Footprints() const
Definition board.h:358
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition board.h:1439
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
Get the list of all outline fonts used in the board.
Definition board.cpp:2728
void RemoveAll(std::initializer_list< KICAD_T > aTypes={ PCB_NETINFO_T, PCB_MARKER_T, PCB_GROUP_T, PCB_ZONE_T, PCB_GENERATOR_T, PCB_FOOTPRINT_T, PCB_TRACE_T, PCB_SHAPE_T })
An efficient way to remove all items of a certain type from the board.
Definition board.cpp:1443
const BOARD_ITEM_SET GetItemSet()
Definition board.cpp:3162
const TRACKS & Tracks() const
Definition board.h:356
int m_DRCMaxPhysicalClearance
Definition board.h:1383
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition board.cpp:2248
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:1308
std::unordered_map< wxString, LSET > m_LayerExpressionCache
Definition board.h:1373
bool m_embedFonts
Definition board.h:1469
wxString GroupsSanityCheckInternal(bool repair)
Definition board.cpp:2931
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition board.cpp:2880
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition board.cpp:1771
wxString GetClass() const override
Return the class name.
Definition board.h:1079
std::unique_ptr< COMPONENT_CLASS_MANAGER > m_componentClassManager
Definition board.h:1475
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition board.h:410
void SetCopperLayerCount(int aCount)
Definition board.cpp:881
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1376
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsBCourtyardCache
Definition board.h:1370
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition board.cpp:641
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:198
PROJECT * m_project
Definition board.h:1444
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:2548
const wxString & GetFileName() const
Definition board.h:354
bool operator==(const BOARD_ITEM &aOther) const override
Definition board.cpp:3178
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition board.cpp:388
int GetPadWithCastellatedAttrCount()
Definition board.cpp:3275
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition board.cpp:2236
unsigned GetNodesCount(int aNet=-1) const
Definition board.cpp:1873
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition board.cpp:1729
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition board.cpp:995
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition board.h:1375
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition board.cpp:765
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:691
void DetachAllFootprints()
Remove all footprints without deleting.
Definition board.cpp:1603
std::map< int, LAYER > m_layers
Definition board.h:1430
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition board.cpp:599
int GetOutlinesChainingEpsilon()
Definition board.h:791
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:2497
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:929
int m_DRCMaxClearance
Definition board.h:1382
void ClearProject()
Definition board.cpp:236
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition board.h:1374
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:1302
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition board.cpp:911
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition board.cpp:1593
PROJECT * GetProject() const
Definition board.h:537
bool IsEmpty() const
Definition board.cpp:559
int GetPadWithPressFitAttrCount()
Definition board.cpp:3257
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:1956
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition board.cpp:2918
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1040
std::vector< ZONE * > m_DRCZones
Definition board.h:1380
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:923
BOARD()
Definition board.cpp:80
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition board.cpp:300
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition board.cpp:1825
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2274
std::unordered_map< KIID, BOARD_ITEM * > m_itemByIdCache
Definition board.h:1428
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition board.cpp:2841
std::shared_mutex m_CachesMutex
Definition board.h:1367
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:2317
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition board.cpp:1560
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition board.cpp:1331
GROUPS m_groups
Definition board.h:1421
MARKERS m_markers
Definition board.h:1417
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsAreaCache
Definition board.h:1371
std::optional< int > m_maxClearanceValue
Definition board.h:1377
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:2908
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:943
TRACKS m_tracks
Definition board.h:1420
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
Definition board.cpp:1613
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:407
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:2865
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition board.h:521
VECTOR2I GetPosition() const override
Definition board.cpp:565
void CacheTriangulation(PROGRESS_REPORTER *aReporter=nullptr, const std::vector< ZONE * > &aZones={})
Definition board.cpp:1084
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:962
void EmbedFonts() override
Finds all fonts used in the board and embeds them in the file if permissions allow.
Definition board.cpp:2755
PCB_BOARD_OUTLINE * m_boardOutline
Definition board.h:1424
void SetUserDefinedLayerCount(int aCount)
Definition board.cpp:893
const DRAWINGS & Drawings() const
Definition board.h:360
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition board.cpp:1528
constexpr coord_type GetY() const
Definition box2.h:208
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr coord_type GetX() const
Definition box2.h:207
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:658
constexpr size_type GetHeight() const
Definition box2.h:215
bool Dirty() const
BOARD_CONNECTED_ITEM * Parent() const
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
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition commit.h:96
A class to manage Component Classes in a board context.
void RunOnUnconnectedEdges(std::function< bool(CN_EDGE &)> aFunc)
unsigned int GetUnconnectedCount(bool aVisibileOnly) const
static DELETED_BOARD_ITEM * GetInstance()
Definition board_item.h:490
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
virtual VECTOR2I GetPosition() const
Definition eda_item.h:272
virtual void ClearEditFlags()
Definition eda_item.h:156
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
const KIID m_Uuid
Definition eda_item.h:516
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
static INSPECT_RESULT IterateForward(std::deque< T > &aList, INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes)
This changes first parameter to avoid the DList and use the main queue instead.
Definition eda_item.h:325
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:127
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:146
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
int Compare(const EDA_SHAPE *aOther) const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:79
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
EMBEDDED_FILES()=default
const std::map< wxString, EMBEDDED_FILE * > & EmbeddedFileMap() const
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Helper for storing and iterating over GAL_LAYER_IDs.
Definition layer_ids.h:402
static GAL_SET DefaultVisible()
Definition lset.cpp:769
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:68
static const std::vector< KICAD_T > Tracks
A scan list for only TRACKs and ARCs.
Definition collectors.h:126
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:131
virtual bool IsOutline() const
Definition font.h:139
Class OUTLINE_FONT implements outline font drawing.
EMBEDDING_PERMISSION GetEmbeddingPermission() const
bool IsBOARD_ITEM() const
Definition view_item.h:102
virtual wxString GetClass() const =0
Return the class name.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
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:1685
Definition kiid.h:49
Lightweight class which holds a pad, via, or a routed trace outline.
TYPE Type() const
Gets the routing item type.
Class which calculates lengths (and associated routing statistics) in a BOARD context.
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
LENGTH_DELAY_STATS CalculateLengthDetails(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr, LENGTH_DELAY_LAYER_OPT aLayerOpt=LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL, LENGTH_DELAY_DOMAIN_OPT aDomain=LENGTH_DELAY_DOMAIN_OPT::NO_DELAY_DETAIL) const
Calculates the electrical length of the given items.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static const LSET & AllLayersMask()
Definition lset.cpp:624
std::shared_ptr< RC_ITEM > GetRCItem() const
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition marker_base.h:94
void SetParent(JSON_SETTINGS *aParent, bool aLoadFromFile=true)
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:47
void SetDescription(const wxString &aDesc)
Definition netclass.h:114
Handle the data for a net.
Definition netinfo.h:54
wxString GetClass() const override
Return the class name.
Definition netinfo.h:65
const wxString & GetNetname() const
Definition netinfo.h:112
int GetNetCode() const
Definition netinfo.h:106
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:365
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition netinfo.h:369
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:373
unsigned GetNetCount() const
Definition netinfo.h:353
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:356
void ClearAllCaches()
Clears the effective netclass cache for all nets.
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const wxString &aNetName)
Fetches the effective (may be aggregate) netclass for the given net name.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
void SetDefaultNetclass(std::shared_ptr< NETCLASS > netclass)
Sets the default netclass for the project Calling user is responsible for resetting the effective net...
Definition pad.h:54
VECTOR2I GetPosition() const override
Definition pad.h:208
const VECTOR2D & GetSizeMils() const
Definition page_info.h:150
wxPrintOrientation GetWxOrientation() const
Definition page_info.h:133
static double GetCustomHeightMils()
Definition page_info.h:202
wxPaperSize GetPaperId() const
Definition page_info.h:138
static double GetCustomWidthMils()
Definition page_info.h:197
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:53
static PCB_MARKER * DeserializeFromString(const wxString &data)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Definition pcb_point.h:43
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.
static int Compare(const PCB_TABLE *aTable, const PCB_TABLE *aOther)
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:568
const VECTOR2I & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition pcb_track.h:167
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.
std::shared_ptr< COMPONENT_CLASS_SETTINGS > & ComponentClassSettings()
Container for project specific data.
Definition project.h:65
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:174
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:204
std::vector< KIID > GetIDs() const
Definition rc_item.h:126
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.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
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 OutlineCount() const
Return the number of outlines in the set.
const wxString & GetComment(int aIdx) const
static void GetContextualTextVars(wxArrayString *aVars)
Handle a list of polygons defining a copper zone.
Definition zone.h:74
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:505
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition zone.h:590
bool IsTeardropArea() const
Definition zone.h:679
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:1134
#define EXCLUDE_ZONES
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
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
RECURSE_MODE
Definition eda_item.h:50
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
INSPECT_RESULT
Definition eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
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:88
#define STRUCT_DELETED
flag indication structures to be erased
EDA_UNITS
Definition eda_units.h:48
KIID niluuid(0)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:674
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition layer_ids.h:228
@ GAL_LAYER_ID_START
Definition layer_ids.h:229
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:258
@ 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:286
@ LAYER_RATSNEST
Definition layer_ids.h:252
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:259
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Edge_Cuts
Definition layer_ids.h:112
@ B_Mask
Definition layer_ids.h:98
@ B_Cu
Definition layer_ids.h:65
@ F_Mask
Definition layer_ids.h:97
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ Rescue
Definition layer_ids.h:121
@ User_1
Definition layer_ids.h:124
@ PCB_LAYER_ID_COUNT
Definition layer_ids.h:171
@ F_Cu
Definition layer_ids.h:64
#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:363
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
STL namespace.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:87
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:107
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:105
PAGE_SIZE_TYPE
Definition page_info.h:50
Class to handle a set of BOARD_ITEMs.
ENDPOINT_T
Definition pcb_track.h:59
see class PGM_BASE
CITER next(CITER it)
Definition ptree.cpp:124
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:3021
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition board.cpp:3000
std::vector< char > decompressedData
Container to hold information pertinent to a layer of a BOARD.
Definition board.h:196
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
Definition board.cpp:794
static const char * ShowType(LAYER_T aType)
Convert a LAYER_T enum to a string representation of the layer type.
Definition board.cpp:778
Holds length measurement result details and statistics.
Struct to control which optimisations the length calculation code runs on the given path objects.
int delta
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::thread_pool< 0 > thread_pool
Definition thread_pool.h:31
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_POINT_T
class PCB_POINT, a 0-dimensional point
Definition typeinfo.h:112
@ 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< int32_t > VECTOR2I
Definition vector2d.h:695
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.