KiCad PCB EDA Suite
class_board.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
10  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
11  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
12  *
13  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, you may find one here:
27  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
28  * or you may search the http://www.gnu.org website for the version 2 license,
29  * or you may write to the Free Software Foundation, Inc.,
30  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
31  */
32 
33 #include <limits.h>
34 #include <algorithm>
35 #include <iterator>
36 
37 #include <fctsys.h>
38 #include <common.h>
39 #include <kicad_string.h>
40 #include <pcb_base_frame.h>
41 #include <msgpanel.h>
42 #include <pcb_netlist.h>
43 #include <reporter.h>
44 #include <base_units.h>
45 #include <ratsnest_data.h>
46 #include <ratsnest_viewitem.h>
47 #include <worksheet_viewitem.h>
48 
49 #include <pcbnew.h>
50 #include <collectors.h>
51 
52 #include <class_board.h>
53 #include <class_module.h>
54 #include <class_track.h>
55 #include <class_zone.h>
56 #include <class_marker_pcb.h>
57 #include <class_drawsegment.h>
58 #include <class_pcb_text.h>
59 #include <class_pcb_target.h>
60 #include <class_dimension.h>
62 
63 
69 {
70 public:
72  BOARD_ITEM( nullptr, NOT_USED )
73  {}
74 
75  wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override
76  {
77  return _( "(Deleted Item)" );
78  }
79 
80  wxString GetClass() const override
81  {
82  return wxT( "DELETED_BOARD_ITEM" );
83  }
84 
85  // pure virtuals:
86  const wxPoint GetPosition() const override { return wxPoint(); }
87  void SetPosition( const wxPoint& ) override {}
88  void Draw( EDA_DRAW_PANEL* , wxDC* , GR_DRAWMODE , const wxPoint& ) override {}
89 
90 #if defined(DEBUG)
91  void Show( int , std::ostream& ) const override {}
92 #endif
93 };
94 
96 
97 
98 /* This is an odd place for this, but CvPcb won't link if it is
99  * in class_board_item.cpp like I first tried it.
100  */
101 wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
102 
103 // this is a dummy colors settings (defined colors are the vdefulat values)
104 // used to initialize the board.
105 // these settings will be overriden later, depending on the draw frame that displays the board.
106 // However, when a board is created by a python script, outside a frame, the colors must be set
107 // so dummyColorsSettings provide this default initialization
109 
112  m_paper( PAGE_INFO::A4 ), m_NetInfo( this )
113 {
114  // we have not loaded a board yet, assume latest until then.
115  m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
116 
118  m_Status_Pcb = 0; // Status word: bit 1 = calculate.
119  m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
120  // zone contour currently in progress
121 
122  BuildListOfNets(); // prepare pad and netlist containers.
123 
124  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
125  {
126  m_Layer[layer].m_name = GetStandardLayerName( ToLAYER_ID( layer ) );
127 
128  if( IsCopperLayer( layer ) )
129  m_Layer[layer].m_type = LT_SIGNAL;
130  else
131  m_Layer[layer].m_type = LT_UNDEFINED;
132  }
133 
134  // Initialize default netclass.
135  NETCLASSPTR defaultClass = m_designSettings.GetDefault();
136  defaultClass->SetDescription( _( "This is the default net class." ) );
137  m_designSettings.SetCurrentNetClass( defaultClass->GetName() );
138 
139  // Set sensible initial values for custom track width & via size
144 
145  // Initialize ratsnest
146  m_connectivity.reset( new CONNECTIVITY_DATA() );
147 }
148 
149 
151 {
152  while( m_ZoneDescriptorList.size() )
153  {
154  ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
155  Delete( area_to_remove );
156  }
157 
158  DeleteMARKERs();
160 
161  delete m_CurrentZoneContour;
162  m_CurrentZoneContour = NULL;
163 }
164 
165 
167 {
168  GetConnectivity()->Build( this );
169 }
170 
171 
172 const wxPoint BOARD::GetPosition() const
173 {
174  return ZeroOffset;
175 }
176 
177 
178 void BOARD::SetPosition( const wxPoint& aPos )
179 {
180  wxLogWarning( wxT( "This should not be called on the BOARD object") );
181 }
182 
183 
184 void BOARD::Move( const wxPoint& aMoveVector ) // overload
185 {
186  // @todo : anything like this elsewhere? maybe put into GENERAL_COLLECTOR class.
187  static const KICAD_T top_level_board_stuff[] = {
188  PCB_MARKER_T,
189  PCB_TEXT_T,
190  PCB_LINE_T,
192  PCB_TARGET_T,
193  PCB_VIA_T,
194  PCB_TRACE_T,
195  // PCB_PAD_T, Can't be at board level
196  // PCB_MODULE_TEXT_T, Can't be at board level
197  PCB_MODULE_T,
199  EOT
200  };
201 
202  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
203  {
204  BOARD_ITEM* brd_item = (BOARD_ITEM*) item;
205 
206  // aMoveVector was snapshotted, don't need "data".
207  brd_item->Move( aMoveVector );
208 
209  return SEARCH_CONTINUE;
210  };
211 
212  Visit( inspector, NULL, top_level_board_stuff );
213 }
214 
215 
216 TRACKS BOARD::TracksInNet( int aNetCode )
217 {
218  TRACKS ret;
219 
220  INSPECTOR_FUNC inspector = [aNetCode,&ret] ( EDA_ITEM* item, void* testData )
221  {
222  TRACK* t = (TRACK*) item;
223 
224  if( t->GetNetCode() == aNetCode )
225  ret.push_back( t );
226 
227  return SEARCH_CONTINUE;
228  };
229 
230  // visit this BOARD's TRACKs and VIAs with above TRACK INSPECTOR which
231  // appends all in aNetCode to ret.
232  Visit( inspector, NULL, GENERAL_COLLECTOR::Tracks );
233 
234  return ret;
235 }
236 
237 
242 static void removeTrack( TRACKS* aList, TRACK* aOneToRemove )
243 {
244  aList->erase( std::remove( aList->begin(), aList->end(), aOneToRemove ), aList->end() );
245 }
246 
247 
248 static void otherEnd( const TRACK& aTrack, const wxPoint& aNotThisEnd, wxPoint* aOtherEnd )
249 {
250  if( aTrack.GetStart() == aNotThisEnd )
251  {
252  *aOtherEnd = aTrack.GetEnd();
253  }
254  else
255  {
256  wxASSERT( aTrack.GetEnd() == aNotThisEnd );
257  *aOtherEnd = aTrack.GetStart();
258  }
259 }
260 
261 
266 static int find_vias_and_tracks_at( TRACKS& at_next, TRACKS& in_net, LSET& lset, const wxPoint& next )
267 {
268  // first find all vias (in this net) at 'next' location, and expand LSET with each
269  for( TRACKS::iterator it = in_net.begin(); it != in_net.end(); )
270  {
271  TRACK* t = *it;
272 
273  if( t->Type() == PCB_VIA_T && (t->GetLayerSet() & lset).any() &&
274  ( t->GetStart() == next || t->GetEnd() == next ) )
275  {
276  lset |= t->GetLayerSet();
277  at_next.push_back( t );
278  it = in_net.erase( it );
279  }
280  else
281  ++it;
282  }
283 
284  int track_count = 0;
285 
286  // with expanded lset, find all tracks with an end on any of the layers in lset
287  for( TRACKS::iterator it = in_net.begin(); it != in_net.end(); /* iterates in the loop body */ )
288  {
289  TRACK* t = *it;
290 
291  if( ( t->GetLayerSet() & lset ).any() && ( t->GetStart() == next || t->GetEnd() == next ) )
292  {
293  at_next.push_back( t );
294  it = in_net.erase( it );
295  ++track_count;
296  }
297  else
298  {
299  ++it;
300  }
301  }
302 
303  return track_count;
304 }
305 
306 
318 static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTracksInNet,
319  const wxPoint& aGoal, const wxPoint& aStart, TRACK* aFirstTrack )
320 {
321  TRACKS in_net = aTracksInNet; // copy source list so the copy can be modified
322  wxPoint next;
323 
324  otherEnd( *aFirstTrack, aStart, &next );
325 
326  aList->push_back( aFirstTrack );
327  removeTrack( &in_net, aFirstTrack );
328 
329  LSET lset( aFirstTrack->GetLayer() );
330 
331  while( in_net.size() )
332  {
333  if( next == aGoal )
334  return; // success
335 
336  // Want an exact match on the position of next, i.e. pad at next,
337  // not a forgiving HitTest() with tolerance type of match, otherwise the overall
338  // algorithm will not work. GetPadFast() is an exact match as I write this.
339  if( aBoard->GetPadFast( next, lset ) )
340  {
341  std::string m = StrPrintf(
342  "intervening pad at:(xy %s) between start:(xy %s) and goal:(xy %s)",
343  FormatInternalUnits( next ).c_str(),
344  FormatInternalUnits( aStart ).c_str(),
345  FormatInternalUnits( aGoal ).c_str()
346  );
347  THROW_IO_ERROR( m );
348  }
349 
350  int track_count = find_vias_and_tracks_at( *aList, in_net, lset, next );
351 
352  if( track_count != 1 )
353  {
354  std::string m = StrPrintf(
355  "found %d tracks intersecting at (xy %s), exactly 2 would be acceptable.",
356  track_count + aList->size() == 1 ? 1 : 0,
357  FormatInternalUnits( next ).c_str()
358  );
359  THROW_IO_ERROR( m );
360  }
361 
362  // reduce lset down to the layer that the last track at 'next' is on.
363  lset = aList->back()->GetLayerSet();
364 
365  otherEnd( *aList->back(), next, &next );
366  }
367 
368  std::string m = StrPrintf(
369  "not enough tracks connecting start:(xy %s) and goal:(xy %s).",
370  FormatInternalUnits( aStart ).c_str(),
371  FormatInternalUnits( aGoal ).c_str()
372  );
373  THROW_IO_ERROR( m );
374 }
375 
376 
377 TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aGoalPos, int aNetCode )
378 {
379  TRACKS in_between_pts;
380  TRACKS on_start_point;
381  TRACKS in_net = TracksInNet( aNetCode ); // a small subset of TRACKs and VIAs
382 
383  for( auto t : in_net )
384  {
385  if( t->Type() == PCB_TRACE_T && ( t->GetStart() == aStartPos || t->GetEnd() == aStartPos ) )
386  on_start_point.push_back( t );
387  }
388 
389  wxString per_path_problem_text;
390 
391  for( auto t : on_start_point ) // explore each trace (path) leaving aStartPos
392  {
393  // checkConnectedTo() fills in_between_pts on every attempt. For failures
394  // this set needs to be cleared.
395  in_between_pts.clear();
396 
397  try
398  {
399  checkConnectedTo( this, &in_between_pts, in_net, aGoalPos, aStartPos, t );
400  }
401  catch( const IO_ERROR& ioe ) // means not connected
402  {
403  per_path_problem_text += "\n\t";
404  per_path_problem_text += ioe.Problem();
405  continue; // keep trying, there may be other paths leaving from aStartPos
406  }
407 
408  // success, no exception means a valid connection,
409  // return this set of TRACKS without throwing.
410  return in_between_pts;
411  }
412 
413  wxString m = wxString::Format(
414  "no clean path connecting start:(xy %s) with goal:(xy %s)",
415  FormatInternalUnits( aStartPos ).c_str(),
416  FormatInternalUnits( aGoalPos ).c_str()
417  );
418 
419  THROW_IO_ERROR( m + per_path_problem_text );
420 }
421 
422 
423 void BOARD::chainMarkedSegments( TRACK* aTrackList, wxPoint aPosition,
424  const LSET& aLayerSet, TRACKS* aList )
425 {
426  LSET layer_set = aLayerSet;
427 
428  if( !aTrackList ) // no tracks at all in board
429  return;
430 
431  D_PAD* pad = NULL;
432  double distanceToPadCenter = std::numeric_limits<double>::max();
433 
434  /* Set the BUSY flag of all connected segments, first search starting at
435  * aPosition. The search ends when a pad is found (end of a track), a
436  * segment end has more than one other segment end connected, or when no
437  * connected item found.
438  *
439  * Vias are a special case because they can connect segments
440  * on other layers and they change the layer mask. They can be a track
441  * end or not. They will be analyzed later, and vias on terminal points
442  * of the track will be considered as part of this track if they do not
443  * connect segments on a other track together and will be considered as
444  * part of a other track when removing the via, the segments of that other
445  * track are disconnected.
446  */
447  for( ; ; )
448  {
449  if( !pad )
450  pad = GetPad( aPosition, layer_set );
451 
452  if( pad )
453  distanceToPadCenter = GetLineLength( aPosition, pad->GetCenter() );
454 
455  /* Test for a via: a via changes the layer mask and can connect a lot
456  * of segments at location aPosition. When found, the via is just
457  * pushed in list. Vias will be examined later, when all connected
458  * segment are found and push in list. This is because when a via
459  * is found we do not know at this time the number of connected items
460  * and we do not know if this via is on the track or finish the track
461  */
462  TRACK* via = aTrackList->GetVia( NULL, aPosition, layer_set );
463 
464  if( via )
465  {
466  layer_set = via->GetLayerSet();
467  aList->push_back( via );
468  }
469 
470  int seg_count = 0;
471  TRACK* candidate = NULL;
472 
473  /* Search all segments connected to point aPosition.
474  * if only 1 segment at aPosition: then this segment is "candidate"
475  * if > 1 segment:
476  * then end of "track" (because more than 2 segments are connected at aPosition)
477  */
478  TRACK* segment = aTrackList;
479 
480  while( ( segment = ::GetTrack( segment, NULL, aPosition, layer_set ) ) != NULL )
481  {
482  if( segment->GetState( BUSY ) ) // already found and selected: skip it
483  {
484  segment = segment->Next();
485  continue;
486  }
487 
488  if( segment == via ) // just previously found: skip it
489  {
490  segment = segment->Next();
491  continue;
492  }
493 
494  if( ++seg_count == 1 ) // if first connected item: then segment is candidate
495  {
496  candidate = segment;
497  segment = segment->Next();
498  }
499  else // More than 1 segment connected -> location is end of track
500  {
501  return;
502  }
503  }
504 
505  if( candidate ) // A candidate is found: flag it and push it in list
506  {
507  /* Initialize parameters to search items connected to this
508  * candidate:
509  * we must analyze connections to its other end
510  */
511  if( aPosition == candidate->GetStart() )
512  {
513  aPosition = candidate->GetEnd();
514  }
515  else
516  {
517  aPosition = candidate->GetStart();
518  }
519 
520  /* If we are in a pad, only candidates approaching the pad center
521  * are accepted.
522  */
523  if( pad )
524  {
525  if( GetPad( aPosition, layer_set ) != pad )
526  return;
527 
528  if( GetLineLength( aPosition, pad->GetCenter() ) > distanceToPadCenter )
529  return;
530  }
531 
532  layer_set = candidate->GetLayerSet();
533 
534  // flag this item and push it in list of selected items
535  aList->push_back( candidate );
536  candidate->SetState( BUSY, true );
537  }
538  else
539  {
540  return;
541  }
542  }
543 }
544 
545 
547 {
549 }
550 
551 
553 {
556 }
557 
558 
559 bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
560 {
561  if( unsigned( aIndex ) < arrayDim( m_Layer ) )
562  {
563  m_Layer[ aIndex ] = aLayer;
564  return true;
565  }
566 
567  return false;
568 }
569 
570 #include <stdio.h>
571 
572 const PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
573 {
574 
575  // Look for the BOARD specific copper layer names
576  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
577  {
578  if ( IsCopperLayer( layer ) && ( m_Layer[ layer ].m_name == aLayerName ) )
579  {
580  return ToLAYER_ID( layer );
581  }
582  }
583 
584  // Otherwise fall back to the system standard layer names
585  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
586  {
587  if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
588  {
589  return ToLAYER_ID( layer );
590  }
591  }
592 
593  return UNDEFINED_LAYER;
594 }
595 
596 const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
597 {
598  // All layer names are stored in the BOARD.
599  if( IsLayerEnabled( aLayer ) )
600  {
601  // Standard names were set in BOARD::BOARD() but they may be
602  // over-ridden by BOARD::SetLayerName().
603  // For copper layers, return the actual copper layer name,
604  // otherwise return the Standard English layer name.
605  if( IsCopperLayer( aLayer ) )
606  return m_Layer[aLayer].m_name;
607  }
608 
609  return GetStandardLayerName( aLayer );
610 }
611 
612 bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
613 {
614  if( !IsCopperLayer( aLayer ) )
615  return false;
616 
617  if( aLayerName == wxEmptyString )
618  return false;
619 
620  // no quote chars in the name allowed
621  if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
622  return false;
623 
624  wxString nameTemp = aLayerName;
625 
626  // replace any spaces with underscores before we do any comparing
627  nameTemp.Replace( wxT( " " ), wxT( "_" ) );
628 
629  if( IsLayerEnabled( aLayer ) )
630  {
631 #if 0
632  for( LAYER_NUM i = FIRST_COPPER_LAYER; i < NB_COPPER_LAYERS; ++i )
633  {
634  if( i != aLayer && IsLayerEnabled( i ) && nameTemp == m_Layer[i].m_Name )
635  return false;
636  }
637 #else
638  for( LSEQ cu = GetEnabledLayers().CuStack(); cu; ++cu )
639  {
640  PCB_LAYER_ID id = *cu;
641 
642  // veto changing the name if it exists elsewhere.
643  if( id != aLayer && nameTemp == m_Layer[id].m_name )
644 // if( id != aLayer && nameTemp == wxString( m_Layer[id].m_name ) )
645  return false;
646  }
647 #endif
648 
649  m_Layer[aLayer].m_name = nameTemp;
650 
651  return true;
652  }
653 
654  return false;
655 }
656 
657 
659 {
660  if( !IsCopperLayer( aLayer ) )
661  return LT_SIGNAL;
662 
663  //@@IMB: The original test was broken due to the discontinuity
664  // in the layer sequence.
665  if( IsLayerEnabled( aLayer ) )
666  return m_Layer[aLayer].m_type;
667 
668  return LT_SIGNAL;
669 }
670 
671 
672 bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
673 {
674  if( !IsCopperLayer( aLayer ) )
675  return false;
676 
677  //@@IMB: The original test was broken due to the discontinuity
678  // in the layer sequence.
679  if( IsLayerEnabled( aLayer ) )
680  {
681  m_Layer[aLayer].m_type = aLayerType;
682  return true;
683  }
684 
685  return false;
686 }
687 
688 
689 const char* LAYER::ShowType( LAYER_T aType )
690 {
691  const char* cp;
692 
693  switch( aType )
694  {
695  default:
696  case LT_SIGNAL:
697  cp = "signal";
698  break;
699 
700  case LT_POWER:
701  cp = "power";
702  break;
703 
704  case LT_MIXED:
705  cp = "mixed";
706  break;
707 
708  case LT_JUMPER:
709  cp = "jumper";
710  break;
711  }
712 
713  return cp;
714 }
715 
716 
717 LAYER_T LAYER::ParseType( const char* aType )
718 {
719  if( strcmp( aType, "signal" ) == 0 )
720  return LT_SIGNAL;
721  else if( strcmp( aType, "power" ) == 0 )
722  return LT_POWER;
723  else if( strcmp( aType, "mixed" ) == 0 )
724  return LT_MIXED;
725  else if( strcmp( aType, "jumper" ) == 0 )
726  return LT_JUMPER;
727  else
728  return LT_UNDEFINED;
729 }
730 
731 
733 {
735 }
736 
737 
738 void BOARD::SetCopperLayerCount( int aCount )
739 {
741 }
742 
743 
745 {
747 }
748 
749 
751 {
753 }
754 
755 
756 void BOARD::SetEnabledLayers( LSET aLayerSet )
757 {
758  m_designSettings.SetEnabledLayers( aLayerSet );
759 }
760 
761 
762 void BOARD::SetVisibleLayers( LSET aLayerSet )
763 {
764  m_designSettings.SetVisibleLayers( aLayerSet );
765 }
766 
767 
768 void BOARD::SetVisibleElements( int aMask )
769 {
770  // Call SetElementVisibility for each item
771  // to ensure specific calculations that can be needed by some items,
772  // just changing the visibility flags could be not sufficient.
774  {
775  int item_mask = 1 << GAL_LAYER_INDEX( ii );
776  SetElementVisibility( ii, aMask & item_mask );
777  }
778 }
779 
780 
782 {
783  SetVisibleLayers( LSET().set() );
784 
785  // Call SetElementVisibility for each item,
786  // to ensure specific calculations that can be needed by some items
788  SetElementVisibility( ii, true );
789 }
790 
791 
793 {
795 }
796 
797 
799 {
800  return m_designSettings.IsElementVisible( aLayer );
801 }
802 
803 
804 void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
805 {
806  m_designSettings.SetElementVisibility( aLayer, isEnabled );
807 
808  switch( aLayer )
809  {
810  case LAYER_RATSNEST:
811  {
812  bool visible = IsElementVisible( LAYER_RATSNEST );
813  // we must clear or set the CH_VISIBLE flags to hide/show ratsnest
814  // because we have a tool to show/hide ratsnest relative to a pad or a module
815  // so the hide/show option is a per item selection
816 
817  for( unsigned int net = 1 /* skip "No Net" at [0] */; net < GetNetCount(); net++ )
818  {
819  auto rn = GetConnectivity()->GetRatsnestForNet( net );
820  if( rn )
821  rn->SetVisible( visible );
822  }
823 
824  for( auto track : Tracks() )
825  track->SetLocalRatsnestVisible( isEnabled );
826 
827  for( auto mod : Modules() )
828  {
829  for( auto pad : mod->Pads() )
830  pad->SetLocalRatsnestVisible( isEnabled );
831  }
832 
833  for( int i = 0; i<GetAreaCount(); i++ )
834  {
835  auto zone = GetArea( i );
836  zone->SetLocalRatsnestVisible( isEnabled );
837  }
838 
839  m_Status_Pcb = 0;
840 
841  break;
842  }
843 
844  default:
845  ;
846  }
847 }
848 
849 
851 {
852  switch( aLayer )
853  {
854  case F_Cu:
855  return IsElementVisible( LAYER_MOD_FR );
856 
857  case B_Cu:
858  return IsElementVisible( LAYER_MOD_BK );
859 
860  default:
861  wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible() param error: bad layer" ) );
862  return true;
863  }
864 }
865 
866 
867 void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
868 {
869  if( aBoardItem == NULL )
870  {
871  wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem NULL" ) );
872  return;
873  }
874 
875  switch( aBoardItem->Type() )
876  {
877  case PCB_NETINFO_T:
878  m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
879  break;
880 
881  // this one uses a vector
882  case PCB_MARKER_T:
883  m_markers.push_back( (MARKER_PCB*) aBoardItem );
884  break;
885 
886  // this one uses a vector
887  case PCB_ZONE_AREA_T:
888  m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
889  break;
890 
891  case PCB_TRACE_T:
892  case PCB_VIA_T:
893  if( aMode == ADD_APPEND )
894  {
895  m_Track.PushBack( (TRACK*) aBoardItem );
896  }
897  else
898  {
899  TRACK* insertAid;
900  insertAid = ( (TRACK*) aBoardItem )->GetBestInsertPoint( this );
901  m_Track.Insert( (TRACK*) aBoardItem, insertAid );
902  }
903 
904  break;
905 
906  case PCB_MODULE_T:
907  if( aMode == ADD_APPEND )
908  m_Modules.PushBack( (MODULE*) aBoardItem );
909  else
910  m_Modules.PushFront( (MODULE*) aBoardItem );
911 
912  // Because the list of pads has changed, reset the status
913  // This indicate the list of pad and nets must be recalculated before use
914  m_Status_Pcb = 0;
915  break;
916 
917  case PCB_DIMENSION_T:
918  case PCB_LINE_T:
919  case PCB_TEXT_T:
920  case PCB_TARGET_T:
921  if( aMode == ADD_APPEND )
922  m_Drawings.PushBack( aBoardItem );
923  else
924  m_Drawings.PushFront( aBoardItem );
925 
926  break;
927 
928  // other types may use linked list
929  default:
930  {
931  wxString msg;
932  msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
933  aBoardItem->Type() );
934  wxFAIL_MSG( msg );
935  return;
936  }
937  break;
938  }
939 
940  aBoardItem->SetParent( this );
941  m_connectivity->Add( aBoardItem );
942 }
943 
944 
945 void BOARD::Remove( BOARD_ITEM* aBoardItem )
946 {
947  // find these calls and fix them! Don't send me no stinking' NULL.
948  wxASSERT( aBoardItem );
949 
950  switch( aBoardItem->Type() )
951  {
952  case PCB_NETINFO_T:
953  {
954  NETINFO_ITEM* item = (NETINFO_ITEM*) aBoardItem;
955  m_NetInfo.RemoveNet( item );
956  break;
957  }
958 
959  case PCB_MARKER_T:
960 
961  // find the item in the vector, then remove it
962  for( unsigned i = 0; i<m_markers.size(); ++i )
963  {
964  if( m_markers[i] == (MARKER_PCB*) aBoardItem )
965  {
966  m_markers.erase( m_markers.begin() + i );
967  break;
968  }
969  }
970 
971  break;
972 
973  case PCB_ZONE_AREA_T: // this one uses a vector
974  // find the item in the vector, then delete then erase it.
975  for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
976  {
977  if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
978  {
979  m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
980  break;
981  }
982  }
983  break;
984 
985  case PCB_MODULE_T:
986  m_Modules.Remove( (MODULE*) aBoardItem );
987  break;
988 
989  case PCB_TRACE_T:
990  case PCB_VIA_T:
991  m_Track.Remove( (TRACK*) aBoardItem );
992  break;
993 
994  case PCB_DIMENSION_T:
995  case PCB_LINE_T:
996  case PCB_TEXT_T:
997  case PCB_TARGET_T:
998  m_Drawings.Remove( aBoardItem );
999  break;
1000 
1001  // other types may use linked list
1002  default:
1003  wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
1004  }
1005 
1006  m_connectivity->Remove( aBoardItem );
1007 }
1008 
1009 
1010 wxString BOARD::GetSelectMenuText( EDA_UNITS_T aUnits ) const
1011 {
1012  return wxString::Format( _( "PCB" ) );
1013 }
1014 
1015 
1017 {
1018  // the vector does not know how to delete the MARKER_PCB, it holds pointers
1019  for( MARKER_PCB* marker : m_markers )
1020  delete marker;
1021 
1022  m_markers.clear();
1023 }
1024 
1025 
1027 {
1028  // the vector does not know how to delete the ZONE Outlines, it holds pointers
1029  for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
1030  delete zone;
1031 
1032  m_ZoneDescriptorList.clear();
1033 }
1034 
1035 
1036 BOARD_ITEM* BOARD::GetItem( void* aWeakReference )
1037 {
1038  for( TRACK* track : Tracks() )
1039  if( track == aWeakReference )
1040  return track;
1041 
1042  for( MODULE* module : Modules() )
1043  {
1044  if( module == aWeakReference )
1045  return module;
1046 
1047  for( D_PAD* pad : module->Pads() )
1048  if( pad == aWeakReference )
1049  return pad;
1050 
1051  if( &module->Reference() == aWeakReference )
1052  return &module->Reference();
1053 
1054  if( &module->Value() == aWeakReference )
1055  return &module->Value();
1056 
1057  for( BOARD_ITEM* drawing : module->GraphicalItems() )
1058  if( drawing == aWeakReference )
1059  return drawing;
1060  }
1061 
1062  for( ZONE_CONTAINER* zone : Zones() )
1063  if( zone == aWeakReference )
1064  return zone;
1065 
1066  for( BOARD_ITEM* drawing : Drawings() )
1067  if( drawing == aWeakReference )
1068  return drawing;
1069 
1070  // Not found; weak reference has been deleted.
1071  return &g_DeletedItem;
1072 }
1073 
1074 
1076 {
1077  return m_Track.GetCount();
1078 }
1079 
1080 
1081 unsigned BOARD::GetNodesCount( int aNet )
1082 {
1083  unsigned retval = 0;
1084  for( auto mod : Modules() )
1085  {
1086  for( auto pad : mod->Pads() )
1087  {
1088  if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1089  retval++;
1090  }
1091  }
1092 
1093  return retval;
1094 }
1095 
1096 
1098 {
1099  return m_connectivity->GetUnconnectedCount();
1100 }
1101 
1102 
1103 EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1104 {
1105  bool hasItems = false;
1106  EDA_RECT area;
1107 
1108  // Check segments, dimensions, texts, and fiducials
1109  for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
1110  {
1111  if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) )
1112  continue;
1113 
1114  if( !hasItems )
1115  area = item->GetBoundingBox();
1116  else
1117  area.Merge( item->GetBoundingBox() );
1118 
1119  hasItems = true;
1120  }
1121 
1122  if( !aBoardEdgesOnly )
1123  {
1124  // Check modules
1125  for( MODULE* module = m_Modules; module; module = module->Next() )
1126  {
1127  if( !hasItems )
1128  area = module->GetBoundingBox();
1129  else
1130  area.Merge( module->GetBoundingBox() );
1131 
1132  hasItems = true;
1133  }
1134 
1135  // Check tracks
1136  for( TRACK* track = m_Track; track; track = track->Next() )
1137  {
1138  if( !hasItems )
1139  area = track->GetBoundingBox();
1140  else
1141  area.Merge( track->GetBoundingBox() );
1142 
1143  hasItems = true;
1144  }
1145 
1146  // Check zones
1147  for( auto aZone : m_ZoneDescriptorList )
1148  {
1149  if( !hasItems )
1150  area = aZone->GetBoundingBox();
1151  else
1152  area.Merge( aZone->GetBoundingBox() );
1153 
1154  area.Merge( aZone->GetBoundingBox() );
1155  hasItems = true;
1156  }
1157  }
1158 
1159  return area;
1160 }
1161 
1162 
1163 void BOARD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
1164 {
1165  wxString txt;
1166  int viasCount = 0;
1167  int trackSegmentsCount = 0;
1168 
1169  for( BOARD_ITEM* item = m_Track; item; item = item->Next() )
1170  {
1171  if( item->Type() == PCB_VIA_T )
1172  viasCount++;
1173  else
1174  trackSegmentsCount++;
1175  }
1176 
1177  txt.Printf( wxT( "%d" ), GetPadCount() );
1178  aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );
1179 
1180  txt.Printf( wxT( "%d" ), viasCount );
1181  aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, DARKGREEN ) );
1182 
1183  txt.Printf( wxT( "%d" ), trackSegmentsCount );
1184  aList.push_back( MSG_PANEL_ITEM( _( "Track Segments" ), txt, DARKGREEN ) );
1185 
1186  txt.Printf( wxT( "%d" ), GetNodesCount() );
1187  aList.push_back( MSG_PANEL_ITEM( _( "Nodes" ), txt, DARKCYAN ) );
1188 
1189  txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() - 1 /* Don't include "No Net" in count */ );
1190  aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
1191 
1192  txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
1193  aList.push_back( MSG_PANEL_ITEM( _( "Unrouted" ), txt, BLUE ) );
1194 }
1195 
1196 
1197 SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1198 {
1199  KICAD_T stype;
1200  SEARCH_RESULT result = SEARCH_CONTINUE;
1201  const KICAD_T* p = scanTypes;
1202  bool done = false;
1203 
1204 #if 0 && defined(DEBUG)
1205  std::cout << GetClass().mb_str() << ' ';
1206 #endif
1207 
1208  while( !done )
1209  {
1210  stype = *p;
1211 
1212  switch( stype )
1213  {
1214  case PCB_T:
1215  result = inspector( this, testData ); // inspect me
1216  // skip over any types handled in the above call.
1217  ++p;
1218  break;
1219 
1220  /* Instances of the requested KICAD_T live in a list, either one
1221  * that I manage, or that my modules manage. If it's a type managed
1222  * by class MODULE, then simply pass it on to each module's
1223  * MODULE::Visit() function by way of the
1224  * IterateForward( m_Modules, ... ) call.
1225  */
1226 
1227  case PCB_MODULE_T:
1228  case PCB_PAD_T:
1229  case PCB_MODULE_TEXT_T:
1230  case PCB_MODULE_EDGE_T:
1231 
1232  // this calls MODULE::Visit() on each module.
1233  result = IterateForward( m_Modules, inspector, testData, p );
1234 
1235  // skip over any types handled in the above call.
1236  for( ; ; )
1237  {
1238  switch( stype = *++p )
1239  {
1240  case PCB_MODULE_T:
1241  case PCB_PAD_T:
1242  case PCB_MODULE_TEXT_T:
1243  case PCB_MODULE_EDGE_T:
1244  continue;
1245 
1246  default:
1247  ;
1248  }
1249 
1250  break;
1251  }
1252 
1253  break;
1254 
1255  case PCB_LINE_T:
1256  case PCB_TEXT_T:
1257  case PCB_DIMENSION_T:
1258  case PCB_TARGET_T:
1259  result = IterateForward( m_Drawings, inspector, testData, p );
1260 
1261  // skip over any types handled in the above call.
1262  for( ; ; )
1263  {
1264  switch( stype = *++p )
1265  {
1266  case PCB_LINE_T:
1267  case PCB_TEXT_T:
1268  case PCB_DIMENSION_T:
1269  case PCB_TARGET_T:
1270  continue;
1271 
1272  default:
1273  ;
1274  }
1275 
1276  break;
1277  }
1278 
1279  ;
1280  break;
1281 
1282 #if 0 // both these are on same list, so we must scan it twice in order
1283  // to get VIA priority, using new #else code below.
1284  // But we are not using separate lists for TRACKs and VIA, because
1285  // items are ordered (sorted) in the linked
1286  // list by netcode AND by physical distance:
1287  // when created, if a track or via is connected to an existing track or
1288  // via, it is put in linked list after this existing track or via
1289  // So usually, connected tracks or vias are grouped in this list
1290  // So the algorithm (used in ratsnest computations) which computes the
1291  // track connectivity is faster (more than 100 time regarding to
1292  // a non ordered list) because when it searches for a connection, first
1293  // it tests the near (near in term of linked list) 50 items
1294  // from the current item (track or via) in test.
1295  // Usually, because of this sort, a connected item (if exists) is
1296  // found.
1297  // If not found (and only in this case) an exhaustive (and time
1298  // consuming) search is made, but this case is statistically rare.
1299  case PCB_VIA_T:
1300  case PCB_TRACE_T:
1301  result = IterateForward( m_Track, inspector, testData, p );
1302 
1303  // skip over any types handled in the above call.
1304  for( ; ; )
1305  {
1306  switch( stype = *++p )
1307  {
1308  case PCB_VIA_T:
1309  case PCB_TRACE_T:
1310  continue;
1311 
1312  default:
1313  ;
1314  }
1315 
1316  break;
1317  }
1318 
1319  break;
1320 
1321 #else
1322  case PCB_VIA_T:
1323  result = IterateForward( m_Track, inspector, testData, p );
1324  ++p;
1325  break;
1326 
1327  case PCB_TRACE_T:
1328  result = IterateForward( m_Track, inspector, testData, p );
1329  ++p;
1330  break;
1331 #endif
1332 
1333  case PCB_MARKER_T:
1334 
1335  // MARKER_PCBS are in the m_markers std::vector
1336  for( unsigned i = 0; i<m_markers.size(); ++i )
1337  {
1338  result = m_markers[i]->Visit( inspector, testData, p );
1339 
1340  if( result == SEARCH_QUIT )
1341  break;
1342  }
1343 
1344  ++p;
1345  break;
1346 
1347  case PCB_ZONE_AREA_T:
1348 
1349  // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
1350  for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
1351  {
1352  result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
1353 
1354  if( result == SEARCH_QUIT )
1355  break;
1356  }
1357 
1358  ++p;
1359  break;
1360 
1361  default: // catch EOT or ANY OTHER type here and return.
1362  done = true;
1363  break;
1364  }
1365 
1366  if( result == SEARCH_QUIT )
1367  break;
1368  }
1369 
1370  return result;
1371 }
1372 
1373 
1374 NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1375 {
1376  // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1377  // zero is reserved for "no connection" and is not actually a net.
1378  // NULL is returned for non valid netcodes
1379 
1380  wxASSERT( m_NetInfo.GetNetCount() > 0 );
1381 
1382  if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1384  else
1385  return m_NetInfo.GetNetItem( aNetcode );
1386 }
1387 
1388 
1389 NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1390 {
1391  return m_NetInfo.GetNetItem( aNetname );
1392 }
1393 
1394 
1395 MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
1396 {
1397  MODULE* found = nullptr;
1398 
1399  // search only for MODULES
1400  static const KICAD_T scanTypes[] = { PCB_MODULE_T, EOT };
1401 
1402  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
1403  {
1404  MODULE* module = (MODULE*) item;
1405 
1406  if( aReference == module->GetReference() )
1407  {
1408  found = module;
1409  return SEARCH_QUIT;
1410  }
1411 
1412  return SEARCH_CONTINUE;
1413  };
1414 
1415  // visit this BOARD with the above inspector
1416  BOARD* nonconstMe = (BOARD*) this;
1417  nonconstMe->Visit( inspector, NULL, scanTypes );
1418 
1419  return found;
1420 }
1421 
1422 
1423 MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeStamp ) const
1424 {
1425  if( aSearchByTimeStamp )
1426  {
1427  for( MODULE* module = m_Modules; module; module = module->Next() )
1428  {
1429  if( aRefOrTimeStamp.CmpNoCase( module->GetPath() ) == 0 )
1430  return module;
1431  }
1432  }
1433  else
1434  {
1435  return FindModuleByReference( aRefOrTimeStamp );
1436  }
1437 
1438  return NULL;
1439 }
1440 
1441 
1442 
1443 // The pad count for each netcode, stored in a buffer for a fast access.
1444 // This is needed by the sort function sortNetsByNodes()
1445 static std::vector<int> padCountListByNet;
1446 
1447 // Sort nets by decreasing pad count.
1448 // For same pad count, sort by alphabetic names
1449 static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1450 {
1451  int countA = padCountListByNet[a->GetNet()];
1452  int countB = padCountListByNet[b->GetNet()];
1453 
1454  if( countA == countB )
1455  return a->GetNetname() < b->GetNetname();
1456  else
1457  return countB < countA;
1458 }
1459 
1460 // Sort nets by alphabetic names
1461 static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1462 {
1463  return a->GetNetname() < b->GetNetname();
1464 }
1465 
1466 int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
1467 {
1468  if( m_NetInfo.GetNetCount() == 0 )
1469  return 0;
1470 
1471  // Build the list
1472  std::vector <NETINFO_ITEM*> netBuffer;
1473 
1474  netBuffer.reserve( m_NetInfo.GetNetCount() );
1475  int max_netcode = 0;
1476 
1477  for( NETINFO_ITEM* net : m_NetInfo )
1478  {
1479  auto netcode = net->GetNet();
1480 
1481  if( netcode > 0 && net->IsCurrent() )
1482  {
1483  netBuffer.push_back( net );
1484  max_netcode = std::max( netcode, max_netcode);
1485  }
1486  }
1487 
1488  // sort the list
1489  if( aSortbyPadsCount )
1490  {
1491  // Build the pad count by net:
1492  padCountListByNet.clear();
1493  std::vector<D_PAD*> pads = GetPads();
1494 
1495  padCountListByNet.assign( max_netcode + 1, 0 );
1496 
1497  for( D_PAD* pad : pads )
1498  padCountListByNet[pad->GetNetCode()]++;
1499 
1500  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNodes );
1501  }
1502  else
1503  {
1504  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNames );
1505  }
1506 
1507  for( NETINFO_ITEM* net : netBuffer )
1508  aNames.Add( UnescapeString( net->GetNetname() ) );
1509 
1510  return netBuffer.size();
1511 }
1512 
1513 
1514 void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1515 {
1516  if( !aDC )
1517  return;
1518 
1519  for( int ii = 0; ii < GetAreaCount(); ii++ )
1520  {
1521  ZONE_CONTAINER* edge_zone = GetArea( ii );
1522 
1523  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1524  edge_zone->Draw( panel, aDC, aDrawMode );
1525  }
1526 }
1527 
1528 
1529 void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1530 {
1531  if( !aDC )
1532  return;
1533 
1534  for( int ii = 0; ii < GetAreaCount(); ii++ )
1535  {
1536  ZONE_CONTAINER* edge_zone = GetArea( ii );
1537 
1538  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1539  edge_zone->DrawFilledArea( panel, aDC, aDrawMode );
1540  }
1541 }
1542 
1543 
1545  PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer, int aNetCode )
1546 {
1547  if( aEndLayer < 0 )
1548  aEndLayer = aStartLayer;
1549 
1550  if( aEndLayer < aStartLayer )
1551  std::swap( aEndLayer, aStartLayer );
1552 
1553  for( ZONE_CONTAINER* area : m_ZoneDescriptorList )
1554  {
1555  if( area->GetLayer() < aStartLayer || area->GetLayer() > aEndLayer )
1556  continue;
1557 
1558  // In locate functions we must skip tagged items with BUSY flag set.
1559  if( area->GetState( BUSY ) )
1560  continue;
1561 
1562  if( aNetCode >= 0 && area->GetNetCode() != aNetCode )
1563  continue;
1564 
1565  if( area->HitTestFilledArea( aRefPos ) )
1566  return area;
1567  }
1568 
1569  return NULL;
1570 }
1571 
1572 
1574 {
1575  int error_count = 0;
1576 
1577  for( int ii = 0; ii < GetAreaCount(); ii++ )
1578  {
1579  ZONE_CONTAINER* it = GetArea( ii );
1580 
1581  if( !it->IsOnCopperLayer() )
1582  {
1584  continue;
1585  }
1586 
1587  if( it->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1588  {
1589  const NETINFO_ITEM* net = it->GetNet();
1590 
1591  if( net )
1592  {
1593  it->SetNetCode( net->GetNet() );
1594  }
1595  else
1596  {
1597  error_count++;
1598 
1599  // keep Net Name and set m_NetCode to -1 : error flag.
1600  it->SetNetCode( -1 );
1601  }
1602  }
1603  }
1604 
1605  return error_count;
1606 }
1607 
1608 
1609 VIA* BOARD::GetViaByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer) const
1610 {
1611  for( VIA *via = GetFirstVia( m_Track); via; via = GetFirstVia( via->Next() ) )
1612  {
1613  if( (via->GetStart() == aPosition) &&
1614  (via->GetState( BUSY | IS_DELETED ) == 0) &&
1615  ((aLayer == UNDEFINED_LAYER) || (via->IsOnLayer( aLayer ))) )
1616  return via;
1617  }
1618 
1619  return NULL;
1620 }
1621 
1622 
1623 D_PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet )
1624 {
1625  if( !aLayerSet.any() )
1626  aLayerSet = LSET::AllCuMask();
1627 
1628  for( MODULE* module = m_Modules; module; module = module->Next() )
1629  {
1630  D_PAD* pad = NULL;
1631 
1632  if( module->HitTest( aPosition ) )
1633  pad = module->GetPad( aPosition, aLayerSet );
1634 
1635  if( pad )
1636  return pad;
1637  }
1638 
1639  return NULL;
1640 }
1641 
1642 
1643 D_PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
1644 {
1645  const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
1646 
1647  LSET lset( aTrace->GetLayer() );
1648 
1649  return GetPad( aPosition, lset );
1650 }
1651 
1652 
1653 std::list<TRACK*> BOARD::GetTracksByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer ) const
1654 {
1655  std::list<TRACK*> tracks;
1656 
1657  for( TRACK* track = GetFirstTrack( m_Track ); track; track = GetFirstTrack( track->Next() ) )
1658  {
1659  if( ( ( track->GetStart() == aPosition ) || track->GetEnd() == aPosition ) &&
1660  ( track->GetState( BUSY | IS_DELETED ) == 0 ) &&
1661  ( ( aLayer == UNDEFINED_LAYER ) || ( track->IsOnLayer( aLayer ) ) ) )
1662 
1663  tracks.push_back( track );
1664  }
1665 
1666  return tracks;
1667 }
1668 
1669 
1670 D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
1671 {
1672  for( auto mod : Modules() )
1673  {
1674  for ( auto pad : mod->Pads() )
1675  {
1676  if( pad->GetPosition() != aPosition )
1677  continue;
1678 
1679  // Pad found, it must be on the correct layer
1680  if( ( pad->GetLayerSet() & aLayerSet ).any() )
1681  return pad;
1682  }
1683  }
1684 
1685  return nullptr;
1686 }
1687 
1688 
1689 D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet )
1690 {
1691  // Search aPadList for aPosition
1692  // aPadList is sorted by X then Y values, and a fast binary search is used
1693  int idxmax = aPadList.size()-1;
1694 
1695  int delta = aPadList.size();
1696 
1697  int idx = 0; // Starting index is the beginning of list
1698 
1699  while( delta )
1700  {
1701  // Calculate half size of remaining interval to test.
1702  // Ensure the computed value is not truncated (too small)
1703  if( (delta & 1) && ( delta > 1 ) )
1704  delta++;
1705 
1706  delta /= 2;
1707 
1708  D_PAD* pad = aPadList[idx];
1709 
1710  if( pad->GetPosition() == aPosition ) // candidate found
1711  {
1712  // The pad must match the layer mask:
1713  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1714  return pad;
1715 
1716  // More than one pad can be at aPosition
1717  // search for a pad at aPosition that matched this mask
1718 
1719  // search next
1720  for( int ii = idx+1; ii <= idxmax; ii++ )
1721  {
1722  pad = aPadList[ii];
1723 
1724  if( pad->GetPosition() != aPosition )
1725  break;
1726 
1727  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1728  return pad;
1729  }
1730  // search previous
1731  for( int ii = idx-1 ;ii >=0; ii-- )
1732  {
1733  pad = aPadList[ii];
1734 
1735  if( pad->GetPosition() != aPosition )
1736  break;
1737 
1738  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1739  return pad;
1740  }
1741 
1742  // Not found:
1743  return 0;
1744  }
1745 
1746  if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1747  {
1748  if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1749  {
1750  idx += delta;
1751 
1752  if( idx > idxmax )
1753  idx = idxmax;
1754  }
1755  else // Must search before this item
1756  {
1757  idx -= delta;
1758 
1759  if( idx < 0 )
1760  idx = 0;
1761  }
1762  }
1763  else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1764  {
1765  idx += delta;
1766 
1767  if( idx > idxmax )
1768  idx = idxmax;
1769  }
1770  else // Must search before this item
1771  {
1772  idx -= delta;
1773 
1774  if( idx < 0 )
1775  idx = 0;
1776  }
1777  }
1778 
1779  return NULL;
1780 }
1781 
1782 
1788 bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
1789 {
1790  if( ref->GetPosition().x == comp->GetPosition().x )
1791  return ref->GetPosition().y < comp->GetPosition().y;
1792  return ref->GetPosition().x < comp->GetPosition().x;
1793 }
1794 
1795 
1796 void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
1797 {
1798  for ( auto mod : Modules() )
1799  {
1800  for ( auto pad : mod->Pads( ) )
1801  {
1802  if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1803  {
1804  aVector.push_back( pad );
1805  }
1806  }
1807  }
1808 
1809  std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1810 }
1811 
1812 
1814 {
1815  GetConnectivity()->Remove( aPad );
1816  aPad->DeleteStructure();
1817 }
1818 
1819 
1820 TRACK* BOARD::GetVisibleTrack( TRACK* aStartingTrace, const wxPoint& aPosition,
1821  LSET aLayerSet ) const
1822 {
1823  for( TRACK* track = aStartingTrace; track; track = track->Next() )
1824  {
1825  PCB_LAYER_ID layer = track->GetLayer();
1826 
1827  if( track->GetState( BUSY | IS_DELETED ) )
1828  continue;
1829 
1830  // track's layer is not visible
1831  if( m_designSettings.IsLayerVisible( layer ) == false )
1832  continue;
1833 
1834  if( track->Type() == PCB_VIA_T ) // VIA encountered.
1835  {
1836  if( track->HitTest( aPosition ) )
1837  return track;
1838  }
1839  else
1840  {
1841  if( !aLayerSet[layer] )
1842  continue; // track's layer is not in aLayerSet
1843 
1844  if( track->HitTest( aPosition ) )
1845  return track;
1846  }
1847  }
1848 
1849  return NULL;
1850 }
1851 
1852 
1853 TRACK* BOARD::MarkTrace( TRACK* aTrackList, TRACK* aTrace, int* aCount,
1854  double* aTraceLength, double* aPadToDieLength,
1855  bool aReorder )
1856 {
1857  TRACKS trackList;
1858 
1859  if( aCount )
1860  *aCount = 0;
1861 
1862  if( aTraceLength )
1863  *aTraceLength = 0;
1864 
1865  if( aTrace == NULL )
1866  return NULL;
1867 
1868  // Ensure the flag BUSY of all tracks of the board is cleared
1869  // because we use it to mark segments of the track
1870  for( TRACK* track = aTrackList; track; track = track->Next() )
1871  track->SetState( BUSY, false );
1872 
1873  // Set flags of the initial track segment
1874  aTrace->SetState( BUSY, true );
1875  LSET layer_set = aTrace->GetLayerSet();
1876 
1877  trackList.push_back( aTrace );
1878 
1879  /* Examine the initial track segment : if it is really a segment, this is
1880  * easy.
1881  * If it is a via, one must search for connected segments.
1882  * If <=2, this via connect 2 segments (or is connected to only one
1883  * segment) and this via and these 2 segments are a part of a track.
1884  * If > 2 only this via is flagged (the track has only this via)
1885  */
1886  if( aTrace->Type() == PCB_VIA_T )
1887  {
1888  TRACK* segm1 = ::GetTrack( aTrackList, NULL, aTrace->GetStart(), layer_set );
1889  TRACK* segm2 = NULL;
1890  TRACK* segm3 = NULL;
1891 
1892  if( segm1 )
1893  {
1894  segm2 = ::GetTrack( segm1->Next(), NULL, aTrace->GetStart(), layer_set );
1895  }
1896 
1897  if( segm2 )
1898  {
1899  segm3 = ::GetTrack( segm2->Next(), NULL, aTrace->GetStart(), layer_set );
1900  }
1901 
1902  if( segm3 )
1903  {
1904  // More than 2 segments are connected to this via.
1905  // The "track" is only this via.
1906 
1907  if( aCount )
1908  *aCount = 1;
1909 
1910  return aTrace;
1911  }
1912 
1913  if( segm1 ) // search for other segments connected to the initial segment start point
1914  {
1915  layer_set = segm1->GetLayerSet();
1916  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1917  }
1918 
1919  if( segm2 ) // search for other segments connected to the initial segment end point
1920  {
1921  layer_set = segm2->GetLayerSet();
1922  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1923  }
1924  }
1925  else // mark the chain using both ends of the initial segment
1926  {
1927  TRACKS from_start;
1928  TRACKS from_end;
1929 
1930  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &from_start );
1931  chainMarkedSegments( aTrackList, aTrace->GetEnd(), layer_set, &from_end );
1932 
1933  // combine into one trackList:
1934  trackList.insert( trackList.end(), from_start.begin(), from_start.end() );
1935  trackList.insert( trackList.end(), from_end.begin(), from_end.end() );
1936  }
1937 
1938  // Now examine selected vias and flag them if they are on the track
1939  // If a via is connected to only one or 2 segments, it is flagged (is on the track)
1940  // If a via is connected to more than 2 segments, it is a track end, and it
1941  // is removed from the list.
1942  // Go through the list backwards.
1943  for( int i = trackList.size() - 1; i>=0; --i )
1944  {
1945  ::VIA* via = dynamic_cast< ::VIA* >( trackList[i] );
1946 
1947  if( !via )
1948  continue;
1949 
1950  if( via == aTrace )
1951  continue;
1952 
1953  via->SetState( BUSY, true ); // Try to flag it. the flag will be cleared later if needed
1954 
1955  layer_set = via->GetLayerSet();
1956 
1957  TRACK* track = ::GetTrack( aTrackList, NULL, via->GetStart(), layer_set );
1958 
1959  // GetTrace does not consider tracks flagged BUSY.
1960  // So if no connected track found, this via is on the current track
1961  // only: keep it
1962  if( track == NULL )
1963  continue;
1964 
1965  /* If a track is found, this via connects also other segments of
1966  * the other track. This case happens when a via ends the selected
1967  * track but must we consider this via is on the selected track, or
1968  * on a other track.
1969  * (this is important when selecting a track for deletion: must this
1970  * via be deleted or not?)
1971  * We consider this via to be on our track if other segments connected
1972  * to this via remain connected when removing this via.
1973  * We search for all other segments connected together:
1974  * if they are on the same layer, then the via is on the selected track;
1975  * if they are on different layers, the via is on a other track.
1976  */
1977  LAYER_NUM layer = track->GetLayer();
1978 
1979  while( ( track = ::GetTrack( track->Next(), NULL, via->GetStart(), layer_set ) ) != NULL )
1980  {
1981  if( layer != track->GetLayer() )
1982  {
1983  // The via connects segments of a other track: it is removed
1984  // from list because it is member of a other track
1985  via->SetState( BUSY, false );
1986  break;
1987  }
1988  }
1989  }
1990 
1991  /* Rearrange the track list in order to have flagged segments linked
1992  * from firstTrack so the NbSegmBusy segments are consecutive segments
1993  * in list, the first item in the full track list is firstTrack, and
1994  * the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
1995  * are the flagged segments
1996  */
1997  int busy_count = 0;
1998  TRACK* firstTrack;
1999 
2000  for( firstTrack = aTrackList; firstTrack; firstTrack = firstTrack->Next() )
2001  {
2002  // Search for the first flagged BUSY segments
2003  if( firstTrack->GetState( BUSY ) )
2004  {
2005  busy_count = 1;
2006  break;
2007  }
2008  }
2009 
2010  if( firstTrack == NULL )
2011  return NULL;
2012 
2013  // First step: calculate the track length and find the pads (when exist)
2014  // at each end of the trace.
2015  double full_len = 0;
2016  double lenPadToDie = 0;
2017  // Because we have a track (a set of track segments between 2 nodes),
2018  // only 2 pads (maximum) will be taken in account:
2019  // that are on each end of the track, if any.
2020  // keep trace of them, to know the die length and the track length ibside each pad.
2021  D_PAD* s_pad = NULL; // the pad on one end of the trace
2022  D_PAD* e_pad = NULL; // the pad on the other end of the trace
2023  int dist_fromstart = INT_MAX;
2024  int dist_fromend = INT_MAX;
2025 
2026  for( TRACK* track = firstTrack; track; track = track->Next() )
2027  {
2028  if( !track->GetState( BUSY ) )
2029  continue;
2030 
2031  layer_set = track->GetLayerSet();
2032  D_PAD * pad_on_start = GetPad( track->GetStart(), layer_set );
2033  D_PAD * pad_on_end = GetPad( track->GetEnd(), layer_set );
2034 
2035  // a segment fully inside a pad does not contribute to the track len
2036  // (another track end inside this pad will contribute to this lenght)
2037  if( pad_on_start && ( pad_on_start == pad_on_end ) )
2038  continue;
2039 
2040  full_len += track->GetLength();
2041 
2042  if( pad_on_start == NULL && pad_on_end == NULL )
2043  // This most of time the case
2044  continue;
2045 
2046  // At this point, we can have one track end on a pad, or the 2 track ends on
2047  // 2 different pads.
2048  // We don't know what pad (s_pad or e_pad) must be used to store the
2049  // start point and the end point of the track, so if a pad is already set,
2050  // use the other
2051  if( pad_on_start )
2052  {
2053  SEG segm( track->GetStart(), pad_on_start->GetPosition() );
2054  int dist = segm.Length();
2055 
2056  if( s_pad == NULL )
2057  {
2058  dist_fromstart = dist;
2059  s_pad = pad_on_start;
2060  }
2061  else if( e_pad == NULL )
2062  {
2063  dist_fromend = dist;
2064  e_pad = pad_on_start;
2065  }
2066  else // Should not occur, at least for basic pads
2067  {
2068  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_start" );
2069  }
2070  }
2071 
2072  if( pad_on_end )
2073  {
2074  SEG segm( track->GetEnd(), pad_on_end->GetPosition() );
2075  int dist = segm.Length();
2076 
2077  if( s_pad == NULL )
2078  {
2079  dist_fromstart = dist;
2080  s_pad = pad_on_end;
2081  }
2082  else if( e_pad == NULL )
2083  {
2084  dist_fromend = dist;
2085  e_pad = pad_on_end;
2086  }
2087  else // Should not occur, at least for basic pads
2088  {
2089  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_end" );
2090  }
2091  }
2092  }
2093 
2094  if( aReorder )
2095  {
2096  DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
2097  wxASSERT( list );
2098 
2099  /* Rearrange the chain starting at firstTrack
2100  * All other BUSY flagged items are moved from their position to the end
2101  * of the flagged list
2102  */
2103  TRACK* next;
2104 
2105  for( TRACK* track = firstTrack->Next(); track; track = next )
2106  {
2107  next = track->Next();
2108 
2109  if( track->GetState( BUSY ) ) // move it!
2110  {
2111  busy_count++;
2112  track->UnLink();
2113  list->Insert( track, firstTrack->Next() );
2114 
2115  }
2116  }
2117  }
2118  else if( aTraceLength )
2119  {
2120  busy_count = 0;
2121 
2122  for( TRACK* track = firstTrack; track; track = track->Next() )
2123  {
2124  if( track->GetState( BUSY ) )
2125  {
2126  busy_count++;
2127  track->SetState( BUSY, false );
2128  }
2129  }
2130  }
2131 
2132  if( s_pad )
2133  {
2134  full_len += dist_fromstart;
2135  lenPadToDie += (double) s_pad->GetPadToDieLength();
2136  }
2137 
2138  if( e_pad )
2139  {
2140  full_len += dist_fromend;
2141  lenPadToDie += (double) e_pad->GetPadToDieLength();
2142  }
2143 
2144  if( aTraceLength )
2145  *aTraceLength = full_len;
2146 
2147  if( aPadToDieLength )
2148  *aPadToDieLength = lenPadToDie;
2149 
2150  if( aCount )
2151  *aCount = busy_count;
2152 
2153  return firstTrack;
2154 }
2155 
2156 
2157 MODULE* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
2158  bool aVisibleOnly, bool aIgnoreLocked )
2159 {
2160  MODULE* pt_module;
2161  MODULE* module = NULL;
2162  MODULE* alt_module = NULL;
2163  int min_dim = 0x7FFFFFFF;
2164  int alt_min_dim = 0x7FFFFFFF;
2165  bool current_layer_back = IsBackLayer( aActiveLayer );
2166 
2167  for( pt_module = m_Modules; pt_module; pt_module = pt_module->Next() )
2168  {
2169  // is the ref point within the module's bounds?
2170  if( !pt_module->HitTest( aPosition ) )
2171  continue;
2172 
2173  // if caller wants to ignore locked modules, and this one is locked, skip it.
2174  if( aIgnoreLocked && pt_module->IsLocked() )
2175  continue;
2176 
2177  PCB_LAYER_ID layer = pt_module->GetLayer();
2178 
2179  // Filter non visible modules if requested
2180  if( !aVisibleOnly || IsModuleLayerVisible( layer ) )
2181  {
2182  EDA_RECT bb = pt_module->GetFootprintRect();
2183 
2184  int offx = bb.GetX() + bb.GetWidth() / 2;
2185  int offy = bb.GetY() + bb.GetHeight() / 2;
2186 
2187  // off x & offy point to the middle of the box.
2188  int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2189  ( aPosition.y - offy ) * ( aPosition.y - offy );
2190 
2191  if( current_layer_back == IsBackLayer( layer ) )
2192  {
2193  if( dist <= min_dim )
2194  {
2195  // better footprint shown on the active side
2196  module = pt_module;
2197  min_dim = dist;
2198  }
2199  }
2200  else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
2201  {
2202  if( dist <= alt_min_dim )
2203  {
2204  // better footprint shown on the other side
2205  alt_module = pt_module;
2206  alt_min_dim = dist;
2207  }
2208  }
2209  }
2210  }
2211 
2212  if( module )
2213  {
2214  return module;
2215  }
2216 
2217  if( alt_module)
2218  {
2219  return alt_module;
2220  }
2221 
2222  return NULL;
2223 }
2224 
2225 
2226 BOARD_CONNECTED_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, LSET aLayerSet )
2227 {
2228  for( MODULE* module = m_Modules; module; module = module->Next() )
2229  {
2230  D_PAD* pad = module->GetPad( aPosition, aLayerSet );
2231 
2232  if( pad )
2233  return pad;
2234  }
2235 
2236  // No pad has been located so check for a segment of the trace.
2237  TRACK* segment = ::GetTrack( m_Track, NULL, aPosition, aLayerSet );
2238 
2239  if( !segment )
2240  segment = GetVisibleTrack( m_Track, aPosition, aLayerSet );
2241 
2242  return segment;
2243 }
2244 
2245 
2246 TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList )
2247 {
2248  /* creates an intermediate point on aSegment and break it into two segments
2249  * at aPosition.
2250  * The new segment starts from aPosition and ends at the end point of
2251  * aSegment. The original segment now ends at aPosition.
2252  */
2253  if( aSegment->GetStart() == aPosition || aSegment->GetEnd() == aPosition )
2254  return NULL;
2255 
2256  // A via is a good lock point
2257  if( aSegment->Type() == PCB_VIA_T )
2258  {
2259  aPosition = aSegment->GetStart();
2260  return aSegment;
2261  }
2262 
2263  // Calculation coordinate of intermediate point relative to the start point of aSegment
2264  wxPoint delta = aSegment->GetEnd() - aSegment->GetStart();
2265 
2266  // calculate coordinates of aPosition relative to aSegment->GetStart()
2267  wxPoint lockPoint = aPosition - aSegment->GetStart();
2268 
2269  // lockPoint must be on aSegment:
2270  // Ensure lockPoint.y/lockPoint.y = delta.y/delta.x
2271  if( delta.x == 0 )
2272  lockPoint.x = 0; // horizontal segment
2273  else
2274  lockPoint.y = KiROUND( ( (double)lockPoint.x * delta.y ) / delta.x );
2275 
2276  /* Create the intermediate point (that is to say creation of a new
2277  * segment, beginning at the intermediate point.
2278  */
2279  lockPoint += aSegment->GetStart();
2280 
2281  TRACK* newTrack = (TRACK*)aSegment->Clone();
2282  // The new segment begins at the new point,
2283  newTrack->SetStart(lockPoint);
2284  newTrack->start = aSegment;
2285  newTrack->SetState( BEGIN_ONPAD, false );
2286 
2287  DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
2288  wxASSERT( list );
2289  list->Insert( newTrack, aSegment->Next() );
2290 
2291  if( aList )
2292  {
2293  // Prepare the undo command for the now track segment
2294  ITEM_PICKER picker( newTrack, UR_NEW );
2295  aList->PushItem( picker );
2296  // Prepare the undo command for the old track segment
2297  // before modifications
2298  picker.SetItem( aSegment );
2299  picker.SetStatus( UR_CHANGED );
2300  picker.SetLink( aSegment->Clone() );
2301  aList->PushItem( picker );
2302  }
2303 
2304  // Old track segment now ends at new point.
2305  aSegment->SetEnd(lockPoint);
2306  aSegment->end = newTrack;
2307  aSegment->SetState( END_ONPAD, false );
2308 
2309  D_PAD * pad = GetPad( newTrack, ENDPOINT_START );
2310 
2311  if( pad )
2312  {
2313  newTrack->start = pad;
2314  newTrack->SetState( BEGIN_ONPAD, true );
2315  aSegment->end = pad;
2316  aSegment->SetState( END_ONPAD, true );
2317  }
2318 
2319  aPosition = lockPoint;
2320  return newTrack;
2321 }
2322 
2323 
2324 ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
2325  PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch )
2326 {
2327  ZONE_CONTAINER* new_area = InsertArea( aNetcode,
2328  m_ZoneDescriptorList.size( ) - 1,
2329  aLayer, aStartPointPosition.x,
2330  aStartPointPosition.y, aHatch );
2331 
2332  if( aNewZonesList )
2333  {
2334  ITEM_PICKER picker( new_area, UR_NEW );
2335  aNewZonesList->PushItem( picker );
2336  }
2337 
2338  return new_area;
2339 }
2340 
2341 
2342 void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
2343 {
2344  if( area_to_remove == NULL )
2345  return;
2346 
2347  if( aDeletedList )
2348  {
2349  ITEM_PICKER picker( area_to_remove, UR_DELETED );
2350  aDeletedList->PushItem( picker );
2351  Remove( area_to_remove ); // remove from zone list, but does not delete it
2352  }
2353  else
2354  {
2355  Delete( area_to_remove );
2356  }
2357 }
2358 
2359 
2360 ZONE_CONTAINER* BOARD::InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
2361  int aCornerX, int aCornerY, int aHatch )
2362 {
2363  ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
2364 
2365  new_area->SetNetCode( aNetcode );
2366  new_area->SetLayer( aLayer );
2367  new_area->SetTimeStamp( GetNewTimeStamp() );
2368 
2369  if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
2370  m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
2371  else
2372  m_ZoneDescriptorList.push_back( new_area );
2373 
2374  new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
2375 
2376  // Add the first corner to the new zone
2377  new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
2378 
2379  return new_area;
2380 }
2381 
2382 
2384 {
2385  // mark all areas as unmodified except this one, if modified
2386  for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
2387  zone->SetLocalFlags( 0 );
2388 
2389  aCurrArea->SetLocalFlags( 1 );
2390 
2391  if( aCurrArea->Outline()->IsSelfIntersecting() )
2392  {
2393  aCurrArea->UnHatch();
2394 
2395  // Normalize copied area and store resulting number of polygons
2396  int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
2397 
2398  // If clipping has created some polygons, we must add these new copper areas.
2399  if( n_poly > 1 )
2400  {
2401  ZONE_CONTAINER* NewArea;
2402 
2403  // Move the newly created polygons to new areas, removing them from the current area
2404  for( int ip = 1; ip < n_poly; ip++ )
2405  {
2406  // Create new copper area and copy poly into it
2407  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
2408  NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
2409  wxPoint(0, 0), aCurrArea->GetHatchStyle() );
2410 
2411  // remove the poly that was automatically created for the new area
2412  // and replace it with a poly from NormalizeAreaOutlines
2413  delete NewArea->Outline();
2414  NewArea->SetOutline( new_p );
2415  NewArea->Hatch();
2416  NewArea->SetLocalFlags( 1 );
2417  }
2418 
2419  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
2420  delete aCurrArea->Outline();
2421  aCurrArea->SetOutline( new_p );
2422  }
2423  }
2424 
2425  aCurrArea->Hatch();
2426 
2427  return true;
2428 }
2429 
2430 
2432  bool aAddToBoard )
2433 {
2434  BOARD_ITEM* new_item = NULL;
2435 
2436  switch( aItem->Type() )
2437  {
2438  case PCB_MODULE_T:
2439  case PCB_TEXT_T:
2440  case PCB_LINE_T:
2441  case PCB_TRACE_T:
2442  case PCB_VIA_T:
2443  case PCB_ZONE_AREA_T:
2444  case PCB_TARGET_T:
2445  case PCB_DIMENSION_T:
2446  new_item = static_cast<BOARD_ITEM*>( aItem->Clone() );
2447  break;
2448 
2449  default:
2450  // Un-handled item for duplication
2451  new_item = NULL;
2452  break;
2453  }
2454 
2455  if( new_item && aAddToBoard )
2456  Add( new_item );
2457 
2458  return new_item;
2459 }
2460 
2461 
2462 /* Extracts the board outlines and build a closed polygon
2463  * from lines, arcs and circle items on edge cut layer
2464  * Any closed outline inside the main outline is a hole
2465  * All contours should be closed, i.e. are valid vertices for a closed polygon
2466  * return true if success, false if a contour is not valid
2467  */
2468 extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
2469  wxString* aErrorText, unsigned int aTolerance,
2470  wxPoint* aErrorLocation = nullptr );
2471 
2472 
2473 bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText, wxPoint* aErrorLocation )
2474 {
2475  bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText,
2476  ARC_HIGH_DEF, aErrorLocation );
2477 
2478  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2480 
2481  return success;
2482 
2483 }
2484 
2485 
2486 const std::vector<D_PAD*> BOARD::GetPads()
2487 {
2488  std::vector<D_PAD*> allPads;
2489 
2490  for( MODULE* mod : Modules() )
2491  {
2492  for( D_PAD* pad : mod->Pads() )
2493  allPads.push_back( pad );
2494  }
2495 
2496  return allPads;
2497 }
2498 
2499 
2501 {
2502  unsigned retval = 0;
2503 
2504  for( auto mod : Modules() )
2505  retval += mod->Pads().Size();
2506 
2507  return retval;
2508 }
2509 
2510 
2515 D_PAD* BOARD::GetPad( unsigned aIndex ) const
2516 {
2517  unsigned count = 0;
2518 
2519  for( MODULE* mod = m_Modules; mod ; mod = mod->Next() ) // FIXME: const DLIST_ITERATOR
2520  {
2521  for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() )
2522  {
2523  if( count == aIndex )
2524  return pad;
2525 
2526  count++;
2527  }
2528  }
2529 
2530  return nullptr;
2531 }
2532 
2534 {
2535  for( auto zone : Zones() )
2536  zone->SetNetCode( 0 );
2537 
2538  for( auto pad : GetPads() )
2539  pad->SetNetCode( 0 );
2540 
2541  for( auto track : Tracks() )
2542  track->SetNetCode( 0 );
2543 }
2544 
2545 const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
2546 {
2547  std::vector<BOARD_CONNECTED_ITEM*> items;
2548 
2549  for( auto track : Tracks() )
2550  {
2551  items.push_back( track );
2552  }
2553 
2554  for( auto mod : Modules() )
2555  {
2556  for( auto pad : mod->Pads() )
2557  {
2558  items.push_back( pad );
2559  }
2560  }
2561 
2562  for( int i = 0; i<GetAreaCount(); i++ )
2563  {
2564  auto zone = GetArea( i );
2565  items.push_back( zone );
2566  }
2567 
2568  return items;
2569 }
2570 
2572 {
2573  for ( auto item : AllConnectedItems() )
2574  {
2575  if( FindNet( item->GetNetCode() ) == nullptr )
2576  item->SetNetCode( NETINFO_LIST::ORPHANED );
2577  }
2578 }
bool IsElementVisible(GAL_LAYER_ID aElementCategory) const
Function IsElementVisible tests whether a given element category is visible.
Definition: colors.h:57
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
CITER next(CITER it)
Definition: ptree.cpp:130
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
DHEAD * GetList() const
Definition: base_struct.h:214
void SetCopperLayerCount(int aNewLayerCount)
Function SetCopperLayerCount do what its name says...
void BuildListOfNets()
Definition: class_board.h:728
void Draw(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset) override
Function Draw Draws the zone outline.
Definition: class_zone.cpp:289
void SetEnabledLayers(LSET aMask)
Function SetEnabledLayers changes the bit-mask of enabled layers.
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
static SEARCH_RESULT IterateForward(EDA_ITEM *listStart, INSPECTOR inspector, void *testData, const KICAD_T scanTypes[])
Function IterateForward walks through the object tree calling the inspector() on each object type req...
TRACK * CreateLockPoint(wxPoint &aPosition, TRACK *aSegment, PICKED_ITEMS_LIST *aList)
Function CreateLockPoint creates an intermediate point on aSegment and break it into two segments at ...
const PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Function GetLayerID returns the ID of a layer given by aLayerName.
TRACK * GetTrack(TRACK *aStartTrace, const TRACK *aEndTrace, const wxPoint &aPosition, LSET aLayerMask)
Function GetTrack is a helper function to locate a trace segment having an end point at aPosition on ...
Definition: class_track.cpp:68
Class that draws missing connections on a PCB.
void DeleteZONEOutlines()
Function DeleteZONEOutlines deletes ALL zone outlines from the board.
int GetNetCode() const
Function GetNetCode.
Definition: typeinfo.h:85
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: base_struct.h:77
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:200
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
void SetElementVisibility(GAL_LAYER_ID aLayer, bool aNewState)
Function SetElementVisibility changes the visibility of an element category.
T * Remove(T *aElement)
Function Remove removes aElement from the list, but does not delete it.
Definition: dlist.h:211
int StrPrintf(std::string *aResult, const char *aFormat,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
TEXTE_PCB class definition.
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:318
static const int dist[10][10]
Definition: ar_matrix.cpp:320
#define END_ONPAD
Pcbnew: flag set for track segment ending on a pad.
Definition: base_struct.h:134
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:118
wxString m_name
The name of the layer, there should be no spaces in this name.
Definition: class_board.h:112
void PadDelete(D_PAD *aPad)
Function PadDelete deletes a given bad from the BOARD by removing it from its module and from the m_N...
void GetMsgPanelInfo(EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
void PushFront(T *aNewElement)
Function PushFront puts aNewElement at front of list sequence.
Definition: dlist.h:240
void SetVisibleElements(int aMask)
Function SetVisibleElements is a proxy function that calls the correspondent function in m_BoardSetti...
virtual const wxPoint GetPosition() const override
Implementation of conversion functions that require both schematic and board internal units.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
wxString GetClass() const override
Function GetClass returns the class name.
Definition: class_board.cpp:80
static void removeTrack(TRACKS *aList, TRACK *aOneToRemove)
Function removeTrack removes aOneToRemove from aList, which is a non-owning std::vector.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:129
int GetX() const
Definition: eda_rect.h:109
D_PAD * GetPadFast(const wxPoint &aPosition, LSET aLayerMask)
Function GetPadFast return pad found at aPosition on aLayerMask using the fast search method.
static void otherEnd(const TRACK &aTrack, const wxPoint &aNotThisEnd, wxPoint *aOtherEnd)
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
const wxPoint & GetStart() const
Definition: class_track.h:133
void SetStatus(UNDO_REDO_T aStatus)
TRACKS TracksInNetBetweenPoints(const wxPoint &aStartPos, const wxPoint &aGoalPos, int aNetCode)
Function TrackInNetBetweenPoints collects all the TRACKs and VIAs that are members of a net given by ...
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 BOARD to handle a board.
void DrawFilledArea(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset)
Function DrawDrawFilledArea Draws the filled area for this zone (polygon list .m_FilledPolysList)
Definition: class_zone.cpp:419
Class that computes missing connections on a PCB.
the 3d code uses this value
Definition: typeinfo.h:80
LAYER_T m_type
The type of the layer.
Definition: class_board.h:114
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
COLORS_DESIGN_SETTINGS * m_colorsSettings
Definition: class_board.h:196
int GetPadToDieLength() const
Definition: class_pad.h:419
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:100
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:185
ZONE_CONTAINER * m_CurrentZoneContour
zone contour currently in progress
Definition: class_board.h:261
void Draw(EDA_DRAW_PANEL *, wxDC *, GR_DRAWMODE, const wxPoint &) override
Function Draw BOARD_ITEMs have their own color information.
Definition: class_board.cpp:88
int GetWidth() const
Definition: eda_rect.h:117
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
void DeleteStructure()
Function DeleteStructure deletes this object after UnLink()ing it from its owner if it has one.
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
void SetCopperLayerCount(int aCount)
virtual EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
void RemoveArea(PICKED_ITEMS_LIST *aDeletedList, ZONE_CONTAINER *area_to_remove)
Function RemoveArea remove copper area from net, and put it in a deleted list (if exists)
const wxPoint GetPosition() const override
Definition: class_board.cpp:86
DELETED_BOARD_ITEM g_DeletedItem
Definition: class_board.cpp:95
bool IsLayerVisible(PCB_LAYER_ID aLayerId) const
Function IsLayerVisible tests whether a given layer is visible.
Classes to handle copper zones.
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text.
void SetVisibleAlls()
Function SetVisibleAlls changes 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 D_PAD, a pad in a footprint
Definition: typeinfo.h:90
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:135
virtual void SetPosition(const wxPoint &aPos) override
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
This is the end of the layers used for visibility bitmasks in Pcbnew There can be at most 32 layers a...
bool SetLayerType(PCB_LAYER_ID aLayer, LAYER_T aLayerType)
Function SetLayerType changes the type of the layer given by aLayer.
HIGH_LIGHT_INFO m_highLight
Definition: class_board.h:187
NETINFO_LIST m_NetInfo
net info list (name, design constraints ..
Definition: class_board.h:200
A singleton item of this class is returned for a weak reference that no longer exists.
Definition: class_board.cpp:68
HIGH_LIGHT_INFO m_highLightPrevious
Definition: class_board.h:188
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
Function IsLayerEnabled is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:442
D_PAD * GetPad(unsigned aIndex) const
Function GetPad.
#define cu(a)
Definition: auxiliary.h:88
#define BEGIN_ONPAD
Pcbnew: flag set for track segment starting on a pad.
Definition: base_struct.h:133
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:49
void SetLink(EDA_ITEM *aItem)
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
static COLORS_DESIGN_SETTINGS dummyColorsSettings(FRAME_PCB)
void SetOutline(SHAPE_POLY_SET *aOutline)
Definition: class_zone.h:263
BOARD_CONNECTED_ITEM * GetLockPoint(const wxPoint &aPosition, LSET aLayerMask)
Function GetLockPoint returns the item at the "attachment" point at the end of a trace at aPosition o...
static const int delta[8][2]
Definition: solve.cpp:112
void SetCustomViaSize(int aSize)
Function SetCustomViaSize Sets custom size for via diameter (i.e.
static int find_vias_and_tracks_at(TRACKS &at_next, TRACKS &in_net, LSET &lset, const wxPoint &next)
Function find_vias_and_tracks_at collects TRACKs and VIAs at aPos and returns the track_count which e...
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 EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:462
static const char * ShowType(LAYER_T aType)
Function ShowType converts a LAYER_T enum to a const char*.
ZONE_CONTAINER * HitTestForAnyFilledArea(const wxPoint &aRefPos, PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer, int aNetCode)
Function HitTestForAnyFilledArea tests if the given wxPoint is within the bounds of a filled area of ...
void SetVisibleLayers(LSET aMask)
Function SetVisibleLayers changes the bit-mask of visible layers.
void PushBack(T *aNewElement)
Function PushBack puts aNewElement at the end of the list sequence.
Definition: dlist.h:250
Classes used in Pcbnew, CvPcb and GerbView.
void AppendNet(NETINFO_ITEM *aNewElement)
Function AppendNet adds aNewElement to the end of the net list.
int GetNumSegmTrack() const
Functions to get some items count.
show modules on front
Class that handles properties and drawing of worksheet layout.
TRACK * GetVisibleTrack(TRACK *aStartingTrace, const wxPoint &aPosition, LSET aLayerSet) const
Function GetVisibleTrack finds the neighboring visible segment of aTrace at aPosition that is on a la...
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:102
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
DIMENSION class definition.
VIA * GetVia(const wxPoint &aPosition, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Function GetVia finds the first VIA object at aPosition on aLayer starting at the trace.
class MODULE, a footprint
Definition: typeinfo.h:89
timestamp_t GetNewTimeStamp()
Definition: common.cpp:216
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Markers used to show a drc problem on boards.
std::list< TRACK * > GetTracksByPosition(const wxPoint &aPosition, PCB_LAYER_ID aLayer=PCB_LAYER_ID(-1)) const
Function GetTracksByPosition finds the list of tracks that starts or ends at aPosition on aLayer.
PCB_LAYER_ID
A quick note on layer IDs:
const std::vector< BOARD_CONNECTED_ITEM * > AllConnectedItems()
ZONE_CONTAINER * InsertArea(int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer, int aCornerX, int aCornerY, int aHatch)
Add a copper area to net, inserting after m_ZoneDescriptorList[aAreaIdx].
void RemoveNet(NETINFO_ITEM *aNet)
Function RemoveNet Removes a new from the net list.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:982
Class LSET is a set of PCB_LAYER_IDs.
void PopHighLight()
Function PopHighLight retrieve a previously saved high light info.
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:547
void chainMarkedSegments(TRACK *aTrackList, wxPoint aPosition, const LSET &aLayerSet, TRACKS *aList)
Function chainMarkedSegments is used by MarkTrace() to set the BUSY flag of connected segments of the...
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:252
bool NormalizeAreaPolygon(PICKED_ITEMS_LIST *aNewZonesList, ZONE_CONTAINER *aCurrArea)
Function NormalizeAreaPolygon Process an area that has been modified, by normalizing its polygon agai...
unsigned GetNodesCount(int aNet=-1)
Function GetNodesCount.
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:778
void DeleteMARKERs()
Function DeleteMARKERs deletes ALL MARKERS from the board.
ZONE_CONTAINER * AddArea(PICKED_ITEMS_LIST *aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch)
Function AddArea Add an empty copper area to board areas list.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:218
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:37
virtual void Move(const wxPoint &aMoveVector)
Function Move move this object.
Class SHAPE_POLY_SET.
void SetVisibleLayers(LSET aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
#define IS_DELETED
Definition: base_struct.h:117
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
Definition: page_info.h:54
bool sortPadsByXthenYCoord(D_PAD *const &ref, D_PAD *const &comp)
Function SortPadsByXCoord is used by GetSortedPadListByXCoord to Sort a pad list by x coordinate valu...
LAYER_T
Enum LAYER_T gives the allowed types of layers, same as Specctra DSN spec.
Definition: class_board.h:72
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:409
unsigned GetUnconnectedNetCount() const
Function GetUnconnectedNetCount.
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Function SetLayerName changes the name of the layer given by aLayer.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:293
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Function SetLayerDescr returns the type of the copper layer given by aLayer.
int SortedNetnamesList(wxArrayString &aNames, bool aSortbyPadsCount)
Function SortedNetnamesList.
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Function SetLayer sets the layer this item is on.
Definition: class_zone.cpp:212
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:239
ENDPOINT_T
Definition: class_track.h:50
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:244
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
Definition: colors.h:60
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
void SetPosition(const wxPoint &) override
Definition: class_board.cpp:87
#define THROW_IO_ERROR(msg)
int SetAreasNetCodesFromNetNames(void)
Function SetAreasNetCodesFromNetNames Set the .m_NetCode member of all copper areas,...
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines,...
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
MARKERS m_markers
MARKER_PCBs for clearance problems, owned by pointer.
Definition: class_board.h:179
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:66
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance, wxPoint *aErrorLocation=nullptr)
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
static LAYER_T ParseType(const char *aType)
Function ParseType converts a string to a LAYER_T.
void SetItem(EDA_ITEM *aItem)
int GetVisibleElements() const
Function GetVisibleElements is a proxy function that calls the correspondent function in m_BoardSetti...
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:98
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:267
unsigned GetPadCount()
Function GetPadCount.
void SetCustomTrackWidth(int aWidth)
Function SetCustomTrackWidth Sets custom width for track (i.e.
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
int GetHeight() const
Definition: eda_rect.h:118
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:99
MODULE * FindModule(const wxString &aRefOrTimeStamp, bool aSearchByTimeStamp=false) const
Function FindModule searches for a module matching aRefOrTimeStamp depending on the state of aSearchB...
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:473
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
static bool sortNetsByNames(const NETINFO_ITEM *a, const NETINFO_ITEM *b)
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:107
TRACKS TracksInNet(int aNetCode)
Function TrackInNet collects all the TRACKs and VIAs that are members of a net given by aNetCode.
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Function IsElementVisible tests whether a given element category is visible.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
Definition: seg.h:36
wxString GetSelectMenuText(EDA_UNITS_T aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: class_board.cpp:75
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
void Move(const wxPoint &aMoveVector) override
Function Move move this object.
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
int GetCurrentViaSize() const
Function GetCurrentViaSize.
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
TRACK * GetBestInsertPoint(BOARD *aPcb)
Function GetBestInsertPoint searches the "best" insertion point within the track linked list.
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:97
LSET GetVisibleLayers() const
Function GetVisibleLayers returns a bit-mask of all the layers that are visible.
ZONE_CONTAINERS & Zones()
Definition: class_board.h:254
BOARD_ITEM * GetItem(void *aWeakReference)
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
int GetVisibleElements() const
Function GetVisibleElements returns a bit-mask of all the element categories that are visible.
void SetState(int type, int state)
Definition: base_struct.h:247
TRACK * Next() const
Definition: class_track.h:110
void UnHatch()
Function UnHatch clears the zone's hatch.
SHAPE_POLY_SET UnitSet(int aPolygonIndex)
Class to handle a graphic segment.
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:205
NETCLASSPTR GetDefault() const
Function GetDefault.
int m_fileFormatVersionAtLoad
the version loaded from the file
Definition: class_board.h:190
static NETINFO_ITEM ORPHANED_ITEM
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:477
int GetNet() const
Function GetNet.
Definition: netinfo.h:231
#define max(a, b)
Definition: auxiliary.h:86
Class LAYER holds information pertinent to a layer of a BOARD.
Definition: class_board.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
LSET GetEnabledLayers() const
Function GetEnabledLayers returns a bit-mask of all the layers that are enabled.
DLIST< MODULE > m_Modules
Definition: class_board.h:248
void RedrawFilledAreas(EDA_DRAW_PANEL *aPanel, wxDC *aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer)
Function RedrawFilledAreas Redraw all filled areas on layer aLayer ( redraw all if aLayer < 0 )
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:123
ZONE_CONTAINERS m_ZoneDescriptorList
edge zone descriptors, owned by pointer.
Definition: class_board.h:182
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:102
size_t i
Definition: json11.cpp:597
int GetCopperLayerCount() const
Function GetCopperLayerCount.
void SanitizeNetcodes()
LAYER m_Layer[PCB_LAYER_ID_COUNT]
Definition: class_board.h:184
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: class_board.h:192
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone's...
int GetY() const
Definition: eda_rect.h:110
void PushHighLight()
Function PushHighLight save current high light info for later use.
void SetHatchStyle(HATCH_STYLE aStyle)
Definition: class_zone.h:552
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:156
static bool sortNetsByNodes(const NETINFO_ITEM *a, const NETINFO_ITEM *b)
void SetLocalFlags(int aFlags)
Definition: class_zone.h:255
The common library.
bool IsModuleLayerVisible(PCB_LAYER_ID aLayer)
Function IsModuleLayerVisible expects either of the two layers on which a module can reside,...
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
wxString GetClass() const override
Function GetClass returns the class name.
Definition: class_board.h:889
void SetElementVisibility(GAL_LAYER_ID aElementCategory, bool aNewState)
Function SetElementVisibility changes the visibility of an element category.
const wxPoint & GetEnd() const
Definition: class_track.h:130
#define FIRST_COPPER_LAYER
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
Class COLORS_DESIGN_SETTINGS is a list of color settings for designs in Pcbnew.
unsigned GetNetCount() const
Function GetNetCount.
Definition: netinfo.h:442
MODULE * Next() const
Definition: class_module.h:122
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
virtual void Delete(BOARD_ITEM *aItem)
Removes an item from the containter and deletes it.
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
virtual const wxPoint GetCenter() const
Function GetCenter()
void SetStart(const wxPoint &aStart)
Definition: class_track.h:132
PCB_TARGET class definition.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
VIA * GetViaByPosition(const wxPoint &aPosition, PCB_LAYER_ID aLayer=PCB_LAYER_ID(-1)) const
Function GetViaByPosition finds the first via at aPosition on aLayer.
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:251
void RedrawAreasOutlines(EDA_DRAW_PANEL *aPanel, wxDC *aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer)
Function RedrawAreasOutlines Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
DLIST< TRACK > m_Track
Definition: class_board.h:249
BOARD_DESIGN_SETTINGS m_designSettings
Definition: class_board.h:194
Module description (excepted pads)
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:953
Abstract interface for BOARD_ITEMs capable of storing other items inside.
static void checkConnectedTo(BOARD *aBoard, TRACKS *aList, const TRACKS &aTracksInNet, const wxPoint &aGoal, const wxPoint &aStart, TRACK *aFirstTrack)
Function checkConnectedTo returns if aTracksInNet contains a copper pathway to aGoal when starting wi...
Class EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
SEARCH_RESULT
Definition: base_struct.h:66
NETINFO_ITEM * GetNetItem(int aNetCode) const
Function GetItem.
const wxPoint GetPosition() const override
Definition: class_pad.h:220
TRACK * MarkTrace(TRACK *aTrackList, TRACK *aTrace, int *aCount, double *aTraceLength, double *aInPackageLength, bool aReorder)
Function MarkTrace marks a chain of trace segments, connected to aTrace.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
Message panel definition file.
bool IsSelfIntersecting()
Function IsSelfIntersecting Checks whether any of the polygons in the set is self intersecting.
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: class_track.h:137
MODULE * GetFootprint(const wxPoint &aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly, bool aIgnoreLocked=false)
Function GetFootprint get a footprint by its bounding rectangle at aPosition on aLayer.
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
BOARD_CONNECTED_ITEM * end
Definition: class_track.h:102
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:469
int GetCopperLayerCount() const
Function GetCopperLayerCount.
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
int GetState(int type) const
Definition: base_struct.h:242
BOARD_CONNECTED_ITEM * start
Definition: class_track.h:101
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:191
void ClearAllNetCodes()
Function ClearAllNetCodes() Resets all items' netcodes to 0 (no net).
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:813
void SetEnabledLayers(LSET aLayerMask)
Function SetEnabledLayers is a proxy function that calls the correspondent function in m_BoardSetting...
#define mod(a, n)
Definition: greymap.cpp:24
void Remove(BOARD_ITEM *aBoardItem) override
Removes an item from the container.
EDA_UNITS_T
Definition: common.h:157
std::string FormatInternalUnits(int aValue)
Function FormatInternalUnits converts aValue from internal units to a string appropriate for writing ...
Definition: base_units.cpp:457
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:253
void UseCustomTrackViaSize(bool aEnabled)
Function UseCustomTrackViaSize Enables/disables custom track/via size settings.
void Insert(T *aNewElement, T *aElementAfterMe)
Function Insert puts aNewElement just in front of aElementAfterMe in the list sequence.
Definition: dlist.h:200
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
KICAD_T Type() const
Function Type()
Definition: base_struct.h:203
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Function GetStandardLayerName returns an "English Standard" name of a PCB layer when given aLayerNumb...
Definition: class_board.h:655
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:208
TRACK * GetFirstTrack(TRACK *aTrk, const TRACK *aStopPoint=NULL)
Scan a track list for the first TRACK object. Returns NULL if not found (or NULL passed)
Definition: class_track.h:506
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:240
BOARD_ITEM * Duplicate(const BOARD_ITEM *aItem, bool aAddToBoard=false)
bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item.
VIA * GetFirstVia(TRACK *aTrk, const TRACK *aStopPoint=NULL)
Scan a track list for the first VIA o NULL if not found (or NULL passed)
Definition: class_track.h:492