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.

630 lines
18 KiB

14 years ago
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 years ago
// Dick Hollenbeck's KiROUND R&D // This provides better project control over rounding to int from double // than wxRound() did. This scheme provides better logging in Debug builds // and it provides for compile time calculation of constants. #include <stdio.h> #include <assert.h> #include <limits.h> //-----<KiROUND KIT>------------------------------------------------------------ /** * KiROUND * rounds a floating point number to an int using * "round halfway cases away from zero". * In Debug build an assert fires if will not fit into an int. */ #if defined( DEBUG ) // DEBUG: a macro to capture line and file, then calls this inline static inline int KiRound( double v, int line, const char* filename ) { v = v < 0 ? v - 0.5 : v + 0.5; if( v > INT_MAX + 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' > 0 ' for int\n", __FUNCTION__, filename, line, v ); } else if( v < INT_MIN - 0.5 ) { printf( "%s: in file %s on line %d, val: %.16g too ' < 0 ' for int\n", __FUNCTION__, filename, line, v ); } return int( v ); } #define KiROUND( v ) KiRound( v, __LINE__, __FILE__ ) #else // RELEASE: a macro so compile can pre-compute constants. #define KiROUND( v ) int( (v) < 0 ? (v) - 0.5 : (v) + 0.5 ) #endif //-----</KiROUND KIT>----------------------------------------------------------- // Only a macro is compile time calculated, an inline function causes a static constructor // in a situation like this. // Therefore the Release build is best done with a MACRO not an inline function. int Computed = KiROUND( 14.3 * 8 ); int main( int argc, char** argv ) { for( double d = double(INT_MAX)-1; d < double(INT_MAX)+8; d += 2.0 ) { int i = KiROUND( d ); printf( "t: %d %.16g\n", i, d ); } return 0; }
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2010 <Jean-Pierre Charras>
  5. * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file class_gerber_draw_item.cpp
  26. */
  27. #include <fctsys.h>
  28. #include <polygons_defs.h>
  29. #include <gr_basic.h>
  30. #include <common.h>
  31. #include <trigo.h>
  32. #include <class_drawpanel.h>
  33. #include <macros.h>
  34. #include <msgpanel.h>
  35. #include <gerbview.h>
  36. #include <gerbview_frame.h>
  37. #include <class_gerber_draw_item.h>
  38. #include <class_GERBER.h>
  39. GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( GBR_LAYOUT* aParent, GERBER_IMAGE* aGerberparams ) :
  40. EDA_ITEM( (EDA_ITEM*)aParent, TYPE_GERBER_DRAW_ITEM )
  41. {
  42. m_imageParams = aGerberparams;
  43. m_Layer = 0;
  44. m_Shape = GBR_SEGMENT;
  45. m_Flashed = false;
  46. m_DCode = 0;
  47. m_UnitsMetric = false;
  48. m_LayerNegative = false;
  49. m_swapAxis = false;
  50. m_mirrorA = false;
  51. m_mirrorB = false;
  52. m_drawScale.x = m_drawScale.y = 1.0;
  53. m_lyrRotation = 0;
  54. if( m_imageParams )
  55. SetLayerParameters();
  56. }
  57. // Copy constructor
  58. GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
  59. EDA_ITEM( aSource )
  60. {
  61. m_imageParams = aSource.m_imageParams;
  62. m_Shape = aSource.m_Shape;
  63. m_Flags = aSource.m_Flags;
  64. SetTimeStamp( aSource.m_TimeStamp );
  65. SetStatus( aSource.GetStatus() );
  66. m_Start = aSource.m_Start;
  67. m_End = aSource.m_End;
  68. m_Size = aSource.m_Size;
  69. m_Layer = aSource.m_Layer;
  70. m_Shape = aSource.m_Shape;
  71. m_Flashed = aSource.m_Flashed;
  72. m_DCode = aSource.m_DCode;
  73. m_PolyCorners = aSource.m_PolyCorners;
  74. m_UnitsMetric = aSource.m_UnitsMetric;
  75. m_LayerNegative = aSource.m_LayerNegative;
  76. m_swapAxis = aSource.m_swapAxis;
  77. m_mirrorA = aSource.m_mirrorA;
  78. m_mirrorB = aSource.m_mirrorB;
  79. m_layerOffset = aSource.m_layerOffset;
  80. m_drawScale = aSource.m_drawScale;
  81. m_lyrRotation = aSource.m_lyrRotation;
  82. }
  83. GERBER_DRAW_ITEM::~GERBER_DRAW_ITEM()
  84. {
  85. }
  86. GERBER_DRAW_ITEM* GERBER_DRAW_ITEM::Copy() const
  87. {
  88. return new GERBER_DRAW_ITEM( *this );
  89. }
  90. wxPoint GERBER_DRAW_ITEM::GetABPosition( const wxPoint& aXYPosition ) const
  91. {
  92. /* Note: RS274Xrevd_e is obscure about the order of transforms:
  93. * For instance: Rotation must be made after or before mirroring ?
  94. * Note: if something is changed here, GetYXPosition must reflect changes
  95. */
  96. wxPoint abPos = aXYPosition + m_imageParams->m_ImageJustifyOffset;
  97. if( m_swapAxis )
  98. EXCHG( abPos.x, abPos.y );
  99. abPos += m_layerOffset + m_imageParams->m_ImageOffset;
  100. abPos.x = KiROUND( abPos.x * m_drawScale.x );
  101. abPos.y = KiROUND( abPos.y * m_drawScale.y );
  102. double rotation = m_lyrRotation * 10 + m_imageParams->m_ImageRotation * 10;
  103. if( rotation )
  104. RotatePoint( &abPos, -rotation );
  105. // Negate A axis if mirrored
  106. if( m_mirrorA )
  107. NEGATE( abPos.x );
  108. // abPos.y must be negated when no mirror, because draw axis is top to bottom
  109. if( !m_mirrorB )
  110. NEGATE( abPos.y );
  111. return abPos;
  112. }
  113. wxPoint GERBER_DRAW_ITEM::GetXYPosition( const wxPoint& aABPosition ) const
  114. {
  115. // do the inverse transform made by GetABPosition
  116. wxPoint xyPos = aABPosition;
  117. if( m_mirrorA )
  118. NEGATE( xyPos.x );
  119. if( !m_mirrorB )
  120. NEGATE( xyPos.y );
  121. double rotation = m_lyrRotation * 10 + m_imageParams->m_ImageRotation * 10;
  122. if( rotation )
  123. RotatePoint( &xyPos, rotation );
  124. xyPos.x = KiROUND( xyPos.x / m_drawScale.x );
  125. xyPos.y = KiROUND( xyPos.y / m_drawScale.y );
  126. xyPos -= m_layerOffset + m_imageParams->m_ImageOffset;
  127. if( m_swapAxis )
  128. EXCHG( xyPos.x, xyPos.y );
  129. return xyPos - m_imageParams->m_ImageJustifyOffset;
  130. }
  131. void GERBER_DRAW_ITEM::SetLayerParameters()
  132. {
  133. m_UnitsMetric = m_imageParams->m_GerbMetric;
  134. m_swapAxis = m_imageParams->m_SwapAxis; // false if A = X, B = Y;
  135. // true if A =Y, B = Y
  136. m_mirrorA = m_imageParams->m_MirrorA; // true: mirror / axe A
  137. m_mirrorB = m_imageParams->m_MirrorB; // true: mirror / axe B
  138. m_drawScale = m_imageParams->m_Scale; // A and B scaling factor
  139. m_layerOffset = m_imageParams->m_Offset; // Offset from OF command
  140. // Rotation from RO command:
  141. m_lyrRotation = m_imageParams->m_LocalRotation;
  142. m_LayerNegative = m_imageParams->GetLayerParams().m_LayerNegative;
  143. }
  144. wxString GERBER_DRAW_ITEM::ShowGBRShape()
  145. {
  146. switch( m_Shape )
  147. {
  148. case GBR_SEGMENT:
  149. return _( "Line" );
  150. case GBR_ARC:
  151. return _( "Arc" );
  152. case GBR_CIRCLE:
  153. return _( "Circle" );
  154. case GBR_SPOT_OVAL:
  155. return wxT( "spot_oval" );
  156. case GBR_SPOT_CIRCLE:
  157. return wxT( "spot_circle" );
  158. case GBR_SPOT_RECT:
  159. return wxT( "spot_rect" );
  160. case GBR_SPOT_POLY:
  161. return wxT( "spot_poly" );
  162. case GBR_POLYGON:
  163. return wxT( "polygon" );
  164. case GBR_SPOT_MACRO:
  165. {
  166. wxString name = wxT( "apt_macro" );
  167. D_CODE* dcode = GetDcodeDescr();
  168. if( dcode && dcode->GetMacro() )
  169. name << wxT(" ") << dcode->GetMacro()->name;
  170. return name;
  171. }
  172. default:
  173. return wxT( "??" );
  174. }
  175. }
  176. D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr()
  177. {
  178. if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) )
  179. return NULL;
  180. GERBER_IMAGE* gerber = g_GERBER_List[m_Layer];
  181. if( gerber == NULL )
  182. return NULL;
  183. D_CODE* d_code = gerber->GetDCODE( m_DCode, false );
  184. return d_code;
  185. }
  186. const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const
  187. {
  188. // return a rectangle which is (pos,dim) in nature. therefore the +1
  189. EDA_RECT bbox( m_Start, wxSize( 1, 1 ) );
  190. bbox.Inflate( m_Size.x / 2, m_Size.y / 2 );
  191. bbox.SetOrigin( GetABPosition( bbox.GetOrigin() ) );
  192. bbox.SetEnd( GetABPosition( bbox.GetEnd() ) );
  193. return bbox;
  194. }
  195. void GERBER_DRAW_ITEM::MoveAB( const wxPoint& aMoveVector )
  196. {
  197. wxPoint xymove = GetXYPosition( aMoveVector );
  198. m_Start += xymove;
  199. m_End += xymove;
  200. m_ArcCentre += xymove;
  201. for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ )
  202. m_PolyCorners[ii] += xymove;
  203. }
  204. void GERBER_DRAW_ITEM::MoveXY( const wxPoint& aMoveVector )
  205. {
  206. m_Start += aMoveVector;
  207. m_End += aMoveVector;
  208. m_ArcCentre += aMoveVector;
  209. for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ )
  210. m_PolyCorners[ii] += aMoveVector;
  211. }
  212. bool GERBER_DRAW_ITEM::Save( FILE* aFile ) const
  213. {
  214. return true;
  215. }
  216. bool GERBER_DRAW_ITEM::HasNegativeItems()
  217. {
  218. bool isClear = m_LayerNegative ^ m_imageParams->m_ImageNegative;
  219. // if isClear is true, this item has negative shape
  220. // but if isClear is true, and if this item use an aperture macro definition,
  221. // we must see if this aperture macro uses a negative shape.
  222. if( isClear )
  223. return true;
  224. // see for a macro def
  225. D_CODE* dcodeDescr = GetDcodeDescr();
  226. if( dcodeDescr == NULL )
  227. return false;
  228. if( m_Shape == GBR_SPOT_MACRO )
  229. {
  230. APERTURE_MACRO* macro = dcodeDescr->GetMacro();
  231. if( macro ) // macro == NULL should not occurs
  232. return macro->HasNegativeItems( this );
  233. }
  234. return false;
  235. }
  236. void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode,
  237. const wxPoint& aOffset )
  238. {
  239. // used when a D_CODE is not found. default D_CODE to draw a flashed item
  240. static D_CODE dummyD_CODE( 0 );
  241. EDA_COLOR_T color, alt_color;
  242. bool isFilled;
  243. int radius;
  244. int halfPenWidth;
  245. static bool show_err;
  246. D_CODE* d_codeDescr = GetDcodeDescr();
  247. GERBVIEW_FRAME* gerbFrame = (GERBVIEW_FRAME*) aPanel->GetParent();
  248. if( d_codeDescr == NULL )
  249. d_codeDescr = &dummyD_CODE;
  250. if( gerbFrame->IsLayerVisible( GetLayer() ) == false )
  251. return;
  252. color = gerbFrame->GetLayerColor( GetLayer() );
  253. if( aDrawMode & GR_HIGHLIGHT )
  254. ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) );
  255. ColorApplyHighlightFlag( &color );
  256. alt_color = gerbFrame->GetNegativeItemsColor();
  257. /* isDark is true if flash is positive and should use a drawing
  258. * color other than the background color, else use the background color
  259. * when drawing so that an erasure happens.
  260. */
  261. bool isDark = !(m_LayerNegative ^ m_imageParams->m_ImageNegative);
  262. if( !isDark )
  263. {
  264. // draw in background color ("negative" color)
  265. EXCHG( color, alt_color );
  266. }
  267. GRSetDrawMode( aDC, aDrawMode );
  268. isFilled = gerbFrame->DisplayLinesSolidMode();
  269. switch( m_Shape )
  270. {
  271. case GBR_POLYGON:
  272. isFilled = gerbFrame->DisplayPolygonsSolidMode();
  273. if( !isDark )
  274. isFilled = true;
  275. DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled );
  276. break;
  277. case GBR_CIRCLE:
  278. radius = KiROUND( GetLineLength( m_Start, m_End ) );
  279. halfPenWidth = m_Size.x >> 1;
  280. if( !isFilled )
  281. {
  282. // draw the border of the pen's path using two circles, each as narrow as possible
  283. GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  284. radius - halfPenWidth, 0, color );
  285. GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  286. radius + halfPenWidth, 0, color );
  287. }
  288. else // Filled mode
  289. {
  290. GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  291. radius, m_Size.x, color );
  292. }
  293. break;
  294. case GBR_ARC:
  295. // Currently, arcs plotted with a rectangular aperture are not supported.
  296. // a round pen only is expected.
  297. #if 0 // for arc debug only
  298. GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  299. GetABPosition( m_ArcCentre ), 0, color );
  300. GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_End ),
  301. GetABPosition( m_ArcCentre ), 0, color );
  302. #endif
  303. if( !isFilled )
  304. {
  305. GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  306. GetABPosition( m_End ), GetABPosition( m_ArcCentre ),
  307. 0, color );
  308. }
  309. else
  310. {
  311. GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  312. GetABPosition( m_End ), GetABPosition( m_ArcCentre ),
  313. m_Size.x, color );
  314. }
  315. break;
  316. case GBR_SPOT_CIRCLE:
  317. case GBR_SPOT_RECT:
  318. case GBR_SPOT_OVAL:
  319. case GBR_SPOT_POLY:
  320. case GBR_SPOT_MACRO:
  321. isFilled = gerbFrame->DisplayFlashedItemsSolidMode();
  322. d_codeDescr->DrawFlashedShape( this, aPanel->GetClipBox(), aDC, color, alt_color,
  323. m_Start, isFilled );
  324. break;
  325. case GBR_SEGMENT:
  326. /* Plot a line from m_Start to m_End.
  327. * Usually, a round pen is used, but some gerber files use a rectangular pen
  328. * In fact, any aperture can be used to plot a line.
  329. * currently: only a square pen is handled (I believe using a polygon gives a strange plot).
  330. */
  331. if( d_codeDescr->m_Shape == APT_RECT )
  332. {
  333. if( m_PolyCorners.size() == 0 )
  334. ConvertSegmentToPolygon( );
  335. DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled );
  336. }
  337. else
  338. {
  339. if( !isFilled )
  340. {
  341. GRCSegm( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  342. GetABPosition( m_End ), m_Size.x, color );
  343. }
  344. else
  345. {
  346. GRFilledSegment( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ),
  347. GetABPosition( m_End ), m_Size.x, color );
  348. }
  349. }
  350. break;
  351. default:
  352. if( !show_err )
  353. {
  354. wxMessageBox( wxT( "Trace_Segment() type error" ) );
  355. show_err = true;
  356. }
  357. break;
  358. }
  359. }
  360. void GERBER_DRAW_ITEM::ConvertSegmentToPolygon( )
  361. {
  362. m_PolyCorners.clear();
  363. m_PolyCorners.reserve(6);
  364. wxPoint start = m_Start;
  365. wxPoint end = m_End;
  366. // make calculations more easy if ensure start.x < end.x
  367. // (only 2 quadrants to consider)
  368. if( start.x > end.x )
  369. EXCHG( start, end );
  370. // calculate values relative to start point:
  371. wxPoint delta = end - start;
  372. // calculate corners for the first quadrant only (delta.x and delta.y > 0 )
  373. // currently, delta.x already is > 0.
  374. // make delta.y > 0
  375. bool change = delta.y < 0;
  376. if( change )
  377. NEGATE( delta.y);
  378. // Now create the full polygon.
  379. // Due to previous changes, the shape is always something like
  380. // 3 4
  381. // 2 5
  382. // 1 6
  383. wxPoint corner;
  384. corner.x -= m_Size.x/2;
  385. corner.y -= m_Size.y/2;
  386. m_PolyCorners.push_back( corner ); // Lower left corner, start point (1)
  387. corner.y += m_Size.y;
  388. m_PolyCorners.push_back( corner ); // upper left corner, start point (2)
  389. if( delta.x || delta.y)
  390. {
  391. corner += delta;
  392. m_PolyCorners.push_back( corner ); // upper left corner, end point (3)
  393. }
  394. corner.x += m_Size.x;
  395. m_PolyCorners.push_back( corner ); // upper right corner, end point (4)
  396. corner.y -= m_Size.y;
  397. m_PolyCorners.push_back( corner ); // lower right corner, end point (5)
  398. if( delta.x || delta.y )
  399. {
  400. corner -= delta;
  401. m_PolyCorners.push_back( corner ); // lower left corner, start point (6)
  402. }
  403. // Create final polygon:
  404. for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ )
  405. {
  406. if( change )
  407. NEGATE( m_PolyCorners[ii].y);
  408. m_PolyCorners[ii] += start;
  409. }
  410. }
  411. void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_RECT* aClipBox,
  412. wxDC* aDC,
  413. EDA_COLOR_T aColor,
  414. const wxPoint& aOffset,
  415. bool aFilledShape )
  416. {
  417. std::vector<wxPoint> points;
  418. points = m_PolyCorners;
  419. for( unsigned ii = 0; ii < points.size(); ii++ )
  420. {
  421. points[ii] += aOffset;
  422. points[ii] = GetABPosition( points[ii] );
  423. }
  424. GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilledShape, aColor, aColor );
  425. }
  426. void GERBER_DRAW_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
  427. {
  428. wxString msg;
  429. msg = ShowGBRShape();
  430. aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) );
  431. // Display D_Code value:
  432. msg.Printf( wxT( "%d" ), m_DCode );
  433. aList.push_back( MSG_PANEL_ITEM( _( "D Code" ), msg, RED ) );
  434. // Display graphic layer number
  435. msg.Printf( wxT( "%d" ), GetLayer() + 1 );
  436. aList.push_back( MSG_PANEL_ITEM( _( "Graphic Layer" ), msg, BROWN ) );
  437. // Display item rotation
  438. // The full rotation is Image rotation + m_lyrRotation
  439. // but m_lyrRotation is specific to this object
  440. // so we display only this parameter
  441. msg.Printf( wxT( "%f" ), m_lyrRotation );
  442. aList.push_back( MSG_PANEL_ITEM( _( "Rotation" ), msg, BLUE ) );
  443. // Display item polarity (item specific)
  444. msg = m_LayerNegative ? _("Clear") : _("Dark");
  445. aList.push_back( MSG_PANEL_ITEM( _( "Polarity" ), msg, BLUE ) );
  446. // Display mirroring (item specific)
  447. msg.Printf( wxT( "A:%s B:%s" ),
  448. m_mirrorA ? _("Yes") : _("No"),
  449. m_mirrorB ? _("Yes") : _("No"));
  450. aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), msg, DARKRED ) );
  451. // Display AB axis swap (item specific)
  452. msg = m_swapAxis ? wxT( "A=Y B=X" ) : wxT( "A=X B=Y" );
  453. aList.push_back( MSG_PANEL_ITEM( _( "AB axis" ), msg, DARKRED ) );
  454. }
  455. bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
  456. {
  457. // calculate aRefPos in XY gerber axis:
  458. wxPoint ref_pos = GetXYPosition( aRefPos );
  459. // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items)
  460. int radius = std::min( m_Size.x, m_Size.y ) >> 1;
  461. if( m_Flashed )
  462. return HitTestPoints( m_Start, ref_pos, radius );
  463. else
  464. return TestSegmentHit( ref_pos, m_Start, m_End, radius );
  465. }
  466. bool GERBER_DRAW_ITEM::HitTest( const EDA_RECT& aRefArea ) const
  467. {
  468. wxPoint pos = GetABPosition( m_Start );
  469. if( aRefArea.Contains( pos ) )
  470. return true;
  471. pos = GetABPosition( m_End );
  472. if( aRefArea.Contains( pos ) )
  473. return true;
  474. return false;
  475. }
  476. #if defined(DEBUG)
  477. void GERBER_DRAW_ITEM::Show( int nestLevel, std::ostream& os ) const
  478. {
  479. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  480. " shape=\"" << m_Shape << '"' <<
  481. " addr=\"" << std::hex << this << std::dec << '"' <<
  482. " layer=\"" << m_Layer << '"' <<
  483. " size=\"" << m_Size << '"' <<
  484. " flags=\"" << m_Flags << '"' <<
  485. " status=\"" << GetStatus() << '"' <<
  486. "<start" << m_Start << "/>" <<
  487. "<end" << m_End << "/>";
  488. os << "</" << GetClass().Lower().mb_str() << ">\n";
  489. }
  490. #endif