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, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <iterator>
25#include <algorithm>
26#include <unordered_map>
27
28#include <wx/log.h>
29#include <wx/filename.h>
30
31#include <drc/drc_engine.h>
32#include <drc/drc_rtree.h>
37#include <pcb_drill_map.h>
38#include <board_commit.h>
39#include <board.h>
40#include <collectors.h>
42#include <core/arraydim.h>
43#include <core/kicad_algo.h>
46#include <footprint.h>
49#include <font/outline_font.h>
51#include <layer_range.h>
52#include <lset.h>
53#include <pad.h>
54#include <pcb_base_frame.h>
55#include <pcb_track.h>
56#include <pcb_marker.h>
57#include <api/board/board_rules.pb.h>
58#include <pcb_group.h>
59#include <pcb_generator.h>
60#include <pcb_point.h>
62#include <pcb_target.h>
63#include <pcb_shape.h>
64#include <pcb_barcode.h>
65#include <pcb_3d_body.h>
66#include <pcb_text.h>
67#include <pcb_textbox.h>
68#include <pcb_table.h>
69#include <pcb_dimension.h>
70#include <pgm_base.h>
71#include <pcbnew_settings.h>
72#include <progress_reporter.h>
73#include <project.h>
79#include <reporter.h>
80#include <tool/tool_manager.h>
82#include <string_utils.h>
83#include <thread_pool.h>
84#include <zone.h>
85#include <mutex>
86#include <pcb_board_outline.h>
87#include <local_history.h>
88#include <pcb_io/pcb_io_mgr.h>
90#include <advanced_config.h>
91#include <richio.h>
92#include <trace_helpers.h>
93
94// This is an odd place for this, but CvPcb won't link if it's in board_item.cpp like I first
95// tried it.
97
98
100 BOARD_ITEM_CONTAINER( nullptr, PCB_T ),
105 m_timeStamp( 1 ),
106 m_itemIndex( *this ),
108 m_project( nullptr ),
110 m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
111 m_NetInfo( this ),
112 m_embedFonts( false ),
113 m_embeddedFilesDelegate( nullptr ),
114 m_componentClassManager( std::make_unique<COMPONENT_CLASS_MANAGER>( this ) ),
115 m_lengthDelayCalc( std::make_unique<LENGTH_DELAY_CALCULATION>( this ) )
116{
117 // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
118 // A too large value do not allow safely connecting 2 shapes like very short segments.
120
123 m_boardOutline = new PCB_BOARD_OUTLINE( this );
124
125 // we have not loaded a board yet, assume latest until then.
126 m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
129
130 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
131 {
132 m_layers[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
133
134 if( IsCopperLayer( layer ) )
135 m_layers[layer].m_type = LT_SIGNAL;
136 else if( layer >= User_1 && layer & 1 )
137 m_layers[layer].m_type = LT_AUX;
138 else
139 m_layers[layer].m_type = LT_UNDEFINED;
140 }
141
143
144 // Creates a zone to show sloder mask bridges created by a min web value
145 // it it just to show them
146 m_SolderMaskBridges = new ZONE( this );
148 m_SolderMaskBridges->SetLayerSet( LSET().set( F_Mask ).set( B_Mask ) );
149 int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
150 m_SolderMaskBridges->Outline()->NewOutline();
151 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
152 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
153 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, +infinity ) );
154 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, -infinity ) );
155 m_SolderMaskBridges->SetMinThickness( 0 );
156
158
159 // Initialize default netclass.
160 bds.m_NetSettings->SetDefaultNetclass( std::make_shared<NETCLASS>( NETCLASS::Default ) );
161 bds.m_NetSettings->GetDefaultNetclass()->SetDescription( _( "This is the default net class." ) );
162
163 bds.UseCustomTrackViaSize( false );
164
165 // Initialize ratsnest
166 m_connectivity.reset( new CONNECTIVITY_DATA() );
167
168 // Set flag bits on these that will only be cleared if these are loaded from a legacy file
169 m_LegacyVisibleLayers.reset().set( Rescue );
171
172 // Install the text-variable dependency adapter as a listener so subsequent
173 // BOARD_COMMIT pushes and undo/redo events reach the tracker. No items
174 // exist yet — RebuildIndex is invoked after load by callers that bypass
175 // per-item notifications.
176 m_textVarAdapter = std::make_unique<BOARD_TEXT_VAR_ADAPTER>( *this );
178}
179
180
185
186
187// Footprints count because the board editor promotes a pad edit to its parent, so watching
188// PAD_T alone would miss every drill change made through the normal editing path
189static bool affectsDrillModel( const BOARD_ITEM* aItem )
190{
191 if( !aItem )
192 return false;
193
194 switch( aItem->Type() )
195 {
196 case PCB_PAD_T:
197 case PCB_VIA_T:
198 case PCB_FOOTPRINT_T:
199 return true;
200
201 default:
202 return false;
203 }
204}
205
206
207std::vector<const PCB_DRILL_MAP*> BOARD::DrillMapsOnLayer( PCB_LAYER_ID aLayer ) const
208{
209 std::vector<const PCB_DRILL_MAP*> maps;
210
211 for( BOARD_ITEM* item : m_drawings )
212 {
213 if( item->Type() == PCB_DRILL_MAP_T && item->GetLayer() == aLayer )
214 maps.push_back( static_cast<const PCB_DRILL_MAP*>( item ) );
215 }
216
217 return maps;
218}
219
220
222{
223 if( !aItem )
224 return;
225
226 // A deleted map keeps drawing until the holes themselves are told
227 if( aItem->Type() == PCB_DRILL_MAP_T )
228 {
231 }
232 else if( affectsDrillModel( aItem ) )
233 {
235 }
236}
237
238
240{
241 LSET layers;
242 std::vector<std::pair<VECTOR2I, int>> placements;
243
244 for( BOARD_ITEM* item : m_drawings )
245 {
246 if( item->Type() != PCB_DRILL_MAP_T )
247 continue;
248
249 const PCB_DRILL_MAP* map = static_cast<const PCB_DRILL_MAP*>( item );
250
251 layers.set( map->GetLayer() );
252 placements.emplace_back( map->GetOffset(), map->GetSymbolExtent() );
253 }
254
255 // Both, because a map can change layer without moving and can move without changing layer
256 if( m_drillSymbolLayers == layers && m_drillSymbolPlacements == placements )
257 return;
258
259 m_drillSymbolLayers = layers;
260 m_drillSymbolPlacements = std::move( placements );
261
262}
263
264
265std::shared_ptr<const DRILL_SYMBOL_CACHE> BOARD::DrillSymbolCache() const
266{
267 std::lock_guard<std::mutex> lock( m_drillSymbolCacheMutex );
268
269 const uint64_t profileKey = GetDesignSettings().GetDrillSymbolProfile().Fingerprint();
270
272 && m_drillSymbolCache->m_Profile == profileKey )
273 {
274 return m_drillSymbolCache;
275 }
276
277 std::shared_ptr<DRILL_SYMBOL_CACHE> rebuilt = std::make_shared<DRILL_SYMBOL_CACHE>();
278 rebuilt->m_ByGroup = ResolveDrillSymbols( *this );
279 rebuilt->m_ByItem = ResolveDrillSymbolsByItem( *this, rebuilt->m_ByGroup );
280
281 DRILL_CHART_MODEL totalsModel( GetDesignSettings().GetDrillSymbolProfile() );
282 totalsModel.Build( *this, EnumerateDrillSpans( *this ) );
283 rebuilt->m_Totals = totalsModel.Totals();
284
285 for( const auto& [itemId, entries] : rebuilt->m_ByItem )
286 {
287 for( const DRILL_SYMBOL_ENTRY& entry : entries )
288 rebuilt->m_HoleExtent.Merge( entry.m_Position );
289 }
290
291 rebuilt->m_Generation = m_drillModelGeneration;
292 rebuilt->m_Profile = profileKey;
293
294 m_drillSymbolCache = rebuilt;
295
296 return m_drillSymbolCache;
297}
298
299
301{
302 if( m_drillSymbolPlacements.empty() )
303 return aBoundingBox;
304
305 BOX2I result = aBoundingBox;
306
307 for( const auto& [offset, extent] : m_drillSymbolPlacements )
308 {
309 BOX2I symbolBox = aBoundingBox;
310 symbolBox.Move( offset );
311 symbolBox.Inflate( extent );
312 result.Merge( symbolBox );
313 }
314
315 return result;
316}
317
318
319void BOARD::bumpDrillModelFor( const std::vector<BOARD_ITEM*>& aItems )
320{
321 for( const BOARD_ITEM* item : aItems )
322 {
323 if( affectsDrillModel( item ) )
324 {
326 return;
327 }
328 }
329}
330
331
333{
334 // Clears m_owningIndex as it goes. Items that outlive the board rely on that to know
335 // ~BOARD_ITEM must not walk their parent chain back into freed memory
337
338 // Clean up the owned elements
340
341 delete m_SolderMaskBridges;
342
343 std::vector<BOARD_ITEM*> ownedItems = collectOwnedItems();
344
345 std::sort( ownedItems.begin(), ownedItems.end() );
346 ownedItems.erase( std::unique( ownedItems.begin(), ownedItems.end() ), ownedItems.end() );
347
348 m_zones.clear();
349 m_footprints.clear();
350 m_tracks.clear();
351 m_drawings.clear();
352 m_groups.clear();
353 m_constraints.clear();
354 m_points.clear();
355
356 delete m_boardOutline;
357 m_generators.clear();
358
359 // Delete the owned items after clearing the containers, because some item dtors
360 // cause call chains that query the containers
361 for( BOARD_ITEM* item : ownedItems )
362 delete item;
363
364 // Remove any listeners
366}
367
368
370{
371 if( !GetConnectivity()->Build( this, aReporter ) )
372 return false;
373
375 return true;
376}
377
378
379void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly )
380{
381 if( m_project == aProject )
382 return;
383
384 if( m_project )
385 ClearProject();
386
387 m_project = aProject;
388
389 if( aProject && !aReferenceOnly )
390 {
391 PROJECT_FILE& project = aProject->GetProjectFile();
392
393 // Link the design settings object to the project file
394 project.m_BoardSettings = m_designSettings;
395
396 // Set parent, which also will load the values from JSON stored in the project if we don't
397 // have legacy design settings loaded already
398 project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
399
400 // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
401 // list at this point. If we loaded anything into it from a legacy board file then we
402 // want to transfer it over to the project netclasses list.
404 {
405 std::shared_ptr<NET_SETTINGS> legacySettings = GetDesignSettings().m_NetSettings;
406 std::shared_ptr<NET_SETTINGS>& projectSettings = project.NetSettings();
407
408 projectSettings->SetDefaultNetclass( legacySettings->GetDefaultNetclass() );
409 projectSettings->SetNetclasses( legacySettings->GetNetclasses() );
410 projectSettings->SetNetclassPatternAssignments(
411 std::move( legacySettings->GetNetclassPatternAssignments() ) );
412 }
413
414 // Now update the DesignSettings' netclass pointer to point into the project.
415 GetDesignSettings().m_NetSettings = project.NetSettings();
416 }
417}
418
419
421{
422 if( !m_project )
423 return;
424
425 PROJECT_FILE& project = m_project->GetProjectFile();
426
427 // Release this board's own design settings, not project.m_BoardSettings; a second board
428 // sharing the project (e.g. diffing a file against itself) overwrites m_BoardSettings, so
429 // trusting it would orphan our settings as a dangling entry in the project's nested list
430 project.ReleaseNestedSettings( m_designSettings.get() );
431
433 m_project = nullptr;
434}
435
436
438{
439 if( m_fileName.IsEmpty() || !m_project )
440 return wxEmptyString;
441
442 wxFileName fn( m_fileName );
444 return m_project->AbsolutePath( fn.GetFullName() );
445}
446
447
449{
450 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
451
452 m_timeStamp++;
453
455
456 if( !m_IntersectsAreaCache.Empty()
457 || !m_IntersectsKeepoutCache.Empty()
458 || !m_EnclosedByAreaCache.Empty()
468 || !m_LayerExpressionCache.empty()
469 || !m_ZoneBBoxCache.empty()
471 || m_maxClearanceValue.has_value()
472 || !m_ZonesByNameCache.empty()
474 || !m_ItemFieldCache.Empty()
475 || m_StackedMicroviaCache.has_value() )
476 {
477 m_IntersectsAreaCache.Clear();
479 m_EnclosedByAreaCache.Clear();
489 m_ItemFieldCache.Clear();
492 m_ZonesByNameCache.clear();
494
495 m_ZoneBBoxCache.clear();
496
497 m_CopperItemRTreeCache = nullptr;
498
499 // These are always regenerated before use, but still probably safer to clear them
500 // while we're here.
503 m_DRCZones.clear();
504 m_DRCCopperZones.clear();
508
509 m_maxClearanceValue.reset();
510 }
511}
512
513
514std::shared_ptr<const FOOTPRINT_COURTYARD_INDEX> BOARD::GetFootprintCourtyardIndex()
515{
516 {
517 std::shared_lock<std::shared_mutex> readLock( m_CachesMutex );
518
521 }
522
523 // Build outside the lock; FOOTPRINT::GetCourtyard guards its own cache with a per-footprint
524 // mutex, so building here is safe even when it has to lazily populate that cache. Publish under
525 // the write lock, letting the first builder win if several worker threads race here on the
526 // first courtyard predicate.
527 auto index = std::make_shared<FOOTPRINT_COURTYARD_INDEX>( this );
528
529 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
530
532 m_footprintCourtyardIndex = std::move( index );
533
535}
536
537
539{
540 std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
541
542 for( PCB_MARKER* marker : GetBoard()->Markers() )
543 {
544 if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
545 {
546 const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
547 m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
548 m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
549 }
550 }
551
553 [&]( CN_EDGE& aEdge )
554 {
555 if( aEdge.GetSourceNode() && aEdge.GetTargetNode() && !aEdge.GetSourceNode()->Dirty()
556 && !aEdge.GetTargetNode()->Dirty() )
557 {
558 std::pair<KIID, KIID> ids = { aEdge.GetSourceNode()->Parent()->m_Uuid,
559 aEdge.GetTargetNode()->Parent()->m_Uuid };
560
561 aEdge.SetVisible( m_ratsnestExclusions.count( ids ) == 0 );
562 }
563
564 return true;
565 } );
566}
567
568
570{
571 m_designSettings->m_DrcExclusions.clear();
572
573 for( PCB_MARKER* marker : m_markers )
574 {
575 // DRC_EXCLUSION::FromMarker() dereferences the RC_ITEM, so a marker carrying none would
576 // fault while persisting exclusions during a save or window close.
577 if( !marker->GetRCItem() )
578 continue;
579
580 if( marker->IsExcluded() )
581 m_designSettings->m_DrcExclusions.insert( DRC_EXCLUSION::FromMarker( *marker ) );
582 }
583
584 if( m_project )
585 {
586 if( PROJECT_FILE* projectFile = &m_project->GetProjectFile() )
587 {
588 if( projectFile->m_BoardSettings )
589 projectFile->m_BoardSettings->m_DrcExclusions = m_designSettings->m_DrcExclusions;
590 }
591 }
592}
593
594
595std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
596{
597 std::set<DRC_EXCLUSION, DRC_EXCLUSION_COMPARE> exclusions = m_designSettings->m_DrcExclusions;
598 m_designSettings->m_DrcExclusions.clear();
599
600 for( PCB_MARKER* marker : GetBoard()->Markers() )
601 {
602 DRC_EXCLUSION lookup = DRC_EXCLUSION::FromMarker( *marker );
603
604 if( auto it = exclusions.find( lookup ); it != exclusions.end() )
605 {
606 marker->SetExcluded( true, it->GetComment() );
607 m_designSettings->m_DrcExclusions.insert( *it );
608 }
609 }
610
611 std::vector<PCB_MARKER*> newMarkers;
612
613 if( aCreateMarkers )
614 {
615 for( const DRC_EXCLUSION& exclusion : exclusions )
616 {
617 if( m_designSettings->m_DrcExclusions.contains( exclusion ) )
618 continue;
619
620 PCB_MARKER* marker = PCB_MARKER::FromProto( exclusion.ToProto().marker() );
621
622 if( !marker )
623 continue;
624
625 std::vector<KIID> ids = marker->GetRCItem()->GetIDs();
626
627 for( const KIID& uuid : ids )
628 {
629 if( uuid != niluuid && !ResolveItem( uuid, true ) )
630 {
631 delete marker;
632 marker = nullptr;
633 break;
634 }
635 }
636
637 if( marker )
638 {
639 marker->SetExcluded( true, exclusion.GetComment() );
640 newMarkers.push_back( marker );
641 m_designSettings->m_DrcExclusions.insert( exclusion );
642 }
643 }
644 }
645
646 return newMarkers;
647}
648
649
650void BOARD::GetContextualTextVars( wxArrayString* aVars ) const
651{
652 auto add = [&]( const wxString& aVar )
653 {
654 if( !alg::contains( *aVars, aVar ) )
655 aVars->push_back( aVar );
656 };
657
658 add( wxT( "LAYER" ) );
659 add( wxT( "FILENAME" ) );
660 add( wxT( "FILEPATH" ) );
661 add( wxT( "PROJECTNAME" ) );
662 add( wxT( "DRC_ERROR <message_text>" ) );
663 add( wxT( "DRC_WARNING <message_text>" ) );
664 add( wxT( "VARIANT" ) );
665 add( wxT( "VARIANT_DESC" ) );
666 add( wxT( "DRILL_OPERATIONS" ) );
667 add( wxT( "DRILL_SITES" ) );
668 add( wxT( "DRILL_GROUPS" ) );
669
671
672 if( GetProject() )
673 {
674 for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
675 add( entry.first );
676 }
677}
678
679
680bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
681{
682 return ResolveTextVar( token, GetCurrentVariant(), aDepth );
683}
684
685
686bool BOARD::ResolveTextVar( wxString* token, const wxString& aVariantName, int aDepth ) const
687{
688 if( token->Contains( ':' ) )
689 {
690 wxString remainder;
691 wxString ref = token->BeforeFirst( ':', &remainder );
692 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
693
694 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
695 {
696 FOOTPRINT* refFP = static_cast<FOOTPRINT*>( refItem );
697
698 if( refFP->ResolveTextVar( &remainder, aVariantName, aDepth + 1 ) )
699 *token = std::move( remainder );
700 else
701 *token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), refFP->GetReference(), remainder );
702
703 return true;
704 }
705
706 // If UUID resolution failed, try to resolve by reference designator
707 // This handles typing ${U1:VALUE} directly without save/reload
708 if( !refItem )
709 {
710 for( const FOOTPRINT* footprint : Footprints() )
711 {
712 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
713 {
714 if( footprint->ResolveTextVar( &remainder, aVariantName, aDepth + 1 ) )
715 *token = std::move( remainder );
716 else
717 *token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), ref, remainder );
718
719 return true;
720 }
721 }
722 }
723
724 if( !refItem )
725 {
726 *token = wxString::Format( wxT( "<Unresolved: %s:%s>" ), ref, remainder );
727 return true;
728 }
729 }
730
731 if( token->IsSameAs( wxT( "FILENAME" ) ) )
732 {
733 wxFileName fn( GetFileName() );
734 *token = fn.GetFullName();
735 return true;
736 }
737 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
738 {
739 wxFileName fn( GetFileName() );
740 *token = fn.GetFullPath();
741 return true;
742 }
743 else if( token->IsSameAs( wxT( "VARIANT" ) ) )
744 {
745 *token = aVariantName;
746 return true;
747 }
748 else if( token->IsSameAs( wxT( "VARIANT_DESC" ) ) )
749 {
750 *token = GetVariantDescription( aVariantName );
751 return true;
752 }
753 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) && GetProject() )
754 {
755 *token = GetProject()->GetProjectName();
756 return true;
757 }
758 else if( token->IsSameAs( wxT( "DRILL_OPERATIONS" ) )
759 || token->IsSameAs( wxT( "DRILL_SITES" ) )
760 || token->IsSameAs( wxT( "DRILL_GROUPS" ) ) )
761 {
762 // Cached, because this resolves on every redraw of every text item and the model
763 // walks every hole on every span
765
766 if( token->IsSameAs( wxT( "DRILL_OPERATIONS" ) ) )
767 *token = wxString::Format( wxT( "%d" ), totals.m_Operations );
768 else if( token->IsSameAs( wxT( "DRILL_SITES" ) ) )
769 *token = wxString::Format( wxT( "%d" ), totals.m_Sites );
770 else
771 *token = wxString::Format( wxT( "%d" ), totals.m_Groups );
772
773 return true;
774 }
775
776 wxString var = *token;
777
778 if( GetTitleBlock().TextVarResolver( token, m_project, INTERNAL ) )
779 return true;
780
781 // Resolve from the project's live text variables before the board's cached properties so
782 // changes made outside the board (schematic, project settings) are always reflected.
783 if( GetProject() && GetProject()->TextVarResolver( token ) )
784 return true;
785
786 // Fall back to the board's cached properties for backward compatibility with boards that
787 // may carry properties not present in the project.
788 if( m_properties.count( var ) )
789 {
790 *token = m_properties.at( var );
791 return true;
792 }
793
794 return false;
795}
796
797
798bool BOARD::IsEmpty() const
799{
800 return m_drawings.empty() && m_footprints.empty() && m_tracks.empty() && m_zones.empty() && m_points.empty();
801}
802
803
805{
806 return ZeroOffset;
807}
808
809
810void BOARD::SetPosition( const VECTOR2I& aPos )
811{
812 wxLogWarning( wxT( "This should not be called on the BOARD object" ) );
813}
814
815
816void BOARD::Move( const VECTOR2I& aMoveVector ) // overload
817{
818 INSPECTOR_FUNC inspector = [&]( EDA_ITEM* item, void* testData )
819 {
820 if( item->IsBOARD_ITEM() )
821 {
822 BOARD_ITEM* board_item = static_cast<BOARD_ITEM*>( item );
823
824 // aMoveVector was snapshotted, don't need "data".
825 // Only move the top level group
826 if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() )
827 board_item->Move( aMoveVector );
828 }
829
831 };
832
833 Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems );
834}
835
836
837void BOARD::RunOnChildren( const std::function<void( BOARD_ITEM* )>& aFunction, RECURSE_MODE aMode ) const
838{
839 try
840 {
841 for( PCB_TRACK* track : m_tracks )
842 aFunction( track );
843
844 for( ZONE* zone : m_zones )
845 aFunction( zone );
846
847 for( PCB_MARKER* marker : m_markers )
848 aFunction( marker );
849
850 for( PCB_GROUP* group : m_groups )
851 aFunction( group );
852
853 for( PCB_CONSTRAINT* constraint : m_constraints )
854 aFunction( constraint );
855
856 for( PCB_POINT* point : m_points )
857 aFunction( point );
858
859 for( FOOTPRINT* footprint : m_footprints )
860 {
861 aFunction( footprint );
862
863 if( aMode == RECURSE_MODE::RECURSE )
864 footprint->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
865 }
866
867 for( BOARD_ITEM* drawing : m_drawings )
868 {
869 aFunction( drawing );
870
871 if( aMode == RECURSE_MODE::RECURSE )
872 drawing->RunOnChildren( aFunction, RECURSE_MODE::RECURSE );
873 }
874 }
875 catch( std::bad_function_call& )
876 {
877 wxFAIL_MSG( wxT( "Error running BOARD::RunOnChildren" ) );
878 }
879}
880
881
883{
884 TRACKS ret;
885
886 INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
887 {
888 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
889
890 if( t->GetNetCode() == aNetCode )
891 ret.push_back( t );
892
894 };
895
896 // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
897 // appends all in aNetCode to ret.
898 Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
899
900 return ret;
901}
902
903
904bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
905{
906 m_layers[aIndex] = aLayer;
908 return true;
909}
910
911
912PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
913{
914 // Check the BOARD physical layer names.
915 for( auto& [layer_id, layer] : m_layers )
916 {
917 if( layer.m_name == aLayerName || layer.m_userName == aLayerName )
918 return ToLAYER_ID( layer_id );
919 }
920
921 // Otherwise fall back to the system standard layer names for virtual layers.
922 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
923 {
924 if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
925 return ToLAYER_ID( layer );
926 }
927
928 return UNDEFINED_LAYER;
929}
930
931
932const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
933{
934 // All layer names are stored in the BOARD.
935 if( IsLayerEnabled( aLayer ) )
936 {
937 auto it = m_layers.find( aLayer );
938
939 // Standard names were set in BOARD::BOARD() but they may be over-ridden by
940 // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
941 // if it was set. Otherwise return the Standard English layer name.
942 if( it != m_layers.end() && !it->second.m_userName.IsEmpty() )
943 return it->second.m_userName;
944 }
945
946 return GetStandardLayerName( aLayer );
947}
948
949
950bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
951{
952 if( aLayerName.IsEmpty() )
953 {
954 // If the name is empty, we clear the user name.
955 m_layers[aLayer].m_userName.clear();
957 }
958 else
959 {
960 // no quote chars in the name allowed
961 if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
962 return false;
963
964 if( IsLayerEnabled( aLayer ) )
965 {
966 m_layers[aLayer].m_userName = aLayerName;
968
969 // A chart prints the span using layer names, so a rename changes what it says
971 return true;
972 }
973 }
974
975 return false;
976}
977
978
980{
981 return ::IsFrontLayer( aLayer ) || GetLayerType( aLayer ) == LT_FRONT;
982}
983
984
986{
987 return ::IsBackLayer( aLayer ) || GetLayerType( aLayer ) == LT_BACK;
988}
989
990
992{
993 if( IsLayerEnabled( aLayer ) )
994 {
995 auto it = m_layers.find( aLayer );
996
997 if( it != m_layers.end() )
998 return it->second.m_type;
999 }
1000
1001 if( aLayer >= User_1 && !IsCopperLayer( aLayer ) )
1002 return LT_AUX;
1003 else if( IsCopperLayer( aLayer ) )
1004 return LT_SIGNAL;
1005 else
1006 return LT_UNDEFINED;
1007}
1008
1009
1010bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
1011{
1012 if( IsLayerEnabled( aLayer ) )
1013 {
1014 m_layers[aLayer].m_type = aLayerType;
1016 return true;
1017 }
1018
1019 return false;
1020}
1021
1022
1023const char* LAYER::ShowType( LAYER_T aType )
1024{
1025 switch( aType )
1026 {
1027 default:
1028 case LT_SIGNAL: return "signal";
1029 case LT_POWER: return "power";
1030 case LT_MIXED: return "mixed";
1031 case LT_JUMPER: return "jumper";
1032 case LT_AUX: return "auxiliary";
1033 case LT_FRONT: return "front";
1034 case LT_BACK: return "back";
1035 }
1036}
1037
1038
1039LAYER_T LAYER::ParseType( const char* aType )
1040{
1041 if( strcmp( aType, "signal" ) == 0 )
1042 return LT_SIGNAL;
1043 else if( strcmp( aType, "power" ) == 0 )
1044 return LT_POWER;
1045 else if( strcmp( aType, "mixed" ) == 0 )
1046 return LT_MIXED;
1047 else if( strcmp( aType, "jumper" ) == 0 )
1048 return LT_JUMPER;
1049 else if( strcmp( aType, "auxiliary" ) == 0 )
1050 return LT_AUX;
1051 else if( strcmp( aType, "front" ) == 0 )
1052 return LT_FRONT;
1053 else if( strcmp( aType, "back" ) == 0 )
1054 return LT_BACK;
1055 else
1056 return LT_UNDEFINED;
1057}
1058
1059
1061{
1062 for( int layer = F_Cu; layer < PCB_LAYER_ID_COUNT; ++layer )
1063 m_layers[layer].m_opposite = ::FlipLayer( ToLAYER_ID( layer ), GetCopperLayerCount() );
1064
1065 // Match up similary-named front/back user layers
1066 for( int layer = User_1; layer <= PCB_LAYER_ID_COUNT; layer += 2 )
1067 {
1068 if( m_layers[layer].m_opposite != layer ) // already paired
1069 continue;
1070
1071 if( m_layers[layer].m_type != LT_FRONT && m_layers[layer].m_type != LT_BACK )
1072 continue;
1073
1074 wxString principalName = m_layers[layer].m_userName.AfterFirst( '.' );
1075
1076 for( int ii = layer + 2; ii <= PCB_LAYER_ID_COUNT; ii += 2 )
1077 {
1078 if( m_layers[ii].m_opposite != ii ) // already paired
1079 continue;
1080
1081 if( m_layers[ii].m_type != LT_FRONT && m_layers[ii].m_type != LT_BACK )
1082 continue;
1083
1084 if( m_layers[layer].m_type == m_layers[ii].m_type )
1085 continue;
1086
1087 wxString candidate = m_layers[ii].m_userName.AfterFirst( '.' );
1088
1089 if( !candidate.IsEmpty() && candidate == principalName )
1090 {
1091 m_layers[layer].m_opposite = ii;
1092 m_layers[ii].m_opposite = layer;
1093 break;
1094 }
1095 }
1096 }
1097
1098 // Match up non-custom-named consecutive front/back user layer pairs
1099 for( int layer = User_1; layer < PCB_LAYER_ID_COUNT - 2; layer += 2 )
1100 {
1101 int next = layer + 2;
1102
1103 // ignore already-matched layers
1104 if( m_layers[layer].m_opposite != layer || m_layers[next].m_opposite != next )
1105 continue;
1106
1107 // ignore layer pairs that aren't consecutive front/back
1108 if( m_layers[layer].m_type != LT_FRONT || m_layers[next].m_type != LT_BACK )
1109 continue;
1110
1111 if( m_layers[layer].m_userName != m_layers[layer].m_name && m_layers[next].m_userName != m_layers[next].m_name )
1112 {
1113 m_layers[layer].m_opposite = next;
1114 m_layers[next].m_opposite = layer;
1115 }
1116 }
1117}
1118
1119
1121{
1122 auto it = m_layers.find( aLayer );
1123 return it == m_layers.end() ? aLayer : ToLAYER_ID( it->second.m_opposite );
1124}
1125
1126
1131
1132
1134{
1137
1138 // A chart prints layer spans, so the count and order change what it says
1140}
1141
1142
1147
1148
1150{
1152}
1153
1155{
1156 int imax = GetCopperLayerCount();
1157
1158 // layers IDs are F_Cu, B_Cu, and even IDs values (imax values)
1159 if( imax <= 2 ) // at least 2 layers are expected
1160 return B_Cu;
1161
1162 // For a 4 layer, last ID is In2_Cu = 6 (IDs are 0, 2, 4, 6)
1163 return static_cast<PCB_LAYER_ID>( ( imax - 1 ) * 2 );
1164}
1165
1166
1167int BOARD::LayerDepth( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer ) const
1168{
1169 // Copper IDs are not in stack order (B_Cu=2, In1_Cu=4), so count in stack positions
1170 return static_cast<int>( LAYER_RANGE( aStartLayer, aEndLayer, GetCopperLayerCount() ).size() ) - 1;
1171}
1172
1173
1175{
1177}
1178
1179
1181{
1182 // If there is no project, assume layer is visible always
1183 return GetDesignSettings().IsLayerEnabled( aLayer )
1184 && ( !m_project || m_project->GetLocalSettings().m_VisibleLayers[aLayer] );
1185}
1186
1187
1189{
1190 return m_project ? m_project->GetLocalSettings().m_VisibleLayers : LSET::AllLayersMask();
1191}
1192
1193
1194void BOARD::SetEnabledLayers( const LSET& aLayerSet )
1195{
1196 GetDesignSettings().SetEnabledLayers( aLayerSet );
1198}
1199
1200
1202{
1203 return GetDesignSettings().IsLayerEnabled( aLayer );
1204}
1205
1206
1207void BOARD::SetVisibleLayers( const LSET& aLayerSet )
1208{
1209 if( m_project )
1210 m_project->GetLocalSettings().m_VisibleLayers = aLayerSet;
1211}
1212
1213
1215{
1216 // Call SetElementVisibility for each item
1217 // to ensure specific calculations that can be needed by some items,
1218 // just changing the visibility flags could be not sufficient.
1219 for( size_t i = 0; i < aSet.size(); i++ )
1220 SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
1221}
1222
1223
1225{
1226 SetVisibleLayers( LSET().set() );
1227
1228 // Call SetElementVisibility for each item,
1229 // to ensure specific calculations that can be needed by some items
1231 SetElementVisibility( ii, true );
1232}
1233
1234
1236{
1237 return m_project ? m_project->GetLocalSettings().m_VisibleItems : GAL_SET::DefaultVisible();
1238}
1239
1240
1242{
1243 return !m_project || m_project->GetLocalSettings().m_VisibleItems[aLayer - GAL_LAYER_ID_START];
1244}
1245
1246
1247void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
1248{
1249 if( m_project )
1250 m_project->GetLocalSettings().m_VisibleItems.set( aLayer - GAL_LAYER_ID_START, isEnabled );
1251
1252 switch( aLayer )
1253 {
1254 case LAYER_RATSNEST:
1255 {
1256 // because we have a tool to show/hide ratsnest relative to a pad or a footprint
1257 // so the hide/show option is a per item selection
1258
1259 for( PCB_TRACK* track : Tracks() )
1260 track->SetLocalRatsnestVisible( isEnabled );
1261
1262 for( FOOTPRINT* footprint : Footprints() )
1263 {
1264 for( PAD* pad : footprint->Pads() )
1265 pad->SetLocalRatsnestVisible( isEnabled );
1266 }
1267
1268 for( ZONE* zone : Zones() )
1269 zone->SetLocalRatsnestVisible( isEnabled );
1270
1271 break;
1272 }
1273
1274 default:;
1275 }
1276}
1277
1278
1280{
1281 switch( aLayer )
1282 {
1285 default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true;
1286 }
1287}
1288
1289
1294
1295
1297{
1298 return *m_designSettings;
1299}
1300
1301
1303{
1304 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
1305
1306 *m_designSettings = aSettings;
1307 m_maxClearanceValue.reset();
1308}
1309
1310
1312{
1313 if( m_designSettings && m_designSettings->m_DRCEngine )
1314 m_designSettings->m_DRCEngine->InvalidateClearanceCache( aUuid );
1315}
1316
1317
1319{
1320 if( m_designSettings && m_designSettings->m_DRCEngine )
1321 m_designSettings->m_DRCEngine->InitializeClearanceCache();
1322}
1323
1324
1326{
1327 if( !m_maxClearanceValue.has_value() )
1328 {
1329 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
1330
1331 int worstClearance = m_designSettings->GetBiggestClearanceValue();
1332
1333 for( ZONE* zone : m_zones )
1334 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1335
1336 for( FOOTPRINT* footprint : m_footprints )
1337 {
1338 for( PAD* pad : footprint->Pads() )
1339 {
1340 std::optional<int> override = pad->GetClearanceOverrides( nullptr );
1341
1342 if( override.has_value() )
1343 worstClearance = std::max( worstClearance, override.value() );
1344 }
1345
1346 for( ZONE* zone : footprint->Zones() )
1347 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
1348 }
1349
1350 m_maxClearanceValue = worstClearance;
1351 }
1352
1353 return m_maxClearanceValue.value_or( 0 );
1354};
1355
1356
1357void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<ZONE*>& aZones )
1358{
1359 std::vector<ZONE*> zones = aZones;
1360
1361 if( zones.empty() )
1362 zones = m_zones;
1363
1364 if( zones.empty() )
1365 return;
1366
1367 if( aReporter )
1368 aReporter->Report( _( "Tessellating copper zones..." ) );
1369
1371
1373 [&tp]( std::function<void()> aTask )
1374 {
1375 tp.detach_task( std::move( aTask ) );
1376 };
1377
1378 // Per layer, not per zone; a plane repeated across inner layers is otherwise one thread
1379 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> work;
1380
1381 for( ZONE* zone : zones )
1382 {
1383 // The format stores each fill's layer independently, so the layer set can miss one
1384 for( PCB_LAYER_ID layer : zone->GetFilledLayers() )
1385 work.emplace_back( zone, layer );
1386 }
1387
1388 std::vector<std::future<size_t>> returns;
1389
1390 returns.reserve( work.size() );
1391
1392 for( const std::pair<ZONE*, PCB_LAYER_ID>& item : work )
1393 {
1394 ZONE* zone = item.first;
1395 PCB_LAYER_ID layer = item.second;
1396
1397 returns.emplace_back( tp.submit_task(
1398 [aReporter, &submitter, zone, layer]() -> size_t
1399 {
1400 if( aReporter && aReporter->IsCancelled() )
1401 return 0;
1402
1403 zone->CacheTriangulation( layer, submitter );
1404
1405 return 1;
1406 } ) );
1407 }
1408
1409 // Finalize the triangulation threads
1410 for( const std::future<size_t>& ret : returns )
1411 {
1412 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1413
1414 while( status != std::future_status::ready )
1415 {
1416 if( aReporter )
1417 aReporter->KeepRefreshing();
1418
1419 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1420 }
1421 }
1422
1423 // A few hundred points board-wide, so not worth a task
1424 for( ZONE* zone : zones )
1425 {
1426 if( aReporter && aReporter->IsCancelled() )
1427 break;
1428
1429 zone->CacheOutlineTriangulation();
1430
1431 if( aReporter )
1432 aReporter->AdvanceProgress();
1433 }
1434}
1435
1436
1437void BOARD::RunOnNestedEmbeddedFiles( const std::function<void( EMBEDDED_FILES* )>& aFunction )
1438{
1439 for( FOOTPRINT* footprint : m_footprints )
1440 aFunction( footprint->GetEmbeddedFiles() );
1441}
1442
1443
1445{
1447 [&]( EMBEDDED_FILES* nested )
1448 {
1449 for( auto& [filename, embeddedFile] : nested->EmbeddedFileMap() )
1450 {
1452
1453 if( file )
1454 {
1455 embeddedFile->compressedEncodedData = file->compressedEncodedData;
1456 embeddedFile->decompressedData = file->decompressedData;
1457 embeddedFile->data_hash = file->data_hash;
1458 embeddedFile->is_valid = file->is_valid;
1459 }
1460 }
1461 } );
1462}
1463
1464
1465wxString BOARD::GetUniqueZoneName( const wxString& aBaseName, const ZONE* aExclude ) const
1466{
1467 auto inUse =
1468 [&]( const wxString& aName )
1469 {
1470 for( const ZONE* zone : m_zones )
1471 {
1472 if( zone != aExclude && zone->GetZoneName() == aName )
1473 return true;
1474 }
1475
1476 return false;
1477 };
1478
1479 return MakeUniqueZoneName( aBaseName, inUse );
1480}
1481
1482
1483wxString BOARD::MakeUniqueZoneName( const wxString& aBaseName, const std::function<bool( const wxString& )>& aInUse )
1484{
1485 if( aBaseName.IsEmpty() || !aInUse( aBaseName ) )
1486 return aBaseName;
1487
1488 // Strip a trailing _<number> so repeated copies increment the root (foo_1 -> foo_2),
1489 // instead of stacking suffixes (foo_1_1_1).
1490 wxString root = aBaseName;
1491
1492 if( aBaseName.Find( '_' ) != wxNOT_FOUND )
1493 {
1494 wxString suffix = aBaseName.AfterLast( '_' );
1495 bool allDigits = !suffix.IsEmpty();
1496
1497 for( wxUniChar ch : suffix )
1498 {
1499 if( !wxIsdigit( ch ) )
1500 {
1501 allDigits = false;
1502 break;
1503 }
1504 }
1505
1506 if( allDigits )
1507 root = aBaseName.BeforeLast( '_' );
1508 }
1509
1510 for( int i = 1;; ++i )
1511 {
1512 wxString candidate = wxString::Format( wxT( "%s_%d" ), root, i );
1513
1514 if( !aInUse( candidate ) )
1515 return candidate;
1516 }
1517}
1518
1519
1520void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
1521{
1522 if( aBoardItem == nullptr )
1523 {
1524 wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem nullptr" ) );
1525 return;
1526 }
1527
1528 switch( aBoardItem->Type() )
1529 {
1530 case PCB_NETINFO_T:
1531 m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
1532 break;
1533
1534 // this one uses a vector
1535 case PCB_MARKER_T:
1536 m_markers.push_back( (PCB_MARKER*) aBoardItem );
1537 break;
1538
1539 // this one uses a vector
1540 case PCB_GROUP_T:
1541 m_groups.push_back( (PCB_GROUP*) aBoardItem );
1542 break;
1543
1544 case PCB_CONSTRAINT_T:
1545 m_constraints.push_back( (PCB_CONSTRAINT*) aBoardItem );
1546 break;
1547
1548 // this one uses a vector
1549 case PCB_GENERATOR_T:
1550 m_generators.push_back( (PCB_GENERATOR*) aBoardItem );
1551 break;
1552
1553 // this one uses a vector
1554 case PCB_ZONE_T:
1555 m_zones.push_back( (ZONE*) aBoardItem );
1556 break;
1557
1558 case PCB_VIA_T:
1559 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1560 m_tracks.push_back( static_cast<PCB_VIA*>( aBoardItem ) );
1561 else
1562 m_tracks.push_front( static_cast<PCB_VIA*>( aBoardItem ) );
1563
1564 break;
1565
1566 case PCB_TRACE_T:
1567 case PCB_ARC_T:
1568 if( !IsCopperLayer( aBoardItem->GetLayer() ) )
1569 {
1570 // The only current known source of these is SWIG (KICAD-BY7, et al).
1571 // N.B. This inserts a small memory leak as we lose the track/via/arc.
1572 wxFAIL_MSG( wxString::Format( "BOARD::Add() Cannot place Track on non-copper layer: %d = %s",
1573 static_cast<int>( aBoardItem->GetLayer() ),
1574 GetLayerName( aBoardItem->GetLayer() ) ) );
1575 return;
1576 }
1577
1578 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1579 m_tracks.push_back( static_cast<PCB_TRACK*>( aBoardItem ) );
1580 else
1581 m_tracks.push_front( static_cast<PCB_TRACK*>( aBoardItem ) );
1582
1583 break;
1584
1585 case PCB_FOOTPRINT_T:
1586 {
1587 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aBoardItem );
1588
1589 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1590 m_footprints.push_back( footprint );
1591 else
1592 m_footprints.push_front( footprint );
1593
1594 break;
1595 }
1596
1597 case PCB_BARCODE_T:
1598 case PCB_DIM_ALIGNED_T:
1599 case PCB_DIM_CENTER_T:
1600 case PCB_DIM_RADIAL_T:
1602 case PCB_DIM_LEADER_T:
1603 case PCB_SHAPE_T:
1605 case PCB_FIELD_T:
1606 case PCB_TEXT_T:
1607 case PCB_TEXTBOX_T:
1608 case PCB_TABLE_T:
1609 case PCB_DRILL_CHART_T:
1610 case PCB_DRILL_MAP_T:
1611 case PCB_TARGET_T:
1612 case PCB_GRID_ITEM_T:
1613 if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
1614 m_drawings.push_back( aBoardItem );
1615 else
1616 m_drawings.push_front( aBoardItem );
1617
1618 break;
1619
1620 case PCB_POINT_T:
1621 // These aren't graphics as they have no physical presence
1622 m_points.push_back( static_cast<PCB_POINT*>( aBoardItem ) );
1623 break;
1624
1625 case PCB_TABLECELL_T:
1626 // Handled by parent table
1627 break;
1628
1629 default:
1630 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Add() item type %s not handled" ), aBoardItem->GetClass() ) );
1631 return;
1632 }
1633
1634 aBoardItem->SetParent( this );
1635 aBoardItem->ClearEditFlags();
1636
1637 // Index only after the item is accepted and parented, so a rejected item never lingers as a
1638 // dangling cache entry and an indexed item can always reach its board through its parent.
1639 CacheItemById( *aBoardItem );
1640
1641 if( aBoardItem->Type() == PCB_FOOTPRINT_T || BaseType( aBoardItem->Type() ) == PCB_TABLE_T )
1642 CacheChildrenById( *aBoardItem );
1643
1644 if( !aSkipConnectivity )
1645 m_connectivity->Add( aBoardItem );
1646
1647 if( aMode != ADD_MODE::BULK_INSERT && aMode != ADD_MODE::BULK_APPEND )
1649
1650 noteDrillModelChange( aBoardItem );
1651}
1652
1653
1654void BOARD::FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems )
1655{
1657
1658 for( BOARD_ITEM* item : aNewItems )
1659 noteDrillModelChange( item );
1660}
1661
1662
1663void BOARD::FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems )
1664{
1665 InvokeListeners( &BOARD_LISTENER::OnBoardItemsRemoved, *this, aRemovedItems );
1666
1667 for( BOARD_ITEM* item : aRemovedItems )
1668 noteDrillModelChange( item );
1669}
1670
1671
1673{
1674 for( int ii = (int) m_zones.size() - 1; ii >= 0; --ii )
1675 {
1676 ZONE* zone = m_zones[ii];
1677
1678 if( zone->IsTeardropArea() && zone->HasFlag( STRUCT_DELETED ) )
1679 {
1680 m_itemIndex.Unbind( zone->m_Uuid );
1681 m_zones.erase( m_zones.begin() + ii );
1683 m_connectivity->Remove( zone );
1684
1685 aCommit.Removed( zone );
1686 }
1687 }
1688}
1689
1690
1691void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
1692{
1693 // find these calls and fix them! Don't send me no stinking' nullptr.
1694 wxASSERT( aBoardItem );
1695
1696 // This is redundant with BOARD_COMMIT::Push but necessary to support SWIG interaction
1697 // until the SWIG API is completely removed (since it doesn't use the commit system)
1698 if( EDA_GROUP* parentGroup = aBoardItem->GetParentGroup();
1699 parentGroup && !( parentGroup->AsEdaItem()->GetFlags() & STRUCT_DELETED ) )
1700 {
1701 parentGroup->RemoveItem( aBoardItem );
1702 }
1703
1704 m_itemIndex.Unbind( aBoardItem->m_Uuid );
1705
1706 switch( aBoardItem->Type() )
1707 {
1708 case PCB_NETINFO_T:
1709 {
1710 NETINFO_ITEM* netItem = static_cast<NETINFO_ITEM*>( aBoardItem );
1711 NETINFO_ITEM* unconnected = m_NetInfo.GetNetItem( NETINFO_LIST::UNCONNECTED );
1712
1713 for( BOARD_CONNECTED_ITEM* boardItem : AllConnectedItems() )
1714 {
1715 if( boardItem->GetNet() == netItem )
1716 boardItem->SetNet( unconnected );
1717 }
1718
1719 m_NetInfo.RemoveNet( netItem );
1720 break;
1721 }
1722
1723 case PCB_MARKER_T:
1724 std::erase( m_markers, aBoardItem );
1725 break;
1726
1727 case PCB_GROUP_T:
1728 std::erase( m_groups, aBoardItem );
1729 break;
1730
1731 case PCB_CONSTRAINT_T:
1732 std::erase( m_constraints, aBoardItem );
1733 break;
1734
1735 case PCB_ZONE_T:
1736 std::erase( m_zones, aBoardItem );
1737 break;
1738
1739 case PCB_POINT_T:
1740 std::erase( m_points, aBoardItem );
1741 break;
1742
1743 case PCB_GENERATOR_T:
1744 std::erase( m_generators, aBoardItem );
1745 break;
1746
1747 case PCB_FOOTPRINT_T:
1748 std::erase( m_footprints, aBoardItem );
1749 UncacheChildrenById( *aBoardItem );
1750
1751 break;
1752
1753 case PCB_TRACE_T:
1754 case PCB_ARC_T:
1755 case PCB_VIA_T:
1756 std::erase( m_tracks, aBoardItem );
1757 break;
1758
1759 case PCB_BARCODE_T:
1760 case PCB_DIM_ALIGNED_T:
1761 case PCB_DIM_CENTER_T:
1762 case PCB_DIM_RADIAL_T:
1764 case PCB_DIM_LEADER_T:
1765 case PCB_SHAPE_T:
1767 case PCB_FIELD_T:
1768 case PCB_TEXT_T:
1769 case PCB_TEXTBOX_T:
1770 case PCB_TABLE_T:
1771 case PCB_DRILL_CHART_T:
1772 case PCB_DRILL_MAP_T:
1773 case PCB_TARGET_T:
1774 case PCB_GRID_ITEM_T:
1775 std::erase( m_drawings, aBoardItem );
1776
1777 if( BaseType( aBoardItem->Type() ) == PCB_TABLE_T )
1778 UncacheChildrenById( *aBoardItem );
1779
1780 break;
1781
1782 case PCB_TABLECELL_T:
1783 // Handled by parent table
1784 break;
1785
1786 // other types may use linked list
1787 default:
1788 wxFAIL_MSG( wxString::Format( wxT( "BOARD::Remove() item type %s not handled" ), aBoardItem->GetClass() ) );
1789 }
1790
1791 aBoardItem->SetFlags( STRUCT_DELETED );
1792
1793 m_connectivity->Remove( aBoardItem );
1794
1795 // Bump here, not in ~FOOTPRINT/~ZONE, so an item kept alive after removal (undo) still invalidates
1797
1798 if( aRemoveMode != REMOVE_MODE::BULK )
1800
1801 noteDrillModelChange( aBoardItem );
1802}
1803
1804
1805void BOARD::RemoveAll( std::initializer_list<KICAD_T> aTypes )
1806{
1807 std::vector<BOARD_ITEM*> removed;
1808 std::vector<NETINFO_ITEM*> removedNets;
1809
1810 for( const KICAD_T& type : aTypes )
1811 {
1812 switch( type )
1813 {
1814 case PCB_NETINFO_T:
1815 for( NETINFO_ITEM* item : m_NetInfo )
1816 {
1817 removed.emplace_back( item );
1818 removedNets.emplace_back( item );
1819 }
1820
1821 // Listeners must observe live pointers during FinalizeBulkRemove;
1822 // free after notification (issue 24100).
1823 m_NetInfo.detachAll();
1824 break;
1825
1826 case PCB_MARKER_T:
1827 std::copy( m_markers.begin(), m_markers.end(), std::back_inserter( removed ) );
1828 m_markers.clear();
1829 break;
1830
1831 case PCB_GROUP_T:
1832 std::copy( m_groups.begin(), m_groups.end(), std::back_inserter( removed ) );
1833 m_groups.clear();
1834 break;
1835
1836 case PCB_CONSTRAINT_T:
1837 std::copy( m_constraints.begin(), m_constraints.end(), std::back_inserter( removed ) );
1838 m_constraints.clear();
1839 break;
1840
1841 case PCB_POINT_T:
1842 std::copy( m_points.begin(), m_points.end(), std::back_inserter( removed ) );
1843 m_points.clear();
1844 break;
1845
1846 case PCB_ZONE_T:
1847 std::copy( m_zones.begin(), m_zones.end(), std::back_inserter( removed ) );
1848 m_zones.clear();
1849 break;
1850
1851 case PCB_GENERATOR_T:
1852 std::copy( m_generators.begin(), m_generators.end(), std::back_inserter( removed ) );
1853 m_generators.clear();
1854 break;
1855
1856 case PCB_FOOTPRINT_T:
1857 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( removed ) );
1858 m_footprints.clear();
1859 break;
1860
1861 case PCB_TRACE_T:
1862 std::copy( m_tracks.begin(), m_tracks.end(), std::back_inserter( removed ) );
1863 m_tracks.clear();
1864 break;
1865
1866 case PCB_ARC_T:
1867 case PCB_VIA_T:
1868 wxFAIL_MSG( wxT( "Use PCB_TRACE_T to remove all tracks, arcs, and vias" ) );
1869 break;
1870
1871 case PCB_SHAPE_T:
1872 std::copy( m_drawings.begin(), m_drawings.end(), std::back_inserter( removed ) );
1873 m_drawings.clear();
1874 break;
1875
1876 case PCB_DIM_ALIGNED_T:
1877 case PCB_DIM_CENTER_T:
1878 case PCB_DIM_RADIAL_T:
1880 case PCB_DIM_LEADER_T:
1882 case PCB_FIELD_T:
1883 case PCB_TEXT_T:
1884 case PCB_TEXTBOX_T:
1885 case PCB_TABLE_T:
1886 case PCB_DRILL_CHART_T:
1887 case PCB_DRILL_MAP_T:
1888 case PCB_TARGET_T:
1889 case PCB_BARCODE_T:
1890 wxFAIL_MSG( wxT( "Use PCB_SHAPE_T to remove all graphics and text" ) );
1891 break;
1892
1893 default:
1894 wxFAIL_MSG( wxT( "BOARD::RemoveAll() needs more ::Type() support" ) );
1895 }
1896 }
1897
1898 for( BOARD_ITEM* item : removed )
1899 m_connectivity->Remove( item );
1900
1902
1904
1905 FinalizeBulkRemove( removed );
1906
1907 for( NETINFO_ITEM* item : removedNets )
1908 delete item;
1909}
1910
1911
1913{
1914 PCB_LAYER_COLLECTOR collector;
1915
1916 collector.SetLayerId( aLayer );
1918
1919 if( collector.GetCount() != 0 )
1920 {
1921 // Skip items owned by footprints and footprints when building
1922 // the actual list of removed layers: these items are not removed
1923 for( int i = 0; i < collector.GetCount(); i++ )
1924 {
1925 BOARD_ITEM* item = collector[i];
1926
1927 if( item->Type() == PCB_FOOTPRINT_T || item->GetParentFootprint() )
1928 continue;
1929
1930 // Vias are on multiple adjacent layers, but only the top and
1931 // the bottom layers are stored. So there are issues only if one
1932 // is on a removed layer
1933 if( item->Type() == PCB_VIA_T )
1934 {
1935 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1936
1937 if( via->GetViaType() == VIATYPE::THROUGH )
1938 continue;
1939 else
1940 {
1941 PCB_LAYER_ID top_layer;
1942 PCB_LAYER_ID bottom_layer;
1943 via->LayerPair( &top_layer, &bottom_layer );
1944
1945 if( top_layer != aLayer && bottom_layer != aLayer )
1946 continue;
1947 }
1948 }
1949
1950 return true;
1951 }
1952 }
1953
1954 return false;
1955}
1956
1957
1959{
1960 bool modified = false;
1961 bool removedItemLayers = false;
1962 PCB_LAYER_COLLECTOR collector;
1963
1964 collector.SetLayerId( aLayer );
1966
1967 for( int i = 0; i < collector.GetCount(); i++ )
1968 {
1969 BOARD_ITEM* item = collector[i];
1970
1971 // Do not remove/change an item owned by a footprint
1972 if( item->GetParentFootprint() )
1973 continue;
1974
1975 // Do not remove footprints
1976 if( item->Type() == PCB_FOOTPRINT_T )
1977 continue;
1978
1979 // Note: vias are specific. They are only on copper layers, and
1980 // do not use a layer set, only store the copper top and the copper bottom.
1981 // So reinit the layer set does not work with vias
1982 if( item->Type() == PCB_VIA_T )
1983 {
1984 PCB_VIA* via = static_cast<PCB_VIA*>( item );
1985
1986 if( via->GetViaType() == VIATYPE::THROUGH )
1987 {
1988 removedItemLayers = true;
1989 continue;
1990 }
1991 else if( via->IsOnLayer( aLayer ) )
1992 {
1993 PCB_LAYER_ID top_layer;
1994 PCB_LAYER_ID bottom_layer;
1995 via->LayerPair( &top_layer, &bottom_layer );
1996
1997 if( top_layer == aLayer || bottom_layer == aLayer )
1998 {
1999 // blind/buried vias with a top or bottom layer on a removed layer
2000 // are removed. Perhaps one could just modify the top/bottom layer,
2001 // but I am not sure this is better.
2002 Remove( item );
2003 delete item;
2004 modified = true;
2005 }
2006
2007 removedItemLayers = true;
2008 }
2009 }
2010 else if( item->IsOnLayer( aLayer ) )
2011 {
2012 LSET layers = item->GetLayerSet();
2013
2014 layers.reset( aLayer );
2015
2016 if( layers.any() )
2017 {
2018 item->SetLayerSet( layers );
2019 }
2020 else
2021 {
2022 Remove( item );
2023 delete item;
2024 modified = true;
2025 }
2026
2027 removedItemLayers = true;
2028 }
2029 }
2030
2031 if( removedItemLayers )
2033
2034 return modified;
2035}
2036
2037
2038wxString BOARD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
2039{
2040 return wxString::Format( _( "PCB" ) );
2041}
2042
2043
2045{
2046 INSPECTOR_FUNC inspector = [&]( EDA_ITEM* descendant, void* aTestData )
2047 {
2048 PCB_DIMENSION_BASE* dimension = static_cast<PCB_DIMENSION_BASE*>( descendant );
2049
2050 if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC )
2051 {
2052 dimension->UpdateUnits();
2053
2054 if( aView )
2055 aView->Update( dimension );
2056 }
2057
2059 };
2060
2061 aItem->Visit( inspector, nullptr,
2063}
2064
2065
2067{
2068 for( PCB_MARKER* marker : m_markers )
2069 m_itemIndex.Unbind( marker->m_Uuid );
2070
2071 for( PCB_MARKER* marker : m_markers )
2072 delete marker;
2073
2074 m_markers.clear();
2076}
2077
2078
2079void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
2080{
2081 // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
2082 std::vector<PCB_MARKER*> remaining;
2083
2084 for( PCB_MARKER* marker : m_markers )
2085 {
2086 if( ( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION && aExclusions )
2087 || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) )
2088 {
2089 m_itemIndex.Unbind( marker->m_Uuid );
2090 delete marker;
2091 }
2092 else
2093 {
2094 remaining.push_back( marker );
2095 }
2096 }
2097
2098 m_markers = std::move( remaining );
2100}
2101
2102
2104{
2105 std::vector<FOOTPRINT*> footprints;
2106 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( footprints ) );
2107
2109
2110 for( FOOTPRINT* footprint : footprints )
2111 delete footprint;
2112}
2113
2114
2116{
2117 std::vector<FOOTPRINT*> footprints;
2118 std::copy( m_footprints.begin(), m_footprints.end(), std::back_inserter( footprints ) );
2119
2121
2122 for( FOOTPRINT* footprint : footprints )
2123 footprint->SetParent( nullptr );
2124}
2125
2126
2127static PCB_TABLECELL* findTableCell( const BOARD_ITEM* aDrawing, const KIID& aID )
2128{
2129 if( BaseType( aDrawing->Type() ) != PCB_TABLE_T )
2130 return nullptr;
2131
2132 for( PCB_TABLECELL* cell : static_cast<const PCB_TABLE*>( aDrawing )->GetCells() )
2133 {
2134 if( cell->m_Uuid == aID )
2135 return cell;
2136 }
2137
2138 return nullptr;
2139}
2140
2141
2142BOARD_ITEM* BOARD::ResolveItem( const KIID& aID, bool aAllowNullptrReturn ) const
2143{
2144 if( aID == niluuid )
2145 return nullptr;
2146
2147 if( BOARD_ITEM* cached = m_itemIndex.Find( aID ) )
2148 return cached;
2149
2150 // Cache the item and return it.
2151 // The item MUST match the requested UUID.
2152 const auto cacheAndReturn =
2153 [&]( BOARD_ITEM& aItem ) -> BOARD_ITEM*
2154 {
2155 wxASSERT_MSG( aItem.m_Uuid == aID,
2156 wxT( "BOARD::ResolveItem() must only return an item that carries the requested UUID" ) );
2157 CacheItemById( aItem );
2158 return &aItem;
2159 };
2160
2161 // Linear scan fallback for items not in the cache. Any hit is cached so
2162 // subsequent lookups for the same item are O(1).
2163
2164 for( PCB_GROUP* group : m_groups )
2165 {
2166 if( group->m_Uuid == aID )
2167 return cacheAndReturn( *group );
2168 }
2169
2170 for( PCB_CONSTRAINT* constraint : m_constraints )
2171 {
2172 if( constraint->m_Uuid == aID )
2173 return cacheAndReturn( *constraint );
2174 }
2175
2176 for( PCB_GENERATOR* generator : m_generators )
2177 {
2178 if( generator->m_Uuid == aID )
2179 return cacheAndReturn( *generator );
2180 }
2181
2182 for( PCB_TRACK* track : Tracks() )
2183 {
2184 if( track->m_Uuid == aID )
2185 return cacheAndReturn( *track );
2186 }
2187
2188 for( FOOTPRINT* footprint : Footprints() )
2189 {
2190 if( footprint->m_Uuid == aID )
2191 return cacheAndReturn( *footprint );
2192
2193 for( PAD* pad : footprint->Pads() )
2194 {
2195 if( pad->m_Uuid == aID )
2196 return cacheAndReturn( *pad );
2197 }
2198
2199 for( PCB_FIELD* field : footprint->GetFields() )
2200 {
2201 wxCHECK2( field, continue );
2202
2203 if( field && field->m_Uuid == aID )
2204 return cacheAndReturn( *field );
2205 }
2206
2207 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
2208 {
2209 if( PCB_TABLECELL* cell = findTableCell( drawing, aID ) )
2210 return cacheAndReturn( *cell );
2211
2212 if( drawing->m_Uuid == aID )
2213 return cacheAndReturn( *drawing );
2214 }
2215
2216 for( BOARD_ITEM* zone : footprint->Zones() )
2217 {
2218 if( zone->m_Uuid == aID )
2219 return cacheAndReturn( *zone );
2220 }
2221
2222 for( PCB_GROUP* group : footprint->Groups() )
2223 {
2224 if( group->m_Uuid == aID )
2225 return cacheAndReturn( *group );
2226 }
2227
2228 for( PCB_CONSTRAINT* constraint : footprint->Constraints() )
2229 {
2230 if( constraint->m_Uuid == aID )
2231 return cacheAndReturn( *constraint );
2232 }
2233
2234 for( PCB_POINT* point : footprint->Points() )
2235 {
2236 if( point->m_Uuid == aID )
2237 return cacheAndReturn( *point );
2238 }
2239
2240 for( PCB_3D_BODY* body : footprint->Bodies() )
2241 {
2242 if( body->m_Uuid == aID )
2243 return cacheAndReturn( *body );
2244 }
2245 }
2246
2247 for( ZONE* zone : Zones() )
2248 {
2249 if( zone->m_Uuid == aID )
2250 return cacheAndReturn( *zone );
2251 }
2252
2253 for( BOARD_ITEM* drawing : Drawings() )
2254 {
2255 if( PCB_TABLECELL* cell = findTableCell( drawing, aID ) )
2256 return cacheAndReturn( *cell );
2257
2258 if( drawing->m_Uuid == aID )
2259 return cacheAndReturn( *drawing );
2260 }
2261
2262 for( PCB_MARKER* marker : m_markers )
2263 {
2264 if( marker->m_Uuid == aID )
2265 return cacheAndReturn( *marker );
2266 }
2267
2268 for( PCB_POINT* point : m_points )
2269 {
2270 if( point->m_Uuid == aID )
2271 return cacheAndReturn( *point );
2272 }
2273
2274 for( NETINFO_ITEM* netInfo : m_NetInfo )
2275 {
2276 if( netInfo->m_Uuid == aID )
2277 return cacheAndReturn( *netInfo );
2278 }
2279
2280 if( m_Uuid == aID )
2281 return const_cast<BOARD*>( this );
2282
2283 // Not found; weak reference has been deleted.
2284 if( aAllowNullptrReturn )
2285 return nullptr;
2286
2288}
2289
2290
2291
2293{
2294 std::set<KIID> ids;
2295 int duplicates = 0;
2296
2297 auto processItem =
2298 [&]( BOARD_ITEM* aItem )
2299 {
2300 wxCHECK2( aItem, return );
2301
2302 if( ids.count( aItem->m_Uuid ) )
2303 {
2304 duplicates++;
2305 RebindItemUuid( *aItem, KIID() );
2306 }
2307
2308 ids.insert( aItem->m_Uuid );
2309 };
2310
2311 // Footprint IDs are the most important, so give them the first crack at "claiming" a
2312 // particular KIID.
2313 for( FOOTPRINT* footprint : Footprints() )
2314 processItem( footprint );
2315
2316 // After that the principal use is for DRC marker pointers, which are most likely to pads
2317 // or tracks.
2318 for( FOOTPRINT* footprint : Footprints() )
2319 {
2320 for( PAD* pad : footprint->Pads() )
2321 processItem( pad );
2322 }
2323
2324 for( PCB_TRACK* track : Tracks() )
2325 processItem( track );
2326
2327 // From here out I don't think order matters much.
2328 for( FOOTPRINT* footprint : Footprints() )
2329 {
2330 processItem( &footprint->Reference() );
2331 processItem( &footprint->Value() );
2332
2333 for( BOARD_ITEM* item : footprint->GraphicalItems() )
2334 processItem( item );
2335
2336 for( PCB_3D_BODY* body : footprint->Bodies() )
2337 processItem( body );
2338
2339 for( ZONE* zone : footprint->Zones() )
2340 processItem( zone );
2341
2342 for( PCB_GROUP* group : footprint->Groups() )
2343 processItem( group );
2344 }
2345
2346 // Everything owned by the board not handled above.
2347 for( BOARD_ITEM* item : GetItemSet() )
2348 {
2349 // Top-level footprints and tracks were handled above.
2350 switch( item->Type() )
2351 {
2352 case PCB_FOOTPRINT_T:
2353 case PCB_TRACE_T:
2354 case PCB_ARC_T:
2355 case PCB_VIA_T:
2356 break;
2357
2358 default:
2359 processItem( item );
2360 break;
2361 }
2362 }
2363
2364 return duplicates;
2365}
2366
2367
2368wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
2369{
2370 wxString newbuf;
2371 size_t sourceLen = aSource.length();
2372
2373 for( size_t i = 0; i < sourceLen; ++i )
2374 {
2375 // Check for escaped expressions: \${ or \@{
2376 // These should be copied verbatim without any ref→KIID conversion
2377 if( aSource[i] == '\\' && i + 2 < sourceLen && aSource[i + 2] == '{' &&
2378 ( aSource[i + 1] == '$' || aSource[i + 1] == '@' ) )
2379 {
2380 // Copy the escape sequence and the entire escaped expression
2381 newbuf.append( aSource[i] ); // backslash
2382 newbuf.append( aSource[i + 1] ); // $ or @
2383 newbuf.append( aSource[i + 2] ); // {
2384 i += 2;
2385
2386 // Find and copy everything until the matching closing brace
2387 int braceDepth = 1;
2388 for( i = i + 1; i < sourceLen && braceDepth > 0; ++i )
2389 {
2390 if( aSource[i] == '{' )
2391 braceDepth++;
2392 else if( aSource[i] == '}' )
2393 braceDepth--;
2394
2395 newbuf.append( aSource[i] );
2396 }
2397 i--; // Back up one since the for loop will increment
2398 continue;
2399 }
2400
2401 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' )
2402 {
2403 wxString token;
2404 bool isCrossRef = false;
2405
2406 for( i = i + 2; i < sourceLen; ++i )
2407 {
2408 if( aSource[i] == '}' )
2409 break;
2410
2411 if( aSource[i] == ':' )
2412 isCrossRef = true;
2413
2414 token.append( aSource[i] );
2415 }
2416
2417 if( isCrossRef )
2418 {
2419 wxString remainder;
2420 wxString ref = token.BeforeFirst( ':', &remainder );
2421
2422 for( const FOOTPRINT* footprint : Footprints() )
2423 {
2424 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
2425 {
2426 wxString test( remainder );
2427
2428 if( footprint->ResolveTextVar( &test ) )
2429 token = footprint->m_Uuid.AsString() + wxT( ":" ) + remainder;
2430
2431 break;
2432 }
2433 }
2434 }
2435
2436 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
2437 }
2438 else
2439 {
2440 newbuf.append( aSource[i] );
2441 }
2442 }
2443
2444 return newbuf;
2445}
2446
2447
2448wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
2449{
2450 wxString newbuf;
2451 size_t sourceLen = aSource.length();
2452
2453 for( size_t i = 0; i < sourceLen; ++i )
2454 {
2455 // Check for escaped expressions: \${ or \@{
2456 // These should be copied verbatim without any KIID→ref conversion
2457 if( aSource[i] == '\\' && i + 2 < sourceLen && aSource[i + 2] == '{' &&
2458 ( aSource[i + 1] == '$' || aSource[i + 1] == '@' ) )
2459 {
2460 // Copy the escape sequence and the entire escaped expression
2461 newbuf.append( aSource[i] ); // backslash
2462 newbuf.append( aSource[i + 1] ); // $ or @
2463 newbuf.append( aSource[i + 2] ); // {
2464 i += 2;
2465
2466 // Find and copy everything until the matching closing brace
2467 int braceDepth = 1;
2468 for( i = i + 1; i < sourceLen && braceDepth > 0; ++i )
2469 {
2470 if( aSource[i] == '{' )
2471 braceDepth++;
2472 else if( aSource[i] == '}' )
2473 braceDepth--;
2474
2475 newbuf.append( aSource[i] );
2476 }
2477 i--; // Back up one since the for loop will increment
2478 continue;
2479 }
2480
2481 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' )
2482 {
2483 wxString token;
2484 bool isCrossRef = false;
2485
2486 for( i = i + 2; i < sourceLen; ++i )
2487 {
2488 if( aSource[i] == '}' )
2489 break;
2490
2491 if( aSource[i] == ':' )
2492 isCrossRef = true;
2493
2494 token.append( aSource[i] );
2495 }
2496
2497 if( isCrossRef )
2498 {
2499 wxString remainder;
2500 wxString ref = token.BeforeFirst( ':', &remainder );
2501 BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true );
2502
2503 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
2504 {
2505 token = static_cast<FOOTPRINT*>( refItem )->GetReference() + wxT( ":" ) + remainder;
2506 }
2507 }
2508
2509 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
2510 }
2511 else
2512 {
2513 newbuf.append( aSource[i] );
2514 }
2515 }
2516
2517 return newbuf;
2518}
2519
2520
2521unsigned BOARD::GetNodesCount( int aNet ) const
2522{
2523 unsigned retval = 0;
2524
2525 for( FOOTPRINT* footprint : Footprints() )
2526 {
2527 for( PAD* pad : footprint->Pads() )
2528 {
2529 if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
2530 retval++;
2531 }
2532 }
2533
2534 return retval;
2535}
2536
2537
2538BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly, bool aPhysicalLayersOnly ) const
2539{
2540 BOX2I bbox;
2541 LSET visible = GetVisibleLayers();
2542
2543 if( aPhysicalLayersOnly )
2544 visible &= LSET::PhysicalLayersMask();
2545
2546 // If the board is just showing a footprint, we want all footprint layers included in the
2547 // bounding box
2548 if( IsFootprintHolder() )
2549 visible.set();
2550
2551 if( aBoardEdgesOnly )
2552 visible.set( Edge_Cuts );
2553
2554 // Check shapes, dimensions, texts, and fiducials
2555 for( BOARD_ITEM* item : m_drawings )
2556 {
2557 if( aBoardEdgesOnly && ( item->Type() != PCB_SHAPE_T || item->GetLayer() != Edge_Cuts ) )
2558 continue;
2559
2560 if( ( item->GetLayerSet() & visible ).any() )
2561 bbox.Merge( item->GetBoundingBox() );
2562 }
2563
2564 // Check footprints
2565 for( FOOTPRINT* footprint : m_footprints )
2566 {
2567 if( aBoardEdgesOnly )
2568 {
2569 for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
2570 {
2571 if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_SHAPE_T )
2572 bbox.Merge( edge->GetBoundingBox() );
2573 }
2574 }
2575 else if( ( footprint->GetLayerSet() & visible ).any() )
2576 {
2577 bbox.Merge( footprint->GetBoundingBox( true ) );
2578 }
2579 }
2580
2581 if( !aBoardEdgesOnly )
2582 {
2583 // Check tracks
2584 for( PCB_TRACK* track : m_tracks )
2585 {
2586 if( ( track->GetLayerSet() & visible ).any() )
2587 bbox.Merge( track->GetBoundingBox() );
2588 }
2589
2590 // Check zones
2591 for( ZONE* aZone : m_zones )
2592 {
2593 if( ( aZone->GetLayerSet() & visible ).any() )
2594 bbox.Merge( aZone->GetBoundingBox() );
2595 }
2596
2597 for( PCB_POINT* point : m_points )
2598 {
2599 bbox.Merge( point->GetBoundingBox() );
2600 }
2601 }
2602
2603 return bbox;
2604}
2605
2606
2607void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
2608{
2609 int padCount = 0;
2610 int viaCount = 0;
2611 int trackSegmentCount = 0;
2612 std::set<int> netCodes;
2613 int unconnected = GetConnectivity()->GetUnconnectedCount( true );
2614
2615 for( PCB_TRACK* item : m_tracks )
2616 {
2617 if( item->Type() == PCB_VIA_T )
2618 viaCount++;
2619 else
2620 trackSegmentCount++;
2621
2622 if( item->GetNetCode() > 0 )
2623 netCodes.insert( item->GetNetCode() );
2624 }
2625
2626 for( FOOTPRINT* footprint : Footprints() )
2627 {
2628 for( PAD* pad : footprint->Pads() )
2629 {
2630 padCount++;
2631
2632 if( pad->GetNetCode() > 0 )
2633 netCodes.insert( pad->GetNetCode() );
2634 }
2635 }
2636
2637 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%d" ), padCount ) );
2638 aList.emplace_back( _( "Vias" ), wxString::Format( wxT( "%d" ), viaCount ) );
2639 aList.emplace_back( _( "Track Segments" ), wxString::Format( wxT( "%d" ), trackSegmentCount ) );
2640 aList.emplace_back( _( "Nets" ), wxString::Format( wxT( "%d" ), (int) netCodes.size() ) );
2641 aList.emplace_back( _( "Unrouted" ), wxString::Format( wxT( "%d" ), unconnected ) );
2642}
2643
2644
2645INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const std::vector<KICAD_T>& scanTypes )
2646{
2647#if 0 && defined( DEBUG )
2648 std::cout << GetClass().mb_str() << ' ';
2649#endif
2650
2651 bool footprintsScanned = false;
2652 bool drawingsScanned = false;
2653 bool tracksScanned = false;
2654
2655 for( KICAD_T scanType : scanTypes )
2656 {
2657 switch( scanType )
2658 {
2659 case PCB_T:
2660 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
2661 return INSPECT_RESULT::QUIT;
2662
2663 break;
2664
2665 /*
2666 * Instances of the requested KICAD_T live in a list, either one that I manage, or one
2667 * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
2668 * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
2669 */
2670
2671 case PCB_FOOTPRINT_T:
2672 case PCB_PAD_T:
2673 case PCB_SHAPE_T:
2675 case PCB_FIELD_T:
2676 case PCB_TEXT_T:
2677 case PCB_TEXTBOX_T:
2678 case PCB_TABLE_T:
2679 case PCB_DRILL_CHART_T:
2680 case PCB_DRILL_MAP_T:
2681 case PCB_TABLECELL_T:
2682 case PCB_DIM_ALIGNED_T:
2683 case PCB_DIM_CENTER_T:
2684 case PCB_DIM_RADIAL_T:
2686 case PCB_DIM_LEADER_T:
2687 case PCB_TARGET_T:
2688 case PCB_BARCODE_T:
2689 case PCB_GRID_ITEM_T:
2690 if( !footprintsScanned )
2691 {
2692 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2693 return INSPECT_RESULT::QUIT;
2694
2695 footprintsScanned = true;
2696 }
2697
2698 if( !drawingsScanned )
2699 {
2700 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2701 return INSPECT_RESULT::QUIT;
2702
2703 drawingsScanned = true;
2704 }
2705
2706 break;
2707
2708 case PCB_VIA_T:
2709 case PCB_TRACE_T:
2710 case PCB_ARC_T:
2711 if( !tracksScanned )
2712 {
2713 if( IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2714 return INSPECT_RESULT::QUIT;
2715
2716 tracksScanned = true;
2717 }
2718
2719 break;
2720
2721 case PCB_MARKER_T:
2722 for( PCB_MARKER* marker : m_markers )
2723 {
2724 if( marker->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2725 return INSPECT_RESULT::QUIT;
2726 }
2727
2728 break;
2729
2730 case PCB_POINT_T:
2731 for( PCB_POINT* point : m_points )
2732 {
2733 if( point->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2734 return INSPECT_RESULT::QUIT;
2735 }
2736
2737 break;
2738
2739 case PCB_ZONE_T:
2740 if( !footprintsScanned )
2741 {
2742 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2743 return INSPECT_RESULT::QUIT;
2744
2745 footprintsScanned = true;
2746 }
2747
2748 for( ZONE* zone : m_zones )
2749 {
2750 if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2751 return INSPECT_RESULT::QUIT;
2752 }
2753
2754 break;
2755
2756 case PCB_GENERATOR_T:
2757 if( !footprintsScanned )
2758 {
2759 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT )
2760 return INSPECT_RESULT::QUIT;
2761
2762 footprintsScanned = true;
2763 }
2764
2765 if( IterateForward<PCB_GENERATOR*>( m_generators, inspector, testData, { scanType } )
2767 {
2768 return INSPECT_RESULT::QUIT;
2769 }
2770
2771 break;
2772
2773 case PCB_GROUP_T:
2774 if( IterateForward<PCB_GROUP*>( m_groups, inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
2775 return INSPECT_RESULT::QUIT;
2776
2777 break;
2778
2779 case PCB_CONSTRAINT_T:
2780 if( IterateForward<PCB_CONSTRAINT*>( m_constraints, inspector, testData, { scanType } )
2782 {
2783 return INSPECT_RESULT::QUIT;
2784 }
2785
2786 break;
2787
2788 default:
2789 break;
2790 }
2791 }
2792
2794}
2795
2796
2797NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
2798{
2799 // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
2800 // zero is reserved for "no connection" and is not actually a net.
2801 // nullptr is returned for non valid netcodes
2802
2803 if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
2805 else
2806 return m_NetInfo.GetNetItem( aNetcode );
2807}
2808
2809
2810NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
2811{
2812 return m_NetInfo.GetNetItem( aNetname );
2813}
2814
2815
2816int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
2817{
2818 int rv = 0;
2819 int count = 0;
2820
2821 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2822 {
2823 int ch = *it;
2824
2825 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
2826 {
2827 continue;
2828 }
2829 else if( ch == '+' )
2830 {
2831 aComplementNet = wxT( "-" );
2832 rv = 1;
2833 }
2834 else if( ch == '-' )
2835 {
2836 aComplementNet = wxT( "+" );
2837 rv = -1;
2838 }
2839 else if( ch == 'N' )
2840 {
2841 aComplementNet = wxT( "P" );
2842 rv = -1;
2843 }
2844 else if( ch == 'P' )
2845 {
2846 aComplementNet = wxT( "N" );
2847 rv = 1;
2848 }
2849 else
2850 {
2851 break;
2852 }
2853 }
2854
2855 if( rv != 0 && count >= 1 )
2856 {
2857 aComplementNet = aNetName.Left( aNetName.length() - count ) + aComplementNet + aNetName.Right( count - 1 );
2858 }
2859
2860 return rv;
2861}
2862
2863
2865{
2866 if( aNet )
2867 {
2868 wxString refName = aNet->GetNetname();
2869 wxString coupledNetName;
2870
2871 if( MatchDpSuffix( refName, coupledNetName ) )
2872 return FindNet( coupledNetName );
2873 }
2874
2875 return nullptr;
2876}
2877
2878
2879FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
2880{
2881 for( FOOTPRINT* footprint : m_footprints )
2882 {
2883 if( aReference == footprint->GetReference() )
2884 return footprint;
2885 }
2886
2887 return nullptr;
2888}
2889
2890
2892{
2893 for( FOOTPRINT* footprint : m_footprints )
2894 {
2895 if( footprint->GetPath() == aPath )
2896 return footprint;
2897 }
2898
2899 return nullptr;
2900}
2901
2902
2903PAD* BOARD::FindPadByUuid( const KIID& aUuid ) const
2904{
2905 for( FOOTPRINT* footprint : m_footprints )
2906 {
2907 if( PAD* pad = footprint->FindPadByUuid( aUuid ) )
2908 return pad;
2909 }
2910
2911 return nullptr;
2912}
2913
2914
2915void BOARD::ReplaceNetChainTerminalPad( const wxString& aNetChain, const KIID& aPrev, const KIID& aNew )
2916{
2917 PAD* newPad = FindPadByUuid( aNew );
2918
2919 for( NETINFO_ITEM* net : m_NetInfo )
2920 {
2921 if( net->GetNetChain() == aNetChain )
2922 {
2923 for( int i = 0; i < 2; ++i )
2924 {
2925 PAD* pad = net->GetTerminalPad( i );
2926
2927 if( pad && pad->m_Uuid == aPrev )
2928 net->SetTerminalPad( i, newPad );
2929 }
2930 }
2931 }
2932}
2933
2934
2936{
2937 std::set<wxString> names;
2938
2939 for( const NETINFO_ITEM* net : m_NetInfo )
2940 {
2941 if( !net->GetNetname().IsEmpty() )
2942 names.insert( net->GetNetname() );
2943 }
2944
2945 return names;
2946}
2947
2948
2950{
2951 if( m_project && !m_project->IsNullProject() )
2952 SetProperties( m_project->GetTextVars() );
2953}
2954
2955
2956static wxString FindVariantNameCaseInsensitive( const std::vector<wxString>& aNames,
2957 const wxString& aVariantName )
2958{
2959 for( const wxString& name : aNames )
2960 {
2961 if( name.CmpNoCase( aVariantName ) == 0 )
2962 return name;
2963 }
2964
2965 return wxEmptyString;
2966}
2967
2968
2969void BOARD::SetCurrentVariant( const wxString& aVariant )
2970{
2971 const wxString previous = m_currentVariant;
2972
2973 if( aVariant.IsEmpty() || aVariant.CmpNoCase( GetDefaultVariantName() ) == 0 )
2974 {
2975 m_currentVariant.Clear();
2976 }
2977 else
2978 {
2979 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariant );
2980
2981 if( actualName.IsEmpty() )
2982 m_currentVariant.Clear();
2983 else
2984 m_currentVariant = actualName;
2985 }
2986
2987 // Variant overrides on footprint fields change `${REFDES:FIELD}` resolution,
2988 // so every cross-ref dependent must repaint on switch. Skip the fan-out if
2989 // the active variant did not actually change (e.g. redundant UI callback).
2990 if( previous != m_currentVariant && m_textVarAdapter )
2991 m_textVarAdapter->Tracker().InvalidateVariantScoped();
2992}
2993
2994
2995bool BOARD::HasVariant( const wxString& aVariantName ) const
2996{
2997 return !FindVariantNameCaseInsensitive( m_variantNames, aVariantName ).IsEmpty();
2998}
2999
3000
3001void BOARD::AddVariant( const wxString& aVariantName )
3002{
3003 if( aVariantName.IsEmpty()
3004 || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0
3005 || HasVariant( aVariantName ) )
3006 {
3007 return;
3008 }
3009
3010 m_variantNames.push_back( aVariantName );
3011}
3012
3013
3014void BOARD::DeleteVariant( const wxString& aVariantName )
3015{
3016 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
3017 return;
3018
3019 auto it = std::find_if( m_variantNames.begin(), m_variantNames.end(),
3020 [&]( const wxString& name )
3021 {
3022 return name.CmpNoCase( aVariantName ) == 0;
3023 } );
3024
3025 if( it != m_variantNames.end() )
3026 {
3027 wxString actualName = *it;
3028 m_variantNames.erase( it );
3029 m_variantDescriptions.erase( actualName );
3030
3031 // Clear current variant if it was the deleted one
3032 if( m_currentVariant.CmpNoCase( aVariantName ) == 0 )
3033 m_currentVariant.Clear();
3034
3035 // Remove variant from all footprints
3036 for( FOOTPRINT* fp : m_footprints )
3037 fp->DeleteVariant( actualName );
3038 }
3039}
3040
3041
3042void BOARD::RenameVariant( const wxString& aOldName, const wxString& aNewName )
3043{
3044 if( aNewName.IsEmpty() || aNewName.CmpNoCase( GetDefaultVariantName() ) == 0 )
3045 return;
3046
3047 auto it = std::find_if( m_variantNames.begin(), m_variantNames.end(),
3048 [&]( const wxString& name )
3049 {
3050 return name.CmpNoCase( aOldName ) == 0;
3051 } );
3052
3053 if( it != m_variantNames.end() )
3054 {
3055 wxString actualOldName = *it;
3056
3057 // Check if new name already exists (case-insensitive) and isn't the same variant
3058 wxString existingName = FindVariantNameCaseInsensitive( m_variantNames, aNewName );
3059
3060 if( !existingName.IsEmpty() && existingName.CmpNoCase( actualOldName ) != 0 )
3061 return;
3062
3063 if( actualOldName == aNewName )
3064 return;
3065
3066 *it = aNewName;
3067
3068 // Transfer description
3069 auto descIt = m_variantDescriptions.find( actualOldName );
3070
3071 if( descIt != m_variantDescriptions.end() )
3072 {
3073 if( !descIt->second.IsEmpty() )
3074 m_variantDescriptions[aNewName] = descIt->second;
3075
3076 m_variantDescriptions.erase( descIt );
3077 }
3078
3079 // Update current variant if it was the renamed one
3080 if( m_currentVariant.CmpNoCase( aOldName ) == 0 )
3081 m_currentVariant = aNewName;
3082
3083 // Rename variant in all footprints
3084 for( FOOTPRINT* fp : m_footprints )
3085 fp->RenameVariant( actualOldName, aNewName );
3086 }
3087}
3088
3089
3090void BOARD::CopyVariant( const wxString& aOldName, const wxString& aNewName, const wxString& aNewDescription )
3091{
3092 if( aOldName.IsEmpty() || aNewName.IsEmpty()
3093 || aNewName.CmpNoCase( GetDefaultVariantName() ) == 0 )
3094 {
3095 return;
3096 }
3097
3098 wxString actualOldName = FindVariantNameCaseInsensitive( m_variantNames, aOldName );
3099
3100 if( actualOldName.IsEmpty() )
3101 return;
3102
3103 if( wxString existingName = FindVariantNameCaseInsensitive( m_variantNames, aNewName ); !existingName.IsEmpty() )
3104 return;
3105
3106 AddVariant( aNewName );
3107
3108 if( !aNewDescription.IsEmpty() )
3109 SetVariantDescription( aNewName, aNewDescription );
3110 else
3111 SetVariantDescription( aNewName, GetVariantDescription( actualOldName ) );
3112
3113 for( FOOTPRINT* fp : m_footprints )
3114 {
3115 if( const FOOTPRINT_VARIANT* variant = fp->GetVariant( actualOldName ) )
3116 {
3117 FOOTPRINT_VARIANT copied = *variant;
3118 copied.SetName( aNewName );
3119 fp->SetVariant( copied );
3120 }
3121 }
3122}
3123
3124
3125wxString BOARD::GetVariantDescription( const wxString& aVariantName ) const
3126{
3127 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
3128 return wxEmptyString;
3129
3130 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariantName );
3131
3132 if( actualName.IsEmpty() )
3133 return wxEmptyString;
3134
3135 auto it = m_variantDescriptions.find( actualName );
3136
3137 if( it != m_variantDescriptions.end() )
3138 return it->second;
3139
3140 return wxEmptyString;
3141}
3142
3143
3144void BOARD::SetVariantDescription( const wxString& aVariantName, const wxString& aDescription )
3145{
3146 if( aVariantName.IsEmpty() || aVariantName.CmpNoCase( GetDefaultVariantName() ) == 0 )
3147 return;
3148
3149 wxString actualName = FindVariantNameCaseInsensitive( m_variantNames, aVariantName );
3150
3151 if( actualName.IsEmpty() )
3152 return;
3153
3154 if( aDescription.IsEmpty() )
3155 m_variantDescriptions.erase( actualName );
3156 else
3157 m_variantDescriptions[actualName] = aDescription;
3158}
3159
3160
3161wxArrayString BOARD::GetVariantNamesForUI() const
3162{
3163 wxArrayString names;
3164 names.Add( GetDefaultVariantName() );
3165
3166 for( const wxString& name : m_variantNames )
3167 names.Add( name );
3168
3169 names.Sort( SortVariantNames ); // SortVariantNames ensures the default is always first
3170
3171 return names;
3172}
3173
3174
3176{
3177 m_lengthDelayCalc->SynchronizeTuningProfileProperties();
3178}
3179
3180
3182{
3183 if( !m_project )
3184 return;
3185
3186 const std::shared_ptr<NET_SETTINGS>& netSettings = GetDesignSettings().m_NetSettings;
3187
3188 if( !netSettings )
3189 return;
3190
3191 const std::map<wxString, wxString>& chainNetclasses = netSettings->GetNetChainNetClasses();
3192
3193 // Nothing to derive and nothing left from a prior pass, so skip the cache wipe a rebuild
3194 // would cost on every resync of a board without chain overrides.
3195 if( chainNetclasses.empty()
3196 && !netSettings->HasChainPatternAssignments( NET_CHAIN_SOURCE::BOARD ) )
3197 {
3198 return;
3199 }
3200
3201 netSettings->ClearChainPatternAssignments( NET_CHAIN_SOURCE::BOARD );
3202
3203 for( NETINFO_ITEM* net : m_NetInfo )
3204 {
3205 const wxString& chainName = net->GetNetChain();
3206
3207 if( chainName.IsEmpty() )
3208 continue;
3209
3210 auto it = chainNetclasses.find( chainName );
3211
3212 if( it == chainNetclasses.end() || !netSettings->HasNetclass( it->second ) )
3213 continue;
3214
3215 netSettings->SetChainPatternAssignment( NET_CHAIN_SOURCE::BOARD, net->GetNetname(),
3216 it->second );
3217 }
3218}
3219
3220
3221void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
3222{
3223 if( !m_project )
3224 return;
3225
3227 const std::shared_ptr<NETCLASS>& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass();
3228
3230
3232
3233 for( NETINFO_ITEM* net : m_NetInfo )
3234 net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) );
3235
3236 if( aResetTrackAndViaSizes )
3237 {
3238 // Set initial values for custom track width & via size to match the default
3239 // netclass settings
3240 bds.UseCustomTrackViaSize( false );
3241 bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
3242 bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
3243 bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
3244
3245 if( defaultNetClass->HasDiffPairWidth() )
3246 bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
3247 else
3248 bds.SetCustomDiffPairWidth( defaultNetClass->GetTrackWidth() );
3249
3250 if( defaultNetClass->HasDiffPairGap() )
3251 bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
3252 else
3253 bds.SetCustomDiffPairGap( defaultNetClass->GetClearance() );
3254
3255 if( defaultNetClass->HasDiffPairViaGap() )
3256 bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
3257 else
3259 }
3260
3262}
3263
3264
3265bool BOARD::SynchronizeComponentClasses( const std::unordered_set<wxString>& aNewSheetPaths ) const
3266{
3268
3269 return m_componentClassManager->SyncDynamicComponentClassAssignments( settings->GetComponentClassAssignments(),
3271 aNewSheetPaths );
3272}
3273
3274
3276{
3277 int error_count = 0;
3278
3279 for( ZONE* zone : Zones() )
3280 {
3281 if( !zone->IsOnCopperLayer() )
3282 {
3283 zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
3284 continue;
3285 }
3286
3287 if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
3288 {
3289 const NETINFO_ITEM* net = zone->GetNet();
3290
3291 if( net )
3292 {
3293 zone->SetNetCode( net->GetNetCode() );
3294 }
3295 else
3296 {
3297 error_count++;
3298
3299 // keep Net Name and set m_NetCode to -1 : error flag.
3300 zone->SetNetCode( -1 );
3301 }
3302 }
3303 }
3304
3305 return error_count;
3306}
3307
3308
3309PAD* BOARD::GetPad( const VECTOR2I& aPosition, const LSET& aLayerSet ) const
3310{
3311 for( FOOTPRINT* footprint : m_footprints )
3312 {
3313 PAD* pad = nullptr;
3314
3315 if( footprint->HitTest( aPosition ) )
3316 pad = footprint->GetPad( aPosition, aLayerSet.any() ? aLayerSet : LSET::AllCuMask() );
3317
3318 if( pad )
3319 return pad;
3320 }
3321
3322 return nullptr;
3323}
3324
3325
3326PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
3327{
3328 const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
3329
3330 LSET lset( { aTrace->GetLayer() } );
3331
3332 return GetPad( aPosition, lset );
3333}
3334
3335
3336PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, const LSET& aLayerSet ) const
3337{
3338 // Search aPadList for aPosition
3339 // aPadList is sorted by X then Y values, and a fast binary search is used
3340 int idxmax = aPadList.size() - 1;
3341
3342 int delta = aPadList.size();
3343
3344 int idx = 0; // Starting index is the beginning of list
3345
3346 while( delta )
3347 {
3348 // Calculate half size of remaining interval to test.
3349 // Ensure the computed value is not truncated (too small)
3350 if( ( delta & 1 ) && ( delta > 1 ) )
3351 delta++;
3352
3353 delta /= 2;
3354
3355 PAD* pad = aPadList[idx];
3356
3357 if( pad->GetPosition() == aPosition ) // candidate found
3358 {
3359 // The pad must match the layer mask:
3360 if( ( aLayerSet & pad->GetLayerSet() ).any() )
3361 return pad;
3362
3363 // More than one pad can be at aPosition
3364 // search for a pad at aPosition that matched this mask
3365
3366 // search next
3367 for( int ii = idx + 1; ii <= idxmax; ii++ )
3368 {
3369 pad = aPadList[ii];
3370
3371 if( pad->GetPosition() != aPosition )
3372 break;
3373
3374 if( ( aLayerSet & pad->GetLayerSet() ).any() )
3375 return pad;
3376 }
3377 // search previous
3378 for( int ii = idx - 1; ii >= 0; ii-- )
3379 {
3380 pad = aPadList[ii];
3381
3382 if( pad->GetPosition() != aPosition )
3383 break;
3384
3385 if( ( aLayerSet & pad->GetLayerSet() ).any() )
3386 return pad;
3387 }
3388
3389 // Not found:
3390 return nullptr;
3391 }
3392
3393 if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
3394 {
3395 if( pad->GetPosition().y < aPosition.y ) // Must search after this item
3396 {
3397 idx += delta;
3398
3399 if( idx > idxmax )
3400 idx = idxmax;
3401 }
3402 else // Must search before this item
3403 {
3404 idx -= delta;
3405
3406 if( idx < 0 )
3407 idx = 0;
3408 }
3409 }
3410 else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
3411 {
3412 idx += delta;
3413
3414 if( idx > idxmax )
3415 idx = idxmax;
3416 }
3417 else // Must search before this item
3418 {
3419 idx -= delta;
3420
3421 if( idx < 0 )
3422 idx = 0;
3423 }
3424 }
3425
3426 return nullptr;
3427}
3428
3429
3435bool sortPadsByXthenYCoord( PAD* const& aLH, PAD* const& aRH )
3436{
3437 if( aLH->GetPosition().x == aRH->GetPosition().x )
3438 return aLH->GetPosition().y < aRH->GetPosition().y;
3439
3440 return aLH->GetPosition().x < aRH->GetPosition().x;
3441}
3442
3443
3444void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
3445{
3446 for( FOOTPRINT* footprint : Footprints() )
3447 {
3448 for( PAD* pad : footprint->Pads() )
3449 {
3450 if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
3451 aVector.push_back( pad );
3452 }
3453 }
3454
3455 std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
3456}
3457
3458
3460{
3461 if( GetDesignSettings().m_HasStackup )
3463
3464 BOARD_STACKUP stackup;
3466 return stackup;
3467}
3468
3469
3470std::tuple<int, double, double, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
3471{
3472 std::shared_ptr<CONNECTIVITY_DATA> connectivity = GetBoard()->GetConnectivity();
3473 std::vector<LENGTH_DELAY_CALCULATION_ITEM> items;
3474
3475 for( BOARD_CONNECTED_ITEM* boardItem : connectivity->GetConnectedItems( &aTrack, EXCLUDE_ZONES ) )
3476 {
3478
3479 if( item.Type() != LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
3480 items.push_back( std::move( item ) );
3481 }
3482
3483 constexpr PATH_OPTIMISATIONS opts = {
3484 .OptimiseVias = true, .MergeTracks = true, .OptimiseTracesInPads = true, .InferViaInPad = false
3485 };
3487 items, opts, nullptr, nullptr, LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL,
3489
3490 return std::make_tuple( items.size(), details.TrackLength + details.ViaLength, details.PadToDieLength,
3491 details.TrackDelay + details.ViaDelay, details.PadToDieDelay );
3492}
3493
3494
3495FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly,
3496 bool aIgnoreLocked ) const
3497{
3498 FOOTPRINT* footprint = nullptr;
3499 FOOTPRINT* alt_footprint = nullptr;
3500 int min_dim = 0x7FFFFFFF;
3501 int alt_min_dim = 0x7FFFFFFF;
3502 bool current_layer_back = IsBackLayer( aActiveLayer );
3503
3504 for( FOOTPRINT* candidate : m_footprints )
3505 {
3506 // is the ref point within the footprint's bounds?
3507 if( !candidate->HitTest( aPosition ) )
3508 continue;
3509
3510 // if caller wants to ignore locked footprints, and this one is locked, skip it.
3511 if( aIgnoreLocked && candidate->IsLocked() )
3512 continue;
3513
3514 PCB_LAYER_ID layer = candidate->GetLayer();
3515
3516 // Filter non visible footprints if requested
3517 if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
3518 {
3519 BOX2I bb = candidate->GetBoundingBox( false );
3520
3521 int offx = bb.GetX() + bb.GetWidth() / 2;
3522 int offy = bb.GetY() + bb.GetHeight() / 2;
3523
3524 // off x & offy point to the middle of the box.
3525 int dist =
3526 ( aPosition.x - offx ) * ( aPosition.x - offx ) + ( aPosition.y - offy ) * ( aPosition.y - offy );
3527
3528 if( current_layer_back == IsBackLayer( layer ) )
3529 {
3530 if( dist <= min_dim )
3531 {
3532 // better footprint shown on the active side
3533 footprint = candidate;
3534 min_dim = dist;
3535 }
3536 }
3537 else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
3538 {
3539 if( dist <= alt_min_dim )
3540 {
3541 // better footprint shown on the other side
3542 alt_footprint = candidate;
3543 alt_min_dim = dist;
3544 }
3545 }
3546 }
3547 }
3548
3549 if( footprint )
3550 return footprint;
3551
3552 if( alt_footprint )
3553 return alt_footprint;
3554
3555 return nullptr;
3556}
3557
3558
3559std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
3560{
3561 std::list<ZONE*> zones;
3562
3563 for( ZONE* zone : Zones() )
3564 zones.push_back( zone );
3565
3566 if( aIncludeZonesInFootprints )
3567 {
3568 for( FOOTPRINT* footprint : m_footprints )
3569 {
3570 for( ZONE* zone : footprint->Zones() )
3571 zones.push_back( zone );
3572 }
3573 }
3574
3575 return zones;
3576}
3577
3578
3579ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, VECTOR2I aStartPointPosition,
3581{
3582 ZONE* new_area = new ZONE( this );
3583
3584 new_area->SetNetCode( aNetcode );
3585 new_area->SetLayer( aLayer );
3586
3587 m_zones.push_back( new_area );
3588
3589 new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
3590
3591 // Add the first corner to the new zone
3592 new_area->AppendCorner( aStartPointPosition, -1 );
3593
3594 if( aNewZonesList )
3595 {
3596 ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
3597 aNewZonesList->PushItem( picker );
3598 }
3599
3600 return new_area;
3601}
3602
3603
3604bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, bool aInferOutlineIfNecessary,
3605 OUTLINE_ERROR_HANDLER* aErrorHandler, bool aAllowUseArcsInPolygons,
3606 bool aIncludeNPTHAsOutlines )
3607{
3608 // max dist from one endPt to next startPt: use the current value
3609 int chainingEpsilon = GetOutlinesChainingEpsilon();
3610
3611 bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError, chainingEpsilon,
3612 aInferOutlineIfNecessary, aErrorHandler, aAllowUseArcsInPolygons );
3613
3614 // Now subtract NPTH oval holes from outlines if required
3615 if( aIncludeNPTHAsOutlines )
3616 {
3617 for( FOOTPRINT* fp : Footprints() )
3618 {
3619 for( PAD* pad : fp->Pads() )
3620 {
3621 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
3622 continue;
3623
3624 SHAPE_POLY_SET hole;
3625 pad->TransformHoleToPolygon( hole, 0, pad->GetMaxError(), ERROR_INSIDE );
3626
3627 if( hole.OutlineCount() > 0 ) // can be not the case for malformed NPTH holes
3628 {
3629 // Issue #20159: BooleanSubtract correctly clips holes extending past board
3630 // edges (common with oval holes near irregular boards). O(n log n) per hole
3631 // vs O(1) for AddHole, but only used for 3D viewer generation, not a hot path.
3632 aOutlines.BooleanSubtract( hole );
3633 }
3634 }
3635 }
3636 }
3637
3638 // Make polygon strictly simple to avoid issues (especially in 3D viewer)
3639 if( aOutlines.ArcCount() > 0 && aOutlines.OutlineCount() > 1 )
3640 {
3641 // Boolean ops keep arcs only within a single outline, so simplify each island alone
3642 SHAPE_POLY_SET simplified;
3643
3644 for( int ii = 0; ii < aOutlines.OutlineCount(); ++ii )
3645 {
3646 SHAPE_POLY_SET island( aOutlines.Polygon( ii ) );
3647 island.Simplify();
3648 simplified.Append( island );
3649 }
3650
3651 aOutlines = std::move( simplified );
3652 }
3653 else
3654 {
3655 aOutlines.Simplify();
3656 }
3657
3658 return success;
3659}
3660
3661
3663{
3665 return static_cast<EMBEDDED_FILES*>( m_embeddedFilesDelegate );
3666
3667 return static_cast<EMBEDDED_FILES*>( this );
3668}
3669
3670
3672{
3674 return static_cast<const EMBEDDED_FILES*>( m_embeddedFilesDelegate );
3675
3676 return static_cast<const EMBEDDED_FILES*>( this );
3677}
3678
3679
3680std::set<KIFONT::OUTLINE_FONT*> BOARD::GetFonts() const
3681{
3683
3684 std::set<KIFONT::OUTLINE_FONT*> fonts;
3685
3686 for( BOARD_ITEM* item : Drawings() )
3687 {
3688 if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
3689 {
3690 KIFONT::FONT* font = text->GetFont();
3691
3692 if( font && font->IsOutline() )
3693 {
3694 KIFONT::OUTLINE_FONT* outlineFont = static_cast<KIFONT::OUTLINE_FONT*>( font );
3695 PERMISSION permission = outlineFont->GetEmbeddingPermission();
3696
3697 if( permission == PERMISSION::EDITABLE || permission == PERMISSION::INSTALLABLE )
3698 fonts.insert( outlineFont );
3699 }
3700 }
3701 }
3702
3703 return fonts;
3704}
3705
3706
3708{
3709 for( KIFONT::OUTLINE_FONT* font : GetFonts() )
3710 {
3711 EMBEDDED_FILES::EMBEDDED_FILE* file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
3712
3713 if( !file )
3714 {
3715 wxLogTrace( "EMBED", "Failed to add font file: %s", font->GetFileName() );
3716 continue;
3717 }
3718
3720 }
3721}
3722
3723
3724const std::vector<PAD*> BOARD::GetPads() const
3725{
3726 std::vector<PAD*> allPads;
3727
3728 for( FOOTPRINT* footprint : Footprints() )
3729 {
3730 for( PAD* pad : footprint->Pads() )
3731 allPads.push_back( pad );
3732 }
3733
3734 return allPads;
3735}
3736
3737
3738const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
3739{
3740 std::vector<BOARD_CONNECTED_ITEM*> items;
3741
3742 for( PCB_TRACK* track : Tracks() )
3743 items.push_back( track );
3744
3745 for( FOOTPRINT* footprint : Footprints() )
3746 {
3747 for( PAD* pad : footprint->Pads() )
3748 items.push_back( pad );
3749
3750 for( ZONE* zone : footprint->Zones() )
3751 items.push_back( zone );
3752
3753 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
3754 {
3755 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( dwg ) )
3756 items.push_back( bci );
3757 }
3758 }
3759
3760 for( ZONE* zone : Zones() )
3761 items.push_back( zone );
3762
3763 for( BOARD_ITEM* item : Drawings() )
3764 {
3765 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
3766 items.push_back( bci );
3767 }
3768
3769 return items;
3770}
3771
3772
3773void BOARD::MapNets( BOARD* aDestBoard )
3774{
3776 {
3777 NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
3778
3779 if( netInfo )
3780 item->SetNet( netInfo );
3781 else
3782 {
3783 NETINFO_ITEM* newNet = new NETINFO_ITEM( aDestBoard, item->GetNetname() );
3784 aDestBoard->Add( newNet );
3785 item->SetNet( newNet );
3786 }
3787 }
3788}
3789
3790
3792{
3794 {
3795 if( FindNet( item->GetNetCode() ) == nullptr )
3796 item->SetNetCode( NETINFO_LIST::ORPHANED );
3797 }
3798}
3799
3800
3801void BOARD::OnZonesFilled( const std::vector<ZONE*>& aZones )
3802{
3803 if( aZones.empty() )
3804 return;
3805
3806 for( PCB_GENERATOR* generator : m_generators )
3807 generator->OnZoneFillChanged( aZones );
3808}
3809
3810
3812{
3813 if( !alg::contains( m_listeners, aListener ) )
3814 m_listeners.push_back( aListener );
3815}
3816
3817
3819{
3820 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
3821
3822 if( i != m_listeners.end() )
3823 {
3824 std::iter_swap( i, m_listeners.end() - 1 );
3825 m_listeners.pop_back();
3826 }
3827}
3828
3829
3831{
3832 m_listeners.clear();
3833}
3834
3835
3837{
3838 if( affectsDrillModel( aItem ) )
3840
3842}
3843
3844
3845void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
3846{
3847 bumpDrillModelFor( aItems );
3848
3850}
3851
3852
3857
3858
3859void BOARD::OnItemsCompositeUpdate( std::vector<BOARD_ITEM*>& aAddedItems, std::vector<BOARD_ITEM*>& aRemovedItems,
3860 std::vector<BOARD_ITEM*>& aChangedItems )
3861{
3862 bumpDrillModelFor( aAddedItems );
3863 bumpDrillModelFor( aRemovedItems );
3864 bumpDrillModelFor( aChangedItems );
3865
3866 InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems, aChangedItems );
3867}
3868
3869
3874
3875
3882
3883
3891
3892
3893void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
3894{
3895 bool already = m_highLight.m_netCodes.count( aNetCode );
3896
3897 if( !already )
3898 {
3899 if( !aMulti )
3900 m_highLight.m_netCodes.clear();
3901
3902 m_highLight.m_netCodes.insert( aNetCode );
3904 }
3905}
3906
3907
3908void BOARD::HighLightON( bool aValue )
3909{
3910 if( m_highLight.m_highLightOn != aValue )
3911 {
3912 m_highLight.m_highLightOn = aValue;
3914 }
3915}
3916
3917
3918wxString BOARD::GroupsSanityCheck( bool repair )
3919{
3920 if( repair )
3921 {
3922 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
3923 {
3924 };
3925
3926 return wxEmptyString;
3927 }
3928 return GroupsSanityCheckInternal( repair );
3929}
3930
3931
3933{
3934 // Cycle detection
3935 //
3936 // Each group has at most one parent group.
3937 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
3938 // If we ever see a group that we've already marked, that's a cycle.
3939 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
3940 //
3941 // Algorithm below is linear in the # of groups because each group is visited only once.
3942 // There may be extra time taken due to the container access calls and iterators.
3943 //
3944 // Groups we know are cycle free
3945 std::unordered_set<EDA_GROUP*> knownCycleFreeGroups;
3946 // Groups in the current chain we're exploring.
3947 std::unordered_set<EDA_GROUP*> currentChainGroups;
3948 // Groups we haven't checked yet.
3949 std::unordered_set<EDA_GROUP*> toCheckGroups;
3950
3951 // Initialize set of groups and generators to check that could participate in a cycle.
3952 for( PCB_GROUP* group : Groups() )
3953 toCheckGroups.insert( group );
3954
3955 for( PCB_GENERATOR* gen : Generators() )
3956 toCheckGroups.insert( gen );
3957
3958 while( !toCheckGroups.empty() )
3959 {
3960 currentChainGroups.clear();
3961 EDA_GROUP* group = *toCheckGroups.begin();
3962
3963 while( true )
3964 {
3965 if( currentChainGroups.find( group ) != currentChainGroups.end() )
3966 {
3967 if( repair )
3968 Remove( static_cast<BOARD_ITEM*>( group->AsEdaItem() ) );
3969
3970 return "Cycle detected in group membership";
3971 }
3972 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
3973 {
3974 // Parent is a group we know does not lead to a cycle
3975 break;
3976 }
3977
3978 currentChainGroups.insert( group );
3979 // We haven't visited currIdx yet, so it must be in toCheckGroups
3980 toCheckGroups.erase( group );
3981
3982 group = group->AsEdaItem()->GetParentGroup();
3983
3984 if( !group )
3985 {
3986 // end of chain and no cycles found in this chain
3987 break;
3988 }
3989 }
3990
3991 // No cycles found in chain, so add it to set of groups we know don't participate
3992 // in a cycle.
3993 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
3994 }
3995
3996 // Success
3997 return "";
3998}
3999
4000
4002{
4003 if( a->Type() != b->Type() )
4004 return a->Type() < b->Type();
4005
4006 if( a->GetLayer() != b->GetLayer() )
4007 return a->GetLayer() < b->GetLayer();
4008
4009 if( a->GetPosition().x != b->GetPosition().x )
4010 return a->GetPosition().x < b->GetPosition().x;
4011
4012 if( a->GetPosition().y != b->GetPosition().y )
4013 return a->GetPosition().y < b->GetPosition().y;
4014
4015 if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards
4016 return a->m_Uuid < b->m_Uuid;
4017
4018 return a < b;
4019}
4020
4021
4022bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const
4023{
4024 if( aFirst->Type() != aSecond->Type() )
4025 return aFirst->Type() < aSecond->Type();
4026
4027 // Layer-free drawings (grid items) assert in GetLayer(); they sort by uuid below.
4028 if( IsSingleLayerType( aFirst->Type() ) && aFirst->GetLayer() != aSecond->GetLayer() )
4029 return aFirst->GetLayer() < aSecond->GetLayer();
4030
4031 // Callers keep these in a std::set, so any branch reporting equality for two distinct items
4032 // loses one of them. Every branch has to fall through to the uuid
4033 int cmp = 0;
4034
4035 if( aFirst->Type() == PCB_SHAPE_T )
4036 {
4037 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aFirst );
4038 const PCB_SHAPE* other = static_cast<const PCB_SHAPE*>( aSecond );
4039
4040 cmp = shape->Compare( other );
4041 }
4042 else if( aFirst->Type() == PCB_TEXT_T || aFirst->Type() == PCB_FIELD_T )
4043 {
4044 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aFirst );
4045 const PCB_TEXT* other = static_cast<const PCB_TEXT*>( aSecond );
4046
4047 cmp = text->Compare( other );
4048 }
4049 else if( aFirst->Type() == PCB_TEXTBOX_T )
4050 {
4051 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aFirst );
4052 const PCB_TEXTBOX* other = static_cast<const PCB_TEXTBOX*>( aSecond );
4053
4054 cmp = textbox->PCB_SHAPE::Compare( other );
4055
4056 if( cmp == 0 )
4057 cmp = textbox->EDA_TEXT::Compare( other );
4058 }
4059 else if( BaseType( aFirst->Type() ) == PCB_TABLE_T )
4060 {
4061 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aFirst );
4062 const PCB_TABLE* other = static_cast<const PCB_TABLE*>( aSecond );
4063
4064 cmp = PCB_TABLE::Compare( table, other );
4065 }
4066 else if( aFirst->Type() == PCB_BARCODE_T )
4067 {
4068 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( aFirst );
4069 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( aSecond );
4070
4071 cmp = PCB_BARCODE::Compare( barcode, other );
4072 }
4073
4074 if( cmp != 0 )
4075 return cmp < 0;
4076
4077 if( aFirst->m_Uuid != aSecond->m_Uuid )
4078 return aFirst->m_Uuid < aSecond->m_Uuid;
4079
4080 return aFirst < aSecond;
4081}
4082
4083
4085 KIGFX::RENDER_SETTINGS* aRenderSettings ) const
4086{
4087 int maxError = GetDesignSettings().m_MaxError;
4088
4089 // convert tracks and vias:
4090 for( const PCB_TRACK* track : m_tracks )
4091 {
4092 if( !track->IsOnLayer( aLayer ) )
4093 continue;
4094
4095 track->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4096 }
4097
4098 // convert pads and other copper items in footprints
4099 for( const FOOTPRINT* footprint : m_footprints )
4100 {
4101 footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4102
4103 footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE, true, /* include text */
4104 true, /* include shapes */
4105 false /* include private items */ );
4106
4107 for( const ZONE* zone : footprint->Zones() )
4108 {
4109 if( zone->GetLayerSet().test( aLayer ) )
4110 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
4111 }
4112 }
4113
4114 // convert copper zones
4115 for( const ZONE* zone : Zones() )
4116 {
4117 if( zone->GetLayerSet().test( aLayer ) )
4118 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
4119 }
4120
4121 // convert graphic items on copper layers (texts)
4122 for( const BOARD_ITEM* item : m_drawings )
4123 {
4124 if( !item->IsOnLayer( aLayer ) )
4125 continue;
4126
4127 switch( item->Type() )
4128 {
4129 case PCB_SHAPE_T:
4130 {
4131 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
4132 shape->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4133 break;
4134 }
4135
4136 case PCB_BARCODE_T:
4137 {
4138 const PCB_BARCODE* barcode = static_cast<const PCB_BARCODE*>( item );
4139 barcode->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4140 break;
4141 }
4142
4143 case PCB_FIELD_T:
4144 case PCB_TEXT_T:
4145 {
4146 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
4147 text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
4148 break;
4149 }
4150
4151 case PCB_TEXTBOX_T:
4152 {
4153 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
4154 // border
4155 textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4156 // text
4157 textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
4158 break;
4159 }
4160
4161 case PCB_TABLE_T:
4162 case PCB_DRILL_CHART_T:
4163 {
4164 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
4165 table->TransformGraphicItemsToPolySet( aOutlines, maxError, ERROR_INSIDE, aRenderSettings );
4166 break;
4167 }
4168
4169 // Configuration only. The symbols it asks for are drawn by the holes themselves
4170 case PCB_DRILL_MAP_T:
4171 break;
4172
4173 case PCB_DIM_ALIGNED_T:
4174 case PCB_DIM_CENTER_T:
4175 case PCB_DIM_RADIAL_T:
4177 case PCB_DIM_LEADER_T:
4178 {
4179 const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
4180 dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
4181 dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
4182 break;
4183 }
4184
4185 default:
4186 break;
4187 }
4188 }
4189}
4190
4191
4192std::vector<BOARD_ITEM*> BOARD::collectOwnedItems() const
4193{
4194 std::vector<BOARD_ITEM*> items;
4195
4196 items.reserve( m_tracks.size() + m_zones.size() + m_generators.size() + m_footprints.size()
4197 + m_drawings.size() + m_markers.size() + m_groups.size() + m_constraints.size()
4198 + m_points.size() );
4199
4200 items.insert( items.end(), m_tracks.begin(), m_tracks.end() );
4201 items.insert( items.end(), m_zones.begin(), m_zones.end() );
4202 items.insert( items.end(), m_generators.begin(), m_generators.end() );
4203 items.insert( items.end(), m_footprints.begin(), m_footprints.end() );
4204 items.insert( items.end(), m_drawings.begin(), m_drawings.end() );
4205 items.insert( items.end(), m_markers.begin(), m_markers.end() );
4206 items.insert( items.end(), m_groups.begin(), m_groups.end() );
4207 items.insert( items.end(), m_constraints.begin(), m_constraints.end() );
4208 items.insert( items.end(), m_points.begin(), m_points.end() );
4209
4210 return items;
4211}
4212
4213
4215{
4216 std::vector<BOARD_ITEM*> items = collectOwnedItems();
4217
4218 return BOARD_ITEM_SET( items.begin(), items.end() );
4219}
4220
4221
4223{
4224 // Delegate to the non-const overload via a single safe const_cast on the
4225 // *this pointer. GetItemSet doesn't mutate the BOARD; the non-const
4226 // signature is historical.
4227 return const_cast<BOARD*>( this )->GetItemSet();
4228}
4229
4230
4231bool BOARD::operator==( const BOARD_ITEM& aItem ) const
4232{
4233 if( aItem.Type() != Type() )
4234 return false;
4235
4236 const BOARD& other = static_cast<const BOARD&>( aItem );
4237
4238 if( *m_designSettings != *other.m_designSettings )
4239 return false;
4240
4241 if( m_NetInfo.GetNetCount() != other.m_NetInfo.GetNetCount() )
4242 return false;
4243
4244 const NETNAMES_MAP& thisNetNames = m_NetInfo.NetsByName();
4245 const NETNAMES_MAP& otherNetNames = other.m_NetInfo.NetsByName();
4246
4247 for( auto it1 = thisNetNames.begin(), it2 = otherNetNames.begin();
4248 it1 != thisNetNames.end() && it2 != otherNetNames.end(); ++it1, ++it2 )
4249 {
4250 // We only compare the names in order here, not the index values
4251 // as the index values are auto-generated and the names are not.
4252 if( it1->first != it2->first )
4253 return false;
4254 }
4255
4256 if( m_properties.size() != other.m_properties.size() )
4257 return false;
4258
4259 for( auto it1 = m_properties.begin(), it2 = other.m_properties.begin();
4260 it1 != m_properties.end() && it2 != other.m_properties.end(); ++it1, ++it2 )
4261 {
4262 if( *it1 != *it2 )
4263 return false;
4264 }
4265
4266 if( m_paper.GetCustomHeightMils() != other.m_paper.GetCustomHeightMils() )
4267 return false;
4268
4269 if( m_paper.GetCustomWidthMils() != other.m_paper.GetCustomWidthMils() )
4270 return false;
4271
4272 if( m_paper.GetSizeMils() != other.m_paper.GetSizeMils() )
4273 return false;
4274
4275 if( m_paper.GetPaperId() != other.m_paper.GetPaperId() )
4276 return false;
4277
4278 if( m_paper.GetWxOrientation() != other.m_paper.GetWxOrientation() )
4279 return false;
4280
4281 for( int ii = 0; !m_titles.GetComment( ii ).empty(); ++ii )
4282 {
4283 if( m_titles.GetComment( ii ) != other.m_titles.GetComment( ii ) )
4284 return false;
4285 }
4286
4287 wxArrayString ourVars;
4288 m_titles.GetContextualTextVars( &ourVars );
4289
4290 wxArrayString otherVars;
4291 other.m_titles.GetContextualTextVars( &otherVars );
4292
4293 if( ourVars != otherVars )
4294 return false;
4295
4296 return true;
4297}
4298
4300{
4302 m_boardOutline->GetOutline().RemoveAllContours();
4303
4304 bool has_outline = GetBoardPolygonOutlines( m_boardOutline->GetOutline(), false );
4305
4306 if( has_outline )
4307 m_boardOutline->GetOutline().Fracture();
4308}
4309
4310
4312{
4313 // return the number of PTH with Press-Fit fabr attribute
4314 int count = 0;
4315
4316 for( FOOTPRINT* footprint : Footprints() )
4317 {
4318 for( PAD* pad : footprint->Pads() )
4319 {
4320 if( pad->GetProperty() == PAD_PROP::PRESSFIT )
4321 count++;
4322 }
4323 }
4324
4325 return count;
4326}
4327
4328
4330{
4331 // @return the number of PTH with Castellated fabr attribute
4332 int count = 0;
4333
4334 for( FOOTPRINT* footprint : Footprints() )
4335 {
4336 for( PAD* pad : footprint->Pads() )
4337 {
4338 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
4339 count++;
4340 }
4341 }
4342
4343 return count;
4344}
4345
4346
4347void BOARD::SaveToHistory( const wxString& aProjectPath, std::vector<HISTORY_FILE_DATA>& aFileData )
4348{
4349 // The board can transiently have no project (e.g. during a non-KiCad import while the old
4350 // project is being unloaded and the new one has not yet been linked). The autosave timer can
4351 // fire in that window, so guard against a null project here rather than dereferencing it.
4353
4354 if( !project )
4355 return;
4356
4357 wxString projPath = project->GetProjectPath();
4358
4359 if( projPath.IsEmpty() )
4360 return;
4361
4362 // Verify we're saving for the correct project
4363 if( !projPath.IsSameAs( aProjectPath ) )
4364 {
4365 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - project path mismatch: %s vs %s" ), projPath,
4366 aProjectPath );
4367 return;
4368 }
4369
4370 wxString boardPath = GetFileName();
4371
4372 if( boardPath.IsEmpty() )
4373 return; // unsaved board
4374
4375 // Derive relative path from project root.
4376 if( !boardPath.StartsWith( projPath ) )
4377 {
4378 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - board not under project: %s" ), boardPath );
4379 return; // not under project
4380 }
4381
4382 wxString rel = boardPath.Mid( projPath.length() );
4383
4384 try
4385 {
4387 STRING_FORMATTER formatter;
4388
4389 pi.FormatBoardToFormatter( &formatter, this, nullptr );
4390
4391 HISTORY_FILE_DATA entry;
4392 entry.relativePath = rel;
4393 entry.content = std::move( formatter.MutableString() );
4394 entry.prettify = true;
4395
4396 if( ADVANCED_CFG::GetCfg().m_CompactSave )
4397 entry.formatMode = KICAD_FORMAT::FORMAT_MODE::COMPACT_TEXT_PROPERTIES;
4398
4399 aFileData.push_back( std::move( entry ) );
4400
4401 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver serialized %zu bytes for '%s'" ),
4402 aFileData.back().content.size(), rel );
4403 }
4404 catch( const IO_ERROR& ioe )
4405 {
4406 wxLogTrace( traceAutoSave, wxS( "[history] pcb saver serialize failed: %s" ), wxString::FromUTF8( ioe.What() ) );
4407 }
4408}
int index
const char * name
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
static PCB_TABLECELL * findTableCell(const BOARD_ITEM *aDrawing, const KIID &aID)
Definition board.cpp:2127
static bool affectsDrillModel(const BOARD_ITEM *aItem)
Definition board.cpp:189
bool sortPadsByXthenYCoord(PAD *const &aLH, PAD *const &aRH)
Used by BOARD::GetSortedPadListByXthenYCoord to sort a pad list by X coordinate value.
Definition board.cpp:3435
static wxString FindVariantNameCaseInsensitive(const std::vector< wxString > &aNames, const wxString &aVariantName)
Definition board.cpp:2956
#define DEFAULT_CHAINING_EPSILON_MM
Definition board.h:95
BOARD_USE
Flags to specify how the board is being used.
Definition board.h:401
@ NORMAL
Definition board.h:402
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition board.h:243
@ LT_POWER
Definition board.h:246
@ LT_FRONT
Definition board.h:250
@ LT_MIXED
Definition board.h:247
@ LT_BACK
Definition board.h:251
@ LT_UNDEFINED
Definition board.h:244
@ LT_JUMPER
Definition board.h:248
@ LT_AUX
Definition board.h:249
@ LT_SIGNAL
Definition board.h:245
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
Definition board.h:395
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
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:153
BASE_SET & set(size_t pos)
Definition base_set.h:126
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
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.
DRILL_SYMBOL_PROFILE & GetDrillSymbolProfile()
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)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:87
virtual void SetLayerSet(const LSET &aLayers)
Definition board_item.h:363
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void Move(const VECTOR2I &aMoveVector)
Move this object.
Definition board_item.h:445
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:418
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:355
static VECTOR2I ZeroOffset
A value of wxPoint(0,0) which can be passed to the Draw() functions.
Definition board_item.h:233
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
virtual void OnBoardNetSettingsChanged(BOARD &aBoard)
Definition board.h:379
virtual void OnBoardRatsnestChanged(BOARD &aBoard)
Definition board.h:384
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:376
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:380
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:377
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition board.h:375
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition board.h:383
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:378
virtual void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAddedItems, std::vector< BOARD_ITEM * > &aRemovedItems, std::vector< BOARD_ITEM * > &aChangedItems)
Definition board.h:385
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItems)
Definition board.h:381
virtual void OnBoardSelectionChanged(BOARD &aBoard)
Definition board.h:382
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:2645
ZONE * m_SolderMaskBridges
Definition board.h:1811
void ApplyNetChainNetclasses()
Expand the project's chain-to-netclass assignments into per-net pattern assignments,...
Definition board.cpp:3181
void GetContextualTextVars(wxArrayString *aVars) const
Definition board.cpp:650
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:1279
BOARD_STACKUP GetStackupOrDefault() const
Definition board.cpp:3459
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition board.h:1812
PCB_LAYER_ID GetCopperLayerStackMaxId() const
Definition board.cpp:1154
std::vector< const PCB_DRILL_MAP * > DrillMapsOnLayer(PCB_LAYER_ID aLayer) const
Every map on this layer.
Definition board.cpp:207
GENERATORS m_generators
Definition board.h:1867
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:3836
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:565
bool IsFootprintHolder() const
Find out if the board is being used to hold a single footprint for editing/viewing.
Definition board.h:441
PAD * GetPad(const VECTOR2I &aPosition, const LSET &aLayerMask) const
Find a pad aPosition on aLayer.
Definition board.cpp:3309
SHARDED_CACHE< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsAreaCache
Definition board.h:1774
void CacheChildrenById(const BOARD_ITEM &aParent)
Definition board.h:1731
int GetUserDefinedLayerCount() const
Definition board.cpp:1143
void recalcOpposites()
Definition board.cpp:1060
void SetPosition(const VECTOR2I &aPos) override
Definition board.cpp:810
std::map< wxString, wxString > m_properties
Definition board.h:1896
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_IntersectsCourtyardResultCache
Definition board.h:1777
EMBEDDED_FILES * GetEmbeddedFiles() override
Definition board.cpp:3662
SHARDED_CACHE< PTR_PTR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaCache
Definition board.h:1776
int m_fileFormatVersionAtLoad
Definition board.h:1881
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition board.cpp:2864
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2969
std::vector< ZONE * > m_DRCCopperZones
Definition board.h:1807
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:1207
void CacheItemById(BOARD_ITEM &aItem) const
Add an item to the item-by-id cache.
Definition board.h:1727
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1520
std::shared_ptr< const DRILL_SYMBOL_CACHE > m_drillSymbolCache
Definition board.h:1892
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaResultCache
Definition board.h:1782
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:3773
TITLE_BLOCK m_titles
Definition board.h:1903
GAL_SET m_LegacyVisibleItems
Definition board.h:562
std::vector< wxString > m_variantNames
Definition board.h:1910
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1679
wxArrayString GetVariantNamesForUI() const
Return the variant names for UI display.
Definition board.cpp:3161
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:1437
const GENERATORS & Generators() const
Definition board.h:485
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition board.h:1122
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition board.cpp:3738
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition board.cpp:1241
int m_outlinesChainingEpsilon
the max distance between 2 end point to see them connected when building the board outlines
Definition board.h:1849
uint64_t m_drillModelGeneration
Definition board.h:1882
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:3470
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition board.cpp:2935
BOARD_USE m_boardUse
What is this board being used for.
Definition board.h:1852
void RefreshDrillSymbolLayers()
Definition board.cpp:239
void CopyVariant(const wxString &aOldName, const wxString &aNewName, const wxString &aNewDescription=wxEmptyString)
Definition board.cpp:3090
PAGE_INFO m_paper
Definition board.h:1902
void RemoveAllListeners()
Remove all listeners.
Definition board.cpp:3830
SHARDED_CACHE< PTR_PTR_CACHE_KEY, bool > m_IntersectsBCourtyardCache
Definition board.h:1773
FOOTPRINTS m_footprints
Definition board.h:1862
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:4084
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:3811
void UpdateUserUnits(BOARD_ITEM *aItem, KIGFX::VIEW *aView)
Update any references within aItem (or its descendants) to the user units.
Definition board.cpp:2044
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition board.h:527
bool IsBackLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:985
std::shared_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:1923
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition board.cpp:1235
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition board.cpp:3893
void CompileRatsnest()
Rebuild the entire board ratsnest.
Definition board.cpp:3876
HIGH_LIGHT_INFO m_highLight
Definition board.h:1878
std::map< wxString, wxString > m_variantDescriptions
Definition board.h:1911
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition board.cpp:904
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition board.cpp:2797
EDA_UNITS m_userUnits
Definition board.h:1906
CONSTRAINTS m_constraints
Definition board.h:1865
void UpdateBoardOutline()
Definition board.cpp:4299
const ZONES & Zones() const
Definition board.h:469
void BulkRemoveStaleTeardrops(BOARD_COMMIT &aCommit)
Remove all teardrop zones with the STRUCT_DELETED flag set.
Definition board.cpp:1672
void ClearItemByIdCache()
Definition board.h:1739
void DeleteVariant(const wxString &aVariantName)
Definition board.cpp:3014
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition board.h:1833
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aSettings)
Definition board.cpp:1302
const LSET & GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:1188
void SanitizeNetcodes()
Definition board.cpp:3791
void InitializeClearanceCache()
Initialize the clearance cache for all board items.
Definition board.cpp:1318
EMBEDDED_FILES * m_embeddedFilesDelegate
Definition board.h:1939
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:3579
bool IsFrontLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:979
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition board.h:518
~BOARD()
Definition board.cpp:332
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:4347
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:369
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:1201
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition board.cpp:991
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition board.cpp:569
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.h:737
DRAWINGS m_drawings
Definition board.h:1861
uint64_t m_boardOutlineGeneration
Definition board.h:1883
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:3859
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition board.cpp:3275
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:3221
void ResetNetHighLight()
Reset all high light data to the init state.
Definition board.cpp:3884
SHARDED_CACHE< PTR_PTR_CACHE_KEY, bool > m_IntersectsCourtyardCache
Definition board.h:1771
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition board.cpp:950
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition board.cpp:3559
bool ResolveTextVar(wxString *token, int aDepth) const
Definition board.cpp:680
const MARKERS & Markers() const
Definition board.h:497
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition board.cpp:1120
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition board.cpp:3724
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition board.cpp:816
TITLE_BLOCK & GetTitleBlock()
Definition board.h:1026
void FixupEmbeddedData()
After loading a file from disk, the footprints do not yet contain the full data for their embedded fi...
Definition board.cpp:1444
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
Definition board.cpp:1325
ZONES m_zones
Definition board.h:1866
void InvalidateClearanceCache(const KIID &aUuid)
Invalidate the clearance cache for a specific item.
Definition board.cpp:1311
PAD * FindPadByUuid(const KIID &aUuid) const
Definition board.cpp:2903
void OnBoardSelectionChanged()
Notify the board and its listeners that the editor selection has changed.
Definition board.cpp:3853
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition board.cpp:912
HIGH_LIGHT_INFO m_highLightPrevious
Definition board.h:1879
NETINFO_LIST m_NetInfo
Definition board.h:1931
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:561
void SetVisibleAlls()
Change the bit-mask of visible element categories and layers.
Definition board.cpp:1224
std::shared_ptr< const DRILL_SYMBOL_CACHE > DrillSymbolCache() const
Resolved drill symbols, by group and by owning item.
Definition board.cpp:265
bool HasVariant(const wxString &aVariantName) const
Definition board.cpp:2995
void AddVariant(const wxString &aVariantName)
Definition board.cpp:3001
int GetCopperLayerCount() const
Definition board.cpp:1127
std::vector< BOARD_LISTENER * > m_listeners
Definition board.h:1933
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:1958
SHARDED_CACHE< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsKeepoutCache
Definition board.h:1775
void IncrementTimeStamp()
Definition board.cpp:448
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition board.cpp:2816
wxString GetUniqueZoneName(const wxString &aBaseName, const ZONE *aExclude=nullptr) const
Return a name based on aBaseName that is not used by any other zone or rule area on the board.
Definition board.cpp:1465
PCB_POINTS m_points
Definition board.h:1869
std::unique_ptr< LENGTH_DELAY_CALCULATION > m_lengthDelayCalc
Definition board.h:1942
const FOOTPRINTS & Footprints() const
Definition board.h:465
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition board.h:1897
std::set< KIFONT::OUTLINE_FONT * > GetFonts() const override
Get the list of all outline fonts used in the board.
Definition board.cpp:3680
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:1805
const BOARD_ITEM_SET GetItemSet()
Collect every owned item (tracks, zones, generators, footprints, drawings, markers,...
Definition board.cpp:4214
const TRACKS & Tracks() const
Definition board.h:463
int m_DRCMaxPhysicalClearance
Definition board.h:1810
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition board.cpp:2891
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:1663
BOARD_ITEM_INDEX m_itemIndex
Definition board.h:1874
std::unordered_map< wxString, LSET > m_LayerExpressionCache
Definition board.h:1784
bool m_embedFonts
Definition board.h:1935
wxString GroupsSanityCheckInternal(bool repair)
Definition board.cpp:3932
std::shared_ptr< const FOOTPRINT_COURTYARD_INDEX > m_footprintCourtyardIndex
Definition board.h:1803
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition board.cpp:3870
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition board.cpp:2368
wxString GetClass() const override
Return the class name.
Definition board.h:1409
std::unique_ptr< COMPONENT_CLASS_MANAGER > m_componentClassManager
Definition board.h:1941
SHARDED_CACHE< PTR_PTR_CACHE_KEY, bool > m_IntersectsFCourtyardCache
Definition board.h:1772
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:3604
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition board.h:569
void SetCopperLayerCount(int aCount)
Definition board.cpp:1133
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition board.h:1787
std::unordered_map< const ZONE *, SHAPE_POLY_SET > m_DeflatedZoneOutlineCache
Definition board.h:1800
std::vector< BOARD_ITEM * > collectOwnedItems() const
Get a simple vector of the board's pointers.
Definition board.cpp:4192
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_IntersectsFCourtyardResultCache
Definition board.h:1778
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition board.cpp:882
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:379
PROJECT * m_project
Definition board.h:1905
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:3495
bool HasItemsOnLayer(PCB_LAYER_ID aLayer)
Definition board.cpp:1912
const wxString & GetFileName() const
Definition board.h:454
bool operator==(const BOARD_ITEM &aOther) const override
Definition board.cpp:4231
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition board.cpp:595
int GetPadWithCastellatedAttrCount()
Definition board.cpp:4329
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_IntersectsKeepoutResultCache
Definition board.h:1781
wxString GetVariantDescription(const wxString &aVariantName) const
Definition board.cpp:3125
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition board.cpp:2879
unsigned GetNodesCount(int aNet=-1) const
Definition board.cpp:2521
SHARDED_CACHE< ITEM_FIELD_CACHE_KEY, wxString > m_ItemFieldCache
Definition board.h:1783
std::map< PCB_LAYER_ID, std::vector< ZONE * > > m_DRCCopperZonesByLayer
Definition board.h:1808
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition board.cpp:1247
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition board.h:1786
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition board.cpp:1010
std::optional< std::set< const PCB_VIA * > > m_StackedMicroviaCache
Definition board.h:1792
wxString m_fileName
Definition board.h:1855
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:932
BOX2I ExpandBoundingBoxForDrillSymbols(const BOX2I &aBoundingBox) const
Include every displaced copy of a hole-owned drill symbol in its view bounds.
Definition board.cpp:300
void DetachAllFootprints()
Remove all footprints without deleting.
Definition board.cpp:2115
std::map< int, LAYER > m_layers
Definition board.h:1876
void noteDrillModelChange(BOARD_ITEM *aItem)
Container-boundary notification, so an item that arrives or leaves without going through a commit sti...
Definition board.cpp:221
wxString GetCurrentVariant() const
Definition board.h:530
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition board.cpp:837
int GetOutlinesChainingEpsilon()
Definition board.h:1072
void BumpDrillModelGeneration()
Bumped whenever anything a drill chart or map reports on has moved.
Definition board.cpp:181
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:3444
void OnZonesFilled(const std::vector< ZONE * > &aZones)
Notify the board that the listed zones were just refilled.
Definition board.cpp:3801
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:1180
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_IntersectsAreaResultCache
Definition board.h:1780
int m_DRCMaxClearance
Definition board.h:1809
void ClearProject()
Definition board.cpp:420
void ReplaceNetChainTerminalPad(const wxString &aNetChain, const KIID &aPrev, const KIID &aNew)
Definition board.cpp:2915
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition board.h:1785
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:1654
wxString m_currentVariant
Definition board.h:1909
int LayerDepth(PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer) const
Definition board.cpp:1167
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition board.cpp:2103
PROJECT * GetProject() const
Definition board.h:774
bool IsEmpty() const
Definition board.cpp:798
int GetPadWithPressFitAttrCount()
Definition board.cpp:4311
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:2607
wxString GetDesignRulesPath() const
Return the absolute path to the design rules file for this board.
Definition board.cpp:437
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition board.cpp:3918
void RenameVariant(const wxString &aOldName, const wxString &aNewName)
Definition board.cpp:3042
std::vector< ZONE * > m_DRCZones
Definition board.h:1806
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1174
BOARD()
Definition board.cpp:99
void bumpDrillModelFor(const std::vector< BOARD_ITEM * > &aItems)
Definition board.cpp:319
std::vector< std::pair< VECTOR2I, int > > m_drillSymbolPlacements
Offset and symbol reach of every drill map, so a pad or track ViewBBox() does not walk the drawings l...
Definition board.h:1890
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition board.cpp:538
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition board.cpp:2448
int RepairDuplicateItemUuids()
Rebind duplicate attached-item UUIDs so each live board item has a unique ID.
Definition board.cpp:2292
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2949
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition board.cpp:3818
std::unique_ptr< BOARD_TEXT_VAR_ADAPTER > m_textVarAdapter
Definition board.h:1946
std::shared_mutex m_CachesMutex
Definition board.h:1768
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false, bool aPhysicalLayersOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition board.cpp:2538
std::shared_ptr< const FOOTPRINT_COURTYARD_INDEX > GetFootprintCourtyardIndex()
Return a spatial index of footprint courtyards, building it on first use.
Definition board.cpp:514
static wxString MakeUniqueZoneName(const wxString &aBaseName, const std::function< bool(const wxString &)> &aInUse)
Return a name based on aBaseName for which aInUse returns false, adding or incrementing a _<number> s...
Definition board.cpp:1483
std::atomic< int > m_timeStamp
Definition board.h:1853
std::mutex m_drillSymbolCacheMutex
Definition board.h:1893
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:3265
void UncacheChildrenById(const BOARD_ITEM &aParent)
Definition board.h:1737
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition board.cpp:2066
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition board.cpp:1691
std::unordered_map< wxString, std::vector< ZONE * > > m_ZonesByNameCache
Definition board.h:1796
GROUPS m_groups
Definition board.h:1864
MARKERS m_markers
Definition board.h:1860
LSET m_drillSymbolLayers
Definition board.h:1884
std::optional< int > m_maxClearanceValue
Definition board.h:1788
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition board.cpp:3908
void SetEnabledLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:1194
void SynchronizeTuningProfileProperties()
Ensure that all time domain properties providers are in sync with current settings.
Definition board.cpp:3175
TRACKS m_tracks
Definition board.h:1863
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
Definition board.cpp:2142
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:566
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
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:3845
SHARDED_CACHE< ITEM_SELECTOR_LAYER_CACHE_KEY, bool > m_IntersectsBCourtyardResultCache
Definition board.h:1779
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition board.h:758
VECTOR2I GetPosition() const override
Definition board.cpp:804
void SetVariantDescription(const wxString &aVariantName, const wxString &aDescription)
Definition board.cpp:3144
void CacheTriangulation(PROGRESS_REPORTER *aReporter=nullptr, const std::vector< ZONE * > &aZones={})
Definition board.cpp:1357
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition board.cpp:1214
void EmbedFonts() override
Finds all fonts used in the board and embeds them in the file if permissions allow.
Definition board.cpp:3707
PCB_BOARD_OUTLINE * m_boardOutline
Definition board.h:1868
void SetUserDefinedLayerCount(int aCount)
Definition board.cpp:1149
const DRAWINGS & Drawings() const
Definition board.h:467
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition board.cpp:2038
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr coord_type GetY() const
Definition box2.h:205
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr coord_type GetX() const
Definition box2.h:204
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition box2.h:135
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:79
COMMIT & Removed(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Notify observers that aItem has been removed.
Definition commit.h:92
A class to manage Component Classes in a board context.
COMPONENT_CLASS_SETTINGS stores data for component classes, including rules for automatic generation ...
bool GetEnableSheetComponentClasses() const
Gets whether component classes should be generated for components in hierarchical sheets.
const std::vector< COMPONENT_CLASS_ASSIGNMENT_DATA > & GetComponentClassAssignments() const
Gets all dynamic component class assignments.
void RecalculateRatsnest(BOARD_COMMIT *aCommit=nullptr)
Update the ratsnest for the board.
void RunOnUnconnectedEdges(std::function< bool(CN_EDGE &)> aFunc)
unsigned int GetUnconnectedCount(bool aVisibleOnly) const
static DELETED_BOARD_ITEM * GetInstance()
Definition board_item.h:641
Container for an DRC exclusion, which is a PCB_MARKER plus an optional comment.
static DRC_EXCLUSION FromMarker(const PCB_MARKER &aMarker)
void Build(const BOARD &aBoard, const std::vector< DRILL_SPAN > &aSpans)
const DRILL_CHART_TOTALS & Totals() const
uint64_t Fingerprint() const
Cheap value used to notice an edit.
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:43
virtual VECTOR2I GetPosition() const
Definition eda_item.h:348
virtual void ClearEditFlags()
Definition eda_item.h:178
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
const KIID m_Uuid
Definition eda_item.h:599
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:116
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
static INSPECT_RESULT IterateForward(std::deque< T > &aList, INSPECTOR inspector, void *testData, const std::vector< KICAD_T > &scanTypes)
This changes first parameter to avoid the DList and use the main queue instead.
Definition eda_item.h:401
virtual INSPECT_RESULT Visit(INSPECTOR aInspector, void *aTestData, 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:287
bool HasFlag(EDA_ITEM_FLAGS aFlag) const
Definition eda_item.h:168
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
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:94
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.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
EMBEDDED_FILES()=default
Variant information for a footprint.
Definition footprint.h:178
bool ResolveTextVar(wxString *aToken, int aDepth=0) const
Resolve any references to system tokens supported by the component.
const wxString & GetReference() const
Definition footprint.h:793
Helper for storing and iterating over GAL_LAYER_IDs.
Definition layer_ids.h:431
static GAL_SET DefaultVisible()
Definition lset.cpp:782
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:132
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:94
virtual bool IsOutline() const
Definition font.h:102
Implement 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:98
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:68
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:2631
Definition kiid.h:46
size_t size() const
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_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, LENGTH_DELAY_ITEM_DETAILS *aPerItemLengthDelays=nullptr) const
Calculates the electrical length of the given items.
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
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:595
static const LSET & AllLayersMask()
Definition lset.cpp:637
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition lset.cpp:693
std::shared_ptr< RC_ITEM > GetRCItem() const
void SetExcluded(bool aExcluded, const wxString &aComment=wxEmptyString)
Definition marker_base.h:91
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:46
void SetDescription(const wxString &aDesc)
Definition netclass.h:139
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:110
int GetNetCode() const
Definition netinfo.h:104
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition netinfo.h:66
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition netinfo.h:281
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition netinfo.h:285
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:289
unsigned GetNetCount() const
Definition netinfo.h:255
const NETNAMES_MAP & NetsByName() const
Return the name map, at least for python.
Definition netinfo.h:258
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() const
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:61
VECTOR2I GetPosition() const override
Definition pad.cpp:255
const VECTOR2D & GetSizeMils() const
Definition page_info.h:145
wxPrintOrientation GetWxOrientation() const
Definition page_info.h:128
static double GetCustomHeightMils()
Definition page_info.h:197
wxPaperSize GetPaperId() const
Definition page_info.h:133
static double GetCustomWidthMils()
Definition page_info.h:192
A 3D body attached to a footprint (or, later, placed on a board).
Definition pcb_3d_body.h:93
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...
A geometric constraint between board items (issue #2329).
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
Turns on drill symbols at the holes, for one layer.
int GetSymbolExtent() const
const VECTOR2I & GetOffset() const
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
A PCB_IO 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:546
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:552
static PCB_MARKER * FromProto(const kiapi::board::DrcMarker &aMsg)
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:39
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
Convert the text to a polygonSet describing the actual character strokes (one per segment).
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Convert the text to a polygonSet describing the actual character strokes (one per segment).
Definition pcb_text.cpp:787
const VECTOR2I & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition pcb_track.h:113
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:63
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:288
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:201
std::vector< KIID > GetIDs() const
Definition rc_item.h:188
Represent a set of closed polygons.
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
int ArcCount() const
Count the number of arc shapes present.
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:430
std::string & MutableString()
Definition richio.h:458
const wxString & GetComment(int aIdx) const
static void GetContextualTextVars(wxArrayString *aVars)
Handle a list of polygons defining a copper zone.
Definition zone.h:70
bool AppendCorner(const 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:1496
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:675
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition zone.h:688
bool SetNetCode(int aNetCode, bool aNoAssert) override
Override that clamps the netcode to 0 when this zone is in copper-thieving fill mode.
Definition zone.cpp:657
const wxString & GetZoneName() const
Definition zone.h:160
bool IsTeardropArea() const
Definition zone.h:807
@ INTERNAL
Definition common.h:96
#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)
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard, bool aPadBackdrills)
Every drill span present on the board, through-holes first.
std::map< KIID, std::vector< DRILL_SYMBOL_ENTRY > > ResolveDrillSymbolsByItem(const BOARD &aBoard, const std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > &aResolved)
The same answer keyed by the item that owns the holes.
std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > ResolveDrillSymbols(const BOARD &aBoard)
The symbol every hole should carry, without touching the board.
#define _(s)
RECURSE_MODE
Definition eda_item.h:50
@ RECURSE
Definition eda_item.h:51
INSPECT_RESULT
Definition eda_item.h:44
const INSPECTOR_FUNC & INSPECTOR
std::function passed to nested users by ref, avoids copying std::function.
Definition eda_item.h:91
std::function< INSPECT_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Used to inspect and possibly collect the (search) results of iterating over a list or tree of KICAD_T...
Definition eda_item.h:88
#define STRUCT_DELETED
flag indication structures to be erased
EDA_UNITS
Definition eda_units.h:44
static const std::string DesignRulesFileExtension
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:741
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Definition layer_ids.h:224
@ GAL_LAYER_ID_START
Definition layer_ids.h:225
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:255
@ 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:283
@ LAYER_RATSNEST
Definition layer_ids.h:249
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:256
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ Rescue
Definition layer_ids.h:117
@ User_1
Definition layer_ids.h:120
@ PCB_LAYER_ID_COUNT
Definition layer_ids.h:167
@ F_Cu
Definition layer_ids.h:60
#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:389
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
STL namespace.
std::map< wxString, NETINFO_ITEM * > NETNAMES_MAP
Definition netinfo.h:225
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:102
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:122
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:120
PAGE_SIZE_TYPE
Definition page_info.h:46
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:120
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:4022
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition board.cpp:4001
DRILL_CHART_TOTALS m_Totals
Counts for the ${DRILL_*} text variables.
Definition board.h:358
One drawable mark, with the geometry the renderer needs to place it.
std::vector< char > decompressedData
Data produced by a registered saver on the UI thread, consumed by either the background local-history...
std::string content
Serialized content (mutually exclusive with sourcePath)
KICAD_FORMAT::FORMAT_MODE formatMode
wxString relativePath
Destination path relative to the project root.
Container to hold information pertinent to a layer of a BOARD.
Definition board.h:259
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
Definition board.cpp:1039
static const char * ShowType(LAYER_T aType)
Convert a LAYER_T enum to a string representation of the layer type.
Definition board.cpp:1023
Holds length measurement result details and statistics.
Struct to control which optimisations the length calculation code runs on the given path objects.
bool copied
static const long long MM
wxString result
Test unit parsing edge cases and error handling.
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:27
wxLogTrace helper definitions.
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:260
constexpr bool IsSingleLayerType(const KICAD_T aType)
Definition typeinfo.h:516
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ PCB_T
Definition typeinfo.h:74
@ PCB_CONSTRAINT_T
a geometric constraint between board items
Definition typeinfo.h:237
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:98
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:95
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
Definition typeinfo.h:83
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_DRILL_MAP_T
class PCB_DRILL_MAP, drill symbols drawn at the holes
Definition typeinfo.h:240
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:96
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:103
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:100
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:84
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:81
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:82
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition typeinfo.h:91
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:93
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:99
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:87
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:78
@ PCB_GRID_ITEM_T
a subgrid placed on a board
Definition typeinfo.h:238
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:94
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:90
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:86
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
Definition typeinfo.h:102
@ PCB_POINT_T
class PCB_POINT, a 0-dimensional point
Definition typeinfo.h:105
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:88
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:97
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
Definition typeinfo.h:239
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.