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 
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
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.
162 
163  // Now update the DesignSettings' netclass pointer to point into the project.
165  }
166 }
167 
168 
170 {
171  if( !m_project )
172  return;
173 
174  PROJECT_FILE& project = m_project->GetProjectFile();
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, NULL, 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 = (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, NULL, 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 == NULL )
566  {
567  wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem NULL" ) );
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' NULL.
668  wxASSERT( aBoardItem );
669 
670  switch( aBoardItem->Type() )
671  {
672  case PCB_NETINFO_T:
673  {
674  NETINFO_ITEM* item = (NETINFO_ITEM*) aBoardItem;
675  m_NetInfo.RemoveNet( item );
676  break;
677  }
678 
679  case PCB_MARKER_T:
680  m_markers.erase( std::remove_if( m_markers.begin(), m_markers.end(),
681  [aBoardItem]( BOARD_ITEM* aItem )
682  {
683  return aItem == aBoardItem;
684  } ) );
685  break;
686 
687  case PCB_GROUP_T:
688  m_groups.erase( std::remove_if( m_groups.begin(), m_groups.end(),
689  [aBoardItem]( BOARD_ITEM* aItem )
690  {
691  return aItem == aBoardItem;
692  } ) );
693  break;
694 
695  case PCB_ZONE_T:
696  m_zones.erase( std::remove_if( m_zones.begin(), m_zones.end(),
697  [aBoardItem]( BOARD_ITEM* aItem )
698  {
699  return aItem == aBoardItem;
700  } ) );
701  break;
702 
703  case PCB_FOOTPRINT_T:
704  m_footprints.erase( std::remove_if( m_footprints.begin(), m_footprints.end(),
705  [aBoardItem]( BOARD_ITEM* aItem )
706  {
707  return aItem == aBoardItem;
708  } ) );
709  break;
710 
711  case PCB_TRACE_T:
712  case PCB_ARC_T:
713  case PCB_VIA_T:
714  m_tracks.erase( std::remove_if( m_tracks.begin(), m_tracks.end(),
715  [aBoardItem]( BOARD_ITEM* aItem )
716  {
717  return aItem == aBoardItem;
718  } ) );
719  break;
720 
721  case PCB_DIM_ALIGNED_T:
722  case PCB_DIM_CENTER_T:
724  case PCB_DIM_LEADER_T:
725  case PCB_SHAPE_T:
726  case PCB_TEXT_T:
727  case PCB_TARGET_T:
728  m_drawings.erase( std::remove_if( m_drawings.begin(), m_drawings.end(),
729  [aBoardItem](BOARD_ITEM* aItem)
730  {
731  return aItem == aBoardItem;
732  } ) );
733  break;
734 
735  // other types may use linked list
736  default:
737  wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
738  }
739 
740  aBoardItem->SetFlags( STRUCT_DELETED );
741 
742  PCB_GROUP* parentGroup = aBoardItem->GetParentGroup();
743 
744  if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
745  parentGroup->RemoveItem( aBoardItem );
746 
747  m_connectivity->Remove( aBoardItem );
748 
749  if( aRemoveMode != REMOVE_MODE::BULK )
751 }
752 
753 
754 wxString BOARD::GetSelectMenuText( EDA_UNITS aUnits ) const
755 {
756  return wxString::Format( _( "PCB" ) );
757 }
758 
759 
761 {
762  // the vector does not know how to delete the PCB_MARKER, it holds pointers
763  for( PCB_MARKER* marker : m_markers )
764  delete marker;
765 
766  m_markers.clear();
767 }
768 
769 
770 void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions )
771 {
772  // Deleting lots of items from a vector can be very slow. Copy remaining items instead.
773  MARKERS remaining;
774 
775  for( PCB_MARKER* marker : m_markers )
776  {
777  if( ( marker->IsExcluded() && aExclusions )
778  || ( !marker->IsExcluded() && aWarningsAndErrors ) )
779  {
780  delete marker;
781  }
782  else
783  {
784  remaining.push_back( marker );
785  }
786  }
787 
788  m_markers = remaining;
789 }
790 
791 
792 BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const
793 {
794  if( aID == niluuid )
795  return nullptr;
796 
797  for( TRACK* track : Tracks() )
798  {
799  if( track->m_Uuid == aID )
800  return track;
801  }
802 
803  for( FOOTPRINT* footprint : Footprints() )
804  {
805  if( footprint->m_Uuid == aID )
806  return footprint;
807 
808  for( PAD* pad : footprint->Pads() )
809  {
810  if( pad->m_Uuid == aID )
811  return pad;
812  }
813 
814  if( footprint->Reference().m_Uuid == aID )
815  return &footprint->Reference();
816 
817  if( footprint->Value().m_Uuid == aID )
818  return &footprint->Value();
819 
820  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
821  {
822  if( drawing->m_Uuid == aID )
823  return drawing;
824  }
825 
826  for( BOARD_ITEM* zone : footprint->Zones() )
827  {
828  if( zone->m_Uuid == aID )
829  return zone;
830  }
831 
832  for( PCB_GROUP* group : footprint->Groups() )
833  {
834  if( group->m_Uuid == aID )
835  return group;
836  }
837  }
838 
839  for( ZONE* zone : Zones() )
840  {
841  if( zone->m_Uuid == aID )
842  return zone;
843  }
844 
845  for( BOARD_ITEM* drawing : Drawings() )
846  {
847  if( drawing->m_Uuid == aID )
848  return drawing;
849  }
850 
851  for( PCB_MARKER* marker : m_markers )
852  {
853  if( marker->m_Uuid == aID )
854  return marker;
855  }
856 
857  for( PCB_GROUP* group : m_groups )
858  {
859  if( group->m_Uuid == aID )
860  return group;
861  }
862 
863  if( m_Uuid == aID )
864  return const_cast<BOARD*>( this );
865 
866  // Not found; weak reference has been deleted.
868 }
869 
870 
871 void BOARD::FillItemMap( std::map<KIID, EDA_ITEM*>& aMap )
872 {
873  // the board itself
874  aMap[ m_Uuid ] = this;
875 
876  for( TRACK* track : Tracks() )
877  aMap[ track->m_Uuid ] = track;
878 
879  for( FOOTPRINT* footprint : Footprints() )
880  {
881  aMap[ footprint->m_Uuid ] = footprint;
882 
883  for( PAD* pad : footprint->Pads() )
884  aMap[ pad->m_Uuid ] = pad;
885 
886  aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference();
887  aMap[ footprint->Value().m_Uuid ] = &footprint->Value();
888 
889  for( BOARD_ITEM* drawing : footprint->GraphicalItems() )
890  aMap[ drawing->m_Uuid ] = drawing;
891  }
892 
893  for( ZONE* zone : Zones() )
894  aMap[ zone->m_Uuid ] = zone;
895 
896  for( BOARD_ITEM* drawing : Drawings() )
897  aMap[ drawing->m_Uuid ] = drawing;
898 
899  for( PCB_MARKER* marker : m_markers )
900  aMap[ marker->m_Uuid ] = marker;
901 
902  for( PCB_GROUP* group : m_groups )
903  aMap[ group->m_Uuid ] = group;
904 }
905 
906 
907 wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource )
908 {
909  wxString newbuf;
910  size_t sourceLen = aSource.length();
911 
912  for( size_t i = 0; i < sourceLen; ++i )
913  {
914  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
915  {
916  wxString token;
917  bool isCrossRef = false;
918 
919  for( i = i + 2; i < sourceLen; ++i )
920  {
921  if( aSource[i] == '}' )
922  break;
923 
924  if( aSource[i] == ':' )
925  isCrossRef = true;
926 
927  token.append( aSource[i] );
928  }
929 
930  if( isCrossRef )
931  {
932  wxString remainder;
933  wxString ref = token.BeforeFirst( ':', &remainder );
934 
935  for( FOOTPRINT* footprint : Footprints() )
936  {
937  if( footprint->GetReference().CmpNoCase( ref ) == 0 )
938  {
939  wxString test( remainder );
940 
941  if( footprint->ResolveTextVar( &test ) )
942  token = footprint->m_Uuid.AsString() + ":" + remainder;
943 
944  break;
945  }
946  }
947  }
948 
949  newbuf.append( "${" + token + "}" );
950  }
951  else
952  {
953  newbuf.append( aSource[i] );
954  }
955  }
956 
957  return newbuf;
958 }
959 
960 
961 wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource )
962 {
963  wxString newbuf;
964  size_t sourceLen = aSource.length();
965 
966  for( size_t i = 0; i < sourceLen; ++i )
967  {
968  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
969  {
970  wxString token;
971  bool isCrossRef = false;
972 
973  for( i = i + 2; i < sourceLen; ++i )
974  {
975  if( aSource[i] == '}' )
976  break;
977 
978  if( aSource[i] == ':' )
979  isCrossRef = true;
980 
981  token.append( aSource[i] );
982  }
983 
984  if( isCrossRef )
985  {
986  wxString remainder;
987  wxString ref = token.BeforeFirst( ':', &remainder );
988  BOARD_ITEM* refItem = GetItem( KIID( ref ) );
989 
990  if( refItem && refItem->Type() == PCB_FOOTPRINT_T )
991  token = static_cast<FOOTPRINT*>( refItem )->GetReference() + ":" + remainder;
992  }
993 
994  newbuf.append( "${" + token + "}" );
995  }
996  else
997  {
998  newbuf.append( aSource[i] );
999  }
1000  }
1001 
1002  return newbuf;
1003 }
1004 
1005 
1006 unsigned BOARD::GetNodesCount( int aNet ) const
1007 {
1008  unsigned retval = 0;
1009 
1010  for( FOOTPRINT* footprint : Footprints() )
1011  {
1012  for( PAD* pad : footprint->Pads() )
1013  {
1014  if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1015  retval++;
1016  }
1017  }
1018 
1019  return retval;
1020 }
1021 
1022 
1024 {
1025  return m_connectivity->GetUnconnectedCount();
1026 }
1027 
1028 
1029 EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1030 {
1031  EDA_RECT area;
1032  LSET visible = GetVisibleLayers();
1033  bool showInvisibleText = IsElementVisible( LAYER_MOD_TEXT_INVISIBLE )
1034  && PgmOrNull() && !PgmOrNull()->m_Printing;
1035 
1036  if( aBoardEdgesOnly )
1037  visible.set( Edge_Cuts );
1038 
1039  // Check shapes, dimensions, texts, and fiducials
1040  for( BOARD_ITEM* item : m_drawings )
1041  {
1042  if( aBoardEdgesOnly && ( item->GetLayer() != Edge_Cuts || item->Type() != PCB_SHAPE_T ) )
1043  continue;
1044 
1045  if( ( item->GetLayerSet() & visible ).any() )
1046  area.Merge( item->GetBoundingBox() );
1047  }
1048 
1049  // Check footprints
1050  for( FOOTPRINT* footprint : m_footprints )
1051  {
1052  if( !( footprint->GetLayerSet() & visible ).any() )
1053  continue;
1054 
1055  if( aBoardEdgesOnly )
1056  {
1057  for( const BOARD_ITEM* edge : footprint->GraphicalItems() )
1058  {
1059  if( edge->GetLayer() == Edge_Cuts && edge->Type() == PCB_FP_SHAPE_T )
1060  area.Merge( edge->GetBoundingBox() );
1061  }
1062  }
1063  else
1064  {
1065  area.Merge( footprint->GetBoundingBox( true, showInvisibleText ) );
1066  }
1067  }
1068 
1069  if( !aBoardEdgesOnly )
1070  {
1071  // Check tracks
1072  for( TRACK* track : m_tracks )
1073  {
1074  if( ( track->GetLayerSet() & visible ).any() )
1075  area.Merge( track->GetBoundingBox() );
1076  }
1077 
1078  // Check zones
1079  for( ZONE* aZone : m_zones )
1080  {
1081  if( ( aZone->GetLayerSet() & visible ).any() )
1082  area.Merge( aZone->GetBoundingBox() );
1083  }
1084  }
1085 
1086  return area;
1087 }
1088 
1089 
1090 void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1091 {
1092  wxString txt;
1093  int viasCount = 0;
1094  int trackSegmentsCount = 0;
1095 
1096  for( TRACK* item : m_tracks )
1097  {
1098  if( item->Type() == PCB_VIA_T )
1099  viasCount++;
1100  else
1101  trackSegmentsCount++;
1102  }
1103 
1104  txt.Printf( wxT( "%d" ), GetPadCount() );
1105  aList.emplace_back( _( "Pads" ), txt );
1106 
1107  txt.Printf( wxT( "%d" ), viasCount );
1108  aList.emplace_back( _( "Vias" ), txt );
1109 
1110  txt.Printf( wxT( "%d" ), trackSegmentsCount );
1111  aList.emplace_back( _( "Track Segments" ), txt );
1112 
1113  txt.Printf( wxT( "%d" ), GetNodesCount() );
1114  aList.emplace_back( _( "Nodes" ), txt );
1115 
1116  txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() - 1 /* Don't include "No Net" in count */ );
1117  aList.emplace_back( _( "Nets" ), txt );
1118 
1119  txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
1120  aList.emplace_back( _( "Unrouted" ), txt );
1121 }
1122 
1123 
1124 SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1125 {
1126  KICAD_T stype;
1128  const KICAD_T* p = scanTypes;
1129  bool done = false;
1130 
1131 #if 0 && defined(DEBUG)
1132  std::cout << GetClass().mb_str() << ' ';
1133 #endif
1134 
1135  while( !done )
1136  {
1137  stype = *p;
1138 
1139  switch( stype )
1140  {
1141  case PCB_T:
1142  result = inspector( this, testData ); // inspect me
1143  // skip over any types handled in the above call.
1144  ++p;
1145  break;
1146 
1147  /*
1148  * Instances of the requested KICAD_T live in a list, either one that I manage, or one
1149  * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply
1150  * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ).
1151  */
1152 
1153  case PCB_FOOTPRINT_T:
1154  case PCB_PAD_T:
1155  case PCB_FP_TEXT_T:
1156  case PCB_FP_SHAPE_T:
1157  case PCB_FP_ZONE_T:
1158 
1159  // this calls FOOTPRINT::Visit() on each footprint.
1160  result = IterateForward<FOOTPRINT*>( m_footprints, inspector, testData, p );
1161 
1162  // skip over any types handled in the above call.
1163  for( ; ; )
1164  {
1165  switch( stype = *++p )
1166  {
1167  case PCB_FOOTPRINT_T:
1168  case PCB_PAD_T:
1169  case PCB_FP_TEXT_T:
1170  case PCB_FP_SHAPE_T:
1171  case PCB_FP_ZONE_T:
1172  continue;
1173 
1174  default:
1175  ;
1176  }
1177 
1178  break;
1179  }
1180 
1181  break;
1182 
1183  case PCB_SHAPE_T:
1184  case PCB_TEXT_T:
1185  case PCB_DIM_ALIGNED_T:
1186  case PCB_DIM_CENTER_T:
1187  case PCB_DIM_ORTHOGONAL_T:
1188  case PCB_DIM_LEADER_T:
1189  case PCB_TARGET_T:
1190  result = IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, p );
1191 
1192  // skip over any types handled in the above call.
1193  for( ; ; )
1194  {
1195  switch( stype = *++p )
1196  {
1197  case PCB_SHAPE_T:
1198  case PCB_TEXT_T:
1199  case PCB_DIM_ALIGNED_T:
1200  case PCB_DIM_CENTER_T:
1201  case PCB_DIM_ORTHOGONAL_T:
1202  case PCB_DIM_LEADER_T:
1203  case PCB_TARGET_T:
1204  continue;
1205 
1206  default:
1207  ;
1208  }
1209 
1210  break;
1211  }
1212 
1213  break;
1214 
1215  case PCB_VIA_T:
1216  result = IterateForward<TRACK*>( m_tracks, inspector, testData, p );
1217  ++p;
1218  break;
1219 
1220  case PCB_TRACE_T:
1221  case PCB_ARC_T:
1222  result = IterateForward<TRACK*>( m_tracks, inspector, testData, p );
1223  ++p;
1224  break;
1225 
1226  case PCB_MARKER_T:
1227  for( PCB_MARKER* marker : m_markers )
1228  {
1229  result = marker->Visit( inspector, testData, p );
1230 
1231  if( result == SEARCH_RESULT::QUIT )
1232  break;
1233  }
1234 
1235  ++p;
1236  break;
1237 
1238  case PCB_ZONE_T:
1239  for( ZONE* zone : m_zones)
1240  {
1241  result = zone->Visit( inspector, testData, p );
1242 
1243  if( result == SEARCH_RESULT::QUIT )
1244  break;
1245  }
1246 
1247  ++p;
1248  break;
1249 
1250  case PCB_GROUP_T:
1251  result = IterateForward<PCB_GROUP*>( m_groups, inspector, testData, p );
1252  ++p;
1253  break;
1254 
1255  default: // catch EOT or ANY OTHER type here and return.
1256  done = true;
1257  break;
1258  }
1259 
1260  if( result == SEARCH_RESULT::QUIT )
1261  break;
1262  }
1263 
1264  return result;
1265 }
1266 
1267 
1268 NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1269 {
1270  // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1271  // zero is reserved for "no connection" and is not actually a net.
1272  // NULL is returned for non valid netcodes
1273 
1274  wxASSERT( m_NetInfo.GetNetCount() > 0 );
1275 
1276  if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1277  return NETINFO_LIST::OrphanedItem();
1278  else
1279  return m_NetInfo.GetNetItem( aNetcode );
1280 }
1281 
1282 
1283 NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1284 {
1285  return m_NetInfo.GetNetItem( aNetname );
1286 }
1287 
1288 
1289 FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
1290 {
1291  for( FOOTPRINT* footprint : m_footprints )
1292  {
1293  if( aReference == footprint->GetReference() )
1294  return footprint;
1295  }
1296 
1297  return nullptr;
1298 }
1299 
1300 
1302 {
1303  for( FOOTPRINT* footprint : m_footprints )
1304  {
1305  if( footprint->GetPath() == aPath )
1306  return footprint;
1307  }
1308 
1309  return nullptr;
1310 }
1311 
1312 
1313 // The pad count for each netcode, stored in a buffer for a fast access.
1314 // This is needed by the sort function sortNetsByNodes()
1315 static std::vector<int> padCountListByNet;
1316 
1317 
1318 // Sort nets by decreasing pad count.
1319 // For same pad count, sort by alphabetic names
1320 static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1321 {
1322  int countA = padCountListByNet[ a->GetNetCode() ];
1323  int countB = padCountListByNet[ b->GetNetCode() ];
1324 
1325  if( countA == countB )
1326  return a->GetNetname() < b->GetNetname();
1327  else
1328  return countB < countA;
1329 }
1330 
1331 
1332 // Sort nets by alphabetic names
1333 static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1334 {
1335  return a->GetNetname() < b->GetNetname();
1336 }
1337 
1338 
1339 int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
1340 {
1341  if( m_NetInfo.GetNetCount() == 0 )
1342  return 0;
1343 
1344  // Build the list
1345  std::vector <NETINFO_ITEM*> netBuffer;
1346 
1347  netBuffer.reserve( m_NetInfo.GetNetCount() );
1348  int max_netcode = 0;
1349 
1350  for( NETINFO_ITEM* net : m_NetInfo )
1351  {
1352  int netcode = net->GetNetCode();
1353 
1354  if( netcode > 0 && net->IsCurrent() )
1355  {
1356  netBuffer.push_back( net );
1357  max_netcode = std::max( netcode, max_netcode);
1358  }
1359  }
1360 
1361  // sort the list
1362  if( aSortbyPadsCount )
1363  {
1364  // Build the pad count by net:
1365  padCountListByNet.clear();
1366  std::vector<PAD*> pads = GetPads();
1367 
1368  padCountListByNet.assign( max_netcode + 1, 0 );
1369 
1370  for( PAD* pad : pads )
1371  {
1372  int netCode = pad->GetNetCode();
1373 
1374  if( netCode >= 0 )
1375  padCountListByNet[ netCode ]++;
1376  }
1377 
1378  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNodes );
1379  }
1380  else
1381  {
1382  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNames );
1383  }
1384 
1385  for( NETINFO_ITEM* net : netBuffer )
1386  aNames.Add( UnescapeString( net->GetNetname() ) );
1387 
1388  return netBuffer.size();
1389 }
1390 
1391 
1393 {
1394  std::vector<wxString> names;
1395 
1396  for( NETINFO_ITEM* net : m_NetInfo )
1397  {
1398  if( !net->GetNetname().IsEmpty() )
1399  names.emplace_back( net->GetNetname() );
1400  }
1401 
1402  return names;
1403 }
1404 
1405 
1407 {
1408  if( m_project )
1410 }
1411 
1412 
1414 {
1415  if( !m_project )
1416  return;
1417 
1418  NET_SETTINGS* netSettings = m_project->GetProjectFile().m_NetSettings.get();
1419  NETCLASSES& netClasses = netSettings->m_NetClasses;
1420  NETCLASSPTR defaultNetClass = netClasses.GetDefault();
1421 
1422  for( NETINFO_ITEM* net : m_NetInfo )
1423  {
1424  const wxString& netname = net->GetNetname();
1425  const wxString& netclassName = netSettings->GetNetclassName( netname );
1426 
1427  net->SetNetClass( netClasses.Find( netclassName ) );
1428  }
1429 
1431 
1432  // Set initial values for custom track width & via size to match the default
1433  // netclass settings
1434  bds.UseCustomTrackViaSize( false );
1435  bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
1436  bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
1437  bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
1438  bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
1439  bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
1440  bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
1441 
1443 }
1444 
1445 
1447 {
1448  int error_count = 0;
1449 
1450  for( ZONE* zone : Zones() )
1451  {
1452  if( !zone->IsOnCopperLayer() )
1453  {
1454  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
1455  continue;
1456  }
1457 
1458  if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1459  {
1460  const NETINFO_ITEM* net = zone->GetNet();
1461 
1462  if( net )
1463  {
1464  zone->SetNetCode( net->GetNetCode() );
1465  }
1466  else
1467  {
1468  error_count++;
1469 
1470  // keep Net Name and set m_NetCode to -1 : error flag.
1471  zone->SetNetCode( -1 );
1472  }
1473  }
1474  }
1475 
1476  return error_count;
1477 }
1478 
1479 
1480 PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet )
1481 {
1482  if( !aLayerSet.any() )
1483  aLayerSet = LSET::AllCuMask();
1484 
1485  for( FOOTPRINT* footprint : m_footprints )
1486  {
1487  PAD* pad = NULL;
1488 
1489  if( footprint->HitTest( aPosition ) )
1490  pad = footprint->GetPad( aPosition, aLayerSet );
1491 
1492  if( pad )
1493  return pad;
1494  }
1495 
1496  return NULL;
1497 }
1498 
1499 
1500 PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
1501 {
1502  const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
1503 
1504  LSET lset( aTrace->GetLayer() );
1505 
1506  return GetPad( aPosition, lset );
1507 }
1508 
1509 
1510 PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
1511 {
1512  for( FOOTPRINT* footprint : Footprints() )
1513  {
1514  for( PAD* pad : footprint->Pads() )
1515  {
1516  if( pad->GetPosition() != aPosition )
1517  continue;
1518 
1519  // Pad found, it must be on the correct layer
1520  if( ( pad->GetLayerSet() & aLayerSet ).any() )
1521  return pad;
1522  }
1523  }
1524 
1525  return nullptr;
1526 }
1527 
1528 
1529 PAD* BOARD::GetPad( std::vector<PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet )
1530 {
1531  // Search aPadList for aPosition
1532  // aPadList is sorted by X then Y values, and a fast binary search is used
1533  int idxmax = aPadList.size()-1;
1534 
1535  int delta = aPadList.size();
1536 
1537  int idx = 0; // Starting index is the beginning of list
1538 
1539  while( delta )
1540  {
1541  // Calculate half size of remaining interval to test.
1542  // Ensure the computed value is not truncated (too small)
1543  if( (delta & 1) && ( delta > 1 ) )
1544  delta++;
1545 
1546  delta /= 2;
1547 
1548  PAD* pad = aPadList[idx];
1549 
1550  if( pad->GetPosition() == aPosition ) // candidate found
1551  {
1552  // The pad must match the layer mask:
1553  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1554  return pad;
1555 
1556  // More than one pad can be at aPosition
1557  // search for a pad at aPosition that matched this mask
1558 
1559  // search next
1560  for( int ii = idx+1; ii <= idxmax; ii++ )
1561  {
1562  pad = aPadList[ii];
1563 
1564  if( pad->GetPosition() != aPosition )
1565  break;
1566 
1567  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1568  return pad;
1569  }
1570  // search previous
1571  for( int ii = idx-1 ;ii >=0; ii-- )
1572  {
1573  pad = aPadList[ii];
1574 
1575  if( pad->GetPosition() != aPosition )
1576  break;
1577 
1578  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1579  return pad;
1580  }
1581 
1582  // Not found:
1583  return 0;
1584  }
1585 
1586  if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1587  {
1588  if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1589  {
1590  idx += delta;
1591 
1592  if( idx > idxmax )
1593  idx = idxmax;
1594  }
1595  else // Must search before this item
1596  {
1597  idx -= delta;
1598 
1599  if( idx < 0 )
1600  idx = 0;
1601  }
1602  }
1603  else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1604  {
1605  idx += delta;
1606 
1607  if( idx > idxmax )
1608  idx = idxmax;
1609  }
1610  else // Must search before this item
1611  {
1612  idx -= delta;
1613 
1614  if( idx < 0 )
1615  idx = 0;
1616  }
1617  }
1618 
1619  return NULL;
1620 }
1621 
1622 
1628 bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH )
1629 {
1630  if( aLH->GetPosition().x == aRH->GetPosition().x )
1631  return aLH->GetPosition().y < aRH->GetPosition().y;
1632 
1633  return aLH->GetPosition().x < aRH->GetPosition().x;
1634 }
1635 
1636 
1637 void BOARD::GetSortedPadListByXthenYCoord( std::vector<PAD*>& aVector, int aNetCode )
1638 {
1639  for( FOOTPRINT* footprint : Footprints() )
1640  {
1641  for( PAD* pad : footprint->Pads( ) )
1642  {
1643  if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1644  aVector.push_back( pad );
1645  }
1646  }
1647 
1648  std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1649 }
1650 
1651 
1652 void BOARD::PadDelete( PAD* aPad )
1653 {
1654  GetConnectivity()->Remove( aPad );
1655 
1657 
1658  aPad->DeleteStructure();
1659 }
1660 
1661 
1662 std::tuple<int, double, double> BOARD::GetTrackLength( const TRACK& aTrack ) const
1663 {
1664  int count = 0;
1665  double length = 0.0;
1666  double package_length = 0.0;
1667 
1668  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
1669  auto connectivity = GetBoard()->GetConnectivity();
1670 
1671  for( BOARD_CONNECTED_ITEM* item : connectivity->GetConnectedItems(
1672  static_cast<const BOARD_CONNECTED_ITEM*>( &aTrack ), types ) )
1673  {
1674  count++;
1675 
1676  if( TRACK* track = dyn_cast<TRACK*>( item ) )
1677  {
1678  bool inPad = false;
1679 
1680  for( auto pad_it : connectivity->GetConnectedPads( item ) )
1681  {
1682  PAD* pad = static_cast<PAD*>( pad_it );
1683 
1684  if( pad->HitTest( track->GetStart(), track->GetWidth() / 2 )
1685  && pad->HitTest( track->GetEnd(), track->GetWidth() / 2 ) )
1686  {
1687  inPad = true;
1688  break;
1689  }
1690  }
1691 
1692  if( !inPad )
1693  length += track->GetLength();
1694  }
1695  else if( PAD* pad = dyn_cast<PAD*>( item ) )
1696  {
1697  package_length += pad->GetPadToDieLength();
1698  }
1699  }
1700 
1701  return std::make_tuple( count, length, package_length );
1702 }
1703 
1704 
1705 FOOTPRINT* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
1706  bool aVisibleOnly, bool aIgnoreLocked )
1707 {
1708  FOOTPRINT* footprint = NULL;
1709  FOOTPRINT* alt_footprint = NULL;
1710  int min_dim = 0x7FFFFFFF;
1711  int alt_min_dim = 0x7FFFFFFF;
1712  bool current_layer_back = IsBackLayer( aActiveLayer );
1713 
1714  for( FOOTPRINT* candidate : m_footprints )
1715  {
1716  // is the ref point within the footprint's bounds?
1717  if( !candidate->HitTest( aPosition ) )
1718  continue;
1719 
1720  // if caller wants to ignore locked footprints, and this one is locked, skip it.
1721  if( aIgnoreLocked && candidate->IsLocked() )
1722  continue;
1723 
1724  PCB_LAYER_ID layer = candidate->GetLayer();
1725 
1726  // Filter non visible footprints if requested
1727  if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
1728  {
1729  EDA_RECT bb = candidate->GetBoundingBox( false, false );
1730 
1731  int offx = bb.GetX() + bb.GetWidth() / 2;
1732  int offy = bb.GetY() + bb.GetHeight() / 2;
1733 
1734  // off x & offy point to the middle of the box.
1735  int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
1736  ( aPosition.y - offy ) * ( aPosition.y - offy );
1737 
1738  if( current_layer_back == IsBackLayer( layer ) )
1739  {
1740  if( dist <= min_dim )
1741  {
1742  // better footprint shown on the active side
1743  footprint = candidate;
1744  min_dim = dist;
1745  }
1746  }
1747  else if( aVisibleOnly && IsFootprintLayerVisible( layer ) )
1748  {
1749  if( dist <= alt_min_dim )
1750  {
1751  // better footprint shown on the other side
1752  alt_footprint = candidate;
1753  alt_min_dim = dist;
1754  }
1755  }
1756  }
1757  }
1758 
1759  if( footprint )
1760  return footprint;
1761 
1762  if( alt_footprint)
1763  return alt_footprint;
1764 
1765  return NULL;
1766 }
1767 
1768 
1769 std::list<ZONE*> BOARD::GetZoneList( bool aIncludeZonesInFootprints )
1770 {
1771  std::list<ZONE*> zones;
1772 
1773  for( ZONE* zone : Zones() )
1774  zones.push_back( zone );
1775 
1776  if( aIncludeZonesInFootprints )
1777  {
1778  for( FOOTPRINT* footprint : m_footprints )
1779  {
1780  for( FP_ZONE* zone : footprint->Zones() )
1781  zones.push_back( zone );
1782  }
1783  }
1784 
1785  return zones;
1786 }
1787 
1788 
1789 ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer,
1790  wxPoint aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch )
1791 {
1792  ZONE* new_area = new ZONE( this );
1793 
1794  new_area->SetNetCode( aNetcode );
1795  new_area->SetLayer( aLayer );
1796 
1797  m_zones.push_back( new_area );
1798 
1799  new_area->SetHatchStyle( (ZONE_BORDER_DISPLAY_STYLE) aHatch );
1800 
1801  // Add the first corner to the new zone
1802  new_area->AppendCorner( aStartPointPosition, -1 );
1803 
1804  if( aNewZonesList )
1805  {
1806  ITEM_PICKER picker( nullptr, new_area, UNDO_REDO::NEWITEM );
1807  aNewZonesList->PushItem( picker );
1808  }
1809 
1810  return new_area;
1811 }
1812 
1813 
1814 bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE* aCurrArea )
1815 {
1816  // mark all areas as unmodified except this one, if modified
1817  for( ZONE* zone : m_zones )
1818  zone->SetLocalFlags( 0 );
1819 
1820  aCurrArea->SetLocalFlags( 1 );
1821 
1822  if( aCurrArea->Outline()->IsSelfIntersecting() )
1823  {
1824  aCurrArea->UnHatchBorder();
1825 
1826  // Normalize copied area and store resulting number of polygons
1827  int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
1828 
1829  // If clipping has created some polygons, we must add these new copper areas.
1830  if( n_poly > 1 )
1831  {
1832  ZONE* NewArea;
1833 
1834  // Move the newly created polygons to new areas, removing them from the current area
1835  for( int ip = 1; ip < n_poly; ip++ )
1836  {
1837  // Create new copper area and copy poly into it
1838  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
1839  NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
1840  wxPoint(0, 0), aCurrArea->GetHatchStyle() );
1841 
1842  // remove the poly that was automatically created for the new area
1843  // and replace it with a poly from NormalizeAreaOutlines
1844  delete NewArea->Outline();
1845  NewArea->SetOutline( new_p );
1846  NewArea->HatchBorder();
1847  NewArea->SetLocalFlags( 1 );
1848  }
1849 
1850  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
1851  delete aCurrArea->Outline();
1852  aCurrArea->SetOutline( new_p );
1853  }
1854  }
1855 
1856  aCurrArea->HatchBorder();
1857 
1858  return true;
1859 }
1860 
1861 
1863  OUTLINE_ERROR_HANDLER* aErrorHandler )
1864 {
1865  int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
1866 
1867  bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
1868  chainingEpsilon, aErrorHandler );
1869 
1870  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
1872 
1873  return success;
1874 }
1875 
1876 
1877 const std::vector<PAD*> BOARD::GetPads() const
1878 {
1879  std::vector<PAD*> allPads;
1880 
1881  for( FOOTPRINT* footprint : Footprints() )
1882  {
1883  for( PAD* pad : footprint->Pads() )
1884  allPads.push_back( pad );
1885  }
1886 
1887  return allPads;
1888 }
1889 
1890 
1891 unsigned BOARD::GetPadCount() const
1892 {
1893  unsigned retval = 0;
1894 
1895  for( FOOTPRINT* footprint : Footprints() )
1896  retval += footprint->Pads().size();
1897 
1898  return retval;
1899 }
1900 
1901 
1902 const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
1903 {
1904  std::vector<BOARD_CONNECTED_ITEM*> items;
1905 
1906  for( TRACK* track : Tracks() )
1907  items.push_back( track );
1908 
1909  for( FOOTPRINT* footprint : Footprints() )
1910  {
1911  for( PAD* pad : footprint->Pads() )
1912  items.push_back( pad );
1913  }
1914 
1915  for( ZONE* zone : Zones() )
1916  items.push_back( zone );
1917 
1918  return items;
1919 }
1920 
1921 
1923 {
1924  for( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1925  item->SetNetCode( 0 );
1926 }
1927 
1928 
1929 void BOARD::MapNets( const BOARD* aDestBoard )
1930 {
1931  for( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1932  {
1933  NETINFO_ITEM* netInfo = aDestBoard->FindNet( item->GetNetname() );
1934 
1935  if( netInfo )
1936  item->SetNet( netInfo );
1937  else
1938  item->SetNetCode( 0 );
1939  }
1940 }
1941 
1942 
1944 {
1945  for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() )
1946  {
1947  if( FindNet( item->GetNetCode() ) == nullptr )
1948  item->SetNetCode( NETINFO_LIST::ORPHANED );
1949  }
1950 }
1951 
1952 
1954 {
1955  if( !alg::contains( m_listeners, aListener ) )
1956  m_listeners.push_back( aListener );
1957 }
1958 
1959 
1961 {
1962  auto i = std::find( m_listeners.begin(), m_listeners.end(), aListener );
1963 
1964  if( i != m_listeners.end() )
1965  {
1966  std::iter_swap( i, m_listeners.end() - 1 );
1967  m_listeners.pop_back();
1968  }
1969 }
1970 
1971 
1973 {
1975 }
1976 
1977 
1978 void BOARD::OnItemsChanged( std::vector<BOARD_ITEM*>& aItems )
1979 {
1981 }
1982 
1983 
1985 {
1986  m_highLight.Clear();
1988 
1990 }
1991 
1992 
1993 void BOARD::SetHighLightNet( int aNetCode, bool aMulti )
1994 {
1995  if( !m_highLight.m_netCodes.count( aNetCode ) )
1996  {
1997  if( !aMulti )
1998  m_highLight.m_netCodes.clear();
1999 
2000  m_highLight.m_netCodes.insert( aNetCode );
2002  }
2003 }
2004 
2005 
2006 void BOARD::HighLightON( bool aValue )
2007 {
2008  if( m_highLight.m_highLightOn != aValue )
2009  {
2010  m_highLight.m_highLightOn = aValue;
2012  }
2013 }
2014 
2015 
2016 wxString BOARD::GroupsSanityCheck( bool repair )
2017 {
2018  if( repair )
2019  {
2020  while( GroupsSanityCheckInternal( repair ) != wxEmptyString )
2021  {};
2022 
2023  return wxEmptyString;
2024  }
2025  return GroupsSanityCheckInternal( repair );
2026 }
2027 
2028 
2029 wxString BOARD::GroupsSanityCheckInternal( bool repair )
2030 {
2031  // Cycle detection
2032  //
2033  // Each group has at most one parent group.
2034  // So we start at group 0 and traverse the parent chain, marking groups seen along the way.
2035  // If we ever see a group that we've already marked, that's a cycle.
2036  // If we reach the end of the chain, we know all groups in that chain are not part of any cycle.
2037  //
2038  // Algorithm below is linear in the # of groups because each group is visited only once.
2039  // There may be extra time taken due to the container access calls and iterators.
2040  //
2041  // Groups we know are cycle free
2042  std::unordered_set<PCB_GROUP*> knownCycleFreeGroups;
2043  // Groups in the current chain we're exploring.
2044  std::unordered_set<PCB_GROUP*> currentChainGroups;
2045  // Groups we haven't checked yet.
2046  std::unordered_set<PCB_GROUP*> toCheckGroups;
2047 
2048  // Initialize set of groups to check that could participate in a cycle.
2049  for( PCB_GROUP* group : Groups() )
2050  toCheckGroups.insert( group);
2051 
2052  while( !toCheckGroups.empty() )
2053  {
2054  currentChainGroups.clear();
2055  PCB_GROUP* group = *toCheckGroups.begin();
2056 
2057  while( true )
2058  {
2059  if( currentChainGroups.find( group ) != currentChainGroups.end() )
2060  {
2061  if( repair )
2062  Remove( group );
2063 
2064  return "Cycle detected in group membership";
2065  }
2066  else if( knownCycleFreeGroups.find( group ) != knownCycleFreeGroups.end() )
2067  {
2068  // Parent is a group we know does not lead to a cycle
2069  break;
2070  }
2071 
2072  currentChainGroups.insert( group );
2073  // We haven't visited currIdx yet, so it must be in toCheckGroups
2074  toCheckGroups.erase( group );
2075 
2076  group = group->GetParentGroup();
2077 
2078  if( !group )
2079  {
2080  // end of chain and no cycles found in this chain
2081  break;
2082  }
2083  }
2084 
2085  // No cycles found in chain, so add it to set of groups we know don't participate
2086  // in a cycle.
2087  knownCycleFreeGroups.insert( currentChainGroups.begin(), currentChainGroups.end() );
2088  }
2089 
2090  // Success
2091  return "";
2092 }
2093 
2094 
2096 {
2097  bool hasGroup = false;
2098  bool hasMember = false;
2099 
2100  for( EDA_ITEM* item : selection )
2101  {
2102  if( item->Type() == PCB_GROUP_T )
2103  hasGroup = true;
2104 
2105  if( item->GetParent() && item->GetParent()->Type() == PCB_GROUP_T )
2106  hasMember = true;
2107  }
2108 
2109  GroupLegalOpsField legalOps;
2110 
2111  legalOps.create = true;
2112  legalOps.removeItems = hasMember;
2113  legalOps.ungroup = hasGroup;
2114  legalOps.enter = hasGroup && selection.Size() == 1;
2115 
2116  return legalOps;
2117 }
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:792
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:1953
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:1268
PAD * GetPad(const wxPoint &aPosition, LSET aLayerMask)
Find a pad aPosition on aLayer.
Definition: board.cpp:1480
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
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:1320
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:2095
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:338
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:1862
ZONES & Zones()
Definition: board.h:309
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()
Function UnHatchBorder clears the zone's hatch.
Definition: zone.cpp:909
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:342
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:1789
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:1628
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:2006
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:621
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:329
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:323
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:1315
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:323
MARKERS & Markers()
Definition: board.h:312
Class that computes missing connections on a PCB.
LAYER_T m_type
The type of the layer.
Definition: board.h:105
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is contained within or on the bounding box of an item.
Definition: pcbnew/pad.cpp:947
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
NET_SETTINGS & NetSettings()
Definition: project_file.h:92
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:591
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.
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:1301
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.
wxString ConvertKIIDsToCrossReferences(const wxString &aSource)
Definition: board.cpp:961
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:513
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:1090
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
PROJECT_FILE is the backing store for a PROJECT, in JSON format.
Definition: project_file.h:62
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
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:165
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
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
FOOTPRINT * GetFootprint(const wxPoint &aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly, bool aIgnoreLocked=false)
Get a footprint by its bounding rectangle at aPosition on aLayer.
Definition: board.cpp:1705
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:1124
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1413
unsigned GetNodesCount(int aNet=-1) const
Definition: board.cpp:1006
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) NOTE: If we go multi-board in the future,...
Definition: project_file.h:175
PCB_LAYER_ID
A quick note on layer IDs:
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
Definition: board.cpp:1902
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:1984
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:202
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:1814
#define NULL
wxString GroupsSanityCheckInternal(bool repair)
Definition: board.cpp:2029
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:1960
void DeleteMARKERs()
Delete all MARKERS from the board.
Definition: board.cpp:760
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()
Function HatchBorder computes the hatch lines depending on the hatch parameters and stores it in the ...
Definition: zone.cpp:923
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:1891
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:215
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:1877
PAD * GetPadFast(const wxPoint &aPosition, LSET aLayerMask)
Return pad found at aPosition on aLayerMask using the fast search method.
Definition: board.cpp:1510
void SetCustomDiffPairWidth(int aWidth)
Sets custom track width for differential pairs (i.e.
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: zone.h:326
FOOTPRINTS & Footprints()
Definition: board.h:303
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:1023
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:414
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:1406
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:1978
Helper for storing and iterating over GAL_LAYER_IDs.
int SortedNetnamesList(wxArrayString &aNames, bool aSortbyPadsCount)
Definition: board.cpp:1339
const wxString & GetNetname() const
Definition: netinfo.h:119
static PCB_MARKER * Deserialize(const wxString &data)
Definition: pcb_marker.cpp:74
void GetSortedPadListByXthenYCoord(std::vector< PAD * > &aVector, int aNetCode=-1)
First empties then fills the vector with all pads and sorts them by increasing x coordinate,...
Definition: board.cpp:1637
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)
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:360
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:115
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:620
void SetHighLightNet(int aNetCode, bool aMulti=false)
Select the netcode to be highlighted.
Definition: board.cpp:1993
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:1446
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:754
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:524
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
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:309
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:1929
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:832
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:331
BOARD_DESIGN_SETTINGS * m_BoardSettings
Board design settings for this project's board.
Definition: project_file.h:167
virtual void OnBoardHighlightNetChanged(BOARD &aBoard)
Definition: board.h:167
TITLE_BLOCK & GetTitleBlock()
Definition: board.h:612
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:1652
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:150
virtual void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aBoardItem)
Definition: board.h:163
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:107
int GetCopperLayerCount() const
Definition: board.cpp:435
void SanitizeNetcodes()
Definition: board.cpp:1943
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:1972
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
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:880
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
Definition: board.cpp:1029
unsigned GetNetCount() const
Definition: netinfo.h:339
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
NETCLASSPTR GetDefault() const
Definition: netclass.h:253
wxString GroupsSanityCheck(bool repair=false)
Definition: board.cpp:2016
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:235
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.
std::list< ZONE * > GetZoneList(bool aIncludeZonesInFootprints=false)
Definition: board.cpp:1769
bool IsFootprintLayerVisible(PCB_LAYER_ID aLayer)
Expect either of the two layers on which a footprint can reside, and returns whether that layer is vi...
Definition: board.cpp:546
Definition: pad.h:60
NETINFO_ITEM * GetNetItem(int aNetCode) const
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
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:1662
void ClearEditFlags()
Definition: eda_item.h:221
SEARCH_RESULT
Definition: eda_item.h:40
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:204
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:1333
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
std::vector< wxString > GetNetClassAssignmentCandidates()
Return a list of name candidates for netclass assignment.
Definition: board.cpp:1392
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:306
void FillItemMap(std::map< KIID, EDA_ITEM * > &aMap)
Definition: board.cpp:871
wxString ConvertCrossReferencesToKIIDs(const wxString &aSource)
Convert cross-references back and forth between ${refDes:field} and ${kiid:field}.
Definition: board.cpp:907
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:334
void ClearAllNetCodes()
Reset all items' netcodes to 0 (no net).
Definition: board.cpp:1922
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
FP_ZONE is a specialization of ZONE for use in footprints.
Definition: zone.h:965
TRACKS & Tracks()
Definition: board.h:300
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:1289
PROJECT * m_project
Definition: board.h:220
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Return an "English Standard" name of a PCB layer when given aLayerNumber.
Definition: board.h:674
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:335