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>
61 #include <connectivity_data.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  */
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 
173 {
174  wxLogWarning( wxT( "This should not be called on the BOARD object") );
175 
176  return ZeroOffset;
177 }
178 
179 
180 void BOARD::SetPosition( const wxPoint& aPos )
181 {
182  wxLogWarning( wxT( "This should not be called on the BOARD object") );
183 }
184 
185 
186 void BOARD::Move( const wxPoint& aMoveVector ) // overload
187 {
188  // @todo : anything like this elsewhere? maybe put into GENERAL_COLLECTOR class.
189  static const KICAD_T top_level_board_stuff[] = {
190  PCB_MARKER_T,
191  PCB_TEXT_T,
192  PCB_LINE_T,
194  PCB_TARGET_T,
195  PCB_VIA_T,
196  PCB_TRACE_T,
197  // PCB_PAD_T, Can't be at board level
198  // PCB_MODULE_TEXT_T, Can't be at board level
199  PCB_MODULE_T,
201  EOT
202  };
203 
204  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
205  {
206  BOARD_ITEM* brd_item = (BOARD_ITEM*) item;
207 
208  // aMoveVector was snapshotted, don't need "data".
209  brd_item->Move( aMoveVector );
210 
211  return SEARCH_CONTINUE;
212  };
213 
214  Visit( inspector, NULL, top_level_board_stuff );
215 }
216 
217 
218 TRACKS BOARD::TracksInNet( int aNetCode )
219 {
220  TRACKS ret;
221 
222  INSPECTOR_FUNC inspector = [aNetCode,&ret] ( EDA_ITEM* item, void* testData )
223  {
224  TRACK* t = (TRACK*) item;
225 
226  if( t->GetNetCode() == aNetCode )
227  ret.push_back( t );
228 
229  return SEARCH_CONTINUE;
230  };
231 
232  // visit this BOARD's TRACKs and VIAs with above TRACK INSPECTOR which
233  // appends all in aNetCode to ret.
234  Visit( inspector, NULL, GENERAL_COLLECTOR::Tracks );
235 
236  return ret;
237 }
238 
239 
244 static void removeTrack( TRACKS* aList, TRACK* aOneToRemove )
245 {
246  aList->erase( std::remove( aList->begin(), aList->end(), aOneToRemove ), aList->end() );
247 }
248 
249 
250 static void otherEnd( const TRACK& aTrack, const wxPoint& aNotThisEnd, wxPoint* aOtherEnd )
251 {
252  if( aTrack.GetStart() == aNotThisEnd )
253  {
254  *aOtherEnd = aTrack.GetEnd();
255  }
256  else
257  {
258  wxASSERT( aTrack.GetEnd() == aNotThisEnd );
259  *aOtherEnd = aTrack.GetStart();
260  }
261 }
262 
263 
268 static int find_vias_and_tracks_at( TRACKS& at_next, TRACKS& in_net, LSET& lset, const wxPoint& next )
269 {
270  // first find all vias (in this net) at 'next' location, and expand LSET with each
271  for( TRACKS::iterator it = in_net.begin(); it != in_net.end(); )
272  {
273  TRACK* t = *it;
274 
275  if( t->Type() == PCB_VIA_T && (t->GetLayerSet() & lset).any() &&
276  ( t->GetStart() == next || t->GetEnd() == next ) )
277  {
278  lset |= t->GetLayerSet();
279  at_next.push_back( t );
280  it = in_net.erase( it );
281  }
282  else
283  ++it;
284  }
285 
286  int track_count = 0;
287 
288  // with expanded lset, find all tracks with an end on any of the layers in lset
289  for( TRACKS::iterator it = in_net.begin(); it != in_net.end(); /* iterates in the loop body */ )
290  {
291  TRACK* t = *it;
292 
293  if( ( t->GetLayerSet() & lset ).any() && ( t->GetStart() == next || t->GetEnd() == next ) )
294  {
295  at_next.push_back( t );
296  it = in_net.erase( it );
297  ++track_count;
298  }
299  else
300  {
301  ++it;
302  }
303  }
304 
305  return track_count;
306 }
307 
308 
320 static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTracksInNet,
321  const wxPoint& aGoal, const wxPoint& aStart, TRACK* aFirstTrack )
322 {
323  TRACKS in_net = aTracksInNet; // copy source list so the copy can be modified
324  wxPoint next;
325 
326  otherEnd( *aFirstTrack, aStart, &next );
327 
328  aList->push_back( aFirstTrack );
329  removeTrack( &in_net, aFirstTrack );
330 
331  LSET lset( aFirstTrack->GetLayer() );
332 
333  while( in_net.size() )
334  {
335  if( next == aGoal )
336  return; // success
337 
338  // Want an exact match on the position of next, i.e. pad at next,
339  // not a forgiving HitTest() with tolerance type of match, otherwise the overall
340  // algorithm will not work. GetPadFast() is an exact match as I write this.
341  if( aBoard->GetPadFast( next, lset ) )
342  {
343  std::string m = StrPrintf(
344  "intervening pad at:(xy %s) between start:(xy %s) and goal:(xy %s)",
345  BOARD_ITEM::FormatInternalUnits( next ).c_str(),
346  BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
347  BOARD_ITEM::FormatInternalUnits( aGoal ).c_str()
348  );
349  THROW_IO_ERROR( m );
350  }
351 
352  int track_count = find_vias_and_tracks_at( *aList, in_net, lset, next );
353 
354  if( track_count != 1 )
355  {
356  std::string m = StrPrintf(
357  "found %d tracks intersecting at (xy %s), exactly 2 would be acceptable.",
358  track_count + aList->size() == 1 ? 1 : 0,
359  BOARD_ITEM::FormatInternalUnits( next ).c_str()
360  );
361  THROW_IO_ERROR( m );
362  }
363 
364  // reduce lset down to the layer that the last track at 'next' is on.
365  lset = aList->back()->GetLayerSet();
366 
367  otherEnd( *aList->back(), next, &next );
368  }
369 
370  std::string m = StrPrintf(
371  "not enough tracks connecting start:(xy %s) and goal:(xy %s).",
372  BOARD_ITEM::FormatInternalUnits( aStart ).c_str(),
373  BOARD_ITEM::FormatInternalUnits( aGoal ).c_str()
374  );
375  THROW_IO_ERROR( m );
376 }
377 
378 
379 TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aGoalPos, int aNetCode )
380 {
381  TRACKS in_between_pts;
382  TRACKS on_start_point;
383  TRACKS in_net = TracksInNet( aNetCode ); // a small subset of TRACKs and VIAs
384 
385  for( auto t : in_net )
386  {
387  if( t->Type() == PCB_TRACE_T && ( t->GetStart() == aStartPos || t->GetEnd() == aStartPos ) )
388  on_start_point.push_back( t );
389  }
390 
391  wxString per_path_problem_text;
392 
393  for( auto t : on_start_point ) // explore each trace (path) leaving aStartPos
394  {
395  // checkConnectedTo() fills in_between_pts on every attempt. For failures
396  // this set needs to be cleared.
397  in_between_pts.clear();
398 
399  try
400  {
401  checkConnectedTo( this, &in_between_pts, in_net, aGoalPos, aStartPos, t );
402  }
403  catch( const IO_ERROR& ioe ) // means not connected
404  {
405  per_path_problem_text += "\n\t";
406  per_path_problem_text += ioe.Problem();
407  continue; // keep trying, there may be other paths leaving from aStartPos
408  }
409 
410  // success, no exception means a valid connection,
411  // return this set of TRACKS without throwing.
412  return in_between_pts;
413  }
414 
415  wxString m = wxString::Format(
416  "no clean path connecting start:(xy %s) with goal:(xy %s)",
417  BOARD_ITEM::FormatInternalUnits( aStartPos ).c_str(),
418  BOARD_ITEM::FormatInternalUnits( aGoalPos ).c_str()
419  );
420 
421  THROW_IO_ERROR( m + per_path_problem_text );
422 }
423 
424 
425 void BOARD::chainMarkedSegments( TRACK* aTrackList, wxPoint aPosition,
426  const LSET& aLayerSet, TRACKS* aList )
427 {
428  LSET layer_set = aLayerSet;
429 
430  if( !aTrackList ) // no tracks at all in board
431  return;
432 
433  D_PAD* pad = NULL;
434  double distanceToPadCenter = std::numeric_limits<double>::max();
435 
436  /* Set the BUSY flag of all connected segments, first search starting at
437  * aPosition. The search ends when a pad is found (end of a track), a
438  * segment end has more than one other segment end connected, or when no
439  * connected item found.
440  *
441  * Vias are a special case because they can connect segments
442  * on other layers and they change the layer mask. They can be a track
443  * end or not. They will be analyzed later, and vias on terminal points
444  * of the track will be considered as part of this track if they do not
445  * connect segments on a other track together and will be considered as
446  * part of a other track when removing the via, the segments of that other
447  * track are disconnected.
448  */
449  for( ; ; )
450  {
451  if( !pad )
452  pad = GetPad( aPosition, layer_set );
453 
454  if( pad )
455  distanceToPadCenter = GetLineLength( aPosition, pad->GetCenter() );
456 
457  /* Test for a via: a via changes the layer mask and can connect a lot
458  * of segments at location aPosition. When found, the via is just
459  * pushed in list. Vias will be examined later, when all connected
460  * segment are found and push in list. This is because when a via
461  * is found we do not know at this time the number of connected items
462  * and we do not know if this via is on the track or finish the track
463  */
464  TRACK* via = aTrackList->GetVia( NULL, aPosition, layer_set );
465 
466  if( via )
467  {
468  layer_set = via->GetLayerSet();
469  aList->push_back( via );
470  }
471 
472  int seg_count = 0;
473  TRACK* candidate = NULL;
474 
475  /* Search all segments connected to point aPosition.
476  * if only 1 segment at aPosition: then this segment is "candidate"
477  * if > 1 segment:
478  * then end of "track" (because more than 2 segments are connected at aPosition)
479  */
480  TRACK* segment = aTrackList;
481 
482  while( ( segment = ::GetTrack( segment, NULL, aPosition, layer_set ) ) != NULL )
483  {
484  if( segment->GetState( BUSY ) ) // already found and selected: skip it
485  {
486  segment = segment->Next();
487  continue;
488  }
489 
490  if( segment == via ) // just previously found: skip it
491  {
492  segment = segment->Next();
493  continue;
494  }
495 
496  if( ++seg_count == 1 ) // if first connected item: then segment is candidate
497  {
498  candidate = segment;
499  segment = segment->Next();
500  }
501  else // More than 1 segment connected -> location is end of track
502  {
503  return;
504  }
505  }
506 
507  if( candidate ) // A candidate is found: flag it and push it in list
508  {
509  /* Initialize parameters to search items connected to this
510  * candidate:
511  * we must analyze connections to its other end
512  */
513  if( aPosition == candidate->GetStart() )
514  {
515  aPosition = candidate->GetEnd();
516  }
517  else
518  {
519  aPosition = candidate->GetStart();
520  }
521 
522  /* If we are in a pad, only candidates approaching the pad center
523  * are accepted.
524  */
525  if( pad )
526  {
527  if( GetPad( aPosition, layer_set ) != pad )
528  return;
529 
530  if( GetLineLength( aPosition, pad->GetCenter() ) > distanceToPadCenter )
531  return;
532  }
533 
534  layer_set = candidate->GetLayerSet();
535 
536  // flag this item and push it in list of selected items
537  aList->push_back( candidate );
538  candidate->SetState( BUSY, true );
539  }
540  else
541  {
542  return;
543  }
544  }
545 }
546 
547 
549 {
551 }
552 
553 
555 {
558 }
559 
560 
561 bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer )
562 {
563  if( unsigned( aIndex ) < DIM( m_Layer ) )
564  {
565  m_Layer[ aIndex ] = aLayer;
566  return true;
567  }
568 
569  return false;
570 }
571 
572 #include <stdio.h>
573 
574 const PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const
575 {
576 
577  // Look for the BOARD specific copper layer names
578  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
579  {
580  if ( IsCopperLayer( layer ) && ( m_Layer[ layer ].m_name == aLayerName ) )
581  {
582  return ToLAYER_ID( layer );
583  }
584  }
585 
586  // Otherwise fall back to the system standard layer names
587  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
588  {
589  if( GetStandardLayerName( ToLAYER_ID( layer ) ) == aLayerName )
590  {
591  return ToLAYER_ID( layer );
592  }
593  }
594 
595  return UNDEFINED_LAYER;
596 }
597 
598 const wxString BOARD::GetLayerName( PCB_LAYER_ID aLayer ) const
599 {
600  // All layer names are stored in the BOARD.
601  if( IsLayerEnabled( aLayer ) )
602  {
603  // Standard names were set in BOARD::BOARD() but they may be
604  // over-ridden by BOARD::SetLayerName().
605  // For copper layers, return the actual copper layer name,
606  // otherwise return the Standard English layer name.
607  if( IsCopperLayer( aLayer ) )
608  return m_Layer[aLayer].m_name;
609  }
610 
611  return GetStandardLayerName( aLayer );
612 }
613 
614 bool BOARD::SetLayerName( PCB_LAYER_ID aLayer, const wxString& aLayerName )
615 {
616  if( !IsCopperLayer( aLayer ) )
617  return false;
618 
619  if( aLayerName == wxEmptyString || aLayerName.Len() > 20 )
620  return false;
621 
622  // no quote chars in the name allowed
623  if( aLayerName.Find( wxChar( '"' ) ) != wxNOT_FOUND )
624  return false;
625 
626  wxString nameTemp = aLayerName;
627 
628  // replace any spaces with underscores before we do any comparing
629  nameTemp.Replace( wxT( " " ), wxT( "_" ) );
630 
631  if( IsLayerEnabled( aLayer ) )
632  {
633 #if 0
634  for( LAYER_NUM i = FIRST_COPPER_LAYER; i < NB_COPPER_LAYERS; ++i )
635  {
636  if( i != aLayer && IsLayerEnabled( i ) && nameTemp == m_Layer[i].m_Name )
637  return false;
638  }
639 #else
640  for( LSEQ cu = GetEnabledLayers().CuStack(); cu; ++cu )
641  {
642  PCB_LAYER_ID id = *cu;
643 
644  // veto changing the name if it exists elsewhere.
645  if( id != aLayer && nameTemp == m_Layer[id].m_name )
646 // if( id != aLayer && nameTemp == wxString( m_Layer[id].m_name ) )
647  return false;
648  }
649 #endif
650 
651  m_Layer[aLayer].m_name = nameTemp;
652 
653  return true;
654  }
655 
656  return false;
657 }
658 
659 
661 {
662  if( !IsCopperLayer( aLayer ) )
663  return LT_SIGNAL;
664 
665  //@@IMB: The original test was broken due to the discontinuity
666  // in the layer sequence.
667  if( IsLayerEnabled( aLayer ) )
668  return m_Layer[aLayer].m_type;
669 
670  return LT_SIGNAL;
671 }
672 
673 
674 bool BOARD::SetLayerType( PCB_LAYER_ID aLayer, LAYER_T aLayerType )
675 {
676  if( !IsCopperLayer( aLayer ) )
677  return false;
678 
679  //@@IMB: The original test was broken due to the discontinuity
680  // in the layer sequence.
681  if( IsLayerEnabled( aLayer ) )
682  {
683  m_Layer[aLayer].m_type = aLayerType;
684  return true;
685  }
686 
687  return false;
688 }
689 
690 
691 const char* LAYER::ShowType( LAYER_T aType )
692 {
693  const char* cp;
694 
695  switch( aType )
696  {
697  default:
698  case LT_SIGNAL:
699  cp = "signal";
700  break;
701 
702  case LT_POWER:
703  cp = "power";
704  break;
705 
706  case LT_MIXED:
707  cp = "mixed";
708  break;
709 
710  case LT_JUMPER:
711  cp = "jumper";
712  break;
713  }
714 
715  return cp;
716 }
717 
718 
719 LAYER_T LAYER::ParseType( const char* aType )
720 {
721  if( strcmp( aType, "signal" ) == 0 )
722  return LT_SIGNAL;
723  else if( strcmp( aType, "power" ) == 0 )
724  return LT_POWER;
725  else if( strcmp( aType, "mixed" ) == 0 )
726  return LT_MIXED;
727  else if( strcmp( aType, "jumper" ) == 0 )
728  return LT_JUMPER;
729  else
730  return LT_UNDEFINED;
731 }
732 
733 
735 {
737 }
738 
739 
740 void BOARD::SetCopperLayerCount( int aCount )
741 {
743 }
744 
745 
747 {
749 }
750 
751 
753 {
755 }
756 
757 
758 void BOARD::SetEnabledLayers( LSET aLayerSet )
759 {
760  m_designSettings.SetEnabledLayers( aLayerSet );
761 }
762 
763 
764 void BOARD::SetVisibleLayers( LSET aLayerSet )
765 {
766  m_designSettings.SetVisibleLayers( aLayerSet );
767 }
768 
769 
770 void BOARD::SetVisibleElements( int aMask )
771 {
772  // Call SetElementVisibility for each item
773  // to ensure specific calculations that can be needed by some items,
774  // just changing the visibility flags could be not sufficient.
776  {
777  int item_mask = 1 << GAL_LAYER_INDEX( ii );
778  SetElementVisibility( ii, aMask & item_mask );
779  }
780 }
781 
782 
784 {
785  SetVisibleLayers( LSET().set() );
786 
787  // Call SetElementVisibility for each item,
788  // to ensure specific calculations that can be needed by some items
790  SetElementVisibility( ii, true );
791 }
792 
793 
795 {
797 }
798 
799 
801 {
802  return m_designSettings.IsElementVisible( aLayer );
803 }
804 
805 
806 void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
807 {
808  m_designSettings.SetElementVisibility( aLayer, isEnabled );
809 
810  switch( aLayer )
811  {
812  case LAYER_RATSNEST:
813  {
814  bool visible = IsElementVisible( LAYER_RATSNEST );
815  // we must clear or set the CH_VISIBLE flags to hide/show ratsnest
816  // because we have a tool to show/hide ratsnest relative to a pad or a module
817  // so the hide/show option is a per item selection
818 
819  for( unsigned int net = 1; net < GetNetCount(); net++ )
820  {
821  auto rn = GetConnectivity()->GetRatsnestForNet( net );
822  if( rn )
823  rn->SetVisible( visible );
824  }
825 
826  for( auto track : Tracks() )
827  track->SetLocalRatsnestVisible( isEnabled );
828 
829  for( auto mod : Modules() )
830  {
831  for( auto pad : mod->Pads() )
832  pad->SetLocalRatsnestVisible( isEnabled );
833  }
834 
835  for( int i = 0; i<GetAreaCount(); i++ )
836  {
837  auto zone = GetArea( i );
838  zone->SetLocalRatsnestVisible( isEnabled );
839  }
840 
841  m_Status_Pcb = 0;
842 
843  break;
844  }
845 
846  default:
847  ;
848  }
849 }
850 
851 
853 {
854  switch( aLayer )
855  {
856  case F_Cu:
857  return IsElementVisible( LAYER_MOD_FR );
858 
859  case B_Cu:
860  return IsElementVisible( LAYER_MOD_BK );
861 
862  default:
863  wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible() param error: bad layer" ) );
864  return true;
865  }
866 }
867 
868 
869 void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
870 {
871  if( aBoardItem == NULL )
872  {
873  wxFAIL_MSG( wxT( "BOARD::Add() param error: aBoardItem NULL" ) );
874  return;
875  }
876 
877  switch( aBoardItem->Type() )
878  {
879  case PCB_NETINFO_T:
880  m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
881  break;
882 
883  // this one uses a vector
884  case PCB_MARKER_T:
885  m_markers.push_back( (MARKER_PCB*) aBoardItem );
886  break;
887 
888  // this one uses a vector
889  case PCB_ZONE_AREA_T:
890  m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
891  break;
892 
893  case PCB_TRACE_T:
894  case PCB_VIA_T:
895  if( aMode == ADD_APPEND )
896  {
897  m_Track.PushBack( (TRACK*) aBoardItem );
898  }
899  else
900  {
901  TRACK* insertAid;
902  insertAid = ( (TRACK*) aBoardItem )->GetBestInsertPoint( this );
903  m_Track.Insert( (TRACK*) aBoardItem, insertAid );
904  }
905 
906  break;
907 
908  case PCB_ZONE_T:
909  if( aMode == ADD_APPEND )
910  m_SegZoneDeprecated.PushBack( (SEGZONE*) aBoardItem );
911  else
912  m_SegZoneDeprecated.PushFront( (SEGZONE*) aBoardItem );
913 
914  break;
915 
916  case PCB_MODULE_T:
917  if( aMode == ADD_APPEND )
918  m_Modules.PushBack( (MODULE*) aBoardItem );
919  else
920  m_Modules.PushFront( (MODULE*) aBoardItem );
921 
922  // Because the list of pads has changed, reset the status
923  // This indicate the list of pad and nets must be recalculated before use
924  m_Status_Pcb = 0;
925  break;
926 
927  case PCB_DIMENSION_T:
928  case PCB_LINE_T:
929  case PCB_TEXT_T:
930  case PCB_TARGET_T:
931  if( aMode == ADD_APPEND )
932  m_Drawings.PushBack( aBoardItem );
933  else
934  m_Drawings.PushFront( aBoardItem );
935 
936  break;
937 
938  // other types may use linked list
939  default:
940  {
941  wxString msg;
942  msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
943  aBoardItem->Type() );
944  wxFAIL_MSG( msg );
945  return;
946  }
947  break;
948  }
949 
950  aBoardItem->SetParent( this );
951  m_connectivity->Add( aBoardItem );
952 }
953 
954 
955 void BOARD::Remove( BOARD_ITEM* aBoardItem )
956 {
957  // find these calls and fix them! Don't send me no stinking' NULL.
958  wxASSERT( aBoardItem );
959 
960  switch( aBoardItem->Type() )
961  {
962  case PCB_NETINFO_T:
963  {
964  NETINFO_ITEM* item = (NETINFO_ITEM*) aBoardItem;
965  m_NetInfo.RemoveNet( item );
966  break;
967  }
968 
969  case PCB_MARKER_T:
970 
971  // find the item in the vector, then remove it
972  for( unsigned i = 0; i<m_markers.size(); ++i )
973  {
974  if( m_markers[i] == (MARKER_PCB*) aBoardItem )
975  {
976  m_markers.erase( m_markers.begin() + i );
977  break;
978  }
979  }
980 
981  break;
982 
983  case PCB_ZONE_AREA_T: // this one uses a vector
984  // find the item in the vector, then delete then erase it.
985  for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
986  {
987  if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
988  {
989  m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
990  break;
991  }
992  }
993  break;
994 
995  case PCB_MODULE_T:
996  m_Modules.Remove( (MODULE*) aBoardItem );
997  break;
998 
999  case PCB_TRACE_T:
1000  case PCB_VIA_T:
1001  m_Track.Remove( (TRACK*) aBoardItem );
1002  break;
1003 
1004  case PCB_ZONE_T:
1005  m_SegZoneDeprecated.Remove( (SEGZONE*) aBoardItem );
1006  break;
1007 
1008  case PCB_DIMENSION_T:
1009  case PCB_LINE_T:
1010  case PCB_TEXT_T:
1011  case PCB_TARGET_T:
1012  m_Drawings.Remove( aBoardItem );
1013  break;
1014 
1015  // other types may use linked list
1016  default:
1017  wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
1018  }
1019 
1020  m_connectivity->Remove( aBoardItem );
1021 }
1022 
1023 
1025 {
1026  // the vector does not know how to delete the MARKER_PCB, it holds pointers
1027  for( unsigned i = 0; i<m_markers.size(); ++i )
1028  delete m_markers[i];
1029 
1030  m_markers.clear();
1031 }
1032 
1033 
1035 {
1036  // the vector does not know how to delete the ZONE Outlines, it holds
1037  // pointers
1038  for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
1039  delete m_ZoneDescriptorList[i];
1040 
1041  m_ZoneDescriptorList.clear();
1042 }
1043 
1044 
1045 BOARD_ITEM* BOARD::GetItem( void* aWeakReference, bool includeDrawings )
1046 {
1047  for( TRACK* track : Tracks() )
1048  if( track == aWeakReference )
1049  return track;
1050 
1051  for( MODULE* module : Modules() )
1052  {
1053  if( module == aWeakReference )
1054  return module;
1055 
1056  for( D_PAD* pad : module->Pads() )
1057  if( pad == aWeakReference )
1058  return pad;
1059 
1060  if( includeDrawings )
1061  {
1062  for( BOARD_ITEM* drawing : module->GraphicalItems() )
1063  if( drawing == aWeakReference )
1064  return drawing;
1065  }
1066  }
1067 
1068  for( ZONE_CONTAINER* zone : Zones() )
1069  if( zone == aWeakReference )
1070  return zone;
1071 
1072  if( includeDrawings )
1073  {
1074  for( BOARD_ITEM* drawing : Drawings() )
1075  if( drawing == aWeakReference )
1076  return drawing;
1077  }
1078 
1079  // Not found; weak reference has been deleted.
1080  return &g_DeletedItem;
1081 }
1082 
1083 
1085 {
1086  return m_Track.GetCount();
1087 }
1088 
1089 
1091 {
1092  return m_SegZoneDeprecated.GetCount();
1093 }
1094 
1095 
1096 unsigned BOARD::GetNodesCount( int aNet )
1097 {
1098  unsigned retval = 0;
1099  for( auto mod : Modules() )
1100  {
1101  for( auto pad : mod->Pads() )
1102  {
1103  if( ( aNet == -1 && pad->GetNetCode() > 0 ) || aNet == pad->GetNetCode() )
1104  retval++;
1105  }
1106  }
1107 
1108  return retval;
1109 }
1110 
1111 
1113 {
1114  return m_connectivity->GetUnconnectedCount();
1115 }
1116 
1117 
1118 EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
1119 {
1120  bool hasItems = false;
1121  EDA_RECT area;
1122 
1123  // Check segments, dimensions, texts, and fiducials
1124  for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
1125  {
1126  if( aBoardEdgesOnly && (item->Type() != PCB_LINE_T || item->GetLayer() != Edge_Cuts ) )
1127  continue;
1128 
1129  if( !hasItems )
1130  area = item->GetBoundingBox();
1131  else
1132  area.Merge( item->GetBoundingBox() );
1133 
1134  hasItems = true;
1135  }
1136 
1137  if( !aBoardEdgesOnly )
1138  {
1139  // Check modules
1140  for( MODULE* module = m_Modules; module; module = module->Next() )
1141  {
1142  if( !hasItems )
1143  area = module->GetBoundingBox();
1144  else
1145  area.Merge( module->GetBoundingBox() );
1146 
1147  hasItems = true;
1148  }
1149 
1150  // Check tracks
1151  for( TRACK* track = m_Track; track; track = track->Next() )
1152  {
1153  if( !hasItems )
1154  area = track->GetBoundingBox();
1155  else
1156  area.Merge( track->GetBoundingBox() );
1157 
1158  hasItems = true;
1159  }
1160 
1161  // Check segment zones
1162  for( TRACK* track = m_SegZoneDeprecated; track; track = track->Next() )
1163  {
1164  if( !hasItems )
1165  area = track->GetBoundingBox();
1166  else
1167  area.Merge( track->GetBoundingBox() );
1168 
1169  hasItems = true;
1170  }
1171 
1172  // Check polygonal zones
1173  for( unsigned int i = 0; i < m_ZoneDescriptorList.size(); i++ )
1174  {
1176 
1177  if( !hasItems )
1178  area = aZone->GetBoundingBox();
1179  else
1180  area.Merge( aZone->GetBoundingBox() );
1181 
1182  area.Merge( aZone->GetBoundingBox() );
1183  hasItems = true;
1184  }
1185  }
1186 
1187  return area;
1188 }
1189 
1190 
1191 void BOARD::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector< MSG_PANEL_ITEM >& aList )
1192 {
1193  wxString txt;
1194  int viasCount = 0;
1195  int trackSegmentsCount = 0;
1196 
1197  for( BOARD_ITEM* item = m_Track; item; item = item->Next() )
1198  {
1199  if( item->Type() == PCB_VIA_T )
1200  viasCount++;
1201  else
1202  trackSegmentsCount++;
1203  }
1204 
1205  txt.Printf( wxT( "%d" ), GetPadCount() );
1206  aList.push_back( MSG_PANEL_ITEM( _( "Pads" ), txt, DARKGREEN ) );
1207 
1208  txt.Printf( wxT( "%d" ), viasCount );
1209  aList.push_back( MSG_PANEL_ITEM( _( "Vias" ), txt, DARKGREEN ) );
1210 
1211  txt.Printf( wxT( "%d" ), trackSegmentsCount );
1212  aList.push_back( MSG_PANEL_ITEM( _( "Track Segments" ), txt, DARKGREEN ) );
1213 
1214  txt.Printf( wxT( "%d" ), GetNodesCount() );
1215  aList.push_back( MSG_PANEL_ITEM( _( "Nodes" ), txt, DARKCYAN ) );
1216 
1217  txt.Printf( wxT( "%d" ), m_NetInfo.GetNetCount() );
1218  aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
1219 
1220  txt.Printf( wxT( "%d" ), GetConnectivity()->GetUnconnectedCount() );
1221  aList.push_back( MSG_PANEL_ITEM( _( "Unrouted" ), txt, BLUE ) );
1222 }
1223 
1224 
1225 SEARCH_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1226 {
1227  KICAD_T stype;
1228  SEARCH_RESULT result = SEARCH_CONTINUE;
1229  const KICAD_T* p = scanTypes;
1230  bool done = false;
1231 
1232 #if 0 && defined(DEBUG)
1233  std::cout << GetClass().mb_str() << ' ';
1234 #endif
1235 
1236  while( !done )
1237  {
1238  stype = *p;
1239 
1240  switch( stype )
1241  {
1242  case PCB_T:
1243  result = inspector( this, testData ); // inspect me
1244  // skip over any types handled in the above call.
1245  ++p;
1246  break;
1247 
1248  /* Instances of the requested KICAD_T live in a list, either one
1249  * that I manage, or that my modules manage. If it's a type managed
1250  * by class MODULE, then simply pass it on to each module's
1251  * MODULE::Visit() function by way of the
1252  * IterateForward( m_Modules, ... ) call.
1253  */
1254 
1255  case PCB_MODULE_T:
1256  case PCB_PAD_T:
1257  case PCB_MODULE_TEXT_T:
1258  case PCB_MODULE_EDGE_T:
1259 
1260  // this calls MODULE::Visit() on each module.
1261  result = IterateForward( m_Modules, inspector, testData, p );
1262 
1263  // skip over any types handled in the above call.
1264  for( ; ; )
1265  {
1266  switch( stype = *++p )
1267  {
1268  case PCB_MODULE_T:
1269  case PCB_PAD_T:
1270  case PCB_MODULE_TEXT_T:
1271  case PCB_MODULE_EDGE_T:
1272  continue;
1273 
1274  default:
1275  ;
1276  }
1277 
1278  break;
1279  }
1280 
1281  break;
1282 
1283  case PCB_LINE_T:
1284  case PCB_TEXT_T:
1285  case PCB_DIMENSION_T:
1286  case PCB_TARGET_T:
1287  result = IterateForward( m_Drawings, inspector, testData, p );
1288 
1289  // skip over any types handled in the above call.
1290  for( ; ; )
1291  {
1292  switch( stype = *++p )
1293  {
1294  case PCB_LINE_T:
1295  case PCB_TEXT_T:
1296  case PCB_DIMENSION_T:
1297  case PCB_TARGET_T:
1298  continue;
1299 
1300  default:
1301  ;
1302  }
1303 
1304  break;
1305  }
1306 
1307  ;
1308  break;
1309 
1310 #if 0 // both these are on same list, so we must scan it twice in order
1311  // to get VIA priority, using new #else code below.
1312  // But we are not using separate lists for TRACKs and VIA, because
1313  // items are ordered (sorted) in the linked
1314  // list by netcode AND by physical distance:
1315  // when created, if a track or via is connected to an existing track or
1316  // via, it is put in linked list after this existing track or via
1317  // So usually, connected tracks or vias are grouped in this list
1318  // So the algorithm (used in ratsnest computations) which computes the
1319  // track connectivity is faster (more than 100 time regarding to
1320  // a non ordered list) because when it searches for a connection, first
1321  // it tests the near (near in term of linked list) 50 items
1322  // from the current item (track or via) in test.
1323  // Usually, because of this sort, a connected item (if exists) is
1324  // found.
1325  // If not found (and only in this case) an exhaustive (and time
1326  // consuming) search is made, but this case is statistically rare.
1327  case PCB_VIA_T:
1328  case PCB_TRACE_T:
1329  result = IterateForward( m_Track, inspector, testData, p );
1330 
1331  // skip over any types handled in the above call.
1332  for( ; ; )
1333  {
1334  switch( stype = *++p )
1335  {
1336  case PCB_VIA_T:
1337  case PCB_TRACE_T:
1338  continue;
1339 
1340  default:
1341  ;
1342  }
1343 
1344  break;
1345  }
1346 
1347  break;
1348 
1349 #else
1350  case PCB_VIA_T:
1351  result = IterateForward( m_Track, inspector, testData, p );
1352  ++p;
1353  break;
1354 
1355  case PCB_TRACE_T:
1356  result = IterateForward( m_Track, inspector, testData, p );
1357  ++p;
1358  break;
1359 #endif
1360 
1361  case PCB_MARKER_T:
1362 
1363  // MARKER_PCBS are in the m_markers std::vector
1364  for( unsigned i = 0; i<m_markers.size(); ++i )
1365  {
1366  result = m_markers[i]->Visit( inspector, testData, p );
1367 
1368  if( result == SEARCH_QUIT )
1369  break;
1370  }
1371 
1372  ++p;
1373  break;
1374 
1375  case PCB_ZONE_AREA_T:
1376 
1377  // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
1378  for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
1379  {
1380  result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
1381 
1382  if( result == SEARCH_QUIT )
1383  break;
1384  }
1385 
1386  ++p;
1387  break;
1388 
1389  case PCB_ZONE_T:
1390  result = IterateForward( m_SegZoneDeprecated, inspector, testData, p );
1391  ++p;
1392  break;
1393 
1394  default: // catch EOT or ANY OTHER type here and return.
1395  done = true;
1396  break;
1397  }
1398 
1399  if( result == SEARCH_QUIT )
1400  break;
1401  }
1402 
1403  return result;
1404 }
1405 
1406 
1407 NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
1408 {
1409  // the first valid netcode is 1 and the last is m_NetInfo.GetCount()-1.
1410  // zero is reserved for "no connection" and is not actually a net.
1411  // NULL is returned for non valid netcodes
1412 
1413  wxASSERT( m_NetInfo.GetNetCount() > 0 ); // net zero should exist
1414 
1415  if( aNetcode == NETINFO_LIST::UNCONNECTED && m_NetInfo.GetNetCount() == 0 )
1417  else
1418  return m_NetInfo.GetNetItem( aNetcode );
1419 }
1420 
1421 
1422 NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
1423 {
1424  return m_NetInfo.GetNetItem( aNetname );
1425 }
1426 
1427 
1428 MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
1429 {
1430  MODULE* found = nullptr;
1431 
1432  // search only for MODULES
1433  static const KICAD_T scanTypes[] = { PCB_MODULE_T, EOT };
1434 
1435  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
1436  {
1437  MODULE* module = (MODULE*) item;
1438 
1439  if( aReference == module->GetReference() )
1440  {
1441  found = module;
1442  return SEARCH_QUIT;
1443  }
1444 
1445  return SEARCH_CONTINUE;
1446  };
1447 
1448  // visit this BOARD with the above inspector
1449  BOARD* nonconstMe = (BOARD*) this;
1450  nonconstMe->Visit( inspector, NULL, scanTypes );
1451 
1452  return found;
1453 }
1454 
1455 
1456 MODULE* BOARD::FindModule( const wxString& aRefOrTimeStamp, bool aSearchByTimeStamp ) const
1457 {
1458  if( aSearchByTimeStamp )
1459  {
1460  for( MODULE* module = m_Modules; module; module = module->Next() )
1461  {
1462  if( aRefOrTimeStamp.CmpNoCase( module->GetPath() ) == 0 )
1463  return module;
1464  }
1465  }
1466  else
1467  {
1468  return FindModuleByReference( aRefOrTimeStamp );
1469  }
1470 
1471  return NULL;
1472 }
1473 
1474 
1475 
1476 // The pad count for each netcode, stored in a buffer for a fast access.
1477 // This is needed by the sort function sortNetsByNodes()
1478 static std::vector<int> padCountListByNet;
1479 
1480 // Sort nets by decreasing pad count.
1481 // For same pad count, sort by alphabetic names
1482 static bool sortNetsByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1483 {
1484  int countA = padCountListByNet[a->GetNet()];
1485  int countB = padCountListByNet[b->GetNet()];
1486 
1487  if( countA == countB )
1488  return a->GetNetname() < b->GetNetname();
1489  else
1490  return countB < countA;
1491 }
1492 
1493 // Sort nets by alphabetic names
1494 static bool sortNetsByNames( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
1495 {
1496  return a->GetNetname() < b->GetNetname();
1497 }
1498 
1499 int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
1500 {
1501  if( m_NetInfo.GetNetCount() == 0 )
1502  return 0;
1503 
1504  // Build the list
1505  std::vector <NETINFO_ITEM*> netBuffer;
1506 
1507  netBuffer.reserve( m_NetInfo.GetNetCount() );
1508 
1509  for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
1510  net != netEnd; ++net )
1511  {
1512  if( net->GetNet() > 0 )
1513  netBuffer.push_back( *net );
1514  }
1515 
1516  // sort the list
1517  if( aSortbyPadsCount )
1518  {
1519  // Build the pad count by net:
1520  padCountListByNet.clear();
1521  std::vector<D_PAD*> pads = GetPads();
1522 
1523  // Calculate the max value of net codes, and creates the buffer to
1524  // store the pad count by net code
1525  int max_netcode = 0;
1526 
1527  for( D_PAD* pad : pads )
1528  max_netcode = std::max( max_netcode, pad->GetNetCode() );
1529 
1530  padCountListByNet.assign( max_netcode+1, 0 );
1531 
1532  for( D_PAD* pad : pads )
1533  padCountListByNet[pad->GetNetCode()]++;
1534 
1535  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNodes );
1536  }
1537  else
1538  sort( netBuffer.begin(), netBuffer.end(), sortNetsByNames );
1539 
1540  for( unsigned ii = 0; ii < netBuffer.size(); ii++ )
1541  aNames.Add( netBuffer[ii]->GetNetname() );
1542 
1543  return netBuffer.size();
1544 }
1545 
1546 
1547 void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1548 {
1549  if( !aDC )
1550  return;
1551 
1552  for( int ii = 0; ii < GetAreaCount(); ii++ )
1553  {
1554  ZONE_CONTAINER* edge_zone = GetArea( ii );
1555 
1556  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1557  edge_zone->Draw( panel, aDC, aDrawMode );
1558  }
1559 }
1560 
1561 
1562 void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, PCB_LAYER_ID aLayer )
1563 {
1564  if( !aDC )
1565  return;
1566 
1567  for( int ii = 0; ii < GetAreaCount(); ii++ )
1568  {
1569  ZONE_CONTAINER* edge_zone = GetArea( ii );
1570 
1571  if( (aLayer < 0) || ( aLayer == edge_zone->GetLayer() ) )
1572  edge_zone->DrawFilledArea( panel, aDC, aDrawMode );
1573  }
1574 }
1575 
1576 
1578  PCB_LAYER_ID aStartLayer, PCB_LAYER_ID aEndLayer, int aNetCode )
1579 {
1580  if( aEndLayer < 0 )
1581  aEndLayer = aStartLayer;
1582 
1583  if( aEndLayer < aStartLayer )
1584  std::swap( aEndLayer, aStartLayer );
1585 
1586  for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
1587  {
1589  LAYER_NUM layer = area->GetLayer();
1590 
1591  if( layer < aStartLayer || layer > aEndLayer )
1592  continue;
1593 
1594  // In locate functions we must skip tagged items with BUSY flag set.
1595  if( area->GetState( BUSY ) )
1596  continue;
1597 
1598  if( aNetCode >= 0 && area->GetNetCode() != aNetCode )
1599  continue;
1600 
1601  if( area->HitTestFilledArea( aRefPos ) )
1602  return area;
1603  }
1604 
1605  return NULL;
1606 }
1607 
1608 
1610 {
1611  int error_count = 0;
1612 
1613  for( int ii = 0; ii < GetAreaCount(); ii++ )
1614  {
1615  ZONE_CONTAINER* it = GetArea( ii );
1616 
1617  if( !it->IsOnCopperLayer() )
1618  {
1620  continue;
1621  }
1622 
1623  if( it->GetNetCode() != 0 ) // i.e. if this zone is connected to a net
1624  {
1625  const NETINFO_ITEM* net = it->GetNet();
1626 
1627  if( net )
1628  {
1629  it->SetNetCode( net->GetNet() );
1630  }
1631  else
1632  {
1633  error_count++;
1634 
1635  // keep Net Name and set m_NetCode to -1 : error flag.
1636  it->SetNetCode( -1 );
1637  }
1638  }
1639  }
1640 
1641  return error_count;
1642 }
1643 
1644 
1645 VIA* BOARD::GetViaByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer) const
1646 {
1647  for( VIA *via = GetFirstVia( m_Track); via; via = GetFirstVia( via->Next() ) )
1648  {
1649  if( (via->GetStart() == aPosition) &&
1650  (via->GetState( BUSY | IS_DELETED ) == 0) &&
1651  ((aLayer == UNDEFINED_LAYER) || (via->IsOnLayer( aLayer ))) )
1652  return via;
1653  }
1654 
1655  return NULL;
1656 }
1657 
1658 
1659 D_PAD* BOARD::GetPad( const wxPoint& aPosition, LSET aLayerSet )
1660 {
1661  if( !aLayerSet.any() )
1662  aLayerSet = LSET::AllCuMask();
1663 
1664  for( MODULE* module = m_Modules; module; module = module->Next() )
1665  {
1666  D_PAD* pad = NULL;
1667 
1668  if( module->HitTest( aPosition ) )
1669  pad = module->GetPad( aPosition, aLayerSet );
1670 
1671  if( pad )
1672  return pad;
1673  }
1674 
1675  return NULL;
1676 }
1677 
1678 
1679 D_PAD* BOARD::GetPad( TRACK* aTrace, ENDPOINT_T aEndPoint )
1680 {
1681  const wxPoint& aPosition = aTrace->GetEndPoint( aEndPoint );
1682 
1683  LSET lset( aTrace->GetLayer() );
1684 
1685  return GetPad( aPosition, lset );
1686 }
1687 
1688 
1689 std::list<TRACK*> BOARD::GetTracksByPosition( const wxPoint& aPosition, PCB_LAYER_ID aLayer ) const
1690 {
1691  std::list<TRACK*> tracks;
1692 
1693  for( TRACK* track = GetFirstTrack( m_Track ); track; track = GetFirstTrack( track->Next() ) )
1694  {
1695  if( ( ( track->GetStart() == aPosition ) || track->GetEnd() == aPosition ) &&
1696  ( track->GetState( BUSY | IS_DELETED ) == 0 ) &&
1697  ( ( aLayer == UNDEFINED_LAYER ) || ( track->IsOnLayer( aLayer ) ) ) )
1698 
1699  tracks.push_back( track );
1700  }
1701 
1702  return tracks;
1703 }
1704 
1705 
1706 D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, LSET aLayerSet )
1707 {
1708  for( auto mod : Modules() )
1709  {
1710  for ( auto pad : mod->Pads() )
1711  {
1712  if( pad->GetPosition() != aPosition )
1713  continue;
1714 
1715  // Pad found, it must be on the correct layer
1716  if( ( pad->GetLayerSet() & aLayerSet ).any() )
1717  return pad;
1718  }
1719  }
1720 
1721  return nullptr;
1722 }
1723 
1724 
1725 D_PAD* BOARD::GetPad( std::vector<D_PAD*>& aPadList, const wxPoint& aPosition, LSET aLayerSet )
1726 {
1727  // Search aPadList for aPosition
1728  // aPadList is sorted by X then Y values, and a fast binary search is used
1729  int idxmax = aPadList.size()-1;
1730 
1731  int delta = aPadList.size();
1732 
1733  int idx = 0; // Starting index is the beginning of list
1734 
1735  while( delta )
1736  {
1737  // Calculate half size of remaining interval to test.
1738  // Ensure the computed value is not truncated (too small)
1739  if( (delta & 1) && ( delta > 1 ) )
1740  delta++;
1741 
1742  delta /= 2;
1743 
1744  D_PAD* pad = aPadList[idx];
1745 
1746  if( pad->GetPosition() == aPosition ) // candidate found
1747  {
1748  // The pad must match the layer mask:
1749  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1750  return pad;
1751 
1752  // More than one pad can be at aPosition
1753  // search for a pad at aPosition that matched this mask
1754 
1755  // search next
1756  for( int ii = idx+1; ii <= idxmax; ii++ )
1757  {
1758  pad = aPadList[ii];
1759 
1760  if( pad->GetPosition() != aPosition )
1761  break;
1762 
1763  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1764  return pad;
1765  }
1766  // search previous
1767  for( int ii = idx-1 ;ii >=0; ii-- )
1768  {
1769  pad = aPadList[ii];
1770 
1771  if( pad->GetPosition() != aPosition )
1772  break;
1773 
1774  if( ( aLayerSet & pad->GetLayerSet() ).any() )
1775  return pad;
1776  }
1777 
1778  // Not found:
1779  return 0;
1780  }
1781 
1782  if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate
1783  {
1784  if( pad->GetPosition().y < aPosition.y ) // Must search after this item
1785  {
1786  idx += delta;
1787 
1788  if( idx > idxmax )
1789  idx = idxmax;
1790  }
1791  else // Must search before this item
1792  {
1793  idx -= delta;
1794 
1795  if( idx < 0 )
1796  idx = 0;
1797  }
1798  }
1799  else if( pad->GetPosition().x < aPosition.x ) // Must search after this item
1800  {
1801  idx += delta;
1802 
1803  if( idx > idxmax )
1804  idx = idxmax;
1805  }
1806  else // Must search before this item
1807  {
1808  idx -= delta;
1809 
1810  if( idx < 0 )
1811  idx = 0;
1812  }
1813  }
1814 
1815  return NULL;
1816 }
1817 
1818 
1824 bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp )
1825 {
1826  if( ref->GetPosition().x == comp->GetPosition().x )
1827  return ref->GetPosition().y < comp->GetPosition().y;
1828  return ref->GetPosition().x < comp->GetPosition().x;
1829 }
1830 
1831 
1832 void BOARD::GetSortedPadListByXthenYCoord( std::vector<D_PAD*>& aVector, int aNetCode )
1833 {
1834  for ( auto mod : Modules() )
1835  {
1836  for ( auto pad : mod->Pads( ) )
1837  {
1838  if( aNetCode < 0 || pad->GetNetCode() == aNetCode )
1839  {
1840  aVector.push_back( pad );
1841  }
1842  }
1843  }
1844 
1845  std::sort( aVector.begin(), aVector.end(), sortPadsByXthenYCoord );
1846 }
1847 
1848 
1850 {
1851  GetConnectivity()->Remove( aPad );
1852  aPad->DeleteStructure();
1853 }
1854 
1855 
1856 TRACK* BOARD::GetVisibleTrack( TRACK* aStartingTrace, const wxPoint& aPosition,
1857  LSET aLayerSet ) const
1858 {
1859  for( TRACK* track = aStartingTrace; track; track = track->Next() )
1860  {
1861  PCB_LAYER_ID layer = track->GetLayer();
1862 
1863  if( track->GetState( BUSY | IS_DELETED ) )
1864  continue;
1865 
1866  // track's layer is not visible
1867  if( m_designSettings.IsLayerVisible( layer ) == false )
1868  continue;
1869 
1870  if( track->Type() == PCB_VIA_T ) // VIA encountered.
1871  {
1872  if( track->HitTest( aPosition ) )
1873  return track;
1874  }
1875  else
1876  {
1877  if( !aLayerSet[layer] )
1878  continue; // track's layer is not in aLayerSet
1879 
1880  if( track->HitTest( aPosition ) )
1881  return track;
1882  }
1883  }
1884 
1885  return NULL;
1886 }
1887 
1888 
1889 TRACK* BOARD::MarkTrace( TRACK* aTrackList, TRACK* aTrace, int* aCount,
1890  double* aTraceLength, double* aPadToDieLength,
1891  bool aReorder )
1892 {
1893  TRACKS trackList;
1894 
1895  if( aCount )
1896  *aCount = 0;
1897 
1898  if( aTraceLength )
1899  *aTraceLength = 0;
1900 
1901  if( aTrace == NULL )
1902  return NULL;
1903 
1904  // Ensure the flag BUSY of all tracks of the board is cleared
1905  // because we use it to mark segments of the track
1906  for( TRACK* track = aTrackList; track; track = track->Next() )
1907  track->SetState( BUSY, false );
1908 
1909  // Set flags of the initial track segment
1910  aTrace->SetState( BUSY, true );
1911  LSET layer_set = aTrace->GetLayerSet();
1912 
1913  trackList.push_back( aTrace );
1914 
1915  /* Examine the initial track segment : if it is really a segment, this is
1916  * easy.
1917  * If it is a via, one must search for connected segments.
1918  * If <=2, this via connect 2 segments (or is connected to only one
1919  * segment) and this via and these 2 segments are a part of a track.
1920  * If > 2 only this via is flagged (the track has only this via)
1921  */
1922  if( aTrace->Type() == PCB_VIA_T )
1923  {
1924  TRACK* segm1 = ::GetTrack( aTrackList, NULL, aTrace->GetStart(), layer_set );
1925  TRACK* segm2 = NULL;
1926  TRACK* segm3 = NULL;
1927 
1928  if( segm1 )
1929  {
1930  segm2 = ::GetTrack( segm1->Next(), NULL, aTrace->GetStart(), layer_set );
1931  }
1932 
1933  if( segm2 )
1934  {
1935  segm3 = ::GetTrack( segm2->Next(), NULL, aTrace->GetStart(), layer_set );
1936  }
1937 
1938  if( segm3 )
1939  {
1940  // More than 2 segments are connected to this via.
1941  // The "track" is only this via.
1942 
1943  if( aCount )
1944  *aCount = 1;
1945 
1946  return aTrace;
1947  }
1948 
1949  if( segm1 ) // search for other segments connected to the initial segment start point
1950  {
1951  layer_set = segm1->GetLayerSet();
1952  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1953  }
1954 
1955  if( segm2 ) // search for other segments connected to the initial segment end point
1956  {
1957  layer_set = segm2->GetLayerSet();
1958  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &trackList );
1959  }
1960  }
1961  else // mark the chain using both ends of the initial segment
1962  {
1963  TRACKS from_start;
1964  TRACKS from_end;
1965 
1966  chainMarkedSegments( aTrackList, aTrace->GetStart(), layer_set, &from_start );
1967  chainMarkedSegments( aTrackList, aTrace->GetEnd(), layer_set, &from_end );
1968 
1969  // combine into one trackList:
1970  trackList.insert( trackList.end(), from_start.begin(), from_start.end() );
1971  trackList.insert( trackList.end(), from_end.begin(), from_end.end() );
1972  }
1973 
1974  // Now examine selected vias and flag them if they are on the track
1975  // If a via is connected to only one or 2 segments, it is flagged (is on the track)
1976  // If a via is connected to more than 2 segments, it is a track end, and it
1977  // is removed from the list.
1978  // Go through the list backwards.
1979  for( int i = trackList.size() - 1; i>=0; --i )
1980  {
1981  ::VIA* via = dynamic_cast< ::VIA* >( trackList[i] );
1982 
1983  if( !via )
1984  continue;
1985 
1986  if( via == aTrace )
1987  continue;
1988 
1989  via->SetState( BUSY, true ); // Try to flag it. the flag will be cleared later if needed
1990 
1991  layer_set = via->GetLayerSet();
1992 
1993  TRACK* track = ::GetTrack( aTrackList, NULL, via->GetStart(), layer_set );
1994 
1995  // GetTrace does not consider tracks flagged BUSY.
1996  // So if no connected track found, this via is on the current track
1997  // only: keep it
1998  if( track == NULL )
1999  continue;
2000 
2001  /* If a track is found, this via connects also other segments of
2002  * the other track. This case happens when a via ends the selected
2003  * track but must we consider this via is on the selected track, or
2004  * on a other track.
2005  * (this is important when selecting a track for deletion: must this
2006  * via be deleted or not?)
2007  * We consider this via to be on our track if other segments connected
2008  * to this via remain connected when removing this via.
2009  * We search for all other segments connected together:
2010  * if they are on the same layer, then the via is on the selected track;
2011  * if they are on different layers, the via is on a other track.
2012  */
2013  LAYER_NUM layer = track->GetLayer();
2014 
2015  while( ( track = ::GetTrack( track->Next(), NULL, via->GetStart(), layer_set ) ) != NULL )
2016  {
2017  if( layer != track->GetLayer() )
2018  {
2019  // The via connects segments of a other track: it is removed
2020  // from list because it is member of a other track
2021  via->SetState( BUSY, false );
2022  break;
2023  }
2024  }
2025  }
2026 
2027  /* Rearrange the track list in order to have flagged segments linked
2028  * from firstTrack so the NbSegmBusy segments are consecutive segments
2029  * in list, the first item in the full track list is firstTrack, and
2030  * the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
2031  * are the flagged segments
2032  */
2033  int busy_count = 0;
2034  TRACK* firstTrack;
2035 
2036  for( firstTrack = aTrackList; firstTrack; firstTrack = firstTrack->Next() )
2037  {
2038  // Search for the first flagged BUSY segments
2039  if( firstTrack->GetState( BUSY ) )
2040  {
2041  busy_count = 1;
2042  break;
2043  }
2044  }
2045 
2046  if( firstTrack == NULL )
2047  return NULL;
2048 
2049  // First step: calculate the track length and find the pads (when exist)
2050  // at each end of the trace.
2051  double full_len = 0;
2052  double lenPadToDie = 0;
2053  // Because we have a track (a set of track segments between 2 nodes),
2054  // only 2 pads (maximum) will be taken in account:
2055  // that are on each end of the track, if any.
2056  // keep trace of them, to know the die length and the track length ibside each pad.
2057  D_PAD* s_pad = NULL; // the pad on one end of the trace
2058  D_PAD* e_pad = NULL; // the pad on the other end of the trace
2059  int dist_fromstart = INT_MAX;
2060  int dist_fromend = INT_MAX;
2061 
2062  for( TRACK* track = firstTrack; track; track = track->Next() )
2063  {
2064  if( !track->GetState( BUSY ) )
2065  continue;
2066 
2067  layer_set = track->GetLayerSet();
2068  D_PAD * pad_on_start = GetPad( track->GetStart(), layer_set );
2069  D_PAD * pad_on_end = GetPad( track->GetEnd(), layer_set );
2070 
2071  // a segment fully inside a pad does not contribute to the track len
2072  // (another track end inside this pad will contribute to this lenght)
2073  if( pad_on_start && ( pad_on_start == pad_on_end ) )
2074  continue;
2075 
2076  full_len += track->GetLength();
2077 
2078  if( pad_on_start == NULL && pad_on_end == NULL )
2079  // This most of time the case
2080  continue;
2081 
2082  // At this point, we can have one track end on a pad, or the 2 track ends on
2083  // 2 different pads.
2084  // We don't know what pad (s_pad or e_pad) must be used to store the
2085  // start point and the end point of the track, so if a pad is already set,
2086  // use the other
2087  if( pad_on_start )
2088  {
2089  SEG segm( track->GetStart(), pad_on_start->GetPosition() );
2090  int dist = segm.Length();
2091 
2092  if( s_pad == NULL )
2093  {
2094  dist_fromstart = dist;
2095  s_pad = pad_on_start;
2096  }
2097  else if( e_pad == NULL )
2098  {
2099  dist_fromend = dist;
2100  e_pad = pad_on_start;
2101  }
2102  else // Should not occur, at least for basic pads
2103  {
2104  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_start" );
2105  }
2106  }
2107 
2108  if( pad_on_end )
2109  {
2110  SEG segm( track->GetEnd(), pad_on_end->GetPosition() );
2111  int dist = segm.Length();
2112 
2113  if( s_pad == NULL )
2114  {
2115  dist_fromstart = dist;
2116  s_pad = pad_on_end;
2117  }
2118  else if( e_pad == NULL )
2119  {
2120  dist_fromend = dist;
2121  e_pad = pad_on_end;
2122  }
2123  else // Should not occur, at least for basic pads
2124  {
2125  wxLogWarning( "Unexpected BOARD::MarkTrace: multiple pad_on_end" );
2126  }
2127  }
2128  }
2129 
2130  if( aReorder )
2131  {
2132  DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
2133  wxASSERT( list );
2134 
2135  /* Rearrange the chain starting at firstTrack
2136  * All other BUSY flagged items are moved from their position to the end
2137  * of the flagged list
2138  */
2139  TRACK* next;
2140 
2141  for( TRACK* track = firstTrack->Next(); track; track = next )
2142  {
2143  next = track->Next();
2144 
2145  if( track->GetState( BUSY ) ) // move it!
2146  {
2147  busy_count++;
2148  track->UnLink();
2149  list->Insert( track, firstTrack->Next() );
2150 
2151  }
2152  }
2153  }
2154  else if( aTraceLength )
2155  {
2156  busy_count = 0;
2157 
2158  for( TRACK* track = firstTrack; track; track = track->Next() )
2159  {
2160  if( track->GetState( BUSY ) )
2161  {
2162  busy_count++;
2163  track->SetState( BUSY, false );
2164  }
2165  }
2166  }
2167 
2168  if( s_pad )
2169  {
2170  full_len += dist_fromstart;
2171  lenPadToDie += (double) s_pad->GetPadToDieLength();
2172  }
2173 
2174  if( e_pad )
2175  {
2176  full_len += dist_fromend;
2177  lenPadToDie += (double) e_pad->GetPadToDieLength();
2178  }
2179 
2180  if( aTraceLength )
2181  *aTraceLength = full_len;
2182 
2183  if( aPadToDieLength )
2184  *aPadToDieLength = lenPadToDie;
2185 
2186  if( aCount )
2187  *aCount = busy_count;
2188 
2189  return firstTrack;
2190 }
2191 
2192 
2193 MODULE* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLayer,
2194  bool aVisibleOnly, bool aIgnoreLocked )
2195 {
2196  MODULE* pt_module;
2197  MODULE* module = NULL;
2198  MODULE* alt_module = NULL;
2199  int min_dim = 0x7FFFFFFF;
2200  int alt_min_dim = 0x7FFFFFFF;
2201  bool current_layer_back = IsBackLayer( aActiveLayer );
2202 
2203  for( pt_module = m_Modules; pt_module; pt_module = pt_module->Next() )
2204  {
2205  // is the ref point within the module's bounds?
2206  if( !pt_module->HitTest( aPosition ) )
2207  continue;
2208 
2209  // if caller wants to ignore locked modules, and this one is locked, skip it.
2210  if( aIgnoreLocked && pt_module->IsLocked() )
2211  continue;
2212 
2213  PCB_LAYER_ID layer = pt_module->GetLayer();
2214 
2215  // Filter non visible modules if requested
2216  if( !aVisibleOnly || IsModuleLayerVisible( layer ) )
2217  {
2218  EDA_RECT bb = pt_module->GetFootprintRect();
2219 
2220  int offx = bb.GetX() + bb.GetWidth() / 2;
2221  int offy = bb.GetY() + bb.GetHeight() / 2;
2222 
2223  // off x & offy point to the middle of the box.
2224  int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) +
2225  ( aPosition.y - offy ) * ( aPosition.y - offy );
2226 
2227  if( current_layer_back == IsBackLayer( layer ) )
2228  {
2229  if( dist <= min_dim )
2230  {
2231  // better footprint shown on the active side
2232  module = pt_module;
2233  min_dim = dist;
2234  }
2235  }
2236  else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
2237  {
2238  if( dist <= alt_min_dim )
2239  {
2240  // better footprint shown on the other side
2241  alt_module = pt_module;
2242  alt_min_dim = dist;
2243  }
2244  }
2245  }
2246  }
2247 
2248  if( module )
2249  {
2250  return module;
2251  }
2252 
2253  if( alt_module)
2254  {
2255  return alt_module;
2256  }
2257 
2258  return NULL;
2259 }
2260 
2261 
2262 BOARD_CONNECTED_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, LSET aLayerSet )
2263 {
2264  for( MODULE* module = m_Modules; module; module = module->Next() )
2265  {
2266  D_PAD* pad = module->GetPad( aPosition, aLayerSet );
2267 
2268  if( pad )
2269  return pad;
2270  }
2271 
2272  // No pad has been located so check for a segment of the trace.
2273  TRACK* segment = ::GetTrack( m_Track, NULL, aPosition, aLayerSet );
2274 
2275  if( !segment )
2276  segment = GetVisibleTrack( m_Track, aPosition, aLayerSet );
2277 
2278  return segment;
2279 }
2280 
2281 
2283 {
2284  /* creates an intermediate point on aSegment and break it into two segments
2285  * at aPosition.
2286  * The new segment starts from aPosition and ends at the end point of
2287  * aSegment. The original segment now ends at aPosition.
2288  */
2289  if( aSegment->GetStart() == aPosition || aSegment->GetEnd() == aPosition )
2290  return NULL;
2291 
2292  // A via is a good lock point
2293  if( aSegment->Type() == PCB_VIA_T )
2294  {
2295  aPosition = aSegment->GetStart();
2296  return aSegment;
2297  }
2298 
2299  // Calculation coordinate of intermediate point relative to the start point of aSegment
2300  wxPoint delta = aSegment->GetEnd() - aSegment->GetStart();
2301 
2302  // calculate coordinates of aPosition relative to aSegment->GetStart()
2303  wxPoint lockPoint = aPosition - aSegment->GetStart();
2304 
2305  // lockPoint must be on aSegment:
2306  // Ensure lockPoint.y/lockPoint.y = delta.y/delta.x
2307  if( delta.x == 0 )
2308  lockPoint.x = 0; // horizontal segment
2309  else
2310  lockPoint.y = KiROUND( ( (double)lockPoint.x * delta.y ) / delta.x );
2311 
2312  /* Create the intermediate point (that is to say creation of a new
2313  * segment, beginning at the intermediate point.
2314  */
2315  lockPoint += aSegment->GetStart();
2316 
2317  TRACK* newTrack = (TRACK*)aSegment->Clone();
2318  // The new segment begins at the new point,
2319  newTrack->SetStart(lockPoint);
2320  newTrack->start = aSegment;
2321  newTrack->SetState( BEGIN_ONPAD, false );
2322 
2323  DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
2324  wxASSERT( list );
2325  list->Insert( newTrack, aSegment->Next() );
2326 
2327  if( aList )
2328  {
2329  // Prepare the undo command for the now track segment
2330  ITEM_PICKER picker( newTrack, UR_NEW );
2331  aList->PushItem( picker );
2332  // Prepare the undo command for the old track segment
2333  // before modifications
2334  picker.SetItem( aSegment );
2335  picker.SetStatus( UR_CHANGED );
2336  picker.SetLink( aSegment->Clone() );
2337  aList->PushItem( picker );
2338  }
2339 
2340  // Old track segment now ends at new point.
2341  aSegment->SetEnd(lockPoint);
2342  aSegment->end = newTrack;
2343  aSegment->SetState( END_ONPAD, false );
2344 
2345  D_PAD * pad = GetPad( newTrack, ENDPOINT_START );
2346 
2347  if( pad )
2348  {
2349  newTrack->start = pad;
2350  newTrack->SetState( BEGIN_ONPAD, true );
2351  aSegment->end = pad;
2352  aSegment->SetState( END_ONPAD, true );
2353  }
2354 
2355  aPosition = lockPoint;
2356  return newTrack;
2357 }
2358 
2359 
2360 ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
2361  PCB_LAYER_ID aLayer, wxPoint aStartPointPosition, int aHatch )
2362 {
2363  ZONE_CONTAINER* new_area = InsertArea( aNetcode,
2364  m_ZoneDescriptorList.size( ) - 1,
2365  aLayer, aStartPointPosition.x,
2366  aStartPointPosition.y, aHatch );
2367 
2368  if( aNewZonesList )
2369  {
2370  ITEM_PICKER picker( new_area, UR_NEW );
2371  aNewZonesList->PushItem( picker );
2372  }
2373 
2374  return new_area;
2375 }
2376 
2377 
2378 void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
2379 {
2380  if( area_to_remove == NULL )
2381  return;
2382 
2383  if( aDeletedList )
2384  {
2385  ITEM_PICKER picker( area_to_remove, UR_DELETED );
2386  aDeletedList->PushItem( picker );
2387  Remove( area_to_remove ); // remove from zone list, but does not delete it
2388  }
2389  else
2390  {
2391  Delete( area_to_remove );
2392  }
2393 }
2394 
2395 
2396 ZONE_CONTAINER* BOARD::InsertArea( int aNetcode, int aAreaIdx, PCB_LAYER_ID aLayer,
2397  int aCornerX, int aCornerY, int aHatch )
2398 {
2399  ZONE_CONTAINER* new_area = new ZONE_CONTAINER( this );
2400 
2401  new_area->SetNetCode( aNetcode );
2402  new_area->SetLayer( aLayer );
2403  new_area->SetTimeStamp( GetNewTimeStamp() );
2404 
2405  if( aAreaIdx < (int) ( m_ZoneDescriptorList.size() - 1 ) )
2406  m_ZoneDescriptorList.insert( m_ZoneDescriptorList.begin() + aAreaIdx + 1, new_area );
2407  else
2408  m_ZoneDescriptorList.push_back( new_area );
2409 
2410  new_area->SetHatchStyle( (ZONE_CONTAINER::HATCH_STYLE) aHatch );
2411 
2412  // Add the first corner to the new zone
2413  new_area->AppendCorner( wxPoint( aCornerX, aCornerY ), -1 );
2414 
2415  return new_area;
2416 }
2417 
2418 
2420 {
2421  // mark all areas as unmodified except this one, if modified
2422  for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
2423  m_ZoneDescriptorList[ia]->SetLocalFlags( 0 );
2424 
2425  aCurrArea->SetLocalFlags( 1 );
2426 
2427  if( aCurrArea->Outline()->IsSelfIntersecting() )
2428  {
2429  aCurrArea->UnHatch();
2430 
2431  // Normalize copied area and store resulting number of polygons
2432  int n_poly = aCurrArea->Outline()->NormalizeAreaOutlines();
2433 
2434  // If clipping has created some polygons, we must add these new copper areas.
2435  if( n_poly > 1 )
2436  {
2437  ZONE_CONTAINER* NewArea;
2438 
2439  // Move the newly created polygons to new areas, removing them from the current area
2440  for( int ip = 1; ip < n_poly; ip++ )
2441  {
2442  // Create new copper area and copy poly into it
2443  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( ip ) );
2444  NewArea = AddArea( aNewZonesList, aCurrArea->GetNetCode(), aCurrArea->GetLayer(),
2445  wxPoint(0, 0), aCurrArea->GetHatchStyle() );
2446 
2447  // remove the poly that was automatically created for the new area
2448  // and replace it with a poly from NormalizeAreaOutlines
2449  delete NewArea->Outline();
2450  NewArea->SetOutline( new_p );
2451  NewArea->Hatch();
2452  NewArea->SetLocalFlags( 1 );
2453  }
2454 
2455  SHAPE_POLY_SET* new_p = new SHAPE_POLY_SET( aCurrArea->Outline()->UnitSet( 0 ) );
2456  delete aCurrArea->Outline();
2457  aCurrArea->SetOutline( new_p );
2458  }
2459  }
2460 
2461  aCurrArea->Hatch();
2462 
2463  return true;
2464 }
2465 
2466 
2467 void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
2468  std::vector<MODULE*>* aNewFootprints, REPORTER* aReporter )
2469 {
2470  unsigned i;
2471  wxPoint bestPosition;
2472  wxString msg;
2473  std::vector<MODULE*> newFootprints;
2474  std::map< ZONE_CONTAINER*, std::vector<D_PAD*> > zoneConnectionsCache;
2475 
2476  for( int ii = 0; ii < GetAreaCount(); ii++ )
2477  {
2478  ZONE_CONTAINER* zone = GetArea( ii );
2479 
2480  if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
2481  continue;
2482 
2483  zoneConnectionsCache[ zone ] = m_connectivity->GetConnectedPads( zone );
2484  }
2485 
2486  if( !IsEmpty() )
2487  {
2488  // Position new components below any existing board features.
2490 
2491  if( bbbox.GetWidth() || bbbox.GetHeight() )
2492  {
2493  bestPosition.x = bbbox.Centre().x;
2494  bestPosition.y = bbbox.GetBottom() + Millimeter2iu( 10 );
2495  }
2496  }
2497  else
2498  {
2499  // Position new components in the center of the page when the board is empty.
2500  wxSize pageSize = m_paper.GetSizeIU();
2501 
2502  bestPosition.x = pageSize.GetWidth() / 2;
2503  bestPosition.y = pageSize.GetHeight() / 2;
2504  }
2505 
2506  m_Status_Pcb = 0;
2507 
2508  for( i = 0; i < aNetlist.GetCount(); i++ )
2509  {
2510  COMPONENT* component = aNetlist.GetComponent( i );
2511  MODULE* footprint;
2512 
2513  if( aReporter )
2514  {
2515 
2516  msg.Printf( _( "Checking netlist symbol footprint \"%s:%s:%s\"." ),
2517  GetChars( component->GetReference() ),
2518  GetChars( component->GetTimeStamp() ),
2519  GetChars( component->GetFPID().Format() ) );
2520  aReporter->Report( msg, REPORTER::RPT_INFO );
2521  }
2522 
2523  if( aNetlist.IsFindByTimeStamp() )
2524  footprint = FindModule( aNetlist.GetComponent( i )->GetTimeStamp(), true );
2525  else
2526  footprint = FindModule( aNetlist.GetComponent( i )->GetReference() );
2527 
2528  if( footprint == NULL ) // A new footprint.
2529  {
2530  if( aReporter )
2531  {
2532  if( component->GetModule() != NULL )
2533  {
2534  msg.Printf( _( "Adding new symbol %s footprint %s." ),
2535  GetChars( component->GetReference() ),
2536  GetChars( component->GetFPID().Format() ) );
2537  aReporter->Report( msg, REPORTER::RPT_ACTION );
2538  }
2539  else
2540  {
2541  msg.Printf( _( "Cannot add new symbol %s due to missing footprint %s." ),
2542  GetChars( component->GetReference() ),
2543  GetChars( component->GetFPID().Format() ) );
2544  aReporter->Report( msg, REPORTER::RPT_ERROR );
2545  }
2546  }
2547 
2548  if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
2549  {
2550  // Owned by NETLIST, can only copy it.
2551  footprint = new MODULE( *component->GetModule() );
2552  footprint->SetParent( this );
2553  footprint->SetPosition( bestPosition );
2554  footprint->SetTimeStamp( GetNewTimeStamp() );
2555  newFootprints.push_back( footprint );
2556  Add( footprint, ADD_APPEND );
2557  m_connectivity->Add( footprint );
2558  }
2559  }
2560  else // An existing footprint.
2561  {
2562  // Test for footprint change.
2563  if( !component->GetFPID().empty() && footprint->GetFPID() != component->GetFPID() )
2564  {
2565  if( aNetlist.GetReplaceFootprints() )
2566  {
2567  if( aReporter )
2568  {
2569  if( component->GetModule() != NULL )
2570  {
2571  msg.Printf( _( "Changing symbol %s footprint from %s to %s." ),
2572  GetChars( footprint->GetReference() ),
2573  GetChars( footprint->GetFPID().Format() ),
2574  GetChars( component->GetFPID().Format() ) );
2575  aReporter->Report( msg, REPORTER::RPT_ACTION );
2576  }
2577  else
2578  {
2579  msg.Printf( _( "Cannot change symbol %s footprint due to missing "
2580  "footprint %s." ),
2581  GetChars( footprint->GetReference() ),
2582  GetChars( component->GetFPID().Format() ) );
2583  aReporter->Report( msg, REPORTER::RPT_ERROR );
2584  }
2585  }
2586 
2587  if( !aNetlist.IsDryRun() && (component->GetModule() != NULL) )
2588  {
2589  wxASSERT( footprint != NULL );
2590  MODULE* newFootprint = new MODULE( *component->GetModule() );
2591 
2592  if( aNetlist.IsFindByTimeStamp() )
2593  newFootprint->SetReference( footprint->GetReference() );
2594  else
2595  newFootprint->SetPath( footprint->GetPath() );
2596 
2597  // Copy placement and pad net names.
2598  // optionally, copy or not local settings (like local clearances)
2599  // if the second parameter is "true", previous values will be used.
2600  // if "false", the default library values of the new footprint
2601  // will be used
2602  footprint->CopyNetlistSettings( newFootprint, false );
2603 
2604  // Compare the footprint name only, in case the nickname is empty or in case
2605  // user moved the footprint to a new library. Chances are if footprint name is
2606  // same then the footprint is very nearly the same and the two texts should
2607  // be kept at same size, position, and rotation.
2608  if( newFootprint->GetFPID().GetLibItemName() == footprint->GetFPID().GetLibItemName() )
2609  {
2610  newFootprint->Reference().SetEffects( footprint->Reference() );
2611  newFootprint->Value().SetEffects( footprint->Value() );
2612  }
2613 
2614  m_connectivity->Remove( footprint );
2615  Remove( footprint );
2616 
2617  Add( newFootprint, ADD_APPEND );
2618  m_connectivity->Add( footprint );
2619 
2620  footprint = newFootprint;
2621  }
2622  }
2623  }
2624 
2625  // Test for reference designator field change.
2626  if( footprint->GetReference() != component->GetReference() )
2627  {
2628  if( aReporter )
2629  {
2630  msg.Printf( _( "Changing footprint %s reference to %s." ),
2631  GetChars( footprint->GetReference() ),
2632  GetChars( component->GetReference() ) );
2633  aReporter->Report( msg, REPORTER::RPT_ACTION );
2634  }
2635 
2636  if( !aNetlist.IsDryRun() )
2637  footprint->SetReference( component->GetReference() );
2638  }
2639 
2640  // Test for value field change.
2641  if( footprint->GetValue() != component->GetValue() )
2642  {
2643  if( aReporter )
2644  {
2645  msg.Printf( _( "Changing footprint %s value from %s to %s." ),
2646  GetChars( footprint->GetReference() ),
2647  GetChars( footprint->GetValue() ),
2648  GetChars( component->GetValue() ) );
2649  aReporter->Report( msg, REPORTER::RPT_ACTION );
2650  }
2651 
2652  if( !aNetlist.IsDryRun() )
2653  footprint->SetValue( component->GetValue() );
2654  }
2655 
2656  // Test for time stamp change.
2657  if( footprint->GetPath() != component->GetTimeStamp() )
2658  {
2659  if( aReporter )
2660  {
2661  msg.Printf( _( "Changing component path \"%s:%s\" to \"%s\"." ),
2662  GetChars( footprint->GetReference() ),
2663  GetChars( footprint->GetPath() ),
2664  GetChars( component->GetTimeStamp() ) );
2665  aReporter->Report( msg, REPORTER::RPT_INFO );
2666  }
2667 
2668  if( !aNetlist.IsDryRun() )
2669  footprint->SetPath( component->GetTimeStamp() );
2670  }
2671  }
2672 
2673  if( footprint == NULL )
2674  continue;
2675 
2676  // At this point, the component footprint is updated. Now update the nets.
2677  for( auto pad : footprint->Pads() )
2678  {
2679  COMPONENT_NET net = component->GetNet( pad->GetName() );
2680 
2681  if( !net.IsValid() ) // Footprint pad had no net.
2682  {
2683  if( aReporter && !pad->GetNetname().IsEmpty() )
2684  {
2685  msg.Printf( _( "Clearing component %s pin %s net." ),
2686  GetChars( footprint->GetReference() ),
2687  GetChars( pad->GetName() ) );
2688  aReporter->Report( msg, REPORTER::RPT_ACTION );
2689  }
2690 
2691  if( !aNetlist.IsDryRun() )
2692  {
2693  m_connectivity->Remove( pad );
2694  pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
2695  }
2696  }
2697  else // Footprint pad has a net.
2698  {
2699  if( net.GetNetName() != pad->GetNetname() )
2700  {
2701  if( aReporter )
2702  {
2703  msg.Printf( _( "Changing footprint %s pad %s net from %s to %s." ),
2704  GetChars( footprint->GetReference() ),
2705  GetChars( pad->GetName() ),
2706  GetChars( pad->GetNetname() ),
2707  GetChars( net.GetNetName() ) );
2708  aReporter->Report( msg, REPORTER::RPT_ACTION );
2709  }
2710 
2711  if( !aNetlist.IsDryRun() )
2712  {
2713  NETINFO_ITEM* netinfo = FindNet( net.GetNetName() );
2714 
2715  if( netinfo == NULL )
2716  {
2717  // It is a new net, we have to add it
2718  netinfo = new NETINFO_ITEM( this, net.GetNetName() );
2719  Add( netinfo );
2720  }
2721 
2722  m_connectivity->Remove( pad );
2723  pad->SetNetCode( netinfo->GetNet() );
2724  m_connectivity->Add( pad );
2725  }
2726  }
2727  }
2728  }
2729  }
2730 
2731  // Remove all components not in the netlist.
2732  if( aNetlist.GetDeleteExtraFootprints() )
2733  {
2734  MODULE* nextModule;
2735  const COMPONENT* component;
2736 
2737  for( MODULE* module = m_Modules; module != NULL; module = nextModule )
2738  {
2739  nextModule = module->Next();
2740 
2741  if( module->IsLocked() )
2742  continue;
2743 
2744  if( aNetlist.IsFindByTimeStamp() )
2745  component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
2746  else
2747  component = aNetlist.GetComponentByReference( module->GetReference() );
2748 
2749  if( component == NULL )
2750  {
2751  if( aReporter )
2752  {
2753  msg.Printf( _( "Removing unused footprint %s." ),
2754  GetChars( module->GetReference() ) );
2755  aReporter->Report( msg, REPORTER::RPT_ACTION );
2756  }
2757 
2758  if( !aNetlist.IsDryRun() )
2759  {
2760  m_connectivity->Remove( module );
2761  module->DeleteStructure();
2762  }
2763  }
2764  }
2765  }
2766 
2767  BuildListOfNets();
2768  std::vector<D_PAD*> padlist = GetPads();
2769  auto connAlgo = m_connectivity->GetConnectivityAlgo();
2770 
2771  // If needed, remove the single pad nets:
2772  if( aDeleteSinglePadNets && !aNetlist.IsDryRun() )
2773  {
2774  std::vector<unsigned int> padCount( connAlgo->NetCount() );
2775 
2776  for( const auto cnItem : connAlgo->ItemList() )
2777  {
2778  if( !cnItem->Valid() || cnItem->Parent()->Type() != PCB_PAD_T )
2779  continue;
2780 
2781  int net = cnItem->Parent()->GetNetCode();
2782 
2783  if( net > 0 )
2784  ++padCount[net];
2785  }
2786 
2787  for( i = 0; i < (unsigned)connAlgo->NetCount(); ++i )
2788  {
2789  // First condition: only one pad in the net
2790  if( padCount[i] == 1 )
2791  {
2792  // Second condition, no zones attached to the pad
2793  D_PAD* pad = nullptr;
2794  int zoneCount = 0;
2795  const KICAD_T types[] = { PCB_PAD_T, PCB_ZONE_AREA_T, EOT };
2796  auto netItems = m_connectivity->GetNetItems( i, types );
2797 
2798  for( const auto item : netItems )
2799  {
2800  if( item->Type() == PCB_ZONE_AREA_T )
2801  {
2802  wxASSERT( !pad || pad->GetNet() == item->GetNet() );
2803  ++zoneCount;
2804  }
2805  else if( item->Type() == PCB_PAD_T )
2806  {
2807  wxASSERT( !pad );
2808  pad = static_cast<D_PAD*>( item );
2809  }
2810  }
2811 
2812  wxASSERT( pad ); // pad = 0 means the pad list is not up to date
2813 
2814  if( pad && zoneCount == 0 )
2815  {
2816  if( aReporter )
2817  {
2818  msg.Printf( _( "Remove single pad net %s." ),
2819  GetChars( pad->GetNetname() ) );
2820  aReporter->Report( msg, REPORTER::RPT_ACTION );
2821  }
2822 
2823  m_connectivity->Remove( pad );
2825  }
2826  }
2827  }
2828  }
2829 
2830  // Verify that board contains all pads in netlist: if it doesn't then footprints are
2831  // wrong or missing.
2832  // Note that we use references to find the footprints as they're already updated by this
2833  // point (whether by-reference or by-timestamp).
2834  if( aReporter )
2835  {
2836  wxString padname;
2837  for( i = 0; i < aNetlist.GetCount(); i++ )
2838  {
2839  const COMPONENT* component = aNetlist.GetComponent( i );
2840  MODULE* footprint = FindModuleByReference( component->GetReference() );
2841 
2842  if( footprint == NULL ) // It can be missing in partial designs
2843  continue;
2844 
2845  // Explore all pins/pads in component
2846  for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
2847  {
2848  const COMPONENT_NET& net = component->GetNet( jj );
2849  padname = net.GetPinName();
2850 
2851  if( footprint->FindPadByName( padname ) )
2852  continue; // OK, pad found
2853 
2854  // not found: bad footprint, report error
2855  msg.Printf( _( "Symbol %s pad %s not found in footprint %s.\n" ),
2856  GetChars( component->GetReference() ),
2857  GetChars( padname ),
2858  GetChars( footprint->GetFPID().Format() ) );
2859  aReporter->Report( msg, REPORTER::RPT_ERROR );
2860  }
2861  }
2862  }
2863 
2864  // Test copper zones to detect "dead" nets (nets without any pad):
2865  for( int ii = 0; ii < GetAreaCount(); ii++ )
2866  {
2867  ZONE_CONTAINER* zone = GetArea( ii );
2868 
2869  if( !zone->IsOnCopperLayer() || zone->GetIsKeepout() )
2870  continue;
2871 
2872  if( m_connectivity->GetPadCount( zone->GetNetCode() ) == 0 )
2873  {
2874  // Look for a pad in the zone's connected-pad-cache which has been updated to
2875  // a new net and use that. While this won't always be the right net, the dead
2876  // net is guaranteed to be wrong.
2877  NETINFO_ITEM* updatedNet = nullptr;
2878 
2879  for( D_PAD* pad : zoneConnectionsCache[ zone ] )
2880  {
2881  if( pad->GetNetname() != zone->GetNetname() )
2882  {
2883  updatedNet = pad->GetNet();
2884  break;
2885  }
2886  }
2887 
2888  if( aReporter )
2889  {
2890  if( updatedNet )
2891  {
2892  msg.Printf( _( "Updating copper zone from net %s to %s." ),
2893  zone->GetNetname(), 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 
2904  if( updatedNet && !aNetlist.IsDryRun() )
2905  {
2906  m_connectivity->Remove( zone );
2907  zone->SetNet( updatedNet );
2908  m_connectivity->Add( zone );
2909  }
2910  }
2911  }
2912 
2913  m_connectivity->RecalculateRatsnest();
2914 
2915  std::swap( newFootprints, *aNewFootprints );
2916 }
2917 
2918 
2920  bool aAddToBoard )
2921 {
2922  BOARD_ITEM* new_item = NULL;
2923 
2924  switch( aItem->Type() )
2925  {
2926  case PCB_MODULE_T:
2927  case PCB_TEXT_T:
2928  case PCB_LINE_T:
2929  case PCB_TRACE_T:
2930  case PCB_VIA_T:
2931  case PCB_ZONE_AREA_T:
2932  case PCB_TARGET_T:
2933  case PCB_DIMENSION_T:
2934  new_item = static_cast<BOARD_ITEM*>( aItem->Clone() );
2935  break;
2936 
2937  default:
2938  // Un-handled item for duplication
2939  new_item = NULL;
2940  break;
2941  }
2942 
2943  if( new_item && aAddToBoard )
2944  Add( new_item );
2945 
2946  return new_item;
2947 }
2948 
2949 
2950 /* Extracts the board outlines and build a closed polygon
2951  * from lines, arcs and circle items on edge cut layer
2952  * Any closed outline inside the main outline is a hole
2953  * All contours should be closed, i.e. are valid vertices for a closed polygon
2954  * return true if success, false if a contour is not valid
2955  */
2956 extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
2957  wxString* aErrorText, unsigned int aTolerance );
2958 
2959 
2960 bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText )
2961 {
2962  bool success = BuildBoardPolygonOutlines( this, aOutlines, aErrorText, Millimeter2iu( 0.05 ) );
2963 
2964  // Make polygon strictly simple to avoid issues (especially in 3D viewer)
2966 
2967  return success;
2968 
2969 }
2970 
2971 
2972 const std::vector<D_PAD*> BOARD::GetPads()
2973 {
2974  std::vector<D_PAD*> rv;
2975  for ( auto mod: Modules() )
2976  {
2977  for ( auto pad: mod->Pads() )
2978  rv.push_back ( pad );
2979 
2980  }
2981 
2982  return rv;
2983 }
2984 
2985 
2987 {
2988  unsigned retval = 0;
2989  for( auto mod : Modules() )
2990  {
2991  retval += mod->Pads().Size();
2992  }
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 mod : Modules() )
3026  for ( auto pad : mod->Pads() )
3027  pad->SetNetCode( 0 );
3028 
3029  for ( auto track : Tracks() )
3030  track->SetNetCode( 0 );
3031 
3032 }
Definition: colors.h:57
DHEAD * GetList() const
Definition: base_struct.h:209
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:673
CITER next(CITER it)
Definition: ptree.cpp:130
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
#define DIM(x)
of elements in an array
Definition: macros.h:98
Wrapper class, so you can iterate through NETINFO_ITEM*s, not std::pair<int/wxString, NETINFO_ITEM*>
Definition: netinfo.h:478
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:728
void Draw(EDA_DRAW_PANEL *panel, wxDC *DC, GR_DRAWMODE aDrawMode, const wxPoint &offset=ZeroOffset) override
Function Draw Draws the zone outline.
Definition: class_zone.cpp: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:60
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:510
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:305
#define END_ONPAD
Pcbnew: flag set for track segment ending on a pad.
Definition: base_struct.h:131
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:111
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 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:118
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=NULL)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines...
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:518
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:196
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:444
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:113
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
MODULE * Next() const
Definition: class_module.h:123
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:195
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...
static const int dist[10][10]
Definition: dist.cpp:57
ZONE_CONTAINER * m_CurrentZoneContour
zone contour currently in progress
Definition: class_board.h:262
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:169
unsigned GetNetCount() const
Function GetNetCount.
Definition: netinfo.h:434
int GetHeight() const
Definition: eda_rect.h:118
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:236
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.
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:494
BOARD_ITEM * GetItem(void *aWeakReference, bool includeDrawings=true)
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:132
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:186
NETINFO_LIST m_NetInfo
net info list (name, design constraints ..
Definition: class_board.h:199
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:187
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:237
#define cu(a)
Definition: auxiliary.h:88
#define BEGIN_ONPAD
Pcbnew: flag set for track segment starting on a pad.
Definition: base_struct.h:130
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:239
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:119
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:360
Classes used in Pcbnew, CvPcb and GerbView.
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, wxString *aErrorText, unsigned int aTolerance)
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:803
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:602
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:193
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:159
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
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.
void ReplaceNetlist(NETLIST &aNetlist, bool aDeleteSinglePadNets, std::vector< MODULE * > *aNewFootprints, REPORTER *aReporter=NULL)
Function ReplaceNetlist updates the BOARD according to aNetlist.
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:253
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.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
#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:509
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:114
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:271
const wxPoint & GetStart() const
Definition: class_track.h:122
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:249
LAYER_T
Enum LAYER_T gives the allowed types of layers, same as Specctra DSN spec.
Definition: class_board.h:71
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:126
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
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:243
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:470
class SEGZONE, a segment used to fill a zone area (segment on a copper layer)
Definition: typeinfo.h:97
#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:1017
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:178
int GetBottom() const
Definition: eda_rect.h:122
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:67
wxPoint Centre() const
Definition: eda_rect.h:60
void SetPosition(const wxPoint &aPos) override
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
int GetNet() const
Function GetNet.
Definition: netinfo.h:227
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:265
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
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
iterator begin() const
Definition: netinfo.h:524
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:255
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:99
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:242
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:988
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:189
iterator end() const
Definition: netinfo.h:529
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:469
#define max(a, b)
Definition: auxiliary.h:86
Class LAYER holds information pertinent to a layer of a BOARD.
Definition: class_board.h:85
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:460
DLIST< MODULE > m_Modules
Definition: class_board.h:247
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:181
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:104
size_t i
Definition: json11.cpp:597
LAYER m_Layer[PCB_LAYER_ID_COUNT]
Definition: class_board.h:183
std::shared_ptr< CONNECTIVITY_DATA > m_connectivity
Definition: class_board.h:191
bool HitTestFilledArea(const wxPoint &aRefPos) const
Function HitTestFilledArea tests if the given wxPoint is within the bounds of a filled area of this z...
Definition: class_zone.cpp:807
int GetNumSegmZone() const
Calculate the zone segment count.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:503
int GetX() const
Definition: eda_rect.h:109
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:498
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:503
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
static bool sortNetsByNodes(const NETINFO_ITEM *a, const NETINFO_ITEM *b)
void SetLocalFlags(int aFlags)
Definition: class_zone.h:231
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:924
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:121
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
void CopyNetlistSettings(MODULE *aModule, bool aCopyLocalSettings)
Function CopyNetlistSettings copies the netlist settings to aModule.
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:252
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:248
bool IsDryRun() const
Definition: pcb_netlist.h:309
BOARD_DESIGN_SETTINGS m_designSettings
Definition: class_board.h:193
Module description (excepted pads)
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:235
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
const wxString & GetPath() const
Definition: class_module.h:202
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.
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:91
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:461
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:90
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:803
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:295
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:203
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:254
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:778
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:652
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:203
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:521
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:239
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:507