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