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