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