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-2018 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  BOARD_ITEM::FormatInternalUnits( next ).c_str(),
344  BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
345  BOARD_ITEM::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  BOARD_ITEM::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  BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
371  BOARD_ITEM::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  BOARD_ITEM::FormatInternalUnits( aStartPos ).c_str(),
416  BOARD_ITEM::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 ) < DIM( 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_SEGZONE_T:
907  if( aMode == ADD_APPEND )
908  m_SegZoneDeprecated.PushBack( (SEGZONE*) aBoardItem );
909  else
910  m_SegZoneDeprecated.PushFront( (SEGZONE*) aBoardItem );
911 
912  break;
913 
914  case PCB_MODULE_T:
915  if( aMode == ADD_APPEND )
916  m_Modules.PushBack( (MODULE*) aBoardItem );
917  else
918  m_Modules.PushFront( (MODULE*) aBoardItem );
919 
920  // Because the list of pads has changed, reset the status
921  // This indicate the list of pad and nets must be recalculated before use
922  m_Status_Pcb = 0;
923  break;
924 
925  case PCB_DIMENSION_T:
926  case PCB_LINE_T:
927  case PCB_TEXT_T:
928  case PCB_TARGET_T:
929  if( aMode == ADD_APPEND )
930  m_Drawings.PushBack( aBoardItem );
931  else
932  m_Drawings.PushFront( aBoardItem );
933 
934  break;
935 
936  // other types may use linked list
937  default:
938  {
939  wxString msg;
940  msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
941  aBoardItem->Type() );
942  wxFAIL_MSG( msg );
943  return;
944  }
945  break;
946  }
947 
948  aBoardItem->SetParent( this );
949  m_connectivity->Add( aBoardItem );
950 }
951 
952 
953 void BOARD::Remove( BOARD_ITEM* aBoardItem )
954 {
955  // find these calls and fix them! Don't send me no stinking' NULL.
956  wxASSERT( aBoardItem );
957 
958  switch( aBoardItem->Type() )
959  {
960  case PCB_NETINFO_T:
961  {
962  NETINFO_ITEM* item = (NETINFO_ITEM*) aBoardItem;
963  m_NetInfo.RemoveNet( item );
964  break;
965  }
966 
967  case PCB_MARKER_T:
968 
969  // find the item in the vector, then remove it
970  for( unsigned i = 0; i<m_markers.size(); ++i )
971  {
972  if( m_markers[i] == (MARKER_PCB*) aBoardItem )
973  {
974  m_markers.erase( m_markers.begin() + i );
975  break;
976  }
977  }
978 
979  break;
980 
981  case PCB_ZONE_AREA_T: // this one uses a vector
982  // find the item in the vector, then delete then erase it.
983  for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
984  {
985  if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
986  {
987  m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
988  break;
989  }
990  }
991  break;
992 
993  case PCB_MODULE_T:
994  m_Modules.Remove( (MODULE*) aBoardItem );
995  break;
996 
997  case PCB_TRACE_T:
998  case PCB_VIA_T:
999  m_Track.Remove( (TRACK*) aBoardItem );
1000  break;
1001 
1002  case PCB_SEGZONE_T:
1003  m_SegZoneDeprecated.Remove( (SEGZONE*) aBoardItem );
1004  break;
1005 
1006  case PCB_DIMENSION_T:
1007  case PCB_LINE_T:
1008  case PCB_TEXT_T:
1009  case PCB_TARGET_T:
1010  m_Drawings.Remove( aBoardItem );
1011  break;
1012 
1013  // other types may use linked list
1014  default:
1015  wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
1016  }
1017 
1018  m_connectivity->Remove( aBoardItem );
1019 }
1020 
1021 
1022 wxString BOARD::GetSelectMenuText( EDA_UNITS_T aUnits ) const
1023 {
1024  return wxString::Format( _( "PCB" ) );
1025 }
1026 
1027 
1029 {
1030  // the vector does not know how to delete the MARKER_PCB, it holds pointers
1031  for( MARKER_PCB* marker : m_markers )
1032  delete marker;
1033 
1034  m_markers.clear();
1035 }
1036 
1037 
1039 {
1040  // the vector does not know how to delete the ZONE Outlines, it holds pointers
1041  for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
1042  delete zone;
1043 
1044  m_ZoneDescriptorList.clear();
1045 }
1046 
1047 
1048 BOARD_ITEM* BOARD::GetItem( void* aWeakReference )
1049 {
1050  for( TRACK* track : Tracks() )
1051  if( track == aWeakReference )
1052  return track;
1053 
1054  for( MODULE* module : Modules() )
1055  {
1056  if( module == aWeakReference )
1057  return module;
1058 
1059  for( D_PAD* pad : module->Pads() )
1060  if( pad == aWeakReference )
1061  return pad;
1062 
1063  if( &module->Reference() == aWeakReference )
1064  return &module->Reference();
1065 
1066  if( &module->Value() == aWeakReference )
1067  return &module->Value();
1068 
1069  for( BOARD_ITEM* drawing : module->GraphicalItems() )
1070  if( drawing == aWeakReference )
1071  return drawing;
1072  }
1073 
1074  for( ZONE_CONTAINER* zone : Zones() )
1075  if( zone == aWeakReference )
1076  return zone;
1077 
1078  for( BOARD_ITEM* drawing : Drawings() )
1079  if( drawing == aWeakReference )
1080  return drawing;
1081 
1082  // Not found; weak reference has been deleted.
1083  return &g_DeletedItem;
1084 }
1085 
1086 
1088 {
1089  return m_Track.GetCount();
1090 }
1091 
1092 
1094 {
1095  return m_SegZoneDeprecated.GetCount();
1096 }
1097 
1098 
1099 unsigned BOARD::GetNodesCount( int aNet )
1100 {
1101  unsigned retval = 0;
1102  for( auto mod : Modules() )
1103  {
1104  for( auto pad : mod->Pads() )
1105  {
1106  if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1107  retval++;
1108  }
1109  }
1110 
1111  return retval;
1112 }
1113 
1114 
1116 {
1117  return m_connectivity->GetUnconnectedCount();
1118 }
1119 
1120 
1121 EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1122 {
1123  bool hasItems = false;
1124  EDA_RECT area;
1125 
1126  // Check segments, dimensions, texts, and fiducials
1127  for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
1128  {
1129  if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) )
1130  continue;
1131 
1132  if( !hasItems )
1133  area = item->GetBoundingBox();
1134  else
1135  area.Merge( item->GetBoundingBox() );
1136 
1137  hasItems = true;
1138  }
1139 
1140  if( !aBoardEdgesOnly )
1141  {
1142  // Check modules
1143  for( MODULE* module = m_Modules; module; module = module->Next() )
1144  {
1145  if( !hasItems )
1146  area = module->GetBoundingBox();
1147  else
1148  area.Merge( module->GetBoundingBox() );
1149 
1150  hasItems = true;
1151  }
1152 
1153  // Check tracks
1154  for( TRACK* track = m_Track; track; track = track->Next() )
1155  {
1156  if( !hasItems )
1157  area = track->GetBoundingBox();
1158  else
1159  area.Merge( track->GetBoundingBox() );
1160 
1161  hasItems = true;
1162  }
1163 
1164  // Check segment zones
1165  for( TRACK* track = m_SegZoneDeprecated; track; track = track->Next() )
1166  {
1167  if( !hasItems )
1168  area = track->GetBoundingBox();
1169  else
1170  area.Merge( track->GetBoundingBox() );
1171 
1172  hasItems = true;
1173  }
1174 
1175  // Check polygonal zones
1176  for( auto aZone : m_ZoneDescriptorList )
1177  {
1178  if( !hasItems )
1179  area = aZone->GetBoundingBox();
1180  else
1181  area.Merge( aZone->GetBoundingBox() );
1182 
1183  area.Merge( aZone->GetBoundingBox() );
1184  hasItems = true;
1185  }
1186  }
1187 
1188  return area;
1189 }
1190 
1191 
1192 void BOARD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
1193 {
1194  wxString txt;
1195  int viasCount = 0;
1196  int trackSegmentsCount = 0;
1197 
1198  for( BOARD_ITEM* item = m_Track; item; item = item->Next() )
1199  {
1200  if( item->Type() == PCB_VIA_T )
1201  viasCount++;
1202  else
1203  trackSegmentsCount++;
1204  }
1205 
1206  txt.Printf( wxT( "%d" ), GetPadCount() );
1207  aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );
1208 
1209  txt.Printf( wxT( "%d" ), viasCount );
1210  aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, DARKGREEN ) );
1211 
1212  txt.Printf( wxT( "%d" ), trackSegmentsCount );
1213  aList.push_back( MSG_PANEL_ITEM( _( "Track Segments" ), txt, DARKGREEN ) );
1214 
1215  txt.Printf( wxT( "%d" ), GetNodesCount() );
1216  aList.push_back( MSG_PANEL_ITEM( _( "Nodes" ), txt, DARKCYAN ) );
1217 
1218  txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() - 1 /* Don't include "No Net" in count */ );
1219  aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
1220 
1221  txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
1222  aList.push_back( MSG_PANEL_ITEM( _( "Unrouted" ), txt, BLUE ) );
1223 }
1224 
1225 
1226 SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1227 {
1228  KICAD_T stype;
1229  SEARCH_RESULT result = SEARCH_CONTINUE;
1230  const KICAD_T* p = scanTypes;
1231  bool done = false;
1232 
1233 #if 0 && defined(DEBUG)
1234  std::cout << GetClass().mb_str() << ' ';
1235 #endif
1236 
1237  while( !done )
1238  {
1239  stype = *p;
1240 
1241  switch( stype )
1242  {
1243  case PCB_T:
1244  result = inspector( this, testData ); // inspect me
1245  // skip over any types handled in the above call.
1246  ++p;
1247  break;
1248 
1249  /* Instances of the requested KICAD_T live in a list, either one
1250  * that I manage, or that my modules manage. If it's a type managed
1251  * by class MODULE, then simply pass it on to each module's
1252  * MODULE::Visit() function by way of the
1253  * IterateForward( m_Modules, ... ) call.
1254  */
1255 
1256  case PCB_MODULE_T:
1257  case PCB_PAD_T:
1258  case PCB_MODULE_TEXT_T:
1259  case PCB_MODULE_EDGE_T:
1260 
1261  // this calls MODULE::Visit() on each module.
1262  result = IterateForward( m_Modules, inspector, testData, p );
1263 
1264  // skip over any types handled in the above call.
1265  for( ; ; )
1266  {
1267  switch( stype = *++p )
1268  {
1269  case PCB_MODULE_T:
1270  case PCB_PAD_T:
1271  case PCB_MODULE_TEXT_T:
1272  case PCB_MODULE_EDGE_T:
1273  continue;
1274 
1275  default:
1276  ;
1277  }
1278 
1279  break;
1280  }
1281 
1282  break;
1283 
1284  case PCB_LINE_T:
1285  case PCB_TEXT_T:
1286  case PCB_DIMENSION_T:
1287  case PCB_TARGET_T:
1288  result = IterateForward( m_Drawings, inspector, testData, p );
1289 
1290  // skip over any types handled in the above call.
1291  for( ; ; )
1292  {
1293  switch( stype = *++p )
1294  {
1295  case PCB_LINE_T:
1296  case PCB_TEXT_T:
1297  case PCB_DIMENSION_T:
1298  case PCB_TARGET_T:
1299  continue;
1300 
1301  default:
1302  ;
1303  }
1304 
1305  break;
1306  }
1307 
1308  ;
1309  break;
1310 
1311 #if 0 // both these are on same list, so we must scan it twice in order
1312  // to get VIA priority, using new #else code below.
1313  // But we are not using separate lists for TRACKs and VIA, because
1314  // items are ordered (sorted) in the linked
1315  // list by netcode AND by physical distance:
1316  // when created, if a track or via is connected to an existing track or
1317  // via, it is put in linked list after this existing track or via
1318  // So usually, connected tracks or vias are grouped in this list
1319  // So the algorithm (used in ratsnest computations) which computes the
1320  // track connectivity is faster (more than 100 time regarding to
1321  // a non ordered list) because when it searches for a connection, first
1322  // it tests the near (near in term of linked list) 50 items
1323  // from the current item (track or via) in test.
1324  // Usually, because of this sort, a connected item (if exists) is
1325  // found.
1326  // If not found (and only in this case) an exhaustive (and time
1327  // consuming) search is made, but this case is statistically rare.
1328  case PCB_VIA_T:
1329  case PCB_TRACE_T:
1330  result = IterateForward( m_Track, inspector, testData, p );
1331 
1332  // skip over any types handled in the above call.
1333  for( ; ; )
1334  {
1335  switch( stype = *++p )
1336  {
1337  case PCB_VIA_T:
1338  case PCB_TRACE_T:
1339  continue;
1340 
1341  default:
1342  ;
1343  }
1344 
1345  break;
1346  }
1347 
1348  break;
1349 
1350 #else
1351  case PCB_VIA_T:
1352  result = IterateForward( m_Track, inspector, testData, p );
1353  ++p;
1354  break;
1355 
1356  case PCB_TRACE_T:
1357  result = IterateForward( m_Track, inspector, testData, p );
1358  ++p;
1359  break;
1360 #endif
1361 
1362  case PCB_MARKER_T:
1363 
1364  // MARKER_PCBS are in the m_markers std::vector
1365  for( unsigned i = 0; i<m_markers.size(); ++i )
1366  {
1367  result = m_markers[i]->Visit( inspector, testData, p );
1368 
1369  if( result == SEARCH_QUIT )
1370  break;
1371  }
1372 
1373  ++p;
1374  break;
1375 
1376  case PCB_ZONE_AREA_T:
1377 
1378  // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
1379  for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
1380  {
1381  result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
1382 
1383  if( result == SEARCH_QUIT )
1384  break;
1385  }
1386 
1387  ++p;
1388  break;
1389 
1390  case PCB_SEGZONE_T:
1391  result = IterateForward( m_SegZoneDeprecated, inspector, testData, p );
1392  ++p;
1393  break;
1394 
1395  default: // catch EOT or ANY OTHER type here and return.
1396  done = true;
1397  break;
1398  }
1399 
1400  if( result == SEARCH_QUIT )
1401  break;
1402  }
1403 
1404  return result;
1405 }
1406 
1407 
1408 NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1409 {
1410  // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1411  // zero is reserved for "no connection" and is not actually a net.
1412  // NULL is returned for non valid netcodes
1413 
1414  wxASSERT( m_NetInfo.GetNetCount() > 0 );
1415 
1416  if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1418  else
1419  return m_NetInfo.GetNetItem( aNetcode );
1420 }
1421 
1422 
1423 NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1424 {
1425  return m_NetInfo.GetNetItem( aNetname );
1426 }
1427 
1428 
1429 MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
1430 {
1431  MODULE* found = nullptr;
1432 
1433  // search only for MODULES
1434  static const KICAD_T scanTypes[] = { PCB_MODULE_T, EOT };
1435 
1436  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
1437  {
1438  MODULE* module = (MODULE*) item;
1439 
1440  if( aReference == module->GetReference() )
1441  {
1442  found = module;
1443  return SEARCH_QUIT;
1444  }
1445 
1446  return SEARCH_CONTINUE;
1447  };
1448 
1449  // visit this BOARD with the above inspector
1450  BOARD* nonconstMe = (BOARD*) this;
1451  nonconstMe->Visit( inspector, NULL, scanTypes );
1452 
1453  return found;
1454 }
1455 
1456 
1457 MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeStamp ) const
1458 {
1459  if( aSearchByTimeStamp )
1460  {
1461  for( MODULE* module = m_Modules; module; module = module->Next() )
1462  {
1463  if( aRefOrTimeStamp.CmpNoCase( module->GetPath() ) == 0 )
1464  return module;
1465  }
1466  }
1467  else
1468  {
1469  return FindModuleByReference( aRefOrTimeStamp );
1470  }
1471 
1472  return NULL;
1473 }
1474 
1475 
1476 
1477 // The pad count for each netcode, stored in a buffer for a fast access.
1478 // This is needed by the sort function sortNetsByNodes()
1479 static std::vector<int> padCountListByNet;
1480 
1481 // Sort nets by decreasing pad count.
1482 // For same pad count, sort by alphabetic names
1483 static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1484 {
1485  int countA = padCountListByNet[a->GetNet()];
1486  int countB = padCountListByNet[b->GetNet()];
1487 
1488  if( countA == countB )
1489  return a->GetNetname() < b->GetNetname();
1490  else
1491  return countB < countA;
1492 }
1493 
1494 // Sort nets by alphabetic names
1495 static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1496 {
1497  return a->GetNetname() < b->GetNetname();
1498 }
1499 
1500 int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
1501 {
1502  if( m_NetInfo.GetNetCount() == 0 )
1503  return 0;
1504 
1505  // Build the list
1506  std::vector <NETINFO_ITEM*> netBuffer;
1507 
1508  netBuffer.reserve( m_NetInfo.GetNetCount() );
1509  int max_netcode = 0;
1510 
1511  for( NETINFO_ITEM* net : m_NetInfo )
1512  {
1513  auto netcode = net->GetNet();
1514 
1515  if( netcode > 0 )
1516  {
1517  netBuffer.push_back( net );
1518  max_netcode = std::max( netcode, max_netcode);
1519  }
1520  }
1521 
1522  // sort the list
1523  if( aSortbyPadsCount )
1524  {
1525  // Build the pad count by net:
1526  padCountListByNet.clear();
1527  std::vector<D_PAD*> pads = GetPads();
1528 
1529  padCountListByNet.assign( max_netcode + 1, 0 );
1530 
1531  for( D_PAD* pad : pads )
1532  padCountListByNet[pad->GetNetCode()]++;
1533 
1534  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNodes );
1535  }
1536  else
1537  {
1538  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNames );
1539  }
1540 
1541  for( NETINFO_ITEM* net : netBuffer )
1542  aNames.Add( net->GetNetname() );
1543 
1544  return netBuffer.size();
1545 }
1546 
1547 
1548 void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1549 {
1550  if( !aDC )
1551  return;
1552 
1553  for( int ii = 0; ii < GetAreaCount(); ii++ )
1554  {
1555  ZONE_CONTAINER* edge_zone = GetArea( ii );
1556 
1557  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1558  edge_zone->Draw( panel, aDC, aDrawMode );
1559  }
1560 }
1561 
1562 
1563 void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1564 {
1565  if( !aDC )
1566  return;
1567 
1568  for( int ii = 0; ii < GetAreaCount(); ii++ )
1569  {
1570  ZONE_CONTAINER* edge_zone = GetArea( ii );
1571 
1572  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1573  edge_zone->DrawFilledArea( panel, aDC, aDrawMode );
1574  }
1575 }
1576 
1577 
1579  PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer, int aNetCode )
1580 {
1581  if( aEndLayer < 0 )
1582  aEndLayer = aStartLayer;
1583 
1584  if( aEndLayer < aStartLayer )
1585  std::swap( aEndLayer, aStartLayer );
1586 
1587  for( ZONE_CONTAINER* area : m_ZoneDescriptorList )
1588  {
1589  if( area->GetLayer() < aStartLayer || area->GetLayer() > aEndLayer )
1590  continue;
1591 
1592  // In locate functions we must skip tagged items with BUSY flag set.
1593  if( area->GetState( BUSY ) )
1594  continue;
1595 
1596  if( aNetCode >= 0 && area->GetNetCode() != aNetCode )
1597  continue;
1598 
1599  if( area->HitTestFilledArea( aRefPos ) )
1600  return area;
1601  }
1602 
1603  return NULL;
1604 }
1605 
1606 
1608 {
1609  int error_count = 0;
1610 
1611  for( int ii = 0; ii < GetAreaCount(); ii++ )
1612  {
1613  ZONE_CONTAINER* it = GetArea( ii );
1614 
1615  if( !it->IsOnCopperLayer() )
1616  {
1618  continue;
1619  }
1620 
1621  if( it->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1622  {
1623  const NETINFO_ITEM* net = it->GetNet();
1624 
1625  if( net )
1626  {
1627  it->SetNetCode( net->GetNet() );
1628  }
1629  else
1630  {
1631  error_count++;
1632 
1633  // keep Net Name and set m_NetCode to -1 : error flag.
1634  it->SetNetCode( -1 );
1635  }
1636  }
1637  }
1638 
1639  return error_count;
1640 }
1641 
1642 
1643 VIA* BOARD::GetViaByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer) const
1644 {
1645  for( VIA *via = GetFirstVia( m_Track); via; via = GetFirstVia( via->Next() ) )
1646  {
1647  if( (via->GetStart() == aPosition) &&
1648  (via->GetState( BUSY | IS_DELETED ) == 0) &&
1649  ((aLayer == UNDEFINED_LAYER) || (via->IsOnLayer( aLayer ))) )
1650  return via;
1651  }
1652 
1653  return NULL;
1654 }
1655 
1656 
1657 D_PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet )
1658 {
1659  if( !aLayerSet.any() )
1660  aLayerSet = LSET::AllCuMask();
1661 
1662  for( MODULE* module = m_Modules; module; module = module->Next() )
1663  {
1664  D_PAD* pad = NULL;
1665 
1666  if( module->HitTest( aPosition ) )
1667  pad = module->GetPad( aPosition, aLayerSet );
1668 
1669  if( pad )
1670  return pad;
1671  }
1672 
1673  return NULL;
1674 }
1675 
1676 
1677 D_PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
1678 {
1679  const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
1680 
1681  LSET lset( aTrace->GetLayer() );
1682 
1683  return GetPad( aPosition, lset );
1684 }
1685 
1686 
1687 std::list<TRACK*> BOARD::GetTracksByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer ) const
1688 {
1689  std::list<TRACK*> tracks;
1690 
1691  for( TRACK* track = GetFirstTrack( m_Track ); track; track = GetFirstTrack( track->Next() ) )
1692  {
1693  if( ( ( track->GetStart() == aPosition ) || track->GetEnd() == aPosition ) &&
1694  ( track->GetState( BUSY | IS_DELETED ) == 0 ) &&
1695  ( ( aLayer == UNDEFINED_LAYER ) || ( track->IsOnLayer( aLayer ) ) ) )
1696 
1697  tracks.push_back( track );
1698  }
1699 
1700  return tracks;
1701 }
1702 
1703 
1704 D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
1705 {
1706  for( auto mod : Modules() )
1707  {
1708  for ( auto pad : mod->Pads() )
1709  {
1710  if( pad->GetPosition() != aPosition )
1711  continue;
1712 
1713  // Pad found, it must be on the correct layer
1714  if( ( pad->GetLayerSet() & aLayerSet ).any() )
1715  return pad;
1716  }
1717  }
1718 
1719  return nullptr;
1720 }
1721 
1722 
1723 D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet )
1724 {
1725  // Search aPadList for aPosition
1726  // aPadList is sorted by X then Y values, and a fast binary search is used
1727  int idxmax = aPadList.size()-1;
1728 
1729  int delta = aPadList.size();
1730 
1731  int idx = 0; // Starting index is the beginning of list
1732 
1733  while( delta )
1734  {
1735  // Calculate half size of remaining interval to test.
1736  // Ensure the computed value is not truncated (too small)
1737  if( (delta & 1) && ( delta > 1 ) )
1738  delta++;
1739 
1740  delta /= 2;
1741 
1742  D_PAD* pad = aPadList[idx];
1743 
1744  if( pad->GetPosition() == aPosition ) // candidate found
1745  {
1746  // The pad must match the layer mask:
1747  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1748  return pad;
1749 
1750  // More than one pad can be at aPosition
1751  // search for a pad at aPosition that matched this mask
1752 
1753  // search next
1754  for( int ii = idx+1; ii <= idxmax; ii++ )
1755  {
1756  pad = aPadList[ii];
1757 
1758  if( pad->GetPosition() != aPosition )
1759  break;
1760 
1761  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1762  return pad;
1763  }
1764  // search previous
1765  for( int ii = idx-1 ;ii >=0; ii-- )
1766  {
1767  pad = aPadList[ii];
1768 
1769  if( pad->GetPosition() != aPosition )
1770  break;
1771 
1772  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1773  return pad;
1774  }
1775 
1776  // Not found:
1777  return 0;
1778  }
1779 
1780  if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1781  {
1782  if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1783  {
1784  idx += delta;
1785 
1786  if( idx > idxmax )
1787  idx = idxmax;
1788  }
1789  else // Must search before this item
1790  {
1791  idx -= delta;
1792 
1793  if( idx < 0 )
1794  idx = 0;
1795  }
1796  }
1797  else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1798  {
1799  idx += delta;
1800 
1801  if( idx > idxmax )
1802  idx = idxmax;
1803  }
1804  else // Must search before this item
1805  {
1806  idx -= delta;
1807 
1808  if( idx < 0 )
1809  idx = 0;
1810  }
1811  }
1812 
1813  return NULL;
1814 }
1815 
1816 
1822 bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
1823 {
1824  if( ref->GetPosition().x == comp->GetPosition().x )
1825  return ref->GetPosition().y < comp->GetPosition().y;
1826  return ref->GetPosition().x < comp->GetPosition().x;
1827 }
1828 
1829 
1830 void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
1831 {
1832  for ( auto mod : Modules() )
1833  {
1834  for ( auto pad : mod->Pads( ) )
1835  {
1836  if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1837  {
1838  aVector.push_back( pad );
1839  }
1840  }
1841  }
1842 
1843  std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1844 }
1845 
1846 
1848 {
1849  GetConnectivity()->Remove( aPad );
1850  aPad->DeleteStructure();
1851 }
1852 
1853 
1854 TRACK* BOARD::GetVisibleTrack( TRACK* aStartingTrace, const wxPoint& aPosition,
1855  LSET aLayerSet ) const
1856 {
1857  for( TRACK* track = aStartingTrace; track; track = track->Next() )
1858  {
1859  PCB_LAYER_ID layer = track->GetLayer();
1860 
1861  if( track->GetState( BUSY | IS_DELETED ) )
1862  continue;
1863 
1864  // track's layer is not visible
1865  if( m_designSettings.IsLayerVisible( layer ) == false )
1866  continue;
1867 
1868  if( track->Type() == PCB_VIA_T ) // VIA encountered.
1869  {
1870  if( track->HitTest( aPosition ) )
1871  return track;
1872  }
1873  else
1874  {
1875  if( !aLayerSet[layer] )
1876  continue; // track's layer is not in aLayerSet
1877 
1878  if( track->HitTest( aPosition ) )
1879  return track;
1880  }
1881  }
1882 
1883  return NULL;
1884 }
1885 
1886 
1887 TRACK* BOARD::MarkTrace( TRACK* aTrackList, TRACK* aTrace, int* aCount,
1888  double* aTraceLength, double* aPadToDieLength,
1889  bool aReorder )
1890 {
1891  TRACKS trackList;
1892 
1893  if( aCount )
1894  *aCount = 0;
1895 
1896  if( aTraceLength )
1897  *aTraceLength = 0;
1898 
1899  if( aTrace == NULL )
1900  return NULL;
1901 
1902  // Ensure the flag BUSY of all tracks of the board is cleared
1903  // because we use it to mark segments of the track
1904  for( TRACK* track = aTrackList; track; track = track->Next() )
1905  track->SetState( BUSY, false );
1906 
1907  // Set flags of the initial track segment
1908  aTrace->SetState( BUSY, true );
1909  LSET layer_set = aTrace->GetLayerSet();
1910 
1911  trackList.push_back( aTrace );
1912 
1913  /* Examine the initial track segment : if it is really a segment, this is
1914  * easy.
1915  * If it is a via, one must search for connected segments.
1916  * If <=2, this via connect 2 segments (or is connected to only one
1917  * segment) and this via and these 2 segments are a part of a track.
1918  * If > 2 only this via is flagged (the track has only this via)
1919  */
1920  if( aTrace->Type() == PCB_VIA_T )
1921  {
1922  TRACK* segm1 = ::GetTrack( aTrackList, NULL, aTrace->GetStart(), layer_set );
1923  TRACK* segm2 = NULL;
1924  TRACK* segm3 = NULL;
1925 
1926  if( segm1 )
1927  {
1928  segm2 = ::GetTrack( segm1->Next(), NULL, aTrace->GetStart(), layer_set );
1929  }
1930 
1931  if( segm2 )
1932  {
1933  segm3 = ::GetTrack( segm2->Next(), NULL, aTrace->GetStart(), layer_set );
1934  }
1935 
1936  if( segm3 )
1937  {
1938  // More than 2 segments are connected to this via.
1939  // The "track" is only this via.
1940 
1941  if( aCount )
1942  *aCount = 1;
1943 
1944  return aTrace;
1945  }
1946 
1947  if( segm1 ) // search for other segments connected to the initial segment start point
1948  {
1949  layer_set = segm1->GetLayerSet();
1950  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1951  }
1952 
1953  if( segm2 ) // search for other segments connected to the initial segment end point
1954  {
1955  layer_set = segm2->GetLayerSet();
1956  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1957  }
1958  }
1959  else // mark the chain using both ends of the initial segment
1960  {
1961  TRACKS from_start;
1962  TRACKS from_end;
1963 
1964  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &from_start );
1965  chainMarkedSegments( aTrackList, aTrace->GetEnd(), layer_set, &from_end );
1966 
1967  // combine into one trackList:
1968  trackList.insert( trackList.end(), from_start.begin(), from_start.end() );
1969  trackList.insert( trackList.end(), from_end.begin(), from_end.end() );
1970  }
1971 
1972  // Now examine selected vias and flag them if they are on the track
1973  // If a via is connected to only one or 2 segments, it is flagged (is on the track)
1974  // If a via is connected to more than 2 segments, it is a track end, and it
1975  // is removed from the list.
1976  // Go through the list backwards.
1977  for( int i = trackList.size() - 1; i>=0; --i )
1978  {
1979  ::VIA* via = dynamic_cast< ::VIA* >( trackList[i] );
1980 
1981  if( !via )
1982  continue;
1983 
1984  if( via == aTrace )
1985  continue;
1986 
1987  via->SetState( BUSY, true ); // Try to flag it. the flag will be cleared later if needed
1988 
1989  layer_set = via->GetLayerSet();
1990 
1991  TRACK* track = ::GetTrack( aTrackList, NULL, via->GetStart(), layer_set );
1992 
1993  // GetTrace does not consider tracks flagged BUSY.
1994  // So if no connected track found, this via is on the current track
1995  // only: keep it
1996  if( track == NULL )
1997  continue;
1998 
1999  /* If a track is found, this via connects also other segments of
2000  * the other track. This case happens when a via ends the selected
2001  * track but must we consider this via is on the selected track, or
2002  * on a other track.
2003  * (this is important when selecting a track for deletion: must this
2004  * via be deleted or not?)
2005  * We consider this via to be on our track if other segments connected
2006  * to this via remain connected when removing this via.
2007  * We search for all other segments connected together:
2008  * if they are on the same layer, then the via is on the selected track;
2009  * if they are on different layers, the via is on a other track.
2010  */
2011  LAYER_NUM layer = track->GetLayer();
2012 
2013  while( ( track = ::GetTrack( track->Next(), NULL, via->GetStart(), layer_set ) ) != NULL )
2014  {
2015  if( layer != track->GetLayer() )
2016  {
2017  // The via connects segments of a other track: it is removed
2018  // from list because it is member of a other track
2019  via->SetState( BUSY, false );
2020  break;
2021  }
2022  }
2023  }
2024 
2025  /* Rearrange the track list in order to have flagged segments linked
2026  * from firstTrack so the NbSegmBusy segments are consecutive segments
2027  * in list, the first item in the full track list is firstTrack, and
2028  * the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
2029  * are the flagged segments
2030  */
2031  int busy_count = 0;
2032  TRACK* firstTrack;
2033 
2034  for( firstTrack = aTrackList; firstTrack; firstTrack = firstTrack->Next() )
2035  {
2036  // Search for the first flagged BUSY segments
2037  if( firstTrack->GetState( BUSY ) )
2038  {
2039  busy_count = 1;
2040  break;
2041  }
2042  }
2043 
2044  if( firstTrack == NULL )
2045  return NULL;
2046 
2047  // First step: calculate the track length and find the pads (when exist)
2048  // at each end of the trace.
2049  double full_len = 0;
2050  double lenPadToDie = 0;
2051  // Because we have a track (a set of track segments between 2 nodes),
2052  // only 2 pads (maximum) will be taken in account:
2053  // that are on each end of the track, if any.
2054  // keep trace of them, to know the die length and the track length ibside each pad.
2055  D_PAD* s_pad = NULL; // the pad on one end of the trace
2056  D_PAD* e_pad = NULL; // the pad on the other end of the trace
2057  int dist_fromstart = INT_MAX;
2058  int dist_fromend = INT_MAX;
2059 
2060  for( TRACK* track = firstTrack; track; track = track->Next() )
2061  {
2062  if( !track->GetState( BUSY ) )
2063  continue;
2064 
2065  layer_set = track->GetLayerSet();
2066  D_PAD * pad_on_start = GetPad( track->GetStart(), layer_set );
2067  D_PAD * pad_on_end = GetPad( track->GetEnd(), layer_set );
2068 
2069  // a segment fully inside a pad does not contribute to the track len
2070  // (another track end inside this pad will contribute to this lenght)
2071  if( pad_on_start && ( pad_on_start == pad_on_end ) )
2072  continue;
2073 
2074  full_len += track->GetLength();
2075 
2076  if( pad_on_start == NULL && pad_on_end == NULL )
2077  // This most of time the case
2078  continue;
2079 
2080  // At this point, we can have one track end on a pad, or the 2 track ends on
2081  // 2 different pads.
2082  // We don't know what pad (s_pad or e_pad) must be used to store the
2083  // start point and the end point of the track, so if a pad is already set,
2084  // use the other
2085  if( pad_on_start )
2086  {
2087  SEG segm( track->GetStart(), pad_on_start->GetPosition() );
2088  int dist = segm.Length();
2089 
2090  if( s_pad == NULL )
2091  {
2092  dist_fromstart = dist;
2093  s_pad = pad_on_start;
2094  }
2095  else if( e_pad == NULL )
2096  {
2097  dist_fromend = dist;
2098  e_pad = pad_on_start;
2099  }
2100  else // Should not occur, at least for basic pads
2101  {
2102  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_start" );
2103  }
2104  }
2105 
2106  if( pad_on_end )
2107  {
2108  SEG segm( track->GetEnd(), pad_on_end->GetPosition() );
2109  int dist = segm.Length();
2110 
2111  if( s_pad == NULL )
2112  {
2113  dist_fromstart = dist;
2114  s_pad = pad_on_end;
2115  }
2116  else if( e_pad == NULL )
2117  {
2118  dist_fromend = dist;
2119  e_pad = pad_on_end;
2120  }
2121  else // Should not occur, at least for basic pads
2122  {
2123  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_end" );
2124  }
2125  }
2126  }
2127 
2128  if( aReorder )
2129  {
2130  DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
2131  wxASSERT( list );
2132 
2133  /* Rearrange the chain starting at firstTrack
2134  * All other BUSY flagged items are moved from their position to the end
2135  * of the flagged list
2136  */
2137  TRACK* next;
2138 
2139  for( TRACK* track = firstTrack->Next(); track; track = next )
2140  {
2141  next = track->Next();
2142 
2143  if( track->GetState( BUSY ) ) // move it!
2144  {
2145  busy_count++;
2146  track->UnLink();
2147  list->Insert( track, firstTrack->Next() );
2148 
2149  }
2150  }
2151  }
2152  else if( aTraceLength )
2153  {
2154  busy_count = 0;
2155 
2156  for( TRACK* track = firstTrack; track; track = track->Next() )
2157  {
2158  if( track->GetState( BUSY ) )
2159  {
2160  busy_count++;
2161  track->SetState( BUSY, false );
2162  }
2163  }
2164  }
2165 
2166  if( s_pad )
2167  {
2168  full_len += dist_fromstart;
2169  lenPadToDie += (double) s_pad->GetPadToDieLength();
2170  }
2171 
2172  if( e_pad )
2173  {
2174  full_len += dist_fromend;
2175  lenPadToDie += (double) e_pad->GetPadToDieLength();
2176  }
2177 
2178  if( aTraceLength )
2179  *aTraceLength = full_len;
2180 
2181  if( aPadToDieLength )
2182  *aPadToDieLength = lenPadToDie;
2183 
2184  if( aCount )
2185  *aCount = busy_count;
2186 
2187  return firstTrack;
2188 }
2189 
2190 
2191 MODULE* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
2192  bool aVisibleOnly, bool aIgnoreLocked )
2193 {
2194  MODULE* pt_module;
2195  MODULE* module = NULL;
2196  MODULE* alt_module = NULL;
2197  int min_dim = 0x7FFFFFFF;
2198  int alt_min_dim = 0x7FFFFFFF;
2199  bool current_layer_back = IsBackLayer( aActiveLayer );
2200 
2201  for( pt_module = m_Modules; pt_module; pt_module = pt_module->Next() )
2202  {
2203  // is the ref point within the module's bounds?
2204  if( !pt_module->HitTest( aPosition ) )
2205  continue;
2206 
2207  // if caller wants to ignore locked modules, and this one is locked, skip it.
2208  if( aIgnoreLocked && pt_module->IsLocked() )
2209  continue;
2210 
2211  PCB_LAYER_ID layer = pt_module->GetLayer();
2212 
2213  // Filter non visible modules if requested
2214  if( !aVisibleOnly || IsModuleLayerVisible( layer ) )
2215  {
2216  EDA_RECT bb = pt_module->GetFootprintRect();
2217 
2218  int offx = bb.GetX() + bb.GetWidth() / 2;
2219  int offy = bb.GetY() + bb.GetHeight() / 2;
2220 
2221  // off x & offy point to the middle of the box.
2222  int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2223  ( aPosition.y - offy ) * ( aPosition.y - offy );
2224 
2225  if( current_layer_back == IsBackLayer( layer ) )
2226  {
2227  if( dist <= min_dim )
2228  {
2229  // better footprint shown on the active side
2230  module = pt_module;
2231  min_dim = dist;
2232  }
2233  }
2234  else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
2235  {
2236  if( dist <= alt_min_dim )
2237  {
2238  // better footprint shown on the other side
2239  alt_module = pt_module;
2240  alt_min_dim = dist;
2241  }
2242  }
2243  }
2244  }
2245 
2246  if( module )
2247  {
2248  return module;
2249  }
2250 
2251  if( alt_module)
2252  {
2253  return alt_module;
2254  }
2255 
2256  return NULL;
2257 }
2258 
2259 
2260 BOARD_CONNECTED_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, LSET aLayerSet )
2261 {
2262  for( MODULE* module = m_Modules; module; module = module->Next() )
2263  {
2264  D_PAD* pad = module->GetPad( aPosition, aLayerSet );
2265 
2266  if( pad )
2267  return pad;
2268  }
2269 
2270  // No pad has been located so check for a segment of the trace.
2271  TRACK* segment = ::GetTrack( m_Track, NULL, aPosition, aLayerSet );
2272 
2273  if( !segment )
2274  segment = GetVisibleTrack( m_Track, aPosition, aLayerSet );
2275 
2276  return segment;
2277 }
2278 
2279 
2280 TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS_LIST* aList )
2281 {
2282  /* creates an intermediate point on aSegment and break it into two segments
2283  * at aPosition.
2284  * The new segment starts from aPosition and ends at the end point of
2285  * aSegment. The original segment now ends at aPosition.
2286  */
2287  if( aSegment->GetStart() == aPosition || aSegment->GetEnd() == aPosition )
2288  return NULL;
2289 
2290  // A via is a good lock point
2291  if( aSegment->Type() == PCB_VIA_T )
2292  {
2293  aPosition = aSegment->GetStart();
2294  return aSegment;
2295  }
2296 
2297  // Calculation coordinate of intermediate point relative to the start point of aSegment
2298  wxPoint delta = aSegment->GetEnd() - aSegment->GetStart();
2299 
2300  // calculate coordinates of aPosition relative to aSegment->GetStart()
2301  wxPoint lockPoint = aPosition - aSegment->GetStart();
2302 
2303  // lockPoint must be on aSegment:
2304  // Ensure lockPoint.y/lockPoint.y = delta.y/delta.x
2305  if( delta.x == 0 )
2306  lockPoint.x = 0; // horizontal segment
2307  else
2308  lockPoint.y = KiROUND( ( (double)lockPoint.x * delta.y ) / delta.x );
2309 
2310  /* Create the intermediate point (that is to say creation of a new
2311  * segment, beginning at the intermediate point.
2312  */
2313  lockPoint += aSegment->GetStart();
2314 
2315  TRACK* newTrack = (TRACK*)aSegment->Clone();
2316  // The new segment begins at the new point,
2317  newTrack->SetStart(lockPoint);
2318  newTrack->start = aSegment;
2319  newTrack->SetState( BEGIN_ONPAD, false );
2320 
2321  DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
2322  wxASSERT( list );
2323  list->Insert( newTrack, aSegment->Next() );
2324 
2325  if( aList )
2326  {
2327  // Prepare the undo command for the now track segment
2328  ITEM_PICKER picker( newTrack, UR_NEW );
2329  aList->PushItem( picker );
2330  // Prepare the undo command for the old track segment
2331  // before modifications
2332  picker.SetItem( aSegment );
2333  picker.SetStatus( UR_CHANGED );
2334  picker.SetLink( aSegment->Clone() );
2335  aList->PushItem( picker );
2336  }
2337 
2338  // Old track segment now ends at new point.
2339  aSegment->SetEnd(lockPoint);
2340  aSegment->end = newTrack;
2341  aSegment->SetState( END_ONPAD, false );
2342 
2343  D_PAD * pad = GetPad( newTrack, ENDPOINT_START );
2344 
2345  if( pad )
2346  {
2347  newTrack->start = pad;
2348  newTrack->SetState( BEGIN_ONPAD, true );
2349  aSegment->end = pad;
2350  aSegment->SetState( END_ONPAD, true );
2351  }
2352 
2353  aPosition = lockPoint;
2354  return newTrack;
2355 }
2356 
2357 
2358 ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
2359  PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch )
2360 {
2361  ZONE_CONTAINER* new_area = InsertArea( aNetcode,
2362  m_ZoneDescriptorList.size( ) - 1,
2363  aLayer, aStartPointPosition.x,
2364  aStartPointPosition.y, aHatch );
2365 
2366  if( aNewZonesList )
2367  {
2368  ITEM_PICKER picker( new_area, UR_NEW );
2369  aNewZonesList->PushItem( picker );
2370  }
2371 
2372  return new_area;
2373 }
2374 
2375 
2376 void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
2377 {
2378  if( area_to_remove == NULL )
2379  return;
2380 
2381  if( aDeletedList )
2382  {
2383  ITEM_PICKER picker( area_to_remove, UR_DELETED );
2384  aDeletedList->PushItem( picker );
2385  Remove( area_to_remove ); // remove from zone list, but does not delete it
2386  }
2387  else
2388  {
2389  Delete( area_to_remove );
2390  }
2391 }
2392 
2393 
2394 ZONE_CONTAINER* BOARD::InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
2395  int aCornerX, int aCornerY, int aHatch )
2396 {
2397  ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
2398 
2399  new_area->SetNetCode( aNetcode );
2400  new_area->SetLayer( aLayer );
2401  new_area->SetTimeStamp( GetNewTimeStamp() );
2402 
2403  if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
2404  m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
2405  else
2406  m_ZoneDescriptorList.push_back( new_area );
2407 
2408  new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
2409 
2410  // Add the first corner to the new zone
2411  new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
2412 
2413  return new_area;
2414 }
2415 
2416 
2418 {
2419  // mark all areas as unmodified except this one, if modified
2420  for( ZONE_CONTAINER* zone : m_ZoneDescriptorList )
2421  zone->SetLocalFlags( 0 );
2422 
2423  aCurrArea->SetLocalFlags( 1 );
2424 
2425  if( aCurrArea->Outline()->IsSelfIntersecting() )
2426  {
2427  aCurrArea->UnHatch();
2428 
2429  // Normalize copied area and store resulting number of polygons
2430  int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
2431 
2432  // If clipping has created some polygons, we must add these new copper areas.
2433  if( n_poly > 1 )
2434  {
2435  ZONE_CONTAINER* NewArea;
2436 
2437  // Move the newly created polygons to new areas, removing them from the current area
2438  for( int ip = 1; ip < n_poly; ip++ )
2439  {
2440  // Create new copper area and copy poly into it
2441  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
2442  NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
2443  wxPoint(0, 0), aCurrArea->GetHatchStyle() );
2444 
2445  // remove the poly that was automatically created for the new area
2446  // and replace it with a poly from NormalizeAreaOutlines
2447  delete NewArea->Outline();
2448  NewArea->SetOutline( new_p );
2449  NewArea->Hatch();
2450  NewArea->SetLocalFlags( 1 );
2451  }
2452 
2453  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
2454  delete aCurrArea->Outline();
2455  aCurrArea->SetOutline( new_p );
2456  }
2457  }
2458 
2459  aCurrArea->Hatch();
2460 
2461  return true;
2462 }
2463 
2464 
2466  COMPONENT* component, REPORTER& aReporter )
2467 {
2468  wxString msg;
2469 
2470  for( auto pad : footprint->Pads() )
2471  {
2472  COMPONENT_NET net = component->GetNet( pad->GetName() );
2473 
2474  if( !net.IsValid() ) // Footprint pad had no net.
2475  {
2476  if( !pad->GetNetname().IsEmpty() )
2477  {
2478  msg.Printf( _( "Clearing component %s pin %s net." ),
2479  footprint->GetReference(),
2480  pad->GetName() );
2481  aReporter.Report( msg, REPORTER::RPT_ACTION );
2482  }
2483 
2484  if( !aNetlist.IsDryRun() )
2485  {
2486  m_connectivity->Remove( pad );
2487  pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
2488  }
2489  }
2490  else // Footprint pad has a net.
2491  {
2492  const wxString& netName = net.GetNetName();
2493  NETINFO_ITEM* netinfo = FindNet( netName );
2494 
2495  if( netinfo && !aNetlist.IsDryRun() )
2496  netinfo->SetIsCurrent( true );
2497 
2498  if( pad->GetNetname() != netName )
2499  {
2500  msg.Printf( _( "Changing footprint %s pad %s net from %s to %s." ),
2501  footprint->GetReference(),
2502  pad->GetName(),
2503  pad->GetNetname(),
2504  netName );
2505  aReporter.Report( msg, REPORTER::RPT_ACTION );
2506 
2507  if( !aNetlist.IsDryRun() )
2508  {
2509  if( netinfo == NULL )
2510  {
2511  // It is a new net, we have to add it
2512  netinfo = new NETINFO_ITEM( this, net.GetNetName() );
2513  Add( netinfo );
2514  }
2515 
2516  m_connectivity->Remove( pad );
2517  pad->SetNetCode( netinfo->GetNet() );
2518  m_connectivity->Add( pad );
2519  }
2520  }
2521  }
2522  }
2523 }
2524 
2525 
2526 void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
2527  std::vector<MODULE*>* aNewFootprints, REPORTER& aReporter )
2528 {
2529  unsigned i;
2530  wxPoint bestPosition;
2531  wxString msg;
2532  std::vector<MODULE*> newFootprints;
2533  std::map< ZONE_CONTAINER*, std::vector<D_PAD*> > zoneConnectionsCache;
2534  MODULE* lastPreexistingFootprint = m_Modules.GetLast();
2535 
2536  for( int ii = 0; ii < GetAreaCount(); ii++ )
2537  {
2538  ZONE_CONTAINER* zone = GetArea( ii );
2539 
2540  if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
2541  continue;
2542 
2543  zoneConnectionsCache[ zone ] = m_connectivity->GetConnectedPads( zone );
2544  }
2545 
2546  if( !IsEmpty() )
2547  {
2548  // Position new components below any existing board features.
2550 
2551  if( bbbox.GetWidth() || bbbox.GetHeight() )
2552  {
2553  bestPosition.x = bbbox.Centre().x;
2554  bestPosition.y = bbbox.GetBottom() + Millimeter2iu( 10 );
2555  }
2556  }
2557  else
2558  {
2559  // Position new components in the center of the page when the board is empty.
2560  wxSize pageSize = m_paper.GetSizeIU();
2561 
2562  bestPosition.x = pageSize.GetWidth() / 2;
2563  bestPosition.y = pageSize.GetHeight() / 2;
2564  }
2565 
2566  m_Status_Pcb = 0;
2567 
2568  // Mark all nets (except <no net>) as stale; we'll update those to current that
2569  // we find in the netlist
2570  for( NETINFO_ITEM* net : m_NetInfo )
2571  net->SetIsCurrent( net->GetNet() == 0 );
2572 
2573  for( i = 0; i < aNetlist.GetCount(); i++ )
2574  {
2575  COMPONENT* component = aNetlist.GetComponent( i );
2576  int matchCount = 0;
2577  MODULE* tmp;
2578 
2579  msg.Printf( _( "Checking netlist symbol footprint \"%s:%s:%s\"." ),
2580  component->GetReference(),
2581  component->GetTimeStamp(),
2582  GetChars( component->GetFPID().Format() ) );
2583  aReporter.Report( msg, REPORTER::RPT_INFO );
2584 
2585  for( MODULE* footprint = m_Modules; footprint; footprint = footprint->Next() )
2586  {
2587  bool match;
2588 
2589  if( aNetlist.IsFindByTimeStamp() )
2590  match = footprint->GetPath() == component->GetTimeStamp();
2591  else
2592  match = footprint->GetReference().CmpNoCase( component->GetReference() ) == 0;
2593 
2594  if( match )
2595  {
2596  // Test for footprint change.
2597  if( !component->GetFPID().empty() && footprint->GetFPID() != component->GetFPID() )
2598  {
2599  if( aNetlist.GetReplaceFootprints() )
2600  {
2601  if( component->GetModule() != NULL )
2602  {
2603  msg.Printf( _( "Changing symbol %s footprint from %s to %s." ),
2604  footprint->GetReference(),
2605  GetChars( footprint->GetFPID().Format() ),
2606  GetChars( component->GetFPID().Format() ) );
2607  aReporter.Report( msg, REPORTER::RPT_ACTION );
2608  }
2609  else
2610  {
2611  msg.Printf( _( "Cannot change symbol %s footprint due to missing footprint %s." ),
2612  footprint->GetReference(),
2613  GetChars( component->GetFPID().Format() ) );
2614  aReporter.Report( msg, REPORTER::RPT_ERROR );
2615  }
2616 
2617  if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
2618  {
2619  wxASSERT( footprint != NULL );
2620  MODULE* newFootprint = new MODULE( *component->GetModule() );
2621 
2622  if( aNetlist.IsFindByTimeStamp() )
2623  newFootprint->SetReference( footprint->GetReference() );
2624  else
2625  newFootprint->SetPath( footprint->GetPath() );
2626 
2627  // Copy placement and pad net names.
2628  // optionally, copy or not local settings (like local clearances)
2629  // if the second parameter is "true", previous values will be used.
2630  // if "false", the default library values of the new footprint
2631  // will be used
2632  footprint->CopyNetlistSettings( newFootprint, false );
2633 
2634  // Compare the footprint name only, in case the nickname is empty or in case
2635  // user moved the footprint to a new library. Chances are if footprint name is
2636  // same then the footprint is very nearly the same and the two texts should
2637  // be kept at same size, position, and rotation.
2638  if( newFootprint->GetFPID().GetLibItemName() == footprint->GetFPID().GetLibItemName() )
2639  {
2640  newFootprint->Reference().SetEffects( footprint->Reference() );
2641  newFootprint->Value().SetEffects( footprint->Value() );
2642  }
2643 
2644  m_connectivity->Remove( footprint );
2645  Remove( footprint );
2646 
2647  Add( newFootprint, ADD_APPEND );
2648  m_connectivity->Add( footprint );
2649 
2650  footprint = newFootprint;
2651  }
2652  }
2653  }
2654 
2655  // Test for reference designator field change.
2656  if( footprint->GetReference() != component->GetReference() )
2657  {
2658  msg.Printf( _( "Changing footprint %s reference to %s." ),
2659  footprint->GetReference(),
2660  component->GetReference() );
2661  aReporter.Report( msg, REPORTER::RPT_ACTION );
2662 
2663  if( !aNetlist.IsDryRun() )
2664  footprint->SetReference( component->GetReference() );
2665  }
2666 
2667  // Test for value field change.
2668  if( footprint->GetValue() != component->GetValue() )
2669  {
2670  msg.Printf( _( "Changing footprint %s value from %s to %s." ),
2671  footprint->GetReference(),
2672  footprint->GetValue(),
2673  component->GetValue() );
2674  aReporter.Report( msg, REPORTER::RPT_ACTION );
2675 
2676  if( !aNetlist.IsDryRun() )
2677  footprint->SetValue( component->GetValue() );
2678  }
2679 
2680  // Test for time stamp change.
2681  if( footprint->GetPath() != component->GetTimeStamp() )
2682  {
2683  msg.Printf( _( "Changing component path \"%s:%s\" to \"%s\"." ),
2684  footprint->GetReference(),
2685  footprint->GetPath(),
2686  component->GetTimeStamp() );
2687  aReporter.Report( msg, REPORTER::RPT_INFO );
2688 
2689  if( !aNetlist.IsDryRun() )
2690  footprint->SetPath( component->GetTimeStamp() );
2691  }
2692 
2693  updateComponentPadConnections( aNetlist, footprint, component, aReporter );
2694 
2695  matchCount++;
2696  }
2697 
2698  if( footprint == lastPreexistingFootprint )
2699  {
2700  // No sense going through the newly-created footprints: end loop
2701  break;
2702  }
2703  }
2704 
2705  if( matchCount == 0 )
2706  {
2707  if( component->GetModule() != NULL )
2708  {
2709  msg.Printf( _( "Adding new symbol %s footprint %s." ),
2710  component->GetReference(),
2711  GetChars( component->GetFPID().Format() ) );
2712  aReporter.Report( msg, REPORTER::RPT_ACTION );
2713  }
2714  else
2715  {
2716  msg.Printf( _( "Cannot add new symbol %s due to missing footprint %s." ),
2717  component->GetReference(),
2718  GetChars( component->GetFPID().Format() ) );
2719  aReporter.Report( msg, REPORTER::RPT_ERROR );
2720  }
2721 
2722  if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
2723  {
2724  // Owned by NETLIST, can only copy it.
2725  tmp = new MODULE( *component->GetModule() );
2726  tmp->SetParent( this );
2727  tmp->SetPosition( bestPosition );
2728  tmp->SetTimeStamp( GetNewTimeStamp() );
2729  newFootprints.push_back( tmp );
2730  Add( tmp, ADD_APPEND );
2731  m_connectivity->Add( tmp );
2732 
2733  updateComponentPadConnections( aNetlist, tmp, component, aReporter );
2734  }
2735  }
2736  else if( matchCount > 1 )
2737  {
2738  msg.Printf( _( "Multiple footprints found for \"%s\"." ), component->GetReference() );
2739  aReporter.Report( msg, REPORTER::RPT_ERROR );
2740  }
2741  }
2742 
2743  // Remove all components not in the netlist.
2744  if( aNetlist.GetDeleteExtraFootprints() )
2745  {
2746  MODULE* nextModule;
2747  const COMPONENT* component;
2748 
2749  for( MODULE* module = m_Modules; module != NULL; module = nextModule )
2750  {
2751  nextModule = module->Next();
2752 
2753  if( module->IsLocked() )
2754  continue;
2755 
2756  if( aNetlist.IsFindByTimeStamp() )
2757  component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
2758  else
2759  component = aNetlist.GetComponentByReference( module->GetReference() );
2760 
2761  if( component == NULL )
2762  {
2763  msg.Printf( _( "Removing unused footprint %s." ), module->GetReference() );
2764  aReporter.Report( msg, REPORTER::RPT_ACTION );
2765 
2766  if( !aNetlist.IsDryRun() )
2767  {
2768  m_connectivity->Remove( module );
2769  module->DeleteStructure();
2770  }
2771  }
2772  }
2773  }
2774 
2775  BuildListOfNets();
2776  std::vector<D_PAD*> padlist = GetPads();
2777  auto connAlgo = m_connectivity->GetConnectivityAlgo();
2778 
2779  // If needed, remove the single pad nets:
2780  if( aDeleteSinglePadNets && !aNetlist.IsDryRun() )
2781  {
2782  std::vector<unsigned int> padCount( (unsigned) connAlgo->NetCount() );
2783 
2784  for( const auto cnItem : connAlgo->ItemList() )
2785  {
2786  if( !cnItem->Valid() || cnItem->Parent()->Type() != PCB_PAD_T )
2787  continue;
2788 
2789  int net = cnItem->Parent()->GetNetCode();
2790 
2791  if( net > 0 )
2792  ++padCount[net];
2793  }
2794 
2795  for( i = 0; i < (unsigned)connAlgo->NetCount(); ++i )
2796  {
2797  // First condition: only one pad in the net
2798  if( padCount[i] == 1 )
2799  {
2800  // Second condition, no zones attached to the pad
2801  D_PAD* pad = nullptr;
2802  int zoneCount = 0;
2803  const KICAD_T types[] = { PCB_PAD_T, PCB_ZONE_AREA_T, EOT };
2804  auto netItems = m_connectivity->GetNetItems( i, types );
2805 
2806  for( const auto item : netItems )
2807  {
2808  if( item->Type() == PCB_ZONE_AREA_T )
2809  {
2810  wxASSERT( !pad || pad->GetNet() == item->GetNet() );
2811  ++zoneCount;
2812  }
2813  else if( item->Type() == PCB_PAD_T )
2814  {
2815  wxASSERT( !pad );
2816  pad = static_cast<D_PAD*>( item );
2817  }
2818  }
2819 
2820  wxASSERT( pad ); // pad = 0 means the pad list is not up to date
2821 
2822  if( pad && zoneCount == 0 )
2823  {
2824  msg.Printf( _( "Remove single pad net %s." ), GetChars( pad->GetNetname() ) );
2825  aReporter.Report( msg, REPORTER::RPT_ACTION );
2826 
2827  m_connectivity->Remove( pad );
2829  }
2830  }
2831  }
2832  }
2833 
2834  // Verify that board contains all pads in netlist: if it doesn't then footprints are
2835  // wrong or missing.
2836  // Note that we use references to find the footprints as they're already updated by this
2837  // point (whether by-reference or by-timestamp).
2838  wxString padname;
2839  for( i = 0; i < aNetlist.GetCount(); i++ )
2840  {
2841  const COMPONENT* component = aNetlist.GetComponent( i );
2842  MODULE* footprint = FindModuleByReference( component->GetReference() );
2843 
2844  if( footprint == NULL ) // It can be missing in partial designs
2845  continue;
2846 
2847  // Explore all pins/pads in component
2848  for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
2849  {
2850  const COMPONENT_NET& net = component->GetNet( jj );
2851  padname = net.GetPinName();
2852 
2853  if( footprint->FindPadByName( padname ) )
2854  continue; // OK, pad found
2855 
2856  // not found: bad footprint, report error
2857  msg.Printf( _( "Symbol %s pad %s not found in footprint %s.\n" ),
2858  component->GetReference(),
2859  padname,
2860  GetChars( footprint->GetFPID().Format() ) );
2861  aReporter.Report( msg, REPORTER::RPT_ERROR );
2862  }
2863  }
2864 
2865  // Test copper zones to detect "dead" nets (nets without any pad):
2866  for( int ii = 0; ii < GetAreaCount(); ii++ )
2867  {
2868  ZONE_CONTAINER* zone = GetArea( ii );
2869 
2870  if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
2871  continue;
2872 
2873  if( m_connectivity->GetPadCount( zone->GetNetCode() ) == 0 )
2874  {
2875  // Look for a pad in the zone's connected-pad-cache which has been updated to
2876  // a new net and use that. While this won't always be the right net, the dead
2877  // net is guaranteed to be wrong.
2878  NETINFO_ITEM* updatedNet = nullptr;
2879 
2880  for( D_PAD* pad : zoneConnectionsCache[ zone ] )
2881  {
2882  if( pad->GetNetname() != zone->GetNetname() )
2883  {
2884  updatedNet = pad->GetNet();
2885  break;
2886  }
2887  }
2888 
2889  if( updatedNet )
2890  {
2891  msg.Printf( _( "Updating copper zone from net %s to %s." ),
2892  zone->GetNetname(),
2893  updatedNet->GetNetname() );
2894  aReporter.Report( msg, REPORTER::RPT_ACTION );
2895  }
2896  else
2897  {
2898  msg.Printf( _( "Copper zone (net %s) has no pads connected." ),
2899  zone->GetNetname() );
2900  aReporter.Report( msg, REPORTER::RPT_WARNING );
2901  }
2902 
2903  if( updatedNet && !aNetlist.IsDryRun() )
2904  {
2905  m_connectivity->Remove( zone );
2906  zone->SetNet( updatedNet );
2907  m_connectivity->Add( zone );
2908  }
2909  }
2910  }
2911 
2912  m_connectivity->RecalculateRatsnest();
2913 
2914  std::swap( newFootprints, *aNewFootprints );
2915 }
2916 
2917 
2919  bool aAddToBoard )
2920 {
2921  BOARD_ITEM* new_item = NULL;
2922 
2923  switch( aItem->Type() )
2924  {
2925  case PCB_MODULE_T:
2926  case PCB_TEXT_T:
2927  case PCB_LINE_T:
2928  case PCB_TRACE_T:
2929  case PCB_VIA_T:
2930  case PCB_ZONE_AREA_T:
2931  case PCB_TARGET_T:
2932  case PCB_DIMENSION_T:
2933  new_item = static_cast<BOARD_ITEM*>( aItem->Clone() );
2934  break;
2935 
2936  default:
2937  // Un-handled item for duplication
2938  new_item = NULL;
2939  break;
2940  }
2941 
2942  if( new_item && aAddToBoard )
2943  Add( new_item );
2944 
2945  return new_item;
2946 }
2947 
2948 
2949 /* Extracts the board outlines and build a closed polygon
2950  * from lines, arcs and circle items on edge cut layer
2951  * Any closed outline inside the main outline is a hole
2952  * All contours should be closed, i.e. are valid vertices for a closed polygon
2953  * return true if success, false if a contour is not valid
2954  */
2955 extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
2956  wxString* aErrorText, unsigned int aTolerance,
2957  wxPoint* aErrorLocation = nullptr );
2958 
2959 
2960 bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText, wxPoint* aErrorLocation )
2961 {
2962  bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText,
2963  Millimeter2iu( 0.05 ), aErrorLocation );
2964 
2965  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2967 
2968  return success;
2969 
2970 }
2971 
2972 
2973 const std::vector<D_PAD*> BOARD::GetPads()
2974 {
2975  std::vector<D_PAD*> allPads;
2976 
2977  for( MODULE* mod : Modules() )
2978  {
2979  for( D_PAD* pad : mod->Pads() )
2980  allPads.push_back( pad );
2981  }
2982 
2983  return allPads;
2984 }
2985 
2986 
2988 {
2989  unsigned retval = 0;
2990 
2991  for( auto mod : Modules() )
2992  retval += mod->Pads().Size();
2993 
2994  return retval;
2995 }
2996 
2997 
3002 D_PAD* BOARD::GetPad( unsigned aIndex ) const
3003 {
3004  unsigned count = 0;
3005 
3006  for( MODULE* mod = m_Modules; mod ; mod = mod->Next() ) // FIXME: const DLIST_ITERATOR
3007  {
3008  for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() )
3009  {
3010  if( count == aIndex )
3011  return pad;
3012 
3013  count++;
3014  }
3015  }
3016 
3017  return nullptr;
3018 }
3019 
3021 {
3022  for( auto zone : Zones() )
3023  zone->SetNetCode( 0 );
3024 
3025  for( auto pad : GetPads() )
3026  pad->SetNetCode( 0 );
3027 
3028  for( auto track : Tracks() )
3029  track->SetNetCode( 0 );
3030 }
3031 
3032 const std::vector<BOARD_CONNECTED_ITEM*> BOARD::AllConnectedItems()
3033 {
3034  std::vector<BOARD_CONNECTED_ITEM*> items;
3035 
3036  for( auto track : Tracks() )
3037  {
3038  items.push_back( track );
3039  }
3040 
3041  for( auto mod : Modules() )
3042  {
3043  for( auto pad : mod->Pads() )
3044  {
3045  items.push_back( pad );
3046  }
3047  }
3048 
3049  for( int i = 0; i<GetAreaCount(); i++ )
3050  {
3051  auto zone = GetArea( i );
3052  items.push_back( zone );
3053  }
3054 
3055  return items;
3056 }
3057 
3059 {
3060  for ( auto item : AllConnectedItems() )
3061  {
3062  if( FindNet( item->GetNetCode() ) == nullptr )
3063  item->SetNetCode( NETINFO_LIST::ORPHANED );
3064  }
3065 }
Definition: colors.h:57
DHEAD * GetList() const
Definition: base_struct.h:212
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
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
#define DIM(x)
of elements in an array
Definition: macros.h:98
const wxString & GetPinName() const
Definition: pcb_netlist.h:61
void SetCopperLayerCount(int aNewLayerCount)
Function SetCopperLayerCount do what its name says...
void BuildListOfNets()
Definition: class_board.h:735
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:276
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 ...
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
TEXTE_MODULE & Reference()
Definition: class_module.h:512
bool empty() const
Definition: lib_id.h:186
Class that draws missing connections on a PCB.
int GetCurrentViaDrill() const
Function GetCurrentViaDrill.
void DeleteZONEOutlines()
Function DeleteZONEOutlines deletes ALL zone outlines from the board.
int GetVisibleElements() const
Function GetVisibleElements returns a bit-mask of all the element categories that are visible...
Definition: typeinfo.h:85
const LIB_ID & GetFPID() const
Definition: pcb_netlist.h:166
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:191
NETCLASSPTR GetDefault() const
Function GetDefault.
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
unsigned GetUnconnectedNetCount() const
Function GetUnconnectedNetCount.
virtual LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:120
wxString m_name
The name of the layer, there should be no spaces in this name.
Definition: class_board.h:113
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&#39;s internal state for displ...
void PushFront(T *aNewElement)
Function PushFront puts aNewElement at front of list sequence.
Definition: dlist.h:240
void updateComponentPadConnections(NETLIST &aNetlist, MODULE *footprint, COMPONENT *component, REPORTER &aReporter)
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:122
D_PAD * GetPadFast(const wxPoint &aPosition, LSET aLayerMask)
Function GetPadFast return pad found at aPosition on aLayerMask using the fast search method...
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
static void otherEnd(const TRACK &aTrack, const wxPoint &aNotThisEnd, wxPoint *aOtherEnd)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
PAGE_INFO m_paper
Definition: class_board.h:198
void SetIsCurrent(bool isCurrent)
Definition: netinfo.h:249
void SetStatus(UNDO_REDO_T aStatus)
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
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 ...
MODULE * GetModule(bool aRelease=false)
Definition: pcb_netlist.h:186
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it&#39;s a back layer.
void SetCustomViaDrill(int aDrill)
Function SetCustomViaDrill Sets custom size for via drill (i.e.
int GetPadToDieLength() const
Definition: class_pad.h:412
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:406
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:446
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:115
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
MODULE * Next() const
Definition: class_module.h:122
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
NETINFO_ITEM * GetNetItem(int aNetCode) const
Function GetItem.
COLORS_DESIGN_SETTINGS * m_colorsSettings
Definition: class_board.h:197
int NormalizeAreaOutlines()
Function NormalizeAreaOutlines Convert a self-intersecting polygon to one (or more) non self-intersec...
int GetCopperLayerCount() const
Function GetCopperLayerCount.
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
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...
ZONE_CONTAINER * m_CurrentZoneContour
zone contour currently in progress
Definition: class_board.h:264
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
show modules on back
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:168
unsigned GetNetCount() const
Function GetNetCount.
Definition: netinfo.h:442
int GetHeight() const
Definition: eda_rect.h:118
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:241
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
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) ...
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
const wxPoint GetPosition() const override
Definition: class_board.cpp:86
DELETED_BOARD_ITEM g_DeletedItem
Definition: class_board.cpp:95
Classes to handle copper zones.
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
D_PAD * GetPad(unsigned aIndex) const
Function GetPad.
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:135
virtual void SetPosition(const wxPoint &aPos) override
bool IsValid() const
Definition: pcb_netlist.h:65
This is the end of the layers used for visibility bitmasks in Pcbnew There can be at most 32 layers a...
MODULE * FindModule(const wxString &aRefOrTimeStamp, bool aSearchByTimeStamp=false) const
Function FindModule searches for a module matching aRefOrTimeStamp depending on the state of aSearchB...
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:188
NETINFO_LIST m_NetInfo
net info list (name, design constraints ..
Definition: class_board.h:201
A singleton item of this class is returned for a weak reference that no longer exists.
Definition: class_board.cpp:68
bool IsLayerVisible(PCB_LAYER_ID aLayerId) const
Function IsLayerVisible tests whether a given layer is visible.
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
HIGH_LIGHT_INFO m_highLightPrevious
Definition: class_board.h:189
int GetVisibleElements() const
Function GetVisibleElements is a proxy function that calls the correspondent function in m_BoardSetti...
virtual void UnLink()
Function UnLink detaches this object from its owner.
int GetState(int type) const
Definition: base_struct.h:240
#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
int GetCurrentViaSize() const
Function GetCurrentViaSize.
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void SetLink(EDA_ITEM *aItem)
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
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:244
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
const wxPoint & GetEnd() const
Definition: class_track.h:123
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.
static std::string FormatInternalUnits(int aValue)
Function FormatInternalUnits converts aValue from board internal units to a string appropriate for wr...
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
ENDPOINT_T
Flag used in locate routines (from which endpoint work)
Definition: pcbnew.h:58
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
SEGZONE * Next() const
Definition: class_track.h:367
Classes used in Pcbnew, CvPcb and GerbView.
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:810
void AppendNet(NETINFO_ITEM *aNewElement)
Function AppendNet adds aNewElement to the end of the net list.
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:628
show modules on front
const wxString & GetReference() const
Definition: pcb_netlist.h:151
virtual const wxPoint GetCenter() const
Function GetCenter()
BOARD_ITEM * Next() const
Class that handles properties and drawing of worksheet layout.
Class COMPONENT_NET is used to store the component pin name to net name associations stored in a netl...
Definition: pcb_netlist.h:48
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:102
const LIB_ID & GetFPID() const
Definition: class_module.h:192
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...
const wxString & GetValue() const
Definition: pcb_netlist.h:153
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:212
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.
PCB_LAYER_ID
A quick note on layer IDs:
bool GetDeleteExtraFootprints() const
Definition: pcb_netlist.h:305
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.
Class LSET is a set of PCB_LAYER_IDs.
void PopHighLight()
Function PopHighLight retrieve a previously saved high light info.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
bool GetReplaceFootprints() const
Definition: pcb_netlist.h:320
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...
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:214
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:49
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.
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.
T * GetLast() const
Function GetLast returns the last T* in the list without removing it, or NULL if the list is empty...
Definition: dlist.h:170
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:216
#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.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:511
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
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text...
#define IS_DELETED
Definition: base_struct.h:117
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
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 IsEmpty() const
Definition: class_board.h:273
const wxPoint & GetStart() const
Definition: class_track.h:126
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...
DLIST< SEGZONE > m_SegZoneDeprecated
Definition: class_board.h:251
LAYER_T
Enum LAYER_T gives the allowed types of layers, same as Specctra DSN spec.
Definition: class_board.h:73
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:402
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Function SetLayerName changes the name of the layer given by aLayer.
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: class_track.h:130
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
const wxString & GetNetName() const
Definition: pcb_netlist.h:63
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Function SetLayerDescr returns the type of the copper layer given by aLayer.
bool IsFindByTimeStamp() const
Definition: pcb_netlist.h:313
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
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:202
void ReplaceNetlist(NETLIST &aNetlist, bool aDeleteSinglePadNets, std::vector< MODULE * > *aNewFootprints, REPORTER &aReporter)
Function ReplaceNetlist updates the BOARD according to aNetlist.
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:245
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
Definition: colors.h:60
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...
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
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:472
#define THROW_IO_ERROR(msg)
int SetAreasNetCodesFromNetNames(void)
Function SetAreasNetCodesFromNetNames Set the .m_NetCode member of all copper areas, according to the area Net Name The SetNetCodesFromNetNames is an equivalent to net name, for fast comparisons.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
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...
const wxString & GetTimeStamp() const
Definition: pcb_netlist.h:170
MARKERS m_markers
MARKER_PCBs for clearance problems, owned by pointer.
Definition: class_board.h:180
int GetBottom() const
Definition: eda_rect.h:122
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:66
wxPoint Centre() const
Definition: eda_rect.h:60
void SetPosition(const wxPoint &aPos) override
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.
int GetNet() const
Function GetNet.
Definition: netinfo.h:231
static LAYER_T ParseType(const char *aType)
Function ParseType converts a string to a LAYER_T.
void SetItem(EDA_ITEM *aItem)
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:267
unsigned GetPadCount()
Function GetPadCount.
bool IsElementVisible(GAL_LAYER_ID aElementCategory) const
Function IsElementVisible tests whether a given element category is visible.
int GetNumSegmTrack() const
Functions to get some items count.
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.
const PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Function GetLayerID returns the ID of a layer given by aLayerName.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
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.
Class COMPONENT is used to store components and all of their related information found in a netlist...
Definition: pcb_netlist.h:83
static bool sortNetsByNames(const NETINFO_ITEM *a, const NETINFO_ITEM *b)
TRACKS TracksInNet(int aNetCode)
Function TrackInNet collects all the TRACKs and VIAs that are members of a net given by aNetCode...
int GetNetCode() const
Function GetNetCode.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:265
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
void Move(const wxPoint &aMoveVector) override
Function Move move this object.
VIA * GetViaByPosition(const wxPoint &aPosition, PCB_LAYER_ID aLayer=PCB_LAYER_ID(-1)) const
Function GetViaByPosition finds the first via at aPosition on aLayer.
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Function IsElementVisible tests whether a given element category is visible.
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
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:99
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
BOARD_ITEM * GetItem(void *aWeakReference)
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
TRACK * Next() const
Definition: class_track.h:103
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
const wxString & GetNetname() const
Function GetNetname.
void SetState(int type, int state)
Definition: base_struct.h:245
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
void UnHatch()
Function UnHatch clears the zone&#39;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
int m_fileFormatVersionAtLoad
the version loaded from the file
Definition: class_board.h:191
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
#define max(a, b)
Definition: auxiliary.h:86
Class LAYER holds information pertinent to a layer of a BOARD.
Definition: class_board.h:87
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
DLIST< MODULE > m_Modules
Definition: class_board.h:249
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 ) ...
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
ZONE_CONTAINERS m_ZoneDescriptorList
edge zone descriptors, owned by pointer.
Definition: class_board.h:183
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:104
size_t i
Definition: json11.cpp:597
void SanitizeNetcodes()
LAYER m_Layer[PCB_LAYER_ID_COUNT]
Definition: class_board.h:185
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: class_board.h:193
int GetNumSegmZone() const
Calculate the zone segment count.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetX() const
Definition: eda_rect.h:109
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:524
void Hatch()
Function Hatch computes the hatch lines depending on the hatch parameters and stores it in the zone&#39;s...
void PushHighLight()
Function PushHighLight save current high light info for later use.
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
void SetHatchStyle(HATCH_STYLE aStyle)
Definition: class_zone.h:529
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:154
static bool sortNetsByNodes(const NETINFO_ITEM *a, const NETINFO_ITEM *b)
void SetLocalFlags(int aFlags)
Definition: class_zone.h:236
The common library.
int GetWidth() const
Definition: eda_rect.h:117
bool IsModuleLayerVisible(PCB_LAYER_ID aLayer)
Function IsModuleLayerVisible expects either of the two layers on which a module can reside...
wxString GetClass() const override
Function GetClass returns the class name.
Definition: class_board.h:933
void SetElementVisibility(GAL_LAYER_ID aElementCategory, bool aNewState)
Function SetElementVisibility changes the visibility of an element category.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
UTF8 Format() const
Definition: lib_id.cpp:237
int GetY() const
Definition: eda_rect.h:110
#define FIRST_COPPER_LAYER
Class COLORS_DESIGN_SETTINGS is a list of color settings for designs in Pcbnew.
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.
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
bool AppendCorner(wxPoint aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
void SetEffects(const TEXTE_MODULE &aSrc)
Function SetEffects sets the text effects from another instance.
void SetStart(const wxPoint &aStart)
Definition: class_track.h:125
PCB_TARGET class definition.
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:139
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
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:250
bool IsDryRun() const
Definition: pcb_netlist.h:309
BOARD_DESIGN_SETTINGS m_designSettings
Definition: class_board.h:195
Module description (excepted pads)
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:239
Abstract interface for BOARD_ITEMs capable of storing other items inside.
LSET GetEnabledLayers() const
Function GetEnabledLayers returns a bit-mask of all the layers that are enabled.
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
const wxPoint GetPosition() const override
Definition: class_pad.h:220
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
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...
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.
class SEGZONE, a segment used to fill a zone area (segment on a
Definition: typeinfo.h:97
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
LSET GetVisibleLayers() const
Function GetVisibleLayers returns a bit-mask of all the layers that are visible.
BOARD_CONNECTED_ITEM * end
Definition: class_track.h:95
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
unsigned GetNetCount() const
Definition: pcb_netlist.h:137
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
BOARD_CONNECTED_ITEM * start
Definition: class_track.h:94
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
void ClearAllNetCodes()
Function ClearAllNetCodes() Resets all items&#39; netcodes to 0 (no net).
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:813
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
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 SetPath(const wxString &aPath)
Definition: class_module.h:202
void Remove(BOARD_ITEM *aBoardItem) override
Removes an item from the container.
EDA_UNITS_T
Definition: common.h:159
NETINFO_ITEM * GetNet() const
Function GetNet Returns NET_INFO object for a given item.
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
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
COMPONENT * GetComponentByTimeStamp(const wxString &aTimeStamp)
Function GetComponentByTimeStamp returns a COMPONENT by aTimeStamp.
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:785
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:659
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:206
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:528
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:241
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:514