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