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