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.

953 lines
29 KiB

  1. /****************************************************/
  2. /* Track editing */
  3. /* routines to move and drag track segments or node */
  4. /****************************************************/
  5. #include "fctsys.h"
  6. #include "gr_basic.h"
  7. #include "common.h"
  8. #include "pcbnew.h"
  9. #include "autorout.h"
  10. #include "trigo.h"
  11. #include "drag.h"
  12. #include "id.h"
  13. #include "protos.h"
  14. /* local functions */
  15. static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
  16. static void Show_Drag_Track_Segment_With_Cte_Slope( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
  17. static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC );
  18. static bool InitialiseDragParameters();
  19. /* variables locales */
  20. static wxPoint PosInit, s_LastPos;
  21. static TRACK* NewTrack; /* Nouvelle piste creee ou piste deplacee */
  22. static int NbPtNewTrack;
  23. static int Old_HightLigth_NetCode;
  24. static bool Old_HightLigt_Status;
  25. static double s_StartSegmentSlope, s_EndSegmentSlope, s_MovingSegmentSlope,
  26. s_StartSegment_Yorg, s_EndSegment_Yorg,
  27. s_MovingSegment_Yorg; //slope and intercept parameters of lines
  28. bool s_StartPointVertical, s_EndPointVertical,
  29. s_MovingSegmentVertical, s_MovingSegmentHorizontal,
  30. s_StartPointHorizontal, s_EndPointHorizontal; // vertical or horizontal line indicators
  31. bool s_StartSegmentPresent, s_EndSegmentPresent;
  32. /**************************************************************/
  33. static void Abort_MoveTrack( WinEDA_DrawPanel* Panel, wxDC* DC )
  34. /***************************************************************/
  35. /* routine d'annulation de la commande drag, copy ou move track si une piste est en cours
  36. * de tracage, ou de sortie de l'application EDITRACK.
  37. */
  38. {
  39. TRACK* NextS;
  40. int ii;
  41. /* Erase the current drawings */
  42. wxPoint oldpos = Panel->GetScreen()->m_Curseur;
  43. Panel->GetScreen()->m_Curseur = PosInit;
  44. if( Panel->ManageCurseur )
  45. Panel->ManageCurseur( Panel, DC, TRUE );
  46. Panel->GetScreen()->m_Curseur = oldpos;
  47. g_HightLigt_Status = FALSE;
  48. ( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
  49. if( NewTrack )
  50. {
  51. if( NewTrack->m_Flags & IS_NEW )
  52. {
  53. for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS )
  54. {
  55. if( NewTrack == NULL )
  56. break;
  57. NextS = (TRACK*) NewTrack->Pnext;
  58. delete NewTrack;
  59. }
  60. }
  61. else /* Move : remise en ancienne position */
  62. {
  63. TRACK* Track = NewTrack;
  64. int dx = s_LastPos.x - PosInit.x;
  65. int dy = s_LastPos.y - PosInit.y;
  66. for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
  67. {
  68. if( Track == NULL )
  69. break;
  70. Track->m_Start.x -= dx;
  71. Track->m_Start.y -= dy;
  72. Track->m_End.x -= dx;
  73. Track->m_End.y -= dy;
  74. Track->m_Flags = 0;
  75. }
  76. Trace_Une_Piste( Panel, DC, NewTrack, NbPtNewTrack, GR_OR );
  77. }
  78. NewTrack = NULL;
  79. }
  80. Panel->ManageCurseur = NULL;
  81. Panel->ForceCloseManageCurseur = NULL;
  82. ((WinEDA_PcbFrame*)Panel->m_Parent)->SetCurItem(NULL);
  83. /* Annulation deplacement et Redessin des segments dragges */
  84. DRAG_SEGM* pt_drag = g_DragSegmentList;
  85. for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
  86. {
  87. TRACK* Track = pt_drag->m_Segm;
  88. pt_drag->SetInitialValues();
  89. Track->SetState( EDIT, OFF );
  90. Track->m_Flags = 0;
  91. Track->Draw( Panel, DC, GR_OR );
  92. }
  93. g_HightLigth_NetCode = Old_HightLigth_NetCode;
  94. g_HightLigt_Status = Old_HightLigt_Status;
  95. if( g_HightLigt_Status )
  96. ( (WinEDA_PcbFrame*) Panel->m_Parent )->DrawHightLight( DC, g_HightLigth_NetCode );
  97. EraseDragListe();
  98. }
  99. /*************************************************************************/
  100. static void Show_MoveNode( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
  101. /*************************************************************************/
  102. /* Redraw the moved node according to the mouse cursor position */
  103. {
  104. int ii, dx, dy;
  105. TRACK* Track;
  106. BASE_SCREEN* screen = panel->GetScreen();
  107. int track_fill_copy = DisplayOpt.DisplayPcbTrackFill;
  108. int draw_mode = GR_XOR | GR_SURBRILL;
  109. DisplayOpt.DisplayPcbTrackFill = FALSE;
  110. erase = TRUE;
  111. /* erase the current moved track segments from screen */
  112. if( erase )
  113. {
  114. if( NewTrack )
  115. Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, draw_mode );
  116. }
  117. /* set the new track coordinates */
  118. wxPoint Pos = screen->m_Curseur;
  119. dx = Pos.x - s_LastPos.x;
  120. dy = Pos.y - s_LastPos.y;
  121. s_LastPos = Pos;
  122. ii = NbPtNewTrack, Track = NewTrack;
  123. for( ; (ii > 0) && (Track != NULL); ii--, Track = Track->Next() )
  124. {
  125. if( Track->m_Flags & STARTPOINT )
  126. {
  127. Track->m_Start.x += dx; Track->m_Start.y += dy;
  128. }
  129. if( Track->m_Flags & ENDPOINT )
  130. {
  131. Track->m_End.x += dx; Track->m_End.y += dy;
  132. }
  133. }
  134. /* Redraw the current moved track segments */
  135. Trace_Une_Piste( panel, DC, NewTrack, NbPtNewTrack, GR_XOR );
  136. DRAG_SEGM* pt_drag = g_DragSegmentList;
  137. for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
  138. {
  139. Track = pt_drag->m_Segm;
  140. if( erase )
  141. Track->Draw( panel, DC, draw_mode );
  142. if( Track->m_Flags & STARTPOINT )
  143. {
  144. Track->m_Start.x += dx; Track->m_Start.y += dy;
  145. }
  146. if( Track->m_Flags & ENDPOINT )
  147. {
  148. Track->m_End.x += dx; Track->m_End.y += dy;
  149. }
  150. Track->Draw( panel, DC, draw_mode );
  151. }
  152. DisplayOpt.DisplayPcbTrackFill = track_fill_copy;
  153. }
  154. /*************************************************************************/
  155. static void Show_Drag_Track_Segment_With_Cte_Slope( WinEDA_DrawPanel* panel,
  156. wxDC* DC, bool erase )
  157. /*************************************************************************/
  158. /* drawing the track segment movement
  159. * > s_MovingSegmentSlope slope = moving track segment slope
  160. * > s_StartSegmentSlope slope = slope of the segment connected to the start point of the moving segment
  161. * > s_EndSegmentSlope slope = slope of the segment connected to the end point of the moving segment
  162. *
  163. * moved segment function :
  164. * yt=s_MovingSegmentSlope * x + s_MovingSegment_Yorg
  165. *
  166. * segment connected to moved segment's start:
  167. * y1 = s_StartSegmentSlope * x + s_StartSegment_Yorg
  168. *
  169. * segment connected to moved segment's end:
  170. * y2=s_EndSegmentSlope * x + s_EndSegment_Yorg
  171. *
  172. * first intersection point will be located at
  173. * y1=yt ->
  174. * xi1=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_StartSegmentSlope-s_MovingSegmentSlope)
  175. * yi1=s_MovingSegmentSlope*xi1+s_MovingSegment_Yorg
  176. * or yi1=s_StartSegmentSlope*xi1+s_MovingSegment_Yorg
  177. *
  178. * second intersection point
  179. * y2=yt ->
  180. * xi2=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_MovingSegmentSlope-s_MovingSegmentSlope)
  181. * yi2=s_MovingSegmentSlope*xi2+s_MovingSegment_Yorg
  182. * or yi1=s_EndSegmentSlope*xi2+s_MovingSegment_Yorg
  183. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  184. * !!!!! special attention to vertical segments because
  185. * !!!!! their slope=infinite
  186. * !!!!! intersection point will be calculated using the
  187. * !!!!! segment intersecting it
  188. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  189. *
  190. * Slope parametres are computed once, because they can become undetermined when moving segments
  191. * (i.e. when a segment lenght is 0) and we want keep them constant
  192. */
  193. {
  194. double xi1 = 0, yi1 = 0, xi2 = 0, yi2 = 0; // calculated intersection points
  195. double tx1, tx2, ty1, ty2; // temporary storage of points
  196. int dx, dy;
  197. BASE_SCREEN* screen = panel->GetScreen();
  198. bool update = true;
  199. TRACK* Track;
  200. DRAG_SEGM* TrackSegWrapper = g_DragSegmentList;
  201. TRACK* tSegmentToStart = NULL, * tSegmentToEnd = NULL;
  202. if( TrackSegWrapper == NULL )
  203. return;
  204. Track = TrackSegWrapper->m_Segm; if( Track == NULL )
  205. return;
  206. TrackSegWrapper = TrackSegWrapper->Pnext;
  207. if( TrackSegWrapper )
  208. {
  209. if( s_EndSegmentPresent )
  210. {
  211. tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
  212. TrackSegWrapper = TrackSegWrapper->Pnext;
  213. }
  214. if( s_StartSegmentPresent )
  215. {
  216. if( TrackSegWrapper )
  217. tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
  218. }
  219. }
  220. int draw_mode = GR_XOR | GR_SURBRILL;
  221. /* Undraw the current moved track segments before modification*/
  222. // if( erase )
  223. {
  224. Track->Draw( panel, DC, draw_mode );
  225. if( tSegmentToStart )
  226. tSegmentToStart->Draw( panel, DC, draw_mode );
  227. if( tSegmentToEnd )
  228. tSegmentToEnd->Draw( panel, DC, draw_mode );
  229. }
  230. /* Compute the new track segment position */
  231. wxPoint Pos = screen->m_Curseur;
  232. dx = Pos.x - s_LastPos.x;
  233. dy = Pos.y - s_LastPos.y;
  234. //move the line by dx and dy
  235. tx1 = (double) (Track->m_Start.x + dx);
  236. ty1 = (double) (Track->m_Start.y + dy);
  237. tx2 = (double) (Track->m_End.x + dx);
  238. ty2 = (double) (Track->m_End.y + dy);
  239. // recalculate the segments new parameters and intersection points
  240. // only the intercept will change, segment slopes does not change
  241. // because we are moving parallel with is initial state
  242. if( !s_MovingSegmentVertical )
  243. {
  244. s_MovingSegment_Yorg = ty1 - (s_MovingSegmentSlope * tx1);
  245. }
  246. if( (!s_EndPointVertical) && (!s_MovingSegmentVertical) )
  247. {
  248. xi2 = (s_MovingSegment_Yorg -
  249. s_EndSegment_Yorg) / (s_EndSegmentSlope - s_MovingSegmentSlope);
  250. }
  251. else
  252. {
  253. if( !s_EndPointVertical )
  254. {
  255. xi2 = tx2;
  256. }
  257. else
  258. {
  259. //P1=P2
  260. if( !s_EndPointHorizontal )
  261. {
  262. xi2 = tx2 - dx;
  263. }
  264. else
  265. {
  266. update = false;
  267. }
  268. }
  269. }
  270. if( !s_MovingSegmentVertical )
  271. {
  272. yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
  273. }
  274. else
  275. {
  276. if( !s_EndPointVertical )
  277. {
  278. yi2 = s_EndSegmentSlope * (xi2) + s_EndSegment_Yorg;
  279. }
  280. else
  281. {
  282. if( !s_EndPointHorizontal )
  283. {
  284. update = false;
  285. }
  286. else
  287. {
  288. yi2 = s_MovingSegmentSlope * (xi2) + s_MovingSegment_Yorg;
  289. }
  290. }
  291. }
  292. if( (!s_StartPointVertical) && (!s_MovingSegmentVertical) )
  293. {
  294. xi1 = (s_MovingSegment_Yorg -
  295. s_StartSegment_Yorg) / (s_StartSegmentSlope - s_MovingSegmentSlope);
  296. }
  297. else
  298. {
  299. if( !s_StartPointVertical )
  300. {
  301. xi1 = tx1;
  302. }
  303. else
  304. {
  305. //P1=P2
  306. if( !s_StartPointHorizontal )
  307. {
  308. xi1 = tx1 - dx;
  309. }
  310. else
  311. {
  312. if( !s_StartPointHorizontal )
  313. {
  314. update = false;
  315. }
  316. }
  317. }
  318. }
  319. if( !s_MovingSegmentVertical )
  320. {
  321. yi1 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
  322. }
  323. else
  324. {
  325. if( !s_StartPointVertical )
  326. {
  327. yi1 = s_StartSegmentSlope * (xi1) + s_StartSegment_Yorg;
  328. }
  329. else
  330. {
  331. if( !s_StartPointHorizontal )
  332. {
  333. update = false;
  334. }
  335. else
  336. {
  337. yi2 = s_MovingSegmentSlope * (xi1) + s_MovingSegment_Yorg;
  338. }
  339. }
  340. }
  341. // update the segment coordinates (if possible)
  342. if( tSegmentToStart == NULL )
  343. {
  344. xi1 = tx1; yi1 = ty1;
  345. }
  346. if( tSegmentToEnd == NULL )
  347. {
  348. xi2 = tx2; yi2 = ty2;
  349. }
  350. if( update )
  351. {
  352. s_LastPos = Pos;
  353. Track->m_Start.x = (int) round( xi1 );
  354. Track->m_Start.y = (int) round( yi1 );
  355. Track->m_End.x = (int) round( xi2 );
  356. Track->m_End.y = (int) round( yi2 );
  357. if( tSegmentToEnd )
  358. {
  359. if( tSegmentToEnd->m_Flags & STARTPOINT )
  360. tSegmentToEnd->m_Start = Track->m_End;
  361. else
  362. tSegmentToEnd->m_End = Track->m_End;
  363. }
  364. if( tSegmentToStart )
  365. {
  366. if( tSegmentToStart->m_Flags & STARTPOINT )
  367. tSegmentToStart->m_Start = Track->m_Start;
  368. else
  369. tSegmentToStart->m_End = Track->m_Start;
  370. }
  371. }
  372. Track->Draw( panel, DC, draw_mode );
  373. if( tSegmentToStart )
  374. tSegmentToStart->Draw( panel, DC, draw_mode );
  375. if( tSegmentToEnd )
  376. tSegmentToEnd->Draw( panel, DC, draw_mode );
  377. }
  378. /**********************************/
  379. bool InitialiseDragParameters()
  380. /**********************************/
  381. /* Init variables (slope, Y intersect point, flags) for Show_Drag_Track_Segment_With_Cte_Slope()
  382. * return TRUE if Ok, FALSE if dragging is not possible
  383. * (2 colinear segments)
  384. */
  385. {
  386. double tx1, tx2, ty1, ty2; // temporary storage of points
  387. TRACK* Track;
  388. DRAG_SEGM* TrackSegWrapper = g_DragSegmentList;
  389. TRACK* tSegmentToStart = NULL, * tSegmentToEnd = NULL;
  390. if( TrackSegWrapper == NULL )
  391. return FALSE;
  392. Track = TrackSegWrapper->m_Segm;
  393. if( Track == NULL )
  394. return FALSE;
  395. TrackSegWrapper = TrackSegWrapper->Pnext;
  396. if( TrackSegWrapper )
  397. {
  398. if( s_EndSegmentPresent )
  399. {
  400. tSegmentToEnd = TrackSegWrapper->m_Segm; // Get the segment connected to the end point
  401. TrackSegWrapper = TrackSegWrapper->Pnext;
  402. }
  403. if( s_StartSegmentPresent )
  404. {
  405. if( TrackSegWrapper )
  406. tSegmentToStart = TrackSegWrapper->m_Segm; // Get the segment connected to the start point
  407. }
  408. }
  409. s_StartPointVertical = false;
  410. s_EndPointVertical = false;
  411. s_MovingSegmentVertical = false;
  412. s_StartPointHorizontal = false;
  413. s_EndPointHorizontal = false;
  414. s_MovingSegmentHorizontal = false;
  415. // Init parameters for the starting point of the moved segment
  416. if( tSegmentToStart )
  417. {
  418. if( tSegmentToStart->m_Flags & ENDPOINT )
  419. {
  420. tx1 = (double) tSegmentToStart->m_Start.x;
  421. ty1 = (double) tSegmentToStart->m_Start.y;
  422. tx2 = (double) tSegmentToStart->m_End.x;
  423. ty2 = (double) tSegmentToStart->m_End.y;
  424. }
  425. else
  426. {
  427. tx1 = (double) tSegmentToStart->m_End.x;
  428. ty1 = (double) tSegmentToStart->m_End.y;
  429. tx2 = (double) tSegmentToStart->m_Start.x;
  430. ty2 = (double) tSegmentToStart->m_Start.y;
  431. }
  432. }
  433. else // move the start point on a line starting at Track->m_Start, and perpendicular to Track
  434. {
  435. tx1 = (double) Track->m_Start.x;
  436. ty1 = (double) Track->m_Start.y;
  437. tx2 = (double) Track->m_End.x;
  438. ty2 = (double) Track->m_End.y;
  439. RotatePoint( &tx2, &ty2, tx1, ty1, 900 );
  440. }
  441. if( tx1!=tx2 )
  442. {
  443. s_StartSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
  444. s_StartSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
  445. }
  446. else
  447. {
  448. s_StartPointVertical = true; //signal first segment vertical
  449. }
  450. if( ty1==ty2 )
  451. {
  452. s_StartPointHorizontal = true;
  453. }
  454. // Init parameters for the ending point of the moved segment
  455. if( tSegmentToEnd )
  456. {
  457. //check if second line is vertical
  458. if( tSegmentToEnd->m_Flags & STARTPOINT )
  459. {
  460. tx1 = (double) tSegmentToEnd->m_Start.x;
  461. ty1 = (double) tSegmentToEnd->m_Start.y;
  462. tx2 = (double) tSegmentToEnd->m_End.x;
  463. ty2 = (double) tSegmentToEnd->m_End.y;
  464. }
  465. else
  466. {
  467. tx1 = (double) tSegmentToEnd->m_End.x;
  468. ty1 = (double) tSegmentToEnd->m_End.y;
  469. tx2 = (double) tSegmentToEnd->m_Start.x;
  470. ty2 = (double) tSegmentToEnd->m_Start.y;
  471. }
  472. }
  473. else // move the start point on a line starting at Track->m_End, and perpendicular to Track
  474. {
  475. tx1 = (double) Track->m_End.x;
  476. ty1 = (double) Track->m_End.y;
  477. tx2 = (double) Track->m_Start.x;
  478. ty2 = (double) Track->m_Start.y;
  479. RotatePoint( &tx2, &ty2, tx1, ty1, -900 );
  480. }
  481. if( tx2!=tx1 )
  482. {
  483. s_EndSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
  484. s_EndSegment_Yorg = ty1 - (ty2 - ty1) * tx1 / (tx2 - tx1);
  485. }
  486. else
  487. {
  488. s_EndPointVertical = true; //signal second segment vertical
  489. }
  490. if( ty1==ty2 )
  491. {
  492. s_EndPointHorizontal = true;
  493. }
  494. // Init parameters for the moved segment
  495. tx1 = (double) Track->m_Start.x;
  496. ty1 = (double) Track->m_Start.y;
  497. tx2 = (double) Track->m_End.x;
  498. ty2 = (double) Track->m_End.y;
  499. if( tx2 != tx1 )
  500. {
  501. s_MovingSegmentSlope = (ty2 - ty1) / (tx2 - tx1);
  502. }
  503. else
  504. {
  505. s_MovingSegmentVertical = true; //signal vertical line
  506. }
  507. if( ty1==ty2 )
  508. {
  509. s_MovingSegmentHorizontal = true;
  510. }
  511. // Test if drag is possible:
  512. if( s_MovingSegmentVertical )
  513. {
  514. if( s_EndPointVertical || s_StartPointVertical )
  515. return false;
  516. }
  517. else
  518. {
  519. if( !s_EndPointVertical && (s_MovingSegmentSlope == s_EndSegmentSlope) )
  520. return false;
  521. if( !s_StartPointVertical && (s_MovingSegmentSlope == s_StartSegmentSlope) )
  522. return false;
  523. }
  524. return TRUE;
  525. }
  526. /*************************************************************************************/
  527. void WinEDA_PcbFrame::Start_MoveOneNodeOrSegment( TRACK* track, wxDC* DC, int command )
  528. /*************************************************************************************/
  529. /* Init parametres to move one node:
  530. * a via or/and a terminal point of a track segment
  531. * The terminal point of other connected segments (if any) are moved too.
  532. */
  533. {
  534. if( !track )
  535. return;
  536. NewTrack = NULL;
  537. NbPtNewTrack = 0;
  538. EraseDragListe();
  539. /* Change hight light net: the new one will be hightlighted */
  540. Old_HightLigt_Status = g_HightLigt_Status;
  541. Old_HightLigth_NetCode = g_HightLigth_NetCode;
  542. if( g_HightLigt_Status )
  543. Hight_Light( DC );
  544. PosInit = GetScreen()->m_Curseur;
  545. if( track->Type() == TYPEVIA )
  546. {
  547. track->m_Flags = IS_DRAGGED | STARTPOINT | ENDPOINT;
  548. if( command != ID_POPUP_PCB_MOVE_TRACK_SEGMENT )
  549. {
  550. Collect_TrackSegmentsToDrag( DrawPanel, DC, track->m_Start,
  551. track->ReturnMaskLayer(), track->m_NetCode );
  552. }
  553. NewTrack = track;
  554. NbPtNewTrack = 1;
  555. PosInit = track->m_Start;
  556. }
  557. else
  558. {
  559. int diag = track->IsPointOnEnds( GetScreen()->m_Curseur, -1 );
  560. wxPoint pos;
  561. switch( command )
  562. {
  563. case ID_POPUP_PCB_MOVE_TRACK_SEGMENT:
  564. track->m_Flags |= IS_DRAGGED | ENDPOINT | STARTPOINT;
  565. AddSegmentToDragList( DrawPanel, DC, track->m_Flags, track );
  566. break;
  567. case ID_POPUP_PCB_DRAG_TRACK_SEGMENT:
  568. pos = track->m_Start;
  569. Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
  570. track->ReturnMaskLayer(), track->m_NetCode );
  571. pos = track->m_End;
  572. track->m_Flags |= IS_DRAGGED | ENDPOINT | STARTPOINT;
  573. Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
  574. track->ReturnMaskLayer(), track->m_NetCode );
  575. break;
  576. case ID_POPUP_PCB_MOVE_TRACK_NODE:
  577. pos = (diag & STARTPOINT) ? track->m_Start : track->m_End;
  578. Collect_TrackSegmentsToDrag( DrawPanel, DC, pos,
  579. track->ReturnMaskLayer(), track->m_NetCode );
  580. PosInit = pos;
  581. break;
  582. }
  583. track->m_Flags |= IS_DRAGGED;
  584. }
  585. s_LastPos = PosInit;
  586. DrawPanel->ManageCurseur = Show_MoveNode;
  587. DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
  588. g_HightLigth_NetCode = track->m_NetCode;
  589. g_HightLigt_Status = TRUE;
  590. DrawHightLight( DC, g_HightLigth_NetCode );
  591. DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
  592. }
  593. /***********************************************************************************/
  594. void WinEDA_PcbFrame::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC )
  595. /***********************************************************************************/
  596. {
  597. TRACK* TrackToStartPoint = NULL;
  598. TRACK* TrackToEndPoint = NULL;
  599. bool error = FALSE;
  600. if( !track )
  601. return;
  602. s_StartSegmentPresent = s_EndSegmentPresent = TRUE;
  603. if( (track->start == NULL) || (track->start->Type() == TYPETRACK) )
  604. TrackToStartPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START );
  605. // Test if more than one segment is connected to this point
  606. if( TrackToStartPoint )
  607. {
  608. TrackToStartPoint->SetState( BUSY, ON );
  609. if( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, START ) )
  610. error = TRUE;
  611. TrackToStartPoint->SetState( BUSY, OFF );
  612. }
  613. if( (track->end == NULL) || (track->end->Type() == TYPETRACK) )
  614. TrackToEndPoint = (TRACK*) Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END );
  615. // Test if more than one segment is connected to this point
  616. if( TrackToEndPoint )
  617. {
  618. TrackToEndPoint->SetState( BUSY, ON );
  619. if( Locate_Piste_Connectee( track, m_Pcb->m_Track, NULL, END ) )
  620. error = TRUE;
  621. TrackToEndPoint->SetState( BUSY, OFF );
  622. }
  623. if( error )
  624. {
  625. DisplayError( this, _( "Unable to drag this segment: too many segments connected" ) );
  626. return;
  627. }
  628. if( !TrackToStartPoint || (TrackToStartPoint->Type() != TYPETRACK) )
  629. s_StartSegmentPresent = FALSE;
  630. if( !TrackToEndPoint || (TrackToEndPoint->Type() != TYPETRACK) )
  631. s_EndSegmentPresent = FALSE;
  632. /* Change hight light net: the new one will be hightlighted */
  633. Old_HightLigt_Status = g_HightLigt_Status;
  634. Old_HightLigth_NetCode = g_HightLigth_NetCode;
  635. if( g_HightLigt_Status )
  636. Hight_Light( DC );
  637. EraseDragListe();
  638. NewTrack = NULL;
  639. NbPtNewTrack = 0;
  640. track->m_Flags = IS_DRAGGED;
  641. if( TrackToStartPoint )
  642. {
  643. int flag = STARTPOINT;
  644. if( track->m_Start != TrackToStartPoint->m_Start )
  645. flag = ENDPOINT;
  646. AddSegmentToDragList( DrawPanel, DC, flag, TrackToStartPoint );
  647. track->m_Flags |= STARTPOINT;
  648. }
  649. if( TrackToEndPoint )
  650. {
  651. int flag = STARTPOINT;
  652. if( track->m_End != TrackToEndPoint->m_Start )
  653. flag = ENDPOINT;
  654. AddSegmentToDragList( DrawPanel, DC, flag, TrackToEndPoint );
  655. track->m_Flags |= ENDPOINT;
  656. }
  657. AddSegmentToDragList( DrawPanel, DC, track->m_Flags, track );
  658. PosInit = GetScreen()->m_Curseur;
  659. s_LastPos = GetScreen()->m_Curseur;
  660. DrawPanel->ManageCurseur = Show_Drag_Track_Segment_With_Cte_Slope;
  661. DrawPanel->ForceCloseManageCurseur = Abort_MoveTrack;
  662. g_HightLigth_NetCode = track->m_NetCode;
  663. g_HightLigt_Status = TRUE;
  664. DrawHightLight( DC, g_HightLigth_NetCode );
  665. if( !InitialiseDragParameters() )
  666. {
  667. DisplayError( this, _( "Unable to drag this segment: two collinear segments" ) );
  668. DrawPanel->ManageCurseur = NULL;
  669. Abort_MoveTrack( DrawPanel, DC );
  670. return;
  671. }
  672. }
  673. /**********************************************************************/
  674. bool WinEDA_PcbFrame::PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC )
  675. /**********************************************************************/
  676. /* Place a dragged (or moved) track segment or via */
  677. {
  678. int errdrc;
  679. DRAG_SEGM* pt_drag;
  680. if( Track == NULL )
  681. return FALSE;
  682. int current_net_code = Track->m_NetCode;
  683. // DRC control:
  684. if( Drc_On )
  685. {
  686. errdrc = Drc( this, DC, Track, m_Pcb->m_Track, 1 );
  687. if( errdrc == BAD_DRC )
  688. return FALSE;
  689. /* Redraw the dragged segments */
  690. pt_drag = g_DragSegmentList;
  691. for( ; pt_drag != NULL; pt_drag = pt_drag->Pnext )
  692. {
  693. errdrc = Drc( this, DC, pt_drag->m_Segm, m_Pcb->m_Track, 1 );
  694. if( errdrc == BAD_DRC )
  695. return FALSE;
  696. }
  697. }
  698. int draw_mode = GR_OR | GR_SURBRILL;
  699. // DRC Ok: place track segments
  700. Track->m_Flags = 0;
  701. Track->SetState( EDIT, OFF );
  702. Track->Draw( DrawPanel, DC, draw_mode );
  703. /* Tracage des segments dragges */
  704. pt_drag = g_DragSegmentList;
  705. for( ; pt_drag; pt_drag = pt_drag->Pnext )
  706. {
  707. Track = pt_drag->m_Segm;
  708. Track->SetState( EDIT, OFF );
  709. Track->m_Flags = 0;
  710. Track->Draw( DrawPanel, DC, draw_mode );
  711. /* Test the connections modified by the move
  712. * (only pad connection must be tested, track connection will be tested by test_1_net_connexion() ) */
  713. int masque_layer = g_TabOneLayerMask[Track->GetLayer()];
  714. Track->start = Fast_Locate_Pad_Connecte( m_Pcb, Track->m_Start, masque_layer );
  715. Track->end = Fast_Locate_Pad_Connecte( m_Pcb, Track->m_End, masque_layer );
  716. }
  717. EraseDragListe();
  718. GetScreen()->SetModify();
  719. DrawPanel->ManageCurseur = NULL;
  720. DrawPanel->ForceCloseManageCurseur = NULL;
  721. if( current_net_code > 0 )
  722. test_1_net_connexion( DC, current_net_code );
  723. return TRUE;
  724. }
  725. /************************************************************************/
  726. EDA_BaseStruct* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
  727. /************************************************************************/
  728. /* Routine trouvant le point " d'accrochage " d'une extremite de piste.
  729. * Ce point peut etre un PAD ou un autre segment de piste
  730. * Retourne:
  731. * - pointeur sur ce PAD ou:
  732. * - pointeur sur le segment ou:
  733. * - NULL
  734. * Parametres d'appel:
  735. * coord pX, pY du point tst
  736. * masque des couches a tester
  737. */
  738. {
  739. D_PAD* pt_pad;
  740. TRACK* ptsegm;
  741. MODULE* Module;
  742. /* detection du point type PAD */
  743. pt_pad = NULL;
  744. Module = Pcb->m_Modules;
  745. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  746. {
  747. pt_pad = Locate_Pads( Module, pos, LayerMask );
  748. if( pt_pad )
  749. return pt_pad;
  750. }
  751. /* ici aucun pad n'a ete localise: detection d'un segment de piste */
  752. ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos, LayerMask );
  753. if( ptsegm == NULL )
  754. ptsegm = Locate_Pistes( Pcb->m_Track, pos, LayerMask );
  755. return ptsegm;
  756. }
  757. /******************************************************************************/
  758. TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm )
  759. /******************************************************************************/
  760. /* Routine de creation d'un point intermediaire sur un segment
  761. * le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
  762. * retourne:
  763. * NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
  764. * a une extremite ou:
  765. * pointeur sur le segment cree
  766. * si refsegm != NULL refsegm est pointeur sur le segment incident,
  767. * et le point cree est l'intersection des 2 axes des segments ptsegm et
  768. * refsegm
  769. * retourne la valeur exacte de pX et pY
  770. * Si ptsegm pointe sur une via:
  771. * retourne la valeur exacte de pX et pY et ptsegm,
  772. * mais ne cree pas de point supplementaire
  773. *
  774. */
  775. {
  776. int cX, cY;
  777. int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
  778. int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */
  779. TRACK* NewTrack;
  780. if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) )
  781. return NULL;
  782. if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) )
  783. return NULL;
  784. /* le point n'est pas sur une extremite de piste */
  785. if( ptsegm->Type() == TYPEVIA )
  786. {
  787. *pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
  788. return ptsegm;
  789. }
  790. /* calcul des coord vraies du point intermediaire dans le repere d'origine
  791. * = origine de ptsegm */
  792. cX = *pX - ptsegm->m_Start.x;
  793. cY = *pY - ptsegm->m_Start.y;
  794. dx = ptsegm->m_End.x - ptsegm->m_Start.x;
  795. dy = ptsegm->m_End.y - ptsegm->m_Start.y;
  796. // ***** A COMPLETER : non utilise
  797. if( refsegm )
  798. {
  799. ox = refsegm->m_Start.x - ptsegm->m_Start.x;
  800. oy = refsegm->m_Start.y - ptsegm->m_Start.y;
  801. fx = refsegm->m_End.x - ptsegm->m_Start.x;
  802. fy = refsegm->m_End.y - ptsegm->m_Start.y;
  803. }
  804. /* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
  805. if( dx == 0 )
  806. cX = 0;/* segm horizontal */
  807. else
  808. cY = (cX * dy) / dx;
  809. /* creation du point intermediaire ( c'est a dire creation d'un nouveau
  810. * segment, debutant au point intermediaire */
  811. cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
  812. NewTrack = ptsegm->Copy();
  813. NewTrack->Insert( NULL, ptsegm );
  814. /* correction du pointeur de fin du nouveau segment */
  815. NewTrack->end = ptsegm->end;
  816. /* le segment primitif finit au nouveau point : */
  817. ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
  818. ptsegm->SetState( END_ONPAD, OFF );
  819. /* le nouveau segment debute au nouveau point : */
  820. ptsegm = NewTrack;;
  821. ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
  822. ptsegm->SetState( BEGIN_ONPAD, OFF );
  823. *pX = cX; *pY = cY;
  824. return ptsegm;
  825. }