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.

905 lines
30 KiB

  1. /*******************************/
  2. /**** Routine de trace HPGL ****/
  3. /*******************************/
  4. #include "fctsys.h"
  5. #include "common.h"
  6. #include "plot_common.h"
  7. #include "pcbnew.h"
  8. #include "pcbplot.h"
  9. #include "trigo.h"
  10. #include "protos.h"
  11. /* Variables locales : */
  12. static int pen_rayon; /* Rayon de la plume en unites pcb */
  13. static int pen_diam; /* Diametre de la plume en unites pcb */
  14. static int pen_recouvrement; /* recouvrement en remplissage en unites pcb */
  15. /* Routines Locales */
  16. /*****************************************************************************/
  17. void WinEDA_BasePcbFrame::Genere_HPGL( const wxString& FullFileName, int Layer )
  18. /*****************************************************************************/
  19. {
  20. int modetrace;
  21. wxSize SheetSize;
  22. wxSize BoardSize;
  23. wxPoint BoardCenter;
  24. double scale_x, scale_y;
  25. int marge = 0 * U_PCB; // Extra margin (set to 0)
  26. bool Center = FALSE;
  27. modetrace = Plot_Mode;
  28. /* Calcul des echelles de conversion */
  29. scale_x = Scale_X * SCALE_HPGL;
  30. scale_y = Scale_Y * SCALE_HPGL;
  31. // calcul en unites internes des dimensions de la feuille ( connues en 1/1000 pouce )
  32. SheetSize.x = m_CurrentScreen->m_CurrentSheet->m_Size.x * U_PCB;
  33. SheetSize.y = m_CurrentScreen->m_CurrentSheet->m_Size.y * U_PCB;
  34. g_PlotOffset.x = 0;
  35. g_PlotOffset.y = (int) (SheetSize.y * scale_y);
  36. // Compute pen_dim (from g_HPGL_Pen_Diam in mils) in pcb units,
  37. // with plot scale (if Scale is 2, pen diametre is always g_HPGL_Pen_Diam
  38. // so apparent pen diam is real pen diam / Scale
  39. pen_diam = (int) round( (g_HPGL_Pen_Diam * U_PCB) / Scale_X ); // Assume Scale_X # Scale_Y
  40. pen_rayon = pen_diam / 2;
  41. nb_plot_erreur = 0;
  42. // compute pen_recouvrement (from g_HPGL_Pen_Recouvrement in mils)
  43. // with plot scale
  44. if( g_HPGL_Pen_Recouvrement < 0 )
  45. g_HPGL_Pen_Recouvrement = 0;
  46. if( g_HPGL_Pen_Recouvrement >= g_HPGL_Pen_Diam )
  47. g_HPGL_Pen_Recouvrement = g_HPGL_Pen_Diam - 1;
  48. pen_recouvrement = (int) round( g_HPGL_Pen_Recouvrement * 10.0 / Scale_X );
  49. dest = wxFopen( FullFileName, wxT( "wt" ) );
  50. if( dest == NULL )
  51. {
  52. wxString msg = _( "Unable to create " ) + FullFileName;
  53. DisplayError( this, msg );
  54. return;
  55. }
  56. setlocale( LC_NUMERIC, "C" );
  57. Affiche_1_Parametre( this, 0, _( "File" ), FullFileName, CYAN );
  58. PrintHeaderHPGL( dest, g_HPGL_Pen_Speed, g_HPGL_Pen_Num );
  59. if( Plot_Sheet_Ref && (g_PlotScaleOpt == 1) )
  60. {
  61. int tmp = g_PlotOrient; g_PlotOrient = 0;
  62. InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_y, g_PlotOrient );
  63. PlotWorkSheet( PLOT_FORMAT_HPGL, m_CurrentScreen );
  64. g_PlotOrient = tmp;
  65. }
  66. /* calcul des dimensions et centre du PCB */
  67. m_Pcb->ComputeBoundaryBox();
  68. BoardSize = m_Pcb->m_BoundaryBox.GetSize();
  69. BoardCenter = m_Pcb->m_BoundaryBox.Centre();
  70. if( g_PlotScaleOpt == 0 ) // Optimum scale
  71. {
  72. float Xscale, Yscale;
  73. Xscale = (float) ( SheetSize.x - ( 2 * marge) ) / BoardSize.x;
  74. Yscale = (float) ( SheetSize.y - ( 2 * marge) ) / BoardSize.y;
  75. scale_x = scale_y = MIN( Xscale, Yscale ) * SCALE_HPGL;
  76. }
  77. BoardCenter.x = (int) (BoardCenter.x * scale_x);
  78. BoardCenter.y = (int) (BoardCenter.y * scale_y);
  79. if( g_PlotScaleOpt != 1 )
  80. Center = TRUE; // Echelle != 1
  81. /* Calcul du cadrage */
  82. marge = (int) (marge * SCALE_HPGL);
  83. if( Center )
  84. g_PlotOffset.x = (int) (-SheetSize.x / 2 * SCALE_HPGL) +
  85. BoardCenter.x + marge;
  86. switch( g_PlotOrient )
  87. {
  88. default:
  89. if( Center )
  90. {
  91. g_PlotOffset.y = (int) (SheetSize.y / 2 * SCALE_HPGL) +
  92. BoardCenter.y + marge;
  93. }
  94. break;
  95. case PLOT_MIROIR:
  96. if( Center )
  97. g_PlotOffset.y = (int) (-SheetSize.y / 2 * SCALE_HPGL) + BoardCenter.y;
  98. else
  99. g_PlotOffset.y = (int) ( ( -SheetSize.y +
  100. m_Pcb->m_BoundaryBox.GetBottom() +
  101. m_Pcb->m_BoundaryBox.GetY() ) * SCALE_HPGL );
  102. break;
  103. }
  104. InitPlotParametresHPGL( g_PlotOffset, scale_x, scale_y, g_PlotOrient );
  105. // Specify that the contents of the "Edges Pcb" layer are to be plotted
  106. // in addition to the contents of the currently specified layer.
  107. int layer_mask = g_TabOneLayerMask[Layer] | EDGE_LAYER;
  108. switch( Layer )
  109. {
  110. case CUIVRE_N:
  111. case LAYER_N_2:
  112. case LAYER_N_3:
  113. case LAYER_N_4:
  114. case LAYER_N_5:
  115. case LAYER_N_6:
  116. case LAYER_N_7:
  117. case LAYER_N_8:
  118. case LAYER_N_9:
  119. case LAYER_N_10:
  120. case LAYER_N_11:
  121. case LAYER_N_12:
  122. case LAYER_N_13:
  123. case LAYER_N_14:
  124. case LAYER_N_15:
  125. case CMP_N:
  126. Plot_Layer_HPGL( dest, layer_mask, 0, 1, modetrace );
  127. break;
  128. case SILKSCREEN_N_CU:
  129. case SILKSCREEN_N_CMP:
  130. Plot_Serigraphie( PLOT_FORMAT_HPGL, dest, layer_mask );
  131. break;
  132. case SOLDERMASK_N_CU:
  133. case SOLDERMASK_N_CMP: /* Trace du vernis epargne */
  134. {
  135. int tracevia;
  136. if( g_DrawViaOnMaskLayer )
  137. tracevia = 1;
  138. else
  139. tracevia = 0;
  140. Plot_Layer_HPGL( dest, layer_mask,
  141. g_DesignSettings.m_MaskMargin, tracevia, modetrace );
  142. }
  143. break;
  144. case SOLDERPASTE_N_CU:
  145. case SOLDERPASTE_N_CMP: /* Trace du masque de pate de soudure */
  146. Plot_Layer_HPGL( dest, layer_mask, 0, 0, modetrace );
  147. break;
  148. default: /* Trace des autres couches (dessin, adhesives,eco,comment) */
  149. Plot_Serigraphie( PLOT_FORMAT_HPGL, dest, layer_mask );
  150. break;
  151. }
  152. /* fin */
  153. CloseFileHPGL( dest );
  154. setlocale( LC_NUMERIC, "" );
  155. }
  156. /*********************************************************************/
  157. void WinEDA_BasePcbFrame::Plot_Layer_HPGL( FILE* File, int masque_layer,
  158. int garde, int tracevia, int modetrace )
  159. /*********************************************************************/
  160. /* Trace en format HPGL. d'une couche cuivre ou masque
  161. * 1 unite HPGL = 0.98 mils ( 1 mil = 1.02041 unite HPGL ) .
  162. */
  163. {
  164. wxSize size;
  165. wxPoint start, end;
  166. MODULE* Module;
  167. D_PAD* PtPad;
  168. TRACK* pts;
  169. BOARD_ITEM* PtStruct;
  170. wxString msg;
  171. // (Following command has been superceded by new command on line 135.)
  172. // masque_layer |= EDGE_LAYER; /* Les elements de la couche EDGE sont tj traces */
  173. /* trace des elements type Drawings Pcb : */
  174. PtStruct = m_Pcb->m_Drawings;
  175. for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
  176. {
  177. switch( PtStruct->Type() )
  178. {
  179. case TYPEDRAWSEGMENT:
  180. PlotDrawSegment( (DRAWSEGMENT*) PtStruct, PLOT_FORMAT_HPGL,
  181. masque_layer );
  182. break;
  183. case TYPETEXTE:
  184. PlotTextePcb( (TEXTE_PCB*) PtStruct, PLOT_FORMAT_HPGL,
  185. masque_layer );
  186. break;
  187. case TYPECOTATION:
  188. PlotCotation( (COTATION*) PtStruct, PLOT_FORMAT_HPGL,
  189. masque_layer );
  190. break;
  191. case TYPEMIRE:
  192. PlotMirePcb( (MIREPCB*) PtStruct, PLOT_FORMAT_HPGL,
  193. masque_layer );
  194. break;
  195. case TYPEMARQUEUR:
  196. break;
  197. default:
  198. DisplayError( this, wxT( "Type Draw non gere" ) );
  199. break;
  200. }
  201. }
  202. /* Trace des Elements des modules autres que pads */
  203. nb_items = 0;
  204. Affiche_1_Parametre( this, 48, wxT( "DrawMod" ), wxEmptyString, GREEN );
  205. Module = m_Pcb->m_Modules;
  206. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  207. {
  208. PtStruct = Module->m_Drawings;
  209. for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
  210. {
  211. switch( PtStruct->Type() )
  212. {
  213. case TYPEEDGEMODULE:
  214. if( masque_layer &
  215. g_TabOneLayerMask[ PtStruct->GetLayer() ] )
  216. Plot_1_EdgeModule( PLOT_FORMAT_HPGL, (EDGE_MODULE*) PtStruct );
  217. break;
  218. default:
  219. break;
  220. }
  221. }
  222. }
  223. /* Trace des Elements des modules : Pastilles */
  224. nb_items = 0;
  225. Affiche_1_Parametre( this, 48, wxT( "Pads " ), wxEmptyString, GREEN );
  226. Module = m_Pcb->m_Modules;
  227. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  228. {
  229. PtPad = (D_PAD*) Module->m_Pads;
  230. for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
  231. {
  232. wxPoint shape_pos;
  233. if( (PtPad->m_Masque_Layer & masque_layer) == 0 )
  234. continue;
  235. shape_pos = PtPad->ReturnShapePos();
  236. start = shape_pos;
  237. size = PtPad->m_Size;
  238. size.x += garde * 2; size.y += garde * 2;
  239. nb_items++;
  240. switch( PtPad->m_PadShape & 0x7F )
  241. {
  242. case CIRCLE:
  243. trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );
  244. break;
  245. case OVALE:
  246. {
  247. trace_1_pastille_OVALE_HPGL( start, size, PtPad->m_Orient, modetrace );
  248. break;
  249. }
  250. case TRAPEZE:
  251. {
  252. wxSize delta;
  253. delta = PtPad->m_DeltaSize;
  254. trace_1_pad_TRAPEZE_HPGL( start, size, delta,
  255. PtPad->m_Orient, modetrace );
  256. break;
  257. }
  258. case RECT:
  259. default:
  260. PlotRectangularPad_HPGL( start, size,
  261. PtPad->m_Orient, modetrace );
  262. break;
  263. }
  264. msg.Printf( wxT( "%d" ), nb_items );
  265. Affiche_1_Parametre( this, 48, wxT( "Pads" ), msg, GREEN );
  266. }
  267. }
  268. /* trace des VIAS : */
  269. if( tracevia )
  270. {
  271. TRACK* pts;
  272. nb_items = 0;
  273. Affiche_1_Parametre( this, 56, wxT( "Vias" ), wxEmptyString, RED );
  274. for( pts = m_Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext )
  275. {
  276. if( pts->Type() != TYPEVIA )
  277. continue;
  278. SEGVIA* Via = (SEGVIA*) pts;
  279. /* vias not plotted if not on selected layer, but if layer
  280. * == SOLDERMASK_LAYER_CU or SOLDERMASK_LAYER_CMP, vias are drawn ,
  281. * if they are on a external copper layer
  282. */
  283. int via_mask_layer = Via->ReturnMaskLayer();
  284. if( (via_mask_layer & CUIVRE_LAYER ) )
  285. via_mask_layer |= SOLDERMASK_LAYER_CU;
  286. if( (via_mask_layer & CMP_LAYER ) )
  287. via_mask_layer |= SOLDERMASK_LAYER_CMP;
  288. if( (via_mask_layer & masque_layer) == 0 )
  289. continue;
  290. start = Via->m_Start;
  291. size.x = Via->m_Width + (garde * 2);
  292. trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );
  293. nb_items++; msg.Printf( wxT( "%d" ), nb_items );
  294. Affiche_1_Parametre( this, 56, wxT( "Vias" ), msg, RED );
  295. }
  296. fputs( "PU;\n", dest );
  297. }
  298. /* trace des segments pistes */
  299. nb_items = 0;
  300. Affiche_1_Parametre( this, 64, wxT( "Tracks " ), wxEmptyString, YELLOW );
  301. for( pts = m_Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext )
  302. {
  303. if( pts->Type() == TYPEVIA )
  304. continue;
  305. if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) == 0 )
  306. continue;
  307. size.x = size.y = pts->m_Width;
  308. start = pts->m_Start;
  309. end = pts->m_End;
  310. if( size.x > pen_diam ) /* c.a.d si largeur piste > diam plume */
  311. trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );
  312. /* Trace d'un segment de piste */
  313. trace_1_segment_HPGL( start.x, start.y, end.x, end.y, size.x );
  314. /* Complement de Trace en mode Remplissage */
  315. if( (Plot_Mode == FILLED) && (pen_diam <= size.x ) )
  316. {
  317. while( ( size.x -= (int) ( (pen_rayon - pen_recouvrement) * 2 ) ) > 0 )
  318. {
  319. trace_1_segment_HPGL( start.x, start.y, end.x, end.y,
  320. MAX( size.x, pen_diam ) );
  321. }
  322. }
  323. if( size.x > pen_diam )
  324. trace_1_pastille_RONDE_HPGL( end, size.x, modetrace );
  325. nb_items++; msg.Printf( wxT( "%d" ), nb_items );
  326. Affiche_1_Parametre( this, 64, wxEmptyString, msg, YELLOW );
  327. }
  328. /* trace des segments pistes et zones */
  329. nb_items = 0;
  330. Affiche_1_Parametre( this, 64, wxT( "Zones " ), wxEmptyString, YELLOW );
  331. for( pts = m_Pcb->m_Zone; pts != NULL; pts = (TRACK*) pts->Pnext )
  332. {
  333. if( g_TabOneLayerMask[pts->GetLayer()] & masque_layer )
  334. {
  335. size.x = size.y = pts->m_Width;
  336. start = pts->m_Start;
  337. end = pts->m_End;
  338. if( size.x > pen_diam ) /* c.a.d si largeur piste > diam plume */
  339. trace_1_pastille_RONDE_HPGL( start, size.x, modetrace );
  340. /* Trace d'un segment de piste */
  341. trace_1_segment_HPGL( start.x, start.y, end.x, end.y, size.x );
  342. /* Complement de Trace en mode Remplissage */
  343. if( (Plot_Mode == FILLED) && (pen_diam <= size.x ) )
  344. {
  345. while( ( size.x -= (int) ( (pen_rayon - pen_recouvrement) * 2 ) ) > 0 )
  346. {
  347. trace_1_segment_HPGL( start.x, start.y, end.x, end.y,
  348. MAX( size.x, pen_diam ) );
  349. }
  350. }
  351. if( size.x > pen_diam )
  352. trace_1_pastille_RONDE_HPGL( end, size.x, modetrace );
  353. nb_items++; msg.Printf( wxT( "%d" ), nb_items );
  354. Affiche_1_Parametre( this, 64, wxEmptyString, msg, YELLOW );
  355. }
  356. }
  357. }
  358. /************************************************************************************/
  359. void trace_1_pastille_OVALE_HPGL( wxPoint pos, wxSize size, int orient, int modetrace )
  360. /************************************************************************************/
  361. /* Trace 1 pastille OVALE en position pos_X,Y , de dim size.x, size.y */
  362. {
  363. int rayon, deltaxy, cx, cy;
  364. int trace_orient = orient;
  365. /* la pastille est ramenee a une pastille ovale avec size.y > size.x
  366. * ( ovale vertical en orientation 0 ) */
  367. if( size.x > size.y )
  368. {
  369. EXCHG( size.x, size.y ); trace_orient += 900;
  370. if( orient >= 3600 )
  371. trace_orient -= 3600;
  372. }
  373. deltaxy = size.y - size.x; /* = distance entre centres de l'ovale */
  374. rayon = size.x / 2;
  375. if( modetrace == FILLED )
  376. {
  377. PlotRectangularPad_HPGL( pos, wxSize( size.x, deltaxy ),
  378. orient, modetrace );
  379. cx = 0; cy = deltaxy / 2;
  380. RotatePoint( &cx, &cy, trace_orient );
  381. trace_1_pastille_RONDE_HPGL( wxPoint( cx + pos.x, cy + pos.y ), size.x, modetrace );
  382. Plume_HPGL( 'U' );
  383. cx = 0; cy = -deltaxy / 2;
  384. RotatePoint( &cx, &cy, trace_orient );
  385. trace_1_pastille_RONDE_HPGL( wxPoint( cx + pos.x, cy + pos.y ), size.x, modetrace );
  386. }
  387. else /* Trace en mode FILAIRE */
  388. {
  389. cx = -rayon; cy = -deltaxy / 2;
  390. RotatePoint( &cx, &cy, trace_orient );
  391. Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'U' );
  392. cx = -rayon; cy = deltaxy / 2;
  393. RotatePoint( &cx, &cy, trace_orient );
  394. Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'D' );
  395. cx = rayon; cy = -deltaxy / 2;
  396. RotatePoint( &cx, &cy, trace_orient );
  397. Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'U' );
  398. cx = rayon; cy = deltaxy / 2;
  399. RotatePoint( &cx, &cy, trace_orient );
  400. Move_Plume_HPGL( wxPoint( cx + pos.x, cy + pos.y ), 'D' );
  401. Plume_HPGL( 'U' );
  402. cx = 0; cy = -deltaxy / 2;
  403. RotatePoint( &cx, &cy, trace_orient );
  404. PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ),
  405. trace_orient, trace_orient + 1800,
  406. size.x / 2, pen_diam );
  407. cx = 0; cy = deltaxy / 2;
  408. RotatePoint( &cx, &cy, trace_orient );
  409. PlotArc( PLOT_FORMAT_HPGL, wxPoint( cx + pos.x, cy + pos.y ),
  410. trace_orient + 1800, trace_orient,
  411. size.x / 2, pen_diam );
  412. }
  413. Plume_HPGL( 'U' );
  414. }
  415. /**************************************************************************/
  416. void trace_1_pastille_RONDE_HPGL( wxPoint pos, int diametre, int modetrace )
  417. /**************************************************************************/
  418. /* Trace 1 pastille RONDE (via,pad rond) en position pos */
  419. {
  420. int rayon, delta;
  421. UserToDeviceCoordinate( pos );
  422. delta = pen_diam - pen_recouvrement;
  423. rayon = diametre / 2;
  424. if( modetrace != FILAIRE )
  425. {
  426. rayon = (diametre - pen_diam ) / 2;
  427. }
  428. if( rayon < 0 )
  429. {
  430. rayon = 0; nb_plot_erreur++; Affiche_erreur( nb_plot_erreur );
  431. }
  432. wxSize rsize( rayon, rayon );
  433. UserToDeviceSize( rsize );
  434. Plume_HPGL( 'U' );
  435. sprintf( cbuf, "PA %d,%d;CI %d;\n", pos.x, pos.y, rsize.x );
  436. fputs( cbuf, dest );
  437. if( modetrace == FILLED ) /* Trace en mode Remplissage */
  438. {
  439. if( delta > 0 )
  440. {
  441. while( (rayon -= delta ) >= 0 )
  442. {
  443. rsize.x = rsize.y = rayon;
  444. UserToDeviceSize( rsize );
  445. sprintf( cbuf, "PA %d,%d; CI %d;\n", pos.x, pos.y, rsize.x );
  446. fputs( cbuf, dest );
  447. }
  448. }
  449. }
  450. Plume_HPGL( 'U' ); return;
  451. }
  452. /***************************************************************/
  453. void PlotRectangularPad_HPGL( wxPoint padpos, wxSize padsize,
  454. int orient, int modetrace )
  455. /****************************************************************/
  456. /*
  457. * Trace 1 pad rectangulaire vertical ou horizontal ( Pad rectangulaire )
  458. * donne par son centre et ses dimensions X et Y
  459. * Units are user units
  460. */
  461. {
  462. wxSize size;
  463. int delta;
  464. int ox, oy, fx, fy;
  465. size.x = padsize.x / 2; size.y = padsize.y / 2;
  466. if( modetrace != FILAIRE )
  467. {
  468. size.x = (padsize.x - (int) pen_diam) / 2;
  469. size.y = (padsize.y - (int) pen_diam) / 2;
  470. }
  471. if( (size.x < 0 ) || (size.y < 0) )
  472. {
  473. nb_plot_erreur++; Affiche_erreur( nb_plot_erreur );
  474. }
  475. if( size.x < 0 )
  476. size.x = 0;if( size.y < 0 )
  477. size.y = 0;
  478. /* Si une des dimensions est nulle, le trace se reduit a 1 trait */
  479. if( size.x == 0 )
  480. {
  481. ox = padpos.x; oy = padpos.y - size.y;
  482. RotatePoint( &ox, &oy, padpos.x, padpos.y, orient );
  483. fx = padpos.x; fy = padpos.y + size.y;
  484. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  485. Move_Plume_HPGL( wxPoint( ox, oy ), 'U' );
  486. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  487. Plume_HPGL( 'U' ); return;
  488. }
  489. if( size.y == 0 )
  490. {
  491. ox = padpos.x - size.x; oy = padpos.y;
  492. RotatePoint( &ox, &oy, padpos.x, padpos.y, orient );
  493. fx = padpos.x + size.x; fy = padpos.y;
  494. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  495. Move_Plume_HPGL( wxPoint( ox, oy ), 'U' );
  496. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  497. Plume_HPGL( 'U' ); return;
  498. }
  499. ox = padpos.x - size.x; oy = padpos.y - size.y;
  500. RotatePoint( &ox, &oy, padpos.x, padpos.y, orient );
  501. Move_Plume_HPGL( wxPoint( ox, oy ), 'U' );
  502. fx = padpos.x - size.x; fy = padpos.y + size.y;
  503. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  504. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  505. fx = padpos.x + size.x; fy = padpos.y + size.y;
  506. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  507. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  508. fx = padpos.x + size.x; fy = padpos.y - size.y;
  509. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  510. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  511. Move_Plume_HPGL( wxPoint( ox, oy ), 'D' );
  512. if( modetrace != FILLED )
  513. {
  514. Plume_HPGL( 'U' ); return;
  515. }
  516. /* Trace en mode Remplissage */
  517. delta = (int) (pen_diam - pen_recouvrement);
  518. if( delta > 0 )
  519. while( (size.x > 0) && (size.y > 0) )
  520. {
  521. size.x -= delta; size.y -= delta;
  522. if( size.x < 0 )
  523. size.x = 0;if( size.y < 0 )
  524. size.y = 0;
  525. ox = padpos.x - size.x; oy = padpos.y - size.y;
  526. RotatePoint( &ox, &oy, padpos.x, padpos.y, orient );
  527. Move_Plume_HPGL( wxPoint( ox, oy ), 'D' );
  528. fx = padpos.x - size.x; fy = padpos.y + size.y;
  529. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  530. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  531. fx = padpos.x + size.x; fy = padpos.y + size.y;
  532. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  533. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  534. fx = padpos.x + size.x; fy = padpos.y - size.y;
  535. RotatePoint( &fx, &fy, padpos.x, padpos.y, orient );
  536. Move_Plume_HPGL( wxPoint( fx, fy ), 'D' );
  537. Move_Plume_HPGL( wxPoint( ox, oy ), 'D' );
  538. }
  539. Plume_HPGL( 'U' );
  540. }
  541. /********************************************************************/
  542. void trace_1_pad_TRAPEZE_HPGL( wxPoint padpos, wxSize size, wxSize delta,
  543. int orient, int modetrace )
  544. /********************************************************************/
  545. /*
  546. * Trace 1 pad trapezoidal donne par :
  547. * son centre padpos.x,padpos.y
  548. * ses dimensions dimX et dimY
  549. * les variations deltaX et deltaY
  550. * son orientation orient et 0.1 degres
  551. * le mode de trace (FILLED, SKETCH, FILAIRE)
  552. * Le trace n'est fait que pour un trapeze, c.a.d que deltaX ou deltaY
  553. * = 0.
  554. *
  555. * les notation des sommets sont ( vis a vis de la table tracante )
  556. * 0 ------------- 3
  557. * . .
  558. * . .
  559. * . .
  560. * 1 --- 2
  561. */
  562. {
  563. int ii, jj;
  564. wxPoint polygone[4]; /* coord des sommets / centre du pad */
  565. wxPoint coord[4]; /* coord reelles des sommets du trapeze a tracer */
  566. float fangle; /* angle d'inclinaison des cotes du trapeze */
  567. int rayon; /* rayon de la plume */
  568. int moveX, moveY;/* variation de position plume selon axe X et Y , lors
  569. * du remplissage du trapeze */
  570. rayon = (int) pen_rayon; if( modetrace == FILAIRE )
  571. rayon = 0;
  572. moveX = moveY = rayon;
  573. size.x /= 2; size.y /= 2;
  574. delta.x /= 2; delta.y /= 2;
  575. polygone[0].x = -size.x - delta.y; polygone[0].y = +size.y + delta.x;
  576. polygone[1].x = -size.x + delta.y; polygone[1].y = -size.y - delta.x;
  577. polygone[2].x = +size.x - delta.y; polygone[2].y = -size.y + delta.x;
  578. polygone[3].x = +size.x + delta.y; polygone[3].y = +size.y - delta.x;
  579. /* Calcul du demi angle d'inclinaison des cotes du trapeze */
  580. if( delta.y ) /* Trapeze horizontal */
  581. {
  582. fangle = atan2( (float) (polygone[1].y - polygone[0].y),
  583. (float) (polygone[1].x - polygone[0].x) ) / 2;
  584. }
  585. else
  586. {
  587. fangle = atan2( (float) (polygone[3].y - polygone[0].y),
  588. (float) (polygone[3].x - polygone[0].x) ) / 2;
  589. }
  590. /* Trace du contour */
  591. polygone[0].x += moveX; polygone[0].y -= moveY;
  592. polygone[1].x += moveX; polygone[1].y += moveY;
  593. polygone[2].x -= moveX; polygone[2].y += moveY;
  594. polygone[3].x -= moveX; polygone[3].y -= moveY;
  595. for( ii = 0; ii < 4; ii++ )
  596. {
  597. coord[ii].x = polygone[ii].x + padpos.x;
  598. coord[ii].y = polygone[ii].y + padpos.y;
  599. RotatePoint( &coord[ii], padpos, orient );
  600. }
  601. // Plot edge:
  602. Move_Plume_HPGL( coord[0], 'U' );
  603. Move_Plume_HPGL( coord[1], 'D' );
  604. Move_Plume_HPGL( coord[2], 'D' );
  605. Move_Plume_HPGL( coord[3], 'D' );
  606. Move_Plume_HPGL( coord[0], 'D' );
  607. if( modetrace != FILLED )
  608. {
  609. Plume_HPGL( 'U' ); return;
  610. }
  611. /* Fill the shape */
  612. moveX = moveY = pen_diam - pen_recouvrement;
  613. /* calcul de jj = hauteur du remplissage */
  614. if( delta.y ) /* Trapeze horizontal */
  615. {
  616. jj = size.y - (int) ( pen_diam + (2 * pen_recouvrement) );
  617. }
  618. else
  619. {
  620. jj = size.x - (int) ( pen_diam + (2 * pen_recouvrement) );
  621. }
  622. /* Calcul de jj = nombre de segments a tracer pour le remplissage */
  623. jj = jj / (int) (pen_diam - pen_recouvrement);
  624. /* Trace du contour */
  625. for( ; jj > 0; jj-- )
  626. {
  627. polygone[0].x += moveX; polygone[0].y -= moveY;
  628. polygone[1].x += moveX; polygone[1].y += moveY;
  629. polygone[2].x -= moveX; polygone[2].y += moveY;
  630. polygone[3].x -= moveX; polygone[3].y -= moveY;
  631. /* Test de limitation de variation des dimensions :
  632. * si les sommets se "croisent", il ne faut plus modifier les
  633. * coordonnees correspondantes */
  634. if( polygone[0].x > polygone[3].x )
  635. { /* croisement sur axe X des 2 sommets 0 et 3 */
  636. polygone[0].x = polygone[3].x = 0;
  637. }
  638. if( polygone[1].x > polygone[2].x )
  639. { /* croisement sur axe X des 2 sommets 1 et 2 */
  640. polygone[1].x = polygone[2].x = 0;
  641. }
  642. if( polygone[1].y > polygone[0].y )
  643. { /* croisement sur axe Y des 2 sommets 0 et 1 */
  644. polygone[0].y = polygone[1].y = 0;
  645. }
  646. if( polygone[2].y > polygone[3].y )
  647. { /* croisement sur axe Y des 2 sommets 2 et 3 */
  648. polygone[2].y = polygone[3].y = 0;
  649. }
  650. for( ii = 0; ii < 4; ii++ )
  651. {
  652. coord[ii].x = polygone[ii].x + padpos.x;
  653. coord[ii].y = polygone[ii].y + padpos.y;
  654. RotatePoint( &coord[ii], padpos, orient );
  655. }
  656. Move_Plume_HPGL( coord[0], 'U' );
  657. Move_Plume_HPGL( coord[1], 'D' );
  658. Move_Plume_HPGL( coord[2], 'D' );
  659. Move_Plume_HPGL( coord[3], 'D' );
  660. Move_Plume_HPGL( coord[0], 'D' );
  661. }
  662. Plume_HPGL( 'U' );
  663. }
  664. /********************************************************************/
  665. void trace_1_segment_HPGL( int pos_X0, int pos_Y0, int pos_X1, int pos_Y1,
  666. int epaisseur )
  667. /********************************************************************/
  668. /* Trace 1 rectangle donne par son axe et son epaisseur (piste rectangulaire)
  669. * en mode SKETCH
  670. */
  671. {
  672. float alpha; /* angle de l'axe du rectangle */
  673. wxSize size; /* coord relatives a l'origine du segment de sa fin */
  674. int dh; /* demi epaisseur du segment compte tenu de la
  675. * largeur de la plume */
  676. int dx_rot; /* coord du segment en repere modifie ( size.y_rot etant nul )*/
  677. float sin_alpha, cos_alpha;
  678. size.x = pos_X1 - pos_X0; size.y = pos_Y1 - pos_Y0;
  679. dh = (epaisseur - (int) pen_diam ) / 2;
  680. if( dh < 0 )
  681. {
  682. dh = 0; nb_plot_erreur++; Affiche_erreur( nb_plot_erreur );
  683. }
  684. if( (dh == 0) || (Plot_Mode == FILAIRE) ) /* Le trace se reduit a 1 trait */
  685. {
  686. Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 ), 'U' );
  687. Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 ), 'D' );
  688. Plume_HPGL( 'U' );
  689. return;
  690. }
  691. if( size.x < 0 )
  692. {
  693. EXCHG( pos_X0, pos_X1 ); EXCHG( pos_Y0, pos_Y1 );
  694. size.y = -size.y; size.x = -size.x;
  695. }
  696. if( size.y == 0 ) /* segment horizontal */
  697. {
  698. Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 - dh ), 'U' );
  699. Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 - dh ), 'D' );
  700. Move_Plume_HPGL( wxPoint( pos_X1, pos_Y1 + dh ), 'D' );
  701. Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 + dh ), 'D' );
  702. Move_Plume_HPGL( wxPoint( pos_X0, pos_Y0 - dh ), 'D' );
  703. }
  704. else if( size.x == 0 ) /* vertical */
  705. {
  706. if( size.y < 0 )
  707. dh = -dh;
  708. Move_Plume_HPGL( wxPoint( pos_X0 - dh, pos_Y0 ), 'U' );
  709. Move_Plume_HPGL( wxPoint( pos_X1 - dh, pos_Y1 ), 'D' );
  710. Move_Plume_HPGL( wxPoint( pos_X1 + dh, pos_Y1 ), 'D' );
  711. Move_Plume_HPGL( wxPoint( pos_X0 + dh, pos_Y0 ), 'D' );
  712. Move_Plume_HPGL( wxPoint( pos_X0 - dh, pos_Y0 ), 'D' );
  713. }
  714. else /* piste inclinee */
  715. {
  716. /* On calcule les coord des extremites du rectangle dans le repere
  717. * a axe x confondu avec l'axe du rect. puis on revient dans le repere
  718. * de trace par 2 rotations inverses
  719. * coord : xrot = x*cos + y*sin
  720. * yrot = y*cos - x*sin
  721. *
  722. * avec ici yrot = 0 puisque le segment est horizontal dans le nouveau repere
  723. * Transformee inverse :
  724. * coord : x = xrot*cos - yrot*sin
  725. * y = yrot*cos + xrot*sin
  726. */
  727. int dx0, dy0, dx1, dy1;
  728. if( size.x == size.y ) /* alpah = 45 degre */
  729. {
  730. sin_alpha = cos_alpha = 0.70711;
  731. }
  732. else if( size.x == -size.y ) /* alpah = -45 degre */
  733. {
  734. cos_alpha = 0.70711; sin_alpha = -0.70711;
  735. }
  736. else
  737. {
  738. alpha = atan2( (float) size.y, (float) size.x );
  739. sin_alpha = sin( alpha );
  740. cos_alpha = cos( alpha );
  741. }
  742. dx_rot = (int) (size.x * cos_alpha + size.y * sin_alpha);
  743. /* size.y_rot = (int)(size.y * cos_alpha - size.x * sin_alpha) ; doit etre NULL */
  744. /* calcul du point de coord 0,-dh */
  745. dx0 = (int) ( dh * sin_alpha);
  746. dy0 = (int) (-dh * cos_alpha );
  747. Move_Plume_HPGL( wxPoint( pos_X0 + dx0, pos_Y0 + dy0 ), 'U' );
  748. /* calcul du point de coord size.xrot,-dh */
  749. dx1 = (int) (dx_rot * cos_alpha + dh * sin_alpha);
  750. dy1 = (int) (-dh * cos_alpha + dx_rot * sin_alpha );
  751. Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );
  752. /* calcul du point de coord size.xrot,+dh */
  753. dx1 = (int) (dx_rot * cos_alpha - dh * sin_alpha);
  754. dy1 = (int) (dh * cos_alpha + dx_rot * sin_alpha );
  755. Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );
  756. /* calcul du point de coord 0,+dh */
  757. dx1 = (int) ( -dh * sin_alpha);
  758. dy1 = (int) (dh * cos_alpha );
  759. Move_Plume_HPGL( wxPoint( pos_X0 + dx1, pos_Y0 + dy1 ), 'D' );
  760. /* retour au point de depart */
  761. Move_Plume_HPGL( wxPoint( pos_X0 + dx0, pos_Y0 + dy0 ), 'D' );
  762. }
  763. Plume_HPGL( 'U' );
  764. }