KiCad PCB EDA Suite
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 (C) 1992-2021 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 <algorithm>
29 #include <iterator>
30 #include <drc/drc_rtree.h>
31 #include <pcb_base_frame.h>
32 #include <board_design_settings.h>
33 #include <reporter.h>
34 #include <board_commit.h>
35 #include <board.h>
36 #include <footprint.h>
37 #include <pcb_track.h>
38 #include <zone.h>
39 #include <pcb_marker.h>
40 #include <pcb_group.h>
41 #include <pcb_target.h>
42 #include <core/arraydim.h>
43 #include <core/kicad_algo.h>
45 #include <kicad_string.h>
46 #include <pgm_base.h>
47 #include <pcbnew_settings.h>
48 #include <project.h>
49 #include <project/net_settings.h>
50 #include <project/project_file.h>
52 #include <ratsnest/ratsnest_data.h>
55 #include <wx/log.h>
56 
57 // This is an odd place for this, but CvPcb won't link if it's in board_item.cpp like I first
58 // tried it.
59 wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
60 
61 
63  BOARD_ITEM_CONTAINER( (BOARD_ITEM*) nullptr, PCB_T ),
64  m_LegacyDesignSettingsLoaded( false ),
65  m_LegacyCopperEdgeClearanceLoaded( false ),
66  m_LegacyNetclassesLoaded( false ),
67  m_boardUse( BOARD_USE::NORMAL ),
68  m_timeStamp( 1 ),
69  m_paper( PAGE_INFO::A4 ),
70  m_project( nullptr ),
71  m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
72  m_NetInfo( this )
73 {
74  // we have not loaded a board yet, assume latest until then.
75  m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
76 
77  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
78  {
79  m_layers[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
80 
81  if( IsCopperLayer( layer ) )
82  m_layers[layer].m_type = LT_SIGNAL;
83  else
84  m_layers[layer].m_type = LT_UNDEFINED;
85  }
86 
88 
89  // Initialize default netclass.
90  NETCLASS* defaultClass = bds.GetDefault();
91  defaultClass->SetDescription( _( "This is the default net class." ) );
92 
93  bds.UseCustomTrackViaSize( false );
94 
95  // Initialize ratsnest
96  m_connectivity.reset( new CONNECTIVITY_DATA() );
97 
98  // Set flag bits on these that will only be cleared if these are loaded from a legacy file
99  m_LegacyVisibleLayers.reset().set( Rescue );
101 }
102 
103 
105 {
106  // Clean up the owned elements
107  DeleteMARKERs();
108 
109  for( ZONE* zone : m_zones )
110  delete zone;
111 
112  m_zones.clear();
113 
114  for( FOOTPRINT* footprint : m_footprints )
115  delete footprint;
116 
117  m_footprints.clear();
118 
119  for( PCB_TRACK* t : m_tracks )
120  delete t;
121 
122  m_tracks.clear();
123 
124  for( BOARD_ITEM* d : m_drawings )
125  delete d;
126 
127  m_drawings.clear();
128 
129  for( PCB_GROUP* g : m_groups )
130  delete g;
131 
132  m_groups.clear();
133 }
134 
135 
137 {
138  GetConnectivity()->Build( this );
139 }
140 
141 
142 void BOARD::SetProject( PROJECT* aProject )
143 {
144  if( m_project )
145  ClearProject();
146 
147  m_project = aProject;
148 
149  if( aProject )
150  {
151  PROJECT_FILE& project = aProject->GetProjectFile();
152 
153  // Link the design settings object to the project file
154  project.m_BoardSettings = &GetDesignSettings();
155 
156  // Set parent, which also will load the values from JSON stored in the project if we don't
157  // have legacy design settings loaded already
158  project.m_BoardSettings->SetParent( &project, !m_LegacyDesignSettingsLoaded );
159 
160  // The DesignSettings' netclasses pointer will be pointing to its internal netclasses
161  // list at this point. If we loaded anything into it from a legacy board file then we
162  // want to transfer it over to the project netclasses list.
164  project.NetSettings().m_NetClasses = GetDesignSettings().GetNetClasses();
165 
166  // Now update the DesignSettings' netclass pointer to point into the project.
167  GetDesignSettings().SetNetClasses( &project.NetSettings().m_NetClasses );
168  }
169 }
170 
171 
173 {
174  if( !m_project )
175  return;
176 
178 
179  // Owned by the BOARD
180  if( project.m_BoardSettings )
181  {
182  project.ReleaseNestedSettings( project.m_BoardSettings );
183  project.m_BoardSettings = nullptr;
184  }
185 
186  GetDesignSettings().SetParent( nullptr );
187  m_project = nullptr;
188 }
189 
190 
192 {
193  m_timeStamp++;
194 
195  {
196  std::unique_lock<std::mutex> cacheLock( m_CachesMutex );
197  m_InsideAreaCache.clear();
198  m_InsideCourtyardCache.clear();
199  m_InsideFCourtyardCache.clear();
200  m_InsideBCourtyardCache.clear();
201  }
202 
203  m_CopperZoneRTrees.clear();
204 }
205 
206 std::vector<PCB_MARKER*> BOARD::ResolveDRCExclusions()
207 {
208  for( PCB_MARKER* marker : GetBoard()->Markers() )
209  {
210  auto i = m_designSettings->m_DrcExclusions.find( marker->Serialize() );
211 
212  if( i != m_designSettings->m_DrcExclusions.end() )
213  {
214  marker->SetExcluded( true );
215  m_designSettings->m_DrcExclusions.erase( i );
216  }
217  }
218 
219  std::vector<PCB_MARKER*> newMarkers;
220 
221  for( const wxString& exclusionData : m_designSettings->m_DrcExclusions )
222  {
223  PCB_MARKER* marker = PCB_MARKER::Deserialize( exclusionData );
224 
225  if( marker )
226  {
227  marker->SetExcluded( true );
228  newMarkers.push_back( marker );
229  }
230  }
231 
232  m_designSettings->m_DrcExclusions.clear();
233 
234  return newMarkers;
235 }
236 
237 
238 bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const
239 {
240  if( GetTitleBlock().TextVarResolver( token, m_project ) )
241  {
242  return true;
243  }
244  else if( m_properties.count( *token ) )
245  {
246  *token = m_properties.at( *token );
247  return true;
248  }
249 
250  return false;
251 }
252 
253 
254 wxPoint BOARD::GetPosition() const
255 {
256  return ZeroOffset;
257 }
258 
259 
260 void BOARD::SetPosition( const wxPoint& aPos )
261 {
262  wxLogWarning( wxT( "This should not be called on the BOARD object") );
263 }
264 
265 
266 void BOARD::Move( const wxPoint& aMoveVector ) // overload
267 {
268  // @todo : anything like this elsewhere? maybe put into GENERAL_COLLECTOR class.
269  static const KICAD_T top_level_board_stuff[] = {
270  PCB_MARKER_T,
271  PCB_TEXT_T,
272  PCB_SHAPE_T,
277  PCB_TARGET_T,
278  PCB_VIA_T,
279  PCB_TRACE_T,
280  PCB_ARC_T,
281  // PCB_PAD_T, Can't be at board level
282  // PCB_FP_TEXT_T, Can't be at board level
283  // PCB_FP_SHAPE_T, Can't be at board level
284  // PCB_FP_ZONE_T, Can't be at board level
286  PCB_ZONE_T,
287  EOT
288  };
289 
290  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
291  {
292  BOARD_ITEM* brd_item = (BOARD_ITEM*) item;
293 
294  // aMoveVector was snapshotted, don't need "data".
295  brd_item->Move( aMoveVector );
296 
298  };
299 
300  Visit( inspector, nullptr, top_level_board_stuff );
301 }
302 
303 
304 TRACKS BOARD::TracksInNet( int aNetCode )
305 {
306  TRACKS ret;
307 
308  INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData )
309  {
310  PCB_TRACK* t = static_cast<PCB_TRACK*>( item );
311 
312  if( t->GetNetCode() == aNetCode )
313  ret.push_back( t );
314 
316  };
317 
318  // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which
319  // appends all in aNetCode to ret.
320  Visit( inspector, nullptr, GENERAL_COLLECTOR::Tracks );
321 
322  return ret;
323 }
324 
325 
326 bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
327 {
328  if( unsigned( aIndex ) < arrayDim( m_layers ) )
329  {
330  m_layers[ aIndex ] = aLayer;
331  return true;
332  }
333 
334  return false;
335 }
336 
337 
338 const PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
339 {
340 
341  // Check the BOARD physical layer names.
342  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
343  {
344  if ( ( m_layers[ layer ].m_name == aLayerName )
345  || ( m_layers[ layer ].m_userName == aLayerName ) )
346  return ToLAYER_ID( layer );
347  }
348 
349  // Otherwise fall back to the system standard layer names for virtual layers.
350  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
351  {
352  if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
353  return ToLAYER_ID( layer );
354  }
355 
356  return UNDEFINED_LAYER;
357 }
358 
359 
360 const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
361 {
362  // All layer names are stored in the BOARD.
363  if( IsLayerEnabled( aLayer ) )
364  {
365  // Standard names were set in BOARD::BOARD() but they may be over-ridden by
366  // BOARD::SetLayerName(). For copper layers, return the user defined layer name,
367  // if it was set. Otherwise return the Standard English layer name.
368  if( !m_layers[aLayer].m_userName.IsEmpty() )
369  return m_layers[aLayer].m_userName;
370  }
371 
372  return GetStandardLayerName( aLayer );
373 }
374 
375 
376 bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
377 {
378  wxCHECK( !aLayerName.IsEmpty(), false );
379 
380  // no quote chars in the name allowed
381  if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
382  return false;
383 
384  if( IsLayerEnabled( aLayer ) )
385  {
386  m_layers[aLayer].m_userName = aLayerName;
387  return true;
388  }
389 
390  return false;
391 }
392 
393 
395 {
396  if( !IsCopperLayer( aLayer ) )
397  return LT_SIGNAL;
398 
399  //@@IMB: The original test was broken due to the discontinuity
400  // in the layer sequence.
401  if( IsLayerEnabled( aLayer ) )
402  return m_layers[aLayer].m_type;
403 
404  return LT_SIGNAL;
405 }
406 
407 
408 bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
409 {
410  if( !IsCopperLayer( aLayer ) )
411  return false;
412 
413  //@@IMB: The original test was broken due to the discontinuity
414  // in the layer sequence.
415  if( IsLayerEnabled( aLayer ) )
416  {
417  m_layers[aLayer].m_type = aLayerType;
418  return true;
419  }
420 
421  return false;
422 }
423 
424 
425 const char* LAYER::ShowType( LAYER_T aType )
426 {
427  switch( aType )
428  {
429  default:
430  case LT_SIGNAL: return "signal";
431  case LT_POWER: return "power";
432  case LT_MIXED: return "mixed";
433  case LT_JUMPER: return "jumper";
434  }
435 }
436 
437 
438 LAYER_T LAYER::ParseType( const char* aType )
439 {
440  if( strcmp( aType, "signal" ) == 0 )
441  return LT_SIGNAL;
442  else if( strcmp( aType, "power" ) == 0 )
443  return LT_POWER;
444  else if( strcmp( aType, "mixed" ) == 0 )
445  return LT_MIXED;
446  else if( strcmp( aType, "jumper" ) == 0 )
447  return LT_JUMPER;
448  else
449  return LT_UNDEFINED;
450 }
451 
452 
454 {
456 }
457 
458 
459 void BOARD::SetCopperLayerCount( int aCount )
460 {
462 }
463 
464 
466 {
468 }
469 
470 
472 {
473  // If there is no project, assume layer is visible always
474  return GetDesignSettings().IsLayerEnabled( aLayer )
475  && ( !m_project || m_project->GetLocalSettings().m_VisibleLayers[aLayer] );
476 }
477 
478 
480 {
482 }
483 
484 
485 void BOARD::SetEnabledLayers( LSET aLayerSet )
486 {
487  GetDesignSettings().SetEnabledLayers( aLayerSet );
488 }
489 
490 
492 {
493  return GetDesignSettings().IsLayerEnabled( aLayer );
494 }
495 
496 
497 void BOARD::SetVisibleLayers( LSET aLayerSet )
498 {
499  if( m_project )
501 }
502 
503 
505 {
506  // Call SetElementVisibility for each item
507  // to ensure specific calculations that can be needed by some items,
508  // just changing the visibility flags could be not sufficient.
509  for( size_t i = 0; i < aSet.size(); i++ )
510  SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
511 }
512 
513 
515 {
516  SetVisibleLayers( LSET().set() );
517 
518  // Call SetElementVisibility for each item,
519  // to ensure specific calculations that can be needed by some items
521  SetElementVisibility( ii, true );
522 }
523 
524 
526 {
528 }
529 
530 
532 {
534 }
535 
536 
537 void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
538 {
539  if( m_project )
541 
542  switch( aLayer )
543  {
544  case LAYER_RATSNEST:
545  {
546  // because we have a tool to show/hide ratsnest relative to a pad or a footprint
547  // so the hide/show option is a per item selection
548 
549  for( PCB_TRACK* track : Tracks() )
550  track->SetLocalRatsnestVisible( isEnabled );
551 
552  for( FOOTPRINT* footprint : Footprints() )
553  {
554  for( PAD* pad : footprint->Pads() )
555  pad->SetLocalRatsnestVisible( isEnabled );
556  }
557 
558  for( ZONE* zone : Zones() )
559  zone->SetLocalRatsnestVisible( isEnabled );
560 
561  break;
562  }
563 
564  default:
565  ;
566  }
567 }
568 
569 
571 {
572  switch( aLayer )
573  {
574  case F_Cu:
575  return IsElementVisible( LAYER_MOD_FR );
576 
577  case B_Cu:
578  return IsElementVisible( LAYER_MOD_BK );
579 
580  default:
581  wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible() param error: bad layer" ) );
582  return true;
583  }
584 }
585 
586 
587 
589 {
590  return *m_designSettings;
591 }
592 
593 
595 {
597 }
598 
599 
600 void BOARD::SetZoneSettings( const ZONE_SETTINGS& aSettings )
601 {
603 }
604 
605 
606 void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
607 {
608  if( aBoardItem == nullptr )
609  {
610  wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem nullptr" ) );
611  return;
612  }
613 
614  switch( aBoardItem->Type() )
615  {
616  case PCB_NETINFO_T:
617  m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
618  break;
619 
620  // this one uses a vector
621  case PCB_MARKER_T:
622  m_markers.push_back( (PCB_MARKER*) aBoardItem );
623  break;
624 
625  // this one uses a vector
626  case PCB_GROUP_T:
627  m_groups.push_back( (PCB_GROUP*) aBoardItem );
628  break;
629 
630  // this one uses a vector
631  case PCB_ZONE_T:
632  m_zones.push_back( (ZONE*) aBoardItem );
633  break;
634 
635  case PCB_TRACE_T:
636  case PCB_VIA_T:
637  case PCB_ARC_T:
638 
639  // N.B. This inserts a small memory leak as we lose the
640  if( !IsCopperLayer( aBoardItem->GetLayer() ) )
641  {
642  wxFAIL_MSG( wxT( "BOARD::Add() Cannot place Track on non-copper layer" ) );
643  return;
644  }
645 
646  if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
647  m_tracks.push_back( static_cast<PCB_TRACK*>( aBoardItem ) );
648  else
649  m_tracks.push_front( static_cast<PCB_TRACK*>( aBoardItem ) );
650 
651  break;
652 
653  case PCB_FOOTPRINT_T:
654  if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
655  m_footprints.push_back( static_cast<FOOTPRINT*>( aBoardItem ) );
656  else
657  m_footprints.push_front( static_cast<FOOTPRINT*>( aBoardItem ) );
658 
659  break;
660 
661  case PCB_DIM_ALIGNED_T:
662  case PCB_DIM_CENTER_T:
664  case PCB_DIM_LEADER_T:
665  case PCB_SHAPE_T:
666  case PCB_TEXT_T:
667  case PCB_TARGET_T:
668  if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND )
669  m_drawings.push_back( aBoardItem );
670  else
671  m_drawings.push_front( aBoardItem );
672 
673  break;
674 
675  // other types may use linked list
676  default:
677  {
678  wxString msg;
679  msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
680  aBoardItem->Type() );
681  wxFAIL_MSG( msg );
682  return;
683  }
684  break;
685  }
686 
687  aBoardItem->SetParent( this );
688  aBoardItem->ClearEditFlags();
689  m_connectivity->Add( aBoardItem );
690 
691  if( aMode != ADD_MODE::BULK_INSERT && aMode != ADD_MODE::BULK_APPEND )
692  InvokeListeners( &BOARD_LISTENER::OnBoardItemAdded, *this, aBoardItem );
693 }
694 
695 
696 void BOARD::FinalizeBulkAdd( std::vector<BOARD_ITEM*>& aNewItems )
697 {
699 }
700 
701 
702 void BOARD::FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems )
703 {
704  InvokeListeners( &BOARD_LISTENER::OnBoardItemsRemoved, *this, aRemovedItems );
705 }
706 
707 
708 void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode )
709 {
710  // find these calls and fix them! Don't send me no stinking' nullptr.
711  wxASSERT( aBoardItem );
712 
713  switch( aBoardItem->Type() )
714  {
715  case PCB_NETINFO_T:
716  {
717  NETINFO_ITEM* item = static_cast<NETINFO_ITEM*>( aBoardItem );
719 
720  for( FOOTPRINT* fp : m_footprints )
721  {
722  for( PAD* pad : fp->Pads() )
723  {
724  if( pad->GetNet() == item )
725  pad->SetNet( unconnected );
726  }
727  }
728 
729  for( ZONE* zone : m_zones )
730  {
731  if( zone->GetNet() == item )
732  zone->SetNet( unconnected );
733  }
734 
735  for( PCB_TRACK* track : m_tracks )
736  {
737  if( track->GetNet() == item )
738  track->SetNet( unconnected );
739  }
740 
741  m_NetInfo.RemoveNet( item );
742  break;
743  }
744 
745  case PCB_MARKER_T:
746  m_markers.erase( std::remove_if( m_markers.begin(), m_markers.end(),
747  [aBoardItem]( BOARD_ITEM* aItem )
748  {
749  return aItem == aBoardItem;
750  } ) );
751  break;
752 
753  case PCB_GROUP_T:
754  m_groups.erase( std::remove_if( m_groups.begin(), m_groups.end(),
755  [aBoardItem]( BOARD_ITEM* aItem )
756  {
757  return aItem == aBoardItem;
758  } ) );
759  break;
760 
761  case PCB_ZONE_T:
762  m_zones.erase( std::remove_if( m_zones.begin(), m_zones.end(),
763  [aBoardItem]( BOARD_ITEM* aItem )
764  {
765  return aItem == aBoardItem;
766  } ) );
767  break;
768 
769  case PCB_FOOTPRINT_T:
770  m_footprints.erase( std::remove_if( m_footprints.begin(), m_footprints.end(),
771  [aBoardItem]( BOARD_ITEM* aItem )
772  {
773  return aItem == aBoardItem;
774  } ) );
775  break;
776 
777  case PCB_TRACE_T:
778  case PCB_ARC_T:
779  case PCB_VIA_T:
780  m_tracks.erase( std::remove_if( m_tracks.begin(), m_tracks.end(),
781  [aBoardItem]( BOARD_ITEM* aItem )
782  {
783  return aItem == aBoardItem;
784  } ) );
785  break;
786 
787  case PCB_DIM_ALIGNED_T:
788  case PCB_DIM_CENTER_T:
790  case PCB_DIM_LEADER_T:
791  case PCB_SHAPE_T:
792  case PCB_TEXT_T:
793  case PCB_TARGET_T:
794  m_drawings.erase( std::remove_if( m_drawings.begin(), m_drawings.end(),
795  [aBoardItem](BOARD_ITEM* aItem)
796  {
797  return aItem == aBoardItem;
798  } ) );
799  break;
800 
801  // other types may use linked list
802  default:
803  wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
804  }
805 
806  aBoardItem->SetFlags( STRUCT_DELETED );
807 
808  PCB_GROUP* parentGroup = aBoardItem->GetParentGroup();
809 
810  if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
811  parentGroup->RemoveItem( aBoardItem );
812 
813  m_connectivity->Remove( aBoardItem );
814 
815  if( aRemoveMode != REMOVE_MODE::BULK )
817 }
818 
819 
820 wxString BOARD::GetSelectMenuText( EDA_UNITS aUnits ) const
821 {
822  return wxString::Format( _( "PCB" ) );
823 }
824 
825 
827 {
828  // the vector does not know how to delete the PCB_MARKER, it holds pointers
829  for( PCB_MARKER* marker : m_markers )
830  delete marker;
831 
832  m_markers.clear();
833 }
834 
835 
836 void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
837 {
838  // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
839  MARKERS remaining;
840 
841  for( PCB_MARKER* marker : m_markers )
842  {
843  if( ( marker->IsExcluded() && aExclusions )
844  || ( !marker->IsExcluded() && aWarningsAndErrors ) )
845  {
846  delete marker;
847  }
848  else
849  {
850  remaining.push_back( marker );
851  }
852  }
853 
854  m_markers = remaining;
855 }
856 
857 
859 {
860  for( FOOTPRINT* footprint : m_footprints )
861  delete footprint;
862 
863  m_footprints.clear();
864 }
865 
866 
867 BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
868 {
869  if( aID == niluuid )
870  return nullptr;
871 
872  for( PCB_TRACK* track : Tracks() )
873  {
874  if( track->m_Uuid == aID )
875  return track;
876  }
877 
878  for( FOOTPRINT* footprint : Footprints() )
879  {
880  if( footprint->m_Uuid == aID )
881  return footprint;
882 
883  for( PAD* pad : footprint->Pads() )
884  {
885  if( pad->m_Uuid == aID )
886  return pad;
887  }
888 
889  if( footprint->Reference().m_Uuid == aID )
890  return &footprint->Reference();
891 
892  if( footprint->Value().m_Uuid == aID )
893  return &footprint->Value();
894 
895  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
896  {
897  if( drawing->m_Uuid == aID )
898  return drawing;
899  }
900 
901  for( BOARD_ITEM* zone : footprint->Zones() )
902  {
903  if( zone->m_Uuid == aID )
904  return zone;
905  }
906 
907  for( PCB_GROUP* group : footprint->Groups() )
908  {
909  if( group->m_Uuid == aID )
910  return group;
911  }
912  }
913 
914  for( ZONE* zone : Zones() )
915  {
916  if( zone->m_Uuid == aID )
917  return zone;
918  }
919 
920  for( BOARD_ITEM* drawing : Drawings() )
921  {
922  if( drawing->m_Uuid == aID )
923  return drawing;
924  }
925 
926  for( PCB_MARKER* marker : m_markers )
927  {
928  if( marker->m_Uuid == aID )
929  return marker;
930  }
931 
932  for( PCB_GROUP* group : m_groups )
933  {
934  if( group->m_Uuid == aID )
935  return group;
936  }
937 
938  if( m_Uuid == aID )
939  return const_cast<BOARD*>( this );
940 
941  // Not found; weak reference has been deleted.
943 }
944 
945 
946 void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
947 {
948  // the board itself
949  aMap[ m_Uuid ] = this;
950 
951  for( PCB_TRACK* track : Tracks() )
952  aMap[ track->m_Uuid ] = track;
953 
954  for( FOOTPRINT* footprint : Footprints() )
955  {
956  aMap[ footprint->m_Uuid ] = footprint;
957 
958  for( PAD* pad : footprint->Pads() )
959  aMap[ pad->m_Uuid ] = pad;
960 
961  aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference();
962  aMap[ footprint->Value().m_Uuid ] = &footprint->Value();
963 
964  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
965  aMap[ drawing->m_Uuid ] = drawing;
966  }
967 
968  for( ZONE* zone : Zones() )
969  aMap[ zone->m_Uuid ] = zone;
970 
971  for( BOARD_ITEM* drawing : Drawings() )
972  aMap[ drawing->m_Uuid ] = drawing;
973 
974  for( PCB_MARKER* marker : m_markers )
975  aMap[ marker->m_Uuid ] = marker;
976 
977  for( PCB_GROUP* group : m_groups )
978  aMap[ group->m_Uuid ] = group;
979 }
980 
981 
982 wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const
983 {
984  wxString newbuf;
985  size_t sourceLen = aSource.length();
986 
987  for( size_t i = 0; i < sourceLen; ++i )
988  {
989  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
990  {
991  wxString token;
992  bool isCrossRef = false;
993 
994  for( i = i + 2; i < sourceLen; ++i )
995  {
996  if( aSource[i] == '}' )
997  break;
998 
999  if( aSource[i] == ':' )
1000  isCrossRef = true;
1001 
1002  token.append( aSource[i] );
1003  }
1004 
1005  if( isCrossRef )
1006  {
1007  wxString remainder;
1008  wxString ref = token.BeforeFirst( ':', &remainder );
1009 
1010  for( const FOOTPRINT* footprint : Footprints() )
1011  {
1012  if( footprint->GetReference().CmpNoCase( ref ) == 0 )
1013  {
1014  wxString test( remainder );
1015 
1016  if( footprint->ResolveTextVar( &test ) )
1017  token = footprint->m_Uuid.AsString() + ":" + remainder;
1018 
1019  break;
1020  }
1021  }
1022  }
1023 
1024  newbuf.append( "${" + token + "}" );
1025  }
1026  else
1027  {
1028  newbuf.append( aSource[i] );
1029  }
1030  }
1031 
1032  return newbuf;
1033 }
1034 
1035 
1036 wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const
1037 {
1038  wxString newbuf;
1039  size_t sourceLen = aSource.length();
1040 
1041  for( size_t i = 0; i < sourceLen; ++i )
1042  {
1043  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
1044  {
1045  wxString token;
1046  bool isCrossRef = false;
1047 
1048  for( i = i + 2; i < sourceLen; ++i )
1049  {
1050  if( aSource[i] == '}' )
1051  break;
1052 
1053  if( aSource[i] == ':' )
1054  isCrossRef = true;
1055 
1056  token.append( aSource[i] );
1057  }
1058 
1059  if( isCrossRef )
1060  {
1061  wxString remainder;
1062  wxString ref = token.BeforeFirst( ':', &remainder );
1063  BOARD_ITEM* refItem = GetItem( KIID( ref ) );
1064 
1065  if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
1066  token = static_cast<FOOTPRINT*>( refItem )->GetReference() + ":" + remainder;
1067  }
1068 
1069  newbuf.append( "${" + token + "}" );
1070  }
1071  else
1072  {
1073  newbuf.append( aSource[i] );
1074  }
1075  }
1076 
1077  return newbuf;
1078 }
1079 
1080 
1081 unsigned BOARD::GetNodesCount( int aNet ) const
1082 {
1083  unsigned retval = 0;
1084 
1085  for( FOOTPRINT* footprint : Footprints() )
1086  {
1087  for( PAD* pad : footprint->Pads() )
1088  {
1089  if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1090  retval++;
1091  }
1092  }
1093 
1094  return retval;
1095 }
1096 
1097 
1099 {
1100  return m_connectivity->GetUnconnectedCount();
1101 }
1102 
1103 
1104 EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1105 {
1106  EDA_RECT area;
1107  LSET visible = GetVisibleLayers();
1108  bool showInvisibleText = IsElementVisible( LAYER_MOD_TEXT_INVISIBLE )
1109  && PgmOrNull() && !PgmOrNull()->m_Printing;
1110 
1111  if( aBoardEdgesOnly )
1112  visible.set( Edge_Cuts );
1113 
1114  // Check shapes, dimensions, texts, and fiducials
1115  for( BOARD_ITEM* item : m_drawings )
1116  {
1117  if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
1118  continue;
1119 
1120  if( ( item->GetLayerSet() & visible ).any() )
1121  area.Merge( item->GetBoundingBox() );
1122  }
1123 
1124  // Check footprints
1125  for( FOOTPRINT* footprint : m_footprints )
1126  {
1127  if( !( footprint->GetLayerSet() & visible ).any() )
1128  continue;
1129 
1130  if( aBoardEdgesOnly )
1131  {
1132  for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
1133  {
1134  if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_FP_SHAPE_T )
1135  area.Merge( edge->GetBoundingBox() );
1136  }
1137  }
1138  else
1139  {
1140  area.Merge( footprint->GetBoundingBox( true, showInvisibleText ) );
1141  }
1142  }
1143 
1144  if( !aBoardEdgesOnly )
1145  {
1146  // Check tracks
1147  for( PCB_TRACK* track : m_tracks )
1148  {
1149  if( ( track->GetLayerSet() & visible ).any() )
1150  area.Merge( track->GetBoundingBox() );
1151  }
1152 
1153  // Check zones
1154  for( ZONE* aZone : m_zones )
1155  {
1156  if( ( aZone->GetLayerSet() & visible ).any() )
1157  area.Merge( aZone->GetBoundingBox() );
1158  }
1159  }
1160 
1161  return area;
1162 }
1163 
1164 
1165 void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1166 {
1167  wxString txt;
1168  int viasCount = 0;
1169  int trackSegmentsCount = 0;
1170 
1171  for( PCB_TRACK* item : m_tracks )
1172  {
1173  if( item->Type() == PCB_VIA_T )
1174  viasCount++;
1175  else
1176  trackSegmentsCount++;
1177  }
1178 
1179  txt.Printf( wxT( "%d" ), GetPadCount() );
1180  aList.emplace_back( _( "Pads" ), txt );
1181 
1182  txt.Printf( wxT( "%d" ), viasCount );
1183  aList.emplace_back( _( "Vias" ), txt );
1184 
1185  txt.Printf( wxT( "%d" ), trackSegmentsCount );
1186  aList.emplace_back( _( "Track Segments" ), txt );
1187 
1188  txt.Printf( wxT( "%d" ), GetNodesCount() );
1189  aList.emplace_back( _( "Nodes" ), txt );
1190 
1191  txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() - 1 /* Don't include "No Net" in count */ );
1192  aList.emplace_back( _( "Nets" ), txt );
1193 
1194  txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
1195  aList.emplace_back( _( "Unrouted" ), txt );
1196 }
1197 
1198 
1199 SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1200 {
1201  KICAD_T stype;
1203  const KICAD_T* p = scanTypes;
1204  bool done = false;
1205 
1206 #if 0 && defined(DEBUG)
1207  std::cout << GetClass().mb_str() << ' ';
1208 #endif
1209 
1210  while( !done )
1211  {
1212  stype = *p;
1213 
1214  switch( stype )
1215  {
1216  case PCB_T:
1217  result = inspector( this, testData ); // inspect me
1218  // skip over any types handled in the above call.
1219  ++p;
1220  break;
1221 
1222  /*
1223  * Instances of the requested KICAD_T live in a list, either one that I manage, or one
1224  * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
1225  * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
1226  */
1227 
1228  case PCB_FOOTPRINT_T:
1229  case PCB_PAD_T:
1230  case PCB_FP_TEXT_T:
1231  case PCB_FP_SHAPE_T:
1232  case PCB_FP_ZONE_T:
1233 
1234  // this calls FOOTPRINT::Visit() on each footprint.
1235  result = IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, p );
1236 
1237  // skip over any types handled in the above call.
1238  for( ; ; )
1239  {
1240  switch( stype = *++p )
1241  {
1242  case PCB_FOOTPRINT_T:
1243  case PCB_PAD_T:
1244  case PCB_FP_TEXT_T:
1245  case PCB_FP_SHAPE_T:
1246  case PCB_FP_ZONE_T:
1247  continue;
1248 
1249  default:
1250  ;
1251  }
1252 
1253  break;
1254  }
1255 
1256  break;
1257 
1258  case PCB_SHAPE_T:
1259  case PCB_TEXT_T:
1260  case PCB_DIM_ALIGNED_T:
1261  case PCB_DIM_CENTER_T:
1262  case PCB_DIM_ORTHOGONAL_T:
1263  case PCB_DIM_LEADER_T:
1264  case PCB_TARGET_T:
1265  result = IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, p );
1266 
1267  // skip over any types handled in the above call.
1268  for( ; ; )
1269  {
1270  switch( stype = *++p )
1271  {
1272  case PCB_SHAPE_T:
1273  case PCB_TEXT_T:
1274  case PCB_DIM_ALIGNED_T:
1275  case PCB_DIM_CENTER_T:
1276  case PCB_DIM_ORTHOGONAL_T:
1277  case PCB_DIM_LEADER_T:
1278  case PCB_TARGET_T:
1279  continue;
1280 
1281  default:
1282  ;
1283  }
1284 
1285  break;
1286  }
1287 
1288  break;
1289 
1290  case PCB_VIA_T:
1291  result = IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, p );
1292  ++p;
1293  break;
1294 
1295  case PCB_TRACE_T:
1296  case PCB_ARC_T:
1297  result = IterateForward<PCB_TRACK*>( m_tracks, inspector, testData, p );
1298  ++p;
1299  break;
1300 
1301  case PCB_MARKER_T:
1302  for( PCB_MARKER* marker : m_markers )
1303  {
1304  result = marker->Visit( inspector, testData, p );
1305 
1306  if( result == SEARCH_RESULT::QUIT )
1307  break;
1308  }
1309 
1310  ++p;
1311  break;
1312 
1313  case PCB_ZONE_T:
1314  for( ZONE* zone : m_zones)
1315  {
1316  result = zone->Visit( inspector, testData, p );
1317 
1318  if( result == SEARCH_RESULT::QUIT )
1319  break;
1320  }
1321 
1322  ++p;
1323  break;
1324 
1325  case PCB_GROUP_T:
1326  result = IterateForward<PCB_GROUP*>( m_groups, inspector, testData, p );
1327  ++p;
1328  break;
1329 
1330  default: // catch EOT or ANY OTHER type here and return.
1331  done = true;
1332  break;
1333  }
1334 
1335  if( result == SEARCH_RESULT::QUIT )
1336  break;
1337  }
1338 
1339  return result;
1340 }
1341 
1342 
1343 NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1344 {
1345  // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1346  // zero is reserved for "no connection" and is not actually a net.
1347  // nullptr is returned for non valid netcodes
1348 
1349  wxASSERT( m_NetInfo.GetNetCount() > 0 );
1350 
1351  if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1352  return NETINFO_LIST::OrphanedItem();
1353  else
1354  return m_NetInfo.GetNetItem( aNetcode );
1355 }
1356 
1357 
1358 NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1359 {
1360  return m_NetInfo.GetNetItem( aNetname );
1361 }
1362 
1363 
1364 FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
1365 {
1366  for( FOOTPRINT* footprint : m_footprints )
1367  {
1368  if( aReference == footprint->GetReference() )
1369  return footprint;
1370  }
1371 
1372  return nullptr;
1373 }
1374 
1375 
1377 {
1378  for( FOOTPRINT* footprint : m_footprints )
1379  {
1380  if( footprint->GetPath() == aPath )
1381  return footprint;
1382  }
1383 
1384  return nullptr;
1385 }
1386 
1387 
1388 std::vector<wxString> BOARD::GetNetClassAssignmentCandidates() const
1389 {
1390  std::vector<wxString> names;
1391 
1392  for( const NETINFO_ITEM* net : m_NetInfo )
1393  {
1394  if( !net->GetNetname().IsEmpty() )
1395  names.emplace_back( net->GetNetname() );
1396  }
1397 
1398  return names;
1399 }
1400 
1401 
1403 {
1404  if( m_project )
1406 }
1407 
1408 
1410 {
1411  if( !m_project )
1412  return;
1413 
1414  NET_SETTINGS* netSettings = m_project->GetProjectFile().m_NetSettings.get();
1415  NETCLASSES& netClasses = netSettings->m_NetClasses;
1416  NETCLASSPTR defaultNetClass = netClasses.GetDefault();
1417 
1418  for( NETINFO_ITEM* net : m_NetInfo )
1419  {
1420  const wxString& netname = net->GetNetname();
1421  const wxString& netclassName = netSettings->GetNetclassName( netname );
1422 
1423  net->SetNetClass( netClasses.Find( netclassName ) );
1424  }
1425 
1427 
1428  // Set initial values for custom track width & via size to match the default
1429  // netclass settings
1430  bds.UseCustomTrackViaSize( false );
1431  bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
1432  bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
1433  bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
1434  bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
1435  bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
1436  bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
1437 
1439 }
1440 
1441 
1443 {
1444  int error_count = 0;
1445 
1446  for( ZONE* zone : Zones() )
1447  {
1448  if( !zone->IsOnCopperLayer() )
1449  {
1450  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
1451  continue;
1452  }
1453 
1454  if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1455  {
1456  const NETINFO_ITEM* net = zone->GetNet();
1457 
1458  if( net )
1459  {
1460  zone->SetNetCode( net->GetNetCode() );
1461  }
1462  else
1463  {
1464  error_count++;
1465 
1466  // keep Net Name and set m_NetCode to -1 : error flag.
1467  zone->SetNetCode( -1 );
1468  }
1469  }
1470  }
1471 
1472  return error_count;
1473 }
1474 
1475 
1476 PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet ) const
1477 {
1478  if( !aLayerSet.any() )
1479  aLayerSet = LSET::AllCuMask();
1480 
1481  for( FOOTPRINT* footprint : m_footprints )
1482  {
1483  PAD* pad = nullptr;
1484 
1485  if( footprint->HitTest( aPosition ) )
1486  pad = footprint->GetPad( aPosition, aLayerSet );
1487 
1488  if( pad )
1489  return pad;
1490  }
1491 
1492  return nullptr;
1493 }
1494 
1495 
1496 PAD* BOARD::GetPad( const PCB_TRACK* aTrace, ENDPOINT_T aEndPoint ) const
1497 {
1498  const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
1499 
1500  LSET lset( aTrace->GetLayer() );
1501 
1502  return GetPad( aPosition, lset );
1503 }
1504 
1505 
1506 PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet ) const
1507 {
1508  for( FOOTPRINT* footprint : Footprints() )
1509  {
1510  for( PAD* pad : footprint->Pads() )
1511  {
1512  if( pad->GetPosition() != aPosition )
1513  continue;
1514 
1515  // Pad found, it must be on the correct layer
1516  if( ( pad->GetLayerSet() & aLayerSet ).any() )
1517  return pad;
1518  }
1519  }
1520 
1521  return nullptr;
1522 }
1523 
1524 
1525 PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet ) const
1526 {
1527  // Search aPadList for aPosition
1528  // aPadList is sorted by X then Y values, and a fast binary search is used
1529  int idxmax = aPadList.size() - 1;
1530 
1531  int delta = aPadList.size();
1532 
1533  int idx = 0; // Starting index is the beginning of list
1534 
1535  while( delta )
1536  {
1537  // Calculate half size of remaining interval to test.
1538  // Ensure the computed value is not truncated (too small)
1539  if( (delta & 1) && ( delta > 1 ) )
1540  delta++;
1541 
1542  delta /= 2;
1543 
1544  PAD* pad = aPadList[idx];
1545 
1546  if( pad->GetPosition() == aPosition ) // candidate found
1547  {
1548  // The pad must match the layer mask:
1549  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1550  return pad;
1551 
1552  // More than one pad can be at aPosition
1553  // search for a pad at aPosition that matched this mask
1554 
1555  // search next
1556  for( int ii = idx+1; ii <= idxmax; ii++ )
1557  {
1558  pad = aPadList[ii];
1559 
1560  if( pad->GetPosition() != aPosition )
1561  break;
1562 
1563  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1564  return pad;
1565  }
1566  // search previous
1567  for( int ii = idx - 1 ;ii >=0; ii-- )
1568  {
1569  pad = aPadList[ii];
1570 
1571  if( pad->GetPosition() != aPosition )
1572  break;
1573 
1574  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1575  return pad;
1576  }
1577 
1578  // Not found:
1579  return nullptr;
1580  }
1581 
1582  if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1583  {
1584  if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1585  {
1586  idx += delta;
1587 
1588  if( idx > idxmax )
1589  idx = idxmax;
1590  }
1591  else // Must search before this item
1592  {
1593  idx -= delta;
1594 
1595  if( idx < 0 )
1596  idx = 0;
1597  }
1598  }
1599  else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1600  {
1601  idx += delta;
1602 
1603  if( idx > idxmax )
1604  idx = idxmax;
1605  }
1606  else // Must search before this item
1607  {
1608  idx -= delta;
1609 
1610  if( idx < 0 )
1611  idx = 0;
1612  }
1613  }
1614 
1615  return nullptr;
1616 }
1617 
1618 
1624 bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH )
1625 {
1626  if( aLH->GetPosition().x == aRH->GetPosition().x )
1627  return aLH->GetPosition().y < aRH->GetPosition().y;
1628 
1629  return aLH->GetPosition().x < aRH->GetPosition().x;
1630 }
1631 
1632 
1633 void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode ) const
1634 {
1635  for( FOOTPRINT* footprint : Footprints() )
1636  {
1637  for( PAD* pad : footprint->Pads( ) )
1638  {
1639  if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1640  aVector.push_back( pad );
1641  }
1642  }
1643 
1644  std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1645 }
1646 
1647 
1648 void BOARD::PadDelete( PAD* aPad )
1649 {
1650  GetConnectivity()->Remove( aPad );
1651 
1653 
1654  aPad->DeleteStructure();
1655 }
1656 
1657 
1658 std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack ) const
1659 {
1660  int count = 0;
1661  double length = 0.0;
1662  double package_length = 0.0;
1663 
1664  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
1665  auto connectivity = GetBoard()->GetConnectivity();
1667  bool useHeight = GetDesignSettings().m_UseHeightForLengthCalcs;
1668 
1669  for( BOARD_CONNECTED_ITEM* item : connectivity->GetConnectedItems(
1670  static_cast<const BOARD_CONNECTED_ITEM*>( &aTrack ), types ) )
1671  {
1672  count++;
1673 
1674  if( PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item ) )
1675  {
1676  if( track->Type() == PCB_VIA_T && useHeight )
1677  {
1678  PCB_VIA* via = static_cast<PCB_VIA*>( track );
1679  length += stackup.GetLayerDistance( via->TopLayer(), via->BottomLayer() );
1680  continue;
1681  }
1682  else if( track->Type() == PCB_ARC_T )
1683  {
1684  // Note: we don't apply the clip-to-pad optimization if an arc ends in a pad
1685  // Room for future improvement.
1686  length += track->GetLength();
1687  continue;
1688  }
1689 
1690  bool inPad = false;
1691  SEG trackSeg( track->GetStart(), track->GetEnd() );
1692  double segLen = trackSeg.Length();
1693  double segInPadLen = 0;
1694 
1695  for( auto pad_it : connectivity->GetConnectedPads( item ) )
1696  {
1697  PAD* pad = static_cast<PAD*>( pad_it );
1698 
1699  bool hitStart = pad->HitTest( track->GetStart(), track->GetWidth() / 2 );
1700  bool hitEnd = pad->HitTest( track->GetEnd(), track->GetWidth() / 2 );
1701 
1702  if( hitStart && hitEnd )
1703  {
1704  inPad = true;
1705  break;
1706  }
1707  else if( hitStart || hitEnd )
1708  {
1709  VECTOR2I loc;
1710 
1711  // We may not collide even if we passed the bounding-box hit test
1712  if( pad->GetEffectivePolygon()->Collide( trackSeg, 0, nullptr, &loc ) )
1713  {
1714  // Part 1: length of the seg to the intersection with the pad poly
1715  if( hitStart )
1716  trackSeg.A = loc;
1717  else
1718  trackSeg.B = loc;
1719 
1720  segLen = trackSeg.Length();
1721 
1722  // Part 2: length from the intersection to the pad anchor
1723  segInPadLen += ( loc - pad->GetPosition() ).EuclideanNorm();
1724  }
1725  }
1726  }
1727 
1728  if( !inPad )
1729  length += segLen + segInPadLen;
1730  }
1731  else if( PAD* pad = dyn_cast<PAD*>( item ) )
1732  {
1733  package_length += pad->GetPadToDieLength();
1734  }
1735  }
1736 
1737  return std::make_tuple( count, length, package_length );
1738 }
1739 
1740 
1741 FOOTPRINT* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
1742  bool aVisibleOnly, bool aIgnoreLocked ) const
1743 {
1744  FOOTPRINT* footprint = nullptr;
1745  FOOTPRINT* alt_footprint = nullptr;
1746  int min_dim = 0x7FFFFFFF;
1747  int alt_min_dim = 0x7FFFFFFF;
1748  bool current_layer_back = IsBackLayer( aActiveLayer );
1749 
1750  for( FOOTPRINT* candidate : m_footprints )
1751  {
1752  // is the ref point within the footprint's bounds?
1753  if( !candidate->HitTest( aPosition ) )
1754  continue;
1755 
1756  // if caller wants to ignore locked footprints, and this one is locked, skip it.
1757  if( aIgnoreLocked && candidate->IsLocked() )
1758  continue;
1759 
1760  PCB_LAYER_ID layer = candidate->GetLayer();
1761 
1762  // Filter non visible footprints if requested
1763  if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
1764  {
1765  EDA_RECT bb = candidate->GetBoundingBox( false, false );
1766 
1767  int offx = bb.GetX() + bb.GetWidth() / 2;
1768  int offy = bb.GetY() + bb.GetHeight() / 2;
1769 
1770  // off x & offy point to the middle of the box.
1771  int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
1772  ( aPosition.y - offy ) * ( aPosition.y - offy );
1773 
1774  if( current_layer_back == IsBackLayer( layer ) )
1775  {
1776  if( dist <= min_dim )
1777  {
1778  // better footprint shown on the active side
1779  footprint = candidate;
1780  min_dim = dist;
1781  }
1782  }
1783  else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
1784  {
1785  if( dist <= alt_min_dim )
1786  {
1787  // better footprint shown on the other side
1788  alt_footprint = candidate;
1789  alt_min_dim = dist;
1790  }
1791  }
1792  }
1793  }
1794 
1795  if( footprint )
1796  return footprint;
1797 
1798  if( alt_footprint)
1799  return alt_footprint;
1800 
1801  return nullptr;
1802 }
1803 
1804 
1805 std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const
1806 {
1807  std::list<ZONE*> zones;
1808 
1809  for( ZONE* zone : Zones() )
1810  zones.push_back( zone );
1811 
1812  if( aIncludeZonesInFootprints )
1813  {
1814  for( FOOTPRINT* footprint : m_footprints )
1815  {
1816  for( FP_ZONE* zone : footprint->Zones() )
1817  zones.push_back( zone );
1818  }
1819  }
1820 
1821  return zones;
1822 }
1823 
1824 
1825 ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer,
1826  wxPoint aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch )
1827 {
1828  ZONE* new_area = new ZONE( this );
1829 
1830  new_area->SetNetCode( aNetcode );
1831  new_area->SetLayer( aLayer );
1832 
1833  m_zones.push_back( new_area );
1834 
1835  new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
1836 
1837  // Add the first corner to the new zone
1838  new_area->AppendCorner( aStartPointPosition, -1 );
1839 
1840  if( aNewZonesList )
1841  {
1842  ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
1843  aNewZonesList->PushItem( picker );
1844  }
1845 
1846  return new_area;
1847 }
1848 
1849 
1850 bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE* aCurrArea )
1851 {
1852  // mark all areas as unmodified except this one, if modified
1853  for( ZONE* zone : m_zones )
1854  zone->SetLocalFlags( 0 );
1855 
1856  aCurrArea->SetLocalFlags( 1 );
1857 
1858  if( aCurrArea->Outline()->IsSelfIntersecting() )
1859  {
1860  aCurrArea->UnHatchBorder();
1861 
1862  // Normalize copied area and store resulting number of polygons
1863  int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
1864 
1865  // If clipping has created some polygons, we must add these new copper areas.
1866  if( n_poly > 1 )
1867  {
1868  ZONE* NewArea;
1869 
1870  // Move the newly created polygons to new areas, removing them from the current area
1871  for( int ip = 1; ip < n_poly; ip++ )
1872  {
1873  // Create new copper area and copy poly into it
1874  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
1875  NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
1876  wxPoint(0, 0), aCurrArea->GetHatchStyle() );
1877 
1878  // remove the poly that was automatically created for the new area
1879  // and replace it with a poly from NormalizeAreaOutlines
1880  delete NewArea->Outline();
1881  NewArea->SetOutline( new_p );
1882  NewArea->HatchBorder();
1883  NewArea->SetLocalFlags( 1 );
1884  }
1885 
1886  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
1887  delete aCurrArea->Outline();
1888  aCurrArea->SetOutline( new_p );
1889  }
1890  }
1891 
1892  aCurrArea->HatchBorder();
1893 
1894  return true;
1895 }
1896 
1897 
1899  OUTLINE_ERROR_HANDLER* aErrorHandler )
1900 {
1901  int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
1902 
1903  bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
1904  chainingEpsilon, aErrorHandler );
1905 
1906  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
1908 
1909  return success;
1910 }
1911 
1912 
1913 const std::vector<PAD*> BOARD::GetPads() const
1914 {
1915  std::vector<PAD*> allPads;
1916 
1917  for( FOOTPRINT* footprint : Footprints() )
1918  {
1919  for( PAD* pad : footprint->Pads() )
1920  allPads.push_back( pad );
1921  }
1922 
1923  return allPads;
1924 }
1925 
1926 
1927 unsigned BOARD::GetPadCount() const
1928 {
1929  unsigned retval = 0;
1930 
1931  for( FOOTPRINT* footprint : Footprints() )
1932  retval += footprint->Pads().size();
1933 
1934  return retval;
1935 }
1936 
1937 
1938 const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
1939 {
1940  std::vector<BOARD_CONNECTED_ITEM*> items;
1941 
1942  for( PCB_TRACK* track : Tracks() )
1943  items.push_back( track );
1944 
1945  for( FOOTPRINT* footprint : Footprints() )
1946  {
1947  for( PAD* pad : footprint->Pads() )
1948  items.push_back( pad );
1949  }
1950 
1951  for( ZONE* zone : Zones() )
1952  items.push_back( zone );
1953 
1954  return items;
1955 }
1956 
1957 
1959 {
1960  for( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1961  item->SetNetCode( 0 );
1962 }
1963 
1964 
1965 void BOARD::MapNets( const BOARD* aDestBoard )
1966 {
1967  for( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1968  {
1969  NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
1970 
1971  if( netInfo )
1972  item->SetNet( netInfo );
1973  else
1974  item->SetNetCode( 0 );
1975  }
1976 }
1977 
1978 
1980 {
1981  for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1982  {
1983  if( FindNet( item->GetNetCode() ) == nullptr )
1984  item->SetNetCode( NETINFO_LIST::ORPHANED );
1985  }
1986 }
1987 
1988 
1990 {
1991  if( !alg::contains( m_listeners, aListener ) )
1992  m_listeners.push_back( aListener );
1993 }
1994 
1995 
1997 {
1998  auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
1999 
2000  if( i != m_listeners.end() )
2001  {
2002  std::iter_swap( i, m_listeners.end() - 1 );
2003  m_listeners.pop_back();
2004  }
2005 }
2006 
2007 
2009 {
2011 }
2012 
2013 
2014 void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
2015 {
2017 }
2018 
2019 
2021 {
2022  m_highLight.Clear();
2024 
2026 }
2027 
2028 
2029 void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
2030 {
2031  if( !m_highLight.m_netCodes.count( aNetCode ) )
2032  {
2033  if( !aMulti )
2034  m_highLight.m_netCodes.clear();
2035 
2036  m_highLight.m_netCodes.insert( aNetCode );
2038  }
2039 }
2040 
2041 
2042 void BOARD::HighLightON( bool aValue )
2043 {
2044  if( m_highLight.m_highLightOn != aValue )
2045  {
2046  m_highLight.m_highLightOn = aValue;
2048  }
2049 }
2050 
2051 
2052 wxString BOARD::GroupsSanityCheck( bool repair )
2053 {
2054  if( repair )
2055  {
2056  while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
2057  {};
2058 
2059  return wxEmptyString;
2060  }
2061  return GroupsSanityCheckInternal( repair );
2062 }
2063 
2064 
2065 wxString BOARD::GroupsSanityCheckInternal( bool repair )
2066 {
2067  // Cycle detection
2068  //
2069  // Each group has at most one parent group.
2070  // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
2071  // If we ever see a group that we've already marked, that's a cycle.
2072  // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
2073  //
2074  // Algorithm below is linear in the # of groups because each group is visited only once.
2075  // There may be extra time taken due to the container access calls and iterators.
2076  //
2077  // Groups we know are cycle free
2078  std::unordered_set<PCB_GROUP*> knownCycleFreeGroups;
2079  // Groups in the current chain we're exploring.
2080  std::unordered_set<PCB_GROUP*> currentChainGroups;
2081  // Groups we haven't checked yet.
2082  std::unordered_set<PCB_GROUP*> toCheckGroups;
2083 
2084  // Initialize set of groups to check that could participate in a cycle.
2085  for( PCB_GROUP* group : Groups() )
2086  toCheckGroups.insert( group);
2087 
2088  while( !toCheckGroups.empty() )
2089  {
2090  currentChainGroups.clear();
2091  PCB_GROUP* group = *toCheckGroups.begin();
2092 
2093  while( true )
2094  {
2095  if( currentChainGroups.find( group ) != currentChainGroups.end() )
2096  {
2097  if( repair )
2098  Remove( group );
2099 
2100  return "Cycle detected in group membership";
2101  }
2102  else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
2103  {
2104  // Parent is a group we know does not lead to a cycle
2105  break;
2106  }
2107 
2108  currentChainGroups.insert( group );
2109  // We haven't visited currIdx yet, so it must be in toCheckGroups
2110  toCheckGroups.erase( group );
2111 
2112  group = group->GetParentGroup();
2113 
2114  if( !group )
2115  {
2116  // end of chain and no cycles found in this chain
2117  break;
2118  }
2119  }
2120 
2121  // No cycles found in chain, so add it to set of groups we know don't participate
2122  // in a cycle.
2123  knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
2124  }
2125 
2126  // Success
2127  return "";
2128 }
2129 
2130 
2132 {
2133  bool hasGroup = false;
2134  bool hasMember = false;
2135 
2136  for( EDA_ITEM* item : selection )
2137  {
2138  if( item->Type() == PCB_GROUP_T )
2139  hasGroup = true;
2140 
2141  if( item->GetParent() && item->GetParent()->Type() == PCB_GROUP_T )
2142  hasMember = true;
2143  }
2144 
2145  GroupLegalOpsField legalOps;
2146 
2147  legalOps.create = true;
2148  legalOps.removeItems = hasMember;
2149  legalOps.ungroup = hasGroup;
2150  legalOps.enter = hasGroup && selection.Size() == 1;
2151 
2152  return legalOps;
2153 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:148
int Length() const
Return the length (this).
Definition: seg.h:350
void SetParent(JSON_SETTINGS *aParent, bool aLoadFromFile=true)
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:867
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
LSET m_VisibleLayers
Board settings.
void InvokeListeners(Func &&aFunc, Args &&... args)
Definition: board.h:1098
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:1989
virtual void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:168
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1343
void SetNetClasses(NETCLASSES *aNetClasses)
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
void SetEnabledLayers(LSET aMask)
Change the bit-mask of enabled layers to aMask.
virtual std::map< wxString, wxString > & GetTextVars() const
Definition: project.cpp:78
const PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
Definition: board.cpp:338
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:100
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:101
Definition: typeinfo.h:84
KIID niluuid(0)
GroupLegalOpsField GroupLegalOps(const PCB_SELECTION &selection) const
Check which selection tool group operations are legal given the selection.
Definition: board.cpp:2131
std::map< std::pair< BOARD_ITEM *, BOARD_ITEM * >, bool > m_InsideCourtyardCache
Definition: board.h:1083
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
void Merge(const EDA_RECT &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: eda_rect.cpp:432
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Change the visibility of an element category.
Definition: board.cpp:537
Container for project specific data.
Definition: project.h:62
NETCLASSPTR Find(const wxString &aName) const
Search this container for a NETCLASS given by aName.
Definition: netclass.cpp:132
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:268
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1898
ZONES & Zones()
Definition: board.h:239
static const KICAD_T Tracks[]
A scan list for only TRACKs.
Definition: collectors.h:298
static NETINFO_ITEM * OrphanedItem()
Wrapper class, so you can iterate through NETINFO_ITEM*s, not std::pair<int/wxString,...
Definition: netinfo.h:373
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:913
const ZONE_SETTINGS & GetZoneSettings() const override
Fetch the zone settings for this container.
Definition: board.cpp:594
wxString m_name
The canonical name of the layer.
Definition: board.h:108
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition: board.h:272
ZONE * AddArea(PICKED_ITEMS_LIST *aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch)
Add an empty copper area to board areas list.
Definition: board.cpp:1825
Manage layers needed to make a physical board.
const wxString & GetNetclassName(const wxString &aNetName) const
bool sortPadsByXthenYCoord(PAD *const &aLH, PAD *const &aRH)
Used by #GetSortedPadListByXCoord to sort a pad list by X coordinate value.
Definition: board.cpp:1624
void SetCustomDiffPairViaGap(int aGap)
Sets custom via gap for differential pairs (i.e.
void HighLightON(bool aValue=true)
Enable or disable net highlighting.
Definition: board.cpp:2042
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
void SetHatchStyle(ZONE_BORDER_DISPLAY_STYLE aStyle)
Definition: zone.h:611
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
void SetDefaultZoneSettings(const ZONE_SETTINGS &aSettings)
Definition: board.h:72
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition: board.h:259
int GetX() const
Definition: eda_rect.h:98
bool IsLayerEnabled(PCB_LAYER_ID aLayerId) const
Test whether a given layer aLayerId is enabled.
GROUPS & Groups()
The groups must maintain the following invariants.
Definition: board.h:253
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
GROUPS m_groups
Definition: board.h:1115
std::map< wxString, wxString > m_properties
Definition: board.h:1126
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
void SetCustomViaDrill(int aDrill)
Sets custom size for via drill (i.e.
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:102
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:145
~BOARD()
Definition: board.cpp:104
SHAPE_POLY_SET * Outline()
Definition: zone.h:317
MARKERS & Markers()
Definition: board.h:242
Class that computes missing connections on a PCB.
LAYER_T m_type
The type of the layer.
Definition: board.h:110
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
int NormalizeAreaOutlines()
Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s).
int GetWidth() const
Definition: eda_rect.h:109
show footprints on back
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
void DeleteStructure()
Delete this object after removing from its parent if it has one.
Definition: board_item.cpp:127
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
void SetCopperLayerCount(int aCount)
Definition: board.cpp:459
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:479
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
void SetVisibleElements(const GAL_SET &aMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:504
void SetDescription(const wxString &aDesc)
Definition: netclass.h:121
virtual void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:167
functions to convert a shape built with DRAWSEGMENTS to a polygon.
void SetVisibleAlls()
Change the bit-mask of visible element categories and layers.
Definition: board.cpp:514
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
PAD * GetPad(const wxPoint &aPosition, LSET aLayerMask) const
Find a pad aPosition on aLayer.
Definition: board.cpp:1476
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
void SetPosition(const wxPoint &aPos) override
Definition: board.cpp:260
FOOTPRINT * FindFootprintByPath(const KIID_PATH &aPath) const
Search for a FOOTPRINT within this board with the given path.
Definition: board.cpp:1376
virtual void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:171
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:465
LAYER m_layers[PCB_LAYER_ID_COUNT]
Definition: board.h:1118
This is the end of the layers used for visibility bit masks in Pcbnew.
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Change the type of the layer given by aLayer.
Definition: board.cpp:408
HIGH_LIGHT_INFO m_highLight
Definition: board.h:1120
NETINFO_LIST m_NetInfo
Definition: board.h:1146
HIGH_LIGHT_INFO m_highLightPrevious
Definition: board.h:1121
The base class for create windows for drawing purpose.
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:491
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:570
TRACKS m_tracks
Definition: board.h:1114
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:1165
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aBoardItem)
Definition: board.h:166
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
FOOTPRINT * GetFootprint(const wxPoint &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:1741
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:64
void SetCustomViaSize(int aSize)
Set custom size for via diameter (i.e.
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:94
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
std::mutex m_CachesMutex
Definition: board.h:1082
static wxPoint ZeroOffset
A value of wxPoint(0,0) which can be passed to the Draw() functions.
Definition: board_item.h:150
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
PAD * GetPadFast(const wxPoint &aPosition, LSET aLayerMask) const
Return pad found at aPosition on aLayerMask using the fast search method.
Definition: board.cpp:1506
virtual void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:172
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:151
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:702
static const char * ShowType(LAYER_T aType)
Convert a LAYER_T enum to a string representation of the layer type.
Definition: board.cpp:425
Definition: board.h:73
Classes used in Pcbnew, CvPcb and GerbView.
void AppendNet(NETINFO_ITEM *aNewElement)
Add aNewElement to the end of the net list.
show footprints on front
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const 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:1199
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false) const
Definition: board.cpp:1805
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1409
unsigned GetNodesCount(int aNet=-1) const
Definition: board.cpp:1081
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: board.cpp:606
Definition: kiid.h:44
std::vector< PCB_MARKER * > ResolveDRCExclusions()
Rebuild DRC markers from the serialized data in BOARD_DESIGN_SETTINGS.
Definition: board.cpp:206
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
Definition: project_file.h:166
BOARD_STACKUP & GetStackupDescriptor()
PCB_LAYER_ID
A quick note on layer IDs:
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition: board.cpp:1938
void RemoveNet(NETINFO_ITEM *aNet)
Remove a net from the net list.
LSET is a set of PCB_LAYER_IDs.
void ResetNetHighLight()
Reset all high light data to the init state.
Definition: board.cpp:2020
A container for NETCLASS instances.
Definition: netclass.h:218
void SetExcluded(bool aExcluded)
Definition: marker_base.h:95
NETCLASSES m_NetClasses
Definition: net_settings.h:40
ENDPOINT_T
Definition: pcb_track.h:52
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
bool NormalizeAreaPolygon(PICKED_ITEMS_LIST *aNewZonesList, ZONE *aCurrArea)
Process an area that has been modified, by normalizing its polygon against itself.
Definition: board.cpp:1850
wxString GroupsSanityCheckInternal(bool repair)
Definition: board.cpp:2065
std::function< SEARCH_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:69
void RemoveListener(BOARD_LISTENER *aListener)
Remove the specified listener.
Definition: board.cpp:1996
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:826
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:125
ZONES m_zones
Definition: board.h:1116
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:927
virtual void Move(const wxPoint &aMoveVector)
Move this object.
Definition: board_item.h:272
Represent a set of closed polygons.
unsigned GetPadCount() const
Definition: board.cpp:1927
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:497
SHAPE_LINE_CHAIN & Outline(int aIndex)
static DELETED_BOARD_ITEM * GetInstance()
Definition: board_item.h:387
GAL_SET GetVisibleElements() const
Return a set of all the element categories that are visible.
Definition: board.cpp:525
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: zone.cpp:218
Use all material properties from model file.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler)
Extracts the board outlines and build a closed polygon from lines, arcs and circle items on edge cut ...
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
Definition: board.cpp:1913
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: zone.h:320
FOOTPRINTS & Footprints()
Definition: board.h:233
bool m_highLightOn
Definition: board.h:138
virtual void OnBoardNetSettingsChanged(BOARD &aBoard)
Definition: board.h:170
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:46
void SetNetCode(int aNetCode)
Definition: netinfo.h:114
unsigned GetUnconnectedNetCount() const
Definition: board.cpp:1098
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:51
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition: board.cpp:376
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:344
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
Definition: board.cpp:326
BOARD_USE
Flags to specify how the board is being used.
Definition: board.h:180
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:1402
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:2014
Helper for storing and iterating over GAL_LAYER_IDs.
static PCB_MARKER * Deserialize(const wxString &data)
Definition: pcb_marker.cpp:75
std::vector< wxString > GetNetClassAssignmentCandidates() const
Return a list of name candidates for netclass assignment.
Definition: board.cpp:1388
#define STRUCT_DELETED
flag indication structures to be erased
#define _(s)
NET_SETTINGS stores various net-related settings in a project context.
Definition: net_settings.h:32
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
NETCLASSES & GetNetClasses() const
bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:50
static LSET AllLayersMask()
Definition: lset.cpp:787
void Simplify(POLYGON_MODE aFastMode)
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
wxString m_userName
The user defined name of the layer.
Definition: board.h:109
class ZONE, a copper pour area
Definition: typeinfo.h:105
void BuildConnectivity()
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition: board.cpp:136
MARKERS m_markers
Definition: board.h:1111
ZONE_BORDER_DISPLAY_STYLE GetHatchStyle() const
Definition: zone.h:610
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:2029
void SetCustomDiffPairGap(int aGap)
Sets custom gap for differential pairs (i.e.
A holder to handle information on schematic or board items.
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:1144
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
Definition: board.cpp:438
DRAWINGS m_drawings
Definition: board.h:1112
void IncrementTimeStamp()
Definition: board.cpp:191
int SetAreasNetCodesFromNetNames()
Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetN...
Definition: board.cpp:1442
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: board.cpp:820
void SetCustomTrackWidth(int aWidth)
Sets custom width for track (i.e.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition: kicad_algo.h:98
int GetHeight() const
Definition: eda_rect.h:110
void ClearProject()
Definition: board.cpp:172
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
static const int ORPHANED
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:369
int LAYER_NUM
This can be replaced with int and removed.
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:155
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
TRACKS TracksInNet(int aNetCode)
Collect all the TRACKs and VIAs that are members of a net given by aNetCode.
Definition: board.cpp:304
const KIID m_Uuid
Definition: eda_item.h:475
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:531
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
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:696
Definition: seg.h:40
EDA_UNITS
Definition: eda_units.h:38
void SetProject(PROJECT *aProject)
Link a board to a given project.
Definition: board.cpp:142
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Return the type of the copper layer given by aLayer.
Definition: board.cpp:394
void Move(const wxPoint &aMoveVector) override
Move this object.
Definition: board.cpp:266
std::set< int > m_netCodes
Definition: board.h:137
void SetLocalFlags(int aFlags)
Definition: zone.h:303
Handle the data for a net.
Definition: netinfo.h:64
void MapNets(const BOARD *aDestBoard)
Map all nets in the given board to nets with the same name (if any) in the destination board.
Definition: board.cpp:1965
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:471
bool m_UseHeightForLengthCalcs
Enable inclusion of stackup height in track length measurements and length tuning.
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition: zone.cpp:836
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
bool m_Printing
wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
Definition: pgm_base.h:289
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition: board.h:173
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:541
see class PGM_BASE
void PadDelete(PAD *aPad)
Delete a given pad from the BOARD by removing it from its footprint and from the m_NetInfo.
Definition: board.cpp:1648
SHAPE_POLY_SET UnitSet(int aPolygonIndex)
Return the reference to aHole-th hole in the aIndex-th outline.
int m_fileFormatVersionAtLoad
Definition: board.h:1123
wxPoint GetPosition() const override
Definition: pad.h:174
Container to hold information pertinent to a layer of a BOARD.
Definition: board.h:81
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
wxPoint GetPosition() const override
Definition: board.cpp:254
BOARD()
Definition: board.cpp:62
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:169
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource) const
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:982
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:107
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:1633
int GetCopperLayerCount() const
Definition: board.cpp:453
void SanitizeNetcodes()
Definition: board.cpp:1979
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: board.h:1127
class ZONE, managed by a footprint
Definition: typeinfo.h:94
Handle the component boundary box.
Definition: eda_rect.h:42
NETCLASS * GetDefault() const
void SetZoneSettings(const ZONE_SETTINGS &aSettings) override
Set the zone settings for this container.
Definition: board.cpp:600
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: pcb_track.h:117
int GetY() const
Definition: eda_rect.h:99
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:2008
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
void Remove(BOARD_ITEM *aBoardItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: board.cpp:708
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const wxPoint &pt)> OUTLINE_ERROR_HANDLER
wxString GetClass() const override
Return the class name.
Definition: board.h:803
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1104
std::map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTrees
Definition: board.h:1088
unsigned GetNetCount() const
Definition: netinfo.h:339
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
wxString ConvertKIIDsToCrossReferences(const wxString &aSource) const
Definition: board.cpp:1036
NETCLASSPTR GetDefault() const
Definition: netclass.h:253
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
Definition: board.cpp:2052
ZONE_BORDER_DISPLAY_STYLE
Zone border styles.
Definition: zone_settings.h:46
FOOTPRINTS m_footprints
Definition: board.h:1113
void DeleteAllFootprints()
Remove all footprints from the deque and free the memory associated with them.
Definition: board.cpp:858
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:103
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: zone.cpp:238
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
ZONE_SETTINGS & GetDefaultZoneSettings()
Abstract interface for BOARD_ITEMs capable of storing other items inside.
std::map< std::pair< BOARD_ITEM *, BOARD_ITEM * >, bool > m_InsideBCourtyardCache
Definition: board.h:1085
Definition: pad.h:57
NETINFO_ITEM * GetNetItem(int aNetCode) const
void ClearEditFlags()
Definition: eda_item.h:172
SEARCH_RESULT
Definition: eda_item.h:41
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: board.cpp:238
LAYER_T
The allowed types of layers, same as Specctra DSN spec.
Definition: board.h:68
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:74
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
static constexpr int Millimeter2iu(double mm)
std::map< std::pair< BOARD_ITEM *, BOARD_ITEM * >, bool > m_InsideAreaCache
Definition: board.h:1086
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
static const int UNCONNECTED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:365
DRAWINGS & Drawings()
Definition: board.h:236
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:946
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:264
void ClearAllNetCodes()
Reset all items' netcodes to 0 (no net).
Definition: board.cpp:1958
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:905
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:485
std::vector< BOARD_LISTENER * > m_listeners
Definition: board.h:1148
A specialization of ZONE for use in footprints.
Definition: zone.h:943
TRACKS & Tracks()
Definition: board.h:230
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
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:1658
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition: board.cpp:1364
PROJECT * m_project
Definition: board.h:1132
int m_timeStamp
Definition: board.h:1108
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition: board.h:605
void Clear()
Definition: board.h:140
Container for design settings for a BOARD object.
bool IsSelfIntersecting() const
Check whether any of the polygons in the set is self intersecting.
std::map< std::pair< BOARD_ITEM *, BOARD_ITEM * >, bool > m_InsideFCourtyardCache
Definition: board.h:1084
int GetNetCode() const
Definition: netinfo.h:113
GAL_SET m_LegacyVisibleItems
Definition: board.h:265