KiCad PCB EDA Suite
tracks_cleaner.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004-2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
32 #include <fctsys.h>
33 #include <class_drawpanel.h>
34 #include <pcb_edit_frame.h>
35 #include <pcbnew.h>
36 #include <class_board.h>
37 #include <class_track.h>
39 #include <board_commit.h>
42 
43 #include <tool/tool_manager.h>
44 #include <tools/pcb_actions.h>
45 
46 // Helper class used to clean tracks and vias
48 {
49 public:
50  TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit );
51 
61  bool CleanupBoard( bool aCleanVias, bool aRemoveMisConnected,
62  bool aMergeSegments, bool aDeleteUnconnected );
63 
64 private:
65  /* finds and remove all track segments which are connected to more than one net.
66  * (short circuits)
67  */
69 
74  bool cleanupVias();
75 
80  void removeDuplicatesOfVia( const VIA *aVia, std::set<BOARD_ITEM *>& aToRemove );
81 
85  void removeDuplicatesOfTrack( const TRACK* aTrack, std::set<BOARD_ITEM*>& aToRemove );
86 
90  bool deleteDanglingTracks();
91 
93  bool deleteNullSegments();
94 
96  bool MergeCollinearTracks( TRACK* aSegment );
97 
101  bool cleanupSegments();
102 
109 
116  TRACK* aCandidate, ENDPOINT_T aEndType );
117 
118  const ZONE_CONTAINER* zoneForTrackEndpoint( const TRACK* aTrack,
119  ENDPOINT_T aEndPoint );
120 
121  bool testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPoint );
122 
125 
126  bool removeItems( std::set<BOARD_ITEM*>& aItems )
127  {
128  bool isModified = false;
129 
130 
131  for( auto item : aItems )
132  {
133  isModified = true;
134  m_brd->Remove( item );
135  m_commit.Removed( item );
136  }
137 
138  return isModified;
139  }
140 };
141 
142 
143 /* Install the cleanup dialog frame to know what should be cleaned
144 */
146 {
147  DIALOG_CLEANING_OPTIONS dlg( this );
148 
149  if( dlg.ShowModal() != wxID_OK )
150  return;
151 
152  // Old model has to be refreshed, GAL normally does not keep updating it
153  Compile_Ratsnest( NULL, false );
154 
155  wxBusyCursor dummy;
156  BOARD_COMMIT commit( this );
157  TRACKS_CLEANER cleaner( GetBoard(), commit );
158 
159  // Clear current selection list to avoid selection of deleted items
161 
162  bool modified = cleaner.CleanupBoard( dlg.m_deleteShortCircuits, dlg.m_cleanVias,
164 
165  if( modified )
166  {
167  // Clear undo and redo lists to avoid inconsistencies between lists
168  SetCurItem( NULL );
169  commit.Push( _( "Board cleanup" ) );
170  }
171 
172  m_canvas->Refresh( true );
173 }
174 
175 
177 {
178  auto connectivity = m_brd->GetConnectivity();
179 
180  connectivity->Build(m_brd);
181 
182  // clear flags and variables used in cleanup
183  for( auto track : m_brd->Tracks() )
184  {
185  track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
186  }
187 
188  for( auto track : m_brd->Tracks() )
189  {
190  // Mark track if connected to pads
191  for( auto pad : connectivity->GetConnectedPads( track ) )
192  {
193  if( pad->HitTest( track->GetStart() ) )
194  {
195  track->SetState( START_ON_PAD, true );
196  }
197 
198  if( pad->HitTest( track->GetEnd() ) )
199  {
200  track->SetState( END_ON_PAD, true );
201  }
202  }
203  }
204 }
205 
206 
207 /* Main cleaning function.
208  * Delete
209  * - Redundant points on tracks (merge aligned segments)
210  * - vias on pad
211  * - null length segments
212  */
213 bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
214  bool aCleanVias,
215  bool aMergeSegments,
216  bool aDeleteUnconnected )
217 {
218 
219  bool modified = false;
220 
221  // delete redundant vias
222  if( aCleanVias )
223  modified |= cleanupVias();
224 
225  // Remove null segments and intermediate points on aligned segments
226  // If not asked, remove null segments only if remove misconnected is asked
227  if( aMergeSegments )
228  modified |= cleanupSegments();
229  else if( aRemoveMisConnected )
230  modified |= deleteNullSegments();
231 
233 
234  if( aRemoveMisConnected )
235  modified |= removeBadTrackSegments();
236 
237  // Delete dangling tracks
238  if( aDeleteUnconnected )
239  {
240  if( deleteDanglingTracks() )
241  {
242  modified = true;
243 
244  // Removed tracks can leave aligned segments
245  // (when a T was formed by tracks and the "vertical" segment
246  // is removed)
247  if( aMergeSegments )
248  cleanupSegments();
249  }
250  }
251 
252  return modified;
253 }
254 
255 
257  : m_brd( aPcb ), m_commit( aCommit )
258 {
259 }
260 
261 
263 {
264  auto connectivity = m_brd->GetConnectivity();
265 
266  std::set<BOARD_ITEM *> toRemove;
267 
268  for( auto segment : m_brd->Tracks() )
269  {
270  segment->SetState( FLAG0, false );
271 
272  for( auto testedPad : connectivity->GetConnectedPads( segment ) )
273  {
274  if( segment->GetNetCode() != testedPad->GetNetCode() )
275  toRemove.insert( segment );
276  }
277 
278  for( auto testedTrack : connectivity->GetConnectedTracks( segment ) )
279  {
280  if( segment->GetNetCode() != testedTrack->GetNetCode() && !testedTrack->GetState( FLAG0 ) )
281  toRemove.insert( segment );
282  }
283  }
284 
285  return removeItems( toRemove );
286 }
287 
288 
289 void TRACKS_CLEANER::removeDuplicatesOfVia( const VIA *aVia, std::set<BOARD_ITEM *>& aToRemove )
290 {
291  VIA* next_via;
292 
293  for( VIA* alt_via = GetFirstVia( aVia->Next() ); alt_via != NULL; alt_via = next_via )
294  {
295  next_via = GetFirstVia( alt_via->Next() );
296 
297  if( ( alt_via->GetViaType() == VIA_THROUGH ) &&
298  ( alt_via->GetStart() == aVia->GetStart() ) )
299  aToRemove.insert ( alt_via );
300  }
301 }
302 
303 
305 {
306  std::set<BOARD_ITEM*> toRemove;
307 
308  for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL;
309  via = GetFirstVia( via->Next() ) )
310  {
311  if( via->GetFlags() & TRACK_LOCKED )
312  continue;
313 
314  // Correct via m_End defects (if any), should never happen
315  if( via->GetStart() != via->GetEnd() )
316  {
317  wxFAIL_MSG( "Malformed via with mismatching ends" );
318  via->SetEnd( via->GetStart() );
319  }
320 
321  /* Important: these cleanups only do thru hole vias, they don't
322  * (yet) handle high density interconnects */
323  if( via->GetViaType() == VIA_THROUGH )
324  {
325  removeDuplicatesOfVia( via, toRemove );
326 
327  /* To delete through Via on THT pads at same location
328  * Examine the list of connected pads:
329  * if one through pad is found, the via can be removed */
330 
331  const auto pads = m_brd->GetConnectivity()->GetConnectedPads( via );
332  for( const auto pad : pads )
333  {
334  const LSET all_cu = LSET::AllCuMask();
335 
336  if( ( pad->GetLayerSet() & all_cu ) == all_cu )
337  {
338  // redundant: delete the via
339  toRemove.insert( via );
340  break;
341  }
342  }
343  }
344  }
345 
346  return removeItems( toRemove );
347 }
348 
349 
353 {
354  auto connectivity = m_brd->GetConnectivity();
355  VECTOR2I endpoint ;
356 
357  if( aTrack->Type() == PCB_TRACE_T )
358  endpoint = aTrack->GetEndPoint( aEndPoint );
359  else
360  endpoint = aTrack->GetStart( );
361 
362  //wxASSERT ( connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ) != nullptr );
363  wxASSERT ( connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems().size() != 0 );
364  auto citem = connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems().front();
365 
366  if( !citem->Valid() )
367  return false;
368 
369  auto anchors = citem->Anchors();
370 
371  for( const auto& anchor : anchors )
372  {
373  if( anchor->Pos() == endpoint && anchor->IsDangling() )
374  return true;
375  }
376 
377  return false;
378 }
379 
380 
381 /* Delete dangling tracks
382  * Vias:
383  * If a via is only connected to a dangling track, it also will be removed
384  */
386 {
387  bool item_erased = false;
388  bool modified = false;
389 
390  do // Iterate when at least one track is deleted
391  {
393  item_erased = false;
394 
395  TRACK* next_track;
396 
397  for( TRACK *track = m_brd->m_Track; track != NULL; track = next_track )
398  {
399  next_track = track->Next();
400  bool flag_erase = false; // Start without a good reason to erase it
401 
402  /* if a track endpoint is not connected to a pad, test if
403  * the endpoint is connected to another track or to a zone.
404  * For via test, an enhancement could be to test if
405  * connected to 2 items on different layers. Currently
406  * a via must be connected to 2 items, that can be on the
407  * same layer */
408 
409  // Check if there is nothing attached on the start
410  if( !( track->GetState( START_ON_PAD ) ) )
411  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_START );
412 
413  // If not sure about removal, then check if there is nothing attached on the end
414  if( !flag_erase && !track->GetState( END_ON_PAD ) )
415  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_END );
416 
417  if( flag_erase )
418  {
419  m_brd->Remove( track );
420  m_commit.Removed( track );
421 
422  /* keep iterating, because a track connected to the deleted track
423  * now perhaps is not connected and should be deleted */
424  item_erased = true;
425  modified = true;
426  }
427  }
428  } while( item_erased );
429 
430 
431  return modified;
432 }
433 
434 
435 // Delete null length track segments
437 {
438  std::set<BOARD_ITEM *> toRemove;
439 
440  for( auto segment : m_brd->Tracks() )
441  {
442  if( segment->IsNull() ) // Length segment = 0; delete it
443  toRemove.insert( segment );
444  }
445 
446  return removeItems( toRemove );
447 }
448 
449 void TRACKS_CLEANER::removeDuplicatesOfTrack( const TRACK *aTrack, std::set<BOARD_ITEM*>& aToRemove )
450 {
451  if( aTrack->GetFlags() & STRUCT_DELETED )
452  return;
453 
454  for( auto other : m_brd->Tracks() )
455  {
456  // New netcode, break out (can't be there any other)
457  if( aTrack->GetNetCode() != other->GetNetCode() )
458  continue;
459 
460  if( aTrack == other )
461  continue;
462 
463  if( other->GetFlags() & STRUCT_DELETED )
464  continue;
465 
466  // Must be of the same type, on the same layer and the endpoints
467  // must be the same (maybe swapped)
468  if( ( aTrack->Type() == other->Type() ) &&
469  ( aTrack->GetLayer() == other->GetLayer() ) )
470  {
471  if( ( ( aTrack->GetStart() == other->GetStart() ) &&
472  ( aTrack->GetEnd() == other->GetEnd() ) ) ||
473  ( ( aTrack->GetStart() == other->GetEnd() ) &&
474  ( aTrack->GetEnd() == other->GetStart() ) ) )
475  {
476  other->SetFlags( STRUCT_DELETED );
477  aToRemove.insert( other );
478  }
479  }
480  }
481 }
482 
483 
485 {
486  bool merged_this = false;
487 
488 
489  for( ENDPOINT_T endpoint = ENDPOINT_START; endpoint <= ENDPOINT_END;
490  endpoint = ENDPOINT_T( endpoint + 1 ) )
491  {
492  // search for a possible segment connected to the current endpoint of the current one
493  TRACK* other = aSegment->Next();
494 
495  if( other )
496  {
497  other = aSegment->GetTrack( other, NULL, endpoint, true, false );
498 
499  if( other )
500  {
501  // the two segments must have the same width and the other
502  // cannot be a via
503  if( ( aSegment->GetWidth() == other->GetWidth() ) &&
504  ( other->Type() == PCB_TRACE_T ) )
505  {
506  // There can be only one segment connected
507  other->SetState( BUSY, true );
508  TRACK* yet_another = aSegment->GetTrack( m_brd->m_Track, NULL,
509  endpoint, true, false );
510  other->SetState( BUSY, false );
511 
512  if( !yet_another )
513  {
514  // Try to merge them
515  TRACK* segDelete = mergeCollinearSegmentIfPossible( aSegment,
516  other, endpoint );
517 
518  // Merge succesful, the other one has to go away
519  if( segDelete )
520  {
521  m_brd->Remove( segDelete );
522  m_commit.Removed( segDelete );
523  merged_this = true;
524  }
525  }
526  }
527  }
528  }
529  }
530 
531 
532 
533  return merged_this;
534 }
535 
536 
537 // Delete null length segments, and intermediate points ..
539 {
540  bool modified = false;
541 
542  // Easy things first
543  modified |= deleteNullSegments();
544 
546 
547  std::set<BOARD_ITEM*> toRemove;
548 
549  // Delete redundant segments, i.e. segments having the same end points and layers
550  // (can happens when blocks are copied on themselve)
551  for( auto segment : m_brd->Tracks() )
552  removeDuplicatesOfTrack( segment, toRemove );
553 
554  modified |= removeItems( toRemove );
555 
556  if( modified )
558 
559  // merge collinear segments:
560  TRACK* nextsegment;
561 
562  for( TRACK* segment = m_brd->m_Track; segment; segment = nextsegment )
563  {
564  nextsegment = segment->Next();
565 
566  if( segment->Type() == PCB_TRACE_T )
567  {
568  bool merged_this = MergeCollinearTracks( segment );
569 
570  if( merged_this ) // The current segment was modified, retry to merge it again
571  {
572  nextsegment = segment->Next();
573  modified = true;
574  }
575  }
576  }
577 
578  return modified;
579 }
580 
581 
582 /* Utility: check for parallelism between two segments */
583 static bool parallelismTest( int dx1, int dy1, int dx2, int dy2 )
584 {
585  /* The following condition list is ugly and repetitive, but I have
586  * not a better way to express clearly the trivial cases. Hope the
587  * compiler optimize it better than always doing the product
588  * below... */
589 
590  // test for vertical alignment (easy to handle)
591  if( dx1 == 0 )
592  return dx2 == 0;
593 
594  if( dx2 == 0 )
595  return dx1 == 0;
596 
597  // test for horizontal alignment (easy to handle)
598  if( dy1 == 0 )
599  return dy2 == 0;
600 
601  if( dy2 == 0 )
602  return dy1 == 0;
603 
604  /* test for alignment in other cases: Do the usual cross product test
605  * (the same as testing the slope, but without a division) */
606  return ((double)dy1 * dx2 == (double)dx1 * dy2);
607 }
608 
609 
623 static void updateConn( TRACK *track, const std::shared_ptr<CONNECTIVITY_DATA>& connectivity )
624 {
625  for( auto pad : connectivity->GetConnectedPads( track ) )
626  {
627  if( pad->HitTest( track->GetStart() ) )
628  {
629  track->SetState( START_ON_PAD, true );
630  }
631 
632  if( pad->HitTest( track->GetEnd() ) )
633  {
634  track->SetState( END_ON_PAD, true );
635  }
636  }
637 }
638 
639 
641  ENDPOINT_T aEndType )
642 {
643  // First of all, they must be of the same width and must be both actual tracks
644  if( ( aTrackRef->GetWidth() != aCandidate->GetWidth() ) ||
645  ( aTrackRef->Type() != PCB_TRACE_T ) ||
646  ( aCandidate->Type() != PCB_TRACE_T ) )
647  return NULL;
648 
649  // Trivial case: exactly the same track
650  if( ( aTrackRef->GetStart() == aCandidate->GetStart() ) &&
651  ( aTrackRef->GetEnd() == aCandidate->GetEnd() ) )
652  return aCandidate;
653 
654  if( ( aTrackRef->GetStart() == aCandidate->GetEnd() ) &&
655  ( aTrackRef->GetEnd() == aCandidate->GetStart() ) )
656  return aCandidate;
657 
658  // Weed out non-parallel tracks
659  if( !parallelismTest( aTrackRef->GetEnd().x - aTrackRef->GetStart().x,
660  aTrackRef->GetEnd().y - aTrackRef->GetStart().y,
661  aCandidate->GetEnd().x - aCandidate->GetStart().x,
662  aCandidate->GetEnd().y - aCandidate->GetStart().y ) )
663  return NULL;
664 
665  auto connectivity = m_brd->GetConnectivity();
666 
667  updateConn( aTrackRef, connectivity );
668  updateConn( aCandidate, connectivity );
669 
670  if( aEndType == ENDPOINT_START )
671  {
672  // We do not have a pad, which is a always terminal point for a track
673  if( aTrackRef->GetState( START_ON_PAD ) )
674  return NULL;
675 
676  /* change the common point coordinate of pt_segm to use the other point
677  * of pt_segm (pt_segm will be removed later) */
678  if( aTrackRef->GetStart() == aCandidate->GetStart() )
679  {
680  m_commit.Modify( aTrackRef );
681  aTrackRef->SetStart( aCandidate->GetEnd() );
682  aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( END_ON_PAD ) );
683  connectivity->Update( aTrackRef );
684  return aCandidate;
685  }
686  else
687  {
688  m_commit.Modify( aTrackRef );
689  aTrackRef->SetStart( aCandidate->GetStart() );
690  aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( START_ON_PAD ) );
691  connectivity->Update( aTrackRef );
692  return aCandidate;
693  }
694  }
695  else // aEndType == END
696  {
697  // We do not have a pad, which is a always terminal point for a track
698  if( aTrackRef->GetState( END_ON_PAD ) )
699  return NULL;
700 
701  /* change the common point coordinate of pt_segm to use the other point
702  * of pt_segm (pt_segm will be removed later) */
703  if( aTrackRef->GetEnd() == aCandidate->GetStart() )
704  {
705  m_commit.Modify( aTrackRef );
706  aTrackRef->SetEnd( aCandidate->GetEnd() );
707  aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( END_ON_PAD ) );
708  connectivity->Update( aTrackRef );
709 
710  return aCandidate;
711  }
712  else
713  {
714  m_commit.Modify( aTrackRef );
715  aTrackRef->SetEnd( aCandidate->GetStart() );
716  aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( START_ON_PAD ) );
717  connectivity->Update( aTrackRef );
718  return aCandidate;
719  }
720  }
721 
722  return NULL;
723 }
724 
725 
727 {
728  // Old model has to be refreshed, GAL normally does not keep updating it
729  Compile_Ratsnest( NULL, false );
730  BOARD_COMMIT commit( this );
731 
732  TRACKS_CLEANER cleaner( GetBoard(), commit );
733  bool isModified = cleaner.CleanupBoard( true, false, false, false );
734 
735  if( isModified )
736  {
737  // Clear undo and redo lists to avoid inconsistencies between lists
738  SetCurItem( NULL );
739  commit.Push( _( "Board cleanup" ) );
740  Compile_Ratsnest( NULL, true );
741  }
742 
743  m_canvas->Refresh( true );
744 
745  return isModified;
746 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
TRACK * GetTrack(TRACK *aStartTrace, TRACK *aEndTrace, ENDPOINT_T aEndPoint, bool aSameNetOnly, bool aSequential)
Function GetTrack returns the trace segment connected to the segment at aEndPoint from aStartTrace to...
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
int GetNetCode() const
Function GetNetCode.
bool MergeCollinearTracks(TRACK *aSegment)
Try to merge the segment to a following collinear one.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:122
const wxPoint & GetStart() const
Definition: class_track.h:126
bool CleanupBoard(bool aCleanVias, bool aRemoveMisConnected, bool aMergeSegments, bool aDeleteUnconnected)
the cleanup function.
Class BOARD to handle a board.
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
bool deleteDanglingTracks()
Removes dangling tracks.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:135
TRACKS_CLEANER(BOARD *aPcb, BOARD_COMMIT &aCommit)
bool testTrackEndpointDangling(TRACK *aTrack, ENDPOINT_T aEndPoint)
Utility: does the endpoint unconnected processed for one endpoint of one track Returns true if the tr...
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD_COMMIT & m_commit
ENDPOINT_T
Flag used in locate routines (from which endpoint work)
Definition: pcbnew.h:58
TOOL_MANAGER * GetToolManager() const
Return the tool manager instance, if any.
Definition: draw_frame.h:941
void removeDuplicatesOfTrack(const TRACK *aTrack, std::set< BOARD_ITEM * > &aToRemove)
Removes all the following duplicates tracks of the specified one.
#define START_ON_PAD
Definition: netinfo.h:590
COMMIT & Removed(EDA_ITEM *aItem)
Notifies observers that aItem has been removed
Definition: commit.h:96
Class LSET is a set of PCB_LAYER_IDs.
bool RemoveMisConnectedTracks()
Function RemoveMisConnectedTracks finds all track segments which are mis-connected (to more than one ...
bool removeBadTrackSegments()
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
#define STRUCT_DELETED
flag indication structures to be erased
Definition: base_struct.h:123
#define TRACK_LOCKED
Pcbnew: track locked: protected from global deletion.
Definition: base_struct.h:129
const ZONE_CONTAINER * zoneForTrackEndpoint(const TRACK *aTrack, ENDPOINT_T aEndPoint)
#define FLAG0
Pcbnew: flag used in local computations.
Definition: base_struct.h:132
#define END_ON_PAD
Definition: netinfo.h:591
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:53
static void updateConn(TRACK *track, const std::shared_ptr< CONNECTIVITY_DATA > &connectivity)
Function used by cleanupSegments.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:126
TRACK * mergeCollinearSegmentIfPossible(TRACK *aTrackRef, TRACK *aCandidate, ENDPOINT_T aEndType)
helper function merge aTrackRef and aCandidate, when possible, i.e.
void SetState(int type, int state)
Definition: base_struct.h:245
int GetWidth() const
Definition: class_track.h:120
TRACK * Next() const
Definition: class_track.h:103
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
static bool parallelismTest(int dx1, int dy1, int dx2, int dy2)
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
const wxPoint & GetEnd() const
Definition: class_track.h:123
void SetStart(const wxPoint &aStart)
Definition: class_track.h:125
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
DLIST< TRACK > m_Track
Definition: class_board.h:250
bool cleanupSegments()
Merge collinear segments and remove duplicated and null len segments.
BOARD * GetBoard() const
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:258
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: class_track.h:130
void removeDuplicatesOfVia(const VIA *aVia, std::set< BOARD_ITEM * > &aToRemove)
Removes all the following THT vias on the same position of the specified one.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetState(int type) const
Definition: base_struct.h:240
bool deleteNullSegments()
Delete null length track segments.
void Clean_Pcb()
Function Clean_Pcb Clean up the board (remove redundant vias, not connected tracks and merges colline...
void Remove(BOARD_ITEM *aBoardItem) override
Removes an item from the container.
void buildTrackConnectionInfo()
helper function Rebuild list of tracks, and connected tracks this info must be rebuilt when tracks ar...
bool removeItems(std::set< BOARD_ITEM * > &aItems)
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
bool cleanupVias()
Removes redundant vias like vias at same location or on pad through.
VIA * GetFirstVia(TRACK *aTrk, const TRACK *aStopPoint=NULL)
Scan a track list for the first VIA o NULL if not found (or NULL passed)
Definition: class_track.h:514