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