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