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.

543 lines
15 KiB

  1. /****************************************************/
  2. /* class_module.cpp : fonctions de la classe MODULE */
  3. /****************************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "wxstruct.h"
  7. #include "common.h"
  8. #include "trigo.h"
  9. #ifdef PCBNEW
  10. #include "pcbnew.h"
  11. #include "autorout.h"
  12. #include "drag.h"
  13. #endif
  14. #ifdef CVPCB
  15. #include "cvpcb.h"
  16. #endif
  17. #include "protos.h"
  18. #define MAX_WIDTH 10000 // Epaisseur (en 1/10000 ") max raisonnable des traits, textes...
  19. /******************************************/
  20. /* class EDGE_MODULE ( contour de module ) */
  21. /******************************************/
  22. EDGE_MODULE::EDGE_MODULE( MODULE* parent ) :
  23. EDA_BaseLineStruct( parent, TYPEEDGEMODULE )
  24. {
  25. m_Shape = S_SEGMENT;
  26. m_Angle = 0;
  27. m_Width = 120;
  28. m_PolyCount = 0; // For polygons : number of points (> 2)
  29. m_PolyList = NULL; // For polygons: coord list (1 point = 2 coord)
  30. }
  31. EDGE_MODULE::~EDGE_MODULE()
  32. {
  33. if( m_PolyList )
  34. free( m_PolyList );
  35. m_PolyList = NULL;
  36. m_PolyCount = 0;
  37. }
  38. /********************************************/
  39. void EDGE_MODULE:: Copy( EDGE_MODULE* source ) // copy structure
  40. /********************************************/
  41. {
  42. if( source == NULL )
  43. return;
  44. m_Start = source->m_Start;
  45. m_End = source->m_End;
  46. m_Shape = source->m_Shape;
  47. m_Start0 = source->m_Start0; // coord relatives a l'ancre du point de depart(Orient 0)
  48. m_End0 = source->m_End0; // coord relatives a l'ancre du point de fin (Orient 0)
  49. m_Angle = source->m_Angle; // pour les arcs de cercle: longueur de l'arc en 0,1 degres
  50. m_Layer = source->m_Layer;
  51. m_Width = source->m_Width;
  52. if( m_PolyList )
  53. free( m_PolyList );
  54. m_PolyCount = 0;
  55. m_PolyList = NULL;
  56. if( source->m_PolyCount && source->m_PolyList )
  57. {
  58. int size;
  59. m_PolyCount = source->m_PolyCount; // For polygons : number of points
  60. size = m_PolyCount * 2 * sizeof(int); // For polygons: 1 point = 2 coord
  61. m_PolyList = (int*) MyMalloc( size );
  62. memcpy( m_PolyList, source->m_PolyList, size );
  63. }
  64. }
  65. /********************************/
  66. void EDGE_MODULE::UnLink( void )
  67. /********************************/
  68. {
  69. /* Modification du chainage arriere */
  70. if( Pback )
  71. {
  72. if( Pback->m_StructType != TYPEMODULE )
  73. {
  74. Pback->Pnext = Pnext;
  75. }
  76. else /* Le chainage arriere pointe sur la structure "Pere" */
  77. {
  78. ( (MODULE*) Pback )->m_Drawings = Pnext;
  79. }
  80. }
  81. /* Modification du chainage avant */
  82. if( Pnext )
  83. Pnext->Pback = Pback;
  84. Pnext = Pback = NULL;
  85. }
  86. /***********************************/
  87. void EDGE_MODULE::SetDrawCoord( void )
  88. /***********************************/
  89. {
  90. MODULE* Module = (MODULE*) m_Parent;
  91. m_Start = m_Start0;
  92. m_End = m_End0;
  93. if( Module )
  94. {
  95. RotatePoint( &m_Start.x, &m_Start.y, Module->m_Orient );
  96. RotatePoint( &m_End.x, &m_End.y, Module->m_Orient );
  97. m_Start.x += Module->m_Pos.x;
  98. m_Start.y += Module->m_Pos.y;
  99. m_End.x += Module->m_Pos.x;
  100. m_End.y += Module->m_Pos.y;
  101. }
  102. }
  103. /********************************************************************************/
  104. void EDGE_MODULE::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
  105. const wxPoint& offset, int draw_mode )
  106. /********************************************************************************/
  107. /* Affichage d'un segment contour de module :
  108. * Entree : ox, oy = offset de trace
  109. * draw_mode = mode de trace ( GR_OR, GR_XOR, GR_AND)
  110. * Les contours sont de differents type:
  111. * - Segment
  112. * - Cercles
  113. * - Arcs
  114. */
  115. {
  116. int ux0, uy0, dx, dy, rayon, StAngle, EndAngle;
  117. int color, type_trace;
  118. int zoom;
  119. int typeaff;
  120. PCB_SCREEN* screen;
  121. WinEDA_BasePcbFrame* frame;
  122. MODULE* Module = NULL;
  123. if( m_Parent && (m_Parent->m_StructType == TYPEMODULE) )
  124. Module = (MODULE*) m_Parent;
  125. color = g_DesignSettings.m_LayerColor[m_Layer];
  126. if( (color & ITEM_NOT_SHOW) != 0 )
  127. return;
  128. if( panel )
  129. screen = (PCB_SCREEN*) panel->m_Parent->m_CurrentScreen;
  130. else
  131. screen = (PCB_SCREEN*) ActiveScreen;
  132. frame = (WinEDA_BasePcbFrame*) panel->m_Parent;
  133. zoom = screen->GetZoom();
  134. type_trace = m_Shape;
  135. ux0 = m_Start.x - offset.x;
  136. uy0 = m_Start.y - offset.y;
  137. dx = m_End.x - offset.x;
  138. dy = m_End.y - offset.y;
  139. GRSetDrawMode( DC, draw_mode );
  140. typeaff = frame->m_DisplayModEdge;
  141. if( m_Layer <= CMP_N )
  142. {
  143. typeaff = frame->m_DisplayPcbTrackFill;
  144. if( !typeaff )
  145. typeaff = SKETCH;
  146. }
  147. if( (m_Width / zoom) < L_MIN_DESSIN )
  148. typeaff = FILAIRE;
  149. switch( type_trace )
  150. {
  151. case S_SEGMENT:
  152. if( typeaff == FILAIRE )
  153. GRLine( &panel->m_ClipBox, DC, ux0, uy0, dx, dy, 0, color );
  154. else if( typeaff == FILLED )
  155. GRLine( &panel->m_ClipBox, DC, ux0, uy0, dx, dy, m_Width, color );
  156. else
  157. // SKETCH Mode
  158. GRCSegm( &panel->m_ClipBox, DC, ux0, uy0, dx, dy, m_Width, color );
  159. break;
  160. case S_CIRCLE:
  161. rayon = (int) hypot( (double) (dx - ux0), (double) (dy - uy0) );
  162. if( typeaff == FILAIRE )
  163. {
  164. GRCircle( &panel->m_ClipBox, DC, ux0, uy0, rayon, color );
  165. }
  166. else
  167. {
  168. if( typeaff == FILLED )
  169. {
  170. GRCircle( &panel->m_ClipBox, DC, ux0, uy0, rayon, m_Width, color );
  171. }
  172. else // SKETCH Mode
  173. {
  174. GRCircle( &panel->m_ClipBox, DC, ux0, uy0, rayon + (m_Width / 2), color );
  175. GRCircle( &panel->m_ClipBox, DC, ux0, uy0, rayon - (m_Width / 2), color );
  176. }
  177. }
  178. break;
  179. case S_ARC:
  180. rayon = (int) hypot( (double) (dx - ux0), (double) (dy - uy0) );
  181. StAngle = (int) ArcTangente( dy - uy0, dx - ux0 );
  182. EndAngle = StAngle + m_Angle;
  183. if( StAngle > EndAngle )
  184. EXCHG( StAngle, EndAngle );
  185. if( typeaff == FILAIRE )
  186. {
  187. GRArc( &panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon, color );
  188. }
  189. else if( typeaff == FILLED )
  190. {
  191. GRArc( &panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle, rayon,
  192. m_Width, color );
  193. }
  194. else // SKETCH Mode
  195. {
  196. GRArc( &panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle,
  197. rayon + (m_Width / 2), color );
  198. GRArc( &panel->m_ClipBox, DC, ux0, uy0, StAngle, EndAngle,
  199. rayon - (m_Width / 2), color );
  200. }
  201. break;
  202. case S_POLYGON:
  203. {
  204. // We must compute true coordinates from m_PolyList
  205. // which are relative to module position, orientation 0
  206. int ii, * source, * ptr, * ptr_base;
  207. ptr = ptr_base = (int*) MyMalloc( 2 * m_PolyCount * sizeof(int) );
  208. source = m_PolyList;
  209. for( ii = 0; ii < m_PolyCount; ii++ )
  210. {
  211. int x, y;
  212. x = *source; source++; y = *source; source++;
  213. if( Module )
  214. {
  215. RotatePoint( &x, &y, Module->m_Orient );
  216. x += Module->m_Pos.x;
  217. y += Module->m_Pos.y;
  218. }
  219. x += m_Start0.x - offset.x;
  220. y += m_Start0.y - offset.y;
  221. *ptr = x; ptr++; *ptr = y; ptr++;
  222. }
  223. GRPoly( &panel->m_ClipBox, DC, m_PolyCount, ptr_base,
  224. TRUE, m_Width, color, color );
  225. free( ptr_base );
  226. break;
  227. }
  228. }
  229. }
  230. /*****************************************/
  231. int EDGE_MODULE::WriteDescr( FILE* File )
  232. /*****************************************/
  233. /* Write one EDGE_MODULE description
  234. * File must be opened.
  235. */
  236. {
  237. int NbLigne = 0, ii, * ptr;
  238. switch( m_Shape )
  239. {
  240. case S_SEGMENT:
  241. fprintf( File, "DS %d %d %d %d %d %d\n",
  242. m_Start0.x, m_Start0.y,
  243. m_End0.x, m_End0.y,
  244. m_Width, m_Layer );
  245. NbLigne++;
  246. break;
  247. case S_CIRCLE:
  248. fprintf( File, "DC %d %d %d %d %d %d\n",
  249. m_Start0.x, m_Start0.y,
  250. m_End0.x, m_End0.y,
  251. m_Width, m_Layer );
  252. NbLigne++;
  253. break;
  254. case S_ARC:
  255. fprintf( File, "DA %d %d %d %d %d %d %d\n",
  256. m_Start0.x, m_Start0.y,
  257. m_End0.x, m_End0.y,
  258. m_Angle,
  259. m_Width, m_Layer );
  260. NbLigne++;
  261. break;
  262. case S_POLYGON:
  263. fprintf( File, "DP %d %d %d %d %d %d %d\n",
  264. m_Start0.x, m_Start0.y,
  265. m_End0.x, m_End0.y,
  266. m_PolyCount,
  267. m_Width, m_Layer );
  268. NbLigne++;
  269. for( ii = 0, ptr = m_PolyList; ii < m_PolyCount; ii++ )
  270. {
  271. fprintf( File, "Dl %d %d\n",
  272. *ptr, *(ptr + 1) );
  273. NbLigne++; ptr += 2;
  274. }
  275. break;
  276. default:
  277. DisplayError( NULL, wxT( "Type Edge Module inconnu" ) );
  278. break;
  279. }
  280. return NbLigne;
  281. }
  282. /****************************************************************/
  283. int EDGE_MODULE::ReadDescr( char* Line, FILE* File,
  284. int* LineNum )
  285. /***************************************************************/
  286. /* Read a description line like:
  287. * DS 2600 0 2600 -600 120 21
  288. * this description line is in Line
  289. * EDGE_MODULE type can be:
  290. * - Circle,
  291. * - Segment (line)
  292. * - Arc
  293. * - Polygon
  294. *
  295. */
  296. {
  297. int ii, * ptr;
  298. int error = 0;
  299. char Buf[1024];
  300. switch( Line[1] )
  301. {
  302. case 'S':
  303. m_Shape = S_SEGMENT;
  304. break;
  305. case 'C':
  306. m_Shape = S_CIRCLE;
  307. break;
  308. case 'A':
  309. m_Shape = S_ARC;
  310. break;
  311. case 'P':
  312. m_Shape = S_POLYGON;
  313. break;
  314. default:
  315. wxString msg;
  316. msg.Printf( wxT( "Unknown EDGE_MODULE type <%s>" ), Line );
  317. DisplayError( NULL, msg );
  318. error = 1;
  319. break;
  320. }
  321. switch( m_Shape )
  322. {
  323. case S_ARC:
  324. sscanf( Line + 3, "%d %d %d %d %d %d %d",
  325. &m_Start0.x, &m_Start0.y,
  326. &m_End0.x, &m_End0.y,
  327. &m_Angle, &m_Width, &m_Layer );
  328. break;
  329. case S_SEGMENT:
  330. case S_CIRCLE:
  331. sscanf( Line + 3, "%d %d %d %d %d %d",
  332. &m_Start0.x, &m_Start0.y,
  333. &m_End0.x, &m_End0.y,
  334. &m_Width, &m_Layer );
  335. break;
  336. case S_POLYGON:
  337. sscanf( Line + 3, "%d %d %d %d %d %d %d",
  338. &m_Start0.x, &m_Start0.y,
  339. &m_End0.x, &m_End0.y,
  340. &m_PolyCount, &m_Width, &m_Layer );
  341. (*LineNum)++;
  342. m_PolyList = (int*) MyZMalloc( 2 * m_PolyCount * sizeof(int) );
  343. for( ii = 0, ptr = m_PolyList; ii < m_PolyCount; ii++ )
  344. {
  345. if( GetLine( File, Buf, LineNum, sizeof(Buf) - 1 ) != NULL )
  346. {
  347. if( strncmp( Buf, "Dl", 2 ) != 0 )
  348. {
  349. error = 1; break;
  350. }
  351. sscanf( Buf + 3, "%d %d\n", ptr, ptr + 1 );
  352. (*LineNum)++; ptr += 2;
  353. }
  354. else
  355. {
  356. error = 1; break;
  357. }
  358. }
  359. break;
  360. default:
  361. sscanf( Line + 3, "%d %d %d %d %d %d",
  362. &m_Start0.x, &m_Start0.y,
  363. &m_End0.x, &m_End0.y,
  364. &m_Width, &m_Layer );
  365. break;
  366. }
  367. // Controle d'epaisseur raisonnable:
  368. if( m_Width <= 1 )
  369. m_Width = 1;
  370. if( m_Width > MAX_WIDTH )
  371. m_Width = MAX_WIDTH;
  372. return error;
  373. }
  374. /**
  375. * Function HitTest
  376. * tests if the given wxPoint is within the bounds of this object.
  377. * @param refPos A wxPoint to test
  378. * @return bool - true if a hit, else false
  379. */
  380. bool EDGE_MODULE::HitTest( const wxPoint& ref_pos )
  381. {
  382. int uxf, uyf;
  383. int rayon, dist;
  384. int dx, dy, spot_cX, spot_cY;
  385. int ux0, uy0;
  386. ux0 = m_Start.x;
  387. uy0 = m_Start.y;
  388. uxf = m_End.x;
  389. uyf = m_End.y;
  390. switch( m_Shape )
  391. {
  392. case S_SEGMENT:
  393. /* recalcul des coordonnees avec ux0,uy0 = origine des coord. */
  394. spot_cX = ref_pos.x - ux0;
  395. spot_cY = ref_pos.y - uy0;
  396. dx = uxf - ux0;
  397. dy = uyf - uy0;
  398. if( DistanceTest( m_Width/2, dx, dy, spot_cX, spot_cY ) )
  399. return true;
  400. break;
  401. case S_CIRCLE:
  402. rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
  403. dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
  404. if( abs( rayon - dist ) <= m_Width )
  405. return true;
  406. break;
  407. case S_ARC:
  408. rayon = (int) hypot( (double) (uxf - ux0), (double) (uyf - uy0) );
  409. dist = (int) hypot( (double) (ref_pos.x - ux0), (double) (ref_pos.y - uy0) );
  410. if( abs( rayon - dist ) > m_Width )
  411. break;
  412. /* pour un arc, controle complementaire */
  413. int mouseAngle = (int) ArcTangente( ref_pos.y - uy0, ref_pos.x - ux0 );
  414. int stAngle = (int) ArcTangente( uyf - uy0, uxf - ux0 );
  415. int endAngle = stAngle + m_Angle;
  416. if( endAngle > 3600 )
  417. {
  418. stAngle -= 3600;
  419. endAngle -= 3600;
  420. }
  421. if( (mouseAngle >= stAngle) && (mouseAngle <= endAngle) )
  422. return true;
  423. break;
  424. }
  425. return false; // an unknown m_Shape also returns false
  426. }
  427. #if defined(DEBUG)
  428. /**
  429. * Function Show
  430. * is used to output the object tree, currently for debugging only.
  431. * @param nestLevel An aid to prettier tree indenting, and is the level
  432. * of nesting of this object within the overall tree.
  433. * @param os The ostream& to output to.
  434. */
  435. void EDGE_MODULE::Show( int nestLevel, std::ostream& os )
  436. {
  437. const char* cp = "???";
  438. switch( m_Shape )
  439. {
  440. case S_SEGMENT: cp = "line"; break;
  441. case S_RECT: cp = "rect"; break;
  442. case S_ARC: cp = "arc"; break;
  443. case S_CIRCLE: cp = "circle"; break;
  444. case S_ARC_RECT: cp = "arc_rect"; break;
  445. case S_SPOT_OVALE: cp = "spot_oval"; break;
  446. case S_SPOT_CIRCLE: cp = "spot_circle"; break;
  447. case S_SPOT_RECT: cp = "spot_rect"; break;
  448. case S_POLYGON: cp = "polygon"; break;
  449. }
  450. // for now, make it look like XML:
  451. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  452. " type=\"" << cp << "\">\n";
  453. NestedSpace( nestLevel+1, os ) << "<start" << m_Start0 << "/>\n";
  454. NestedSpace( nestLevel+1, os ) << "<end" << m_End0 << "/>\n";
  455. NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
  456. }
  457. #endif