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