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_skipMaxClearanceCacheUpdate( false ),
85 m_maxClearanceValue( 0 ),
86 m_NetInfo( this )
87{
88 // A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
89 // A too large value do not allow safely connecting 2 shapes like very short segments.
91
92 // we have not loaded a board yet, assume latest until then.
93 m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
94
95 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
96 {
98
99 if( IsCopperLayer( layer ) )
100 m_layers[layer].m_type = LT_SIGNAL;
101 else
103 }
104
105 // Creates a zone to show sloder mask bridges created by a min web value
106 // it it just to show them
107 m_SolderMaskBridges = new ZONE( this );
108 m_SolderMaskBridges->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::INVISIBLE_BORDER );
110 int infinity = ( std::numeric_limits<int>::max() / 2 ) - pcbIUScale.mmToIU( 1 );
112 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, -infinity ) );
113 m_SolderMaskBridges->Outline()->Append( VECTOR2I( -infinity, +infinity ) );
114 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, +infinity ) );
115 m_SolderMaskBridges->Outline()->Append( VECTOR2I( +infinity, -infinity ) );
117
119
120 // Initialize default netclass.
121 bds.m_NetSettings->m_DefaultNetClass = std::make_shared<NETCLASS>( NETCLASS::Default );
122 bds.m_NetSettings->m_DefaultNetClass->SetDescription( _( "This is the default net class." ) );
123
124 bds.UseCustomTrackViaSize( false );
125
126 // Initialize ratsnest
127 m_connectivity.reset( new CONNECTIVITY_DATA() );
128
129 // Set flag bits on these that will only be cleared if these are loaded from a legacy file
130 m_LegacyVisibleLayers.reset().set( Rescue );
132}
133
134
136{
138
139 // Untangle group parents before doing any deleting
140 for( PCB_GROUP* group : m_groups )
141 {
142 for( BOARD_ITEM* item : group->GetItems() )
143 item->SetParentGroup( nullptr );
144 }
145
146 for( PCB_GENERATOR* generator : m_generators )
147 {
148 for( BOARD_ITEM* item : generator->GetItems() )
149 item->SetParentGroup( nullptr );
150 }
151
152 m_itemByIdCache.clear();
153
154 // Clean up the owned elements
156
157 delete m_SolderMaskBridges;
158
159 BOARD_ITEM_SET ownedItems = GetItemSet();
160
161 m_zones.clear();
162 m_footprints.clear();
163 m_tracks.clear();
164 m_drawings.clear();
165 m_groups.clear();
166
167 // Generators not currently returned by GetItemSet
168 for( PCB_GENERATOR* g : m_generators )
169 ownedItems.insert( g );
170
171 m_generators.clear();
172
173 // Delete the owned items after clearing the containers, because some item dtors
174 // cause call chains that query the containers
175 for( BOARD_ITEM* item : ownedItems )
176 delete item;
177}
178
179
181{
182 if( !GetConnectivity()->Build( this, aReporter ) )
183 return false;
184
186 return true;
187}
188
189
190void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly )
191{
192 if( m_project )
193 ClearProject();
194
195 m_project = aProject;
196
197 if( aProject && !aReferenceOnly )
198 {
199 PROJECT_FILE& project = aProject->GetProjectFile();
200
201 // Link the design settings object to the project file
202 project.m_BoardSettings = &GetDesignSettings();
203
204 // Set parent, which also will load the values from JSON stored in the project if we don't
205 // have legacy design settings loaded already
206 project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
207
208 // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
209 // list at this point. If we loaded anything into it from a legacy board file then we
210 // want to transfer it over to the project netclasses list.
212 {
213 std::shared_ptr<NET_SETTINGS> legacySettings = GetDesignSettings().m_NetSettings;
214 std::shared_ptr<NET_SETTINGS>& projectSettings = project.NetSettings();
215
216 projectSettings->m_DefaultNetClass = legacySettings->m_DefaultNetClass;
217 projectSettings->m_NetClasses = legacySettings->m_NetClasses;
218 projectSettings->m_NetClassPatternAssignments =
219 std::move( legacySettings->m_NetClassPatternAssignments );
220 projectSettings->m_NetClassPatternAssignmentCache.clear();
221 }
222
223 // Now update the DesignSettings' netclass pointer to point into the project.
224 GetDesignSettings().m_NetSettings = project.NetSettings();
225 }
226}
227
228
230{
231 if( !m_project )
232 return;
233
235
236 // Owned by the BOARD
237 if( project.m_BoardSettings )
238 {
239 project.ReleaseNestedSettings( project.m_BoardSettings );
240 project.m_BoardSettings = nullptr;
241 }
242
244 GetDesignSettings().SetParent( nullptr );
245 m_project = nullptr;
246}
247
248
250{
251 m_timeStamp++;
252
254
255 if( !m_IntersectsAreaCache.empty()
256 || !m_EnclosedByAreaCache.empty()
260 || !m_LayerExpressionCache.empty()
261 || !m_ZoneBBoxCache.empty()
263 {
264 std::unique_lock<std::shared_mutex> writeLock( m_CachesMutex );
265
266 m_IntersectsAreaCache.clear();
267 m_EnclosedByAreaCache.clear();
272
273 m_ZoneBBoxCache.clear();
274
275 m_CopperItemRTreeCache = nullptr;
276
277 // These are always regenerated before use, but still probably safer to clear them
278 // while we're here.
281 m_DRCZones.clear();
282 m_DRCCopperZones.clear();
285 }
286}
287
288
290{
291 std::set<std::pair<KIID, KIID>> m_ratsnestExclusions;
292
293 for( PCB_MARKER* marker : GetBoard()->Markers() )
294 {
295 if( marker->GetMarkerType() == MARKER_BASE::MARKER_RATSNEST && marker->IsExcluded() )
296 {
297 const std::shared_ptr<RC_ITEM>& rcItem = marker->GetRCItem();
298 m_ratsnestExclusions.emplace( rcItem->GetMainItemID(), rcItem->GetAuxItemID() );
299 m_ratsnestExclusions.emplace( rcItem->GetAuxItemID(), rcItem->GetMainItemID() );
300 }
301 }
302
303 GetConnectivity()->RunOnUnconnectedEdges(
304 [&]( CN_EDGE& aEdge )
305 {
306 if( aEdge.GetSourceNode() && aEdge.GetTargetNode()
307 && !aEdge.GetSourceNode()->Dirty() && !aEdge.GetTargetNode()->Dirty() )
308 {
309 std::pair<KIID, KIID> ids = { aEdge.GetSourceNode()->Parent()->m_Uuid,
310 aEdge.GetTargetNode()->Parent()->m_Uuid };
311
312 aEdge.SetVisible( m_ratsnestExclusions.count( ids ) == 0 );
313 }
314
315 return true;
316 } );
317}
318
319
321{
322 m_designSettings->m_DrcExclusions.clear();
323 m_designSettings->m_DrcExclusionComments.clear();
324
325 for( PCB_MARKER* marker : m_markers )
326 {
327 if( marker->IsExcluded() )
328 {
329 wxString serialized = marker->SerializeToString();
330 m_designSettings->m_DrcExclusions.insert( serialized );
331 m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment();
332 }
333 }
334}
335
336
337std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions( bool aCreateMarkers )
338{
339 std::set<wxString> exclusions = m_designSettings->m_DrcExclusions;
340 std::map<wxString, wxString> comments = m_designSettings->m_DrcExclusionComments;
341
342 m_designSettings->m_DrcExclusions.clear();
343 m_designSettings->m_DrcExclusionComments.clear();
344
345 for( PCB_MARKER* marker : GetBoard()->Markers() )
346 {
347 wxString serialized = marker->SerializeToString();
348 std::set<wxString>::iterator it = exclusions.find( serialized );
349
350 if( it != exclusions.end() )
351 {
352 marker->SetExcluded( true, comments[ serialized ] );
353
354 // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS
355 m_designSettings->m_DrcExclusions.insert( serialized );
356 m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ];
357
358 exclusions.erase( it );
359 }
360 }
361
362 std::vector<PCB_MARKER*> newMarkers;
363
364 if( aCreateMarkers )
365 {
366 for( const wxString& serialized : exclusions )
367 {
368 PCB_MARKER* marker = PCB_MARKER::DeserializeFromString( serialized );
369
370 if( !marker )
371 continue;
372
373 // Check to see if items still exist
374 for( const KIID& guid : marker->GetRCItem()->GetIDs() )
375 {
377 {
378 delete marker;
379 marker = nullptr;
380 break;
381 }
382 }
383
384 if( marker )
385 {
386 marker->SetExcluded( true, comments[ serialized ] );
387 newMarkers.push_back( marker );
388
389 // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS
390 m_designSettings->m_DrcExclusions.insert( serialized );
391 m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ];
392 }
393 }
394 }
395
396 return newMarkers;
397}
398
399
400void BOARD::GetContextualTextVars( wxArrayString* aVars ) const
401{
402 auto add =
403 [&]( const wxString& aVar )
404 {
405 if( !alg::contains( *aVars, aVar ) )
406 aVars->push_back( aVar );
407 };
408
409 add( wxT( "LAYER" ) );
410 add( wxT( "FILENAME" ) );
411 add( wxT( "FILEPATH" ) );
412 add( wxT( "PROJECTNAME" ) );
413
415
416 if( GetProject() )
417 {
418 for( std::pair<wxString, wxString> entry : GetProject()->GetTextVars() )
419 add( entry.first );
420 }
421}
422
423
424bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
425{
426 if( token->Contains( ':' ) )
427 {
428 wxString remainder;
429 wxString ref = token->BeforeFirst( ':', &remainder );
430 BOARD_ITEM* refItem = GetItem( KIID( ref ) );
431
432 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
433 {
434 FOOTPRINT* refFP = static_cast<FOOTPRINT*>( refItem );
435
436 if( refFP->ResolveTextVar( &remainder, aDepth + 1 ) )
437 {
438 *token = remainder;
439 return true;
440 }
441 }
442 }
443
444 if( token->IsSameAs( wxT( "FILENAME" ) ) )
445 {
446 wxFileName fn( GetFileName() );
447 *token = fn.GetFullName();
448 return true;
449 }
450 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
451 {
452 wxFileName fn( GetFileName() );
453 *token = fn.GetFullPath();
454 return true;
455 }
456 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) && GetProject() )
457 {
458 *token = GetProject()->GetProjectName();
459 return true;
460 }
461
462 wxString var = *token;
463
464 if( GetTitleBlock().TextVarResolver( token, m_project ) )
465 {
466 return true;
467 }
468 else if( m_properties.count( var ) )
469 {
470 *token = m_properties.at( var );
471 return true;
472 }
473
474 if( GetProject() && GetProject()->TextVarResolver( token ) )
475 return true;
476
477 return false;
478}
479
480
482{
483 return ZeroOffset;
484}
485
486
487void BOARD::SetPosition( const VECTOR2I& aPos )
488{
489 wxLogWarning( wxT( "This should not be called on the BOARD object") );
490}
491
492
493void BOARD::Move( const VECTOR2I& aMoveVector ) // overload
494{
495 INSPECTOR_FUNC inspector =
496 [&] ( EDA_ITEM* item, void* testData )
497 {
498 if( BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item ) )
499 {
500 // aMoveVector was snapshotted, don't need "data".
501 // Only move the top level group
502 if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() )
503 board_item->Move( aMoveVector );
504 }
505
506 return INSPECT_RESULT::CONTINUE;
507 };
508
509 Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems );
510}
511
512
513TRACKS BOARD::TracksInNet( int aNetCode )
514{
515 TRACKS ret;
516
517 INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
518 {
519 PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
520
521 if( t->GetNetCode() == aNetCode )
522 ret.push_back( t );
523
524 return INSPECT_RESULT::CONTINUE;
525 };
526
527 // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
528 // appends all in aNetCode to ret.
529 Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
530
531 return ret;
532}
533
534
535bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
536{
537 if( unsigned( aIndex ) < arrayDim( m_layers ) )
538 {
539 m_layers[ aIndex ] = aLayer;
540 return true;
541 }
542
543 return false;
544}
545
546
547PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
548{
549 // Check the BOARD physical layer names.
550 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
551 {
552 if ( m_layers[ layer ].m_name == aLayerName || m_layers[ layer ].m_userName == aLayerName )
553 return ToLAYER_ID( layer );
554 }
555
556 // Otherwise fall back to the system standard layer names for virtual layers.
557 for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
558 {
559 if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
560 return ToLAYER_ID( layer );
561 }
562
563 return UNDEFINED_LAYER;
564}
565
566
567const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
568{
569 // All layer names are stored in the BOARD.
570 if( IsLayerEnabled( aLayer ) )
571 {
572 // Standard names were set in BOARD::BOARD() but they may be over-ridden by
573 // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
574 // if it was set. Otherwise return the Standard English layer name.
575 if( !m_layers[aLayer].m_userName.IsEmpty() )
576 return m_layers[aLayer].m_userName;
577 }
578
579 return GetStandardLayerName( aLayer );
580}
581
582
583bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
584{
585 wxCHECK( !aLayerName.IsEmpty(), false );
586
587 // no quote chars in the name allowed
588 if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
589 return false;
590
591 if( IsLayerEnabled( aLayer ) )
592 {
593 m_layers[aLayer].m_userName = aLayerName;
594 return true;
595 }
596
597 return false;
598}
599
600
602{
603 if( !IsCopperLayer( aLayer ) )
604 return LT_SIGNAL;
605
606 if( IsLayerEnabled( aLayer ) )
607 return m_layers[aLayer].m_type;
608
609 return LT_SIGNAL;
610}
611
612
613bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
614{
615 if( !IsCopperLayer( aLayer ) )
616 return false;
617
618 if( IsLayerEnabled( aLayer ) )
619 {
620 m_layers[aLayer].m_type = aLayerType;
621 return true;
622 }
623
624 return false;
625}
626
627
628const char* LAYER::ShowType( LAYER_T aType )
629{
630 switch( aType )
631 {
632 default:
633 case LT_SIGNAL: return "signal";
634 case LT_POWER: return "power";
635 case LT_MIXED: return "mixed";
636 case LT_JUMPER: return "jumper";
637 }
638}
639
640
641LAYER_T LAYER::ParseType( const char* aType )
642{
643 if( strcmp( aType, "signal" ) == 0 )
644 return LT_SIGNAL;
645 else if( strcmp( aType, "power" ) == 0 )
646 return LT_POWER;
647 else if( strcmp( aType, "mixed" ) == 0 )
648 return LT_MIXED;
649 else if( strcmp( aType, "jumper" ) == 0 )
650 return LT_JUMPER;
651 else
652 return LT_UNDEFINED;
653}
654
655
657{
659}
660
661
663{
665}
666
667
668int BOARD::LayerDepth( PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer ) const
669{
670 if( aStartLayer > aEndLayer )
671 std::swap( aStartLayer, aEndLayer );
672
673 if( aEndLayer == B_Cu )
674 aEndLayer = ToLAYER_ID( F_Cu + GetCopperLayerCount() - 1 );
675
676 return aEndLayer - aStartLayer;
677}
678
679
681{
683}
684
685
687{
688 // If there is no project, assume layer is visible always
689 return GetDesignSettings().IsLayerEnabled( aLayer )
691}
692
693
695{
697}
698
699
701{
702 GetDesignSettings().SetEnabledLayers( aLayerSet );
703}
704
705
707{
708 return GetDesignSettings().IsLayerEnabled( aLayer );
709}
710
711
713{
714 if( m_project )
716}
717
718
720{
721 // Call SetElementVisibility for each item
722 // to ensure specific calculations that can be needed by some items,
723 // just changing the visibility flags could be not sufficient.
724 for( size_t i = 0; i < aSet.size(); i++ )
725 SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
726}
727
728
730{
731 SetVisibleLayers( LSET().set() );
732
733 // Call SetElementVisibility for each item,
734 // to ensure specific calculations that can be needed by some items
736 SetElementVisibility( ii, true );
737}
738
739
741{
743}
744
745
747{
749}
750
751
752void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
753{
754 if( m_project )
756
757 switch( aLayer )
758 {
759 case LAYER_RATSNEST:
760 {
761 // because we have a tool to show/hide ratsnest relative to a pad or a footprint
762 // so the hide/show option is a per item selection
763
764 for( PCB_TRACK* track : Tracks() )
765 track->SetLocalRatsnestVisible( isEnabled );
766
767 for( FOOTPRINT* footprint : Footprints() )
768 {
769 for( PAD* pad : footprint->Pads() )
770 pad->SetLocalRatsnestVisible( isEnabled );
771 }
772
773 for( ZONE* zone : Zones() )
774 zone->SetLocalRatsnestVisible( isEnabled );
775
776 break;
777 }
778
779 default:
780 ;
781 }
782}
783
784
786{
787 switch( aLayer )
788 {
791 default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true;
792 }
793}
794
795
796
798{
799 return *m_designSettings;
800}
801
802
804{
805 // in destructor or otherwise reasonable to skip
807 return;
808
809 int worstClearance = m_designSettings->GetBiggestClearanceValue();
810
811 for( ZONE* zone : m_zones )
812 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
813
814 for( FOOTPRINT* footprint : m_footprints )
815 {
816 for( PAD* pad : footprint->Pads() )
817 {
818 std::optional<int> override = pad->GetClearanceOverrides( nullptr );
819
820 if( override.has_value() )
821 worstClearance = std::max( worstClearance, override.value() );
822 }
823
824 for( ZONE* zone : footprint->Zones() )
825 worstClearance = std::max( worstClearance, zone->GetLocalClearance().value() );
826 }
827
828 m_maxClearanceValue = worstClearance;
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{
1280
1281 for( FOOTPRINT* footprint : m_footprints )
1282 {
1283 m_itemByIdCache.erase( footprint->m_Uuid );
1284 delete footprint;
1285 }
1286
1287 m_footprints.clear();
1290}
1291
1292
1293BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
1294{
1295 if( aID == niluuid )
1296 return nullptr;
1297
1298 if( m_itemByIdCache.count( aID ) )
1299 return m_itemByIdCache.at( aID );
1300
1301 for( PCB_TRACK* track : Tracks() )
1302 {
1303 if( track->m_Uuid == aID )
1304 return track;
1305 }
1306
1307 for( FOOTPRINT* footprint : Footprints() )
1308 {
1309 if( footprint->m_Uuid == aID )
1310 return footprint;
1311
1312 for( PAD* pad : footprint->Pads() )
1313 {
1314 if( pad->m_Uuid == aID )
1315 return pad;
1316 }
1317
1318 for( PCB_FIELD* field : footprint->Fields() )
1319 {
1320 if( field->m_Uuid == aID )
1321 return field;
1322 }
1323
1324 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1325 {
1326 if( drawing->m_Uuid == aID )
1327 return drawing;
1328 }
1329
1330 for( BOARD_ITEM* zone : footprint->Zones() )
1331 {
1332 if( zone->m_Uuid == aID )
1333 return zone;
1334 }
1335
1336 for( PCB_GROUP* group : footprint->Groups() )
1337 {
1338 if( group->m_Uuid == aID )
1339 return group;
1340 }
1341 }
1342
1343 for( ZONE* zone : Zones() )
1344 {
1345 if( zone->m_Uuid == aID )
1346 return zone;
1347 }
1348
1349 for( BOARD_ITEM* drawing : Drawings() )
1350 {
1351 if( drawing->Type() == PCB_TABLE_T )
1352 {
1353 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( drawing )->GetCells() )
1354 {
1355 if( cell->m_Uuid == aID )
1356 return drawing;
1357 }
1358 }
1359
1360 if( drawing->m_Uuid == aID )
1361 return drawing;
1362 }
1363
1364 for( PCB_MARKER* marker : m_markers )
1365 {
1366 if( marker->m_Uuid == aID )
1367 return marker;
1368 }
1369
1370 for( PCB_GROUP* group : m_groups )
1371 {
1372 if( group->m_Uuid == aID )
1373 return group;
1374 }
1375
1376 for( PCB_GENERATOR* generator : m_generators )
1377 {
1378 if( generator->m_Uuid == aID )
1379 return generator;
1380 }
1381
1382
1383 for( NETINFO_ITEM* netInfo : m_NetInfo )
1384 {
1385 if( netInfo->m_Uuid == aID )
1386 return netInfo;
1387 }
1388
1389 if( m_Uuid == aID )
1390 return const_cast<BOARD*>( this );
1391
1392 // Not found; weak reference has been deleted.
1394}
1395
1396
1397void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
1398{
1399 // the board itself
1400 aMap[ m_Uuid ] = this;
1401
1402 for( PCB_TRACK* track : Tracks() )
1403 aMap[ track->m_Uuid ] = track;
1404
1405 for( FOOTPRINT* footprint : Footprints() )
1406 {
1407 aMap[ footprint->m_Uuid ] = footprint;
1408
1409 for( PAD* pad : footprint->Pads() )
1410 aMap[ pad->m_Uuid ] = pad;
1411
1412 aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference();
1413 aMap[ footprint->Value().m_Uuid ] = &footprint->Value();
1414
1415 for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
1416 aMap[ drawing->m_Uuid ] = drawing;
1417 }
1418
1419 for( ZONE* zone : Zones() )
1420 aMap[ zone->m_Uuid ] = zone;
1421
1422 for( BOARD_ITEM* drawing : Drawings() )
1423 aMap[ drawing->m_Uuid ] = drawing;
1424
1425 for( PCB_MARKER* marker : m_markers )
1426 aMap[ marker->m_Uuid ] = marker;
1427
1428 for( PCB_GROUP* group : m_groups )
1429 aMap[ group->m_Uuid ] = group;
1430
1431 for( PCB_GENERATOR* generator : m_generators )
1432 aMap[ generator->m_Uuid ] = generator;
1433}
1434
1435
1436wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
1437{
1438 wxString newbuf;
1439 size_t sourceLen = aSource.length();
1440
1441 for( size_t i = 0; i < sourceLen; ++i )
1442 {
1443 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1444 {
1445 wxString token;
1446 bool isCrossRef = false;
1447
1448 for( i = i + 2; i < sourceLen; ++i )
1449 {
1450 if( aSource[i] == '}' )
1451 break;
1452
1453 if( aSource[i] == ':' )
1454 isCrossRef = true;
1455
1456 token.append( aSource[i] );
1457 }
1458
1459 if( isCrossRef )
1460 {
1461 wxString remainder;
1462 wxString ref = token.BeforeFirst( ':', &remainder );
1463
1464 for( const FOOTPRINT* footprint : Footprints() )
1465 {
1466 if( footprint->GetReference().CmpNoCase( ref ) == 0 )
1467 {
1468 wxString test( remainder );
1469
1470 if( footprint->ResolveTextVar( &test ) )
1471 token = footprint->m_Uuid.AsString() + wxT( ":" ) + remainder;
1472
1473 break;
1474 }
1475 }
1476 }
1477
1478 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1479 }
1480 else
1481 {
1482 newbuf.append( aSource[i] );
1483 }
1484 }
1485
1486 return newbuf;
1487}
1488
1489
1490wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
1491{
1492 wxString newbuf;
1493 size_t sourceLen = aSource.length();
1494
1495 for( size_t i = 0; i < sourceLen; ++i )
1496 {
1497 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1498 {
1499 wxString token;
1500 bool isCrossRef = false;
1501
1502 for( i = i + 2; i < sourceLen; ++i )
1503 {
1504 if( aSource[i] == '}' )
1505 break;
1506
1507 if( aSource[i] == ':' )
1508 isCrossRef = true;
1509
1510 token.append( aSource[i] );
1511 }
1512
1513 if( isCrossRef )
1514 {
1515 wxString remainder;
1516 wxString ref = token.BeforeFirst( ':', &remainder );
1517 BOARD_ITEM* refItem = GetItem( KIID( ref ) );
1518
1519 if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
1520 {
1521 token = static_cast<FOOTPRINT*>( refItem )->GetReference() + wxT( ":" )
1522 + remainder;
1523 }
1524 }
1525
1526 newbuf.append( wxT( "${" ) + token + wxT( "}" ) );
1527 }
1528 else
1529 {
1530 newbuf.append( aSource[i] );
1531 }
1532 }
1533
1534 return newbuf;
1535}
1536
1537
1538unsigned BOARD::GetNodesCount( int aNet ) const
1539{
1540 unsigned retval = 0;
1541
1542 for( FOOTPRINT* footprint : Footprints() )
1543 {
1544 for( PAD* pad : footprint->Pads() )
1545 {
1546 if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1547 retval++;
1548 }
1549 }
1550
1551 return retval;
1552}
1553
1554
1555BOX2I BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1556{
1557 BOX2I bbox;
1558 LSET visible = GetVisibleLayers();
1559 bool showHiddenText = IsElementVisible( LAYER_HIDDEN_TEXT );
1560
1561 if( PgmOrNull() && PgmOrNull()->m_Printing )
1562 showHiddenText = false;
1563
1564 // If the board is just showing a footprint, we want all footprint layers
1565 // included in the bounding box
1566 if( IsFootprintHolder() )
1567 visible.set();
1568
1569 if( aBoardEdgesOnly )
1570 visible.set( Edge_Cuts );
1571
1572 // Check shapes, dimensions, texts, and fiducials
1573 for( BOARD_ITEM* item : m_drawings )
1574 {
1575 if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
1576 continue;
1577
1578 if( ( item->GetLayerSet() & visible ).any() )
1579 bbox.Merge( item->GetBoundingBox() );
1580 }
1581
1582 // Check footprints
1583 for( FOOTPRINT* footprint : m_footprints )
1584 {
1585 if( !( footprint->GetLayerSet() & visible ).any() )
1586 continue;
1587
1588 if( aBoardEdgesOnly )
1589 {
1590 for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
1591 {
1592 if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_SHAPE_T )
1593 bbox.Merge( edge->GetBoundingBox() );
1594 }
1595 }
1596 else
1597 {
1598 bbox.Merge( footprint->GetBoundingBox( true, showHiddenText ) );
1599 }
1600 }
1601
1602 if( !aBoardEdgesOnly )
1603 {
1604 // Check tracks
1605 for( PCB_TRACK* track : m_tracks )
1606 {
1607 if( ( track->GetLayerSet() & visible ).any() )
1608 bbox.Merge( track->GetBoundingBox() );
1609 }
1610
1611 // Check zones
1612 for( ZONE* aZone : m_zones )
1613 {
1614 if( ( aZone->GetLayerSet() & visible ).any() )
1615 bbox.Merge( aZone->GetBoundingBox() );
1616 }
1617 }
1618
1619 return bbox;
1620}
1621
1622
1623void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1624{
1625 int padCount = 0;
1626 int viaCount = 0;
1627 int trackSegmentCount = 0;
1628 std::set<int> netCodes;
1629 int unconnected = GetConnectivity()->GetUnconnectedCount( true );
1630
1631 for( PCB_TRACK* item : m_tracks )
1632 {
1633 if( item->Type() == PCB_VIA_T )
1634 viaCount++;
1635 else
1636 trackSegmentCount++;
1637
1638 if( item->GetNetCode() > 0 )
1639 netCodes.insert( item->GetNetCode() );
1640 }
1641
1642 for( FOOTPRINT* footprint : Footprints() )
1643 {
1644 for( PAD* pad : footprint->Pads() )
1645 {
1646 padCount++;
1647
1648 if( pad->GetNetCode() > 0 )
1649 netCodes.insert( pad->GetNetCode() );
1650 }
1651 }
1652
1653 aList.emplace_back( _( "Pads" ), wxString::Format( wxT( "%d" ), padCount ) );
1654 aList.emplace_back( _( "Vias" ), wxString::Format( wxT( "%d" ), viaCount ) );
1655 aList.emplace_back( _( "Track Segments" ), wxString::Format( wxT( "%d" ), trackSegmentCount ) );
1656 aList.emplace_back( _( "Nets" ), wxString::Format( wxT( "%d" ), (int) netCodes.size() ) );
1657 aList.emplace_back( _( "Unrouted" ), wxString::Format( wxT( "%d" ), unconnected ) );
1658}
1659
1660
1661INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData,
1662 const std::vector<KICAD_T>& scanTypes )
1663{
1664#if 0 && defined(DEBUG)
1665 std::cout << GetClass().mb_str() << ' ';
1666#endif
1667
1668 bool footprintsScanned = false;
1669 bool drawingsScanned = false;
1670 bool tracksScanned = false;
1671
1672 for( KICAD_T scanType : scanTypes )
1673 {
1674 switch( scanType )
1675 {
1676 case PCB_T:
1677 if( inspector( this, testData ) == INSPECT_RESULT::QUIT )
1678 return INSPECT_RESULT::QUIT;
1679
1680 break;
1681
1682 /*
1683 * Instances of the requested KICAD_T live in a list, either one that I manage, or one
1684 * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
1685 * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
1686 */
1687
1688 case PCB_FOOTPRINT_T:
1689 case PCB_PAD_T:
1690 case PCB_SHAPE_T:
1692 case PCB_FIELD_T:
1693 case PCB_TEXT_T:
1694 case PCB_TEXTBOX_T:
1695 case PCB_TABLE_T:
1696 case PCB_TABLECELL_T:
1697 case PCB_DIM_ALIGNED_T:
1698 case PCB_DIM_CENTER_T:
1699 case PCB_DIM_RADIAL_T:
1701 case PCB_DIM_LEADER_T:
1702 case PCB_TARGET_T:
1703 if( !footprintsScanned )
1704 {
1705 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1706 == INSPECT_RESULT::QUIT )
1707 {
1708 return INSPECT_RESULT::QUIT;
1709 }
1710
1711 footprintsScanned = true;
1712 }
1713
1714 if( !drawingsScanned )
1715 {
1716 if( IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, scanTypes )
1717 == INSPECT_RESULT::QUIT )
1718 {
1719 return INSPECT_RESULT::QUIT;
1720 }
1721
1722 drawingsScanned = true;
1723 }
1724
1725 break;
1726
1727 case PCB_VIA_T:
1728 case PCB_TRACE_T:
1729 case PCB_ARC_T:
1730 if( !tracksScanned )
1731 {
1732 if( IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, scanTypes )
1733 == INSPECT_RESULT::QUIT )
1734 {
1735 return INSPECT_RESULT::QUIT;
1736 }
1737
1738 tracksScanned = true;
1739 }
1740
1741 break;
1742
1743 case PCB_MARKER_T:
1744 for( PCB_MARKER* marker : m_markers )
1745 {
1746 if( marker->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
1747 return INSPECT_RESULT::QUIT;
1748 }
1749
1750 break;
1751
1752 case PCB_ZONE_T:
1753 if( !footprintsScanned )
1754 {
1755 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1756 == INSPECT_RESULT::QUIT )
1757 {
1758 return INSPECT_RESULT::QUIT;
1759 }
1760
1761 footprintsScanned = true;
1762 }
1763
1764 for( ZONE* zone : m_zones)
1765 {
1766 if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT )
1767 return INSPECT_RESULT::QUIT;
1768 }
1769
1770 break;
1771
1772 case PCB_GENERATOR_T:
1773 if( !footprintsScanned )
1774 {
1775 if( IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, scanTypes )
1776 == INSPECT_RESULT::QUIT )
1777 {
1778 return INSPECT_RESULT::QUIT;
1779 }
1780
1781 footprintsScanned = true;
1782 }
1783
1784 if( IterateForward<PCB_GENERATOR*>( m_generators, inspector, testData, { scanType } )
1785 == INSPECT_RESULT::QUIT )
1786 {
1787 return INSPECT_RESULT::QUIT;
1788 }
1789
1790 break;
1791
1792 case PCB_GROUP_T:
1793 if( IterateForward<PCB_GROUP*>( m_groups, inspector, testData, { scanType } )
1794 == INSPECT_RESULT::QUIT )
1795 {
1796 return INSPECT_RESULT::QUIT;
1797 }
1798
1799 break;
1800
1801 default:
1802 break;
1803 }
1804 }
1805
1806 return INSPECT_RESULT::CONTINUE;
1807}
1808
1809
1810NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1811{
1812 // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1813 // zero is reserved for "no connection" and is not actually a net.
1814 // nullptr is returned for non valid netcodes
1815
1816 wxASSERT( m_NetInfo.GetNetCount() > 0 );
1817
1818 if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1820 else
1821 return m_NetInfo.GetNetItem( aNetcode );
1822}
1823
1824
1825NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1826{
1827 return m_NetInfo.GetNetItem( aNetname );
1828}
1829
1830
1831int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
1832{
1833 int rv = 0;
1834 int count = 0;
1835
1836 for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1837 {
1838 int ch = *it;
1839
1840 if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
1841 {
1842 continue;
1843 }
1844 else if( ch == '+' )
1845 {
1846 aComplementNet = wxT( "-" );
1847 rv = 1;
1848 }
1849 else if( ch == '-' )
1850 {
1851 aComplementNet = wxT( "+" );
1852 rv = -1;
1853 }
1854 else if( ch == 'N' )
1855 {
1856 aComplementNet = wxT( "P" );
1857 rv = -1;
1858 }
1859 else if ( ch == 'P' )
1860 {
1861 aComplementNet = wxT( "N" );
1862 rv = 1;
1863 }
1864 else
1865 {
1866 break;
1867 }
1868 }
1869
1870 if( rv != 0 && count >= 1 )
1871 {
1872 aComplementNet = aNetName.Left( aNetName.length() - count )
1873 + aComplementNet
1874 + aNetName.Right( count - 1 );
1875 }
1876
1877 return rv;
1878}
1879
1880
1882{
1883 if( aNet )
1884 {
1885 wxString refName = aNet->GetNetname();
1886 wxString coupledNetName;
1887
1888 if( MatchDpSuffix( refName, coupledNetName ) )
1889 return FindNet( coupledNetName );
1890 }
1891
1892 return nullptr;
1893}
1894
1895
1896FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
1897{
1898 for( FOOTPRINT* footprint : m_footprints )
1899 {
1900 if( aReference == footprint->GetReference() )
1901 return footprint;
1902 }
1903
1904 return nullptr;
1905}
1906
1907
1909{
1910 for( FOOTPRINT* footprint : m_footprints )
1911 {
1912 if( footprint->GetPath() == aPath )
1913 return footprint;
1914 }
1915
1916 return nullptr;
1917}
1918
1919
1921{
1922 std::set<wxString> names;
1923
1924 for( const NETINFO_ITEM* net : m_NetInfo )
1925 {
1926 if( !net->GetNetname().IsEmpty() )
1927 names.insert( net->GetNetname() );
1928 }
1929
1930 return names;
1931}
1932
1933
1935{
1936 wxCHECK( m_project, /*void*/ );
1937
1938 if( !m_project->IsNullProject() )
1940}
1941
1942
1943void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes )
1944{
1945 if( !m_project )
1946 return;
1947
1949 std::shared_ptr<NETCLASS>& defaultNetClass = bds.m_NetSettings->m_DefaultNetClass;
1950
1951 for( NETINFO_ITEM* net : m_NetInfo )
1952 net->SetNetClass( bds.m_NetSettings->GetEffectiveNetClass( net->GetNetname() ) );
1953
1954 if( aResetTrackAndViaSizes )
1955 {
1956 // Set initial values for custom track width & via size to match the default
1957 // netclass settings
1958 bds.UseCustomTrackViaSize( false );
1959 bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
1960 bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
1961 bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
1962 bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
1963 bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
1964 bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
1965 }
1966
1968}
1969
1970
1972{
1973 int error_count = 0;
1974
1975 for( ZONE* zone : Zones() )
1976 {
1977 if( !zone->IsOnCopperLayer() )
1978 {
1979 zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
1980 continue;
1981 }
1982
1983 if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1984 {
1985 const NETINFO_ITEM* net = zone->GetNet();
1986
1987 if( net )
1988 {
1989 zone->SetNetCode( net->GetNetCode() );
1990 }
1991 else
1992 {
1993 error_count++;
1994
1995 // keep Net Name and set m_NetCode to -1 : error flag.
1996 zone->SetNetCode( -1 );
1997 }
1998 }
1999 }
2000
2001 return error_count;
2002}
2003
2004
2005PAD* BOARD::GetPad( const VECTOR2I& aPosition, LSET aLayerSet ) const
2006{
2007 if( !aLayerSet.any() )
2008 aLayerSet = LSET::AllCuMask();
2009
2010 for( FOOTPRINT* footprint : m_footprints )
2011 {
2012 PAD* pad = nullptr;
2013
2014 if( footprint->HitTest( aPosition ) )
2015 pad = footprint->GetPad( aPosition, aLayerSet );
2016
2017 if( pad )
2018 return pad;
2019 }
2020
2021 return nullptr;
2022}
2023
2024
2025PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
2026{
2027 const VECTOR2I& aPosition = aTrace->GetEndPoint( aEndPoint );
2028
2029 LSET lset( aTrace->GetLayer() );
2030
2031 return GetPad( aPosition, lset );
2032}
2033
2034
2035PAD* BOARD::GetPadFast( const VECTOR2I& aPosition, LSET aLayerSet ) const
2036{
2037 for( FOOTPRINT* footprint : Footprints() )
2038 {
2039 for( PAD* pad : footprint->Pads() )
2040 {
2041 if( pad->GetPosition() != aPosition )
2042 continue;
2043
2044 // Pad found, it must be on the correct layer
2045 if( ( pad->GetLayerSet() & aLayerSet ).any() )
2046 return pad;
2047 }
2048 }
2049
2050 return nullptr;
2051}
2052
2053
2054PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const VECTOR2I& aPosition, LSET aLayerSet ) const
2055{
2056 // Search aPadList for aPosition
2057 // aPadList is sorted by X then Y values, and a fast binary search is used
2058 int idxmax = aPadList.size() - 1;
2059
2060 int delta = aPadList.size();
2061
2062 int idx = 0; // Starting index is the beginning of list
2063
2064 while( delta )
2065 {
2066 // Calculate half size of remaining interval to test.
2067 // Ensure the computed value is not truncated (too small)
2068 if( (delta & 1) && ( delta > 1 ) )
2069 delta++;
2070
2071 delta /= 2;
2072
2073 PAD* pad = aPadList[idx];
2074
2075 if( pad->GetPosition() == aPosition ) // candidate found
2076 {
2077 // The pad must match the layer mask:
2078 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2079 return pad;
2080
2081 // More than one pad can be at aPosition
2082 // search for a pad at aPosition that matched this mask
2083
2084 // search next
2085 for( int ii = idx+1; ii <= idxmax; ii++ )
2086 {
2087 pad = aPadList[ii];
2088
2089 if( pad->GetPosition() != aPosition )
2090 break;
2091
2092 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2093 return pad;
2094 }
2095 // search previous
2096 for( int ii = idx - 1 ;ii >=0; ii-- )
2097 {
2098 pad = aPadList[ii];
2099
2100 if( pad->GetPosition() != aPosition )
2101 break;
2102
2103 if( ( aLayerSet & pad->GetLayerSet() ).any() )
2104 return pad;
2105 }
2106
2107 // Not found:
2108 return nullptr;
2109 }
2110
2111 if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
2112 {
2113 if( pad->GetPosition().y < aPosition.y ) // Must search after this item
2114 {
2115 idx += delta;
2116
2117 if( idx > idxmax )
2118 idx = idxmax;
2119 }
2120 else // Must search before this item
2121 {
2122 idx -= delta;
2123
2124 if( idx < 0 )
2125 idx = 0;
2126 }
2127 }
2128 else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
2129 {
2130 idx += delta;
2131
2132 if( idx > idxmax )
2133 idx = idxmax;
2134 }
2135 else // Must search before this item
2136 {
2137 idx -= delta;
2138
2139 if( idx < 0 )
2140 idx = 0;
2141 }
2142 }
2143
2144 return nullptr;
2145}
2146
2147
2153bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH )
2154{
2155 if( aLH->GetPosition().x == aRH->GetPosition().x )
2156 return aLH->GetPosition().y < aRH->GetPosition().y;
2157
2158 return aLH->GetPosition().x < aRH->GetPosition().x;
2159}
2160
2161
2162void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
2163{
2164 for( FOOTPRINT* footprint : Footprints() )
2165 {
2166 for( PAD* pad : footprint->Pads( ) )
2167 {
2168 if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
2169 aVector.push_back( pad );
2170 }
2171 }
2172
2173 std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
2174}
2175
2176
2178{
2179 if( GetDesignSettings().m_HasStackup )
2181
2182 BOARD_STACKUP stackup;
2184 return stackup;
2185}
2186
2187
2188std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
2189{
2190 int count = 0;
2191 double length = 0.0;
2192 double package_length = 0.0;
2193
2194 auto connectivity = GetBoard()->GetConnectivity();
2197
2198 for( BOARD_CONNECTED_ITEM* item : connectivity->GetConnectedItems(
2199 static_cast<const BOARD_CONNECTED_ITEM*>( &aTrack ),
2200 { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T } ) )
2201 {
2202 count++;
2203
2204 if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
2205 {
2206 if( track->Type() == PCB_VIA_T && useHeight )
2207 {
2208 PCB_VIA* via = static_cast<PCB_VIA*>( track );
2209 length += stackup.GetLayerDistance( via->TopLayer(), via->BottomLayer() );
2210 continue;
2211 }
2212 else if( track->Type() == PCB_ARC_T )
2213 {
2214 // Note: we don't apply the clip-to-pad optimization if an arc ends in a pad
2215 // Room for future improvement.
2216 length += track->GetLength();
2217 continue;
2218 }
2219
2220 bool inPad = false;
2221 SEG trackSeg( track->GetStart(), track->GetEnd() );
2222 double segLen = trackSeg.Length();
2223 double segInPadLen = 0;
2224
2225 for( auto pad_it : connectivity->GetConnectedPads( item ) )
2226 {
2227 PAD* pad = static_cast<PAD*>( pad_it );
2228
2229 bool hitStart = pad->HitTest( track->GetStart(), track->GetWidth() / 2 );
2230 bool hitEnd = pad->HitTest( track->GetEnd(), track->GetWidth() / 2 );
2231
2232 if( hitStart && hitEnd )
2233 {
2234 inPad = true;
2235 break;
2236 }
2237 else if( hitStart || hitEnd )
2238 {
2239 VECTOR2I loc;
2240
2241 // We may not collide even if we passed the bounding-box hit test
2242 if( pad->GetEffectivePolygon( ERROR_INSIDE )->Collide( trackSeg, 0, nullptr, &loc ) )
2243 {
2244 // Part 1: length of the seg to the intersection with the pad poly
2245 if( hitStart )
2246 trackSeg.A = loc;
2247 else
2248 trackSeg.B = loc;
2249
2250 segLen = trackSeg.Length();
2251
2252 // Part 2: length from the intersection to the pad anchor
2253 segInPadLen += ( loc - pad->GetPosition() ).EuclideanNorm();
2254 }
2255 }
2256 }
2257
2258 if( !inPad )
2259 length += segLen + segInPadLen;
2260 }
2261 else if( PAD* pad = dynamic_cast<PAD*>( item ) )
2262 {
2263 package_length += pad->GetPadToDieLength();
2264 }
2265 }
2266
2267 return std::make_tuple( count, length, package_length );
2268}
2269
2270
2271FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer,
2272 bool aVisibleOnly, bool aIgnoreLocked ) const
2273{
2274 FOOTPRINT* footprint = nullptr;
2275 FOOTPRINT* alt_footprint = nullptr;
2276 int min_dim = 0x7FFFFFFF;
2277 int alt_min_dim = 0x7FFFFFFF;
2278 bool current_layer_back = IsBackLayer( aActiveLayer );
2279
2280 for( FOOTPRINT* candidate : m_footprints )
2281 {
2282 // is the ref point within the footprint's bounds?
2283 if( !candidate->HitTest( aPosition ) )
2284 continue;
2285
2286 // if caller wants to ignore locked footprints, and this one is locked, skip it.
2287 if( aIgnoreLocked && candidate->IsLocked() )
2288 continue;
2289
2290 PCB_LAYER_ID layer = candidate->GetLayer();
2291
2292 // Filter non visible footprints if requested
2293 if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
2294 {
2295 BOX2I bb = candidate->GetBoundingBox( false, false );
2296
2297 int offx = bb.GetX() + bb.GetWidth() / 2;
2298 int offy = bb.GetY() + bb.GetHeight() / 2;
2299
2300 // off x & offy point to the middle of the box.
2301 int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2302 ( aPosition.y - offy ) * ( aPosition.y - offy );
2303
2304 if( current_layer_back == IsBackLayer( layer ) )
2305 {
2306 if( dist <= min_dim )
2307 {
2308 // better footprint shown on the active side
2309 footprint = candidate;
2310 min_dim = dist;
2311 }
2312 }
2313 else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
2314 {
2315 if( dist <= alt_min_dim )
2316 {
2317 // better footprint shown on the other side
2318 alt_footprint = candidate;
2319 alt_min_dim = dist;
2320 }
2321 }
2322 }
2323 }
2324
2325 if( footprint )
2326 return footprint;
2327
2328 if( alt_footprint)
2329 return alt_footprint;
2330
2331 return nullptr;
2332}
2333
2334
2335std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
2336{
2337 std::list<ZONE*> zones;
2338
2339 for( ZONE* zone : Zones() )
2340 zones.push_back( zone );
2341
2342 if( aIncludeZonesInFootprints )
2343 {
2344 for( FOOTPRINT* footprint : m_footprints )
2345 {
2346 for( ZONE* zone : footprint->Zones() )
2347 zones.push_back( zone );
2348 }
2349 }
2350
2351 return zones;
2352}
2353
2354
2355ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer,
2356 VECTOR2I aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch )
2357{
2358 ZONE* new_area = new ZONE( this );
2359
2360 new_area->SetNetCode( aNetcode );
2361 new_area->SetLayer( aLayer );
2362
2363 m_zones.push_back( new_area );
2364
2365 new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
2366
2367 // Add the first corner to the new zone
2368 new_area->AppendCorner( aStartPointPosition, -1 );
2369
2370 if( aNewZonesList )
2371 {
2372 ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
2373 aNewZonesList->PushItem( picker );
2374 }
2375
2376 return new_area;
2377}
2378
2379
2381 OUTLINE_ERROR_HANDLER* aErrorHandler,
2382 bool aAllowUseArcsInPolygons,
2383 bool aIncludeNPTHAsOutlines )
2384{
2385 // max dist from one endPt to next startPt: use the current value
2386 int chainingEpsilon = GetOutlinesChainingEpsilon();
2387
2388 bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
2389 chainingEpsilon, aErrorHandler,
2390 aAllowUseArcsInPolygons );
2391
2392 // Now add NPTH oval holes as holes in outlines if required
2393 if( aIncludeNPTHAsOutlines )
2394 {
2395 for( FOOTPRINT* fp : Footprints() )
2396 {
2397 for( PAD* pad : fp->Pads() )
2398 {
2399 if( pad->GetAttribute () != PAD_ATTRIB::NPTH )
2400 continue;
2401
2402 SHAPE_POLY_SET hole;
2403 pad->TransformHoleToPolygon( hole, 0, GetDesignSettings().m_MaxError, ERROR_INSIDE );
2404
2405 // Add this pad hole to the main outline
2406 // But we can have more than one main outline (i.e. more than one board), so
2407 // search the right main outline i.e. the outline that contains the pad hole
2408 SHAPE_LINE_CHAIN& pad_hole = hole.Outline( 0 );
2409 const VECTOR2I holePt = pad_hole.CPoint( 0 );
2410
2411 for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj )
2412 {
2413 if( aOutlines.Outline( jj ).PointInside( holePt ) )
2414 {
2415 aOutlines.AddHole( pad_hole, jj );
2416 break;
2417 }
2418 }
2419 }
2420 }
2421 }
2422
2423 // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2425
2426 return success;
2427}
2428
2429
2430const std::vector<PAD*> BOARD::GetPads() const
2431{
2432 std::vector<PAD*> allPads;
2433
2434 for( FOOTPRINT* footprint : Footprints() )
2435 {
2436 for( PAD* pad : footprint->Pads() )
2437 allPads.push_back( pad );
2438 }
2439
2440 return allPads;
2441}
2442
2443
2444const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
2445{
2446 std::vector<BOARD_CONNECTED_ITEM*> items;
2447
2448 for( PCB_TRACK* track : Tracks() )
2449 items.push_back( track );
2450
2451 for( FOOTPRINT* footprint : Footprints() )
2452 {
2453 for( PAD* pad : footprint->Pads() )
2454 items.push_back( pad );
2455 }
2456
2457 for( ZONE* zone : Zones() )
2458 items.push_back( zone );
2459
2460 for( BOARD_ITEM* item : Drawings() )
2461 {
2462 if( BOARD_CONNECTED_ITEM* bci = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
2463 items.push_back( bci );
2464 }
2465
2466 return items;
2467}
2468
2469
2470void BOARD::MapNets( BOARD* aDestBoard )
2471{
2473 {
2474 NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
2475
2476 if( netInfo )
2477 item->SetNet( netInfo );
2478 else
2479 {
2480 NETINFO_ITEM* newNet = new NETINFO_ITEM( aDestBoard, item->GetNetname() );
2481 aDestBoard->Add( newNet );
2482 item->SetNet( newNet );
2483
2484 }
2485 }
2486}
2487
2488
2490{
2491 for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
2492 {
2493 if( FindNet( item->GetNetCode() ) == nullptr )
2494 item->SetNetCode( NETINFO_LIST::ORPHANED );
2495 }
2496}
2497
2498
2500{
2501 if( !alg::contains( m_listeners, aListener ) )
2502 m_listeners.push_back( aListener );
2503}
2504
2505
2507{
2508 auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
2509
2510 if( i != m_listeners.end() )
2511 {
2512 std::iter_swap( i, m_listeners.end() - 1 );
2513 m_listeners.pop_back();
2514 }
2515}
2516
2517
2519{
2520 m_listeners.clear();
2521}
2522
2523
2525{
2527}
2528
2529
2530void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
2531{
2533}
2534
2535
2536void BOARD::OnItemsCompositeUpdate( std::vector<BOARD_ITEM*>& aAddedItems,
2537 std::vector<BOARD_ITEM*>& aRemovedItems,
2538 std::vector<BOARD_ITEM*>& aChangedItems )
2539{
2540 InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems,
2541 aChangedItems );
2542}
2543
2544
2546{
2548}
2549
2550
2552{
2555
2557}
2558
2559
2560void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
2561{
2562 if( !m_highLight.m_netCodes.count( aNetCode ) )
2563 {
2564 if( !aMulti )
2565 m_highLight.m_netCodes.clear();
2566
2567 m_highLight.m_netCodes.insert( aNetCode );
2569 }
2570}
2571
2572
2573void BOARD::HighLightON( bool aValue )
2574{
2575 if( m_highLight.m_highLightOn != aValue )
2576 {
2577 m_highLight.m_highLightOn = aValue;
2579 }
2580}
2581
2582
2583wxString BOARD::GroupsSanityCheck( bool repair )
2584{
2585 if( repair )
2586 {
2587 while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
2588 {};
2589
2590 return wxEmptyString;
2591 }
2592 return GroupsSanityCheckInternal( repair );
2593}
2594
2595
2597{
2598 // Cycle detection
2599 //
2600 // Each group has at most one parent group.
2601 // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
2602 // If we ever see a group that we've already marked, that's a cycle.
2603 // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
2604 //
2605 // Algorithm below is linear in the # of groups because each group is visited only once.
2606 // There may be extra time taken due to the container access calls and iterators.
2607 //
2608 // Groups we know are cycle free
2609 std::unordered_set<PCB_GROUP*> knownCycleFreeGroups;
2610 // Groups in the current chain we're exploring.
2611 std::unordered_set<PCB_GROUP*> currentChainGroups;
2612 // Groups we haven't checked yet.
2613 std::unordered_set<PCB_GROUP*> toCheckGroups;
2614
2615 // Initialize set of groups and generators to check that could participate in a cycle.
2616 for( PCB_GROUP* group : Groups() )
2617 toCheckGroups.insert( group );
2618
2619 for( PCB_GENERATOR* gen : Generators() )
2620 toCheckGroups.insert( gen );
2621
2622 while( !toCheckGroups.empty() )
2623 {
2624 currentChainGroups.clear();
2625 PCB_GROUP* group = *toCheckGroups.begin();
2626
2627 while( true )
2628 {
2629 if( currentChainGroups.find( group ) != currentChainGroups.end() )
2630 {
2631 if( repair )
2632 Remove( group );
2633
2634 return "Cycle detected in group membership";
2635 }
2636 else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
2637 {
2638 // Parent is a group we know does not lead to a cycle
2639 break;
2640 }
2641
2642 currentChainGroups.insert( group );
2643 // We haven't visited currIdx yet, so it must be in toCheckGroups
2644 toCheckGroups.erase( group );
2645
2646 group = group->GetParentGroup();
2647
2648 if( !group )
2649 {
2650 // end of chain and no cycles found in this chain
2651 break;
2652 }
2653 }
2654
2655 // No cycles found in chain, so add it to set of groups we know don't participate
2656 // in a cycle.
2657 knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
2658 }
2659
2660 // Success
2661 return "";
2662}
2663
2664
2666{
2667 bool hasGroup = false;
2668 bool hasMember = false;
2669
2670 for( EDA_ITEM* item : selection )
2671 {
2672 if( BOARD_ITEM* board_item = dynamic_cast<BOARD_ITEM*>( item ) )
2673 {
2674 if( board_item->Type() == PCB_GROUP_T )
2675 hasGroup = true;
2676
2677 if( board_item->GetParentGroup() )
2678 hasMember = true;
2679 }
2680 }
2681
2682 GroupLegalOpsField legalOps;
2683
2684 legalOps.create = true;
2685 legalOps.removeItems = hasMember;
2686 legalOps.ungroup = hasGroup;
2687
2688 return legalOps;
2689}
2690
2691
2693{
2694 if( a->Type() != b->Type() )
2695 return a->Type() < b->Type();
2696
2697 if( a->GetLayer() != b->GetLayer() )
2698 return a->GetLayer() < b->GetLayer();
2699
2700 if( a->GetPosition().x != b->GetPosition().x )
2701 return a->GetPosition().x < b->GetPosition().x;
2702
2703 if( a->GetPosition().y != b->GetPosition().y )
2704 return a->GetPosition().y < b->GetPosition().y;
2705
2706 if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards
2707 return a->m_Uuid < b->m_Uuid;
2708
2709 return a < b;
2710}
2711
2712
2714 const BOARD_ITEM* aSecond ) const
2715{
2716 if( aFirst->Type() != aSecond->Type() )
2717 return aFirst->Type() < aSecond->Type();
2718
2719 if( aFirst->GetLayer() != aSecond->GetLayer() )
2720 return aFirst->GetLayer() < aSecond->GetLayer();
2721
2722 if( aFirst->Type() == PCB_SHAPE_T )
2723 {
2724 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aFirst );
2725 const PCB_SHAPE* other = static_cast<const PCB_SHAPE*>( aSecond );
2726 return shape->Compare( other );
2727 }
2728 else if( aFirst->Type() == PCB_TEXT_T || aFirst->Type() == PCB_FIELD_T )
2729 {
2730 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( aFirst );
2731 const PCB_TEXT* other = static_cast<const PCB_TEXT*>( aSecond );
2732 return text->Compare( other );
2733 }
2734 else if( aFirst->Type() == PCB_TEXTBOX_T )
2735 {
2736 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( aFirst );
2737 const PCB_TEXTBOX* other = static_cast<const PCB_TEXTBOX*>( aSecond );
2738
2739 return textbox->PCB_SHAPE::Compare( other ) && textbox->EDA_TEXT::Compare( other );
2740 }
2741 else if( aFirst->Type() == PCB_TABLE_T )
2742 {
2743 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( aFirst );
2744 const PCB_TABLE* other = static_cast<const PCB_TABLE*>( aSecond );
2745
2746 return PCB_TABLE::Compare( table, other );
2747 }
2748
2749 return aFirst->m_Uuid < aSecond->m_Uuid;
2750}
2751
2752
2754 SHAPE_POLY_SET& aOutlines ) const
2755{
2756 int maxError = GetDesignSettings().m_MaxError;
2757
2758 // convert tracks and vias:
2759 for( const PCB_TRACK* track : m_tracks )
2760 {
2761 if( !track->IsOnLayer( aLayer ) )
2762 continue;
2763
2764 track->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2765 }
2766
2767 // convert pads and other copper items in footprints
2768 for( const FOOTPRINT* footprint : m_footprints )
2769 {
2770 footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2771
2772 footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE,
2773 true, /* include text */
2774 true, /* include shapes */
2775 false /* include private items */ );
2776
2777 for( const ZONE* zone : footprint->Zones() )
2778 {
2779 if( zone->GetLayerSet().test( aLayer ) )
2780 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
2781 }
2782 }
2783
2784 // convert copper zones
2785 for( const ZONE* zone : Zones() )
2786 {
2787 if( zone->GetLayerSet().test( aLayer ) )
2788 zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
2789 }
2790
2791 // convert graphic items on copper layers (texts)
2792 for( const BOARD_ITEM* item : m_drawings )
2793 {
2794 if( !item->IsOnLayer( aLayer ) )
2795 continue;
2796
2797 switch( item->Type() )
2798 {
2799 case PCB_SHAPE_T:
2800 {
2801 const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
2802 shape->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2803 break;
2804 }
2805
2806 case PCB_FIELD_T:
2807 case PCB_TEXT_T:
2808 {
2809 const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
2810 text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2811 break;
2812 }
2813
2814 case PCB_TEXTBOX_T:
2815 {
2816 const PCB_TEXTBOX* textbox = static_cast<const PCB_TEXTBOX*>( item );
2817
2818 // border
2819 textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError,
2820 ERROR_INSIDE );
2821 // text
2822 textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2823 break;
2824 }
2825
2826 case PCB_TABLE_T:
2827 {
2828 const PCB_TABLE* table = static_cast<const PCB_TABLE*>( item );
2829
2830 table->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2831 break;
2832 }
2833
2834 case PCB_DIM_ALIGNED_T:
2835 case PCB_DIM_CENTER_T:
2836 case PCB_DIM_RADIAL_T:
2838 case PCB_DIM_LEADER_T:
2839 {
2840 const PCB_DIMENSION_BASE* dim = static_cast<const PCB_DIMENSION_BASE*>( item );
2841
2842 dim->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE );
2843 dim->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE );
2844 break;
2845 }
2846
2847 default:
2848 break;
2849 }
2850 }
2851}
2852
2853
2855{
2856 BOARD_ITEM_SET items;
2857
2858 std::copy( m_tracks.begin(), m_tracks.end(), std::inserter( items, items.end() ) );
2859 std::copy( m_zones.begin(), m_zones.end(), std::inserter( items, items.end() ) );
2860 std::copy( m_footprints.begin(), m_footprints.end(), std::inserter( items, items.end() ) );
2861 std::copy( m_drawings.begin(), m_drawings.end(), std::inserter( items, items.end() ) );
2862 std::copy( m_markers.begin(), m_markers.end(), std::inserter( items, items.end() ) );
2863 std::copy( m_groups.begin(), m_groups.end(), std::inserter( items, items.end() ) );
2864
2865 return items;
2866}
2867
2868
2869bool BOARD::operator==( const BOARD_ITEM& aItem ) const
2870{
2871 if( aItem.Type() != Type() )
2872 return false;
2873
2874 const BOARD& other = static_cast<const BOARD&>( aItem );
2875
2876 if( *m_designSettings != *other.m_designSettings )
2877 return false;
2878
2879 if( m_NetInfo.GetNetCount() != other.m_NetInfo.GetNetCount() )
2880 return false;
2881
2882 const NETNAMES_MAP& thisNetNames = m_NetInfo.NetsByName();
2883 const NETNAMES_MAP& otherNetNames = other.m_NetInfo.NetsByName();
2884
2885 for( auto it1 = thisNetNames.begin(), it2 = otherNetNames.begin();
2886 it1 != thisNetNames.end() && it2 != otherNetNames.end(); ++it1, ++it2 )
2887 {
2888 // We only compare the names in order here, not the index values
2889 // as the index values are auto-generated and the names are not.
2890 if( it1->first != it2->first )
2891 return false;
2892 }
2893
2894 if( m_properties.size() != other.m_properties.size() )
2895 return false;
2896
2897 for( auto it1 = m_properties.begin(), it2 = other.m_properties.begin();
2898 it1 != m_properties.end() && it2 != other.m_properties.end(); ++it1, ++it2 )
2899 {
2900 if( *it1 != *it2 )
2901 return false;
2902 }
2903
2905 return false;
2906
2908 return false;
2909
2910 if( m_paper.GetSizeMils() != other.m_paper.GetSizeMils() )
2911 return false;
2912
2913 if( m_paper.GetPaperId() != other.m_paper.GetPaperId() )
2914 return false;
2915
2917 return false;
2918
2919 for( int ii = 0; !m_titles.GetComment( ii ).empty(); ++ii )
2920 {
2921 if( m_titles.GetComment( ii ) != other.m_titles.GetComment( ii ) )
2922 return false;
2923 }
2924
2925 wxArrayString ourVars;
2926 m_titles.GetContextualTextVars( &ourVars );
2927
2928 wxArrayString otherVars;
2929 other.m_titles.GetContextualTextVars( &otherVars );
2930
2931 if( ourVars != otherVars )
2932 return false;
2933
2934 return true;
2935}
2936
2937
@ 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:2153
#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:1661
ZONE * m_SolderMaskBridges
Definition: board.h:1278
void GetContextualTextVars(wxArrayString *aVars) const
Definition: board.cpp:400
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:785
BOARD_STACKUP GetStackupOrDefault() const
Definition: board.cpp:2177
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_EnclosedByAreaCache
Definition: board.h:1267
std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > m_ZoneIsolatedIslandsMap
Definition: board.h:1279
GENERATORS m_generators
Definition: board.h:1317
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:2380
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:2524
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:680
void SetPosition(const VECTOR2I &aPos) override
Definition: board.cpp:487
std::map< wxString, wxString > m_properties
Definition: board.h:1330
int m_fileFormatVersionAtLoad
Definition: board.h:1327
NETINFO_ITEM * DpCoupledNet(const NETINFO_ITEM *aNet)
Definition: board.cpp:1881
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:694
std::vector< ZONE * > m_DRCCopperZones
Definition: board.h:1275
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:2470
TITLE_BLOCK m_titles
Definition: board.h:1334
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:2035
LAYER m_layers[PCB_LAYER_ID_COUNT]
Definition: board.h:1322
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:2444
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:746
int m_outlinesChainingEpsilon
the max distance between 2 end point to see them connected when building the board outlines
Definition: board.h:1302
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition: board.cpp:1920
PAGE_INFO m_paper
Definition: board.h:1333
void RemoveAllListeners()
Remove all listeners.
Definition: board.cpp:2518
FOOTPRINTS m_footprints
Definition: board.h:1313
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:1349
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:700
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:2499
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:740
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2560
HIGH_LIGHT_INFO m_highLight
Definition: board.h:1324
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition: board.cpp:535
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1810
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:1293
const ZONES & Zones() const
Definition: board.h:327
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition: board.h:1289
void SanitizeNetcodes()
Definition: board.cpp:2489
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:2355
const GROUPS & Groups() const
The groups must maintain the following invariants.
Definition: board.h:350
~BOARD()
Definition: board.cpp:135
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:180
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:706
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:601
void RecordDRCExclusions()
Scan existing markers and record data from any that are Excluded.
Definition: board.cpp:320
DRAWINGS m_drawings
Definition: board.h:1312
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:2536
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition: board.cpp:1971
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1943
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2551
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:583
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition: board.cpp:2335
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:2753
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:424
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:2430
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: board.cpp:493
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:677
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1555
ZONES m_zones
Definition: board.h:1316
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition: board.cpp:547
HIGH_LIGHT_INFO m_highLightPrevious
Definition: board.h:1325
NETINFO_LIST m_NetInfo
Definition: board.h:1360
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:729
GroupLegalOpsField GroupLegalOps(const PCB_SELECTION &selection) const
Check which selection tool group operations are legal given the selection.
Definition: board.cpp:2665
int GetCopperLayerCount() const
Definition: board.cpp:656
int m_timeStamp
Definition: board.h:1306
std::vector< BOARD_LISTENER * > m_listeners
Definition: board.h:1362
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsCourtyardCache
Definition: board.h:1263
void IncrementTimeStamp()
Definition: board.cpp:249
int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet)
Fetch the coupled netname for a given net.
Definition: board.cpp:1831
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsFCourtyardCache
Definition: board.h:1264
const FOOTPRINTS & Footprints() const
Definition: board.h:323
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: board.h:1331
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:2854
const TRACKS & Tracks() const
Definition: board.h:321
int m_DRCMaxPhysicalClearance
Definition: board.h:1277
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition: board.cpp:1908
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:1268
wxString GroupsSanityCheckInternal(bool repair)
Definition: board.cpp:2596
void OnRatsnestChanged()
Notify the board and its listeners that the ratsnest has been recomputed.
Definition: board.cpp:2545
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:1436
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:712
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition: board.h:369
void SetCopperLayerCount(int aCount)
Definition: board.cpp:662
std::unordered_map< const ZONE *, BOX2I > m_ZoneBBoxCache
Definition: board.h:1271
std::unordered_map< PTR_PTR_CACHE_KEY, bool > m_IntersectsBCourtyardCache
Definition: board.h:1265
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition: board.cpp:513
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:190
PROJECT * m_project
Definition: board.h:1336
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:2271
const wxString & GetFileName() const
Definition: board.h:319
bool operator==(const BOARD_ITEM &aOther) const override
Definition: board.cpp:2869
bool m_skipMaxClearanceCacheUpdate
Definition: board.h:1357
std::vector< PCB_MARKER * > ResolveDRCExclusions(bool aCreateMarkers)
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition: board.cpp:337
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition: board.cpp:1896
unsigned GetNodesCount(int aNet=-1) const
Definition: board.cpp:1538
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:1397
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:752
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition: board.h:1270
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:613
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:2162
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:686
int m_DRCMaxClearance
Definition: board.h:1276
void ClearProject()
Definition: board.cpp:229
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition: board.h:1269
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:668
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:2188
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:1623
void UpdateMaxClearanceCache()
Definition: board.cpp:803
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition: board.cpp:2583
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
std::vector< ZONE * > m_DRCZones
Definition: board.h:1274
PAD * GetPad(const VECTOR2I &aPosition, LSET aLayerMask) const
Find a pad aPosition on aLayer.
Definition: board.cpp:2005
BOARD()
Definition: board.cpp:73
void UpdateRatsnestExclusions()
Update the visibility flags on the current unconnected ratsnest lines.
Definition: board.cpp:289
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1490
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:1934
std::unordered_map< KIID, BOARD_ITEM * > m_itemByIdCache
Definition: board.h:1320
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition: board.cpp:2506
std::shared_mutex m_CachesMutex
Definition: board.h:1262
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:1315
MARKERS m_markers
Definition: board.h:1311
std::unordered_map< PTR_PTR_LAYER_CACHE_KEY, bool > m_IntersectsAreaCache
Definition: board.h:1266
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2573
int m_maxClearanceValue
Definition: board.h:1358
TRACKS m_tracks
Definition: board.h:1314
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:2530
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:481
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:719
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:427
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:1626
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:1992
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:59
VECTOR2I GetPosition() const override
Definition: pad.h:201
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:785
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:295
static int Compare(const PCB_TABLE *aTable, const PCB_TABLE *aOther)
Definition: pcb_table.cpp:379
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const override
Invoke a function on all children.
Definition: pcb_table.cpp:214
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:122
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_HIDDEN_TEXT
text marked as invisible
Definition: layer_ids.h:204
@ 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:57
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: pgm_base.cpp:1066
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:2713
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition: board.cpp:2692
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:641
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:628
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:588
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:49