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