KiCad PCB EDA Suite
clean.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-2016 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2016 KiCad Developers, see change_log.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 <wxPcbStruct.h>
35 #include <pcbnew.h>
36 #include <class_board.h>
37 #include <class_track.h>
38 #include <connect.h>
40 #include <board_commit.h>
41 
42 #include <tuple>
43 
44 // Helper class used to clean tracks and vias
46 {
47 public:
48  TRACKS_CLEANER( BOARD* aPcb, BOARD_COMMIT& aCommit );
49 
60  bool CleanupBoard( bool aCleanVias, bool aRemoveMisConnected,
61  bool aMergeSegments, bool aDeleteUnconnected );
62 
63 private:
64  /* finds and remove all track segments which are connected to more than one net.
65  * (short circuits)
66  */
68 
73  bool clean_vias();
74 
79  bool remove_duplicates_of_via( const VIA* aVia );
80 
84  bool remove_duplicates_of_track( const TRACK* aTrack );
85 
89  bool deleteDanglingTracks();
90 
92  bool delete_null_segments();
93 
95  bool merge_collinear_of_track( TRACK* aSegment );
96 
100  bool clean_segments();
101 
108 
115  TRACK* aCandidate, ENDPOINT_T aEndType );
116 
117  const ZONE_CONTAINER* zoneForTrackEndpoint( const TRACK* aTrack,
118  ENDPOINT_T aEndPoint );
119 
120  bool testTrackEndpointDangling( TRACK* aTrack, ENDPOINT_T aEndPoint );
121 
124 };
125 
126 
127 /* Install the cleanup dialog frame to know what should be cleaned
128 */
130 {
131  DIALOG_CLEANING_OPTIONS dlg( this );
132 
133  if( dlg.ShowModal() != wxID_OK )
134  return;
135 
136  // Old model has to be refreshed, GAL normally does not keep updating it
137  Compile_Ratsnest( NULL, false );
138 
139  wxBusyCursor( dummy );
140  BOARD_COMMIT commit( this );
141  TRACKS_CLEANER cleaner( GetBoard(), commit );
142 
143  bool modified = cleaner.CleanupBoard( dlg.m_deleteShortCircuits, dlg.m_cleanVias,
145 
146  if( modified )
147  {
148  // Clear undo and redo lists to avoid inconsistencies between lists
149  SetCurItem( NULL );
150  commit.Push( _( "Board cleanup" ) );
151  Compile_Ratsnest( NULL, true );
152  }
153 
154  m_canvas->Refresh( true );
155 }
156 
157 
158 /* Main cleaning function.
159  * Delete
160  * - Redundant points on tracks (merge aligned segments)
161  * - vias on pad
162  * - null length segments
163  */
164 bool TRACKS_CLEANER::CleanupBoard( bool aRemoveMisConnected,
165  bool aCleanVias,
166  bool aMergeSegments,
167  bool aDeleteUnconnected )
168 {
170 
171  bool modified = false;
172 
173  // delete redundant vias
174  if( aCleanVias )
175  modified |= clean_vias();
176 
177  // Remove null segments and intermediate points on aligned segments
178  // If not asked, remove null segments only if remove misconnected is asked
179  if( aMergeSegments )
180  modified |= clean_segments();
181  else if( aRemoveMisConnected )
182  modified |= delete_null_segments();
183 
184  if( aRemoveMisConnected )
185  {
186  if( removeBadTrackSegments() )
187  {
188  modified = true;
189 
190  // Refresh track connection info
192  }
193  }
194 
195  // Delete dangling tracks
196  if( aDeleteUnconnected )
197  {
198  if( modified ) // Refresh track connection info
200 
201  if( deleteDanglingTracks() )
202  {
203  modified = true;
204 
205  // Removed tracks can leave aligned segments
206  // (when a T was formed by tracks and the "vertical" segment
207  // is removed)
208  if( aMergeSegments )
209  clean_segments();
210  }
211  }
212 
213  return modified;
214 }
215 
216 
218  : CONNECTIONS( aPcb ), m_brd( aPcb ), m_commit( aCommit )
219 {
220  // Be sure pad list is up to date
221  BuildPadsList();
222 }
223 
224 
226 {
228 
229  // clear flags and variables used in cleanup
230  for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() )
231  {
232  track->start = NULL;
233  track->end = NULL;
234  track->m_PadsConnected.clear();
235  track->SetState( START_ON_PAD | END_ON_PAD | BUSY, false );
236  }
237 
238  // Build connections info tracks to pads
240 
241  for( TRACK* track = m_brd->m_Track; track != NULL; track = track->Next() )
242  {
243  // Mark track if connected to pads
244  for( unsigned jj = 0; jj < track->m_PadsConnected.size(); jj++ )
245  {
246  D_PAD * pad = track->m_PadsConnected[jj];
247 
248  if( pad->HitTest( track->GetStart() ) )
249  {
250  track->start = pad;
251  track->SetState( START_ON_PAD, true );
252  }
253 
254  if( pad->HitTest( track->GetEnd() ) )
255  {
256  track->end = pad;
257  track->SetState( END_ON_PAD, true );
258  }
259  }
260  }
261 }
262 
263 
265 {
266  // The rastsnet is expected to be up to date (Compile_Ratsnest was called)
267 
268  // Rebuild physical connections.
269  // the list of physical connected items to a given item is in
270  // m_PadsConnected and m_TracksConnected members of each item
272 
273  // build connections between track segments and pads.
275 
276  TRACK* segment;
277 
278  // build connections between track ends
279  for( segment = m_brd->m_Track; segment; segment = segment->Next() )
280  {
281  SearchConnectedTracks( segment );
282  GetConnectedTracks( segment );
283  }
284 
285  bool isModified = false;
286 
287  for( segment = m_brd->m_Track; segment; segment = segment->Next() )
288  {
289  segment->SetState( FLAG0, false );
290 
291  for( unsigned ii = 0; ii < segment->m_PadsConnected.size(); ++ii )
292  {
293  if( segment->GetNetCode() != segment->m_PadsConnected[ii]->GetNetCode() )
294  segment->SetState( FLAG0, true );
295  }
296 
297  for( unsigned ii = 0; ii < segment->m_TracksConnected.size(); ++ii )
298  {
299  TRACK* tested = segment->m_TracksConnected[ii];
300 
301  if( segment->GetNetCode() != tested->GetNetCode() && !tested->GetState( FLAG0 ) )
302  segment->SetState( FLAG0, true );
303  }
304  }
305 
306  // Remove tracks having a flagged segment
307  TRACK* next;
308 
309  for( segment = m_brd->m_Track; segment; segment = next )
310  {
311  next = segment->Next();
312 
313  if( segment->GetState( FLAG0 ) ) // Segment is flagged to be removed
314  {
315  isModified = true;
316  m_brd->Remove( segment );
317  m_commit.Removed( segment );
318  }
319  }
320 
321  if( isModified )
322  { // some pointers are invalid. Clear the m_TracksConnected list,
323  // to avoid any issue
324  for( segment = m_brd->m_Track; segment; segment = segment->Next() )
325  segment->m_TracksConnected.clear();
326 
327  m_brd->m_Status_Pcb = 0;
328  }
329 
330  return isModified;
331 }
332 
333 
335 {
336  bool modified = false;
337 
338  // Search and delete others vias at same location
339  VIA* next_via;
340 
341  for( VIA* alt_via = GetFirstVia( aVia->Next() ); alt_via != NULL; alt_via = next_via )
342  {
343  next_via = GetFirstVia( alt_via->Next() );
344 
345  if( ( alt_via->GetViaType() == VIA_THROUGH ) &&
346  ( alt_via->GetStart() == aVia->GetStart() ) )
347  {
348  m_brd->Remove( alt_via );
349  m_commit.Removed( alt_via );
350  modified = true;
351  }
352  }
353  return modified;
354 }
355 
356 
358 {
359  bool modified = false;
360 
361  for( VIA* via = GetFirstVia( m_brd->m_Track ); via != NULL;
362  via = GetFirstVia( via->Next() ) )
363  {
364  // Correct via m_End defects (if any), should never happen
365  if( via->GetStart() != via->GetEnd() )
366  {
367  wxFAIL_MSG( "Malformed via with mismatching ends" );
368  via->SetEnd( via->GetStart() );
369  }
370 
371  /* Important: these cleanups only do thru hole vias, they don't
372  * (yet) handle high density interconnects */
373  if( via->GetViaType() == VIA_THROUGH )
374  {
375  modified |= remove_duplicates_of_via( via );
376 
377  /* To delete through Via on THT pads at same location
378  * Examine the list of connected pads:
379  * if one through pad is found, the via can be removed */
380  for( unsigned ii = 0; ii < via->m_PadsConnected.size(); ++ii )
381  {
382  const D_PAD* pad = via->m_PadsConnected[ii];
383  const LSET all_cu = LSET::AllCuMask();
384 
385  if( ( pad->GetLayerSet() & all_cu ) == all_cu )
386  {
387  // redundant: delete the via
388  m_brd->Remove( via );
389  m_commit.Removed( via );
390  modified = true;
391  break;
392  }
393  }
394  }
395  }
396 
397  return modified;
398 }
399 
400 
403  ENDPOINT_T aEndPoint )
404 {
405  // Vias are special cased, since they get a layer range, not a single one
406  PCB_LAYER_ID top_layer, bottom_layer;
407  const VIA* via = dyn_cast<const VIA*>( aTrack );
408 
409  if( via )
410  via->LayerPair( &top_layer, &bottom_layer );
411  else
412  {
413  top_layer = aTrack->GetLayer();
414  bottom_layer = top_layer;
415  }
416 
417  return m_brd->HitTestForAnyFilledArea( aTrack->GetEndPoint( aEndPoint ),
418  top_layer, bottom_layer, aTrack->GetNetCode() );
419 }
420 
421 
425 {
426  bool flag_erase = false;
427 
428  TRACK* other = aTrack->GetTrack( m_brd->m_Track, NULL, aEndPoint, true, false );
429 
430  if( !other && !zoneForTrackEndpoint( aTrack, aEndPoint ) )
431  flag_erase = true; // Start endpoint is neither on pad, zone or other track
432  else // segment, via or zone connected to this end
433  {
434  // Fill connectivity informations
435  if( aEndPoint == ENDPOINT_START )
436  aTrack->start = other;
437  else
438  aTrack->end = other;
439 
440  /* If a via is connected to this end, test if this via has a second item connected.
441  * If not, remove the current segment (the via would then become
442  * unconnected and remove on the following pass) */
443  VIA* via = dyn_cast<VIA*>( other );
444 
445  if( via )
446  {
447  // search for another segment following the via
448  aTrack->SetState( BUSY, true );
449 
450  other = via->GetTrack( m_brd->m_Track, NULL, aEndPoint, true, false );
451 
452  // There is a via on the start but it goes nowhere
453  if( !other && !zoneForTrackEndpoint( via, aEndPoint ) )
454  flag_erase = true;
455 
456  aTrack->SetState( BUSY, false );
457  }
458  }
459 
460  return flag_erase;
461 }
462 
463 
464 /* Delete dangling tracks
465  * Vias:
466  * If a via is only connected to a dangling track, it also will be removed
467  */
469 {
470  if( m_brd->m_Track == NULL )
471  return false;
472 
473  bool modified = false;
474  bool item_erased;
475 
476  do // Iterate when at least one track is deleted
477  {
478  item_erased = false;
479  TRACK* next_track;
480 
481  for( TRACK *track = m_brd->m_Track; track != NULL; track = next_track )
482  {
483  next_track = track->Next();
484 
485  bool flag_erase = false; // Start without a good reason to erase it
486 
487  /* if a track endpoint is not connected to a pad, test if
488  * the endpoint is connected to another track or to a zone.
489  * For via test, an enhancement could be to test if
490  * connected to 2 items on different layers. Currently
491  * a via must be connected to 2 items, that can be on the
492  * same layer */
493 
494  // Check if there is nothing attached on the start
495  if( !( track->GetState( START_ON_PAD ) ) )
496  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_START );
497 
498  // If not sure about removal, then check if there is nothing attached on the end
499  if( !flag_erase && !track->GetState( END_ON_PAD ) )
500  flag_erase |= testTrackEndpointDangling( track, ENDPOINT_END );
501 
502  if( flag_erase )
503  {
504  m_brd->Remove( track );
505  m_commit.Removed( track );
506 
507  /* keep iterating, because a track connected to the deleted track
508  * now perhaps is not connected and should be deleted */
509  item_erased = true;
510  modified = true;
511  }
512  }
513  } while( item_erased );
514 
515  return modified;
516 }
517 
518 
519 // Delete null length track segments
521 {
522  bool modified = false;
523  TRACK* nextsegment;
524 
525  // Delete null segments
526  for( TRACK* segment = m_brd->m_Track; segment; segment = nextsegment )
527  {
528  nextsegment = segment->Next();
529 
530  if( segment->IsNull() ) // Length segment = 0; delete it
531  {
532  m_brd->Remove( segment );
533  m_commit.Removed( segment );
534  modified = true;
535  }
536  }
537 
538  return modified;
539 }
540 
541 
543 {
544  bool modified = false;
545  TRACK* nextsegment;
546 
547  for( TRACK* other = aTrack->Next(); other; other = nextsegment )
548  {
549  nextsegment = other->Next();
550 
551  // New netcode, break out (can't be there any other)
552  if( aTrack->GetNetCode() != other->GetNetCode() )
553  break;
554 
555  // Must be of the same type, on the same layer and the endpoints
556  // must be the same (maybe swapped)
557  if( ( aTrack->Type() == other->Type() ) &&
558  ( aTrack->GetLayer() == other->GetLayer() ) )
559  {
560  if( ( ( aTrack->GetStart() == other->GetStart() ) &&
561  ( aTrack->GetEnd() == other->GetEnd() ) ) ||
562  ( ( aTrack->GetStart() == other->GetEnd() ) &&
563  ( aTrack->GetEnd() == other->GetStart() ) ) )
564  {
565  m_brd->Remove( other );
566  m_commit.Removed( other );
567  modified = true;
568  }
569  }
570  }
571 
572  return modified;
573 }
574 
575 
577 {
578  bool merged_this = false;
579 
580  for( ENDPOINT_T endpoint = ENDPOINT_START; endpoint <= ENDPOINT_END;
581  endpoint = ENDPOINT_T( endpoint + 1 ) )
582  {
583  // search for a possible segment connected to the current endpoint of the current one
584  TRACK* other = aSegment->Next();
585 
586  if( other )
587  {
588  other = aSegment->GetTrack( other, NULL, endpoint, true, false );
589 
590  if( other )
591  {
592  // the two segments must have the same width and the other
593  // cannot be a via
594  if( ( aSegment->GetWidth() == other->GetWidth() ) &&
595  ( other->Type() == PCB_TRACE_T ) )
596  {
597  // There can be only one segment connected
598  other->SetState( BUSY, true );
599  TRACK* yet_another = aSegment->GetTrack( m_brd->m_Track, NULL,
600  endpoint, true, false );
601  other->SetState( BUSY, false );
602 
603  if( !yet_another )
604  {
605  // Try to merge them
606  TRACK* segDelete = mergeCollinearSegmentIfPossible( aSegment,
607  other, endpoint );
608 
609  // Merge succesful, the other one has to go away
610  if( segDelete )
611  {
612  m_brd->Remove( segDelete );
613  m_commit.Removed( segDelete );
614  merged_this = true;
615  }
616  }
617  }
618  }
619  }
620  }
621 
622  return merged_this;
623 }
624 
625 
626 // Delete null length segments, and intermediate points ..
628 {
629  bool modified = false;
630 
631  // Easy things first
632  modified |= delete_null_segments();
633 
634  // Delete redundant segments, i.e. segments having the same end points and layers
635  // (can happens when blocks are copied on themselve)
636  for( TRACK* segment = m_brd->m_Track; segment; segment = segment->Next() )
637  modified |= remove_duplicates_of_track( segment );
638 
639  // merge collinear segments:
640  TRACK* nextsegment;
641 
642  for( TRACK* segment = m_brd->m_Track; segment; segment = nextsegment )
643  {
644  nextsegment = segment->Next();
645 
646  if( segment->Type() == PCB_TRACE_T )
647  {
648  bool merged_this = merge_collinear_of_track( segment );
649 
650  if( merged_this ) // The current segment was modified, retry to merge it again
651  {
652  nextsegment = segment->Next();
653  modified = true;
654  }
655  }
656  }
657 
658  return modified;
659 }
660 
661 
662 /* Utility: check for parallelism between two segments */
663 static bool parallelism_test( int dx1, int dy1, int dx2, int dy2 )
664 {
665  /* The following condition list is ugly and repetitive, but I have
666  * not a better way to express clearly the trivial cases. Hope the
667  * compiler optimize it better than always doing the product
668  * below... */
669 
670  // test for vertical alignment (easy to handle)
671  if( dx1 == 0 )
672  return dx2 == 0;
673 
674  if( dx2 == 0 )
675  return dx1 == 0;
676 
677  // test for horizontal alignment (easy to handle)
678  if( dy1 == 0 )
679  return dy2 == 0;
680 
681  if( dy2 == 0 )
682  return dy1 == 0;
683 
684  /* test for alignment in other cases: Do the usual cross product test
685  * (the same as testing the slope, but without a division) */
686  return ((double)dy1 * dx2 == (double)dx1 * dy2);
687 }
688 
689 
703  ENDPOINT_T aEndType )
704 {
705  // First of all, they must be of the same width and must be both actual tracks
706  if( ( aTrackRef->GetWidth() != aCandidate->GetWidth() ) ||
707  ( aTrackRef->Type() != PCB_TRACE_T ) ||
708  ( aCandidate->Type() != PCB_TRACE_T ) )
709  return NULL;
710 
711  // Trivial case: exactly the same track
712  if( ( aTrackRef->GetStart() == aCandidate->GetStart() ) &&
713  ( aTrackRef->GetEnd() == aCandidate->GetEnd() ) )
714  return aCandidate;
715 
716  if( ( aTrackRef->GetStart() == aCandidate->GetEnd() ) &&
717  ( aTrackRef->GetEnd() == aCandidate->GetStart() ) )
718  return aCandidate;
719 
720  // Weed out non-parallel tracks
721  if ( !parallelism_test( aTrackRef->GetEnd().x - aTrackRef->GetStart().x,
722  aTrackRef->GetEnd().y - aTrackRef->GetStart().y,
723  aCandidate->GetEnd().x - aCandidate->GetStart().x,
724  aCandidate->GetEnd().y - aCandidate->GetStart().y ) )
725  return NULL;
726 
727  /* Here we have 2 aligned segments:
728  * We must change the pt_ref common point only if not on a pad
729  * (this function) is called when there is only 2 connected segments,
730  * and if this point is not on a pad, it can be removed and the 2 segments will be merged
731  */
732  if( aEndType == ENDPOINT_START )
733  {
734  // We do not have a pad, which is a always terminal point for a track
735  if( aTrackRef->GetState( START_ON_PAD ) )
736  return NULL;
737 
738  /* change the common point coordinate of pt_segm to use the other point
739  * of pt_segm (pt_segm will be removed later) */
740  if( aTrackRef->GetStart() == aCandidate->GetStart() )
741  {
742  aTrackRef->SetStart( aCandidate->GetEnd() );
743  aTrackRef->start = aCandidate->end;
744  aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( END_ON_PAD ) );
745  return aCandidate;
746  }
747  else
748  {
749  aTrackRef->SetStart( aCandidate->GetStart() );
750  aTrackRef->start = aCandidate->start;
751  aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( START_ON_PAD ) );
752  return aCandidate;
753  }
754  }
755  else // aEndType == END
756  {
757  // We do not have a pad, which is a always terminal point for a track
758  if( aTrackRef->GetState( END_ON_PAD ) )
759  return NULL;
760 
761  /* change the common point coordinate of pt_segm to use the other point
762  * of pt_segm (pt_segm will be removed later) */
763  if( aTrackRef->GetEnd() == aCandidate->GetStart() )
764  {
765  aTrackRef->SetEnd( aCandidate->GetEnd() );
766  aTrackRef->end = aCandidate->end;
767  aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( END_ON_PAD ) );
768  return aCandidate;
769  }
770  else
771  {
772  aTrackRef->SetEnd( aCandidate->GetStart() );
773  aTrackRef->end = aCandidate->start;
774  aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( START_ON_PAD ) );
775  return aCandidate;
776  }
777  }
778 
779  return NULL;
780 }
781 
782 
784 {
785  // Old model has to be refreshed, GAL normally does not keep updating it
786  Compile_Ratsnest( NULL, false );
787  BOARD_COMMIT commit( this );
788 
789  TRACKS_CLEANER cleaner( GetBoard(), commit );
790  bool isModified = cleaner.CleanupBoard( true, false, false, false );
791 
792  if( isModified )
793  {
794  // Clear undo and redo lists to avoid inconsistencies between lists
795  SetCurItem( NULL );
796  commit.Push( _( "Board cleanup" ) );
797  Compile_Ratsnest( NULL, true );
798  }
799 
800  m_canvas->Refresh( true );
801 
802  return isModified;
803 }
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
BOARD * m_brd
Definition: clean.cpp:122
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
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...
static bool parallelism_test(int dx1, int dy1, int dx2, int dy2)
Definition: clean.cpp:663
bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
Definition: class_pad.cpp:752
#define END_ON_PAD
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Definition: draw_panel.cpp:326
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:117
bool CleanupBoard(bool aCleanVias, bool aRemoveMisConnected, bool aMergeSegments, bool aDeleteUnconnected)
the cleanup function.
Definition: clean.cpp:164
void GetConnectedTracks(TRACK *aTrack)
Function GetConnectedTracks Copy m_Connected that contains the list of tracks connected calculated by...
Definition: connect.h:170
Class BOARD to handle a board.
helper classes to find track to track and track to pad connections.
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.
Definition: clean.cpp:468
BOARD * GetBoard() const
bool remove_duplicates_of_via(const VIA *aVia)
Removes all the following THT vias on the same position of the specified one.
Definition: clean.cpp:334
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:134
TRACKS_CLEANER(BOARD *aPcb, BOARD_COMMIT &aCommit)
Definition: clean.cpp:217
bool testTrackEndpointDangling(TRACK *aTrack, ENDPOINT_T aEndPoint)
Utility: does the endpoint unconnected processed for one endpoint of one track Returns true if the tr...
Definition: clean.cpp:424
bool clean_segments()
Merge collinear segments and remove duplicated and null len segments.
Definition: clean.cpp:627
int GetState(int type) const
Definition: base_struct.h:237
#define START_ON_PAD
bool delete_null_segments()
Delete null length track segments.
Definition: clean.cpp:520
bool clean_vias()
Removes redundant vias like vias at same location or on pad through.
Definition: clean.cpp:357
Casted dyn_cast(From aObject)
Function dyn_cast()
Definition: typeinfo.h:73
const wxPoint & GetEnd() const
Definition: class_track.h:118
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true) override
Executes the changes.
Functions relatives to tracks, vias and segments used to fill zones.
void BuildPadsList(int aNetcode=-1)
Function BuildPadsList Fills m_sortedPads with all pads that be connected to tracks pads are sorted b...
Definition: connect.cpp:61
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
bool merge_collinear_of_track(TRACK *aSegment)
Try to merge the segment to a following collinear one.
Definition: clean.cpp:576
BOARD_COMMIT & m_commit
Definition: clean.cpp:123
ENDPOINT_T
Flag used in locate routines (from which endpoint work)
Definition: pcbnew.h:54
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 ...
COMMIT & Removed(EDA_ITEM *aItem)
Notifies observers that aItem has been removed
Definition: commit.h:96
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
void BuildTracksCandidatesList(TRACK *aBegin, TRACK *aEnd=NULL)
Function BuildTracksCandidatesList Fills m_Candidates with all connecting points (track ends or via l...
Definition: connect.cpp:252
const ZONE_CONTAINER * zoneForTrackEndpoint(const TRACK *aTrack, ENDPOINT_T aEndPoint)
Utility for checking if a track/via ends on a zone.
Definition: clean.cpp:402
bool RemoveMisConnectedTracks()
Function RemoveMisConnectedTracks finds all track segments which are mis-connected (to more than one ...
Definition: clean.cpp:783
int SearchConnectedTracks(const TRACK *aTrack)
function SearchConnectedTracks Populates .m_connected with tracks/vias connected to aTrack m_candidat...
Definition: connect.cpp:306
const wxPoint & GetStart() const
Definition: class_track.h:121
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
const wxPoint & GetEndPoint(ENDPOINT_T aEndPoint) const
Return the selected endpoint (start or end)
Definition: class_track.h:125
bool removeBadTrackSegments()
Definition: clean.cpp:264
void SearchTracksConnectedToPads(bool add_to_padlist=true, bool add_to_tracklist=true)
function SearchTracksConnectedToPads Explores the list of pads.
Definition: connect.cpp:114
std::vector< D_PAD * > m_PadsConnected
#define FLAG0
Pcbnew: flag used in local computations.
Definition: base_struct.h:131
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:165
int GetNetCode() const
Function GetNetCode.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
TRACK * Next() const
Definition: class_track.h:98
TRACK * mergeCollinearSegmentIfPossible(TRACK *aTrackRef, TRACK *aCandidate, ENDPOINT_T aEndType)
helper function merge aTrackRef and aCandidate, when possible, i.e.
Definition: clean.cpp:702
void SetState(int type, int state)
Definition: base_struct.h:242
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:166
int GetWidth() const
Definition: class_track.h:115
bool remove_duplicates_of_track(const TRACK *aTrack)
Removes all the following duplicates tracks of the specified one.
Definition: clean.cpp:542
std::vector< TRACK * > m_TracksConnected
void SetStart(const wxPoint &aStart)
Definition: class_track.h:120
DLIST< TRACK > m_Track
Definition: class_board.h:244
BOARD_CONNECTED_ITEM * end
Definition: class_track.h:90
BOARD_CONNECTED_ITEM * start
Definition: class_track.h:89
void Clean_Pcb()
Function Clean_Pcb Clean up the board (remove redundant vias, not connected tracks and merges colline...
Definition: clean.cpp:129
void Remove(BOARD_ITEM *aBoardItem) override
>
void buildTrackConnectionInfo()
helper function Rebuild list of tracks, and connected tracks this info must be rebuilt when tracks ar...
Definition: clean.cpp:225
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:240
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:497