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