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