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.

274 lines
8.6 KiB

  1. /******************/
  2. /* Trace editing. */
  3. /******************/
  4. #include "fctsys.h"
  5. #include "common.h"
  6. #include "pcbnew.h"
  7. #include "wxPcbStruct.h"
  8. #include "protos.h"
  9. /** function EraseRedundantTrack
  10. * Called after creating a track
  11. * Remove (if exists) the old track that have the same starting and the same
  12. * ending point as the new created track (this is the redunding track)
  13. * @param aDC = the current device context (can be NULL)
  14. * @param aNewTrack = the new created track (a pointer to a segment of the
  15. * track list)
  16. * @param aNewTrackSegmentsCount = number of segments in this new track
  17. * @param aItemsListPicker = the list picker to use for an undo command (can
  18. * be NULL)
  19. */
  20. int WinEDA_PcbFrame::EraseRedundantTrack(
  21. wxDC* aDC,
  22. TRACK* aNewTrack,
  23. int aNewTrackSegmentsCount,
  24. PICKED_ITEMS_LIST* aItemsListPicker )
  25. {
  26. TRACK* StartTrack, * EndTrack;
  27. TRACK* pt_segm;
  28. TRACK* pt_del;
  29. int ii, jj, nb_segm, nbconnect;
  30. wxPoint start;
  31. wxPoint end;
  32. int startmasklayer, endmasklayer;
  33. TRACK* BufDeb, * BufEnd;
  34. int netcode = aNewTrack->GetNet();
  35. /* Reconstruct the complete track (the new track has to start on a
  36. * segment of track).
  37. */
  38. ListSetState( aNewTrack, aNewTrackSegmentsCount, BUSY, OFF );
  39. /* If the new track begins with a via, complete the track segment using
  40. * the following segment as a reference because a via is often a hub of
  41. * segments, and does not characterize track.
  42. */
  43. if( aNewTrack->Type() == TYPE_VIA && ( aNewTrackSegmentsCount > 1 ) )
  44. aNewTrack = aNewTrack->Next();
  45. aNewTrack = Marque_Une_Piste( GetBoard(), aNewTrack,
  46. &aNewTrackSegmentsCount, NULL, true );
  47. wxASSERT( aNewTrack );
  48. #if 0 && defined(DEBUG)
  49. TRACK* EndNewTrack; /* The last segment of the list chained to
  50. * the track */
  51. EndNewTrack = aNewTrack;
  52. for( ii = 1; ii < aNewTrackSegmentsCount; ii++ )
  53. {
  54. wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
  55. D( printf( "track %p is newly part of net %d\n", EndNewTrack,
  56. netcode ); )
  57. EndNewTrack = EndNewTrack->Next();
  58. }
  59. wxASSERT( EndNewTrack->GetState( -1 ) != 0 );
  60. D( printf( "track %p is newly part of net %d\n", EndNewTrack, netcode ); )
  61. for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
  62. track->Show( 0, std::cout );
  63. #endif
  64. /* Calculate search in terms of segments of track, 1st edge BufDeb useful
  65. * segment. */
  66. BufDeb = m_Pcb->m_Track->GetStartNetCode( netcode );
  67. /* Point BufEnd the last segment. */
  68. BufEnd = BufDeb->GetEndNetCode( netcode );
  69. /* Flags for cleaning the net. */
  70. for( pt_del = BufDeb; pt_del; pt_del = pt_del->Next() )
  71. {
  72. D( printf( "track %p turning off BUSY | EDIT | CHAIN\n", pt_del ); )
  73. pt_del->SetState( BUSY | EDIT | CHAIN, OFF );
  74. if( pt_del == BufEnd ) // Last segment reached
  75. break;
  76. }
  77. if( ReturnEndsTrack( aNewTrack, aNewTrackSegmentsCount,
  78. &StartTrack, &EndTrack ) == 0 )
  79. return 0;
  80. if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
  81. return 0;
  82. start = StartTrack->m_Start;
  83. end = EndTrack->m_End;
  84. /* The start and end points cannot be the same. */
  85. if( start == end )
  86. return 0;
  87. /* Determine layers interconnected these points. */
  88. startmasklayer = StartTrack->ReturnMaskLayer();
  89. endmasklayer = EndTrack->ReturnMaskLayer();
  90. /* There may be a via or a pad on the end points. */
  91. pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, start, startmasklayer );
  92. if( pt_segm )
  93. startmasklayer |= pt_segm->ReturnMaskLayer();
  94. if( StartTrack->start && ( StartTrack->start->Type() == TYPE_PAD ) )
  95. {
  96. /* Start on pad. */
  97. D_PAD* pt_pad = (D_PAD*)(StartTrack->start);
  98. startmasklayer |= pt_pad->m_Masque_Layer;
  99. }
  100. pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, end, endmasklayer );
  101. if( pt_segm )
  102. endmasklayer |= pt_segm->ReturnMaskLayer();
  103. if( EndTrack->end && ( EndTrack->end->Type() == TYPE_PAD ) )
  104. {
  105. D_PAD* pt_pad = (D_PAD*)(EndTrack->end);
  106. endmasklayer |= pt_pad->m_Masque_Layer;
  107. }
  108. /* Mark as deleted a new track (which is not involved in the search for
  109. * other connections)
  110. */
  111. ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, ON );
  112. /* A segment must be connected to the starting point, otherwise
  113. * it is unnecessary to analyze the other point
  114. */
  115. pt_segm = Fast_Locate_Piste( BufDeb, BufEnd, start, startmasklayer );
  116. if( pt_segm == NULL ) /* Not connected to the track starting point. */
  117. {
  118. /* Clear the delete flag. */
  119. ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, OFF );
  120. return 0;
  121. }
  122. /* Marking a list of candidate segmented connect to endpoint
  123. * Note: the vias are not taken into account because they do
  124. * not define a track, since they are on an intersection.
  125. */
  126. for( pt_del = BufDeb, nbconnect = 0; ; )
  127. {
  128. pt_segm = Fast_Locate_Piste( pt_del, BufEnd, end, endmasklayer );
  129. if( pt_segm == NULL )
  130. break;
  131. if( pt_segm->Type() != TYPE_VIA )
  132. {
  133. if( pt_segm->GetState( CHAIN ) == 0 )
  134. {
  135. pt_segm->SetState( CHAIN, ON );
  136. nbconnect++;
  137. }
  138. }
  139. if( pt_del == BufEnd )
  140. break;
  141. pt_del = pt_segm->Next();
  142. }
  143. if( nbconnect == 0 )
  144. {
  145. /* Clear used flags */
  146. for( pt_del = BufDeb; pt_del; pt_del = pt_del->Next() )
  147. {
  148. pt_del->SetState( BUSY | DELETED | EDIT | CHAIN, OFF );
  149. if( pt_del == BufEnd ) // Last segment reached
  150. break;
  151. }
  152. return 0;
  153. }
  154. /* Mark trace as edited (which does not involve searching for other
  155. * tracks)
  156. */
  157. ListSetState( aNewTrack, aNewTrackSegmentsCount, DELETED, OFF );
  158. ListSetState( aNewTrack, aNewTrackSegmentsCount, EDIT, ON );
  159. /* Test all marked segments. */
  160. while( nbconnect )
  161. {
  162. for( pt_del = BufDeb; pt_del; pt_del = pt_del->Next() )
  163. {
  164. if( pt_del->GetState( CHAIN ) )
  165. break;
  166. if( pt_del == BufEnd ) // Last segment reached
  167. break;
  168. }
  169. nbconnect--;
  170. pt_del->SetState( CHAIN, OFF );
  171. pt_del = Marque_Une_Piste( GetBoard(), pt_del, &nb_segm, NULL, true );
  172. /* Test if the marked track is redundant, ie if one of marked segments
  173. * is connected to the starting point of the new track.
  174. */
  175. ii = 0;
  176. pt_segm = pt_del;
  177. for( ; pt_segm && (ii < nb_segm); pt_segm = pt_segm->Next(), ii++ )
  178. {
  179. if( pt_segm->GetState( BUSY ) == 0 )
  180. break;
  181. if( pt_segm->m_Start == start || pt_segm->m_End == start )
  182. {
  183. /* Marked track can be erased. */
  184. TRACK* NextS;
  185. Trace_Une_Piste( DrawPanel, aDC, pt_del, nb_segm,
  186. GR_XOR | GR_SURBRILL );
  187. for( jj = 0; jj < nb_segm; jj++, pt_del = NextS )
  188. {
  189. NextS = pt_del->Next();
  190. if( aItemsListPicker )
  191. {
  192. pt_del->UnLink();
  193. pt_del->SetStatus( 0 );
  194. pt_del->m_Flags = 0;
  195. ITEM_PICKER picker( pt_del, UR_DELETED );
  196. aItemsListPicker->PushItem( picker );
  197. }
  198. else
  199. pt_del->DeleteStructure();
  200. }
  201. /* Clean up flags. */
  202. for( pt_del = m_Pcb->m_Track; pt_del != NULL;
  203. pt_del = pt_del->Next() )
  204. {
  205. if( pt_del->GetState( EDIT ) )
  206. {
  207. pt_del->SetState( EDIT, OFF );
  208. if( aDC )
  209. pt_del->Draw( DrawPanel, aDC, GR_OR );
  210. }
  211. pt_del->SetState( EDIT | CHAIN, OFF );
  212. }
  213. return 1;
  214. }
  215. }
  216. /* Clear BUSY flag here because the track did not get marked.
  217. */
  218. ListSetState( pt_del, nb_segm, BUSY, OFF );
  219. }
  220. /* Clear used flags */
  221. for( pt_del = m_Pcb->m_Track; pt_del; pt_del = pt_del->Next() )
  222. {
  223. pt_del->SetState( BUSY | DELETED | EDIT | CHAIN, OFF );
  224. if( pt_del == BufEnd ) // Last segment reached
  225. break;
  226. }
  227. return 0;
  228. }