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.

549 lines
18 KiB

  1. /****************************************************/
  2. /* Edition des pistes */
  3. /* Routines de duplication et deplacement de pistes */
  4. /****************************************************/
  5. #include "fctsys.h"
  6. #include "gr_basic.h"
  7. #include "common.h"
  8. #include "pcbnew.h"
  9. #include "autorout.h"
  10. #include "protos.h"
  11. #define COPY_ROUTE 1
  12. #define MOVE_ROUTE 2
  13. extern char marq_bitmap[]; // dans TRACEPCB : bitmap du marqueur "DRC"
  14. /* Routines externes */
  15. #if 0
  16. /* Routines Locales */
  17. static void Exit_DuplicTrack( COMMAND* Cmd );
  18. static void Start_CopieMove_Route( COMMAND* Cmd );
  19. static void Duplic_Track( COMMAND* Cmd );
  20. static void Place_Dupl_Route( COMMAND* Cmd );
  21. static void Show_Move_Piste( wxDC* DC, int flag );
  22. /* variables locales */
  23. static int startX, startY;
  24. static int PosInitX, PosInitY;
  25. static TRACK* NewTrack; /* Nouvelle piste creee ou piste deplacee */
  26. static int NbPtNewTrack;
  27. static int FlagState; /* memoire de la commande (COPY_ROUTE ou MOVE_ROUTE) */
  28. /* variables externes */
  29. /**************************************************************/
  30. static void Exit_DuplicTrack( WinEDA_DrawFrame* frame, wxDC* DC )
  31. /***************************************************************/
  32. /* routine d'annulation de la Commande Begin_Route si une piste est en cours
  33. * de tracage, ou de sortie de l'application EDITRACK.
  34. * Appel par la touche ESC
  35. */
  36. {
  37. TRACK* NextS;
  38. int ii;
  39. wxDC* DC = Cmd->DC;
  40. frame->DrawPanel->ManageCurseur = NULL;
  41. if( NewTrack )
  42. {
  43. /* Effacement du trace en cours */
  44. DisplayOpt.DisplayPcbTrackFill = FALSE;
  45. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  46. DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
  47. if( FlagState == COPY_ROUTE )
  48. {
  49. for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS )
  50. {
  51. if( NewTrack == NULL )
  52. break;
  53. NextS = (TRACK*) NewTrack->Pnext;
  54. delete NewTrack;
  55. }
  56. }
  57. else /* Move : remise en ancienne position */
  58. {
  59. TRACK* Track = NewTrack;
  60. PosInitX -= Track->m_Start.x;
  61. PosInitY -= Track->m_Start.y;
  62. for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
  63. {
  64. if( Track == NULL )
  65. break;
  66. Track->m_Start.x += PosInitX;
  67. Track->m_Start.y += PosInitY;
  68. Track->m_End.x += PosInitX;
  69. Track->m_End.y += PosInitY;
  70. }
  71. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
  72. }
  73. if( Etat_Surbrillance )
  74. Hight_Light( DC );
  75. EraseMsgBox();
  76. NewTrack = NULL;
  77. }
  78. else
  79. {
  80. EraseMsgBox();
  81. }
  82. }
  83. /******************************************/
  84. static void Place_Dupl_Route( COMMAND* Cmd )
  85. /******************************************/
  86. /*
  87. * Routine de placement d'une piste (succession de segments)
  88. */
  89. {
  90. D_PAD* pt_pad;
  91. TRACK* pt_track, * Track, * pt_classe, * NextS;
  92. int masquelayer;
  93. EDA_BaseStruct* LockPoint;
  94. int ii, old_net_code, new_net_code, DRC_error = 0;
  95. wxDC* DC = Cmd->DC;
  96. ActiveDrawPanel->ManageCurseur = NULL;
  97. if( NewTrack == NULL )
  98. return;
  99. old_net_code = NewTrack->net_code;
  100. /* Placement du flag BUSY de la piste originelle, qui ne doit
  101. * pas etre vue dans les recherches de raccordement suivantes */
  102. ii = NbPtNewTrack; pt_track = NewTrack;
  103. for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
  104. {
  105. pt_track->SetState( BUSY, ON );
  106. }
  107. /* Detection du nouveau net_code */
  108. ii = NbPtNewTrack; pt_track = NewTrack;
  109. for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
  110. {
  111. pt_track->net_code = 0;
  112. }
  113. new_net_code = 0;
  114. ii = 0; pt_track = NewTrack;
  115. for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
  116. {
  117. /* Localisation de la pastille ou segment en debut de segment: */
  118. masquelayer = tab_layer[pt_track->Layer];
  119. LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
  120. if( LockPoint )
  121. {
  122. if( LockPoint->m_StructType == TYPEPAD )
  123. {
  124. pt_pad = (D_PAD*) LockPoint;
  125. new_net_code = pt_pad->net_code;
  126. if( new_net_code > 0 )
  127. break;
  128. }
  129. else /* debut de piste sur un segment de piste */
  130. {
  131. Track = (TRACK*) LockPoint;
  132. new_net_code = Track->net_code;
  133. if( new_net_code > 0 )
  134. break;
  135. }
  136. }
  137. LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
  138. if( LockPoint )
  139. {
  140. if( LockPoint->m_StructType == TYPEPAD )
  141. {
  142. pt_pad = (D_PAD*) LockPoint;
  143. new_net_code = pt_pad->net_code;
  144. if( new_net_code > 0 )
  145. break;
  146. }
  147. else /* debut de piste sur un segment de piste */
  148. {
  149. Track = (TRACK*) LockPoint;
  150. new_net_code = Track->net_code;
  151. if( new_net_code > 0 )
  152. break;
  153. }
  154. }
  155. }
  156. /* Mise a jour du nouveau net code de la piste */
  157. ii = 0; pt_track = NewTrack;
  158. for( ; ii < NbPtNewTrack; ii++, pt_track = (TRACK*) pt_track->Pnext )
  159. {
  160. pt_track->net_code = new_net_code;
  161. }
  162. /* Controle DRC de la nouvelle piste */
  163. ii = 0; pt_track = NewTrack;
  164. for( ; ii < NbPtNewTrack; ii++, pt_track = pt_track->Next() )
  165. {
  166. if( Drc_On == RUN )
  167. if( drc( DC, pt_track, pt_pcb->Track, 1 ) == BAD_DRC )
  168. {
  169. if( confirmation( " Erreur DRC, Place piste:" ) == YES )
  170. continue;
  171. else
  172. {
  173. DRC_error = 1; break;
  174. }
  175. }
  176. }
  177. if( DRC_error == 0 )
  178. {
  179. if( FlagState == MOVE_ROUTE )
  180. {
  181. /* copie nouvelle piste */
  182. pt_track = NewTrack;
  183. NewTrack = pt_track->Copy( NbPtNewTrack );
  184. /* effacement ancienne ( chainage et liens mauvais */
  185. ii = NbPtNewTrack;
  186. for( ; ii > 0; ii--, pt_track = NextS )
  187. {
  188. NextS = (TRACK*) pt_track->Pnext;
  189. DeleteStructure( pt_track );
  190. }
  191. test_1_net_connexion( DC, old_net_code );
  192. }
  193. pt_classe = NewTrack->GetBestInsertPoint();
  194. NewTrack->Insert( pt_classe );
  195. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
  196. /* Mise a jour des connexions sur pads et sur pistes */
  197. ii = 0; pt_track = NewTrack;
  198. for( ; ii < NbPtNewTrack; ii++, pt_track = NextS )
  199. {
  200. NextS = (TRACK*) pt_track->Pnext;
  201. pt_track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
  202. masquelayer = tab_layer[pt_track->Layer];
  203. /* Localisation de la pastille ou segment sur debut segment: */
  204. LockPoint = LocateLockPoint( pt_track->m_Start.x, pt_track->m_Start.y, masquelayer );
  205. if( LockPoint )
  206. {
  207. pt_track->start = LockPoint;
  208. if( LockPoint->m_StructType == TYPEPAD )
  209. { /* fin de piste sur un pad */
  210. pt_pad = (D_PAD*) LockPoint;
  211. pt_track->SetState( BEGIN_ONPAD, ON );
  212. }
  213. else /* debut de piste sur un segment de piste */
  214. {
  215. Track = (TRACK*) LockPoint;
  216. CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
  217. }
  218. }
  219. /* Localisation de la pastille ou segment sur fin de segment: */
  220. LockPoint = LocateLockPoint( pt_track->m_End.x, pt_track->m_End.y, masquelayer );
  221. if( LockPoint )
  222. {
  223. pt_track->end = LockPoint;
  224. if( LockPoint->m_StructType == TYPEPAD )
  225. { /* fin de piste sur un pad */
  226. pt_pad = (D_PAD*) LockPoint;
  227. pt_track->SetState( END_ONPAD, ON );
  228. }
  229. else /* debut de piste sur un segment de piste */
  230. {
  231. Track = (TRACK*) LockPoint;
  232. CreateLockPoint( &pt_track->m_Start.x, &pt_track->m_Start.y, Track, pt_track );
  233. }
  234. }
  235. }
  236. /* Suppression du flag BUSY */
  237. ii = NbPtNewTrack; pt_track = NewTrack;
  238. for( ; ii > 0; ii--, pt_track = (TRACK*) pt_track->Pnext )
  239. {
  240. pt_track->SetState( BUSY, OFF );
  241. }
  242. test_1_net_connexion( DC, new_net_code );
  243. ActiveScreen->SetModify();
  244. }
  245. else /* Erreur DRC: Annulation commande */
  246. {
  247. DisplayOpt.DisplayPcbTrackFill = FALSE;
  248. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  249. DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
  250. if( FlagState == MOVE_ROUTE )
  251. { /* Remise en position de la piste deplacee */
  252. Track = NewTrack;
  253. PosInitX -= Track->m_Start.x; PosInitY -= Track->m_Start.y;
  254. for( ii = 0; ii < NbPtNewTrack; ii++, Track = (TRACK*) Track->Pnext )
  255. {
  256. if( Track == NULL )
  257. break;
  258. Track->m_Start.x += PosInitX; Track->m_Start.y += PosInitY;
  259. Track->m_End.x += PosInitX; Track->m_End.y += PosInitY;
  260. Track->SetState( BUSY, OFF );
  261. }
  262. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_OR );
  263. }
  264. if( FlagState == COPY_ROUTE )
  265. { /* Suppression copie */
  266. for( ii = 0; ii < NbPtNewTrack; NewTrack = NextS )
  267. {
  268. if( NewTrack == NULL )
  269. break;
  270. NextS = (TRACK*) NewTrack->Pnext;
  271. delete NewTrack;
  272. }
  273. }
  274. }
  275. NewTrack = NULL;
  276. Affiche_Infos_Status_Pcb( Cmd );
  277. if( Etat_Surbrillance )
  278. Hight_Light( DC );
  279. }
  280. /***********************************************/
  281. static void Show_Move_Piste( wxDC* DC, int flag )
  282. /***********************************************/
  283. /* redessin du contour de la piste lors des deplacements de la souris */
  284. {
  285. int ii, dx, dy;
  286. TRACK* ptsegm;
  287. if( NewTrack == NULL )
  288. return; /* Pas de piste en cours (Erreur ) */
  289. /* efface ancienne position si elle a ete deja dessinee */
  290. if( (flag == CURSEUR_MOVED ) && (FlagState == COPY_ROUTE ) )
  291. {
  292. DisplayOpt.DisplayPcbTrackFill = FALSE;
  293. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  294. }
  295. if( FlagState == MOVE_ROUTE )
  296. {
  297. if( flag == CURSEUR_MOVED )
  298. DisplayOpt.DisplayPcbTrackFill = FALSE;
  299. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  300. }
  301. /* mise a jour des coordonnees des segments de la piste */
  302. dx = ActiveScreen->Curseur_X - startX;
  303. dy = ActiveScreen->Curseur_Y - startY;
  304. startX = ActiveScreen->Curseur_X;
  305. startY = ActiveScreen->Curseur_Y;
  306. ii = NbPtNewTrack, ptsegm = NewTrack;
  307. for( ; ii > 0; ii--, ptsegm = (TRACK*) ptsegm->Pnext )
  308. {
  309. ptsegm->m_Start.x += dx; ptsegm->m_Start.y += dy;
  310. ptsegm->m_End.x += dx; ptsegm->m_End.y += dy;
  311. }
  312. /* dessin de la nouvelle piste */
  313. DisplayOpt.DisplayPcbTrackFill = FALSE;
  314. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  315. DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
  316. }
  317. /************************************************/
  318. /* void Start_CopieMove_Route(COMMAND * Cmd) */
  319. /************************************************/
  320. /* Routine permettant la recopie d'une piste deja tracee
  321. */
  322. static void Start_CopieMove_Route( COMMAND* Cmd )
  323. {
  324. int ii;
  325. TRACK* pt_segm, * pt_track;
  326. int masquelayer = tab_layer[ActiveScreen->Active_Layer];
  327. wxDC* DC = Cmd->DC;
  328. if( NewTrack )
  329. return;
  330. FlagState = (int) Cmd->Menu->param_inf;
  331. /* Recherche de la piste sur la couche active (non zone) */
  332. for( pt_segm = pt_pcb->Track; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
  333. {
  334. pt_segm = Locate_Pistes( pt_segm, masquelayer, CURSEUR_OFF_GRILLE );
  335. if( pt_segm == NULL )
  336. break;
  337. break;
  338. }
  339. if( pt_segm != NULL )
  340. {
  341. if( FlagState == COPY_ROUTE )
  342. pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, 0 );
  343. else
  344. pt_track = Marque_Une_Piste( DC, pt_segm, &NbPtNewTrack, GR_XOR );
  345. if( NbPtNewTrack ) /* Il y a NbPtNewTrack segments de piste a traiter */
  346. {
  347. /* effacement du flag BUSY de la piste originelle */
  348. ii = NbPtNewTrack; pt_segm = pt_track;
  349. for( ; ii > 0; ii--, pt_segm = (TRACK*) pt_segm->Pnext )
  350. {
  351. pt_segm->SetState( BUSY, OFF );
  352. }
  353. if( FlagState == COPY_ROUTE )
  354. NewTrack = pt_track->Copy( NbPtNewTrack );
  355. else
  356. NewTrack = pt_track;
  357. Affiche_Infos_Piste( Cmd, pt_track );
  358. startX = ActiveScreen->Curseur_X;
  359. startY = ActiveScreen->Curseur_Y;
  360. Place_Dupl_Route_Item.State = WAIT;
  361. ActiveDrawPanel->ManageCurseur = Show_Move_Piste;
  362. DisplayOpt.DisplayPcbTrackFill = FALSE;
  363. Trace_Une_Piste( DC, NewTrack, NbPtNewTrack, GR_XOR );
  364. DisplayOpt.DisplayPcbTrackFill = Track_fill_copy;
  365. PosInitX = NewTrack->m_Start.x; PosInitY = NewTrack->m_Start.y;
  366. }
  367. }
  368. }
  369. #endif
  370. /************************************************************************/
  371. EDA_BaseStruct* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
  372. /************************************************************************/
  373. /* Routine trouvant le point " d'accrochage " d'une extremite de piste.
  374. * Ce point peut etre un PAD ou un autre segment de piste
  375. * Retourne:
  376. * - pointeur sur ce PAD ou:
  377. * - pointeur sur le segment ou:
  378. * - NULL
  379. * Parametres d'appel:
  380. * coord pX, pY du point tst
  381. * masque des couches a tester
  382. */
  383. {
  384. D_PAD* pt_pad;
  385. TRACK* ptsegm;
  386. MODULE* Module;
  387. /* detection du point type PAD */
  388. pt_pad = NULL;
  389. Module = Pcb->m_Modules;
  390. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  391. {
  392. pt_pad = Locate_Pads( Module, pos.x, pos.y, LayerMask );
  393. if( pt_pad )
  394. return pt_pad;
  395. }
  396. /* ici aucun pad n'a ete localise: detection d'un segment de piste */
  397. ptsegm = Fast_Locate_Piste( Pcb->m_Track, NULL, pos.x, pos.y, LayerMask );
  398. if( ptsegm == NULL )
  399. ptsegm = Locate_Pistes( Pcb->m_Track, pos.x, pos.y, LayerMask );
  400. return ptsegm;
  401. }
  402. /******************************************************************************/
  403. TRACK* CreateLockPoint( int* pX, int* pY, TRACK* ptsegm, TRACK* refsegm )
  404. /******************************************************************************/
  405. /* Routine de creation d'un point intermediaire sur un segment
  406. * le segment ptsegm est casse en 2 segments se raccordant au point pX, pY
  407. * retourne:
  408. * NULL si pas de nouveau point ( c.a.d si pX, pY correspondait deja
  409. * a une extremite ou:
  410. * pointeur sur le segment cree
  411. * si refsegm != NULL refsegm est pointeur sur le segment incident,
  412. * et le point cree est l'intersection des 2 axes des segments ptsegm et
  413. * refsegm
  414. * retourne la valeur exacte de pX et pY
  415. * Si ptsegm pointe sur une via:
  416. * retourne la valeur exacte de pX et pY et ptsegm,
  417. * mais ne cree pas de point supplementaire
  418. *
  419. */
  420. {
  421. int cX, cY;
  422. int dx, dy; /* Coord de l'extremite du segm ptsegm / origine */
  423. int ox, oy, fx, fy; /* coord de refsegm / origine de prsegm */
  424. TRACK* NewTrack;
  425. if( (ptsegm->m_Start.x == *pX) && (ptsegm->m_Start.y == *pY) )
  426. return NULL;
  427. if( (ptsegm->m_End.x == *pX) && (ptsegm->m_End.y == *pY) )
  428. return NULL;
  429. /* le point n'est pas sur une extremite de piste */
  430. if( ptsegm->m_StructType == TYPEVIA )
  431. {
  432. *pX = ptsegm->m_Start.x; *pY = ptsegm->m_Start.y;
  433. return ptsegm;
  434. }
  435. /* calcul des coord vraies du point intermediaire dans le repere d'origine
  436. * = origine de ptsegm */
  437. cX = *pX - ptsegm->m_Start.x;
  438. cY = *pY - ptsegm->m_Start.y;
  439. dx = ptsegm->m_End.x - ptsegm->m_Start.x;
  440. dy = ptsegm->m_End.y - ptsegm->m_Start.y;
  441. // ***** A COMPLETER : non utilise
  442. if( refsegm )
  443. {
  444. ox = refsegm->m_Start.x - ptsegm->m_Start.x;
  445. oy = refsegm->m_Start.y - ptsegm->m_Start.y;
  446. fx = refsegm->m_End.x - ptsegm->m_Start.x;
  447. fy = refsegm->m_End.y - ptsegm->m_Start.y;
  448. }
  449. /* pour que le point soit sur le segment ptsegm: cY/cX = dy/dx */
  450. if( dx == 0 )
  451. cX = 0; /* segm horizontal */
  452. else
  453. cY = (cX * dy) / dx;
  454. /* creation du point intermediaire ( c'est a dire creation d'un nouveau
  455. * segment, debutant au point intermediaire */
  456. cX += ptsegm->m_Start.x; cY += ptsegm->m_Start.y;
  457. NewTrack = ptsegm->Copy();
  458. NewTrack->Insert( NULL, ptsegm );
  459. /* correction du pointeur de fin du nouveau segment */
  460. NewTrack->end = ptsegm->end;
  461. /* le segment primitif finit au nouveau point : */
  462. ptsegm->m_End.x = cX; ptsegm->m_End.y = cY;
  463. ptsegm->SetState( END_ONPAD, OFF );
  464. /* le nouveau segment debute au nouveau point : */
  465. ptsegm = NewTrack;;
  466. ptsegm->m_Start.x = cX; ptsegm->m_Start.y = cY;
  467. ptsegm->SetState( BEGIN_ONPAD, OFF );
  468. *pX = cX; *pY = cY;
  469. return ptsegm;
  470. }