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 #include <connectivity_data.h>
44 
45 static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
46  bool onoff );
47 
48 
49 void DrawTraces( EDA_DRAW_PANEL* panel, wxDC* DC, TRACK* aTrackList, int nbsegment,
50  GR_DRAWMODE draw_mode )
51 {
52  // preserve the start of the list for debugging.
53  for( TRACK* track = aTrackList; nbsegment > 0 && track; nbsegment--, track = track->Next() )
54  {
55  track->Draw( panel, DC, draw_mode );
56  }
57 }
58 
59 /*
60  * This function try to remove an old track, when a new track is created,
61  * and the old track is no more needed
62  */
64  TRACK* aNewTrack,
65  int aNewTrackSegmentsCount,
66  PICKED_ITEMS_LIST* aItemsListPicker )
67 {
68  TRACK* StartTrack, * EndTrack;
69  TRACK* pt_segm;
70  TRACK* pt_del;
71  int ii, jj, nb_segm, nbconnect;
72  wxPoint start;
73  wxPoint end;
74  LSET startmasklayer, endmasklayer;
75 
76  int netcode = aNewTrack->GetNetCode();
77 
78  /* Reconstruct the complete track (the new track has to start on a segment of track).
79  */
80  ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, false );
81 
82  /* If the new track begins with a via, complete the track segment using
83  * the following segment as a reference because a via is often a hub of
84  * segments, and does not characterize track.
85  */
86  if( aNewTrack->Type() == PCB_VIA_T && ( aNewTrackSegmentsCount > 1 ) )
87  aNewTrack = aNewTrack->Next();
88 
89  aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
90  wxASSERT( aNewTrack );
91 
92 #if 0 && defined(DEBUG)
93  TRACK* EndNewTrack; // The last segment of the list chained to the track
94 
95  EndNewTrack = aNewTrack;
96 
97  for( ii = 1; ii < aNewTrackSegmentsCount; ii++ )
98  {
99  wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
100  D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
101  EndNewTrack = EndNewTrack->Next();
102  }
103 
104  wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
105  D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
106 
107  for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
108  track->Show( 0, std::cout );
109 
110 #endif
111 
112  TRACK* bufStart = m_Pcb->m_Track->GetStartNetCode( netcode ); // Beginning of tracks of the net
113  TRACK* bufEnd = bufStart->GetEndNetCode( netcode ); // End of tracks of the net
114 
115  // Flags for cleaning the net.
116  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
117  {
118 // D( std::cout<<"track "<<pt_del<<" turning off BUSY | IN_EDIT | IS_LINKED"<<std::endl; )
119  pt_del->SetState( BUSY | IN_EDIT | IS_LINKED, false );
120 
121  if( pt_del == bufEnd ) // Last segment reached
122  break;
123  }
124 
125  if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
126  return 0;
127 
128  if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
129  return 0;
130 
131  start = StartTrack->GetStart();
132  end = EndTrack->GetEnd();
133 
134  // The start and end points cannot be the same.
135  if( start == end )
136  return 0;
137 
138  // Determine layers interconnected these points.
139  startmasklayer = StartTrack->GetLayerSet();
140  endmasklayer = EndTrack->GetLayerSet();
141 
142  // There may be a via or a pad on the end points.
143  pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer );
144 
145  if( pt_segm )
146  startmasklayer |= pt_segm->GetLayerSet();
147 
148  if( StartTrack->start && ( StartTrack->start->Type() == PCB_PAD_T ) )
149  {
150  // Start on pad.
151  D_PAD* pad = (D_PAD*) StartTrack->start;
152  startmasklayer |= pad->GetLayerSet();
153  }
154 
155  pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer );
156 
157  if( pt_segm )
158  endmasklayer |= pt_segm->GetLayerSet();
159 
160  if( EndTrack->end && ( EndTrack->end->Type() == PCB_PAD_T ) )
161  {
162  D_PAD* pad = (D_PAD*) EndTrack->end;
163  endmasklayer |= pad->GetLayerSet();
164  }
165 
166  // Mark as deleted a new track (which is not involved in the search for other connections)
167  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, true );
168 
169  /* A segment must be connected to the starting point, otherwise
170  * it is unnecessary to analyze the other point
171  */
172  pt_segm = GetTrack( bufStart, bufEnd, start, startmasklayer );
173 
174  if( pt_segm == NULL ) // Not connected to the track starting point.
175  {
176  // Clear the delete flag.
177  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
178  return 0;
179  }
180 
181  /* Marking a list of candidate segmented connect to endpoint
182  * Note: the vias are not taken into account because they do
183  * not define a track, since they are on an intersection.
184  */
185  for( pt_del = bufStart, nbconnect = 0; ; )
186  {
187  pt_segm = GetTrack( pt_del, bufEnd, end, endmasklayer );
188 
189  if( pt_segm == NULL )
190  break;
191 
192  if( pt_segm->Type() != PCB_VIA_T )
193  {
194  if( pt_segm->GetState( IS_LINKED ) == 0 )
195  {
196  pt_segm->SetState( IS_LINKED, true );
197  nbconnect++;
198  }
199  }
200 
201  if( pt_del == bufEnd )
202  break;
203 
204  pt_del = pt_segm->Next();
205  }
206 
207  if( nbconnect == 0 )
208  {
209  // Clear used flags
210  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
211  {
212  pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
213 
214  if( pt_del == bufEnd ) // Last segment reached
215  break;
216  }
217 
218  return 0;
219  }
220 
221  // Mark trace as edited (which does not involve searching for other tracks)
222  ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
223  ListSetState( aNewTrack, aNewTrackSegmentsCount, IN_EDIT, true );
224 
225  // Test all marked segments.
226  while( nbconnect )
227  {
228  for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
229  {
230  if( pt_del->GetState( IS_LINKED ) )
231  break;
232 
233  if( pt_del == bufEnd ) // Last segment reached
234  break;
235  }
236 
237  nbconnect--;
238 
239  if( pt_del )
240  pt_del->SetState( IS_LINKED, false );
241 
242  pt_del = GetBoard()->MarkTrace( pt_del, &nb_segm, NULL, NULL, true );
243 
244  /* Test if the marked track is redundant, i.e. if one of marked segments
245  * is connected to the starting point of the new track.
246  */
247  ii = 0;
248  pt_segm = pt_del;
249 
250  for( ; pt_segm && (ii < nb_segm); pt_segm = pt_segm->Next(), ii++ )
251  {
252  if( pt_segm->GetState( BUSY ) == 0 )
253  break;
254 
255  if( pt_segm->GetStart() == start || pt_segm->GetEnd() == start )
256  {
257  // Marked track can be erased.
258  TRACK* NextS;
259 
260  DrawTraces( m_canvas, aDC, pt_del, nb_segm, GR_XOR | GR_HIGHLIGHT );
261 
262  for( jj = 0; jj < nb_segm; jj++, pt_del = NextS )
263  {
264  NextS = pt_del->Next();
265 
266  if( aItemsListPicker )
267  {
268  pt_del->UnLink();
269  pt_del->SetStatus( 0 );
270  pt_del->ClearFlags();
271  GetBoard()->GetConnectivity()->Remove( pt_del );
272  ITEM_PICKER picker( pt_del, UR_DELETED );
273  aItemsListPicker->PushItem( picker );
274  }
275  else
276  {
277  GetBoard()->GetConnectivity()->Remove( pt_del );
278  pt_del->DeleteStructure();
279  }
280  }
281 
282  // Clean up flags.
283  for( pt_del = m_Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() )
284  {
285  if( pt_del->GetState( IN_EDIT ) )
286  {
287  pt_del->SetState( IN_EDIT, false );
288 
289  if( aDC )
290  pt_del->Draw( m_canvas, aDC, GR_OR );
291  }
292 
293  pt_del->SetState( IN_EDIT | IS_LINKED, false );
294  }
295 
296  return 1;
297  }
298  }
299 
300  // Clear BUSY flag here because the track did not get marked.
301  ListSetState( pt_del, nb_segm, BUSY, false );
302  }
303 
304  // Clear used flags
305  for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() )
306  {
307  pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
308 
309  if( pt_del == bufEnd ) // Last segment reached
310  break;
311  }
312 
313  return 0;
314 }
315 
316 
317 /* Set the bits of .m_State member to on/off value, using bit mask State
318  * of a list of EDA_ITEM
319  */
320 static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
321  bool onoff )
322 {
323  for( ; (Start != NULL ) && ( NbItem > 0 ); NbItem--, Start = Start->Next() )
324  {
325  Start->SetState( State, onoff );
326  }
327 }
#define IS_LINKED
Used in calculation to mark linked items (temporary use)
Definition: base_struct.h:124
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
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:125
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:90
#define BUSY
Pcbnew: flag indicating that the structure has.
Definition: base_struct.h:148
EDA_ITEM * Next() const
Definition: base_struct.h:220
virtual void UnLink()
Function UnLink detaches this object from its owner.
int GetState(int type) const
Definition: base_struct.h:251
const wxPoint & GetEnd() const
Definition: class_track.h:120
Functions relatives to tracks, vias and segments used to fill zones.
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...
static void ListSetState(EDA_ITEM *Start, int NbItem, STATUS_FLAGS State, bool onoff)
Definition: tr_modif.cpp:320
Class LSET is a set of PCB_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:63
GR_DRAWMODE
Drawmode. Compositing mode plus a flag or two.
Definition: gr_basic.h:41
#define IS_DELETED
Definition: base_struct.h:130
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:49
const wxPoint & GetStart() const
Definition: class_track.h:123
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:395
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:158
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:93
#define D(x)
Definition: ptree.cpp:41
TRACK * Next() const
Definition: class_track.h:100
void SetState(int type, int state)
Definition: base_struct.h:256
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:165
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
BOARD_CONNECTED_ITEM * end
Definition: class_track.h:92
BOARD_CONNECTED_ITEM * start
Definition: class_track.h:91
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290