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