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