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