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