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