KiCad PCB EDA Suite
tr_modif.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) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
33 #include <fctsys.h>
34 #include <gr_basic.h>
35 #include <wxPcbStruct.h>
36 
37 #include <class_board.h>
38 #include <class_track.h>
39 
40 #include <pcbnew.h>
41 #include <protos.h>
42 
43 
44 static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
45  bool onoff );
46 
47 
48 void DrawTraces( EDA_DRAW_PANEL* panel, wxDC* DC, TRACK* aTrackList, int nbsegment,
49  GR_DRAWMODE draw_mode )
50 {
51  // preserve the start of the list for debugging.
52  for( TRACK* track = aTrackList; nbsegment > 0 && track; nbsegment--, track = track->Next() )
53  {
54  track->Draw( panel, DC, draw_mode );
55  }
56 }
57 
58 /*
59  * This function try to remove an old track, when a new track is created,
60  * and the old track is no more needed
61  */
63  TRACK* aNewTrack,
64  int aNewTrackSegmentsCount,
65  PICKED_ITEMS_LIST* aItemsListPicker )
66 {
67  TRACK* StartTrack, * EndTrack;
68  TRACK* pt_segm;
69  TRACK* pt_del;
70  int ii, jj, nb_segm, nbconnect;
71  wxPoint start;
72  wxPoint end;
73  LSET startmasklayer, endmasklayer;
74 
75  int netcode = aNewTrack->GetNetCode();
76 
77  /* Reconstruct the complete track (the new track has to start on a segment of track).
78  */
79  ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, false );
80 
81  /* If the new track begins with a via, complete the track segment using
82  * the following segment as a reference because a via is often a hub of
83  * segments, and does not characterize track.
84  */
85  if( aNewTrack->Type() == PCB_VIA_T && ( aNewTrackSegmentsCount > 1 ) )
86  aNewTrack = aNewTrack->Next();
87 
88  aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
89  wxASSERT( aNewTrack );
90 
91 #if 0 && defined(DEBUG)
92  TRACK* EndNewTrack; // The last segment of the list chained to the track
93 
94  EndNewTrack = aNewTrack;
95 
96  for( ii = 1; ii < aNewTrackSegmentsCount; ii++ )
97  {
98  wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
99  D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
100  EndNewTrack = EndNewTrack->Next();
101  }
102 
103  wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
104  D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
105 
106  for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
107  track->Show( 0, std::cout );
108 
109 #endif
110 
111  TRACK* bufStart = m_Pcb->m_Track->GetStartNetCode( netcode ); // Beginning of tracks of the net
112  TRACK* bufEnd = bufStart->GetEndNetCode( netcode ); // End of tracks of the net
113 
114  // Flags for cleaning the net.
115  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
116  {
117 // D( std::cout<<"track "<<pt_del<<" turning off BUSY | IN_EDIT | IS_LINKED"<<std::endl; )
118  pt_del->SetState( BUSY | IN_EDIT | IS_LINKED, false );
119 
120  if( pt_del == bufEnd ) // Last segment reached
121  break;
122  }
123 
124  if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
125  return 0;
126 
127  if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
128  return 0;
129 
130  start = StartTrack->GetStart();
131  end = EndTrack->GetEnd();
132 
133  // The start and end points cannot be the same.
134  if( start == end )
135  return 0;
136 
137  // Determine layers interconnected these points.
138  startmasklayer = StartTrack->GetLayerSet();
139  endmasklayer = EndTrack->GetLayerSet();
140 
141  // There may be a via or a pad on the end points.
142  pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer );
143 
144  if( pt_segm )
145  startmasklayer |= pt_segm->GetLayerSet();
146 
147  if( StartTrack->start && ( StartTrack->start->Type() == PCB_PAD_T ) )
148  {
149  // Start on pad.
150  D_PAD* pad = (D_PAD*) StartTrack->start;
151  startmasklayer |= pad->GetLayerSet();
152  }
153 
154  pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer );
155 
156  if( pt_segm )
157  endmasklayer |= pt_segm->GetLayerSet();
158 
159  if( EndTrack->end && ( EndTrack->end->Type() == PCB_PAD_T ) )
160  {
161  D_PAD* pad = (D_PAD*) EndTrack->end;
162  endmasklayer |= pad->GetLayerSet();
163  }
164 
165  // Mark as deleted a new track (which is not involved in the search for other connections)
166  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, true );
167 
168  /* A segment must be connected to the starting point, otherwise
169  * it is unnecessary to analyze the other point
170  */
171  pt_segm = GetTrack( bufStart, bufEnd, start, startmasklayer );
172 
173  if( pt_segm == NULL ) // Not connected to the track starting point.
174  {
175  // Clear the delete flag.
176  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
177  return 0;
178  }
179 
180  /* Marking a list of candidate segmented connect to endpoint
181  * Note: the vias are not taken into account because they do
182  * not define a track, since they are on an intersection.
183  */
184  for( pt_del = bufStart, nbconnect = 0; ; )
185  {
186  pt_segm = GetTrack( pt_del, bufEnd, end, endmasklayer );
187 
188  if( pt_segm == NULL )
189  break;
190 
191  if( pt_segm->Type() != PCB_VIA_T )
192  {
193  if( pt_segm->GetState( IS_LINKED ) == 0 )
194  {
195  pt_segm->SetState( IS_LINKED, true );
196  nbconnect++;
197  }
198  }
199 
200  if( pt_del == bufEnd )
201  break;
202 
203  pt_del = pt_segm->Next();
204  }
205 
206  if( nbconnect == 0 )
207  {
208  // Clear used flags
209  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
210  {
211  pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
212 
213  if( pt_del == bufEnd ) // Last segment reached
214  break;
215  }
216 
217  return 0;
218  }
219 
220  // Mark trace as edited (which does not involve searching for other tracks)
221  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
222  ListSetState( aNewTrack, aNewTrackSegmentsCount, IN_EDIT, true );
223 
224  // Test all marked segments.
225  while( nbconnect )
226  {
227  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
228  {
229  if( pt_del->GetState( IS_LINKED ) )
230  break;
231 
232  if( pt_del == bufEnd ) // Last segment reached
233  break;
234  }
235 
236  nbconnect--;
237 
238  if( pt_del )
239  pt_del->SetState( IS_LINKED, false );
240 
241  pt_del = GetBoard()->MarkTrace( pt_del, &nb_segm, NULL, NULL, true );
242 
243  /* Test if the marked track is redundant, i.e. if one of marked segments
244  * is connected to the starting point of the new track.
245  */
246  ii = 0;
247  pt_segm = pt_del;
248 
249  for( ; pt_segm && (ii < nb_segm); pt_segm = pt_segm->Next(), ii++ )
250  {
251  if( pt_segm->GetState( BUSY ) == 0 )
252  break;
253 
254  if( pt_segm->GetStart() == start || pt_segm->GetEnd() == start )
255  {
256  // Marked track can be erased.
257  TRACK* NextS;
258 
259  DrawTraces( m_canvas, aDC, pt_del, nb_segm, GR_XOR | GR_HIGHLIGHT );
260 
261  for( jj = 0; jj < nb_segm; jj++, pt_del = NextS )
262  {
263  NextS = pt_del->Next();
264 
265  if( aItemsListPicker )
266  {
267  pt_del->UnLink();
268  pt_del->SetStatus( 0 );
269  pt_del->ClearFlags();
270  ITEM_PICKER picker( pt_del, UR_DELETED );
271  aItemsListPicker->PushItem( picker );
272  }
273  else
274  {
275  pt_del->DeleteStructure();
276  }
277  }
278 
279  // Clean up flags.
280  for( pt_del = m_Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() )
281  {
282  if( pt_del->GetState( IN_EDIT ) )
283  {
284  pt_del->SetState( IN_EDIT, false );
285 
286  if( aDC )
287  pt_del->Draw( m_canvas, aDC, GR_OR );
288  }
289 
290  pt_del->SetState( IN_EDIT | IS_LINKED, false );
291  }
292 
293  return 1;
294  }
295  }
296 
297  // Clear BUSY flag here because the track did not get marked.
298  ListSetState( pt_del, nb_segm, BUSY, false );
299  }
300 
301  // Clear used flags
302  for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() )
303  {
304  pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
305 
306  if( pt_del == bufEnd ) // Last segment reached
307  break;
308  }
309 
310  return 0;
311 }
312 
313 
314 /* Set the bits of .m_State member to on/off value, using bit mask State
315  * of a list of EDA_ITEM
316  */
317 static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
318  bool onoff )
319 {
320  for( ; (Start != NULL ) && ( NbItem > 0 ); NbItem--, Start = Start->Next() )
321  {
322  Start->SetState( State, onoff );
323  }
324 }
#define IS_LINKED
Used in calculation to mark linked items (temporary use)
Definition: base_struct.h:110
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
TRACK * GetTrack(TRACK *aStartTrace, const TRACK *aEndTrace, const wxPoint &aPosition, LSET aLayerMask)
Function GetTrack is a helper function to locate a trace segment having an end point at aPosition on ...
Definition: class_track.cpp:68
#define IN_EDIT
Item currently edited.
Definition: base_struct.h:111
VIA * GetVia(const wxPoint &aPosition, LAYER_ID aLayer=UNDEFINED_LAYER)
Function GetVia finds the first VIA object at aPosition on aLayer starting at the trace...
Class BOARD to handle a board.
int GetEndSegments(int NbSegm, TRACK **StartTrack, TRACK **EndTrack)
Function GetEndSegments get the segments connected to the end point of the track. ...
BOARD * GetBoard() const
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
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:134
EDA_ITEM * Next() const
Definition: base_struct.h:206
virtual void UnLink()
Function UnLink detaches this object from its owner.
int GetState(int type) const
Definition: base_struct.h:237
const wxPoint & GetEnd() const
Definition: class_track.h:117
Functions relatives to tracks, vias and segments used to fill zones.
static void ListSetState(EDA_ITEM *Start, int NbItem, STATUS_FLAGS State, bool onoff)
Definition: tr_modif.cpp:317
Class LSET is a set of LAYER_IDs.
int EraseRedundantTrack(wxDC *aDC, TRACK *aNewTrack, int aNewTrackSegmentsCount, PICKED_ITEMS_LIST *aItemsListPicker)
Function EraseRedundantTrack Called after creating a track Remove (if exists) the old track that have...
Definition: tr_modif.cpp:62
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
#define IS_DELETED
Definition: base_struct.h:116
void DrawTraces(EDA_DRAW_PANEL *panel, wxDC *DC, TRACK *aTrackList, int nbsegment, GR_DRAWMODE draw_mode)
Function DrawTraces Draws n consecutive track segments in list.
Definition: tr_modif.cpp:48
const wxPoint & GetStart() const
Definition: class_track.h:120
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
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
unsigned STATUS_FLAGS
Definition: base_struct.h:144
TRACK * GetEndNetCode(int NetCode)
TRACK * MarkTrace(TRACK *aTrace, int *aCount, double *aTraceLength, double *aInPackageLength, bool aReorder)
Function MarkTrace marks a chain of trace segments, connected to aTrace.
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
Definition: gr_basic.h:42
int GetNetCode() const
Function GetNetCode.
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
#define D(x)
Definition: ptree.cpp:41
TRACK * Next() const
Definition: class_track.h:97
void SetState(int type, int state)
Definition: base_struct.h:242
TRACK * GetStartNetCode(int NetCode)
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
DLIST< TRACK > m_Track
Definition: class_board.h:244
BOARD_CONNECTED_ITEM * end
Definition: class_track.h:89
BOARD_CONNECTED_ITEM * start
Definition: class_track.h:88