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