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 <reporter.h>
40 #include <board_commit.h>
43 
44 #include <tool/tool_manager.h>
45 #include <tools/pcb_actions.h>
46 
47 #include <tracks_cleaner.h>
48 
49 
50 /* Install the cleanup dialog frame to know what should be cleaned
51 */
53 {
55 
56  dlg.ShowModal();
57 }
58 
59 
61  m_units( aUnits ),
62  m_brd( aPcb ),
63  m_commit( aCommit ),
64  m_dryRun( true ),
65  m_itemsList( nullptr )
66 {
67 }
68 
69 
71 {
72  auto connectivity = m_brd->GetConnectivity();
73 
74  connectivity->Build(m_brd);
75 
76  // clear flags and variables used in cleanup
77  for( auto track : m_brd->Tracks() )
78  {
79  track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
80  }
81 
82  for( auto track : m_brd->Tracks() )
83  {
84  // Mark track if connected to pads
85  for( auto pad : connectivity->GetConnectedPads( track ) )
86  {
87  if( pad->HitTest( track->GetStart() ) )
88  track->SetState( START_ON_PAD, true );
89 
90  if( pad->HitTest( track->GetEnd() ) )
91  track->SetState( END_ON_PAD, true );
92  }
93  }
94 }
95 
96 
97 /* Main cleaning function.
98  * Delete
99  * - Redundant points on tracks (merge aligned segments)
100  * - vias on pad
101  * - null length segments
102  */
103 bool TRACKS_CLEANER::CleanupBoard( bool aDryRun, DRC_LIST* aItemsList,
104  bool aRemoveMisConnected,
105  bool aCleanVias,
106  bool aMergeSegments,
107  bool aDeleteUnconnected )
108 {
109  m_dryRun = aDryRun;
110  m_itemsList = aItemsList;
111  bool modified = false;
112 
113  // delete redundant vias
114  if( aCleanVias )
115  modified |= cleanupVias();
116 
117  // Remove null segments and intermediate points on aligned segments
118  // If not asked, remove null segments only if remove misconnected is asked
119  if( aMergeSegments )
120  modified |= cleanupSegments();
121  else if( aRemoveMisConnected )
122  modified |= deleteNullSegments();
123 
125 
126  if( aRemoveMisConnected )
127  modified |= removeBadTrackSegments();
128 
129  // Delete dangling tracks
130  if( aDeleteUnconnected )
131  {
132  if( deleteDanglingTracks() )
133  {
134  modified = true;
135 
136  // Removed tracks can leave aligned segments
137  // (when a T was formed by tracks and the "vertical" segment
138  // is removed)
139  if( aMergeSegments )
140  cleanupSegments();
141  }
142  }
143 
144  return modified;
145 }
146 
147 
149 {
150  auto connectivity = m_brd->GetConnectivity();
151 
152  std::set<BOARD_ITEM *> toRemove;
153 
154  for( auto segment : m_brd->Tracks() )
155  {
156  segment->SetState( FLAG0, false );
157 
158  for( auto testedPad : connectivity->GetConnectedPads( segment ) )
159  {
160  if( segment->GetNetCode() != testedPad->GetNetCode() )
161  {
162  if( m_itemsList )
163  {
164  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_SHORT,
165  segment, segment->GetPosition(),
166  nullptr, wxPoint() ) );
167  }
168 
169  toRemove.insert( segment );
170  }
171  }
172 
173  for( auto testedTrack : connectivity->GetConnectedTracks( segment ) )
174  {
175  if( segment->GetNetCode() != testedTrack->GetNetCode() && !testedTrack->GetState( FLAG0 ) )
176  {
177  if( m_itemsList )
178  {
179  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_SHORT,
180  segment, segment->GetPosition(),
181  nullptr, wxPoint() ) );
182  }
183 
184  toRemove.insert( segment );
185  }
186  }
187  }
188 
189  return removeItems( toRemove );
190 }
191 
192 
193 void TRACKS_CLEANER::removeDuplicatesOfVia( const VIA *aVia, std::set<BOARD_ITEM *>& aToRemove )
194 {
195  VIA* next_via;
196 
197  for( VIA* alt_via = GetFirstVia( aVia->Next() ); alt_via != NULL; alt_via = next_via )
198  {
199  next_via = GetFirstVia( alt_via->Next() );
200 
201  if( ( alt_via->GetViaType() == VIA_THROUGH ) && alt_via->GetStart() == aVia->GetStart() )
202  {
203  if( m_itemsList )
204  {
205  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_REDUNDANT_VIA,
206  alt_via, alt_via->GetPosition(),
207  nullptr, wxPoint() ) );
208  }
209 
210  aToRemove.insert ( alt_via );
211  }
212  }
213 }
214 
215 
217 {
218  std::set<BOARD_ITEM*> toRemove;
219 
220  for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL; via = GetFirstVia( via->Next() ) )
221  {
222  if( via->GetFlags() & TRACK_LOCKED )
223  continue;
224 
225  // Correct via m_End defects (if any), should never happen
226  if( via->GetStart() != via->GetEnd() )
227  {
228  wxFAIL_MSG( "Malformed via with mismatching ends" );
229  via->SetEnd( via->GetStart() );
230  }
231 
232  /* Important: these cleanups only do thru hole vias, they don't
233  * (yet) handle high density interconnects */
234  if( via->GetViaType() == VIA_THROUGH )
235  {
236  removeDuplicatesOfVia( via, toRemove );
237 
238  /* To delete through Via on THT pads at same location
239  * Examine the list of connected pads:
240  * if one through pad is found, the via can be removed */
241 
242  const auto pads = m_brd->GetConnectivity()->GetConnectedPads( via );
243  for( const auto pad : pads )
244  {
245  const LSET all_cu = LSET::AllCuMask();
246 
247  if( ( pad->GetLayerSet() & all_cu ) == all_cu )
248  {
249  if( m_itemsList )
250  {
251  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_REDUNDANT_VIA,
252  via, via->GetPosition(),
253  nullptr, wxPoint() ) );
254  }
255 
256  // redundant: delete the via
257  toRemove.insert( via );
258  break;
259  }
260  }
261  }
262  }
263 
264  return removeItems( toRemove );
265 }
266 
267 
271 {
272  auto connectivity = m_brd->GetConnectivity();
273  VECTOR2I endpoint ;
274 
275  if( aTrack->Type() == PCB_TRACE_T )
276  endpoint = aTrack->GetEndPoint( aEndPoint );
277  else
278  endpoint = aTrack->GetStart( );
279 
280  //wxASSERT ( connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ) != nullptr );
281  wxASSERT ( connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems().size() != 0 );
282  auto citem = connectivity->GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems().front();
283 
284  if( !citem->Valid() )
285  return false;
286 
287  auto anchors = citem->Anchors();
288 
289  for( const auto& anchor : anchors )
290  {
291  if( anchor->Pos() == endpoint && anchor->IsDangling() )
292  return true;
293  }
294 
295  return false;
296 }
297 
298 
299 /* Delete dangling tracks
300  * Vias:
301  * If a via is only connected to a dangling track, it also will be removed
302  */
304 {
305  bool item_erased = false;
306  bool modified = false;
307 
308  do // Iterate when at least one track is deleted
309  {
311  item_erased = false;
312 
313  TRACK* next_track;
314 
315  for( TRACK *track = m_brd->m_Track; track != NULL; track = next_track )
316  {
317  next_track = track->Next();
318  bool flag_erase = false; // Start without a good reason to erase it
319 
320  /* if a track endpoint is not connected to a pad, test if
321  * the endpoint is connected to another track or to a zone.
322  * For via test, an enhancement could be to test if
323  * connected to 2 items on different layers. Currently
324  * a via must be connected to 2 items, that can be on the
325  * same layer */
326 
327  // Check if there is nothing attached on the start
328  if( !( track->GetState( START_ON_PAD ) ) )
329  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_START );
330 
331  // If not sure about removal, then check if there is nothing attached on the end
332  if( !flag_erase && !track->GetState( END_ON_PAD ) )
333  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_END );
334 
335  if( flag_erase )
336  {
337  if( m_itemsList )
338  {
339  int code = track->IsTrack() ? DRCE_DANGLING_TRACK : DRCE_DANGLING_VIA;
340  m_itemsList->emplace_back( new DRC_ITEM( m_units, code,
341  track, track->GetPosition(),
342  nullptr, wxPoint() ) );
343  }
344 
345  if( !m_dryRun )
346  {
347  m_brd->Remove( track );
348  m_commit.Removed( track );
349 
350  /* keep iterating, because a track connected to the deleted track
351  * now perhaps is not connected and should be deleted */
352  item_erased = true;
353  modified = true;
354  }
355  }
356  }
357  } while( item_erased );
358 
359 
360  return modified;
361 }
362 
363 
364 // Delete null length track segments
366 {
367  std::set<BOARD_ITEM *> toRemove;
368 
369  for( auto segment : m_brd->Tracks() )
370  {
371  if( segment->IsNull() ) // Length segment = 0; delete it
372  {
373  if( m_itemsList )
374  {
375  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_ZERO_LENGTH_TRACK,
376  segment, segment->GetPosition(),
377  nullptr, wxPoint() ) );
378  }
379 
380  toRemove.insert( segment );
381  }
382  }
383 
384  return removeItems( toRemove );
385 }
386 
387 void TRACKS_CLEANER::removeDuplicatesOfTrack( const TRACK *aSeg, std::set<BOARD_ITEM*>& aToRemove )
388 {
389  if( aSeg->GetEditFlags() & STRUCT_DELETED )
390  return;
391 
392  for( auto seg2 : m_brd->Tracks() )
393  {
394  // New netcode, break out (can't be there any seg2)
395  if( aSeg->GetNetCode() != seg2->GetNetCode() )
396  continue;
397 
398  if( aSeg == seg2 )
399  continue;
400 
401  if( seg2->GetFlags() & STRUCT_DELETED )
402  continue;
403 
404  // Must be of the same type, on the same layer and with the same endpoints (although
405  // they might be swapped)
406  if( aSeg->Type() == seg2->Type() && aSeg->GetLayer() == seg2->GetLayer() )
407  {
408  if( ( aSeg->GetStart() == seg2->GetStart() && aSeg->GetEnd() == seg2->GetEnd() ) ||
409  ( aSeg->GetStart() == seg2->GetEnd() && aSeg->GetEnd() == seg2->GetStart() ) )
410  {
411  if( m_itemsList )
412  {
413  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_DUPLICATE_TRACK,
414  seg2, seg2->GetPosition(),
415  nullptr, wxPoint() ) );
416  }
417 
418  seg2->SetFlags( STRUCT_DELETED );
419  aToRemove.insert( seg2 );
420  }
421  }
422  }
423 }
424 
425 
427 {
428  bool merged_this = false;
429 
430  if( !aSegment->Next() )
431  return merged_this;
432 
433  for( ENDPOINT_T endpoint : { ENDPOINT_START, ENDPOINT_END } )
434  {
435  // search for a possible segment connected to the current endpoint of the current one
436  TRACK* seg2 = aSegment->GetTrack( aSegment->Next(), NULL, endpoint, true, false );
437 
438  if( seg2 )
439  {
440  // the two segments must have the same width and seg2 cannot be a via
441  if( aSegment->GetWidth() == seg2->GetWidth() && seg2->Type() == PCB_TRACE_T )
442  {
443  // There can be only one segment connected
444  seg2->SetState( BUSY, true );
445  TRACK* seg3 = aSegment->GetTrack( m_brd->m_Track, NULL, endpoint, true, false );
446  seg2->SetState( BUSY, false );
447 
448  if( seg3 )
449  continue;
450 
451  // Try to merge them
452  TRACK* segDelete = mergeCollinearSegments( aSegment, seg2, endpoint );
453 
454  // Merge succesful, seg2 has to go away
455  if( !m_dryRun && segDelete )
456  {
457  m_brd->Remove( segDelete );
458  m_commit.Removed( segDelete );
459  merged_this = true;
460  }
461  }
462  }
463  }
464 
465  return merged_this;
466 }
467 
468 
469 // Delete null length segments, and intermediate points ..
471 {
472  bool modified = false;
473 
474  // Easy things first
475  modified |= deleteNullSegments();
476 
478 
479  std::set<BOARD_ITEM*> toRemove;
480 
481  // Delete redundant segments, i.e. segments having the same end points and layers
482  // (can happens when blocks are copied on themselve)
483  for( auto segment : m_brd->Tracks() )
484  removeDuplicatesOfTrack( segment, toRemove );
485 
486  modified |= removeItems( toRemove );
487 
488  if( modified )
490 
491  // merge collinear segments:
492  TRACK* nextsegment;
493 
494  for( TRACK* segment = m_brd->m_Track; segment; segment = nextsegment )
495  {
496  nextsegment = segment->Next();
497 
498  if( segment->Type() == PCB_TRACE_T )
499  {
500  bool merged_this = MergeCollinearTracks( segment );
501 
502  if( merged_this ) // The current segment was modified, retry to merge it again
503  {
504  nextsegment = segment->Next();
505  modified = true;
506  }
507  }
508  }
509 
510  return modified;
511 }
512 
513 
514 /* Utility: check for parallelism between two segments */
515 static bool parallelismTest( int dx1, int dy1, int dx2, int dy2 )
516 {
517  /* The following condition list is ugly and repetitive, but I have
518  * not a better way to express clearly the trivial cases. Hope the
519  * compiler optimize it better than always doing the product
520  * below... */
521 
522  // test for vertical alignment (easy to handle)
523  if( dx1 == 0 )
524  return dx2 == 0;
525 
526  if( dx2 == 0 )
527  return dx1 == 0;
528 
529  // test for horizontal alignment (easy to handle)
530  if( dy1 == 0 )
531  return dy2 == 0;
532 
533  if( dy2 == 0 )
534  return dy1 == 0;
535 
536  /* test for alignment in other cases: Do the usual cross product test
537  * (the same as testing the slope, but without a division) */
538  return ((double)dy1 * dx2 == (double)dx1 * dy2);
539 }
540 
541 
554 static void updateConn( TRACK *track, const std::shared_ptr<CONNECTIVITY_DATA>& connectivity )
555 {
556  for( auto pad : connectivity->GetConnectedPads( track ) )
557  {
558  if( pad->HitTest( track->GetStart() ) )
559  track->SetState( START_ON_PAD, true );
560 
561  if( pad->HitTest( track->GetEnd() ) )
562  track->SetState( END_ON_PAD, true );
563  }
564 }
565 
566 
568  ENDPOINT_T aEndType )
569 {
570  // First of all, they must be of the same width and must be both actual tracks
571  if( aSeg1->GetWidth() != aSeg2->GetWidth() ||
572  aSeg1->Type() != PCB_TRACE_T || aSeg2->Type() != PCB_TRACE_T )
573  {
574  return NULL;
575  }
576 
577  // Trivial case: exactly the same track
578  if( ( aSeg1->GetStart() == aSeg2->GetStart() && aSeg1->GetEnd() == aSeg2->GetEnd() ) ||
579  ( aSeg1->GetStart() == aSeg2->GetEnd() && aSeg1->GetEnd() == aSeg2->GetStart() ))
580  {
581  if( m_itemsList )
582  {
583  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_DUPLICATE_TRACK,
584  aSeg2, aSeg2->GetPosition(),
585  nullptr, wxPoint() ) );
586  }
587 
588  return aSeg2;
589  }
590 
591  // Weed out non-parallel tracks
592  if( !parallelismTest( aSeg1->GetEnd().x - aSeg1->GetStart().x,
593  aSeg1->GetEnd().y - aSeg1->GetStart().y,
594  aSeg2->GetEnd().x - aSeg2->GetStart().x,
595  aSeg2->GetEnd().y - aSeg2->GetStart().y ) )
596  {
597  return NULL;
598  }
599 
600  auto connectivity = m_brd->GetConnectivity();
601 
602  updateConn( aSeg1, connectivity );
603  updateConn( aSeg2, connectivity );
604 
605  if( ( aEndType == ENDPOINT_START && aSeg1->GetState( START_ON_PAD ) ) ||
606  ( aEndType == ENDPOINT_END && aSeg1->GetState( END_ON_PAD ) ) )
607  {
608  // We do not have a pad, which is a always terminal point for a track
609  return NULL;
610  }
611 
612  if( m_itemsList )
613  {
614  m_itemsList->emplace_back( new DRC_ITEM( m_units, DRCE_MERGE_TRACKS,
615  aSeg1, aSeg1->GetPosition(),
616  aSeg2, aSeg2->GetPosition() ) );
617  }
618 
619  if( !m_dryRun )
620  {
621  m_commit.Modify( aSeg1 );
622 
623  if( aEndType == ENDPOINT_START )
624  {
625  /* change the common point coordinate of pt_segm to use the other point
626  * of pt_segm (pt_segm will be removed later) */
627  if( aSeg1->GetStart() == aSeg2->GetStart() )
628  {
629  aSeg1->SetStart( aSeg2->GetEnd() );
630  aSeg1->SetState( START_ON_PAD, aSeg2->GetState( END_ON_PAD ) );
631  }
632  else
633  {
634  aSeg1->SetStart( aSeg2->GetStart() );
635  aSeg1->SetState( START_ON_PAD, aSeg2->GetState( START_ON_PAD ) );
636  }
637  }
638  else // aEndType == END
639  {
640  /* change the common point coordinate of pt_segm to use the other point
641  * of pt_segm (pt_segm will be removed later) */
642  if( aSeg1->GetEnd() == aSeg2->GetStart() )
643  {
644  aSeg1->SetEnd( aSeg2->GetEnd() );
645  aSeg1->SetState( END_ON_PAD, aSeg2->GetState( END_ON_PAD ) );
646  }
647  else
648  {
649  aSeg1->SetEnd( aSeg2->GetStart() );
650  aSeg1->SetState( END_ON_PAD, aSeg2->GetState( START_ON_PAD ) );
651  }
652  }
653 
654  connectivity->Update( aSeg1 );
655  }
656 
657  return aSeg2;
658 }
659 
660 
661 bool TRACKS_CLEANER::removeItems( std::set<BOARD_ITEM*>& aItems )
662 {
663  if( m_dryRun )
664  return false;
665 
666  bool isModified = false;
667 
668  for( auto item : aItems )
669  {
670  isModified = true;
671  m_brd->Remove( item );
672  m_commit.Removed( item );
673  }
674 
675  return isModified;
676 }
677 
678 
680 {
681  // Old model has to be refreshed, GAL normally does not keep updating it
682  Compile_Ratsnest( NULL, false );
683  BOARD_COMMIT commit( this );
684 
685  TRACKS_CLEANER cleaner( m_UserUnits, GetBoard(), commit );
686  bool isModified = cleaner.CleanupBoard( true, nullptr, true, false, false, false );
687 
688  if( isModified )
689  {
690  // Clear undo and redo lists to avoid inconsistencies between lists
691  SetCurItem( NULL );
692  commit.Push( _( "Board cleanup" ) );
693  Compile_Ratsnest( NULL, true );
694  }
695 
696  m_canvas->Refresh( true );
697 
698  return isModified;
699 }
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
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.
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
#define DRCE_MERGE_TRACKS
Definition: drc.h:109
TRACK * mergeCollinearSegments(TRACK *aSeg1, TRACK *aSeg2, ENDPOINT_T aEndType)
helper function merge aTrackRef and aCandidate, when possible, i.e.
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:129
const wxPoint & GetStart() const
Definition: class_track.h:133
#define DRCE_DANGLING_VIA
Definition: drc.h:111
#define DRCE_DUPLICATE_TRACK
Definition: drc.h:108
#define DRCE_SHORT
Definition: drc.h:106
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.
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:134
bool testTrackEndpointDangling(TRACK *aTrack, ENDPOINT_T aEndPoint)
Utility: does the endpoint unconnected processed for one endpoint of one track Returns true if the tr...
bool CleanupBoard(bool aDryRun, DRC_LIST *aItemsList, bool aCleanVias, bool aRemoveMisConnected, bool aMergeSegments, bool aDeleteUnconnected)
the cleanup function.
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
#define START_ON_PAD
Definition: netinfo.h:586
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.
#define DRCE_ZERO_LENGTH_TRACK
Definition: drc.h:112
const wxPoint GetPosition() const override
Definition: class_track.h:124
bool RemoveMisConnectedTracks()
Function RemoveMisConnectedTracks finds all track segments which are mis-connected (to more than one ...
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:263
EDA_UNITS_T m_units
bool removeBadTrackSegments()
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:292
ENDPOINT_T
Definition: class_track.h:50
#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:128
std::vector< DRC_ITEM * > DRC_LIST
Definition: drc.h:177
TRACKS_CLEANER(EDA_UNITS_T aUnits, BOARD *aPcb, BOARD_COMMIT &aCommit)
#define FLAG0
Pcbnew: flag used in local computations.
Definition: base_struct.h:131
#define END_ON_PAD
Definition: netinfo.h:587
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:53
void removeDuplicatesOfTrack(const TRACK *aSeg, std::set< BOARD_ITEM * > &aToRemove)
Removes all the following duplicates tracks of the specified one.
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:128
void SetState(int type, int state)
Definition: base_struct.h:248
int GetWidth() const
Definition: class_track.h:127
TRACK * Next() const
Definition: class_track.h:110
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
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:130
void SetStart(const wxPoint &aStart)
Definition: class_track.h:132
#define DRCE_REDUNDANT_VIA
Definition: drc.h:107
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:251
DLIST< TRACK > m_Track
Definition: class_board.h:249
DRC_LIST * m_itemsList
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)
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: class_track.h:137
EDA_UNITS_T m_UserUnits
Definition: draw_frame.h:125
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:243
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.
EDA_UNITS_T
Definition: common.h:157
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:204
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:490
#define DRCE_DANGLING_TRACK
Definition: drc.h:110