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