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.

945 lines
26 KiB

18 years ago
18 years ago
  1. /****************************************************/
  2. /* PCB EDITOR: autorouting and "graphics" routines. */
  3. /****************************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "pcbnew.h"
  8. #include "autorout.h"
  9. #include "zones.h"
  10. #include "trigo.h"
  11. #include "cell.h"
  12. int ToMatrixCoordinate( int aPhysicalCoordinate );
  13. void TraceLignePcb( int x0,
  14. int y0,
  15. int x1,
  16. int y1,
  17. int layer,
  18. int color );
  19. void TraceArc( int ux0,
  20. int uy0,
  21. int ux1,
  22. int uy1,
  23. int ArcAngle,
  24. int lg,
  25. int layer,
  26. int color,
  27. int op_logique );
  28. static void DrawSegmentQcq( int ux0,
  29. int uy0,
  30. int ux1,
  31. int uy1,
  32. int lg,
  33. int layer,
  34. int color,
  35. int op_logique );
  36. static void TraceFilledCercle( BOARD* Pcb,
  37. int cx,
  38. int cy,
  39. int rayon,
  40. int masque_layer,
  41. int color,
  42. int op_logique );
  43. static void TraceCercle( int ux0, int uy0, int ux1, int uy1, int lg, int layer,
  44. int color, int op_logique );
  45. /* Macro call to update cell. */
  46. #define OP_CELL( layer, dy, dx ) \
  47. { \
  48. if( layer < 0 ) \
  49. { \
  50. WriteCell( dy, dx, BOTTOM, color ); \
  51. if( Nb_Sides ) \
  52. WriteCell( dy, dx, TOP, color ); \
  53. } \
  54. else \
  55. { \
  56. if( layer == Route_Layer_BOTTOM ) \
  57. WriteCell( dy, dx, BOTTOM, color ); \
  58. if( Nb_Sides ) \
  59. if( layer == Route_Layer_TOP ) \
  60. WriteCell( dy, dx, TOP, color ); \
  61. } \
  62. }
  63. /**
  64. * Function ToMatrixCoordinate
  65. * compute the coordinate in the routing matrix from the real (board) value
  66. * @param aPhysicalCoordinate = value to convert
  67. * @return the coordinate relative to the matrix
  68. */
  69. int ToMatrixCoordinate( int aPhysicalCoordinate )
  70. {
  71. return aPhysicalCoordinate / g_GridRoutingSize;
  72. }
  73. /* Initialize a color value, the cells included in the board edge of the
  74. * pad surface by pt_pad, with the margin reserved for isolation and the
  75. * half width of the runway
  76. * Parameters:
  77. * Pt_pad: pointer to the description of the pad
  78. * color: mask write in cells
  79. * margin: add a value to the radius or half the score pad
  80. * op_logique: type of writing in the cell (WRITE, OR)
  81. */
  82. void Place_1_Pad_Board( BOARD* Pcb,
  83. D_PAD* pt_pad,
  84. int color,
  85. int marge,
  86. int op_logique )
  87. {
  88. int dx, dy;
  89. wxPoint shape_pos = pt_pad->ReturnShapePos();;
  90. dx = pt_pad->m_Size.x / 2; dx += marge;
  91. if( pt_pad->m_PadShape == PAD_CIRCLE )
  92. {
  93. TraceFilledCercle( Pcb, shape_pos.x, shape_pos.y, dx,
  94. pt_pad->m_Masque_Layer, color, op_logique );
  95. return;
  96. }
  97. dy = pt_pad->m_Size.y / 2; dy += marge;
  98. if( pt_pad->m_PadShape == PAD_TRAPEZOID )
  99. {
  100. dx += abs( pt_pad->m_DeltaSize.y ) / 2;
  101. dy += abs( pt_pad->m_DeltaSize.x ) / 2;
  102. }
  103. if( ( pt_pad->m_Orient % 900 ) == 0 ) /* The pad is a rectangle
  104. * horizontally or vertically. */
  105. {
  106. /* Orientation turned 90 deg. */
  107. if( ( pt_pad->m_Orient == 900 ) || ( pt_pad->m_Orient == 2700 ) )
  108. {
  109. EXCHG( dx, dy );
  110. }
  111. TraceFilledRectangle( Pcb, shape_pos.x - dx, shape_pos.y - dy,
  112. shape_pos.x + dx, shape_pos.y + dy,
  113. pt_pad->m_Masque_Layer, color, op_logique );
  114. }
  115. else
  116. {
  117. TraceFilledRectangle( Pcb, shape_pos.x - dx, shape_pos.y - dy,
  118. shape_pos.x + dx, shape_pos.y + dy,
  119. (int) pt_pad->m_Orient,
  120. pt_pad->m_Masque_Layer, color, op_logique );
  121. }
  122. }
  123. /* Initialize a color value, the cells included in the board rea of the
  124. * circle center cx, cy.
  125. * Parameters:
  126. * radius: a value add to the radius or half the score pad
  127. * masque_layer: layer occupied
  128. * color: mask write in cells
  129. * op_logique: type of writing in the cell (WRITE, OR)
  130. */
  131. void TraceFilledCercle( BOARD* Pcb,
  132. int cx,
  133. int cy,
  134. int rayon,
  135. int masque_layer,
  136. int color,
  137. int op_logique )
  138. {
  139. int row, col;
  140. int ux0, uy0, ux1, uy1;
  141. int row_max, col_max, row_min, col_min;
  142. int trace = 0;
  143. float fdistmin, fdistx, fdisty;
  144. void (* WriteCell)( int, int, int, BoardCell );
  145. int tstwrite = 0;
  146. int distmin;
  147. /* Determine occupied layer. */
  148. /* Single routing layer on bitmap and BOTTOM
  149. * Route_Layer_B = Route_Layer_A */
  150. if( masque_layer & g_TabOneLayerMask[Route_Layer_BOTTOM] )
  151. trace = 1; /* Trace on BOTTOM */
  152. if( masque_layer & g_TabOneLayerMask[Route_Layer_TOP] )
  153. if( Nb_Sides )
  154. trace |= 2; /* Trace on TOP */
  155. if( trace == 0 )
  156. return;
  157. switch( op_logique )
  158. {
  159. default:
  160. case WRITE_CELL:
  161. WriteCell = SetCell;
  162. break;
  163. case WRITE_OR_CELL:
  164. WriteCell = OrCell;
  165. break;
  166. case WRITE_XOR_CELL:
  167. WriteCell = XorCell;
  168. break;
  169. case WRITE_AND_CELL:
  170. WriteCell = AndCell;
  171. break;
  172. case WRITE_ADD_CELL:
  173. WriteCell = AddCell;
  174. break;
  175. }
  176. cx -= Pcb->m_BoundaryBox.m_Pos.x;
  177. cy -= Pcb->m_BoundaryBox.m_Pos.y;
  178. distmin = rayon;
  179. /* Calculate the bounding rectangle of the circle. */
  180. ux0 = cx - rayon;
  181. uy0 = cy - rayon;
  182. ux1 = cx + rayon;
  183. uy1 = cy + rayon;
  184. /* Calculate limit coordinates of cells belonging to the rectangle. */
  185. row_max = uy1 / g_GridRoutingSize;
  186. col_max = ux1 / g_GridRoutingSize;
  187. row_min = uy0 / g_GridRoutingSize; // if (uy0 > row_min*g_GridRoutingSize
  188. // ) row_min++;
  189. col_min = ux0 / g_GridRoutingSize; // if (ux0 > col_min*g_GridRoutingSize
  190. // ) col_min++;
  191. if( row_min < 0 )
  192. row_min = 0;
  193. if( row_max >= (Nrows - 1) )
  194. row_max = Nrows - 1;
  195. if( col_min < 0 )
  196. col_min = 0;
  197. if( col_max >= (Ncols - 1) )
  198. col_max = Ncols - 1;
  199. /* Calculate coordinate limits of cell belonging to the rectangle. */
  200. if( row_min > row_max )
  201. row_max = row_min;
  202. if( col_min > col_max )
  203. col_max = col_min;
  204. fdistmin = (float) distmin * distmin;
  205. for( row = row_min; row <= row_max; row++ )
  206. {
  207. fdisty = (float) ( cy - ( row * g_GridRoutingSize ) );
  208. fdisty *= fdisty;
  209. for( col = col_min; col <= col_max; col++ )
  210. {
  211. fdistx = (float) ( cx - ( col * g_GridRoutingSize ) );
  212. fdistx *= fdistx;
  213. if( fdistmin <= ( fdistx + fdisty ) )
  214. continue;
  215. if( trace & 1 )
  216. WriteCell( row, col, BOTTOM, color );
  217. if( trace & 2 )
  218. WriteCell( row, col, TOP, color );
  219. tstwrite = 1;
  220. }
  221. }
  222. if( tstwrite )
  223. return;
  224. /* If no cell has been written, it affects the 4 neighboring diagonal
  225. * (Adverse event: pad off grid in the center of the 4 neighboring
  226. * diagonal) */
  227. distmin = g_GridRoutingSize / 2 + 1;
  228. fdistmin = ( (float) distmin * distmin ) * 2; /* Distance to center point
  229. * diagonally */
  230. for( row = row_min; row <= row_max; row++ )
  231. {
  232. fdisty = (float) ( cy - ( row * g_GridRoutingSize ) );
  233. fdisty *= fdisty;
  234. for( col = col_min; col <= col_max; col++ )
  235. {
  236. fdistx = (float) ( cx - ( col * g_GridRoutingSize ) );
  237. fdistx *= fdistx;
  238. if( fdistmin <= ( fdistx + fdisty ) )
  239. continue;
  240. if( trace & 1 )
  241. WriteCell( row, col, BOTTOM, color );
  242. if( trace & 2 )
  243. WriteCell( row, col, TOP, color );
  244. }
  245. }
  246. }
  247. /* Draws a segment of track on the BOARD.
  248. */
  249. void TraceSegmentPcb( BOARD* Pcb,
  250. TRACK* pt_segm,
  251. int color,
  252. int marge,
  253. int op_logique )
  254. {
  255. int demi_pas, demi_largeur;
  256. int ux0, uy0, ux1, uy1;
  257. demi_pas = g_GridRoutingSize / 2;
  258. demi_largeur = ( pt_segm->m_Width / 2 ) + marge;
  259. /* Calculate the bounding rectangle of the segment (if H, V or Via) */
  260. ux0 = pt_segm->m_Start.x - Pcb->m_BoundaryBox.m_Pos.x;
  261. uy0 = pt_segm->m_Start.y - Pcb->m_BoundaryBox.m_Pos.y;
  262. ux1 = pt_segm->m_End.x - Pcb->m_BoundaryBox.m_Pos.x;
  263. uy1 = pt_segm->m_End.y - Pcb->m_BoundaryBox.m_Pos.y;
  264. /* Test if VIA (filled circle was drawn) */
  265. if( pt_segm->Type() == TYPE_VIA )
  266. {
  267. int mask_layer = 0;
  268. if( pt_segm->IsOnLayer( Route_Layer_BOTTOM ) )
  269. mask_layer = 1 << Route_Layer_BOTTOM;
  270. if( pt_segm->IsOnLayer( Route_Layer_TOP ) )
  271. {
  272. if( mask_layer == 0 )
  273. mask_layer = 1 << Route_Layer_TOP;
  274. else
  275. mask_layer = -1;
  276. }
  277. if( color == VIA_IMPOSSIBLE )
  278. mask_layer = -1;
  279. if( mask_layer )
  280. TraceFilledCercle( Pcb, pt_segm->m_Start.x, pt_segm->m_Start.y,
  281. demi_largeur, mask_layer, color, op_logique );
  282. return;
  283. }
  284. int layer = pt_segm->GetLayer();
  285. if( color == VIA_IMPOSSIBLE )
  286. layer = -1;
  287. /* The segment is here a straight line or a circle or an arc.: */
  288. if( pt_segm->m_Shape == S_CIRCLE )
  289. {
  290. TraceCercle( ux0, uy0, ux1, uy1, demi_largeur, layer, color,
  291. op_logique );
  292. return;
  293. }
  294. if( pt_segm->m_Shape == S_ARC )
  295. {
  296. TraceArc( ux0, uy0, ux1, uy1, pt_segm->m_Param, demi_largeur, layer,
  297. color, op_logique );
  298. return;
  299. }
  300. /* The segment is here a line segment. */
  301. if( ( ux0 != ux1 ) && ( uy0 != uy1 ) ) // Segment tilts.
  302. {
  303. DrawSegmentQcq( ux0, uy0, ux1, uy1, demi_largeur, layer, color,
  304. op_logique );
  305. return;
  306. }
  307. // The segment is horizontal or vertical.
  308. // DrawHVSegment(ux0,uy0,ux1,uy1,demi_largeur,layer,color,op_logique);
  309. // F4EXB 051018-01
  310. DrawSegmentQcq( ux0, uy0, ux1, uy1, demi_largeur, layer, color,
  311. op_logique ); // F4EXB 051018-01
  312. return; // F4EXB 051018-01
  313. }
  314. /* Draws a line, if layer = -1 on all layers
  315. */
  316. void TraceLignePcb( int x0,
  317. int y0,
  318. int x1,
  319. int y1,
  320. int layer,
  321. int color,
  322. int op_logique )
  323. {
  324. int dx, dy, lim;
  325. int cumul, inc, il, delta;
  326. void (* WriteCell)( int, int, int, BoardCell );
  327. switch( op_logique )
  328. {
  329. default:
  330. case WRITE_CELL:
  331. WriteCell = SetCell; break;
  332. case WRITE_OR_CELL:
  333. WriteCell = OrCell; break;
  334. case WRITE_XOR_CELL:
  335. WriteCell = XorCell; break;
  336. case WRITE_AND_CELL:
  337. WriteCell = AndCell; break;
  338. case WRITE_ADD_CELL:
  339. WriteCell = AddCell; break;
  340. }
  341. if( x0 == x1 ) // Vertical.
  342. {
  343. if( y1 < y0 )
  344. EXCHG( y0, y1 );
  345. dy = y0 / g_GridRoutingSize;
  346. lim = y1 / g_GridRoutingSize;
  347. dx = x0 / g_GridRoutingSize;
  348. /* Clipping limits of board. */
  349. if( ( dx < 0 ) || ( dx >= Ncols ) )
  350. return;
  351. if( dy < 0 )
  352. dy = 0;
  353. if( lim >= Nrows )
  354. lim = Nrows - 1;
  355. for( ; dy <= lim; dy++ )
  356. {
  357. OP_CELL( layer, dy, dx );
  358. }
  359. return;
  360. }
  361. if( y0 == y1 ) // Horizontal
  362. {
  363. if( x1 < x0 )
  364. EXCHG( x0, x1 );
  365. dx = x0 / g_GridRoutingSize;
  366. lim = x1 / g_GridRoutingSize;
  367. dy = y0 / g_GridRoutingSize;
  368. /* Clipping limits of board. */
  369. if( ( dy < 0 ) || ( dy >= Nrows ) )
  370. return;
  371. if( dx < 0 )
  372. dx = 0;
  373. if( lim >= Ncols )
  374. lim = Ncols - 1;
  375. for( ; dx <= lim; dx++ )
  376. {
  377. OP_CELL( layer, dy, dx );
  378. }
  379. return;
  380. }
  381. /* Here is some perspective: using the algorithm LUCAS. */
  382. if( abs( x1 - x0 ) >= abs( y1 - y0 ) ) /* segment slightly inclined/ */
  383. {
  384. if( x1 < x0 )
  385. {
  386. EXCHG( x1, x0 ); EXCHG( y1, y0 );
  387. }
  388. dx = x0 / g_GridRoutingSize;
  389. lim = x1 / g_GridRoutingSize;
  390. dy = y0 / g_GridRoutingSize;
  391. inc = 1; if( y1 < y0 )
  392. inc = -1;
  393. il = lim - dx; cumul = il / 2;
  394. delta = abs( y1 - y0 ) / g_GridRoutingSize;
  395. for( ; dx <= lim; )
  396. {
  397. if( ( dx >= 0 ) && ( dy >= 0 )
  398. && ( dx < Ncols ) && ( dy < Nrows ) )
  399. {
  400. OP_CELL( layer, dy, dx );
  401. }
  402. dx++;
  403. cumul += delta;
  404. if( cumul > il )
  405. {
  406. cumul -= il;
  407. dy += inc;
  408. }
  409. }
  410. }
  411. else
  412. {
  413. if( y1 < y0 )
  414. {
  415. EXCHG( x1, x0 );
  416. EXCHG( y1, y0 );
  417. }
  418. dy = y0 / g_GridRoutingSize;
  419. lim = y1 / g_GridRoutingSize;
  420. dx = x0 / g_GridRoutingSize;
  421. inc = 1;
  422. if( x1 < x0 )
  423. inc = -1;
  424. il = lim - dy; cumul = il / 2;
  425. delta = abs( x1 - x0 ) / g_GridRoutingSize;
  426. for( ; dy <= lim; )
  427. {
  428. if( ( dx >= 0 ) && ( dy >= 0 )
  429. && ( dx < Ncols ) && ( dy < Nrows ) )
  430. {
  431. OP_CELL( layer, dy, dx );
  432. }
  433. dy++;
  434. cumul += delta;
  435. if( cumul > il )
  436. {
  437. cumul -= il;
  438. dx += inc;
  439. }
  440. }
  441. }
  442. }
  443. /* Overloaded functions.
  444. *
  445. * Uses the color value of all cells included in the board coordinate of
  446. * the rectangle ux0, uy0 (top left corner)
  447. * A UX1, UY1 (bottom right corner)
  448. * The rectangle is horizontal (or vertical)
  449. * Contact PCBs.
  450. */
  451. void TraceFilledRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1,
  452. int masque_layer, int color, int op_logique )
  453. {
  454. int row, col;
  455. int row_min, row_max, col_min, col_max;
  456. int trace = 0;
  457. void (* WriteCell)( int, int, int, BoardCell );
  458. if( masque_layer & g_TabOneLayerMask[Route_Layer_BOTTOM] )
  459. trace = 1; /* Trace on BOTTOM */
  460. if( ( masque_layer & g_TabOneLayerMask[Route_Layer_TOP] ) && Nb_Sides )
  461. trace |= 2; /* Trace on TOP */
  462. if( trace == 0 )
  463. return;
  464. switch( op_logique )
  465. {
  466. default:
  467. case WRITE_CELL:
  468. WriteCell = SetCell;
  469. break;
  470. case WRITE_OR_CELL:
  471. WriteCell = OrCell;
  472. break;
  473. case WRITE_XOR_CELL:
  474. WriteCell = XorCell;
  475. break;
  476. case WRITE_AND_CELL:
  477. WriteCell = AndCell;
  478. break;
  479. case WRITE_ADD_CELL:
  480. WriteCell = AddCell;
  481. break;
  482. }
  483. ux0 -= Pcb->m_BoundaryBox.m_Pos.x;
  484. uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
  485. ux1 -= Pcb->m_BoundaryBox.m_Pos.x;
  486. uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
  487. /* Calculating limits coord cells belonging to the rectangle. */
  488. row_max = uy1 / g_GridRoutingSize;
  489. col_max = ux1 / g_GridRoutingSize;
  490. row_min = uy0 / g_GridRoutingSize;
  491. if( uy0 > row_min * g_GridRoutingSize )
  492. row_min++;
  493. col_min = ux0 / g_GridRoutingSize;
  494. if( ux0 > col_min * g_GridRoutingSize )
  495. col_min++;
  496. if( row_min < 0 )
  497. row_min = 0;
  498. if( row_max >= ( Nrows - 1 ) )
  499. row_max = Nrows - 1;
  500. if( col_min < 0 )
  501. col_min = 0;
  502. if( col_max >= ( Ncols - 1 ) )
  503. col_max = Ncols - 1;
  504. for( row = row_min; row <= row_max; row++ )
  505. {
  506. for( col = col_min; col <= col_max; col++ )
  507. {
  508. if( trace & 1 )
  509. WriteCell( row, col, BOTTOM, color );
  510. if( trace & 2 )
  511. WriteCell( row, col, TOP, color );
  512. }
  513. }
  514. }
  515. /* Overloaded functions.
  516. *
  517. * Uses the color value of all cells included in the board coordinate of the
  518. * rectangle ux0, uy0 (top right corner)
  519. * a UX1, UY1 (lower left corner)
  520. * the rectangle is the value of turning angle (in degrees 0.1)
  521. * contact PCBs.
  522. */
  523. void TraceFilledRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1,
  524. int angle, int masque_layer, int color,
  525. int op_logique )
  526. {
  527. int row, col;
  528. int cx, cy; /* Center of rectangle */
  529. int rayon; /* Radius of the circle */
  530. int row_min, row_max, col_min, col_max;
  531. int rotrow, rotcol;
  532. int trace = 0;
  533. void (* WriteCell)( int, int, int, BoardCell );
  534. if( masque_layer & g_TabOneLayerMask[Route_Layer_BOTTOM] )
  535. trace = 1; /* Trace on BOTTOM */
  536. if( masque_layer & g_TabOneLayerMask[Route_Layer_TOP] )
  537. if( Nb_Sides )
  538. trace |= 2; /* Trace on TOP */
  539. if( trace == 0 )
  540. return;
  541. switch( op_logique )
  542. {
  543. default:
  544. case WRITE_CELL:
  545. WriteCell = SetCell;
  546. break;
  547. case WRITE_OR_CELL:
  548. WriteCell = OrCell;
  549. break;
  550. case WRITE_XOR_CELL:
  551. WriteCell = XorCell;
  552. break;
  553. case WRITE_AND_CELL:
  554. WriteCell = AndCell;
  555. break;
  556. case WRITE_ADD_CELL:
  557. WriteCell = AddCell;
  558. break;
  559. }
  560. ux0 -= Pcb->m_BoundaryBox.m_Pos.x;
  561. uy0 -= Pcb->m_BoundaryBox.m_Pos.y;
  562. ux1 -= Pcb->m_BoundaryBox.m_Pos.x;
  563. uy1 -= Pcb->m_BoundaryBox.m_Pos.y;
  564. cx = (ux0 + ux1) / 2;
  565. cy = (uy0 + uy1) / 2;
  566. rayon = (int) sqrt( (double) ( cx - ux0 ) * ( cx - ux0 )
  567. + (double) ( cy - uy0 ) * ( cy - uy0 ) );
  568. /* Calculating coordinate limits belonging to the rectangle. */
  569. row_max = ( cy + rayon ) / g_GridRoutingSize;
  570. col_max = ( cx + rayon ) / g_GridRoutingSize;
  571. row_min = ( cy - rayon ) / g_GridRoutingSize;
  572. if( uy0 > row_min * g_GridRoutingSize )
  573. row_min++;
  574. col_min = ( cx - rayon ) / g_GridRoutingSize;
  575. if( ux0 > col_min * g_GridRoutingSize )
  576. col_min++;
  577. if( row_min < 0 )
  578. row_min = 0;
  579. if( row_max >= ( Nrows - 1 ) )
  580. row_max = Nrows - 1;
  581. if( col_min < 0 )
  582. col_min = 0;
  583. if( col_max >= ( Ncols - 1 ) )
  584. col_max = Ncols - 1;
  585. for( row = row_min; row <= row_max; row++ )
  586. {
  587. for( col = col_min; col <= col_max; col++ )
  588. {
  589. rotrow = row * g_GridRoutingSize;
  590. rotcol = col * g_GridRoutingSize;
  591. RotatePoint( &rotcol, &rotrow, cx, cy, -angle );
  592. if( rotrow <= uy0 )
  593. continue;
  594. if( rotrow >= uy1 )
  595. continue;
  596. if( rotcol <= ux0 )
  597. continue;
  598. if( rotcol >= ux1 )
  599. continue;
  600. if( trace & 1 )
  601. WriteCell( row, col, BOTTOM, color );
  602. if( trace & 2 )
  603. WriteCell( row, col, TOP, color );
  604. }
  605. }
  606. }
  607. /* Fills all cells BOARD contained in the segment
  608. * half-width lg, org ux, ux end y0, y1 is set to color.
  609. * coordinates in PCB units (0.1 million) relating to the origin
  610. * pt_pcb-> m_PcbBox.m_Xmin, Y's board.
  611. */
  612. void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer,
  613. int color, int op_logique )
  614. {
  615. int row, col;
  616. int inc;
  617. int row_max, col_max, row_min, col_min;
  618. int demi_pas;
  619. void (* WriteCell)( int, int, int, BoardCell );
  620. int angle;
  621. int cx, cy, dx, dy;
  622. switch( op_logique )
  623. {
  624. default:
  625. case WRITE_CELL:
  626. WriteCell = SetCell;
  627. break;
  628. case WRITE_OR_CELL:
  629. WriteCell = OrCell;
  630. break;
  631. case WRITE_XOR_CELL:
  632. WriteCell = XorCell;
  633. break;
  634. case WRITE_AND_CELL:
  635. WriteCell = AndCell;
  636. break;
  637. case WRITE_ADD_CELL:
  638. WriteCell = AddCell;
  639. break;
  640. }
  641. /* Make coordinate ux1 tj > ux0 to simplify calculations */
  642. if( ux1 < ux0 )
  643. {
  644. EXCHG( ux1, ux0 );
  645. EXCHG( uy1, uy0 );
  646. }
  647. /* Calculating the incrementing the Y axis */
  648. inc = 1;
  649. if( uy1 < uy0 )
  650. inc = -1;
  651. demi_pas = g_GridRoutingSize / 2;
  652. col_min = ( ux0 - lg ) / g_GridRoutingSize;
  653. if( col_min < 0 )
  654. col_min = 0;
  655. col_max = ( ux1 + lg + demi_pas ) / g_GridRoutingSize;
  656. if( col_max > ( Ncols - 1 ) )
  657. col_max = Ncols - 1;
  658. if( inc > 0 )
  659. {
  660. row_min = ( uy0 - lg ) / g_GridRoutingSize;
  661. row_max = ( uy1 + lg + demi_pas ) / g_GridRoutingSize;
  662. }
  663. else
  664. {
  665. row_min = ( uy1 - lg ) / g_GridRoutingSize;
  666. row_max = ( uy0 + lg + demi_pas ) / g_GridRoutingSize;
  667. }
  668. if( row_min < 0 )
  669. row_min = 0;
  670. if( row_min > ( Nrows - 1 ) )
  671. row_min = Nrows - 1;
  672. if( row_max < 0 )
  673. row_max = 0;
  674. if( row_max > ( Nrows - 1 ) )
  675. row_max = Nrows - 1;
  676. dx = ux1 - ux0;
  677. dy = uy1 - uy0;
  678. if( dx )
  679. angle = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI );
  680. else
  681. {
  682. angle = 900;
  683. if( dy < 0 )
  684. angle = -900;
  685. }
  686. RotatePoint( &dx, &dy, angle ); /* dx = length, dy = 0 */
  687. for( col = col_min; col <= col_max; col++ )
  688. {
  689. int cxr;
  690. cxr = ( col * g_GridRoutingSize ) - ux0;
  691. for( row = row_min; row <= row_max; row++ )
  692. {
  693. cy = (row * g_GridRoutingSize) - uy0;
  694. cx = cxr;
  695. RotatePoint( &cx, &cy, angle );
  696. if( abs( cy ) > lg )
  697. continue; /* The point is too far on the Y axis. */
  698. /* This point a test is close to the segment: the position
  699. * along the X axis must be tested.
  700. */
  701. if( ( cx >= 0 ) && ( cx <= dx ) )
  702. {
  703. OP_CELL( layer, row, col );
  704. continue;
  705. }
  706. /* Examination of extremities are rounded. */
  707. if( ( cx < 0 ) && ( cx >= -lg ) )
  708. {
  709. if( ( ( cx * cx ) + ( cy * cy ) ) <= ( lg * lg ) )
  710. OP_CELL( layer, row, col );
  711. continue;
  712. }
  713. if( ( cx > dx ) && ( cx <= ( dx + lg ) ) )
  714. {
  715. if( ( ( ( cx - dx ) * ( cx - dx ) ) + ( cy * cy ) )
  716. <= ( lg * lg ) )
  717. OP_CELL( layer, row, col );
  718. continue;
  719. }
  720. }
  721. }
  722. }
  723. /* Fills all cells BOARD contained in the circle
  724. * half-width lg center ux, ux through y0, y1 is set to color.
  725. * coord in PCB units (0.1 million) relating to the origin
  726. * pt_pcb-> m_PcbBox.m_Xmin, Y's board.
  727. */
  728. void TraceCercle( int ux0, int uy0, int ux1, int uy1, int lg, int layer,
  729. int color, int op_logique )
  730. {
  731. int rayon, nb_segm;
  732. int x0, y0, // Starting point of the current segment trace.
  733. x1, y1; // End point.
  734. int ii;
  735. int angle;
  736. rayon = (int) hypot( (double) (ux1 - ux0), (double) (uy1 - uy0) );
  737. x0 = x1 = rayon;
  738. y0 = y1 = 0;
  739. if( lg < 1 )
  740. lg = 1;
  741. nb_segm = ( 2 * rayon ) / lg;
  742. if( nb_segm < 5 )
  743. nb_segm = 5;
  744. if( nb_segm > 100 )
  745. nb_segm = 100;
  746. for( ii = 1; ii < nb_segm; ii++ )
  747. {
  748. angle = (3600 * ii) / nb_segm;
  749. x1 = (int) ( rayon * fcosinus[angle] );
  750. y1 = (int) ( rayon * fsinus[angle] );
  751. DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg,
  752. layer, color, op_logique );
  753. x0 = x1;
  754. y0 = y1;
  755. }
  756. DrawSegmentQcq( x1 + ux0, y1 + uy0, ux0 + rayon, uy0, lg, layer,
  757. color, op_logique );
  758. }
  759. /* Fills all cells BOARD contained in the arc of "L" angle
  760. * half-width lg ux center, starting in ux y0, y1 is set to color.
  761. * coord in PCB units (0.1 million) relating to the origin
  762. * Pt_pcb->m_PcbBox.m_Xmin, Y's board.
  763. */
  764. void TraceArc( int ux0, int uy0, int ux1, int uy1, int ArcAngle, int lg,
  765. int layer, int color, int op_logique )
  766. {
  767. int rayon, nb_segm;
  768. int x0, y0, // Starting point of the current segment trace
  769. x1, y1; // End point
  770. int ii;
  771. int angle, StAngle;
  772. rayon = (int) hypot( (double) (ux1 - ux0), (double) (uy1 - uy0) );
  773. x0 = ux1 - ux0;
  774. y0 = uy1 - uy0;
  775. StAngle = ArcTangente( uy1 - uy0, ux1 - ux0 );
  776. if( lg < 1 )
  777. lg = 1;
  778. nb_segm = ( 2 * rayon ) / lg;
  779. nb_segm = ( nb_segm * abs( ArcAngle ) ) / 3600;
  780. if( nb_segm < 5 )
  781. nb_segm = 5;
  782. if( nb_segm > 100 )
  783. nb_segm = 100;
  784. for( ii = 1; ii <= nb_segm; ii++ )
  785. {
  786. angle = ( ArcAngle * ii ) / nb_segm;
  787. angle += StAngle;
  788. while( angle >= 3600 )
  789. angle -= 3600;
  790. while( angle < 0 )
  791. angle += 3600;
  792. x1 = (int) ( rayon * fcosinus[angle] );
  793. y1 = (int) ( rayon * fsinus[angle] );
  794. DrawSegmentQcq( x0 + ux0, y0 + uy0, x1 + ux0, y1 + uy0, lg, layer,
  795. color, op_logique );
  796. x0 = x1;
  797. y0 = y1;
  798. }
  799. // DrawSegmentQcq(x1+ux0,y1+uy0, ux0+rayon, uy0,lg,layer, color,
  800. // op_logique);
  801. }