KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 *
8 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#include <iterator>
29#include <algorithm>
30
31#include <wx/log.h>
32
33#include <drc/drc_engine.h>
34#include <drc/drc_rtree.h>
36#include <board_commit.h>
37#include <board.h>
38#include <core/arraydim.h>
39#include <core/kicad_algo.h>
42#include <footprint.h>
43#include <font/outline_font.h>
45#include <lset.h>
46#include <pcb_base_frame.h>
47#include <pcb_track.h>
48#include <pcb_marker.h>
49#include <pcb_group.h>
50#include <pcb_generator.h>
51#include <pcb_point.h>
52#include <pcb_target.h>
53#include <pcb_shape.h>
54#include <pcb_barcode.h>
55#include <pcb_text.h>
56#include <pcb_textbox.h>
57#include <pcb_table.h>
58#include <pcb_dimension.h>
59#include <pgm_base.h>
60#include <pcbnew_settings.h>
61#include <progress_reporter.h>
62#include <project.h>
68#include <reporter.h>
69#include <tool/tool_manager.h>
71#include <string_utils.h>
72#include <thread_pool.h>
73#include <zone.h>
74#include <mutex>
75#include <pcb_board_outline.h>
76#include <local_history.h>
77#include <pcb_io/pcb_io_mgr.h>
78#include <trace_helpers.h>
79
80// This is an odd place for this, but CvPcb won't link if it's in board_item.cpp like I first
81// tried it.
83
84
91 m_timeStamp( 1 ),
93 m_project( nullptr ),
95 m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
96 m_NetInfo( this ),
97 m_embedFonts( false ),
98 m_embeddedFilesDelegate( nullptr ),
100 m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) )
101{
102 // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
103 // A too large value do not allow safely connecting 2 shapes like very short segments.
105
108 m_boardOutline = new PCB_BOARD_OUTLINE( this );
109
110 // we have not loaded a board yet, assume latest until then.
111 m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
112
113 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
114 {
115 m_layers[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
116
117 if( IsCopperLayer( layer ) )
118 m_layers[layer].m_type = LT_SIGNAL;
119 else if( layer >= User_1 && layer & 1 )
120 m_layers[layer].m_type = LT_AUX;
121 else
122 m_layers[layer].m_type = LT_UNDEFINED;
123 }
124
126
127 // Creates a zone to show sloder mask bridges created by a min web value
128 // it it just to show them
129 m_SolderMaskBridges = new ZONE( this );
131 m_SolderMaskBridges->SetLayerSet( LSET().set( F_Mask ).set( B_Mask ) );
132 int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
133 m_SolderMaskBridges->Outline()->NewOutline();
134 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
135 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
136 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, +infinity ) );
137 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, -infinity ) );
138 m_SolderMaskBridges->SetMinThickness( 0 );
139
141
142 // Initialize default netclass.
143 bds.m_NetSettings->SetDefaultNetclass( std::make_shared<NETCLASS>( NETCLASS::Default ) );
144 bds.m_NetSettings->GetDefaultNetclass()->SetDescription( _( "This is the default net class." ) );
145
146 bds.UseCustomTrackViaSize( false );
147
148 // Initialize ratsnest
149 m_connectivity.reset( new CONNECTIVITY_DATA() );
150
151 // Set flag bits on these that will only be cleared if these are loaded from a legacy file
152 m_LegacyVisibleLayers.reset().set( Rescue );
154}
155
156
158{
159 m_itemByIdCache.clear();
160
161 // Clean up the owned elements
163
164 delete m_SolderMaskBridges;
165
166 BOARD_ITEM_SET ownedItems = GetItemSet();
167
168 m_zones.clear();
169 m_footprints.clear();
170 m_tracks.clear();
171 m_drawings.clear();
172 m_groups.clear();
173 m_points.clear();
174
175 // Generators not currently returned by GetItemSet
176 for( PCB_GENERATOR* g : m_generators )
177 ownedItems.insert( g );
178
179 delete m_boardOutline;
180 m_generators.clear();
181
182 // Delete the owned items after clearing the containers, because some item dtors
183 // cause call chains that query the containers
184 for( BOARD_ITEM* item : ownedItems )
185 delete item;
186
187 // Remove any listeners
189}
190
191
193{
194 if( !GetConnectivity()->Build( this, aReporter ) )
195 return false;
196
198 return true;
199}
200
201
202void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly )
203{
204 if( m_project )
205 ClearProject();
206
207 m_project = aProject;
208
209 if( aProject && !aReferenceOnly )
210 {
211 PROJECT_FILE& project = aProject->GetProjectFile();
212
213 // Link the design settings object to the project file
214 project.m_BoardSettings = &GetDesignSettings();
215
216 // Set parent, which also will load the values from JSON stored in the project if we don't
217 // have legacy design settings loaded already
218 project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
219
220 // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
221 // list at this point. If we loaded anything into it from a legacy board file then we
222 // want to transfer it over to the project netclasses list.
224 {
225 std::shared_ptr<NET_SETTINGS> legacySettings = GetDesignSettings().m_NetSettings;
226 std::shared_ptr<NET_SETTINGS>& projectSettings = project.NetSettings();
227
228 projectSettings->SetDefaultNetclass( legacySettings->GetDefaultNetclass() );
229 projectSettings->SetNetclasses( legacySettings->GetNetclasses() );
230 projectSettings->SetNetclassPatternAssignments(
231 std::move( legacySettings->GetNetclassPatternAssignments() ) );
232 }
233
234 // Now update the DesignSettings' netclass pointer to point into the project.
235 GetDesignSettings().m_NetSettings = project.NetSettings();
236 }
237}
238
239
241{
242 if( !m_project )
243 return;
244
245 PROJECT_FILE& project = m_project->GetProjectFile();
246
247 // Owned by the BOARD
248 if( project.m_BoardSettings )
249 {
250 project.ReleaseNestedSettings( project.m_BoardSettings );
251 project.m_BoardSettings = nullptr;
252 }
253
255 GetDesignSettings().SetParent( nullptr );
256 m_project = nullptr;
257}
258
259
261{
262 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
263
264 m_timeStamp++;
265
269 || m_maxClearanceValue.has_value() || !m_itemByIdCache.empty() || !m_ItemNetclassCache.empty() )
270 {
271 m_IntersectsAreaCache.clear();
272 m_EnclosedByAreaCache.clear();
277 m_ItemNetclassCache.clear();
278
279 m_ZoneBBoxCache.clear();
280
281 m_CopperItemRTreeCache = nullptr;
282
283 // These are always regenerated before use, but still probably safer to clear them
284 // while we're here.
287 m_DRCZones.clear();
288 m_DRCCopperZones.clear();
291
292 m_maxClearanceValue.reset();
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
312 [&]( CN_EDGE& aEdge )
313 {
314 if( aEdge.GetSourceNode() && aEdge.GetTargetNode() && !aEdge.GetSourceNode()->Dirty()
315 && !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 = [&]( const wxString& aVar )
476 {
477 if( !alg::contains( *aVars, aVar ) )
478 aVars->push_back( aVar );
479 };
480
481 add( wxT( "LAYER" ) );
482 add( wxT( "FILENAME" ) );
483 add( wxT( "FILEPATH" ) );
484 add( wxT( "PROJECTNAME" ) );
485 add( wxT( "DRC_ERROR <message_text>" ) );
486 add( wxT( "DRC_WARNING <message_text>" ) );
487 add( wxT( "VARIANT" ) );
488 add( wxT( "VARIANT_DESC" ) );
489
491
492 if( GetProject() )
493 {
494 for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
495 add( entry.first );
496 }
497}
498
499
500bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
501{
502 if( token->Contains( ':' ) )
503 {
504 wxString remainder;
505 wxString ref = token->BeforeFirst( ':', &remainder );
506 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
507
508 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
509 {
510 FOOTPRINT* refFP = static_cast<FOOTPRINT*>( refItem );
511
512 if( refFP->ResolveTextVar( &remainder, aDepth + 1 ) )
513 {
514 *token = std::move( remainder );
515 return true;
516 }
517 }
518
519 // If UUID resolution failed, try to resolve by reference designator
520 // This handles typing ${U1:VALUE} directly without save/reload
521 if( !refItem )
522 {
523 for( const FOOTPRINT* footprint : Footprints() )
524 {
525 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
526 {
527 wxString remainderCopy = remainder;
528
529 if( footprint->ResolveTextVar( &remainderCopy, aDepth + 1 ) )
530 {
531 *token = std::move( remainderCopy );
532 }
533 else
534 {
535 // Field/function not found on footprint
536 *token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), footprint->GetReference(), remainder );
537 }
538
539 return true;
540 }
541 }
542
543 // Reference not found - show error message
544 *token = wxString::Format( wxT( "<Unknown reference: %s>" ), ref );
545 return true;
546 }
547 }
548
549 if( token->IsSameAs( wxT( "FILENAME" ) ) )
550 {
551 wxFileName fn( GetFileName() );
552 *token = fn.GetFullName();
553 return true;
554 }
555 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
556 {
557 wxFileName fn( GetFileName() );
558 *token = fn.GetFullPath();
559 return true;
560 }
561 else if( token->IsSameAs( wxT( "VARIANT" ) ) )
562 {
563 *token = GetCurrentVariant();
564 return true;
565 }
566 else if( token->IsSameAs( wxT( "VARIANT_DESC" ) ) )
567 {
569 return true;
570 }
571 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) && GetProject() )
572 {
573 *token = GetProject()->GetProjectName();
574 return true;
575 }
576
577 wxString var = *token;
578
579 if( m_properties.count( var ) )
580 {
581 *token = m_properties.at( var );
582 return true;
583 }
584 else if( GetTitleBlock().TextVarResolver( token, m_project ) )
585 {
586 return true;
587 }
588
589 if( GetProject() && GetProject()->TextVarResolver( token ) )
590 return true;
591
592 return false;
593}
594
595
596bool BOARD::IsEmpty() const
597{
598 return m_drawings.empty() && m_footprints.empty() && m_tracks.empty() && m_zones.empty() && m_points.empty();
599}
600
601
603{
604 return ZeroOffset;
605}
606
607
608void BOARD::SetPosition( const VECTOR2I& aPos )
609{
610 wxLogWarning( wxT( "This should not be called on the BOARD object" ) );
611}
612
613
614void BOARD::Move( const VECTOR2I& aMoveVector ) // overload
615{
616 INSPECTOR_FUNC inspector = [&]( EDA_ITEM* item, void* testData )
617 {
618 if( item->IsBOARD_ITEM() )
619 {
620 BOARD_ITEM* board_item = static_cast<BOARD_ITEM*>( item );
621
622 // aMoveVector was snapshotted, don't need "data".
623 // Only move the top level group
624 if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() )
625 board_item->Move( aMoveVector );
626 }
627
629 };
630
631 Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems );
632}
633
634
635void BOARD::RunOnChildren( const std::function<void( BOARD_ITEM* )>& aFunction, RECURSE_MODE aMode ) const
636{
637 try
638 {
639 for( PCB_TRACK* track : m_tracks )
640 aFunction( track );
641
642 for( ZONE* zone : m_zones )
643 aFunction( zone );
644
645 for( PCB_MARKER* marker : m_markers )
646 aFunction( marker );
647
648 for( PCB_GROUP* group : m_groups )
649 aFunction( group );
650
651 for( PCB_POINT* point : m_points )
652 aFunction( point );
653
654 for( FOOTPRINT* footprint : m_footprints )
655 {
656 aFunction( footprint );
657
658 if( aMode == RECURSE_MODE::RECURSE )
659 footprint->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
660 }
661
662 for( BOARD_ITEM* drawing : m_drawings )
663 {
664 aFunction( drawing );
665
666 if( aMode == RECURSE_MODE::RECURSE )
667 drawing->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
668 }
669 }
670 catch( std::bad_function_call& )
671 {
672 wxFAIL_MSG( wxT( "Error running BOARD::RunOnChildren" ) );
673 }
674}
675
676
678{
679 TRACKS ret;
680
681 INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
682 {
683 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
684
685 if( t->GetNetCode() == aNetCode )
686 ret.push_back( t );
687
689 };
690
691 // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
692 // appends all in aNetCode to ret.
693 Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
694
695 return ret;
696}
697
698
699bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
700{
701 m_layers[aIndex] = aLayer;
703 return true;
704}
705
706
707PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
708{
709 // Check the BOARD physical layer names.
710 for( auto& [layer_id, layer] : m_layers )
711 {
712 if( layer.m_name == aLayerName || layer.m_userName == aLayerName )
713 return ToLAYER_ID( layer_id );
714 }
715
716 // Otherwise fall back to the system standard layer names for virtual layers.
717 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
718 {
719 if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
720 return ToLAYER_ID( layer );
721 }
722
723 return UNDEFINED_LAYER;
724}
725
726
727const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
728{
729 // All layer names are stored in the BOARD.
730 if( IsLayerEnabled( aLayer ) )
731 {
732 auto it = m_layers.find( aLayer );
733
734 // Standard names were set in BOARD::BOARD() but they may be over-ridden by
735 // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
736 // if it was set. Otherwise return the Standard English layer name.
737 if( it != m_layers.end() && !it->second.m_userName.IsEmpty() )
738 return it->second.m_userName;
739 }
740
741 return GetStandardLayerName( aLayer );
742}
743
744
745bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
746{
747 if( aLayerName.IsEmpty() )
748 {
749 // If the name is empty, we clear the user name.
750 m_layers[aLayer].m_userName.clear();
751 }
752 else
753 {
754 // no quote chars in the name allowed
755 if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
756 return false;
757
758 if( IsLayerEnabled( aLayer ) )
759 {
760 m_layers[aLayer].m_userName = aLayerName;
762 return true;
763 }
764 }
765
766 return false;
767}
768
769
771{
772 return ::IsFrontLayer( aLayer ) || GetLayerType( aLayer ) == LT_FRONT;
773}
774
775
777{
778 return ::IsBackLayer( aLayer ) || GetLayerType( aLayer ) == LT_BACK;
779}
780
781
783{
784 if( IsLayerEnabled( aLayer ) )
785 {
786 auto it = m_layers.find( aLayer );
787
788 if( it != m_layers.end() )
789 return it->second.m_type;
790 }
791
792 if( aLayer >= User_1 && !IsCopperLayer( aLayer ) )
793 return LT_AUX;
794 else if( IsCopperLayer( aLayer ) )
795 return LT_SIGNAL;
796 else
797 return LT_UNDEFINED;
798}
799
800
801bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
802{
803 if( IsLayerEnabled( aLayer ) )
804 {
805 m_layers[aLayer].m_type = aLayerType;
807 return true;
808 }
809
810 return false;
811}
812
813
814const char* LAYER::ShowType( LAYER_T aType )
815{
816 switch( aType )
817 {
818 default:
819 case LT_SIGNAL: return "signal";
820 case LT_POWER: return "power";
821 case LT_MIXED: return "mixed";
822 case LT_JUMPER: return "jumper";
823 case LT_AUX: return "auxiliary";
824 case LT_FRONT: return "front";
825 case LT_BACK: return "back";
826 }
827}
828
829
830LAYER_T LAYER::ParseType( const char* aType )
831{
832 if( strcmp( aType, "signal" ) == 0 )
833 return LT_SIGNAL;
834 else if( strcmp( aType, "power" ) == 0 )
835 return LT_POWER;
836 else if( strcmp( aType, "mixed" ) == 0 )
837 return LT_MIXED;
838 else if( strcmp( aType, "jumper" ) == 0 )
839 return LT_JUMPER;
840 else if( strcmp( aType, "auxiliary" ) == 0 )
841 return LT_AUX;
842 else if( strcmp( aType, "front" ) == 0 )
843 return LT_FRONT;
844 else if( strcmp( aType, "back" ) == 0 )
845 return LT_BACK;
846 else
847 return LT_UNDEFINED;
848}
849
850
852{
853 for( int layer = F_Cu; layer < PCB_LAYER_ID_COUNT; ++layer )
854 m_layers[layer].m_opposite = ::FlipLayer( ToLAYER_ID( layer ), GetCopperLayerCount() );
855
856 // Match up similary-named front/back user layers
857 for( int layer = User_1; layer <= PCB_LAYER_ID_COUNT; layer += 2 )
858 {
859 if( m_layers[layer].m_opposite != layer ) // already paired
860 continue;
861
862 if( m_layers[layer].m_type != LT_FRONT && m_layers[layer].m_type != LT_BACK )
863 continue;
864
865 wxString principalName = m_layers[layer].m_userName.AfterFirst( '.' );
866
867 for( int ii = layer + 2; ii <= PCB_LAYER_ID_COUNT; ii += 2 )
868 {
869 if( m_layers[ii].m_opposite != ii ) // already paired
870 continue;
871
872 if( m_layers[ii].m_type != LT_FRONT && m_layers[ii].m_type != LT_BACK )
873 continue;
874
875 if( m_layers[layer].m_type == m_layers[ii].m_type )
876 continue;
877
878 wxString candidate = m_layers[ii].m_userName.AfterFirst( '.' );
879
880 if( !candidate.IsEmpty() && candidate == principalName )
881 {
882 m_layers[layer].m_opposite = ii;
883 m_layers[ii].m_opposite = layer;
884 break;
885 }
886 }
887 }
888
889 // Match up non-custom-named consecutive front/back user layer pairs
890 for( int layer = User_1; layer < PCB_LAYER_ID_COUNT - 2; layer += 2 )
891 {
892 int next = layer + 2;
893
894 // ignore already-matched layers
895 if( m_layers[layer].m_opposite != layer || m_layers[next].m_opposite != next )
896 continue;
897
898 // ignore layer pairs that aren't consecutive front/back
899 if( m_layers[layer].m_type != LT_FRONT || m_layers[next].m_type != LT_BACK )
900 continue;
901
902 if( m_layers[layer].m_userName != m_layers[layer].m_name && m_layers[next].m_userName != m_layers[next].m_name )
903 {
904 m_layers[layer].m_opposite = next;
905 m_layers[next].m_opposite = layer;
906 }
907 }
908}
909
910
912{
913 auto it = m_layers.find( aLayer );
914 return it == m_layers.end() ? aLayer : ToLAYER_ID( it->second.m_opposite );
915}
916
917
922
923
925{
927}
928
929
934
935
937{
939}
940
942{
943 int imax = GetCopperLayerCount();
944
945 // layers IDs are F_Cu, B_Cu, and even IDs values (imax values)
946 if( imax <= 2 ) // at least 2 layers are expected
947 return B_Cu;
948
949 // For a 4 layer, last ID is In2_Cu = 6 (IDs are 0, 2, 4, 6)
950 return static_cast<PCB_LAYER_ID>( ( imax - 1 ) * 2 );
951}
952
953
954int BOARD::LayerDepth( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer ) const
955{
956 if( aStartLayer > aEndLayer )
957 std::swap( aStartLayer, aEndLayer );
958
959 if( aEndLayer == B_Cu )
960 aEndLayer = ToLAYER_ID( F_Cu + GetCopperLayerCount() - 1 );
961
962 return aEndLayer - aStartLayer;
963}
964
965
967{
969}
970
971
973{
974 // If there is no project, assume layer is visible always
975 return GetDesignSettings().IsLayerEnabled( aLayer )
976 && ( !m_project || m_project->GetLocalSettings().m_VisibleLayers[aLayer] );
977}
978
979
981{
982 return m_project ? m_project->GetLocalSettings().m_VisibleLayers : LSET::AllLayersMask();
983}
984
985
986void BOARD::SetEnabledLayers( const LSET& aLayerSet )
987{
988 GetDesignSettings().SetEnabledLayers( aLayerSet );
989}
990
991
993{
994 return GetDesignSettings().IsLayerEnabled( aLayer );
995}
996
997
998void BOARD::SetVisibleLayers( const LSET& aLayerSet )
999{
1000 if( m_project )
1001 m_project->GetLocalSettings().m_VisibleLayers = aLayerSet;
1002}
1003
1004
1006{
1007 // Call SetElementVisibility for each item
1008 // to ensure specific calculations that can be needed by some items,
1009 // just changing the visibility flags could be not sufficient.
1010 for( size_t i = 0; i < aSet.size(); i++ )
1011 SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
1012}
1013
1014
1016{
1017 SetVisibleLayers( LSET().set() );
1018
1019 // Call SetElementVisibility for each item,
1020 // to ensure specific calculations that can be needed by some items
1022 SetElementVisibility( ii, true );
1023}
1024
1025
1027{
1028 return m_project ? m_project->GetLocalSettings().m_VisibleItems : GAL_SET::DefaultVisible();
1029}
1030
1031
1033{
1034 return !m_project || m_project->GetLocalSettings().m_VisibleItems[aLayer - GAL_LAYER_ID_START];
1035}
1036
1037
1038void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
1039{
1040 if( m_project )
1041 m_project->GetLocalSettings().m_VisibleItems.set( aLayer - GAL_LAYER_ID_START, isEnabled );
1042
1043 switch( aLayer )
1044 {
1045 case LAYER_RATSNEST:
1046 {
1047 // because we have a tool to show/hide ratsnest relative to a pad or a footprint
1048 // so the hide/show option is a per item selection
1049
1050 for( PCB_TRACK* track : Tracks() )
1051 track->SetLocalRatsnestVisible( isEnabled );
1052
1053 for( FOOTPRINT* footprint : Footprints() )
1054 {
1055 for( PAD* pad : footprint->Pads() )
1056 pad->SetLocalRatsnestVisible( isEnabled );
1057 }
1058
1059 for( ZONE* zone : Zones() )
1060 zone->SetLocalRatsnestVisible( isEnabled );
1061
1062 break;
1063 }
1064
1065 default:;
1066 }
1067}
1068
1069
1071{
1072 switch( aLayer )
1073 {
1076 default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true;
1077 }
1078}
1079
1080
1085
1086
1088{
1089 *m_designSettings = aSettings;
1090}
1091
1092
1094{
1095 if( m_designSettings && m_designSettings->m_DRCEngine )
1096 m_designSettings->m_DRCEngine->InvalidateClearanceCache( aUuid );
1097}
1098
1099
1101{
1102 if( m_designSettings && m_designSettings->m_DRCEngine )
1103 m_designSettings->m_DRCEngine->InitializeClearanceCache();
1104}
1105
1106
1108{
1109 if( !m_maxClearanceValue.has_value() )
1110 {
1111 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
1112
1113 int worstClearance = m_designSettings->GetBiggestClearanceValue();
1114
1115 for( ZONE* zone : m_zones )
1116 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1117
1118 for( FOOTPRINT* footprint : m_footprints )
1119 {
1120 for( PAD* pad : footprint->Pads() )
1121 {
1122 std::optional<int> override = pad->GetClearanceOverrides( nullptr );
1123
1124 if( override.has_value() )
1125 worstClearance = std::max( worstClearance, override.value() );
1126 }
1127
1128 for( ZONE* zone : footprint->Zones() )
1129 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1130 }
1131
1132 m_maxClearanceValue = worstClearance;
1133 }
1134
1135 return m_maxClearanceValue.value_or( 0 );
1136};
1137
1138
1139void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<ZONE*>& aZones )
1140{
1141 std::vector<ZONE*> zones = aZones;
1142
1143 if( zones.empty() )
1144 zones = m_zones;
1145
1146 if( zones.empty() )
1147 return;
1148
1149 if( aReporter )
1150 aReporter->Report( _( "Tessellating copper zones..." ) );
1151
1153 std::vector<std::future<size_t>> returns;
1154
1155 returns.reserve( zones.size() );
1156
1157 auto cache_zones = [aReporter]( ZONE* aZone ) -> size_t
1158 {
1159 if( aReporter && aReporter->IsCancelled() )
1160 return 0;
1161
1162 aZone->CacheTriangulation();
1163
1164 if( aReporter )
1165 aReporter->AdvanceProgress();
1166
1167 return 1;
1168 };
1169
1170 for( ZONE* zone : zones )
1171 returns.emplace_back( tp.submit_task(
1172 [cache_zones, zone]
1173 {
1174 return cache_zones( zone );
1175 } ) );
1176
1177 // Finalize the triangulation threads
1178 for( const std::future<size_t>& ret : returns )
1179 {
1180 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1181
1182 while( status != std::future_status::ready )
1183 {
1184 if( aReporter )
1185 aReporter->KeepRefreshing();
1186
1187 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1188 }
1189 }
1190}
1191
1192
1193void BOARD::RunOnNestedEmbeddedFiles( const std::function<void( EMBEDDED_FILES* )>& aFunction )
1194{
1195 for( FOOTPRINT* footprint : m_footprints )
1196 aFunction( footprint->GetEmbeddedFiles() );
1197}
1198
1199
1201{
1203 [&]( EMBEDDED_FILES* nested )
1204 {
1205 for( auto& [filename, embeddedFile] : nested->EmbeddedFileMap() )
1206 {
1208
1209 if( file )
1210 {
1211 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1212 embeddedFile->decompressedData = file->decompressedData;
1213 embeddedFile->data_hash = file->data_hash;
1214 embeddedFile->is_valid = file->is_valid;
1215 }
1216 }
1217 } );
1218}
1219
1220
1221void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
1222{
1223 if( aBoardItem == nullptr )
1224 {
1225 wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem nullptr" ) );
1226 return;
1227 }
1228
1229 m_itemByIdCache.insert( { aBoardItem->m_Uuid, aBoardItem } );
1230
1231 switch( aBoardItem->Type() )
1232 {
1233 case PCB_NETINFO_T: m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem ); break;
1234
1235 // this one uses a vector
1236 case PCB_MARKER_T: m_markers.push_back( (PCB_MARKER*) aBoardItem ); break;
1237
1238 // this one uses a vector
1239 case PCB_GROUP_T: m_groups.push_back( (PCB_GROUP*) aBoardItem ); break;
1240
1241 // this one uses a vector
1242 case PCB_GENERATOR_T: m_generators.push_back( (PCB_GENERATOR*) aBoardItem ); break;
1243
1244 // this one uses a vector
1245 case PCB_ZONE_T: m_zones.push_back( (ZONE*) aBoardItem ); break;
1246
1247 case PCB_VIA_T:
1248 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1249 m_tracks.push_back( static_cast<PCB_VIA*>( aBoardItem ) );
1250 else
1251 m_tracks.push_front( static_cast<PCB_VIA*>( aBoardItem ) );
1252
1253 break;
1254
1255 case PCB_TRACE_T:
1256 case PCB_ARC_T:
1257 if( !IsCopperLayer( aBoardItem->GetLayer() ) )
1258 {
1259 // The only current known source of these is SWIG (KICAD-BY7, et al).
1260 // N.B. This inserts a small memory leak as we lose the track/via/arc.
1261 wxFAIL_MSG( wxString::Format( "BOARD::Add() Cannot place Track on non-copper layer: %d = %s",
1262 static_cast<int>( aBoardItem->GetLayer() ),
1263 GetLayerName( aBoardItem->GetLayer() ) ) );
1264 return;
1265 }
1266
1267 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1268 m_tracks.push_back( static_cast<PCB_TRACK*>( aBoardItem ) );
1269 else
1270 m_tracks.push_front( static_cast<PCB_TRACK*>( aBoardItem ) );
1271
1272 break;
1273
1274 case PCB_FOOTPRINT_T:
1275 {
1276 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aBoardItem );
1277
1278 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1279 m_footprints.push_back( footprint );
1280 else
1281 m_footprints.push_front( footprint );
1282
1283 footprint->RunOnChildren(
1284 [&]( BOARD_ITEM* aChild )
1285 {
1286 m_itemByIdCache.insert( { aChild->m_Uuid, aChild } );
1287 },
1289 break;
1290 }
1291
1292 case PCB_BARCODE_T:
1293 case PCB_DIM_ALIGNED_T:
1294 case PCB_DIM_CENTER_T:
1295 case PCB_DIM_RADIAL_T:
1297 case PCB_DIM_LEADER_T:
1298 case PCB_SHAPE_T:
1300 case PCB_FIELD_T:
1301 case PCB_TEXT_T:
1302 case PCB_TEXTBOX_T:
1303 case PCB_TABLE_T:
1304 case PCB_TARGET_T:
1305 {
1306 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1307 m_drawings.push_back( aBoardItem );
1308 else
1309 m_drawings.push_front( aBoardItem );
1310
1311 if( aBoardItem->Type() == PCB_TABLE_T )
1312 {
1313 PCB_TABLE* table = static_cast<PCB_TABLE*>( aBoardItem );
1314
1315 table->RunOnChildren(
1316 [&]( BOARD_ITEM* aChild )
1317 {
1318 m_itemByIdCache.insert( { aChild->m_Uuid, aChild } );
1319 },
1321 }
1322
1323 break;
1324 }
1325
1326 case PCB_POINT_T:
1327 // These aren't graphics as they have no physical presence
1328 m_points.push_back( static_cast<PCB_POINT*>( aBoardItem ) );
1329 break;
1330
1331 case PCB_TABLECELL_T:
1332 // Handled by parent table
1333 break;
1334
1335 default:
1336 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Add() item type %s not handled" ), aBoardItem->GetClass() ) );
1337 return;
1338 }
1339
1340 aBoardItem->SetParent( this );
1341 aBoardItem->ClearEditFlags();
1342
1343 if( !aSkipConnectivity )
1344 m_connectivity->Add( aBoardItem );
1345
1346 if( aMode != ADD_MODE::BULK_INSERT && aMode != ADD_MODE::BULK_APPEND )
1348}
1349
1350
1351void BOARD::FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems )
1352{
1354}
1355
1356
1357void BOARD::FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems )
1358{
1359 InvokeListeners( &BOARD_LISTENER::OnBoardItemsRemoved, *this, aRemovedItems );
1360}
1361
1362
1364{
1365 for( int ii = (int) m_zones.size() - 1; ii >= 0; --ii )
1366 {
1367 ZONE* zone = m_zones[ii];
1368
1369 if( zone->IsTeardropArea() && zone->HasFlag( STRUCT_DELETED ) )
1370 {
1371 m_itemByIdCache.erase( zone->m_Uuid );
1372 m_zones.erase( m_zones.begin() + ii );
1373 m_connectivity->Remove( zone );
1374 aCommit.Removed( zone );
1375 }
1376 }
1377}
1378
1379
1380void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
1381{
1382 // find these calls and fix them! Don't send me no stinking' nullptr.
1383 wxASSERT( aBoardItem );
1384
1385 m_itemByIdCache.erase( aBoardItem->m_Uuid );
1386
1387 switch( aBoardItem->Type() )
1388 {
1389 case PCB_NETINFO_T:
1390 {
1391 NETINFO_ITEM* netItem = static_cast<NETINFO_ITEM*>( aBoardItem );
1392 NETINFO_ITEM* unconnected = m_NetInfo.GetNetItem( NETINFO_LIST::UNCONNECTED );
1393
1394 for( BOARD_CONNECTED_ITEM* boardItem : AllConnectedItems() )
1395 {
1396 if( boardItem->GetNet() == netItem )
1397 boardItem->SetNet( unconnected );
1398 }
1399
1400 m_NetInfo.RemoveNet( netItem );
1401 break;
1402 }
1403
1404 case PCB_MARKER_T: std::erase( m_markers, aBoardItem ); break;
1405
1406 case PCB_GROUP_T: std::erase( m_groups, aBoardItem ); break;
1407
1408 case PCB_ZONE_T: std::erase( m_zones, aBoardItem ); break;
1409
1410 case PCB_POINT_T: std::erase( m_points, aBoardItem ); break;
1411
1412 case PCB_GENERATOR_T: std::erase( m_generators, aBoardItem ); break;
1413
1414 case PCB_FOOTPRINT_T:
1415 {
1416 std::erase( m_footprints, aBoardItem );
1417 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aBoardItem );
1418
1419 footprint->RunOnChildren(
1420 [&]( BOARD_ITEM* aChild )
1421 {
1422 m_itemByIdCache.erase( aChild->m_Uuid );
1423 },
1425
1426 break;
1427 }
1428
1429 case PCB_TRACE_T:
1430 case PCB_ARC_T:
1431 case PCB_VIA_T: std::erase( m_tracks, aBoardItem ); break;
1432
1433 case PCB_BARCODE_T:
1434 case PCB_DIM_ALIGNED_T:
1435 case PCB_DIM_CENTER_T:
1436 case PCB_DIM_RADIAL_T:
1438 case PCB_DIM_LEADER_T:
1439 case PCB_SHAPE_T:
1441 case PCB_FIELD_T:
1442 case PCB_TEXT_T:
1443 case PCB_TEXTBOX_T:
1444 case PCB_TABLE_T:
1445 case PCB_TARGET_T:
1446 {
1447 std::erase( m_drawings, aBoardItem );
1448
1449 if( aBoardItem->Type() == PCB_TABLE_T )
1450 {
1451 PCB_TABLE* table = static_cast<PCB_TABLE*>( aBoardItem );
1452
1453 table->RunOnChildren(
1454 [&]( BOARD_ITEM* aChild )
1455 {
1456 m_itemByIdCache.erase( aChild->m_Uuid );
1457 },
1459 }
1460
1461 break;
1462 }
1463
1464 case PCB_TABLECELL_T:
1465 // Handled by parent table
1466 break;
1467
1468 // other types may use linked list
1469 default:
1470 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Remove() item type %s not handled" ), aBoardItem->GetClass() ) );
1471 }
1472
1473 aBoardItem->SetFlags( STRUCT_DELETED );
1474
1475 m_connectivity->Remove( aBoardItem );
1476
1477 if( aRemoveMode != REMOVE_MODE::BULK )
1479}
1480
1481
1482void BOARD::RemoveAll( std::initializer_list<KICAD_T> aTypes )
1483{
1484 std::vector<BOARD_ITEM*> removed;
1485
1486 for( const KICAD_T& type : aTypes )
1487 {
1488 switch( type )
1489 {
1490 case PCB_NETINFO_T:
1491 for( NETINFO_ITEM* item : m_NetInfo )
1492 removed.emplace_back( item );
1493
1494 m_NetInfo.clear();
1495 break;
1496
1497 case PCB_MARKER_T:
1498 std::copy( m_markers.begin(), m_markers.end(), std::back_inserter( removed ) );
1499 m_markers.clear();
1500 break;
1501
1502 case PCB_GROUP_T:
1503 std::copy( m_groups.begin(), m_groups.end(), std::back_inserter( removed ) );
1504 m_groups.clear();
1505 break;
1506
1507 case PCB_POINT_T:
1508 std::copy( m_points.begin(), m_points.end(), std::back_inserter( removed ) );
1509 m_points.clear();
1510 break;
1511
1512 case PCB_ZONE_T:
1513 std::copy( m_zones.begin(), m_zones.end(), std::back_inserter( removed ) );
1514 m_zones.clear();
1515 break;
1516
1517 case PCB_GENERATOR_T:
1518 std::copy( m_generators.begin(), m_generators.end(), std::back_inserter( removed ) );
1519 m_generators.clear();
1520 break;
1521
1522 case PCB_FOOTPRINT_T:
1523 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( removed ) );
1524 m_footprints.clear();
1525 break;
1526
1527 case PCB_TRACE_T:
1528 std::copy( m_tracks.begin(), m_tracks.end(), std::back_inserter( removed ) );
1529 m_tracks.clear();
1530 break;
1531
1532 case PCB_ARC_T:
1533 case PCB_VIA_T: wxFAIL_MSG( wxT( "Use PCB_TRACE_T to remove all tracks, arcs, and vias" ) ); break;
1534
1535 case PCB_SHAPE_T:
1536 std::copy( m_drawings.begin(), m_drawings.end(), std::back_inserter( removed ) );
1537 m_drawings.clear();
1538 break;
1539
1540 case PCB_DIM_ALIGNED_T:
1541 case PCB_DIM_CENTER_T:
1542 case PCB_DIM_RADIAL_T:
1544 case PCB_DIM_LEADER_T:
1546 case PCB_FIELD_T:
1547 case PCB_TEXT_T:
1548 case PCB_TEXTBOX_T:
1549 case PCB_TABLE_T:
1550 case PCB_TARGET_T:
1551 case PCB_BARCODE_T: wxFAIL_MSG( wxT( "Use PCB_SHAPE_T to remove all graphics and text" ) ); break;
1552
1553 default: wxFAIL_MSG( wxT( "BOARD::RemoveAll() needs more ::Type() support" ) );
1554 }
1555 }
1556
1558
1559 FinalizeBulkRemove( removed );
1560}
1561
1562
1564{
1565 PCB_LAYER_COLLECTOR collector;
1566
1567 collector.SetLayerId( aLayer );
1569
1570 if( collector.GetCount() != 0 )
1571 {
1572 // Skip items owned by footprints and footprints when building
1573 // the actual list of removed layers: these items are not removed
1574 for( int i = 0; i < collector.GetCount(); i++ )
1575 {
1576 BOARD_ITEM* item = collector[i];
1577
1578 if( item->Type() == PCB_FOOTPRINT_T || item->GetParentFootprint() )
1579 continue;
1580
1581 // Vias are on multiple adjacent layers, but only the top and
1582 // the bottom layers are stored. So there are issues only if one
1583 // is on a removed layer
1584 if( item->Type() == PCB_VIA_T )
1585 {
1586 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1587
1588 if( via->GetViaType() == VIATYPE::THROUGH )
1589 continue;
1590 else
1591 {
1592 PCB_LAYER_ID top_layer;
1593 PCB_LAYER_ID bottom_layer;
1594 via->LayerPair( &top_layer, &bottom_layer );
1595
1596 if( top_layer != aLayer && bottom_layer != aLayer )
1597 continue;
1598 }
1599 }
1600
1601 return true;
1602 }
1603 }
1604
1605 return false;
1606}
1607
1608
1610{
1611 bool modified = false;
1612 bool removedItemLayers = false;
1613 PCB_LAYER_COLLECTOR collector;
1614
1615 collector.SetLayerId( aLayer );
1617
1618 for( int i = 0; i < collector.GetCount(); i++ )
1619 {
1620 BOARD_ITEM* item = collector[i];
1621
1622 // Do not remove/change an item owned by a footprint
1623 if( item->GetParentFootprint() )
1624 continue;
1625
1626 // Do not remove footprints
1627 if( item->Type() == PCB_FOOTPRINT_T )
1628 continue;
1629
1630 // Note: vias are specific. They are only on copper layers, and
1631 // do not use a layer set, only store the copper top and the copper bottom.
1632 // So reinit the layer set does not work with vias
1633 if( item->Type() == PCB_VIA_T )
1634 {
1635 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1636
1637 if( via->GetViaType() == VIATYPE::THROUGH )
1638 {
1639 removedItemLayers = true;
1640 continue;
1641 }
1642 else if( via->IsOnLayer( aLayer ) )
1643 {
1644 PCB_LAYER_ID top_layer;
1645 PCB_LAYER_ID bottom_layer;
1646 via->LayerPair( &top_layer, &bottom_layer );
1647
1648 if( top_layer == aLayer || bottom_layer == aLayer )
1649 {
1650 // blind/buried vias with a top or bottom layer on a removed layer
1651 // are removed. Perhaps one could just modify the top/bottom layer,
1652 // but I am not sure this is better.
1653 Remove( item );
1654 delete item;
1655 modified = true;
1656 }
1657
1658 removedItemLayers = true;
1659 }
1660 }
1661 else if( item->IsOnLayer( aLayer ) )
1662 {
1663 LSET layers = item->GetLayerSet();
1664
1665 layers.reset( aLayer );
1666
1667 if( layers.any() )
1668 {
1669 item->SetLayerSet( layers );
1670 }
1671 else
1672 {
1673 Remove( item );
1674 delete item;
1675 modified = true;
1676 }
1677
1678 removedItemLayers = true;
1679 }
1680 }
1681
1682 if( removedItemLayers )
1684
1685 return modified;
1686}
1687
1688
1689wxString BOARD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1690{
1691 return wxString::Format( _( "PCB" ) );
1692}
1693
1694
1696{
1697 INSPECTOR_FUNC inspector = [&]( EDA_ITEM* descendant, void* aTestData )
1698 {
1699 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( descendant );
1700
1701 if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC )
1702 {
1703 dimension->UpdateUnits();
1704
1705 if( aView )
1706 aView->Update( dimension );
1707 }
1708
1710 };
1711
1712 aItem->Visit( inspector, nullptr,
1714}
1715
1716
1718{
1719 for( PCB_MARKER* marker : m_markers )
1720 delete marker;
1721
1722 m_markers.clear();
1724}
1725
1726
1727void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
1728{
1729 // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
1730 std::vector<PCB_MARKER*> remaining;
1731
1732 for( PCB_MARKER* marker : m_markers )
1733 {
1734 if( ( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION && aExclusions )
1735 || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) )
1736 {
1737 delete marker;
1738 }
1739 else
1740 {
1741 remaining.push_back( marker );
1742 }
1743 }
1744
1745 m_markers = std::move( remaining );
1747}
1748
1749
1751{
1752 std::vector<FOOTPRINT*> footprints;
1753 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( footprints ) );
1754
1756
1757 for( FOOTPRINT* footprint : footprints )
1758 delete footprint;
1759}
1760
1761
1763{
1764 std::vector<FOOTPRINT*> footprints;
1765 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( footprints ) );
1766
1768
1769 for( FOOTPRINT* footprint : footprints )
1770 footprint->SetParent( nullptr );
1771}
1772
1773
1774BOARD_ITEM* BOARD::ResolveItem( const KIID& aID, bool aAllowNullptrReturn ) const
1775{
1776 if( aID == niluuid )
1777 return nullptr;
1778
1779 if( m_itemByIdCache.count( aID ) )
1780 return m_itemByIdCache.at( aID );
1781
1782 // Main clients include highlighting, group undo/redo and DRC items. Since
1783 // everything but group undo/redo will be spread over all object types, we
1784 // might as well prioritize group undo/redo and search them first.
1785
1786 for( PCB_GROUP* group : m_groups )
1787 {
1788 if( group->m_Uuid == aID )
1789 return group;
1790 }
1791
1792 for( PCB_GENERATOR* generator : m_generators )
1793 {
1794 if( generator->m_Uuid == aID )
1795 return generator;
1796 }
1797
1798 for( PCB_TRACK* track : Tracks() )
1799 {
1800 if( track->m_Uuid == aID )
1801 return track;
1802 }
1803
1804 for( FOOTPRINT* footprint : Footprints() )
1805 {
1806 if( footprint->m_Uuid == aID )
1807 return footprint;
1808
1809 for( PAD* pad : footprint->Pads() )
1810 {
1811 if( pad->m_Uuid == aID )
1812 return pad;
1813 }
1814
1815 for( PCB_FIELD* field : footprint->GetFields() )
1816 {
1817 if( field && field->m_Uuid == aID )
1818 return field;
1819 }
1820
1821 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1822 {
1823 if( drawing->m_Uuid == aID )
1824 return drawing;
1825 }
1826
1827 for( BOARD_ITEM* zone : footprint->Zones() )
1828 {
1829 if( zone->m_Uuid == aID )
1830 return zone;
1831 }
1832
1833 for( PCB_GROUP* group : footprint->Groups() )
1834 {
1835 if( group->m_Uuid == aID )
1836 return group;
1837 }
1838 }
1839
1840 for( ZONE* zone : Zones() )
1841 {
1842 if( zone->m_Uuid == aID )
1843 return zone;
1844 }
1845
1846 for( BOARD_ITEM* drawing : Drawings() )
1847 {
1848 if( drawing->Type() == PCB_TABLE_T )
1849 {
1850 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( drawing )->GetCells() )
1851 {
1852 if( cell->m_Uuid == aID )
1853 return drawing;
1854 }
1855 }
1856
1857 if( drawing->m_Uuid == aID )
1858 return drawing;
1859 }
1860
1861 for( PCB_MARKER* marker : m_markers )
1862 {
1863 if( marker->m_Uuid == aID )
1864 return marker;
1865 }
1866
1867 for( PCB_POINT* point : m_points )
1868 {
1869 if( point->m_Uuid == aID )
1870 return point;
1871 }
1872
1873 for( NETINFO_ITEM* netInfo : m_NetInfo )
1874 {
1875 if( netInfo->m_Uuid == aID )
1876 return netInfo;
1877 }
1878
1879 if( m_Uuid == aID )
1880 return const_cast<BOARD*>( this );
1881
1882 // Not found; weak reference has been deleted.
1883 if( aAllowNullptrReturn )
1884 return nullptr;
1885
1887}
1888
1889
1890void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1891{
1892 // the board itself
1893 aMap[m_Uuid] = this;
1894
1895 for( PCB_TRACK* track : Tracks() )
1896 aMap[track->m_Uuid] = track;
1897
1898 for( FOOTPRINT* footprint : Footprints() )
1899 {
1900 aMap[footprint->m_Uuid] = footprint;
1901
1902 for( PAD* pad : footprint->Pads() )
1903 aMap[pad->m_Uuid] = pad;
1904
1905 aMap[footprint->Reference().m_Uuid] = &footprint->Reference();
1906 aMap[footprint->Value().m_Uuid] = &footprint->Value();
1907
1908 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1909 aMap[drawing->m_Uuid] = drawing;
1910 }
1911
1912 for( ZONE* zone : Zones() )
1913 aMap[zone->m_Uuid] = zone;
1914
1915 for( BOARD_ITEM* drawing : Drawings() )
1916 aMap[drawing->m_Uuid] = drawing;
1917
1918 for( PCB_MARKER* marker : m_markers )
1919 aMap[marker->m_Uuid] = marker;
1920
1921 for( PCB_GROUP* group : m_groups )
1922 aMap[group->m_Uuid] = group;
1923
1924 for( PCB_POINT* point : m_points )
1925 aMap[point->m_Uuid] = point;
1926
1927 for( PCB_GENERATOR* generator : m_generators )
1928 aMap[generator->m_Uuid] = generator;
1929}
1930
1931
1932wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
1933{
1934 wxString newbuf;
1935 size_t sourceLen = aSource.length();
1936
1937 for( size_t i = 0; i < sourceLen; ++i )
1938 {
1939 // Check for escaped expressions: \${ or \@{
1940 // These should be copied verbatim without any ref→KIID conversion
1941 if( aSource[i] == '\\' && i + 2 < sourceLen && aSource[i + 2] == '{' &&
1942 ( aSource[i + 1] == '$' || aSource[i + 1] == '@' ) )
1943 {
1944 // Copy the escape sequence and the entire escaped expression
1945 newbuf.append( aSource[i] ); // backslash
1946 newbuf.append( aSource[i + 1] ); // $ or @
1947 newbuf.append( aSource[i + 2] ); // {
1948 i += 2;
1949
1950 // Find and copy everything until the matching closing brace
1951 int braceDepth = 1;
1952 for( i = i + 1; i < sourceLen && braceDepth > 0; ++i )
1953 {
1954 if( aSource[i] == '{' )
1955 braceDepth++;
1956 else if( aSource[i] == '}' )
1957 braceDepth--;
1958
1959 newbuf.append( aSource[i] );
1960 }
1961 i--; // Back up one since the for loop will increment
1962 continue;
1963 }
1964
1965 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' )
1966 {
1967 wxString token;
1968 bool isCrossRef = false;
1969
1970 for( i = i + 2; i < sourceLen; ++i )
1971 {
1972 if( aSource[i] == '}' )
1973 break;
1974
1975 if( aSource[i] == ':' )
1976 isCrossRef = true;
1977
1978 token.append( aSource[i] );
1979 }
1980
1981 if( isCrossRef )
1982 {
1983 wxString remainder;
1984 wxString ref = token.BeforeFirst( ':', &remainder );
1985
1986 for( const FOOTPRINT* footprint : Footprints() )
1987 {
1988 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
1989 {
1990 wxString test( remainder );
1991
1992 if( footprint->ResolveTextVar( &test ) )
1993 token = footprint->m_Uuid.AsString() + wxT( ":" ) + remainder;
1994
1995 break;
1996 }
1997 }
1998 }
1999
2000 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
2001 }
2002 else
2003 {
2004 newbuf.append( aSource[i] );
2005 }
2006 }
2007
2008 return newbuf;
2009}
2010
2011
2012wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
2013{
2014 wxString newbuf;
2015 size_t sourceLen = aSource.length();
2016
2017 for( size_t i = 0; i < sourceLen; ++i )
2018 {
2019 // Check for escaped expressions: \${ or \@{
2020 // These should be copied verbatim without any KIID→ref conversion
2021 if( aSource[i] == '\\' && i + 2 < sourceLen && aSource[i + 2] == '{' &&
2022 ( aSource[i + 1] == '$' || aSource[i + 1] == '@' ) )
2023 {
2024 // Copy the escape sequence and the entire escaped expression
2025 newbuf.append( aSource[i] ); // backslash
2026 newbuf.append( aSource[i + 1] ); // $ or @
2027 newbuf.append( aSource[i + 2] ); // {
2028 i += 2;
2029
2030 // Find and copy everything until the matching closing brace
2031 int braceDepth = 1;
2032 for( i = i + 1; i < sourceLen && braceDepth > 0; ++i )
2033 {
2034 if( aSource[i] == '{' )
2035 braceDepth++;
2036 else if( aSource[i] == '}' )
2037 braceDepth--;
2038
2039 newbuf.append( aSource[i] );
2040 }
2041 i--; // Back up one since the for loop will increment
2042 continue;
2043 }
2044
2045 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' )
2046 {
2047 wxString token;
2048 bool isCrossRef = false;
2049
2050 for( i = i + 2; i < sourceLen; ++i )
2051 {
2052 if( aSource[i] == '}' )
2053 break;
2054
2055 if( aSource[i] == ':' )
2056 isCrossRef = true;
2057
2058 token.append( aSource[i] );
2059 }
2060
2061 if( isCrossRef )
2062 {
2063 wxString remainder;
2064 wxString ref = token.BeforeFirst( ':', &remainder );
2065 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
2066
2067 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
2068 {
2069 token = static_cast<FOOTPRINT*>( refItem )->GetReference() + wxT( ":" ) + remainder;
2070 }
2071 }
2072
2073 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
2074 }
2075 else
2076 {
2077 newbuf.append( aSource[i] );
2078 }
2079 }
2080
2081 return newbuf;
2082}
2083
2084
2085unsigned BOARD::GetNodesCount( int aNet ) const
2086{
2087 unsigned retval = 0;
2088
2089 for( FOOTPRINT* footprint : Footprints() )
2090 {
2091 for( PAD* pad : footprint->Pads() )
2092 {
2093 if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
2094 retval++;
2095 }
2096 }
2097
2098 return retval;
2099}
2100
2101
2102BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
2103{
2104 BOX2I bbox;
2105 LSET visible = GetVisibleLayers();
2106
2107 // If the board is just showing a footprint, we want all footprint layers included in the
2108 // bounding box
2109 if( IsFootprintHolder() )
2110 visible.set();
2111
2112 if( aBoardEdgesOnly )
2113 visible.set( Edge_Cuts );
2114
2115 // Check shapes, dimensions, texts, and fiducials
2116 for( BOARD_ITEM* item : m_drawings )
2117 {
2118 if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
2119 continue;
2120
2121 if( ( item->GetLayerSet() & visible ).any() )
2122 bbox.Merge( item->GetBoundingBox() );
2123 }
2124
2125 // Check footprints
2126 for( FOOTPRINT* footprint : m_footprints )
2127 {
2128 if( aBoardEdgesOnly )
2129 {
2130 for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
2131 {
2132 if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_SHAPE_T )
2133 bbox.Merge( edge->GetBoundingBox() );
2134 }
2135 }
2136 else if( ( footprint->GetLayerSet() & visible ).any() )
2137 {
2138 bbox.Merge( footprint->GetBoundingBox( true ) );
2139 }
2140 }
2141
2142 if( !aBoardEdgesOnly )
2143 {
2144 // Check tracks
2145 for( PCB_TRACK* track : m_tracks )
2146 {
2147 if( ( track->GetLayerSet() & visible ).any() )
2148 bbox.Merge( track->GetBoundingBox() );
2149 }
2150
2151 // Check zones
2152 for( ZONE* aZone : m_zones )
2153 {
2154 if( ( aZone->GetLayerSet() & visible ).any() )
2155 bbox.Merge( aZone->GetBoundingBox() );
2156 }
2157
2158 for( PCB_POINT* point : m_points )
2159 {
2160 bbox.Merge( point->GetBoundingBox() );
2161 }
2162 }
2163
2164 return bbox;
2165}
2166
2167
2168void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2169{
2170 int padCount = 0;
2171 int viaCount = 0;
2172 int trackSegmentCount = 0;
2173 std::set<int> netCodes;
2174 int unconnected = GetConnectivity()->GetUnconnectedCount( true );
2175
2176 for( PCB_TRACK* item : m_tracks )
2177 {
2178 if( item->Type() == PCB_VIA_T )
2179 viaCount++;
2180 else
2181 trackSegmentCount++;
2182
2183 if( item->GetNetCode() > 0 )
2184 netCodes.insert( item->GetNetCode() );
2185 }
2186
2187 for( FOOTPRINT* footprint : Footprints() )
2188 {
2189 for( PAD* pad : footprint->Pads() )
2190 {
2191 padCount++;
2192
2193 if( pad->GetNetCode() > 0 )
2194 netCodes.insert( pad->GetNetCode() );
2195 }
2196 }
2197
2198 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%d" ), padCount ) );
2199 aList.emplace_back( _( "Vias" ), wxString::Format( wxT( "%d" ), viaCount ) );
2200 aList.emplace_back( _( "Track Segments" ), wxString::Format( wxT( "%d" ), trackSegmentCount ) );
2201 aList.emplace_back( _( "Nets" ), wxString::Format( wxT( "%d" ), (int) netCodes.size() ) );
2202 aList.emplace_back( _( "Unrouted" ), wxString::Format( wxT( "%d" ), unconnected ) );
2203}
2204
2205
2206INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const std::vector<KICAD_T>& scanTypes )
2207{
2208#if 0 && defined( DEBUG )
2209 std::cout << GetClass().mb_str() << ' ';
2210#endif
2211
2212 bool footprintsScanned = false;
2213 bool drawingsScanned = false;
2214 bool tracksScanned = false;
2215
2216 for( KICAD_T scanType : scanTypes )
2217 {
2218 switch( scanType )
2219 {
2220 case PCB_T:
2221 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
2222 return INSPECT_RESULT::QUIT;
2223
2224 break;
2225
2226 /*
2227 * Instances of the requested KICAD_T live in a list, either one that I manage, or one
2228 * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
2229 * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
2230 */
2231
2232 case PCB_FOOTPRINT_T:
2233 case PCB_PAD_T:
2234 case PCB_SHAPE_T:
2236 case PCB_FIELD_T:
2237 case PCB_TEXT_T:
2238 case PCB_TEXTBOX_T:
2239 case PCB_TABLE_T:
2240 case PCB_TABLECELL_T:
2241 case PCB_DIM_ALIGNED_T:
2242 case PCB_DIM_CENTER_T:
2243 case PCB_DIM_RADIAL_T:
2245 case PCB_DIM_LEADER_T:
2246 case PCB_TARGET_T:
2247 case PCB_BARCODE_T:
2248 if( !footprintsScanned )
2249 {
2250 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2251 {
2252 return INSPECT_RESULT::QUIT;
2253 }
2254
2255 footprintsScanned = true;
2256 }
2257
2258 if( !drawingsScanned )
2259 {
2260 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2261 {
2262 return INSPECT_RESULT::QUIT;
2263 }
2264
2265 drawingsScanned = true;
2266 }
2267
2268 break;
2269
2270 case PCB_VIA_T:
2271 case PCB_TRACE_T:
2272 case PCB_ARC_T:
2273 if( !tracksScanned )
2274 {
2275 if( IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2276 {
2277 return INSPECT_RESULT::QUIT;
2278 }
2279
2280 tracksScanned = true;
2281 }
2282
2283 break;
2284
2285 case PCB_MARKER_T:
2286 for( PCB_MARKER* marker : m_markers )
2287 {
2288 if( marker->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2289 return INSPECT_RESULT::QUIT;
2290 }
2291
2292 break;
2293
2294 case PCB_POINT_T:
2295 for( PCB_POINT* point : m_points )
2296 {
2297 if( point->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2298 return INSPECT_RESULT::QUIT;
2299 }
2300
2301 break;
2302
2303 case PCB_ZONE_T:
2304 if( !footprintsScanned )
2305 {
2306 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2307 {
2308 return INSPECT_RESULT::QUIT;
2309 }
2310
2311 footprintsScanned = true;
2312 }
2313
2314 for( ZONE* zone : m_zones )
2315 {
2316 if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2317 return INSPECT_RESULT::QUIT;
2318 }
2319
2320 break;
2321
2322 case PCB_GENERATOR_T:
2323 if( !footprintsScanned )
2324 {
2325 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2326 {
2327 return INSPECT_RESULT::QUIT;
2328 }
2329
2330 footprintsScanned = true;
2331 }
2332
2333 if( IterateForward<PCB_GENERATOR*>( m_generators, inspector, testData, { scanType } )
2335 {
2336 return INSPECT_RESULT::QUIT;
2337 }
2338
2339 break;
2340
2341 case PCB_GROUP_T:
2342 if( IterateForward<PCB_GROUP*>( m_groups, inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2343 {
2344 return INSPECT_RESULT::QUIT;
2345 }
2346
2347 break;
2348
2349 default: break;
2350 }
2351 }
2352
2354}
2355
2356
2357NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
2358{
2359 // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
2360 // zero is reserved for "no connection" and is not actually a net.
2361 // nullptr is returned for non valid netcodes
2362
2363 if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
2365 else
2366 return m_NetInfo.GetNetItem( aNetcode );
2367}
2368
2369
2370NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
2371{
2372 return m_NetInfo.GetNetItem( aNetname );
2373}
2374
2375
2376int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
2377{
2378 int rv = 0;
2379 int count = 0;
2380
2381 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2382 {
2383 int ch = *it;
2384
2385 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
2386 {
2387 continue;
2388 }
2389 else if( ch == '+' )
2390 {
2391 aComplementNet = wxT( "-" );
2392 rv = 1;
2393 }
2394 else if( ch == '-' )
2395 {
2396 aComplementNet = wxT( "+" );
2397 rv = -1;
2398 }
2399 else if( ch == 'N' )
2400 {
2401 aComplementNet = wxT( "P" );
2402 rv = -1;
2403 }
2404 else if( ch == 'P' )
2405 {
2406 aComplementNet = wxT( "N" );
2407 rv = 1;
2408 }
2409 else
2410 {
2411 break;
2412 }
2413 }
2414
2415 if( rv != 0 && count >= 1 )
2416 {
2417 aComplementNet = aNetName.Left( aNetName.length() - count ) + aComplementNet + aNetName.Right( count - 1 );
2418 }
2419
2420 return rv;
2421}
2422
2423
2425{
2426 if( aNet )
2427 {
2428 wxString refName = aNet->GetNetname();
2429 wxString coupledNetName;
2430
2431 if( MatchDpSuffix( refName, coupledNetName ) )
2432 return FindNet( coupledNetName );
2433 }
2434
2435 return nullptr;
2436}
2437
2438
2439FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
2440{
2441 for( FOOTPRINT* footprint : m_footprints )
2442 {
2443 if( aReference == footprint->GetReference() )
2444 return footprint;
2445 }
2446
2447 return nullptr;
2448}
2449
2450
2452{
2453 for( FOOTPRINT* footprint : m_footprints )
2454 {
2455 if( footprint->GetPath() == aPath )
2456 return footprint;
2457 }
2458
2459 return nullptr;
2460}
2461
2462
2464{
2465 std::set<wxString> names;
2466
2467 for( const NETINFO_ITEM* net : m_NetInfo )
2468 {
2469 if( !net->GetNetname().IsEmpty() )
2470 names.insert( net->GetNetname() );
2471 }
2472
2473 return names;
2474}
2475
2476
2478{
2479 if( m_project && !m_project->IsNullProject() )
2480 SetProperties( m_project->GetTextVars() );
2481}
2482
2483
2484static wxString FindVariantNameCaseInsensitive( const std::vector<wxString>& aNames,
2485 const wxString& aVariantName )
2486{
2487 for( const wxString& name : aNames )
2488 {
2489 if( name.CmpNoCase( aVariantName ) == 0 )
2490 return name;
2491 }
2492
2493 return wxEmptyString;
2494}
2495
2496
2497void BOARD::SetCurrentVariant( const wxString& aVariant )
2498{
2499 if( aVariant.IsEmpty() || aVariant.CmpNoCase( GetDefaultVariantName() ) == 0 )
2500 {
2501 m_currentVariant.Clear();
2502 return;
2503 }
2504
2505 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariant );
2506
2507 if( actualName.IsEmpty() )
2508 m_currentVariant.Clear();
2509 else
2510 m_currentVariant = actualName;
2511}
2512
2513
2514bool BOARD::HasVariant( const wxString& aVariantName ) const
2515{
2516 return !FindVariantNameCaseInsensitive( m_variantNames, aVariantName ).IsEmpty();
2517}
2518
2519
2520void BOARD::AddVariant( const wxString& aVariantName )
2521{
2522 if( aVariantName.IsEmpty()
2523 || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0
2524 || HasVariant( aVariantName ) )
2525 return;
2526
2527 m_variantNames.push_back( aVariantName );
2528}
2529
2530
2531void BOARD::DeleteVariant( const wxString& aVariantName )
2532{
2533 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
2534 return;
2535
2536 auto it = std::find_if( m_variantNames.begin(), m_variantNames.end(),
2537 [&]( const wxString& name )
2538 {
2539 return name.CmpNoCase( aVariantName ) == 0;
2540 } );
2541
2542 if( it != m_variantNames.end() )
2543 {
2544 wxString actualName = *it;
2545 m_variantNames.erase( it );
2546 m_variantDescriptions.erase( actualName );
2547
2548 // Clear current variant if it was the deleted one
2549 if( m_currentVariant.CmpNoCase( aVariantName ) == 0 )
2550 m_currentVariant.Clear();
2551
2552 // Remove variant from all footprints
2553 for( FOOTPRINT* fp : m_footprints )
2554 fp->DeleteVariant( actualName );
2555 }
2556}
2557
2558
2559void BOARD::RenameVariant( const wxString& aOldName, const wxString& aNewName )
2560{
2561 if( aNewName.IsEmpty() || aNewName.CmpNoCase( GetDefaultVariantName() ) == 0 )
2562 return;
2563
2564 auto it = std::find_if( m_variantNames.begin(), m_variantNames.end(),
2565 [&]( const wxString& name )
2566 {
2567 return name.CmpNoCase( aOldName ) == 0;
2568 } );
2569
2570 if( it != m_variantNames.end() )
2571 {
2572 wxString actualOldName = *it;
2573
2574 // Check if new name already exists (case-insensitive) and isn't the same variant
2575 wxString existingName = FindVariantNameCaseInsensitive( m_variantNames, aNewName );
2576
2577 if( !existingName.IsEmpty() && existingName.CmpNoCase( actualOldName ) != 0 )
2578 return;
2579
2580 if( actualOldName == aNewName )
2581 return;
2582
2583 *it = aNewName;
2584
2585 // Transfer description
2586 auto descIt = m_variantDescriptions.find( actualOldName );
2587
2588 if( descIt != m_variantDescriptions.end() )
2589 {
2590 if( !descIt->second.IsEmpty() )
2591 m_variantDescriptions[aNewName] = descIt->second;
2592
2593 m_variantDescriptions.erase( descIt );
2594 }
2595
2596 // Update current variant if it was the renamed one
2597 if( m_currentVariant.CmpNoCase( aOldName ) == 0 )
2598 m_currentVariant = aNewName;
2599
2600 // Rename variant in all footprints
2601 for( FOOTPRINT* fp : m_footprints )
2602 fp->RenameVariant( actualOldName, aNewName );
2603 }
2604}
2605
2606
2607wxString BOARD::GetVariantDescription( const wxString& aVariantName ) const
2608{
2609 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
2610 return wxEmptyString;
2611
2612 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariantName );
2613
2614 if( actualName.IsEmpty() )
2615 return wxEmptyString;
2616
2617 auto it = m_variantDescriptions.find( actualName );
2618
2619 if( it != m_variantDescriptions.end() )
2620 return it->second;
2621
2622 return wxEmptyString;
2623}
2624
2625
2626void BOARD::SetVariantDescription( const wxString& aVariantName, const wxString& aDescription )
2627{
2628 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
2629 return;
2630
2631 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariantName );
2632
2633 if( actualName.IsEmpty() )
2634 return;
2635
2636 if( aDescription.IsEmpty() )
2637 m_variantDescriptions.erase( actualName );
2638 else
2639 m_variantDescriptions[actualName] = aDescription;
2640}
2641
2642
2643wxArrayString BOARD::GetVariantNamesForUI() const
2644{
2645 wxArrayString names;
2646 names.Add( GetDefaultVariantName() );
2647
2648 for( const wxString& name : m_variantNames )
2649 names.Add( name );
2650
2651 names.Sort( SortVariantNames );
2652
2653 return names;
2654}
2655
2656
2658{
2659 m_lengthDelayCalc->SynchronizeTuningProfileProperties();
2660}
2661
2662
2663void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
2664{
2665 if( !m_project )
2666 return;
2667
2669 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass();
2670
2672
2673 for( NETINFO_ITEM* net : m_NetInfo )
2674 net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) );
2675
2676 if( aResetTrackAndViaSizes )
2677 {
2678 // Set initial values for custom track width & via size to match the default
2679 // netclass settings
2680 bds.UseCustomTrackViaSize( false );
2681 bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
2682 bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
2683 bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
2684 bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
2685 bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
2686 bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
2687 }
2688
2690}
2691
2692
2693bool BOARD::SynchronizeComponentClasses( const std::unordered_set<wxString>& aNewSheetPaths ) const
2694{
2695 std::shared_ptr<COMPONENT_CLASS_SETTINGS> settings = GetProject()->GetProjectFile().ComponentClassSettings();
2696
2697 return m_componentClassManager->SyncDynamicComponentClassAssignments(
2698 settings->GetComponentClassAssignments(), settings->GetEnableSheetComponentClasses(), aNewSheetPaths );
2699}
2700
2701
2703{
2704 int error_count = 0;
2705
2706 for( ZONE* zone : Zones() )
2707 {
2708 if( !zone->IsOnCopperLayer() )
2709 {
2710 zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
2711 continue;
2712 }
2713
2714 if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
2715 {
2716 const NETINFO_ITEM* net = zone->GetNet();
2717
2718 if( net )
2719 {
2720 zone->SetNetCode( net->GetNetCode() );
2721 }
2722 else
2723 {
2724 error_count++;
2725
2726 // keep Net Name and set m_NetCode to -1 : error flag.
2727 zone->SetNetCode( -1 );
2728 }
2729 }
2730 }
2731
2732 return error_count;
2733}
2734
2735
2736PAD* BOARD::GetPad( const VECTOR2I& aPosition, const LSET& aLayerSet ) const
2737{
2738 for( FOOTPRINT* footprint : m_footprints )
2739 {
2740 PAD* pad = nullptr;
2741
2742 if( footprint->HitTest( aPosition ) )
2743 pad = footprint->GetPad( aPosition, aLayerSet.any() ? aLayerSet : LSET::AllCuMask() );
2744
2745 if( pad )
2746 return pad;
2747 }
2748
2749 return nullptr;
2750}
2751
2752
2753PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
2754{
2755 const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
2756
2757 LSET lset( { aTrace->GetLayer() } );
2758
2759 return GetPad( aPosition, lset );
2760}
2761
2762
2763PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, const LSET& aLayerSet ) const
2764{
2765 // Search aPadList for aPosition
2766 // aPadList is sorted by X then Y values, and a fast binary search is used
2767 int idxmax = aPadList.size() - 1;
2768
2769 int delta = aPadList.size();
2770
2771 int idx = 0; // Starting index is the beginning of list
2772
2773 while( delta )
2774 {
2775 // Calculate half size of remaining interval to test.
2776 // Ensure the computed value is not truncated (too small)
2777 if( ( delta & 1 ) && ( delta > 1 ) )
2778 delta++;
2779
2780 delta /= 2;
2781
2782 PAD* pad = aPadList[idx];
2783
2784 if( pad->GetPosition() == aPosition ) // candidate found
2785 {
2786 // The pad must match the layer mask:
2787 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2788 return pad;
2789
2790 // More than one pad can be at aPosition
2791 // search for a pad at aPosition that matched this mask
2792
2793 // search next
2794 for( int ii = idx + 1; ii <= idxmax; ii++ )
2795 {
2796 pad = aPadList[ii];
2797
2798 if( pad->GetPosition() != aPosition )
2799 break;
2800
2801 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2802 return pad;
2803 }
2804 // search previous
2805 for( int ii = idx - 1; ii >= 0; ii-- )
2806 {
2807 pad = aPadList[ii];
2808
2809 if( pad->GetPosition() != aPosition )
2810 break;
2811
2812 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2813 return pad;
2814 }
2815
2816 // Not found:
2817 return nullptr;
2818 }
2819
2820 if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
2821 {
2822 if( pad->GetPosition().y < aPosition.y ) // Must search after this item
2823 {
2824 idx += delta;
2825
2826 if( idx > idxmax )
2827 idx = idxmax;
2828 }
2829 else // Must search before this item
2830 {
2831 idx -= delta;
2832
2833 if( idx < 0 )
2834 idx = 0;
2835 }
2836 }
2837 else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
2838 {
2839 idx += delta;
2840
2841 if( idx > idxmax )
2842 idx = idxmax;
2843 }
2844 else // Must search before this item
2845 {
2846 idx -= delta;
2847
2848 if( idx < 0 )
2849 idx = 0;
2850 }
2851 }
2852
2853 return nullptr;
2854}
2855
2856
2862bool sortPadsByXthenYCoord( PAD* const& aLH, PAD* const& aRH )
2863{
2864 if( aLH->GetPosition().x == aRH->GetPosition().x )
2865 return aLH->GetPosition().y < aRH->GetPosition().y;
2866
2867 return aLH->GetPosition().x < aRH->GetPosition().x;
2868}
2869
2870
2871void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
2872{
2873 for( FOOTPRINT* footprint : Footprints() )
2874 {
2875 for( PAD* pad : footprint->Pads() )
2876 {
2877 if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
2878 aVector.push_back( pad );
2879 }
2880 }
2881
2882 std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
2883}
2884
2885
2887{
2888 if( GetDesignSettings().m_HasStackup )
2890
2891 BOARD_STACKUP stackup;
2893 return stackup;
2894}
2895
2896
2897std::tuple<int, double, double, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
2898{
2899 std::shared_ptr<CONNECTIVITY_DATA> connectivity = GetBoard()->GetConnectivity();
2900 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items;
2901
2902 for( BOARD_CONNECTED_ITEM* boardItem : connectivity->GetConnectedItems( &aTrack, EXCLUDE_ZONES ) )
2903 {
2905
2906 if( item.Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
2907 items.push_back( std::move( item ) );
2908 }
2909
2910 constexpr PATH_OPTIMISATIONS opts = {
2911 .OptimiseViaLayers = true, .MergeTracks = true, .OptimiseTracesInPads = true, .InferViaInPad = false
2912 };
2914 items, opts, nullptr, nullptr, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
2916
2917 return std::make_tuple( items.size(), details.TrackLength + details.ViaLength, details.PadToDieLength,
2918 details.TrackDelay + details.ViaDelay, details.PadToDieDelay );
2919}
2920
2921
2922FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly,
2923 bool aIgnoreLocked ) const
2924{
2925 FOOTPRINT* footprint = nullptr;
2926 FOOTPRINT* alt_footprint = nullptr;
2927 int min_dim = 0x7FFFFFFF;
2928 int alt_min_dim = 0x7FFFFFFF;
2929 bool current_layer_back = IsBackLayer( aActiveLayer );
2930
2931 for( FOOTPRINT* candidate : m_footprints )
2932 {
2933 // is the ref point within the footprint's bounds?
2934 if( !candidate->HitTest( aPosition ) )
2935 continue;
2936
2937 // if caller wants to ignore locked footprints, and this one is locked, skip it.
2938 if( aIgnoreLocked && candidate->IsLocked() )
2939 continue;
2940
2941 PCB_LAYER_ID layer = candidate->GetLayer();
2942
2943 // Filter non visible footprints if requested
2944 if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
2945 {
2946 BOX2I bb = candidate->GetBoundingBox( false );
2947
2948 int offx = bb.GetX() + bb.GetWidth() / 2;
2949 int offy = bb.GetY() + bb.GetHeight() / 2;
2950
2951 // off x & offy point to the middle of the box.
2952 int dist =
2953 ( aPosition.x - offx ) * ( aPosition.x - offx ) + ( aPosition.y - offy ) * ( aPosition.y - offy );
2954
2955 if( current_layer_back == IsBackLayer( layer ) )
2956 {
2957 if( dist <= min_dim )
2958 {
2959 // better footprint shown on the active side
2960 footprint = candidate;
2961 min_dim = dist;
2962 }
2963 }
2964 else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
2965 {
2966 if( dist <= alt_min_dim )
2967 {
2968 // better footprint shown on the other side
2969 alt_footprint = candidate;
2970 alt_min_dim = dist;
2971 }
2972 }
2973 }
2974 }
2975
2976 if( footprint )
2977 return footprint;
2978
2979 if( alt_footprint )
2980 return alt_footprint;
2981
2982 return nullptr;
2983}
2984
2985
2986std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
2987{
2988 std::list<ZONE*> zones;
2989
2990 for( ZONE* zone : Zones() )
2991 zones.push_back( zone );
2992
2993 if( aIncludeZonesInFootprints )
2994 {
2995 for( FOOTPRINT* footprint : m_footprints )
2996 {
2997 for( ZONE* zone : footprint->Zones() )
2998 zones.push_back( zone );
2999 }
3000 }
3001
3002 return zones;
3003}
3004
3005
3006ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, VECTOR2I aStartPointPosition,
3008{
3009 ZONE* new_area = new ZONE( this );
3010
3011 new_area->SetNetCode( aNetcode );
3012 new_area->SetLayer( aLayer );
3013
3014 m_zones.push_back( new_area );
3015
3016 new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
3017
3018 // Add the first corner to the new zone
3019 new_area->AppendCorner( aStartPointPosition, -1 );
3020
3021 if( aNewZonesList )
3022 {
3023 ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
3024 aNewZonesList->PushItem( picker );
3025 }
3026
3027 return new_area;
3028}
3029
3030
3031bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, bool aInferOutlineIfNecessary,
3032 OUTLINE_ERROR_HANDLER* aErrorHandler, bool aAllowUseArcsInPolygons,
3033 bool aIncludeNPTHAsOutlines )
3034{
3035 // max dist from one endPt to next startPt: use the current value
3036 int chainingEpsilon = GetOutlinesChainingEpsilon();
3037
3038 bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError, chainingEpsilon,
3039 aInferOutlineIfNecessary, aErrorHandler, aAllowUseArcsInPolygons );
3040
3041 // Now add NPTH oval holes as holes in outlines if required
3042 if( aIncludeNPTHAsOutlines )
3043 {
3044 for( FOOTPRINT* fp : Footprints() )
3045 {
3046 for( PAD* pad : fp->Pads() )
3047 {
3048 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
3049 continue;
3050
3051 SHAPE_POLY_SET hole;
3052 pad->TransformHoleToPolygon( hole, 0, pad->GetMaxError(), ERROR_INSIDE );
3053
3054 if( hole.OutlineCount() > 0 ) // can be not the case for malformed NPTH holes
3055 {
3056 // Add this pad hole to the main outline
3057 // But we can have more than one main outline (i.e. more than one board), so
3058 // search the right main outline i.e. the outline that contains the pad hole
3059 SHAPE_LINE_CHAIN& pad_hole = hole.Outline( 0 );
3060 const VECTOR2I holePt = pad_hole.CPoint( 0 );
3061
3062 for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj )
3063 {
3064 if( aOutlines.Outline( jj ).PointInside( holePt ) )
3065 {
3066 aOutlines.AddHole( pad_hole, jj );
3067 break;
3068 }
3069 }
3070 }
3071 }
3072 }
3073 }
3074
3075 // Make polygon strictly simple to avoid issues (especially in 3D viewer)
3076 aOutlines.Simplify();
3077
3078 return success;
3079}
3080
3081
3083{
3085 return static_cast<EMBEDDED_FILES*>( m_embeddedFilesDelegate );
3086
3087 return static_cast<EMBEDDED_FILES*>( this );
3088}
3089
3090
3092{
3094 return static_cast<const EMBEDDED_FILES*>( m_embeddedFilesDelegate );
3095
3096 return static_cast<const EMBEDDED_FILES*>( this );
3097}
3098
3099
3100std::set<KIFONT::OUTLINE_FONT*> BOARD::GetFonts() const
3101{
3103
3104 std::set<KIFONT::OUTLINE_FONT*> fonts;
3105
3106 for( BOARD_ITEM* item : Drawings() )
3107 {
3108 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
3109 {
3110 KIFONT::FONT* font = text->GetFont();
3111
3112 if( font && font->IsOutline() )
3113 {
3114 KIFONT::OUTLINE_FONT* outlineFont = static_cast<KIFONT::OUTLINE_FONT*>( font );
3115 PERMISSION permission = outlineFont->GetEmbeddingPermission();
3116
3117 if( permission == PERMISSION::EDITABLE || permission == PERMISSION::INSTALLABLE )
3118 fonts.insert( outlineFont );
3119 }
3120 }
3121 }
3122
3123 return fonts;
3124}
3125
3126
3128{
3129 for( KIFONT::OUTLINE_FONT* font : GetFonts() )
3130 {
3131 EMBEDDED_FILES::EMBEDDED_FILE* file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
3133 }
3134}
3135
3136
3137const std::vector<PAD*> BOARD::GetPads() const
3138{
3139 std::vector<PAD*> allPads;
3140
3141 for( FOOTPRINT* footprint : Footprints() )
3142 {
3143 for( PAD* pad : footprint->Pads() )
3144 allPads.push_back( pad );
3145 }
3146
3147 return allPads;
3148}
3149
3150
3151const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
3152{
3153 std::vector<BOARD_CONNECTED_ITEM*> items;
3154
3155 for( PCB_TRACK* track : Tracks() )
3156 items.push_back( track );
3157
3158 for( FOOTPRINT* footprint : Footprints() )
3159 {
3160 for( PAD* pad : footprint->Pads() )
3161 items.push_back( pad );
3162 }
3163
3164 for( ZONE* zone : Zones() )
3165 items.push_back( zone );
3166
3167 for( BOARD_ITEM* item : Drawings() )
3168 {
3169 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
3170 items.push_back( bci );
3171 }
3172
3173 return items;
3174}
3175
3176
3177void BOARD::MapNets( BOARD* aDestBoard )
3178{
3180 {
3181 NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
3182
3183 if( netInfo )
3184 item->SetNet( netInfo );
3185 else
3186 {
3187 NETINFO_ITEM* newNet = new NETINFO_ITEM( aDestBoard, item->GetNetname() );
3188 aDestBoard->Add( newNet );
3189 item->SetNet( newNet );
3190 }
3191 }
3192}
3193
3194
3196{
3198 {
3199 if( FindNet( item->GetNetCode() ) == nullptr )
3200 item->SetNetCode( NETINFO_LIST::ORPHANED );
3201 }
3202}
3203
3204
3206{
3207 if( !alg::contains( m_listeners, aListener ) )
3208 m_listeners.push_back( aListener );
3209}
3210
3211
3213{
3214 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
3215
3216 if( i != m_listeners.end() )
3217 {
3218 std::iter_swap( i, m_listeners.end() - 1 );
3219 m_listeners.pop_back();
3220 }
3221}
3222
3223
3225{
3226 m_listeners.clear();
3227}
3228
3229
3234
3235
3236void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
3237{
3239}
3240
3241
3242void BOARD::OnItemsCompositeUpdate( std::vector<BOARD_ITEM*>& aAddedItems, std::vector<BOARD_ITEM*>& aRemovedItems,
3243 std::vector<BOARD_ITEM*>& aChangedItems )
3244{
3245 InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems, aChangedItems );
3246}
3247
3248
3253
3254
3262
3263
3264void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
3265{
3266 if( !m_highLight.m_netCodes.count( aNetCode ) )
3267 {
3268 if( !aMulti )
3269 m_highLight.m_netCodes.clear();
3270
3271 m_highLight.m_netCodes.insert( aNetCode );
3273 }
3274}
3275
3276
3277void BOARD::HighLightON( bool aValue )
3278{
3279 if( m_highLight.m_highLightOn != aValue )
3280 {
3281 m_highLight.m_highLightOn = aValue;
3283 }
3284}
3285
3286
3287wxString BOARD::GroupsSanityCheck( bool repair )
3288{
3289 if( repair )
3290 {
3291 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
3292 {
3293 };
3294
3295 return wxEmptyString;
3296 }
3297 return GroupsSanityCheckInternal( repair );
3298}
3299
3300
3302{
3303 // Cycle detection
3304 //
3305 // Each group has at most one parent group.
3306 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
3307 // If we ever see a group that we've already marked, that's a cycle.
3308 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
3309 //
3310 // Algorithm below is linear in the # of groups because each group is visited only once.
3311 // There may be extra time taken due to the container access calls and iterators.
3312 //
3313 // Groups we know are cycle free
3314 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
3315 // Groups in the current chain we're exploring.
3316 std::unordered_set<EDA_GROUP*> currentChainGroups;
3317 // Groups we haven't checked yet.
3318 std::unordered_set<EDA_GROUP*> toCheckGroups;
3319
3320 // Initialize set of groups and generators to check that could participate in a cycle.
3321 for( PCB_GROUP* group : Groups() )
3322 toCheckGroups.insert( group );
3323
3324 for( PCB_GENERATOR* gen : Generators() )
3325 toCheckGroups.insert( gen );
3326
3327 while( !toCheckGroups.empty() )
3328 {
3329 currentChainGroups.clear();
3330 EDA_GROUP* group = *toCheckGroups.begin();
3331
3332 while( true )
3333 {
3334 if( currentChainGroups.find( group ) != currentChainGroups.end() )
3335 {
3336 if( repair )
3337 Remove( static_cast<BOARD_ITEM*>( group->AsEdaItem() ) );
3338
3339 return "Cycle detected in group membership";
3340 }
3341 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
3342 {
3343 // Parent is a group we know does not lead to a cycle
3344 break;
3345 }
3346
3347 currentChainGroups.insert( group );
3348 // We haven't visited currIdx yet, so it must be in toCheckGroups
3349 toCheckGroups.erase( group );
3350
3351 group = group->AsEdaItem()->GetParentGroup();
3352
3353 if( !group )
3354 {
3355 // end of chain and no cycles found in this chain
3356 break;
3357 }
3358 }
3359
3360 // No cycles found in chain, so add it to set of groups we know don't participate
3361 // in a cycle.
3362 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
3363 }
3364
3365 // Success
3366 return "";
3367}
3368
3369
3371{
3372 if( a->Type() != b->Type() )
3373 return a->Type() < b->Type();
3374
3375 if( a->GetLayer() != b->GetLayer() )
3376 return a->GetLayer() < b->GetLayer();
3377
3378 if( a->GetPosition().x != b->GetPosition().x )
3379 return a->GetPosition().x < b->GetPosition().x;
3380
3381 if( a->GetPosition().y != b->GetPosition().y )
3382 return a->GetPosition().y < b->GetPosition().y;
3383
3384 if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards
3385 return a->m_Uuid < b->m_Uuid;
3386
3387 return a < b;
3388}
3389
3390
3391bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const
3392{
3393 if( aFirst->Type() != aSecond->Type() )
3394 return aFirst->Type() < aSecond->Type();
3395
3396 if( aFirst->GetLayer() != aSecond->GetLayer() )
3397 return aFirst->GetLayer() < aSecond->GetLayer();
3398
3399 if( aFirst->Type() == PCB_SHAPE_T )
3400 {
3401 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aFirst );
3402 const PCB_SHAPE* other = static_cast<const PCB_SHAPE*>( aSecond );
3403 return shape->Compare( other );
3404 }
3405 else if( aFirst->Type() == PCB_TEXT_T || aFirst->Type() == PCB_FIELD_T )
3406 {
3407 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aFirst );
3408 const PCB_TEXT* other = static_cast<const PCB_TEXT*>( aSecond );
3409 return text->Compare( other );
3410 }
3411 else if( aFirst->Type() == PCB_TEXTBOX_T )
3412 {
3413 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aFirst );
3414 const PCB_TEXTBOX* other = static_cast<const PCB_TEXTBOX*>( aSecond );
3415
3416 return textbox->PCB_SHAPE::Compare( other ) && textbox->EDA_TEXT::Compare( other );
3417 }
3418 else if( aFirst->Type() == PCB_TABLE_T )
3419 {
3420 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aFirst );
3421 const PCB_TABLE* other = static_cast<const PCB_TABLE*>( aSecond );
3422
3423 return PCB_TABLE::Compare( table, other );
3424 }
3425 else if( aFirst->Type() == PCB_BARCODE_T )
3426 {
3427 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( aFirst );
3428 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( aSecond );
3429
3430 return PCB_BARCODE::Compare( barcode, other );
3431 }
3432
3433 return aFirst->m_Uuid < aSecond->m_Uuid;
3434}
3435
3436
3438 KIGFX::RENDER_SETTINGS* aRenderSettings ) const
3439{
3440 int maxError = GetDesignSettings().m_MaxError;
3441
3442 // convert tracks and vias:
3443 for( const PCB_TRACK* track : m_tracks )
3444 {
3445 if( !track->IsOnLayer( aLayer ) )
3446 continue;
3447
3448 track->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3449 }
3450
3451 // convert pads and other copper items in footprints
3452 for( const FOOTPRINT* footprint : m_footprints )
3453 {
3454 footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3455
3456 footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE, true, /* include text */
3457 true, /* include shapes */
3458 false /* include private items */ );
3459
3460 for( const ZONE* zone : footprint->Zones() )
3461 {
3462 if( zone->GetLayerSet().test( aLayer ) )
3463 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
3464 }
3465 }
3466
3467 // convert copper zones
3468 for( const ZONE* zone : Zones() )
3469 {
3470 if( zone->GetLayerSet().test( aLayer ) )
3471 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
3472 }
3473
3474 // convert graphic items on copper layers (texts)
3475 for( const BOARD_ITEM* item : m_drawings )
3476 {
3477 if( !item->IsOnLayer( aLayer ) )
3478 continue;
3479
3480 switch( item->Type() )
3481 {
3482 case PCB_SHAPE_T:
3483 {
3484 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
3485 shape->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3486 break;
3487 }
3488
3489 case PCB_BARCODE_T:
3490 {
3491 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( item );
3492 barcode->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3493 break;
3494 }
3495
3496 case PCB_FIELD_T:
3497 case PCB_TEXT_T:
3498 {
3499 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
3500 text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3501 break;
3502 }
3503
3504 case PCB_TEXTBOX_T:
3505 {
3506 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
3507 // border
3508 textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3509 // text
3510 textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3511 break;
3512 }
3513
3514 case PCB_TABLE_T:
3515 {
3516 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
3517 table->TransformGraphicItemsToPolySet( aOutlines, maxError, ERROR_INSIDE, aRenderSettings );
3518 break;
3519 }
3520
3521 case PCB_DIM_ALIGNED_T:
3522 case PCB_DIM_CENTER_T:
3523 case PCB_DIM_RADIAL_T:
3525 case PCB_DIM_LEADER_T:
3526 {
3527 const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
3528 dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
3529 dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
3530 break;
3531 }
3532
3533 default: break;
3534 }
3535 }
3536}
3537
3538
3540{
3541 BOARD_ITEM_SET items;
3542
3543 std::copy( m_tracks.begin(), m_tracks.end(), std::inserter( items, items.end() ) );
3544 std::copy( m_zones.begin(), m_zones.end(), std::inserter( items, items.end() ) );
3545 std::copy( m_footprints.begin(), m_footprints.end(), std::inserter( items, items.end() ) );
3546 std::copy( m_drawings.begin(), m_drawings.end(), std::inserter( items, items.end() ) );
3547 std::copy( m_markers.begin(), m_markers.end(), std::inserter( items, items.end() ) );
3548 std::copy( m_groups.begin(), m_groups.end(), std::inserter( items, items.end() ) );
3549 std::copy( m_points.begin(), m_points.end(), std::inserter( items, items.end() ) );
3550
3551 return items;
3552}
3553
3554
3555bool BOARD::operator==( const BOARD_ITEM& aItem ) const
3556{
3557 if( aItem.Type() != Type() )
3558 return false;
3559
3560 const BOARD& other = static_cast<const BOARD&>( aItem );
3561
3562 if( *m_designSettings != *other.m_designSettings )
3563 return false;
3564
3565 if( m_NetInfo.GetNetCount() != other.m_NetInfo.GetNetCount() )
3566 return false;
3567
3568 const NETNAMES_MAP& thisNetNames = m_NetInfo.NetsByName();
3569 const NETNAMES_MAP& otherNetNames = other.m_NetInfo.NetsByName();
3570
3571 for( auto it1 = thisNetNames.begin(), it2 = otherNetNames.begin();
3572 it1 != thisNetNames.end() && it2 != otherNetNames.end(); ++it1, ++it2 )
3573 {
3574 // We only compare the names in order here, not the index values
3575 // as the index values are auto-generated and the names are not.
3576 if( it1->first != it2->first )
3577 return false;
3578 }
3579
3580 if( m_properties.size() != other.m_properties.size() )
3581 return false;
3582
3583 for( auto it1 = m_properties.begin(), it2 = other.m_properties.begin();
3584 it1 != m_properties.end() && it2 != other.m_properties.end(); ++it1, ++it2 )
3585 {
3586 if( *it1 != *it2 )
3587 return false;
3588 }
3589
3590 if( m_paper.GetCustomHeightMils() != other.m_paper.GetCustomHeightMils() )
3591 return false;
3592
3593 if( m_paper.GetCustomWidthMils() != other.m_paper.GetCustomWidthMils() )
3594 return false;
3595
3596 if( m_paper.GetSizeMils() != other.m_paper.GetSizeMils() )
3597 return false;
3598
3599 if( m_paper.GetPaperId() != other.m_paper.GetPaperId() )
3600 return false;
3601
3602 if( m_paper.GetWxOrientation() != other.m_paper.GetWxOrientation() )
3603 return false;
3604
3605 for( int ii = 0; !m_titles.GetComment( ii ).empty(); ++ii )
3606 {
3607 if( m_titles.GetComment( ii ) != other.m_titles.GetComment( ii ) )
3608 return false;
3609 }
3610
3611 wxArrayString ourVars;
3612 m_titles.GetContextualTextVars( &ourVars );
3613
3614 wxArrayString otherVars;
3615 other.m_titles.GetContextualTextVars( &otherVars );
3616
3617 if( ourVars != otherVars )
3618 return false;
3619
3620 return true;
3621}
3622
3624{
3625 m_boardOutline->GetOutline().RemoveAllContours();
3626
3627 bool has_outline = GetBoardPolygonOutlines( m_boardOutline->GetOutline(), false );
3628
3629 if( has_outline )
3630 m_boardOutline->GetOutline().Fracture();
3631}
3632
3633
3635{
3636 // return the number of PTH with Press-Fit fabr attribute
3637 int count = 0;
3638
3639 for( FOOTPRINT* footprint : Footprints() )
3640 {
3641 for( PAD* pad : footprint->Pads() )
3642 {
3643 if( pad->GetProperty() == PAD_PROP::PRESSFIT )
3644 count++;
3645 }
3646 }
3647
3648 return count;
3649}
3650
3651
3653{
3654 // @return the number of PTH with Castellated fabr attribute
3655 int count = 0;
3656
3657 for( FOOTPRINT* footprint : Footprints() )
3658 {
3659 for( PAD* pad : footprint->Pads() )
3660 {
3661 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
3662 count++;
3663 }
3664 }
3665
3666 return count;
3667}
3668
3669
3670void BOARD::SaveToHistory( const wxString& aProjectPath, std::vector<wxString>& aFiles )
3671{
3672 wxString projPath = GetProject()->GetProjectPath();
3673
3674 if( projPath.IsEmpty() )
3675 return;
3676
3677 // Verify we're saving for the correct project
3678 if( !projPath.IsSameAs( aProjectPath ) )
3679 {
3680 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - project path mismatch: %s vs %s" ), projPath,
3681 aProjectPath );
3682 return;
3683 }
3684
3685 wxString boardPath = GetFileName();
3686
3687 if( boardPath.IsEmpty() )
3688 return; // unsaved board
3689
3690 // Derive relative path from project root.
3691 if( !boardPath.StartsWith( projPath ) )
3692 {
3693 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - board not under project: %s" ), boardPath );
3694 return; // not under project
3695 }
3696
3697 wxString rel = boardPath.Mid( projPath.length() );
3698
3699 // Build destination path inside .history mirror.
3700 wxFileName historyRoot( projPath, wxEmptyString );
3701 historyRoot.AppendDir( wxS( ".history" ) );
3702 wxFileName dst( historyRoot.GetPath(), rel );
3703
3704 // Ensure destination directories exist.
3705 wxFileName dstDir( dst );
3706 dstDir.SetFullName( wxEmptyString );
3707
3708 if( !dstDir.DirExists() )
3709 wxFileName::Mkdir( dstDir.GetPath(), 0777, wxPATH_MKDIR_FULL );
3710
3711 try
3712 {
3714 // Save directly to history mirror path.
3715 pi->SaveBoard( dst.GetFullPath(), this, nullptr );
3716 aFiles.push_back( dst.GetFullPath() );
3717 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver exported '%s'" ), dst.GetFullPath() );
3718 }
3719 catch( const IO_ERROR& ioe )
3720 {
3721 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver export failed: %s" ), wxString::FromUTF8( ioe.What() ) );
3722 }
3723}
const char * name
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
bool sortPadsByXthenYCoord(PAD *const &aLH, PAD *const &aRH)
Used by #GetSortedPadListByXCoord to sort a pad list by X coordinate value.
Definition board.cpp:2862
std::set< wxString >::iterator FindByFirstNFields(std::set< wxString > &strSet, const wxString &searchStr, char delimiter, int n)
Definition board.cpp:356
static wxString FindVariantNameCaseInsensitive(const std::vector< wxString > &aNames, const wxString &aVariantName)
Definition board.cpp:2484
#define DEFAULT_CHAINING_EPSILON_MM
Definition board.h:87
BOARD_USE
Flags to specify how the board is being used.
Definition board.h:312
@ NORMAL
Definition board.h:313
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition board.h:185
@ LT_POWER
Definition board.h:188
@ LT_FRONT
Definition board.h:192
@ LT_MIXED
Definition board.h:189
@ LT_BACK
Definition board.h:193
@ LT_UNDEFINED
Definition board.h:186
@ LT_JUMPER
Definition board.h:190
@ LT_AUX
Definition board.h:191
@ LT_SIGNAL
Definition board.h:187
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
Definition board.h:306
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
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.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Container for design settings for a BOARD object.
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
void SetEnabledLayers(const LSET &aMask)
Change the bit-mask of enabled layers to aMask.
std::shared_ptr< NET_SETTINGS > m_NetSettings
void SetCustomTrackWidth(int aWidth)
Sets custom width for track (i.e.
void SetCustomViaSize(int aSize)
Set custom size for via diameter (i.e.
const LSET & GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
bool IsLayerEnabled(PCB_LAYER_ID aLayerId) const
Test whether a given layer aLayerId is enabled.
void SetUserDefinedLayerCount(int aNewLayerCount)
Set the number of user defined layers to aNewLayerCount.
BOARD_STACKUP & GetStackupDescriptor()
void SetCustomViaDrill(int aDrill)
Sets custom size for via drill (i.e.
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
BOARD_ITEM_CONTAINER(BOARD_ITEM *aParent, KICAD_T aType)
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:85
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:236
virtual void SetLayerSet(const LSET &aLayers)
Definition board_item.h:264
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition board_item.h:343
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:318
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:256
static VECTOR2I ZeroOffset
A value of wxPoint(0,0) which can be passed to the Draw() functions.
Definition board_item.h:185
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
virtual void OnBoardNetSettingsChanged(BOARD &aBoard)
Definition board.h:291
virtual void OnBoardRatsnestChanged(BOARD &aBoard)
Definition board.h:295
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:288
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:292
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:289
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:287
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition board.h:294
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:290
virtual void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems)
Definition board.h:296
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:293
Manage layers needed to make a physical board.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition board.cpp:2206
ZONE * m_SolderMaskBridges
Definition board.h:1459
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:1070
BOARD_STACKUP GetStackupOrDefault() const
Definition board.cpp:2886
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaCache
Definition board.h:1445
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition board.h:1460
PCB_LAYER_ID GetCopperLayerStackMaxId() const
Definition board.cpp:941
GENERATORS m_generators
Definition board.h:1498
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:3230
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:436
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition board.h:352
PAD * GetPad(const VECTOR2I &aPosition, const LSET &aLayerMask) const
Find a pad aPosition on aLayer.
Definition board.cpp:2736
int GetUserDefinedLayerCount() const
Definition board.cpp:930
void recalcOpposites()
Definition board.cpp:851
void SetPosition(const VECTOR2I &aPos) override
Definition board.cpp:608
std::map< wxString, wxString > m_properties
Definition board.h:1513
std::unordered_map< const BOARD_ITEM *, wxString > m_ItemNetclassCache
Definition board.h:1452
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition board.cpp:3082
int m_fileFormatVersionAtLoad
Definition board.h:1510
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition board.cpp:2424
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2497
std::vector< ZONE * > m_DRCCopperZones
Definition board.h:1456
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:998
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1221
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:3177
TITLE_BLOCK m_titles
Definition board.h:1517
GAL_SET m_LegacyVisibleItems
Definition board.h:433
std::vector< wxString > m_variantNames
Definition board.h:1524
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1402
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
Definition board.cpp:2643
void RunOnNestedEmbeddedFiles(const std::function< void(EMBEDDED_FILES *)> &aFunction) override
Provide access to nested embedded files, such as symbols in schematics and footprints in boards.
Definition board.cpp:1193
const GENERATORS & Generators() const
Definition board.h:369
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition board.h:901
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition board.cpp:3151
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition board.cpp:1032
int m_outlinesChainingEpsilon
the max distance between 2 end point to see them connected when building the board outlines
Definition board.h:1483
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:2897
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition board.cpp:2463
BOARD_USE m_boardUse
What is this board being used for.
Definition board.h:1486
PAGE_INFO m_paper
Definition board.h:1516
void RemoveAllListeners()
Remove all listeners.
Definition board.cpp:3224
FOOTPRINTS m_footprints
Definition board.h:1494
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:1537
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
Definition board.cpp:3437
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:3205
void UpdateUserUnits(BOARD_ITEM *aItem, KIGFX::VIEW *aView)
Update any references within aItem (or its descendants) to the user units.
Definition board.cpp:1695
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition board.h:401
bool IsBackLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:776
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition board.cpp:1026
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition board.cpp:3264
HIGH_LIGHT_INFO m_highLight
Definition board.h:1507
std::map< wxString, wxString > m_variantDescriptions
Definition board.h:1525
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition board.cpp:699
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition board.cpp:2357
EDA_UNITS m_userUnits
Definition board.h:1520
void UpdateBoardOutline()
Definition board.cpp:3623
const ZONES & Zones() const
Definition board.h:367
void BulkRemoveStaleTeardrops(BOARD_COMMIT &aCommit)
Remove all teardrop zones with the STRUCT_DELETED flag set.
Definition board.cpp:1363
void DeleteVariant(const wxString &aVariantName)
Definition board.cpp:2531
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition board.h:1470
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aSettings)
Definition board.cpp:1087
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:980
void SanitizeNetcodes()
Definition board.cpp:3195
void InitializeClearanceCache()
Initialize the clearance cache for all board items.
Definition board.cpp:1100
EMBEDDED_FILES * m_embeddedFilesDelegate
Definition board.h:1553
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:3006
bool IsFrontLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:770
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition board.h:396
~BOARD()
Definition board.cpp:157
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:192
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:992
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition board.cpp:782
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition board.cpp:328
DRAWINGS m_drawings
Definition board.h:1493
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:3242
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition board.cpp:2702
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:2663
void ResetNetHighLight()
Reset all high light data to the init state.
Definition board.cpp:3255
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition board.cpp:745
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition board.cpp:2986
bool ResolveTextVar(wxString *token, int aDepth) const
Definition board.cpp:500
const MARKERS & Markers() const
Definition board.h:375
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:911
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition board.cpp:3137
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition board.cpp:614
TITLE_BLOCK & GetTitleBlock()
Definition board.h:805
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition board.cpp:2102
void FixupEmbeddedData()
After loading a file from disk, the footprints do not yet contain the full data for their embedded fi...
Definition board.cpp:1200
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition board.cpp:1107
ZONES m_zones
Definition board.h:1497
void InvalidateClearanceCache(const KIID &aUuid)
Invalidate the clearance cache for a specific item.
Definition board.cpp:1093
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition board.cpp:707
HIGH_LIGHT_INFO m_highLightPrevious
Definition board.h:1508
NETINFO_LIST m_NetInfo
Definition board.h:1545
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:432
void SetVisibleAlls()
Change the bit-mask of visible element categories and layers.
Definition board.cpp:1015
bool HasVariant(const wxString &aVariantName) const
Definition board.cpp:2514
void AddVariant(const wxString &aVariantName)
Definition board.cpp:2520
int GetCopperLayerCount() const
Definition board.cpp:918
int m_timeStamp
Definition board.h:1487
std::vector< BOARD_LISTENER * > m_listeners
Definition board.h:1547
bool RemoveAllItemsOnLayer(PCB_LAYER_ID aLayer)
Removes all owned items other than footprints existing on the given board layer, and modifies the sta...
Definition board.cpp:1609
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsCourtyardCache
Definition board.h:1441
void IncrementTimeStamp()
Definition board.cpp:260
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition board.cpp:2376
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsFCourtyardCache
Definition board.h:1442
PCB_POINTS m_points
Definition board.h:1500
std::unique_ptr< LENGTH_DELAY_CALCULATION > m_lengthDelayCalc
Definition board.h:1556
const FOOTPRINTS & Footprints() const
Definition board.h:363
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition board.h:1514
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
Get the list of all outline fonts used in the board.
Definition board.cpp:3100
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:1482
const BOARD_ITEM_SET GetItemSet()
Definition board.cpp:3539
const TRACKS & Tracks() const
Definition board.h:361
int m_DRCMaxPhysicalClearance
Definition board.h:1458
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition board.cpp:2451
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:1357
std::unordered_map< wxString, LSET > m_LayerExpressionCache
Definition board.h:1446
bool m_embedFonts
Definition board.h:1549
wxString GroupsSanityCheckInternal(bool repair)
Definition board.cpp:3301
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition board.cpp:3249
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition board.cpp:1932
wxString GetClass() const override
Return the class name.
Definition board.h:1142
std::unique_ptr< COMPONENT_CLASS_MANAGER > m_componentClassManager
Definition board.h:1555
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, bool aInferOutlineIfNecessary, 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:3031
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition board.h:440
void SetCopperLayerCount(int aCount)
Definition board.cpp:924
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1449
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsBCourtyardCache
Definition board.h:1443
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition board.cpp:677
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:202
PROJECT * m_project
Definition board.h:1519
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:2922
bool HasItemsOnLayer(PCB_LAYER_ID aLayer)
Definition board.cpp:1563
const wxString & GetFileName() const
Definition board.h:359
bool operator==(const BOARD_ITEM &aOther) const override
Definition board.cpp:3555
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition board.cpp:385
int GetPadWithCastellatedAttrCount()
Definition board.cpp:3652
wxString GetVariantDescription(const wxString &aVariantName) const
Definition board.cpp:2607
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition board.cpp:2439
unsigned GetNodesCount(int aNet=-1) const
Definition board.cpp:2085
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition board.cpp:1890
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition board.cpp:1038
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition board.h:1448
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition board.cpp:801
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:727
void DetachAllFootprints()
Remove all footprints without deleting.
Definition board.cpp:1762
std::map< int, LAYER > m_layers
Definition board.h:1505
wxString GetCurrentVariant() const
Definition board.h:404
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition board.cpp:635
int GetOutlinesChainingEpsilon()
Definition board.h:851
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:2871
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:972
int m_DRCMaxClearance
Definition board.h:1457
void ClearProject()
Definition board.cpp:240
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition board.h:1447
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:1351
wxString m_currentVariant
Definition board.h:1523
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition board.cpp:954
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition board.cpp:1750
PROJECT * GetProject() const
Definition board.h:579
bool IsEmpty() const
Definition board.cpp:596
int GetPadWithPressFitAttrCount()
Definition board.cpp:3634
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:2168
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition board.cpp:3287
void RenameVariant(const wxString &aOldName, const wxString &aNewName)
Definition board.cpp:2559
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1081
std::vector< ZONE * > m_DRCZones
Definition board.h:1455
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:966
BOARD()
Definition board.cpp:85
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:2012
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2477
std::unordered_map< KIID, BOARD_ITEM * > m_itemByIdCache
Definition board.h:1503
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition board.cpp:3212
std::shared_mutex m_CachesMutex
Definition board.h:1440
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:2693
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition board.cpp:1717
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition board.cpp:1380
GROUPS m_groups
Definition board.h:1496
MARKERS m_markers
Definition board.h:1492
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsAreaCache
Definition board.h:1444
std::optional< int > m_maxClearanceValue
Definition board.h:1450
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:3277
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:986
void SynchronizeTuningProfileProperties()
Ensure that all time domain properties providers are in sync with current settings.
Definition board.cpp:2657
TRACKS m_tracks
Definition board.h:1495
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
Definition board.cpp:1774
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:437
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:3236
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition board.h:563
VECTOR2I GetPosition() const override
Definition board.cpp:602
void SetVariantDescription(const wxString &aVariantName, const wxString &aDescription)
Definition board.cpp:2626
void CacheTriangulation(PROGRESS_REPORTER *aReporter=nullptr, const std::vector< ZONE * > &aZones={})
Definition board.cpp:1139
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:1005
void SaveToHistory(const wxString &aProjectPath, std::vector< wxString > &aFiles)
Save board file to the .history directory.
Definition board.cpp:3670
void EmbedFonts() override
Finds all fonts used in the board and embeds them in the file if permissions allow.
Definition board.cpp:3127
PCB_BOARD_OUTLINE * m_boardOutline
Definition board.h:1499
void SetUserDefinedLayerCount(int aCount)
Definition board.cpp:936
const DRAWINGS & Drawings() const
Definition board.h:365
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition board.cpp:1689
constexpr coord_type GetY() const
Definition box2.h:208
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr coord_type GetX() const
Definition box2.h:207
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:658
constexpr size_type GetHeight() const
Definition box2.h:215
bool Dirty() const
BOARD_CONNECTED_ITEM * Parent() const
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
std::shared_ptr< const CN_ANCHOR > GetSourceNode() const
void SetVisible(bool aVisible)
std::shared_ptr< const CN_ANCHOR > GetTargetNode() const
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Definition commit.h:96
A class to manage Component Classes in a board context.
void RunOnUnconnectedEdges(std::function< bool(CN_EDGE &)> aFunc)
unsigned int GetUnconnectedCount(bool aVisibileOnly) const
static DELETED_BOARD_ITEM * GetInstance()
Definition board_item.h:495
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
virtual VECTOR2I GetPosition() const
Definition eda_item.h:278
virtual void ClearEditFlags()
Definition eda_item.h:162
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:148
const KIID m_Uuid
Definition eda_item.h:522
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
static INSPECT_RESULT IterateForward(std::deque< T > &aList, INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes)
This changes first parameter to avoid the DList and use the main queue instead.
Definition eda_item.h:331
virtual INSPECT_RESULT Visit(INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &aScanTypes)
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition eda_item.cpp:127
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:152
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
int Compare(const EDA_SHAPE *aOther) const
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:80
EMBEDDED_FILE * GetEmbeddedFile(const wxString &aName) const
Returns the embedded file with the given name or nullptr if it does not exist.
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
EMBEDDED_FILES()=default
const std::map< wxString, EMBEDDED_FILE * > & EmbeddedFileMap() const
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Helper for storing and iterating over GAL_LAYER_IDs.
Definition layer_ids.h:403
static GAL_SET DefaultVisible()
Definition lset.cpp:769
static const std::vector< KICAD_T > BoardLevelItems
A scan list for all primary board items, omitting items which are subordinate to a FOOTPRINT,...
Definition collectors.h:69
static const std::vector< KICAD_T > Tracks
A scan list for only TRACKs and ARCs.
Definition collectors.h:129
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:131
virtual bool IsOutline() const
Definition font.h:139
Class OUTLINE_FONT implements outline font drawing.
EMBEDDING_PERMISSION GetEmbeddingPermission() const
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
bool IsBOARD_ITEM() const
Definition view_item.h:102
virtual wxString GetClass() const =0
Return the class name.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1685
Definition kiid.h:49
Lightweight class which holds a pad, via, or a routed trace outline.
TYPE Type() const
Gets the routing item type.
Class which calculates lengths (and associated routing statistics) in a BOARD context.
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
LENGTH_DELAY_STATS CalculateLengthDetails(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr, LENGTH_DELAY_LAYER_OPT aLayerOpt=LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL, LENGTH_DELAY_DOMAIN_OPT aDomain=LENGTH_DELAY_DOMAIN_OPT::NO_DELAY_DETAIL) const
Calculates the electrical length of the given items.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:582
static const LSET & AllLayersMask()
Definition lset.cpp:624
std::shared_ptr< RC_ITEM > GetRCItem() const
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition marker_base.h:94
void SetParent(JSON_SETTINGS *aParent, bool aLoadFromFile=true)
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:47
void SetDescription(const wxString &aDesc)
Definition netclass.h:114
Handle the data for a net.
Definition netinfo.h:54
wxString GetClass() const override
Return the class name.
Definition netinfo.h:65
const wxString & GetNetname() const
Definition netinfo.h:112
int GetNetCode() const
Definition netinfo.h:106
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:247
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition netinfo.h:251
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:255
unsigned GetNetCount() const
Definition netinfo.h:235
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:238
void ClearAllCaches()
Clears the effective netclass cache for all nets.
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const wxString &aNetName)
Fetches the effective (may be aggregate) netclass for the given net name.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
void SetDefaultNetclass(std::shared_ptr< NETCLASS > netclass)
Sets the default netclass for the project Calling user is responsible for resetting the effective net...
Definition pad.h:55
VECTOR2I GetPosition() const override
Definition pad.h:209
const VECTOR2D & GetSizeMils() const
Definition page_info.h:150
wxPrintOrientation GetWxOrientation() const
Definition page_info.h:133
static double GetCustomHeightMils()
Definition page_info.h:202
wxPaperSize GetPaperId() const
Definition page_info.h:138
static double GetCustomWidthMils()
Definition page_info.h:197
static int Compare(const PCB_BARCODE *aBarcode, const PCB_BARCODE *aOther)
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the barcode (text + symbol shapes) to polygonal geometry suitable for filling/collision tests...
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
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
Collect all BOARD_ITEM objects on a given layer.
Definition collectors.h:549
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Test a BOARD_ITEM using this class's Inspector method, which does the collection.
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition collectors.h:555
static PCB_MARKER * DeserializeFromString(const wxString &data)
A PCB_POINT is a 0-dimensional point that is used to mark a position on a PCB, or more usually a foot...
Definition pcb_point.h:43
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
static int Compare(const PCB_TABLE *aTable, const PCB_TABLE *aOther)
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
Definition pcb_text.cpp:567
const VECTOR2I & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition pcb_track.h:169
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
The backing store for a PROJECT, in JSON format.
std::shared_ptr< COMPONENT_CLASS_SETTINGS > & ComponentClassSettings()
Container for project specific data.
Definition project.h:65
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:167
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:179
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:199
std::vector< KIID > GetIDs() const
Definition rc_item.h:130
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
const wxString & GetComment(int aIdx) const
static void GetContextualTextVars(wxArrayString *aVars)
Handle a list of polygons defining a copper zone.
Definition zone.h:74
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:517
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition zone.h:586
bool IsTeardropArea() const
Definition zone.h:676
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:1135
#define EXCLUDE_ZONES
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, bool aInferOutlineIfNecessary, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const VECTOR2I &pt)> OUTLINE_ERROR_HANDLER
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
RECURSE_MODE
Definition eda_item.h:50
@ RECURSE
Definition eda_item.h:51
@ NO_RECURSE
Definition eda_item.h:52
INSPECT_RESULT
Definition eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
std::function< INSPECT_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Used to inspect and possibly collect the (search) results of iterating over a list or tree of KICAD_T...
Definition eda_item.h:88
#define STRUCT_DELETED
flag indication structures to be erased
EDA_UNITS
Definition eda_units.h:48
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
KIID niluuid(0)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:677
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:259
@ 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:287
@ LAYER_RATSNEST
Definition layer_ids.h:253
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:260
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:364
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:737
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
STL namespace.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:103
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:123
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:121
PAGE_SIZE_TYPE
Definition page_info.h:50
BARCODE class definition.
Class to handle a set of BOARD_ITEMs.
@ THROUGH
Definition pcb_track.h:68
ENDPOINT_T
Definition pcb_track.h:60
see class PGM_BASE
CITER next(CITER it)
Definition ptree.cpp:124
Class that computes missing connections on a PCB.
@ RPT_SEVERITY_EXCLUSION
wxString GetDefaultVariantName()
int SortVariantNames(const wxString &aLhs, const wxString &aRhs)
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition board.cpp:3391
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition board.cpp:3370
std::vector< char > decompressedData
Container to hold information pertinent to a layer of a BOARD.
Definition board.h:201
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
Definition board.cpp:830
static const char * ShowType(LAYER_T aType)
Convert a LAYER_T enum to a string representation of the layer type.
Definition board.cpp:814
Holds length measurement result details and statistics.
Struct to control which optimisations the length calculation code runs on the given path objects.
int delta
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::priority_thread_pool thread_pool
Definition thread_pool.h:31
wxLogTrace helper definitions.
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:106
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:103
@ 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:104
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:111
@ 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:108
@ 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_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:107
@ 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:102
@ 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:110
@ PCB_POINT_T
class PCB_POINT, a 0-dimensional point
Definition typeinfo.h:113
@ 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:105
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.