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