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.

1040 lines
27 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /*******************************************************************/
  2. /* Functions relatives to tracks, vias and zones(see class_track.h */
  3. /*******************************************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "pcbnew.h"
  8. #ifdef CVPCB
  9. #include "cvpcb.h"
  10. #endif
  11. #include "trigo.h"
  12. #include "protos.h"
  13. // #define RATSNET_DEBUG
  14. #ifdef RATSNET_DEBUG
  15. /**************************************/
  16. void DbgDisplayTrackInfos( TRACK* track )
  17. /**************************************/
  18. /* Only for ratsnest debug
  19. */
  20. {
  21. wxString msg;
  22. msg << wxT( "Netcode " ) << track->GetNet();
  23. msg << wxT( " - " ) << track->GetSubNet();
  24. msg << wxT( "\nptrS " ) << (unsigned) track->start;
  25. msg << wxT( " ptrE " ) << (unsigned) track->end;
  26. msg << wxT( " this " ) << (unsigned) track;
  27. wxMessageBox( msg );
  28. }
  29. #endif
  30. /**********************************************************/
  31. TRACK::TRACK( BOARD_ITEM* StructFather, KICAD_T idtype ) :
  32. BOARD_ITEM( StructFather, idtype )
  33. /**********************************************************/
  34. {
  35. m_Width = 0;
  36. m_Shape = S_SEGMENT;
  37. start = end = NULL;
  38. SetNet( 0 );
  39. SetSubNet( 0 );
  40. SetDrillDefault();
  41. m_Param = 0;
  42. }
  43. /***************************/
  44. wxString TRACK::ShowWidth()
  45. /***************************/
  46. {
  47. wxString msg;
  48. valeur_param( m_Width, msg );
  49. return msg;
  50. }
  51. SEGZONE::SEGZONE( BOARD_ITEM* StructFather ) :
  52. TRACK( StructFather, TYPEZONE )
  53. {
  54. }
  55. SEGVIA::SEGVIA( BOARD_ITEM* StructFather ) :
  56. TRACK( StructFather, TYPEVIA )
  57. {
  58. }
  59. // Copy constructor
  60. TRACK::TRACK( const TRACK& Source ) :
  61. BOARD_ITEM( Source )
  62. {
  63. m_Shape = Source.m_Shape;
  64. SetNet( Source.GetNet() );
  65. m_Flags = Source.m_Flags;
  66. m_TimeStamp = Source.m_TimeStamp;
  67. SetStatus( Source.ReturnStatus() );
  68. m_Start = Source.m_Start;
  69. m_End = Source.m_End;
  70. m_Width = Source.m_Width;
  71. m_Drill = Source.m_Drill;
  72. SetSubNet( Source.GetSubNet() );
  73. m_Param = Source.m_Param;
  74. }
  75. /* Because of the way SEGVIA and SEGZONE are derived from TRACK and because there are
  76. * virtual functions being used, we can no longer simply copy a TRACK and
  77. * expect it to be a via or zone. We must construct a true SEGVIA or SEGZONE so its constructor
  78. * can initialize the virtual function table properly. This factory type of
  79. * function called Copy() can duplicate either a TRACK, SEGVIA, or SEGZONE.
  80. */
  81. TRACK* TRACK::Copy() const
  82. {
  83. if( Type() == TYPETRACK )
  84. return new TRACK( *this );
  85. if( Type() == TYPEVIA )
  86. return new SEGVIA( (const SEGVIA &) * this );
  87. if( Type() == TYPEZONE )
  88. return new SEGZONE( (const SEGZONE &) * this );
  89. return NULL; // should never happen
  90. }
  91. /**
  92. * Function GetDrillValue
  93. * calculate the drill value for vias (m-Drill if > 0, or default drill value for the board
  94. * @return real drill_value
  95. */
  96. int TRACK::GetDrillValue() const
  97. {
  98. if ( Type() != TYPEVIA )
  99. return 0;
  100. if ( m_Drill >= 0 )
  101. return m_Drill;
  102. if ( m_Shape == VIA_MICROVIA )
  103. return g_DesignSettings.m_MicroViaDrill;
  104. return g_DesignSettings.m_ViaDrill;
  105. }
  106. /***********************/
  107. bool TRACK::IsNull()
  108. /***********************/
  109. // return TRUE if segment length = 0
  110. {
  111. if( ( Type() != TYPEVIA ) && ( m_Start == m_End ) )
  112. return TRUE;
  113. else
  114. return FALSE;
  115. }
  116. /*************************************************************/
  117. int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
  118. /*************************************************************/
  119. /* Return:
  120. * STARTPOINT if point if near (dist = min_dist) star point
  121. * ENDPOINT if point if near (dist = min_dist) end point
  122. * STARTPOINT|ENDPOINT if point if near (dist = min_dist) both ends
  123. * 0 if no
  124. * if min_dist < 0: min_dist = track_width/2
  125. */
  126. {
  127. int result = 0;
  128. if( min_dist < 0 )
  129. min_dist = m_Width / 2;
  130. int dx = m_Start.x - point.x;
  131. int dy = m_Start.y - point.y;
  132. if( min_dist == 0 )
  133. {
  134. if( (dx == 0) && (dy == 0 ) )
  135. result |= STARTPOINT;
  136. }
  137. else
  138. {
  139. double dist = ( (double) dx * dx ) + ( (double) dy * dy );
  140. dist = sqrt( dist );
  141. if( min_dist >= (int) dist )
  142. result |= STARTPOINT;
  143. }
  144. dx = m_End.x - point.x;
  145. dy = m_End.y - point.y;
  146. if( min_dist == 0 )
  147. {
  148. if( (dx == 0) && (dy == 0 ) )
  149. result |= ENDPOINT;
  150. }
  151. else
  152. {
  153. double dist = ( (double) dx * dx ) + ( (double) dy * dy );
  154. dist = sqrt( dist );
  155. if( min_dist >= (int) dist )
  156. result |= ENDPOINT;
  157. }
  158. return result;
  159. }
  160. EDA_Rect TRACK::GetBoundingBox() const
  161. {
  162. // end of track is round, this is its radius, rounded up
  163. int radius = ( m_Width+1 )/2;
  164. int ymax;
  165. int xmax;
  166. int ymin;
  167. int xmin;
  168. if( Type() == TYPEVIA )
  169. {
  170. // Because vias are sometimes drawn larger than their m_Width would
  171. // provide, erasing them using a dirty rect must also compensate for this
  172. // possibility (that the via is larger on screen than its m_Width would provide).
  173. // Because it is cheap to return a larger BoundingBox, do it so that
  174. // the via gets erased properly. Do not divide width by 2 for this reason.
  175. radius = m_Width;
  176. ymax = m_Start.y;
  177. xmax = m_Start.x;
  178. ymin = m_Start.y;
  179. xmin = m_Start.x;
  180. }
  181. else
  182. {
  183. radius = ( m_Width+1 )/2;
  184. ymax = MAX( m_Start.y, m_End.y );
  185. xmax = MAX( m_Start.x, m_End.x );
  186. ymin = MIN( m_Start.y, m_End.y );
  187. xmin = MIN( m_Start.x, m_End.x );
  188. }
  189. ymax += radius;
  190. xmax += radius;
  191. ymin -= radius;
  192. xmin -= radius;
  193. // return a rectangle which is [pos,dim) in nature. therefore the +1
  194. return EDA_Rect( wxPoint( xmin, ymin ), wxSize( xmax-xmin+1, ymax-ymin+1 ) );
  195. }
  196. // see class_track.h
  197. // SEGVIA and SEGZONE inherit this version
  198. SEARCH_RESULT TRACK::Visit( INSPECTOR* inspector, const void* testData,
  199. const KICAD_T scanTypes[] )
  200. {
  201. KICAD_T stype = *scanTypes;
  202. #if 0 && defined (DEBUG)
  203. std::cout << GetClass().mb_str() << ' ';
  204. #endif
  205. // If caller wants to inspect my type
  206. if( stype == Type() )
  207. {
  208. if( SEARCH_QUIT == inspector->Inspect( this, testData ) )
  209. return SEARCH_QUIT;
  210. }
  211. return SEARCH_CONTINUE;
  212. }
  213. /***********************************************/
  214. bool SEGVIA::IsOnLayer( int layer_number ) const
  215. /***********************************************/
  216. {
  217. /**
  218. * @param layer_number = layer number to test
  219. * @return true if the via is on the layer layer_number
  220. */
  221. int bottom_layer, top_layer;
  222. ReturnLayerPair( &top_layer, &bottom_layer );
  223. if( bottom_layer <= layer_number && layer_number <= top_layer )
  224. return true;
  225. else
  226. return false;
  227. }
  228. /***********************************/
  229. int TRACK::ReturnMaskLayer()
  230. /***********************************/
  231. /* Return the mask layer for this.
  232. * for a via, there is more than one layer used
  233. */
  234. {
  235. if( Type() == TYPEVIA )
  236. {
  237. int via_type = Shape();
  238. if( via_type == VIA_THROUGH )
  239. return ALL_CU_LAYERS;
  240. // VIA_BLIND_BURIED or VIA_MICRVIA:
  241. int bottom_layer, top_layer;
  242. // ReturnLayerPair() knows how layers are stored
  243. ( (SEGVIA*) this )->ReturnLayerPair( &top_layer, &bottom_layer );
  244. int layermask = 0;
  245. while( bottom_layer <= top_layer )
  246. {
  247. layermask |= g_TabOneLayerMask[bottom_layer++];
  248. }
  249. return layermask;
  250. }
  251. else
  252. return g_TabOneLayerMask[m_Layer];
  253. }
  254. /*********************************************************/
  255. void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
  256. /*********************************************************/
  257. /** Set the .m_Layer member param:
  258. * For a via m_Layer contains the 2 layers :
  259. * top layer and bottom layer used by the via.
  260. * The via connect all layers from top layer to bottom layer
  261. * 4 bits for the first layer and 4 next bits for the secaon layer
  262. * @param top_layer = first layer connected by the via
  263. * @param bottom_layer = last layer connected by the via
  264. */
  265. {
  266. int via_type = Shape();
  267. if( via_type == VIA_THROUGH )
  268. {
  269. top_layer = LAYER_CMP_N;
  270. bottom_layer = COPPER_LAYER_N;
  271. }
  272. if( bottom_layer > top_layer )
  273. EXCHG( bottom_layer, top_layer );
  274. m_Layer = (top_layer & 15) + ( (bottom_layer & 15) << 4 );
  275. }
  276. /*********************************************************************/
  277. void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer ) const
  278. /*********************************************************************/
  279. /**
  280. * Function ReturnLayerPair
  281. * Return the 2 layers used by the via (the via actually uses
  282. * all layers between these 2 layers)
  283. * @param top_layer = pointer to the first layer (can be null)
  284. * @param bottom_layer = pointer to the last layer (can be null)
  285. */
  286. {
  287. int b_layer = (m_Layer >> 4) & 15;
  288. int t_layer = m_Layer & 15;
  289. if( b_layer > t_layer )
  290. EXCHG( b_layer, t_layer );
  291. if( top_layer )
  292. *top_layer = t_layer;
  293. if( bottom_layer )
  294. *bottom_layer = b_layer;
  295. }
  296. /* Remove this from the track or zone linked list
  297. */
  298. void TRACK::UnLink()
  299. {
  300. /* Remove the back link */
  301. if( Pback )
  302. {
  303. if( Pback->Type() != TYPEPCB )
  304. {
  305. Pback->Pnext = Pnext;
  306. }
  307. else /* Le chainage arriere pointe sur la structure "Pere" */
  308. {
  309. if( GetState( DELETED ) ) // A REVOIR car Pback = NULL si place en undelete
  310. {
  311. if( g_UnDeleteStackPtr )
  312. g_UnDeleteStack[g_UnDeleteStackPtr - 1] = (BOARD_ITEM*) Pnext;
  313. }
  314. else
  315. {
  316. if( Type() == TYPEZONE )
  317. {
  318. ( (BOARD*) Pback )->m_Zone = (SEGZONE*) Pnext;
  319. }
  320. else
  321. {
  322. ( (BOARD*) Pback )->m_Track = (TRACK*) Pnext;
  323. }
  324. }
  325. }
  326. }
  327. /* Remove the forward link */
  328. if( Pnext )
  329. Pnext->Pback = Pback;
  330. Pnext = Pback = NULL;
  331. }
  332. /************************************************************/
  333. void TRACK::Insert( BOARD* Pcb, BOARD_ITEM* InsertPoint )
  334. /************************************************************/
  335. /* insert this (and its linked segments is exists)
  336. * in the track linked list
  337. * @param InsertPoint = insert point within the linked list
  338. * if NULL: insert as first element of Pcb->m_Tracks
  339. */
  340. {
  341. TRACK* track;
  342. TRACK* NextS;
  343. if( InsertPoint == NULL )
  344. {
  345. Pback = Pcb;
  346. if( Type() == TYPEZONE ) // put SEGZONE on front of m_Zone list
  347. {
  348. NextS = Pcb->m_Zone;
  349. Pcb->m_Zone = (SEGZONE*) this;
  350. }
  351. else // put TRACK or SEGVIA on front of m_Track list
  352. {
  353. NextS = Pcb->m_Track;
  354. Pcb->m_Track = this;
  355. }
  356. }
  357. else
  358. {
  359. NextS = (TRACK*) InsertPoint->Pnext;
  360. Pback = InsertPoint;
  361. InsertPoint->Pnext = this;
  362. }
  363. /* Set the forward link */
  364. track = this;
  365. while( track->Pnext ) // Search the end of added chain
  366. track = (TRACK*) track->Pnext;
  367. /* Link the end of chain */
  368. track->Pnext = NextS;
  369. if( NextS )
  370. NextS->Pback = track;
  371. }
  372. /***********************************************/
  373. TRACK* TRACK::GetBestInsertPoint( BOARD* Pcb )
  374. /***********************************************/
  375. /**
  376. * Search the "best" insertion point within the track linked list
  377. * the best point is the of the corresponding net code section
  378. * @return the item found in the linked list (or NULL if no track)
  379. */
  380. {
  381. TRACK* track, * NextTrack;
  382. if( Type() == TYPEZONE )
  383. track = Pcb->m_Zone;
  384. else
  385. track = Pcb->m_Track;
  386. /* Traitement du debut de liste */
  387. if( track == NULL )
  388. return NULL; /* No tracks ! */
  389. if( GetNet() < track->GetNet() ) /* no net code or net code = 0 (track not connected) */
  390. return NULL;
  391. while( (NextTrack = (TRACK*) track->Pnext) != NULL )
  392. {
  393. if( NextTrack->GetNet() > this->GetNet() )
  394. break;
  395. track = NextTrack;
  396. }
  397. return track;
  398. }
  399. /*******************************************/
  400. TRACK* TRACK::GetStartNetCode( int NetCode )
  401. /*******************************************/
  402. /* Search (within the track linked list) the first segment matching the netcode
  403. * ( the linked list is always sorted by net codes )
  404. */
  405. {
  406. TRACK* Track = this;
  407. int ii = 0;
  408. if( NetCode == -1 )
  409. NetCode = GetNet();
  410. while( Track != NULL )
  411. {
  412. if( Track->GetNet() > NetCode )
  413. break;
  414. if( Track->GetNet() == NetCode )
  415. {
  416. ii++;
  417. break;
  418. }
  419. Track = (TRACK*) Track->Pnext;
  420. }
  421. if( ii )
  422. return Track;
  423. else
  424. return NULL;
  425. }
  426. /*****************************************/
  427. TRACK* TRACK::GetEndNetCode( int NetCode )
  428. /*****************************************/
  429. /* Search (within the track linked list) the last segment matching the netcode
  430. * ( the linked list is always sorted by net codes )
  431. */
  432. {
  433. TRACK* NextS, * Track = this;
  434. int ii = 0;
  435. if( Track == NULL )
  436. return NULL;
  437. if( NetCode == -1 )
  438. NetCode = GetNet();
  439. while( Track != NULL )
  440. {
  441. NextS = (TRACK*) Track->Pnext;
  442. if( Track->GetNet() == NetCode )
  443. ii++;
  444. if( NextS == NULL )
  445. break;
  446. if( NextS->GetNet() > NetCode )
  447. break;
  448. Track = NextS;
  449. }
  450. if( ii )
  451. return Track;
  452. else
  453. return NULL;
  454. }
  455. bool TRACK::Save( FILE* aFile ) const
  456. {
  457. int type = 0;
  458. if( Type() == TYPEVIA )
  459. type = 1;
  460. if( GetState( DELETED ) )
  461. return true;
  462. fprintf( aFile, "Po %d %d %d %d %d %d %d\n", m_Shape,
  463. m_Start.x, m_Start.y, m_End.x, m_End.y, m_Width, m_Drill );
  464. fprintf( aFile, "De %d %d %d %lX %X\n",
  465. m_Layer, type, GetNet(),
  466. m_TimeStamp, ReturnStatus() );
  467. return true;
  468. }
  469. /*********************************************************************/
  470. void TRACK::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode )
  471. /*********************************************************************/
  472. /** Draws the segment.
  473. * @param panel = current panel
  474. * @param DC = current device context
  475. * @param draw_mode = GR_XOR, GR_OR..
  476. */
  477. {
  478. int l_piste;
  479. int color;
  480. int zoom;
  481. int rayon;
  482. int curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer;
  483. if( Type() == TYPEZONE && !DisplayOpt.DisplayZones )
  484. return;
  485. GRSetDrawMode( DC, draw_mode );
  486. if( Type() == TYPEVIA )
  487. color = g_DesignSettings.m_ViaColor[m_Shape];
  488. else
  489. color = g_DesignSettings.m_LayerColor[m_Layer];
  490. if( ( color & (ITEM_NOT_SHOW | HIGHT_LIGHT_FLAG) ) == ITEM_NOT_SHOW )
  491. return;
  492. if( DisplayOpt.ContrastModeDisplay )
  493. {
  494. if( !IsOnLayer( curr_layer ) )
  495. {
  496. color &= ~MASKCOLOR;
  497. color |= DARKDARKGRAY;
  498. }
  499. }
  500. if( draw_mode & GR_SURBRILL )
  501. {
  502. if( draw_mode & GR_AND )
  503. color &= ~HIGHT_LIGHT_FLAG;
  504. else
  505. color |= HIGHT_LIGHT_FLAG;
  506. }
  507. if( color & HIGHT_LIGHT_FLAG )
  508. color = ColorRefs[color & MASKCOLOR].m_LightColor;
  509. zoom = panel->GetZoom();
  510. l_piste = m_Width >> 1;
  511. if( Type() == TYPEVIA ) /* The via is drawn as a circle */
  512. {
  513. rayon = l_piste;
  514. if( rayon < zoom )
  515. rayon = zoom;
  516. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
  517. if( rayon > (4 * zoom) )
  518. {
  519. int drill_rayon = GetDrillValue() / 2;
  520. int inner_rayon = rayon - (2 * zoom);
  521. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  522. inner_rayon, color );
  523. // Draw the via hole if the display option allows it
  524. if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW )
  525. {
  526. if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) || // Display all drill holes requested
  527. ( (drill_rayon > 0 ) && ! IsDrillDefault() ) ) // Or Display non default holes requested
  528. {
  529. if( drill_rayon < inner_rayon ) // We can show the via hole
  530. {
  531. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  532. drill_rayon, color );
  533. }
  534. }
  535. }
  536. if( DisplayOpt.DisplayTrackIsol )
  537. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  538. rayon + g_DesignSettings.m_TrackClearence, color );
  539. // for Micro Vias, draw a partial cross :
  540. // X on component layer, or + on copper layer
  541. // (so we can see 2 superimposed microvias ):
  542. if ( Shape() == VIA_MICROVIA )
  543. {
  544. int ax, ay, bx, by;
  545. if ( IsOnLayer(COPPER_LAYER_N) )
  546. {
  547. ax = rayon; ay = 0;
  548. bx = drill_rayon; by = 0;
  549. }
  550. else
  551. {
  552. ax = ay = (rayon * 707) / 1000;
  553. bx = by = (drill_rayon * 707) / 1000;
  554. }
  555. /* lines | or \ */
  556. GRLine( &panel->m_ClipBox, DC, m_Start.x - ax , m_Start.y - ay,
  557. m_Start.x - bx , m_Start.y - by, 0, color );
  558. GRLine( &panel->m_ClipBox, DC, m_Start.x + bx , m_Start.y + by,
  559. m_Start.x + ax , m_Start.y + ay, 0, color );
  560. /* lines - or / */
  561. GRLine( &panel->m_ClipBox, DC, m_Start.x + ay, m_Start.y - ax ,
  562. m_Start.x + by, m_Start.y - bx, 0, color );
  563. GRLine( &panel->m_ClipBox, DC, m_Start.x - by, m_Start.y + bx ,
  564. m_Start.x - ay, m_Start.y + ax, 0, color );
  565. }
  566. // for Buried Vias, draw a partial line :
  567. // orient depending on layer pair
  568. // (so we can see superimposed buried vias ):
  569. if ( Shape() == VIA_BLIND_BURIED )
  570. {
  571. int ax = 0, ay = rayon, bx = 0, by = drill_rayon;
  572. int layer_top, layer_bottom ;
  573. ((SEGVIA*)this)->ReturnLayerPair(&layer_top, &layer_bottom);
  574. /* lines for the top layer */
  575. RotatePoint( &ax, &ay, layer_top * 3600 / g_DesignSettings.m_CopperLayerCount);
  576. RotatePoint( &bx, &by, layer_top * 3600 / g_DesignSettings.m_CopperLayerCount);
  577. GRLine( &panel->m_ClipBox, DC, m_Start.x - ax , m_Start.y - ay,
  578. m_Start.x - bx , m_Start.y - by, 0, color );
  579. /* lines for the bottom layer */
  580. ax = 0; ay = rayon; bx = 0; by = drill_rayon;
  581. RotatePoint( &ax, &ay, layer_bottom * 3600 / g_DesignSettings.m_CopperLayerCount);
  582. RotatePoint( &bx, &by, layer_bottom * 3600 / g_DesignSettings.m_CopperLayerCount);
  583. GRLine( &panel->m_ClipBox, DC, m_Start.x - ax , m_Start.y - ay,
  584. m_Start.x - bx , m_Start.y - by, 0, color );
  585. }
  586. }
  587. return;
  588. }
  589. if( m_Shape == S_CIRCLE )
  590. {
  591. rayon = (int) hypot( (double) (m_End.x - m_Start.x),
  592. (double) (m_End.y - m_Start.y) );
  593. if( (l_piste / zoom) < L_MIN_DESSIN )
  594. {
  595. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
  596. }
  597. else
  598. {
  599. if( l_piste <= zoom ) /* Sketch mode if l_piste/zoom <= 1 */
  600. {
  601. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon, color );
  602. }
  603. else if( ( !DisplayOpt.DisplayPcbTrackFill) || GetState( FORCE_SKETCH ) )
  604. {
  605. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon - l_piste, color );
  606. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon + l_piste, color );
  607. }
  608. else
  609. {
  610. GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, rayon,
  611. m_Width, color );
  612. }
  613. }
  614. return;
  615. }
  616. if( (l_piste / zoom) < L_MIN_DESSIN )
  617. {
  618. GRLine( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  619. m_End.x, m_End.y, 0, color );
  620. return;
  621. }
  622. if( (!DisplayOpt.DisplayPcbTrackFill) || GetState( FORCE_SKETCH ) )
  623. {
  624. GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  625. m_End.x, m_End.y, m_Width, color );
  626. }
  627. else
  628. {
  629. GRFillCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  630. m_End.x, m_End.y, m_Width, color );
  631. }
  632. /* Shows clearance (for tracks and vias, not for zone segments */
  633. if( DisplayOpt.DisplayTrackIsol && ( m_Layer <= LAST_COPPER_LAYER )
  634. && ( Type() == TYPETRACK || Type() == TYPEVIA) )
  635. {
  636. GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
  637. m_End.x, m_End.y,
  638. m_Width + (g_DesignSettings.m_TrackClearence * 2), color );
  639. }
  640. }
  641. // see class_track.h
  642. void TRACK::Display_Infos( WinEDA_DrawFrame* frame )
  643. {
  644. wxString msg;
  645. int text_pos;
  646. BOARD* board = ((WinEDA_PcbFrame*)frame)->m_Pcb;
  647. #ifdef RATSNET_DEBUG
  648. DbgDisplayTrackInfos( this );
  649. #endif
  650. frame->MsgPanel->EraseMsgBox();
  651. switch( Type() )
  652. {
  653. case TYPEVIA:
  654. msg = g_ViaType_Name[Shape()];
  655. break;
  656. case TYPETRACK:
  657. msg = _( "Track" );
  658. break;
  659. case TYPEZONE:
  660. msg = _( "Zone" ); break;
  661. default:
  662. msg = wxT( "????" ); break;
  663. }
  664. text_pos = 1;
  665. Affiche_1_Parametre( frame, text_pos, _( "Type" ), msg, DARKCYAN );
  666. /* Display NetName pour les segments de piste type cuivre */
  667. text_pos += 15;
  668. if( Type() == TYPETRACK
  669. || Type() == TYPEZONE
  670. || Type() == TYPEVIA )
  671. {
  672. EQUIPOT* equipot = board->FindNet( GetNet() );
  673. if( equipot )
  674. msg = equipot->m_Netname;
  675. else
  676. msg = wxT( "<noname>" );
  677. Affiche_1_Parametre( frame, text_pos, _( "NetName" ), msg, RED );
  678. /* Display net code : (usefull in test or debug) */
  679. msg.Printf( wxT( "%d .%d" ), GetNet(), GetSubNet() );
  680. text_pos += 18;
  681. Affiche_1_Parametre( frame, text_pos, _( "NetCode" ), msg, RED );
  682. }
  683. else
  684. {
  685. Affiche_1_Parametre( frame, text_pos, _( "Segment" ), wxEmptyString, RED );
  686. if( m_Shape == S_CIRCLE )
  687. Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Circle" ), RED );
  688. else
  689. Affiche_1_Parametre( frame, -1, wxEmptyString, _( "Standard" ), RED );
  690. }
  691. /* Display the Status flags */
  692. msg = wxT( ". . " );
  693. if( GetState( SEGM_FIXE ) )
  694. msg[0] = 'F';
  695. if( GetState( SEGM_AR ) )
  696. msg[2] = 'A';
  697. text_pos = 42;
  698. Affiche_1_Parametre( frame, text_pos, _( "Stat" ), msg, MAGENTA );
  699. /* Display layer or layer pair) */
  700. if( Type() == TYPEVIA )
  701. {
  702. SEGVIA* Via = (SEGVIA*) this;
  703. int top_layer, bottom_layer;
  704. Via->ReturnLayerPair( &top_layer, &bottom_layer );
  705. msg = board->GetLayerName( top_layer ) + wxT( "/" )
  706. + board->GetLayerName( bottom_layer );
  707. }
  708. else
  709. msg = board->GetLayerName( m_Layer );
  710. text_pos += 5;
  711. Affiche_1_Parametre( frame, text_pos, _( "Layer" ), msg, BROWN );
  712. /* Display width */
  713. valeur_param( (unsigned) m_Width, msg );
  714. text_pos += 11;
  715. if( Type() == TYPEVIA ) // Display Diam and Drill values
  716. {
  717. Affiche_1_Parametre( frame, text_pos, _( "Diam" ), msg, DARKCYAN );
  718. int drill_value = GetDrillValue();
  719. valeur_param( (unsigned) drill_value, msg );
  720. text_pos += 8;
  721. wxString title = _( "Drill" );
  722. if( g_DesignSettings.m_ViaDrill >= 0 )
  723. title += wxT( "*" );
  724. Affiche_1_Parametre( frame, text_pos, _( "Drill" ), msg, RED );
  725. }
  726. else
  727. Affiche_1_Parametre( frame, text_pos, _( "Width" ), msg, DARKCYAN );
  728. }
  729. /**
  730. * Function HitTest
  731. * tests if the given wxPoint is within the bounds of this object.
  732. * @param ref_pos A wxPoint to test
  733. * @return bool - true if a hit, else false
  734. */
  735. bool TRACK::HitTest( const wxPoint& ref_pos )
  736. {
  737. int radius = m_Width >> 1;
  738. // (dx, dy) is a vector from m_Start to m_End (an origin of m_Start)
  739. int dx = m_End.x - m_Start.x;
  740. int dy = m_End.y - m_Start.y;
  741. // (spot_cX, spot_cY) is a vector from m_Start to ref_pos (an origin of m_Start)
  742. int spot_cX = ref_pos.x - m_Start.x;
  743. int spot_cY = ref_pos.y - m_Start.y;
  744. if( Type() == TYPEVIA ) /* VIA rencontree */
  745. {
  746. return (double) spot_cX * spot_cX + (double) spot_cY * spot_cY <=
  747. (double) radius * radius;
  748. }
  749. else
  750. {
  751. if( DistanceTest( radius, dx, dy, spot_cX, spot_cY ) )
  752. return true;
  753. }
  754. return false;
  755. }
  756. /**
  757. * Function HitTest (overlayed)
  758. * tests if the given EDA_Rect intersect this object.
  759. * For now, an ending point must be inside this rect.
  760. * @param refArea : the given EDA_Rect
  761. * @return bool - true if a hit, else false
  762. */
  763. bool TRACK::HitTest( EDA_Rect& refArea )
  764. {
  765. if( refArea.Inside( m_Start ) )
  766. return true;
  767. if( refArea.Inside( m_End ) )
  768. return true;
  769. return false;
  770. }
  771. #if defined (DEBUG)
  772. /**
  773. * Function Show
  774. * is used to output the object tree, currently for debugging only.
  775. * @param nestLevel An aid to prettier tree indenting, and is the level
  776. * of nesting of this object within the overall tree.
  777. * @param os The ostream& to output to.
  778. */
  779. void TRACK::Show( int nestLevel, std::ostream& os )
  780. {
  781. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  782. // " shape=\"" << m_Shape << '"' <<
  783. " layer=\"" << m_Layer << '"' <<
  784. " width=\"" << m_Width << '"' <<
  785. // " drill=\"" << GetDrillValue() << '"' <<
  786. " netcode=\"" << GetNet() << "\">" <<
  787. "<start" << m_Start << "/>" <<
  788. "<end" << m_End << "/>";
  789. os << "</" << GetClass().Lower().mb_str() << ">\n";
  790. }
  791. /**
  792. * Function Show
  793. * is used to output the object tree, currently for debugging only.
  794. * @param nestLevel An aid to prettier tree indenting, and is the level
  795. * of nesting of this object within the overall tree.
  796. * @param os The ostream& to output to.
  797. */
  798. void SEGVIA::Show( int nestLevel, std::ostream& os )
  799. {
  800. const char* cp;
  801. switch( Shape() )
  802. {
  803. case VIA_THROUGH:
  804. cp = "through";
  805. break;
  806. case VIA_BLIND_BURIED:
  807. cp = "blind/buried";
  808. break;
  809. case VIA_MICROVIA:
  810. cp = "micro via";
  811. break;
  812. default:
  813. case VIA_NOT_DEFINED:
  814. cp = "undefined";
  815. break;
  816. }
  817. int topLayer;
  818. int botLayer;
  819. BOARD* board = (BOARD*) m_Parent;
  820. ReturnLayerPair( &topLayer, &botLayer );
  821. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  822. " type=\"" << cp << '"';
  823. if( board )
  824. os << " layers=\"" << board->GetLayerName( topLayer ).Trim().mb_str() << ","
  825. << board->GetLayerName( botLayer ).Trim().mb_str() << '"';
  826. os <<
  827. " width=\"" << m_Width << '"' <<
  828. " drill=\"" << GetDrillValue() << '"' <<
  829. " netcode=\"" << GetNet() << "\">" <<
  830. "<pos" << m_Start << "/>";
  831. os << "</" << GetClass().Lower().mb_str() << ">\n";
  832. }
  833. #endif