You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

511 lines
16 KiB

8 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
19 years ago
18 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015 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-2015 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. /**
  27. * @file editrack-part2.cpp
  28. */
  29. #include <fctsys.h>
  30. #include <gr_basic.h>
  31. #include <class_drawpanel.h>
  32. #include <confirm.h>
  33. #include <pcb_edit_frame.h>
  34. #include <class_board.h>
  35. #include <class_module.h>
  36. #include <class_track.h>
  37. #include <class_marker_pcb.h>
  38. #include <pcbnew.h>
  39. #include <drc.h>
  40. #include <connectivity_data.h>
  41. bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC )
  42. {
  43. unsigned itmp;
  44. if( aTrack == NULL )
  45. {
  46. if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP )
  47. SetActiveLayer( GetScreen()->m_Route_Layer_TOP );
  48. else
  49. SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM );
  50. UpdateStatusBar();
  51. return true;
  52. }
  53. // Avoid more than one via on the current location:
  54. if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(),
  55. g_CurrentTrackSegment->GetLayer() ) )
  56. return false;
  57. for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() )
  58. {
  59. if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() )
  60. return false;
  61. }
  62. // Is the current segment Ok (no DRC error) ?
  63. if( Settings().m_legacyDrcOn )
  64. {
  65. if( BAD_DRC==m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment, GetBoard()->m_Track ) )
  66. // DRC error, the change layer is not made
  67. return false;
  68. // Handle 2 segments.
  69. if( Settings().m_legacyUseTwoSegmentTracks && g_CurrentTrackSegment->Back() )
  70. {
  71. if( BAD_DRC == m_drc->DrcOnCreatingTrack( g_CurrentTrackSegment->Back(),
  72. GetBoard()->m_Track ) )
  73. return false;
  74. }
  75. }
  76. /* Save current state before placing a via.
  77. * If the via cannot be placed this current state will be reused
  78. */
  79. itmp = g_CurrentTrackList.GetCount();
  80. Begin_Route( g_CurrentTrackSegment, DC );
  81. m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
  82. // create the via
  83. VIA* via = new VIA( GetBoard() );
  84. via->SetFlags( IS_NEW );
  85. via->SetViaType( GetDesignSettings().m_CurrentViaType );
  86. via->SetNetCode( GetBoard()->GetHighLightNetCode() );
  87. via->SetPosition( g_CurrentTrackSegment->GetEnd() );
  88. // for microvias, the size and hole will be changed later.
  89. via->SetWidth( GetDesignSettings().GetCurrentViaSize());
  90. via->SetDrill( GetDesignSettings().GetCurrentViaDrill() );
  91. // Usual via is from copper to component.
  92. // layer pair is B_Cu and F_Cu.
  93. via->SetLayerPair( B_Cu, F_Cu );
  94. PCB_LAYER_ID first_layer = GetActiveLayer();
  95. PCB_LAYER_ID last_layer;
  96. // prepare switch to new active layer:
  97. if( first_layer != GetScreen()->m_Route_Layer_TOP )
  98. last_layer = GetScreen()->m_Route_Layer_TOP;
  99. else
  100. last_layer = GetScreen()->m_Route_Layer_BOTTOM;
  101. // Adjust the actual via layer pair
  102. switch( via->GetViaType() )
  103. {
  104. case VIA_BLIND_BURIED:
  105. via->SetLayerPair( first_layer, last_layer );
  106. break;
  107. case VIA_MICROVIA: // from external to the near neighbor inner layer
  108. {
  109. PCB_LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) );
  110. if( first_layer == B_Cu )
  111. last_layer = last_inner_layer;
  112. else if( first_layer == F_Cu )
  113. last_layer = In1_Cu;
  114. else if( first_layer == last_inner_layer )
  115. last_layer = B_Cu;
  116. else if( first_layer == In1_Cu )
  117. last_layer = F_Cu;
  118. // else error: will be removed later
  119. via->SetLayerPair( first_layer, last_layer );
  120. // Update diameter and hole size, which where set previously
  121. // for normal vias
  122. NETINFO_ITEM* net = via->GetNet();
  123. via->SetWidth( net->GetMicroViaSize() );
  124. via->SetDrill( net->GetMicroViaDrillSize() );
  125. }
  126. break;
  127. default:
  128. break;
  129. }
  130. if( Settings().m_legacyDrcOn &&
  131. BAD_DRC == m_drc->DrcOnCreatingTrack( via, GetBoard()->m_Track ) )
  132. {
  133. // DRC fault: the Via cannot be placed here ...
  134. delete via;
  135. m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
  136. // delete the track(s) added in Begin_Route()
  137. while( g_CurrentTrackList.GetCount() > itmp )
  138. {
  139. Delete_Segment( DC, g_CurrentTrackSegment );
  140. }
  141. SetCurItem( g_CurrentTrackSegment, false );
  142. // Refresh DRC diag, erased by previous calls
  143. if( m_drc->GetCurrentMarker() )
  144. SetMsgPanel( m_drc->GetCurrentMarker() );
  145. return false;
  146. }
  147. SetActiveLayer( last_layer );
  148. TRACK* lastNonVia = g_CurrentTrackSegment;
  149. /* A new via was created. It was Ok.
  150. */
  151. g_CurrentTrackList.PushBack( via );
  152. /* The via is now in linked list and we need a new track segment
  153. * after the via, starting at via location.
  154. * it will become the new current segment (from via to the mouse cursor)
  155. */
  156. TRACK* track = (TRACK*)lastNonVia->Clone();
  157. /* the above creates a new segment from the last entered segment, with the
  158. * current width, flags, netcode, etc... values.
  159. * layer, start and end point are not correct,
  160. * and will be modified next
  161. */
  162. // set the layer to the new value
  163. track->SetLayer( GetActiveLayer() );
  164. /* the start point is the via position and the end point is the cursor
  165. * which also is on the via (will change when moving mouse)
  166. */
  167. track->SetEnd( via->GetStart() );
  168. track->SetStart( via->GetStart() );
  169. g_CurrentTrackList.PushBack( track );
  170. if( Settings().m_legacyUseTwoSegmentTracks )
  171. {
  172. // Create a second segment (we must have 2 track segments to adjust)
  173. g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() );
  174. }
  175. m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
  176. SetMsgPanel( via );
  177. UpdateStatusBar();
  178. return true;
  179. }
  180. static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
  181. bool onoff );
  182. void DrawTraces( EDA_DRAW_PANEL* panel, wxDC* DC, TRACK* aTrackList, int nbsegment,
  183. GR_DRAWMODE draw_mode )
  184. {
  185. // preserve the start of the list for debugging.
  186. for( TRACK* track = aTrackList; nbsegment > 0 && track; nbsegment--, track = track->Next() )
  187. {
  188. track->Draw( panel, DC, draw_mode );
  189. }
  190. }
  191. /*
  192. * This function try to remove an old track, when a new track is created,
  193. * and the old track is no more needed
  194. */
  195. int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
  196. TRACK* aNewTrack,
  197. int aNewTrackSegmentsCount,
  198. PICKED_ITEMS_LIST* aItemsListPicker )
  199. {
  200. TRACK* StartTrack, * EndTrack;
  201. TRACK* pt_segm;
  202. TRACK* pt_del;
  203. int nb_segm, nbconnect;
  204. wxPoint start;
  205. wxPoint end;
  206. LSET startmasklayer, endmasklayer;
  207. int netcode = aNewTrack->GetNetCode();
  208. // Reconstruct the complete track (the new track has to start on a segment of track).
  209. // Note: aNewTrackSegmentsCount conatins the number of new track segments
  210. ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, false );
  211. /* If the new track begins with a via, complete the track segment using
  212. * the following segment as a reference because a via is often a hub of
  213. * segments, and does not characterize track.
  214. */
  215. if( aNewTrack->Type() == PCB_VIA_T && ( aNewTrackSegmentsCount > 1 ) )
  216. aNewTrack = aNewTrack->Next();
  217. // When MarkTrace try to find the entire track, if the starting segment
  218. // is fully inside a pad, MarkTrace does not find correctly the full trace,
  219. // because the entire track is the set of segments between 2 nodes
  220. // (pads or point connecting more than 2 items)
  221. // so use another (better) starting segment in this case
  222. TRACK* track_segment = aNewTrack;
  223. for( int ii = 0; ii < aNewTrackSegmentsCount; ii++ )
  224. {
  225. D_PAD* pad_st = m_Pcb->GetPad( aNewTrack->GetStart() );
  226. D_PAD* pad_end = m_Pcb->GetPad( aNewTrack->GetEnd() );
  227. if( pad_st && pad_st == pad_end )
  228. track_segment = aNewTrack->Next();
  229. else
  230. break;
  231. }
  232. // Mark the full trace containing track_segment, and recalculate the
  233. // beginning of the trace, and the number of segments, as the new trace
  234. // can contain also already existing track segments
  235. aNewTrack = GetBoard()->MarkTrace( GetBoard()->m_Track, track_segment,
  236. &aNewTrackSegmentsCount,
  237. nullptr, nullptr, true );
  238. wxASSERT( aNewTrack );
  239. TRACK* bufStart = m_Pcb->m_Track->GetStartNetCode( netcode ); // Beginning of tracks of the net
  240. TRACK* bufEnd = bufStart->GetEndNetCode( netcode ); // End of tracks of the net
  241. // Flags for cleaning the net.
  242. for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
  243. {
  244. // printf( "track %p turning off BUSY | IN_EDIT | IS_LINKED\n", pt_del );
  245. pt_del->SetState( BUSY | IN_EDIT | IS_LINKED, false );
  246. if( pt_del == bufEnd ) // Last segment reached
  247. break;
  248. }
  249. if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
  250. return 0;
  251. if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
  252. return 0;
  253. start = StartTrack->GetStart();
  254. end = EndTrack->GetEnd();
  255. // The start and end points cannot be the same.
  256. if( start == end )
  257. return 0;
  258. // Determine layers interconnected these points.
  259. startmasklayer = StartTrack->GetLayerSet();
  260. endmasklayer = EndTrack->GetLayerSet();
  261. // There may be a via or a pad on the end points.
  262. pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer );
  263. if( pt_segm )
  264. startmasklayer |= pt_segm->GetLayerSet();
  265. if( StartTrack->start && ( StartTrack->start->Type() == PCB_PAD_T ) )
  266. {
  267. // Start on pad.
  268. D_PAD* pad = (D_PAD*) StartTrack->start;
  269. startmasklayer |= pad->GetLayerSet();
  270. }
  271. pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer );
  272. if( pt_segm )
  273. endmasklayer |= pt_segm->GetLayerSet();
  274. if( EndTrack->end && ( EndTrack->end->Type() == PCB_PAD_T ) )
  275. {
  276. D_PAD* pad = (D_PAD*) EndTrack->end;
  277. endmasklayer |= pad->GetLayerSet();
  278. }
  279. // Mark as deleted a new track (which is not involved in the search for other connections)
  280. ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, true );
  281. /* A segment must be connected to the starting point, otherwise
  282. * it is unnecessary to analyze the other point
  283. */
  284. pt_segm = GetTrack( bufStart, bufEnd, start, startmasklayer );
  285. if( pt_segm == NULL ) // Not connected to the track starting point.
  286. {
  287. // Clear the delete flag.
  288. ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
  289. return 0;
  290. }
  291. /* Marking a list of candidate segmented connect to endpoint
  292. * Note: the vias are not taken into account because they do
  293. * not define a track, since they are on an intersection.
  294. */
  295. for( pt_del = bufStart, nbconnect = 0; ; )
  296. {
  297. pt_segm = GetTrack( pt_del, bufEnd, end, endmasklayer );
  298. if( pt_segm == NULL )
  299. break;
  300. if( pt_segm->Type() != PCB_VIA_T )
  301. {
  302. if( pt_segm->GetState( IS_LINKED ) == 0 )
  303. {
  304. pt_segm->SetState( IS_LINKED, true );
  305. nbconnect++;
  306. }
  307. }
  308. if( pt_del == bufEnd )
  309. break;
  310. pt_del = pt_segm->Next();
  311. }
  312. if( nbconnect == 0 )
  313. {
  314. // Clear used flags
  315. for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
  316. {
  317. pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
  318. if( pt_del == bufEnd ) // Last segment reached
  319. break;
  320. }
  321. return 0;
  322. }
  323. // Mark trace as edited (which does not involve searching for other tracks)
  324. ListSetState( aNewTrack, aNewTrackSegmentsCount, IS_DELETED, false );
  325. ListSetState( aNewTrack, aNewTrackSegmentsCount, IN_EDIT, true );
  326. // Test all marked segments.
  327. while( nbconnect )
  328. {
  329. for( pt_del = bufStart; pt_del; pt_del = pt_del->Next() )
  330. {
  331. if( pt_del->GetState( IS_LINKED ) )
  332. break;
  333. if( pt_del == bufEnd ) // Last segment reached
  334. break;
  335. }
  336. nbconnect--;
  337. if( pt_del )
  338. pt_del->SetState( IS_LINKED, false );
  339. pt_del = GetBoard()->MarkTrace( GetBoard()->m_Track, pt_del, &nb_segm,
  340. NULL, NULL, true );
  341. /* Test if the marked track is redundant, i.e. if one of marked segments
  342. * is connected to the starting point of the new track.
  343. */
  344. pt_segm = pt_del;
  345. for( int ii = 0; pt_segm && (ii < nb_segm); pt_segm = pt_segm->Next(), ii++ )
  346. {
  347. if( pt_segm->GetState( BUSY ) == 0 )
  348. break;
  349. if( pt_segm->GetStart() == start || pt_segm->GetEnd() == start )
  350. {
  351. // Marked track can be erased.
  352. TRACK* NextS;
  353. DrawTraces( m_canvas, aDC, pt_del, nb_segm, GR_XOR | GR_HIGHLIGHT );
  354. for( int jj = 0; jj < nb_segm; jj++, pt_del = NextS )
  355. {
  356. NextS = pt_del->Next();
  357. if( aItemsListPicker )
  358. {
  359. pt_del->UnLink();
  360. pt_del->SetStatus( 0 );
  361. pt_del->ClearFlags();
  362. GetBoard()->GetConnectivity()->Remove( pt_del );
  363. ITEM_PICKER picker( pt_del, UR_DELETED );
  364. aItemsListPicker->PushItem( picker );
  365. }
  366. else
  367. {
  368. GetBoard()->GetConnectivity()->Remove( pt_del );
  369. pt_del->DeleteStructure();
  370. }
  371. }
  372. // Clean up flags.
  373. for( pt_del = m_Pcb->m_Track; pt_del != NULL; pt_del = pt_del->Next() )
  374. {
  375. if( pt_del->GetState( IN_EDIT ) )
  376. {
  377. pt_del->SetState( IN_EDIT, false );
  378. if( aDC )
  379. pt_del->Draw( m_canvas, aDC, GR_OR );
  380. }
  381. pt_del->SetState( IN_EDIT | IS_LINKED, false );
  382. }
  383. return 1;
  384. }
  385. }
  386. // Clear BUSY flag here because the track did not get marked.
  387. ListSetState( pt_del, nb_segm, BUSY, false );
  388. }
  389. // Clear used flags
  390. for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() )
  391. {
  392. pt_del->SetState( BUSY | IS_DELETED | IN_EDIT | IS_LINKED, false );
  393. if( pt_del == bufEnd ) // Last segment reached
  394. break;
  395. }
  396. return 0;
  397. }
  398. /* Set the bits of .m_State member to on/off value, using bit mask State
  399. * of a list of EDA_ITEM
  400. */
  401. static void ListSetState( EDA_ITEM* Start, int NbItem, STATUS_FLAGS State,
  402. bool onoff )
  403. {
  404. for( ; (Start != NULL ) && ( NbItem > 0 ); NbItem--, Start = Start->Next() )
  405. {
  406. Start->SetState( State, onoff );
  407. }
  408. }