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