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.

356 lines
10 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2004-2014 KiCad Developers, see change_log.txt for contributors.
  6. * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file eda_rect.h
  27. */
  28. #ifndef EDA_RECT_H
  29. #define EDA_RECT_H
  30. #include <wx/gdicmn.h>
  31. #include <math/box2.h>
  32. /**
  33. * EDA_RECT
  34. * handles the component boundary box.
  35. * This class is similar to wxRect, but some wxRect functions are very curious,
  36. * and are working only if dimensions are >= 0 (not always the case in KiCad)
  37. * and also KiCad needs some specific method.
  38. * so I prefer this more suitable class
  39. */
  40. class EDA_RECT
  41. {
  42. private:
  43. wxPoint m_Pos; // Rectangle Origin
  44. wxSize m_Size; // Rectangle Size
  45. bool m_init; // Is the rectangle initialized
  46. public:
  47. EDA_RECT() : m_init( false ) { };
  48. EDA_RECT( const wxPoint& aPos, const wxSize& aSize ) :
  49. m_Pos( aPos ),
  50. m_Size( aSize ),
  51. m_init( true )
  52. { }
  53. virtual ~EDA_RECT() { };
  54. wxPoint Centre() const
  55. {
  56. return wxPoint( m_Pos.x + ( m_Size.x >> 1 ),
  57. m_Pos.y + ( m_Size.y >> 1 ) );
  58. }
  59. /**
  60. * Function Move
  61. * moves the rectangle by the \a aMoveVector.
  62. * @param aMoveVector A wxPoint that is the value to move this rectangle
  63. */
  64. void Move( const wxPoint& aMoveVector );
  65. /**
  66. * Function Normalize
  67. * ensures that the height ant width are positive.
  68. */
  69. void Normalize();
  70. /**
  71. * Function Contains
  72. * @param aPoint = the wxPoint to test
  73. * @return true if aPoint is inside the boundary box. A point on a edge is seen as inside
  74. */
  75. bool Contains( const wxPoint& aPoint ) const;
  76. /**
  77. * Function Contains
  78. * @param x = the x coordinate of the point to test
  79. * @param y = the x coordinate of the point to test
  80. * @return true if point is inside the boundary box. A point on a edge is seen as inside
  81. */
  82. bool Contains( int x, int y ) const { return Contains( wxPoint( x, y ) ); }
  83. /**
  84. * Function Contains
  85. * @param aRect = the EDA_RECT to test
  86. * @return true if aRect is Contained. A common edge is seen as contained
  87. */
  88. bool Contains( const EDA_RECT& aRect ) const;
  89. const wxSize GetSize() const { return m_Size; }
  90. /**
  91. * @brief GetSizeMax
  92. * @return the max size dimension
  93. */
  94. int GetSizeMax() const { return ( m_Size.x > m_Size.y )?m_Size.x:m_Size.y; }
  95. int GetX() const { return m_Pos.x; }
  96. int GetY() const { return m_Pos.y; }
  97. const wxPoint GetOrigin() const { return m_Pos; }
  98. const wxPoint GetPosition() const { return m_Pos; }
  99. const wxPoint GetEnd() const { return wxPoint( m_Pos.x + m_Size.x, m_Pos.y + m_Size.y ); }
  100. const wxPoint GetCenter() const { return wxPoint( m_Pos.x + ( m_Size.x / 2 ), m_Pos.y + ( m_Size.y / 2 ) ); }
  101. int GetWidth() const { return m_Size.x; }
  102. int GetHeight() const { return m_Size.y; }
  103. int GetRight() const { return m_Pos.x + m_Size.x; }
  104. int GetLeft() const { return m_Pos.x; }
  105. int GetTop() const { return m_Pos.y; }
  106. int GetBottom() const { return m_Pos.y + m_Size.y; } // Y axis from top to bottom
  107. bool IsValid() const
  108. {
  109. return m_init;
  110. }
  111. void SetOrigin( const wxPoint &pos )
  112. {
  113. m_Pos = pos;
  114. m_init = true;
  115. }
  116. void SetOrigin( int x, int y )
  117. {
  118. m_Pos.x = x;
  119. m_Pos.y = y;
  120. m_init = true;
  121. }
  122. void SetSize( const wxSize &size )
  123. {
  124. m_Size = size;
  125. m_init = true;
  126. }
  127. void SetSize( int w, int h )
  128. {
  129. m_Size.x = w;
  130. m_Size.y = h;
  131. m_init = true;
  132. }
  133. void Offset( int dx, int dy )
  134. {
  135. m_Pos.x += dx;
  136. m_Pos.y += dy;
  137. }
  138. void Offset( const wxPoint &offset )
  139. {
  140. m_Pos += offset;
  141. }
  142. void SetX( int val )
  143. {
  144. m_Pos.x = val;
  145. m_init = true;
  146. }
  147. void SetY( int val )
  148. {
  149. m_Pos.y = val;
  150. m_init = true;
  151. }
  152. void SetWidth( int val )
  153. {
  154. m_Size.x = val;
  155. m_init = true;
  156. }
  157. void SetHeight( int val )
  158. {
  159. m_Size.y = val;
  160. m_init = true;
  161. }
  162. void SetEnd( int x, int y )
  163. {
  164. SetEnd( wxPoint( x, y ) );
  165. m_init = true;
  166. }
  167. void SetEnd( const wxPoint &pos )
  168. {
  169. m_Size.x = pos.x - m_Pos.x;
  170. m_Size.y = pos.y - m_Pos.y;
  171. m_init = true;
  172. }
  173. /**
  174. * Function RevertYAxis
  175. * Mirror the rectangle from the X axis (negate Y pos and size)
  176. */
  177. void RevertYAxis()
  178. {
  179. m_Pos.y = -m_Pos.y;
  180. m_Size.y = -m_Size.y;
  181. Normalize();
  182. }
  183. /**
  184. * Function Intersects
  185. * tests for a common area between rectangles.
  186. *
  187. * @param aRect A rectangle to test intersection with.
  188. * @return bool - true if the argument rectangle intersects this rectangle.
  189. * (i.e. if the 2 rectangles have at least a common point)
  190. */
  191. bool Intersects( const EDA_RECT& aRect ) const;
  192. /**
  193. * Tests for a common area between this rectangle,
  194. * and a rectangle with arbitrary rotation
  195. *
  196. * @param aRect a rectangle to test intersection with
  197. * @param aRot rectangle rotation (in 1/10 degrees)
  198. */
  199. bool Intersects( const EDA_RECT& aRect, double aRot ) const;
  200. /**
  201. * Function Intersects
  202. * tests for a common area between a segment and this rectangle.
  203. *
  204. * @param aPoint1 First point of the segment to test intersection with.
  205. * @param aPoint2 Second point of the segment to test intersection with.
  206. * @return bool - true if the argument segment intersects this rectangle.
  207. * (i.e. if the segment and rectangle have at least a common point)
  208. */
  209. bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;
  210. /**
  211. * Return the point in this rect that is closest to the provided point
  212. */
  213. const wxPoint ClosestPointTo( const wxPoint& aPoint ) const;
  214. /**
  215. * Return the point in this rect that is farthest from the provided point
  216. */
  217. const wxPoint FarthestPointTo( const wxPoint& aPoint ) const;
  218. /**
  219. * Function IntersectsCircle
  220. * tests for a common area between a circle and this rectangle
  221. *
  222. * @param aCenter center of the circle
  223. * @param aRadius radius of the circle
  224. */
  225. bool IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const;
  226. /**
  227. * IntersectsCircleEdge
  228. * Tests for intersection between this rect and the edge (radius) of a circle
  229. *
  230. * @param aCenter center of the circle
  231. * @param aRadius radius of the circle
  232. * @param aWidth width of the circle edge
  233. */
  234. bool IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const;
  235. /**
  236. * Function operator(wxRect)
  237. * overloads the cast operator to return a wxRect
  238. * wxRect does not accept negative values for size, so ensure the
  239. * wxRect size is always >= 0
  240. */
  241. operator wxRect() const
  242. {
  243. EDA_RECT rect( m_Pos, m_Size );
  244. rect.Normalize();
  245. return wxRect( rect.m_Pos, rect.m_Size );
  246. }
  247. /**
  248. * Function operator(BOX2I)
  249. * overloads the cast operator to return a BOX2I
  250. * @return BOX2I - this box shaped as a BOX2I object.
  251. */
  252. operator BOX2I() const
  253. {
  254. EDA_RECT rect( m_Pos, m_Size );
  255. rect.Normalize();
  256. return BOX2I( rect.GetOrigin(), rect.GetSize() );
  257. }
  258. /**
  259. * Function Inflate
  260. * inflates the rectangle horizontally by \a dx and vertically by \a dy. If \a dx
  261. * and/or \a dy is negative the rectangle is deflated.
  262. */
  263. EDA_RECT& Inflate( wxCoord dx, wxCoord dy );
  264. /**
  265. * Function Inflate
  266. * inflates the rectangle horizontally and vertically by \a aDelta. If \a aDelta
  267. * is negative the rectangle is deflated.
  268. */
  269. EDA_RECT& Inflate( int aDelta );
  270. /**
  271. * Function Merge
  272. * modifies the position and size of the rectangle in order to contain \a aRect. It is
  273. * mainly used to calculate bounding boxes.
  274. * @param aRect The rectangle to merge with this rectangle.
  275. */
  276. void Merge( const EDA_RECT& aRect );
  277. /**
  278. * Function Merge
  279. * modifies the position and size of the rectangle in order to contain the given point.
  280. * @param aPoint The point to merge with the rectangle.
  281. */
  282. void Merge( const wxPoint& aPoint );
  283. /**
  284. * Function GetArea
  285. * returns the area of the rectangle.
  286. * @return The area of the rectangle.
  287. */
  288. double GetArea() const;
  289. /**
  290. * Function Common
  291. * returns the area that is common with another rectangle.
  292. * @param aRect is the rectangle to find the common area with.
  293. * @return The common area rect or 0-sized rectangle if there is no intersection.
  294. */
  295. EDA_RECT Common( const EDA_RECT& aRect ) const;
  296. /**
  297. * Function GetBoundingBoxRotated
  298. * @return the bounding box of this, after rotation
  299. * @param aAngle = the rotation angle in 0.1 deg.
  300. * @param aRotCenter = the rotation point.
  301. * useful to calculate bounding box of rotated items, when
  302. * rotation if not k*90 degrees
  303. */
  304. const EDA_RECT GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle );
  305. };
  306. #endif // EDA_RECT_H