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.

848 lines
27 KiB

  1. /*************************************************************/
  2. /******************* editeur de PCB **************************/
  3. /* traitement du Chevelu: routines de calcul des connexions */
  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. /* variables locales */
  12. /* routines exportees */
  13. void Recalcule_all_net_connexion( wxDC* DC );
  14. /* Routines locales */
  15. static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn );
  16. static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn );
  17. static void RebuildTrackChain( BOARD* pcb );
  18. static int tri_par_netcode( TRACK** pt_ref, TRACK** pt_compare );
  19. /*..*/
  20. /*****************************************************************/
  21. static int change_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn,
  22. int old_val, int new_val )
  23. /*****************************************************************/
  24. /*
  25. * Change les num locaux d'equipot old valeur en new valeur
  26. * retourne le nombre de changements
  27. * si pt_end_conn = NULL: recherche jusqu'a fin de chaine
  28. */
  29. {
  30. TRACK* pt_conn;
  31. int nb_change = 0;
  32. D_PAD* pt_pad;
  33. if( old_val == new_val )
  34. return 0;
  35. if( (old_val > 0) && (old_val < new_val) )
  36. EXCHG( old_val, new_val );
  37. pt_conn = pt_start_conn;
  38. for( ; pt_conn != NULL; pt_conn = (TRACK*) pt_conn->Pnext )
  39. {
  40. if( pt_conn->m_Sous_Netcode != old_val )
  41. {
  42. if( pt_conn == pt_end_conn )
  43. break;
  44. continue;
  45. }
  46. nb_change++;
  47. pt_conn->m_Sous_Netcode = new_val;
  48. if( pt_conn->start && ( pt_conn->start->m_StructType == TYPEPAD) )
  49. {
  50. pt_pad = (D_PAD*) (pt_conn->start);
  51. if( pt_pad->m_physical_connexion == old_val )
  52. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  53. }
  54. if( pt_conn->end && (pt_conn->end->m_StructType == TYPEPAD) )
  55. {
  56. pt_pad = (D_PAD*) (pt_conn->end);
  57. if( pt_pad->m_physical_connexion == old_val )
  58. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  59. }
  60. if( pt_conn == pt_end_conn )
  61. break;
  62. }
  63. return nb_change;
  64. }
  65. /******************************************************************/
  66. static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
  67. /******************************************************************/
  68. /* balaye la liste des SEGMENTS de PISTE
  69. * - debut = pt_start_conn
  70. * - fin = pt_end_conn (pointe le dernier segment a analyser)
  71. * pour attribuer ou propager un numero d'equipotentielle par
  72. * blocs de connexions existantes
  73. * la zone balayee est supposee appartenir au meme net, c'est a dire que
  74. * les segments de pistes sont tries par net_code
  75. */
  76. {
  77. TRACK* pt_conn;
  78. int sous_net_code;
  79. D_PAD* pt_pad;
  80. TRACK* pt_autre_piste;
  81. BOARD_ITEM* PtStruct;
  82. /* Initialisations prealables */
  83. pt_conn = pt_start_conn;
  84. for( ; pt_conn != NULL; pt_conn = (TRACK*) pt_conn->Pnext )
  85. {
  86. pt_conn->m_Sous_Netcode = 0;
  87. PtStruct = pt_conn->start;
  88. if( PtStruct && (PtStruct->m_StructType == TYPEPAD) )
  89. ( (D_PAD*) PtStruct )->m_physical_connexion = 0;
  90. PtStruct = pt_conn->end;
  91. if( PtStruct && (PtStruct->m_StructType == TYPEPAD) )
  92. ( (D_PAD*) PtStruct )->m_physical_connexion = 0;
  93. if( pt_conn == pt_end_conn )
  94. break;
  95. }
  96. sous_net_code = 1;
  97. pt_start_conn->m_Sous_Netcode = sous_net_code;
  98. /* debut du calcul de propagation */
  99. pt_conn = pt_start_conn;
  100. for( ; pt_conn != NULL; pt_conn = (TRACK*) pt_conn->Pnext )
  101. {
  102. /* Traitement des connexions a pads */
  103. PtStruct = pt_conn->start;
  104. if( PtStruct && (PtStruct->m_StructType == TYPEPAD) )
  105. /* la connexion debute sur 1 pad */
  106. {
  107. pt_pad = (D_PAD*) PtStruct;
  108. if( pt_conn->m_Sous_Netcode ) /* la connexion fait deja partie d'une chaine */
  109. {
  110. if( pt_pad->m_physical_connexion > 0 ) /* le pad fait aussi partie d'une chaine */
  111. {
  112. change_equipot( pt_start_conn, pt_end_conn,
  113. pt_pad->m_physical_connexion, pt_conn->m_Sous_Netcode );
  114. }
  115. else
  116. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  117. }
  118. else /* la connexion ne fait pas partie encore d'une chaine */
  119. {
  120. if( pt_pad->m_physical_connexion > 0 )
  121. {
  122. pt_conn->m_Sous_Netcode = pt_pad->m_physical_connexion;
  123. }
  124. else
  125. {
  126. sous_net_code++;
  127. pt_conn->m_Sous_Netcode = sous_net_code;
  128. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  129. }
  130. }
  131. }
  132. PtStruct = pt_conn->end;
  133. if( PtStruct && (PtStruct->m_StructType == TYPEPAD) )
  134. /* la connexion finit sur 1 pad */
  135. {
  136. pt_pad = (D_PAD*) PtStruct;
  137. if( pt_conn->m_Sous_Netcode )
  138. {
  139. if( pt_pad->m_physical_connexion > 0 )
  140. {
  141. change_equipot( pt_start_conn, pt_end_conn,
  142. pt_pad->m_physical_connexion, pt_conn->m_Sous_Netcode );
  143. }
  144. else
  145. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  146. }
  147. else
  148. {
  149. if( pt_pad->m_physical_connexion > 0 )
  150. {
  151. pt_conn->m_Sous_Netcode = pt_pad->m_physical_connexion;
  152. }
  153. else
  154. {
  155. sous_net_code++; pt_conn->m_Sous_Netcode = sous_net_code;
  156. pt_pad->m_physical_connexion = pt_conn->m_Sous_Netcode;
  157. }
  158. }
  159. }
  160. /* traitement des connexions entre segments */
  161. PtStruct = pt_conn->start;
  162. if( PtStruct && (PtStruct->m_StructType != TYPEPAD) )
  163. {
  164. /* debut sur une autre piste */
  165. pt_autre_piste = (TRACK*) PtStruct;
  166. if( pt_conn->m_Sous_Netcode ) /* La connexion fait deja partie d'un block */
  167. {
  168. if( pt_autre_piste->m_Sous_Netcode )
  169. {
  170. change_equipot( pt_start_conn, pt_end_conn,
  171. pt_autre_piste->m_Sous_Netcode, pt_conn->m_Sous_Netcode );
  172. }
  173. else
  174. {
  175. pt_autre_piste->m_Sous_Netcode = pt_conn->m_Sous_Netcode;
  176. }
  177. }
  178. else /* La connexion ne fait partie d'aucun block */
  179. {
  180. if( pt_autre_piste->m_Sous_Netcode )
  181. {
  182. pt_conn->m_Sous_Netcode = pt_autre_piste->m_Sous_Netcode;
  183. }
  184. else
  185. {
  186. sous_net_code++; pt_conn->m_Sous_Netcode = sous_net_code;
  187. pt_autre_piste->m_Sous_Netcode = pt_conn->m_Sous_Netcode;
  188. }
  189. }
  190. }
  191. PtStruct = pt_conn->end;
  192. if( PtStruct && (PtStruct->m_StructType != TYPEPAD) )
  193. {
  194. /* fin connectee a une autre piste */
  195. pt_autre_piste = (TRACK*) PtStruct;
  196. if( pt_conn->m_Sous_Netcode ) /* La connexion fait deja partie d'un block */
  197. {
  198. if( pt_autre_piste->m_Sous_Netcode )
  199. {
  200. change_equipot( pt_start_conn, pt_end_conn,
  201. pt_autre_piste->m_Sous_Netcode, pt_conn->m_Sous_Netcode );
  202. }
  203. else
  204. pt_autre_piste->m_Sous_Netcode = pt_conn->m_Sous_Netcode;
  205. }
  206. else /* La connexion ne fait partie d'aucun block */
  207. {
  208. if( pt_autre_piste->m_Sous_Netcode )
  209. {
  210. pt_conn->m_Sous_Netcode = pt_autre_piste->m_Sous_Netcode;
  211. }
  212. else
  213. {
  214. sous_net_code++; pt_conn->m_Sous_Netcode = sous_net_code;
  215. pt_autre_piste->m_Sous_Netcode = pt_conn->m_Sous_Netcode;
  216. }
  217. }
  218. }
  219. if( pt_conn == pt_end_conn )
  220. break;
  221. }
  222. }
  223. /***************************************************/
  224. void WinEDA_BasePcbFrame::test_connexions( wxDC* DC )
  225. /***************************************************/
  226. /*
  227. * Routine recherchant les connexions deja faites et mettant a jour
  228. * le status du chevelu ( Bit CH_ACTIF mis a 0 si connexion trouvee
  229. * Les pistes sont supposees etre triees par ordre de net_code croissant
  230. */
  231. {
  232. TRACK* pt_start_conn, * pt_end_conn;
  233. int ii;
  234. LISTE_PAD* pt_pad;
  235. int current_net_code;
  236. /* Etablissement des equipotentielles vraies */
  237. pt_pad = m_Pcb->m_Pads;
  238. for( ii = 0; ii < m_Pcb->m_NbPads; ii++, pt_pad++ )
  239. {
  240. (*pt_pad)->m_physical_connexion = 0;
  241. }
  242. ////////////////////////////
  243. // Calcul de la connexite //
  244. ////////////////////////////
  245. /* Les pointeurs .start et .end sont mis a jour, si la
  246. * connexion est du type segment a segment
  247. */
  248. pt_start_conn = m_Pcb->m_Track;
  249. while( pt_start_conn != NULL )
  250. {
  251. current_net_code = pt_start_conn->m_NetCode;
  252. pt_end_conn = pt_start_conn->GetEndNetCode( current_net_code );
  253. /* Calcul des connexions type segment du net courant */
  254. calcule_connexite_1_net( pt_start_conn, pt_end_conn );
  255. pt_start_conn = (TRACK*) pt_end_conn->Pnext;
  256. }
  257. return;
  258. }
  259. /**************************************************************/
  260. void WinEDA_BasePcbFrame::Recalcule_all_net_connexion( wxDC* DC )
  261. /**************************************************************/
  262. /*
  263. * Routine Recalculant les pointeurs sur connexions types piste a piste
  264. * relatives a tous les nets.
  265. * Cette routine est utilisee apres reclassement des segments de piste par
  266. * ordre de net_code, puisque des pointeurs sur connexions deviennent faux
  267. * ( les pointeurs type pad restent bons )
  268. */
  269. {
  270. TRACK* EndConn;
  271. int net_code, net_code_max;
  272. if( m_Pcb->m_Track == NULL )
  273. return;
  274. /* calcul du net_code max */
  275. EndConn = m_Pcb->m_Track;
  276. while( EndConn->Pnext )
  277. EndConn = (TRACK*) EndConn->Pnext;
  278. net_code_max = EndConn->m_NetCode;
  279. for( net_code = 0; net_code <= net_code_max; net_code++ )
  280. {
  281. test_1_net_connexion( DC, net_code );
  282. }
  283. }
  284. /*************************************************************************/
  285. void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
  286. /*************************************************************************/
  287. /*
  288. * Routine recherchant les connexions deja faites relatives a 1 net
  289. */
  290. {
  291. TRACK* pt_start_conn, * pt_end_conn;
  292. int ii, nb_net_noconnect = 0;
  293. LISTE_PAD* pt_pad;
  294. wxString msg;
  295. if( net_code == 0 )
  296. return;
  297. if( (m_Pcb->m_Status_Pcb & LISTE_CHEVELU_OK) == 0 )
  298. Compile_Ratsnest( DC, TRUE );
  299. pt_pad = (LISTE_PAD*) m_Pcb->m_Pads;
  300. for( ii = 0; ii < m_Pcb->m_NbPads; ii++, pt_pad++ )
  301. {
  302. int pad_net_code = (*pt_pad)->m_NetCode;
  303. if( pad_net_code < net_code )
  304. continue;
  305. if( pad_net_code > net_code )
  306. break;
  307. (*pt_pad)->m_physical_connexion = 0;
  308. }
  309. /* Determination des limites du net */
  310. if( m_Pcb->m_Track )
  311. {
  312. pt_end_conn = NULL;
  313. pt_start_conn = m_Pcb->m_Track->GetStartNetCode( net_code );
  314. if( pt_start_conn )
  315. pt_end_conn = pt_start_conn->GetEndNetCode( net_code );
  316. if( pt_start_conn && pt_end_conn ) // c.a.d. s'il y a des segments
  317. {
  318. calcule_connexite_1_net( pt_start_conn, pt_end_conn );
  319. }
  320. }
  321. /* Test des chevelus */
  322. nb_net_noconnect = Test_1_Net_Ratsnest( DC, net_code );
  323. /* Affichage des resultats */
  324. msg.Printf( wxT( "links %d nc %d net:nc %d" ),
  325. m_Pcb->m_NbLinks, m_Pcb->GetNumNoconnect(),
  326. nb_net_noconnect );
  327. Affiche_Message( msg );
  328. return;
  329. }
  330. /***************************************************************************/
  331. static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
  332. /***************************************************************************/
  333. /* calcule la connexite d'un net constitue de segments de piste consecutifs.
  334. * Entree:
  335. * pt_start_conn = adresse du 1er segment ( debut du net )
  336. * pt_end_conn = adr de fin (dernier segment)
  337. * Les connexions relatives aux pads doivent etre deja calculees, car elles
  338. * ne sont pas ici recalculees ( pour des raisons de temps de calcul, et
  339. * du fait que lors des modif de pistes, les pads ne sont pas touches
  340. */
  341. {
  342. TRACK* Track;
  343. /* Les pointeurs .start et .end sont mis a jour, si la
  344. * connexion est du type segment a segment.
  345. * la connexion sur pads est supposee etre deja calculee */
  346. /* Raz des pointeurs sur pistes */
  347. for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext )
  348. {
  349. Track->m_Sous_Netcode = 0;
  350. if( Track->GetState( BEGIN_ONPAD ) == 0 )
  351. Track->start = NULL;
  352. if( Track->GetState( END_ONPAD ) == 0 )
  353. Track->end = NULL;
  354. if( Track == pt_end_conn )
  355. break;
  356. }
  357. /* calcul des connexions */
  358. for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext )
  359. {
  360. if( Track->m_StructType == TYPEVIA )
  361. {
  362. TRACK* pt_segm;
  363. int layermask = Track->ReturnMaskLayer();
  364. for( pt_segm = pt_start_conn; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext )
  365. {
  366. int curlayermask = pt_segm->ReturnMaskLayer();
  367. if( !pt_segm->start && (pt_segm->m_Start == Track->m_Start)
  368. && ( layermask & curlayermask ) )
  369. {
  370. pt_segm->start = Track;
  371. }
  372. if( !pt_segm->end && (pt_segm->m_End == Track->m_Start)
  373. && (layermask & curlayermask) )
  374. {
  375. pt_segm->end = Track;
  376. }
  377. if( pt_segm == pt_end_conn )
  378. break;
  379. }
  380. }
  381. if( Track->start == NULL )
  382. {
  383. Track->start = Locate_Piste_Connectee( Track, Track, pt_end_conn, START );
  384. }
  385. if( Track->end == NULL )
  386. {
  387. Track->end = Locate_Piste_Connectee( Track, Track, pt_end_conn, END );
  388. }
  389. if( Track == pt_end_conn )
  390. break;
  391. }
  392. /* Generation des sous equipots du net */
  393. propage_equipot( pt_start_conn, pt_end_conn );
  394. }
  395. /********************************************/
  396. /* Reattribution des net_codes de reference */
  397. /********************************************/
  398. /*
  399. * reattribution des net_codes aux segments de pistes.
  400. * Routine utilisee apres modification generale des noms de nets (apres
  401. * lecrure netliste ou edition de nets sur pads, effacement /ajout de
  402. * modules...)
  403. *
  404. * Elle se fait en 2 passes:
  405. * 1 - reattribution des segments commencant ( et/ou finissant ) sur 1 pad
  406. * les autres segments sont mis a reference NULLE
  407. * 2 - reattribution des segments restantes a ref NULLE
  408. */
  409. #define POS_AFF_CHREF 62
  410. /* recherche le pad connecte a l'extremite de la piste de coord px, py
  411. * parametres d'appel:
  412. * px, py = coord du point tst
  413. * masque_layer = couche(s) de connexion
  414. * pt_liste = adresse de la liste des pointeurs de pads, tels que
  415. * apparaissant apres build_liste_pad, mais classee par position X
  416. * de pads croissantes.
  417. * retourne : pointeur sur le pad connecte
  418. * la routine travaille par dichotomie sur la liste des pads tries par pos X
  419. * croissante, elle est donc beaucoup plus rapide que Fast_Locate_Pad_connecte,
  420. * mais implique le calcul de cette liste.
  421. *
  422. * (la liste placee en m_Pcb->m_Pads et elle triee par netcodes croissants)
  423. */
  424. static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* pcb, LISTE_PAD* pt_liste,
  425. int px, int py, int masque_layer )
  426. {
  427. D_PAD* pad;
  428. LISTE_PAD* ptr_pad, * lim;
  429. int nb_pad = pcb->m_NbPads;
  430. int ii;
  431. lim = pt_liste + (pcb->m_NbPads - 1 );
  432. ptr_pad = pt_liste;
  433. while( nb_pad )
  434. {
  435. pad = *ptr_pad;
  436. ii = nb_pad;
  437. nb_pad >>= 1; if( (ii & 1) && ( ii > 1 ) )
  438. nb_pad++;
  439. if( pad->m_Pos.x < px ) /* on doit chercher plus loin */
  440. {
  441. ptr_pad += nb_pad; if( ptr_pad > lim )
  442. ptr_pad = lim;
  443. continue;
  444. }
  445. if( pad->m_Pos.x > px ) /* on doit chercher moins loin */
  446. {
  447. ptr_pad -= nb_pad;
  448. if( ptr_pad < pt_liste )
  449. ptr_pad = pt_liste;
  450. continue;
  451. }
  452. if( pad->m_Pos.x == px ) /* zone de classement trouvee */
  453. {
  454. /* recherche du debut de la zone */
  455. while( ptr_pad >= pt_liste )
  456. {
  457. pad = *ptr_pad;
  458. if( pad->m_Pos.x == px )
  459. ptr_pad--;
  460. else
  461. break;
  462. }
  463. ptr_pad++; /* pointe depart de zone a pad->m_Pos.x = px */
  464. for( ; ; ptr_pad++ )
  465. {
  466. if( ptr_pad > lim )
  467. return NULL; /* hors zone */
  468. pad = *ptr_pad;
  469. if( pad->m_Pos.x != px )
  470. return NULL; /* hors zone */
  471. if( pad->m_Pos.y != py )
  472. continue;
  473. /* Pad peut-etre trouve ici: il doit etre sur la bonne couche */
  474. if( pad->m_Masque_Layer & masque_layer )
  475. return pad;
  476. }
  477. }
  478. }
  479. return NULL;
  480. }
  481. static int SortPadsByXCoord( void* pt_ref, void* pt_comp )
  482. /* used to Sort a pad list by x coordinate value
  483. */
  484. {
  485. D_PAD* ref = *(LISTE_PAD*) pt_ref;
  486. D_PAD* comp = *(LISTE_PAD*) pt_comp;
  487. return ref->m_Pos.x - comp->m_Pos.x;
  488. }
  489. /****************************************************/
  490. LISTE_PAD* CreateSortedPadListByXCoord( BOARD* pcb )
  491. /****************************************************/
  492. /* Create a sorted list of pointers to pads.
  493. * This list is sorted by X ccordinate value.
  494. * The list must be freed bu user
  495. */
  496. {
  497. LISTE_PAD* pad_list = (LISTE_PAD*) MyMalloc( pcb->m_NbPads * sizeof( D_PAD *) );
  498. memcpy( pad_list, pcb->m_Pads, pcb->m_NbPads * sizeof( D_PAD *) );
  499. qsort( pad_list, pcb->m_NbPads, sizeof( D_PAD *),
  500. ( int( * ) ( const void*, const void* ) )SortPadsByXCoord );
  501. return pad_list;
  502. }
  503. /******************************************************************/
  504. void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
  505. /******************************************************************/
  506. {
  507. TRACK* pt_piste,
  508. * pt_next;
  509. int a_color;
  510. char new_passe_request = 1, flag;
  511. LISTE_PAD* pt_mem;
  512. BOARD_ITEM* PtStruct;
  513. int masque_layer;
  514. wxString msg;
  515. if( m_Pcb->m_NbPads == 0 )
  516. return;
  517. a_color = CYAN;
  518. if( affiche )
  519. Affiche_1_Parametre( this, POS_AFF_CHREF, wxT( "DataBase" ), wxT( "Netcodes" ), a_color );
  520. recalcule_pad_net_code();
  521. if( affiche )
  522. Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Gen Pads " ), a_color );
  523. //////////////////////////////////////////////////////
  524. // Connexion des pistes accrochees a 1 pad au moins //
  525. //////////////////////////////////////////////////////
  526. pt_mem = CreateSortedPadListByXCoord( m_Pcb );
  527. if( affiche )
  528. Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Conn Pads" ), a_color );
  529. /* Raz des flags particuliers des segments de piste */
  530. pt_piste = m_Pcb->m_Track;
  531. for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext )
  532. {
  533. pt_piste->SetState( BUSY | EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
  534. pt_piste->m_NetCode = 0;
  535. }
  536. pt_piste = m_Pcb->m_Track;
  537. for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext )
  538. {
  539. flag = 0;
  540. masque_layer = g_TabOneLayerMask[pt_piste->GetLayer()];
  541. /* y a t-il une pastille sur une extremite */
  542. pt_piste->start = SuperFast_Locate_Pad_Connecte( m_Pcb,
  543. pt_mem,
  544. pt_piste->m_Start.x,
  545. pt_piste->m_Start.y,
  546. masque_layer );
  547. if( pt_piste->start != NULL )
  548. {
  549. pt_piste->SetState( BEGIN_ONPAD, ON );
  550. pt_piste->m_NetCode = ( (D_PAD*) (pt_piste->start) )->m_NetCode;
  551. }
  552. pt_piste->end = SuperFast_Locate_Pad_Connecte( m_Pcb,
  553. pt_mem,
  554. pt_piste->m_End.x,
  555. pt_piste->m_End.y,
  556. masque_layer );
  557. if( pt_piste->end != NULL )
  558. {
  559. pt_piste->SetState( END_ONPAD, ON );
  560. pt_piste->m_NetCode = ( (D_PAD*) (pt_piste->end) )->m_NetCode;
  561. }
  562. }
  563. MyFree( pt_mem );
  564. ////////////////////////////////////////////////////
  565. // Calcul de la connexite entre segments de piste //
  566. ////////////////////////////////////////////////////
  567. /* Les pointeurs .start et .end sont mis a jour, s'ils etaient NULLs.
  568. * La connexion est alors du type segment a segment
  569. */
  570. if( affiche )
  571. Affiche_1_Parametre( this, POS_AFF_CHREF, wxEmptyString, wxT( "Conn Segm" ), a_color );
  572. for( pt_piste = m_Pcb->m_Track; pt_piste != NULL; pt_piste = pt_piste->Next() )
  573. {
  574. if( pt_piste->start == NULL )
  575. {
  576. pt_piste->start = Locate_Piste_Connectee( pt_piste, m_Pcb->m_Track, NULL, START );
  577. }
  578. if( pt_piste->end == NULL )
  579. {
  580. pt_piste->end = Locate_Piste_Connectee( pt_piste, m_Pcb->m_Track, NULL, END );
  581. }
  582. }
  583. ////////////////////////////////
  584. // Reattribution des net_code //
  585. ////////////////////////////////
  586. a_color = YELLOW;
  587. while( new_passe_request )
  588. {
  589. bool reset_flag = FALSE;
  590. new_passe_request = 0;
  591. if( affiche )
  592. {
  593. msg.Printf( wxT( "Net->Segm pass %d " ), new_passe_request + 1 );
  594. Affiche_1_Parametre( this, POS_AFF_CHREF, wxEmptyString, msg, a_color );
  595. }
  596. /* look for vias which could be connect many tracks */
  597. for( TRACK* via = m_Pcb->m_Track; via != NULL; via = via->Next() )
  598. {
  599. if( via->m_StructType != TYPEVIA )
  600. continue;
  601. if( via->m_NetCode > 0 )
  602. continue; // Netcode already known
  603. // Lock for a connection to a track with a known netcode
  604. pt_next = m_Pcb->m_Track;
  605. while( ( pt_next = Locate_Piste_Connectee( via, pt_next, NULL, START ) ) != NULL )
  606. {
  607. if( pt_next->m_NetCode )
  608. {
  609. via->m_NetCode = pt_next->m_NetCode;
  610. break;
  611. }
  612. pt_next->SetState( BUSY, ON );
  613. reset_flag = TRUE;
  614. }
  615. }
  616. if( reset_flag )
  617. for( pt_piste = m_Pcb->m_Track; pt_piste != NULL; pt_piste = pt_piste->Next() )
  618. {
  619. pt_piste->SetState( BUSY, OFF );
  620. }
  621. for( pt_piste = m_Pcb->m_Track; pt_piste != NULL; pt_piste = pt_piste->Next() )
  622. {
  623. /* Traitement du point de debut */
  624. PtStruct = (BOARD_ITEM*) pt_piste->start;
  625. if( PtStruct && (PtStruct->m_StructType != TYPEPAD) )
  626. { // Begin on an other track segment
  627. pt_next = (TRACK*) PtStruct;
  628. if( pt_piste->m_NetCode )
  629. {
  630. if( pt_next->m_NetCode == 0 )
  631. {
  632. new_passe_request = 1;
  633. pt_next->m_NetCode = pt_piste->m_NetCode;
  634. }
  635. }
  636. else
  637. {
  638. if( pt_next->m_NetCode != 0 )
  639. {
  640. pt_piste->m_NetCode = pt_next->m_NetCode;
  641. new_passe_request = 1;
  642. }
  643. }
  644. }
  645. /* Localisation du point de fin */
  646. PtStruct = pt_piste->end;
  647. if( PtStruct &&(PtStruct->m_StructType != TYPEPAD) )
  648. { // End sur piste
  649. pt_next = (TRACK*) PtStruct;
  650. if( pt_piste->m_NetCode )
  651. {
  652. if( pt_next->m_NetCode == 0 )
  653. {
  654. new_passe_request = 1;
  655. pt_next->m_NetCode = pt_piste->m_NetCode;
  656. }
  657. }
  658. else
  659. {
  660. if( pt_next->m_NetCode != 0 )
  661. {
  662. pt_piste->m_NetCode = pt_next->m_NetCode;
  663. new_passe_request = 1;
  664. }
  665. }
  666. }
  667. }
  668. }
  669. /* Reclassemment des pistes par numero de net: */
  670. if( affiche )
  671. Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Reorder " ), a_color );
  672. RebuildTrackChain( m_Pcb );
  673. if( affiche )
  674. Affiche_1_Parametre( this, -1, wxEmptyString, wxT( " " ), a_color );
  675. }
  676. /*
  677. * routine de tri de connexion utilisee par la fonction QSORT
  678. * le tri est fait par numero de net
  679. */
  680. int tri_par_netcode( TRACK** pt_ref, TRACK** pt_compare )
  681. {
  682. int ii;
  683. ii = (*pt_ref)->m_NetCode - (*pt_compare)->m_NetCode;
  684. return ii;
  685. }
  686. /*****************************************/
  687. static void RebuildTrackChain( BOARD* pcb )
  688. /*****************************************/
  689. /* Recalcule le chainage des pistes pour que le chainage soit fait par
  690. * netcodes croissants
  691. */
  692. {
  693. TRACK* Track, ** Liste;
  694. int ii, nbsegm;
  695. /* Count segments */
  696. nbsegm = pcb->GetNumSegmTrack();
  697. if( pcb->m_Track == NULL )
  698. return;
  699. Liste = (TRACK**) MyZMalloc( (nbsegm + 1) * sizeof(TRACK *) );
  700. ii = 0; Track = pcb->m_Track;
  701. for( ; Track != NULL; ii++, Track = (TRACK*) Track->Pnext )
  702. {
  703. Liste[ii] = Track;
  704. }
  705. qsort( Liste, nbsegm, sizeof(TRACK *),
  706. ( int( * ) ( const void*, const void* ) )tri_par_netcode );
  707. /* Update the linked list pointers */
  708. Track = Liste[0];
  709. Track->Pback = pcb; Track->Pnext = Liste[1];
  710. pcb->m_Track = Track;
  711. for( ii = 1; ii < nbsegm; ii++ )
  712. {
  713. Track = Liste[ii];
  714. Track->Pback = Liste[ii - 1];
  715. Track->Pnext = Liste[ii + 1];
  716. }
  717. MyFree( Liste );
  718. }