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