1. /*
  2. * @(#)Ellipse2D.java 1.15 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.geom;
  8. /**
  9. * The <code>Ellipse2D</code> class describes an ellipse that is defined
  10. * by a bounding rectangle.
  11. * <p>
  12. * This class is only the abstract superclass for all objects which
  13. * store a 2D ellipse.
  14. * The actual storage representation of the coordinates is left to
  15. * the subclass.
  16. *
  17. * @version 1.15, 01/23/03
  18. * @author Jim Graham
  19. */
  20. public abstract class Ellipse2D extends RectangularShape {
  21. /**
  22. * The <code>Float</code> class defines an ellipse specified
  23. * in <code>float</code> precision.
  24. */
  25. public static class Float extends Ellipse2D {
  26. /**
  27. * The x coordinate of the upper left corner of this
  28. * <code>Ellipse2D</code>.
  29. */
  30. public float x;
  31. /**
  32. * The y coordinate of the upper left corner of this
  33. * <code>Ellipse2D</code>.
  34. */
  35. public float y;
  36. /**
  37. * The overall width of this <code>Ellipse2D</code>.
  38. */
  39. public float width;
  40. /**
  41. * The overall height of this <code>Ellipse2D</code>.
  42. */
  43. public float height;
  44. /**
  45. * Constructs a new <code>Ellipse2D</code>, initialized to
  46. * location (0, 0) and size (0, 0).
  47. */
  48. public Float() {
  49. }
  50. /**
  51. * Constructs and initializes an <code>Ellipse2D</code> from the
  52. * specified coordinates.
  53. * @param x, y the coordinates of the bounding rectangle
  54. * @param w the width of the bounding rectangle
  55. * @param h the height of the bounding rectangle
  56. */
  57. public Float(float x, float y, float w, float h) {
  58. setFrame(x, y, w, h);
  59. }
  60. /**
  61. * Returns the X coordinate of the upper left corner of this
  62. * <code>Ellipse2D</code> in <code>double</code> precision.
  63. * @return the X coordinate of the upper left corner of the
  64. * bounding rectangle of this <code>Ellipse2D</code>.
  65. */
  66. public double getX() {
  67. return (double) x;
  68. }
  69. /**
  70. * Returns the Y coordinate of the upper left corner of this
  71. * <code>Ellipse2D</code> in <code>double</code> precision.
  72. * @return the Y coordinate of the upper left corner of the
  73. * bounding rectangle of this <code>Ellipse2D</code>.
  74. */
  75. public double getY() {
  76. return (double) y;
  77. }
  78. /**
  79. * Returns the overall width of this <code>Ellipse2D</code> in
  80. * <code>double</code> precision.
  81. * @return the width of this <code>Ellipse2D</code>.
  82. */
  83. public double getWidth() {
  84. return (double) width;
  85. }
  86. /**
  87. * Returns the overall height of this <code>Ellipse2D</code> in
  88. * <code>double</code> precision.
  89. * @return the height of this <code>Ellipse2D</code>.
  90. */
  91. public double getHeight() {
  92. return (double) height;
  93. }
  94. /**
  95. * Determines whether or not the bounding box of this
  96. * <code>Ellipse2D</code> is empty.
  97. * @return <code>true</code> if the bounding rectangle of this
  98. * <code>Ellipse2D</code> is empty; <code>false</code> otherwise.
  99. */
  100. public boolean isEmpty() {
  101. return (width <= 0.0 || height <= 0.0);
  102. }
  103. /**
  104. * Sets the location and size of this <code>Ellipse2D</code> to
  105. * the specified <code>float</code> values.
  106. * @param x, y the specified coordinates to which to set
  107. * the location of the bounding box of this <code>Ellipse2D</code>
  108. * @param w the specified width to which to set the width of
  109. * this <code>Ellipse2D</code>
  110. * @param h the specified height to which to set the height of
  111. * the <code>Ellipse2D</code>
  112. */
  113. public void setFrame(float x, float y, float w, float h) {
  114. this.x = x;
  115. this.y = y;
  116. this.width = w;
  117. this.height = h;
  118. }
  119. /**
  120. * Sets the location and size of this <code>Ellipse2D</code> to
  121. * the specified <code>double</code> values.
  122. * @param x, y the specified coordinates to which to set
  123. * the location of the bounding box of this <code>Ellipse2D</code>
  124. * @param w the specified width to which to set the width of
  125. * this <code>Ellipse2D</code>
  126. * @param h the specified height to which to set the height of
  127. * this <code>Ellipse2D</code>
  128. */
  129. public void setFrame(double x, double y, double w, double h) {
  130. this.x = (float) x;
  131. this.y = (float) y;
  132. this.width = (float) w;
  133. this.height = (float) h;
  134. }
  135. /**
  136. * Returns the high precision bounding box of this
  137. * <code>Ellipse2D</code>.
  138. * @return a {@link Rectangle2D} that is the bounding box
  139. * of this <code>Ellipse2D</code>.
  140. */
  141. public Rectangle2D getBounds2D() {
  142. return new Rectangle2D.Float(x, y, width, height);
  143. }
  144. }
  145. /**
  146. * The <code>Double</code> class defines an ellipse specified
  147. * in <code>double</code> precision.
  148. */
  149. public static class Double extends Ellipse2D {
  150. /**
  151. * The x coordinate of the upper left corner of this
  152. * <code>Ellipse2D</code>.
  153. */
  154. public double x;
  155. /**
  156. * The y coordinate of the upper left corner of this
  157. * <code>Ellipse2D</code>.
  158. */
  159. public double y;
  160. /**
  161. * The overall width of this <code>Ellipse2D</code>.
  162. */
  163. public double width;
  164. /**
  165. * The overall height of the <code>Ellipse2D</code>.
  166. */
  167. public double height;
  168. /**
  169. * Constructs a new <code>Ellipse2D</code>, initialized to
  170. * location (0, 0) and size (0, 0).
  171. */
  172. public Double() {
  173. }
  174. /**
  175. * Constructs and initializes an <code>Ellipse2D</code> from the
  176. * specified coordinates.
  177. * @param x, y the coordinates of the bounding rectangle
  178. * @param w the width of the rectangle
  179. * @param h the height of the rectangle
  180. */
  181. public Double(double x, double y, double w, double h) {
  182. setFrame(x, y, w, h);
  183. }
  184. /**
  185. * Returns the X coordinate of the upper left corner of this
  186. * <code>Ellipse2D</code> in <code>double</code> precision.
  187. * @return the X coordinate of the upper left corner of
  188. * the bounding box of this <code>Ellipse2D</code>.
  189. */
  190. public double getX() {
  191. return x;
  192. }
  193. /**
  194. * Returns the Y coordinate of the upper left corner of this
  195. * <code>Ellipse2D</code> in <code>double</code> precision.
  196. * @return the Y coordinate of the upper left corner of
  197. * the bounding box of this <code>Ellipse2D</code>.
  198. */
  199. public double getY() {
  200. return y;
  201. }
  202. /**
  203. * Returns the overall width of this <code>Ellipse2D</code>
  204. * in <code>double</code> precision.
  205. * @return the width of this <code>Ellipse2D</code>.
  206. */
  207. public double getWidth() {
  208. return width;
  209. }
  210. /**
  211. * Returns the overall height of this <code>Ellipse2D</code>
  212. * in <code>double</code> precision.
  213. * @return the height of this <code>Ellipse2D</code>.
  214. */
  215. public double getHeight() {
  216. return height;
  217. }
  218. /**
  219. * Determines whether or not the bounding box of this
  220. * <code>Ellipse2D</code> is empty.
  221. * @return <code>true</code> if the bounding box of this
  222. * <code>Ellipse2D</code> is empty;
  223. * <code>false</code> otherwise.
  224. */
  225. public boolean isEmpty() {
  226. return (width <= 0.0 || height <= 0.0);
  227. }
  228. /**
  229. * Sets the location and size of this <code>Ellipse2D</code>
  230. * to the specified <code>double</code> values.
  231. * @param x, y the specified coordinates to which to set
  232. * the location of the bounding box of this <code>Ellipse2D</code>
  233. * @param w the width to which to set the width of this
  234. * <code>Ellipse2D</code>
  235. * @param h the height to which to set the height of this
  236. * <code>Ellipse2D</code>
  237. */
  238. public void setFrame(double x, double y, double w, double h) {
  239. this.x = x;
  240. this.y = y;
  241. this.width = w;
  242. this.height = h;
  243. }
  244. /**
  245. * Returns the high precision bounding box of this
  246. * <code>Ellipse2D</code>.
  247. * @return a <code>Rectangle2D</code> that is the bounding
  248. * box of this <code>Ellipse2D</code>.
  249. */
  250. public Rectangle2D getBounds2D() {
  251. return new Rectangle2D.Double(x, y, width, height);
  252. }
  253. }
  254. /**
  255. * This is an abstract class that cannot be instantiated directly.
  256. * Type-specific implementation subclasses are available for
  257. * instantiation and provide a number of formats for storing
  258. * the information necessary to satisfy the various accessor
  259. * methods below.
  260. *
  261. * @see java.awt.geom.Ellipse2D.Float
  262. * @see java.awt.geom.Ellipse2D.Double
  263. */
  264. protected Ellipse2D() {
  265. }
  266. /**
  267. * Tests if a specified point is inside the boundary of this
  268. * <code>Ellipse2D</code>.
  269. * @param x, y the coordinates to test
  270. * @return <code>true</code> if the specified point is contained
  271. * in this ellipse; <code>false</code> otherwise.
  272. */
  273. public boolean contains(double x, double y) {
  274. // Normalize the coordinates compared to the ellipse
  275. // having a center at 0,0 and a radius of 0.5.
  276. double ellw = getWidth();
  277. if (ellw <= 0.0) {
  278. return false;
  279. }
  280. double normx = (x - getX()) / ellw - 0.5;
  281. double ellh = getHeight();
  282. if (ellh <= 0.0) {
  283. return false;
  284. }
  285. double normy = (y - getY()) / ellh - 0.5;
  286. return (normx * normx + normy * normy) < 0.25;
  287. }
  288. /**
  289. * Tests if the interior of this <code>Ellipse2D</code> intersects
  290. * the interior of a specified rectangular area.
  291. * @param x, y the coordinates of the upper left corner of the
  292. * specified rectangular area
  293. * @param w the width of the specified rectangular area
  294. * @param h the height of the specified rectangluar area
  295. * @return <code>true</code> if this <code>Ellipse2D</code> contains
  296. * the specified rectangular area; <code>false</code> otherwise.
  297. */
  298. public boolean intersects(double x, double y, double w, double h) {
  299. if (w <= 0.0 || h <= 0.0) {
  300. return false;
  301. }
  302. // Normalize the rectangular coordinates compared to the ellipse
  303. // having a center at 0,0 and a radius of 0.5.
  304. double ellw = getWidth();
  305. if (ellw <= 0.0) {
  306. return false;
  307. }
  308. double normx0 = (x - getX()) / ellw - 0.5;
  309. double normx1 = normx0 + w / ellw;
  310. double ellh = getHeight();
  311. if (ellh <= 0.0) {
  312. return false;
  313. }
  314. double normy0 = (y - getY()) / ellh - 0.5;
  315. double normy1 = normy0 + h / ellh;
  316. // find nearest x (left edge, right edge, 0.0)
  317. // find nearest y (top edge, bottom edge, 0.0)
  318. // if nearest x,y is inside circle of radius 0.5, then intersects
  319. double nearx, neary;
  320. if (normx0 > 0.0) {
  321. // center to left of X extents
  322. nearx = normx0;
  323. } else if (normx1 < 0.0) {
  324. // center to right of X extents
  325. nearx = normx1;
  326. } else {
  327. nearx = 0.0;
  328. }
  329. if (normy0 > 0.0) {
  330. // center above Y extents
  331. neary = normy0;
  332. } else if (normy1 < 0.0) {
  333. // center below Y extents
  334. neary = normy1;
  335. } else {
  336. neary = 0.0;
  337. }
  338. return (nearx * nearx + neary * neary) < 0.25;
  339. }
  340. /**
  341. * Tests if the interior of this <code>Ellipse2D</code> entirely
  342. * contains the specified rectangular area.
  343. * @param x, y the coordinates of the upper left corner of the
  344. * specified rectangular area
  345. * @param w the width of the specified rectangular area
  346. * @param h the height of the specified rectangular area
  347. * @return <code>true</code> if this <code>Ellipse2D</code> contains
  348. * the specified rectangular area; <code>false</code> otherwise.
  349. */
  350. public boolean contains(double x, double y, double w, double h) {
  351. return (contains(x, y) &&
  352. contains(x + w, y) &&
  353. contains(x, y + h) &&
  354. contains(x + w, y + h));
  355. }
  356. /**
  357. * Returns an iteration object that defines the boundary of this
  358. * <code>Ellipse2D</code>.
  359. * The iterator for this class is multi-threaded safe, which means
  360. * that this <code>Ellipse2D</code> class guarantees that
  361. * modifications to the geometry of this <code>Ellipse2D</code>
  362. * object do not affect any iterations of that geometry that
  363. * are already in process.
  364. * @param at an optional <code>AffineTransform</code> to be applied to
  365. * the coordinates as they are returned in the iteration, or
  366. * <code>null</code> if untransformed coordinates are desired
  367. * @return the <code>PathIterator</code> object that returns the
  368. * geometry of the outline of this <code>Ellipse2D</code>,
  369. * one segment at a time.
  370. */
  371. public PathIterator getPathIterator(AffineTransform at) {
  372. return new EllipseIterator(this, at);
  373. }
  374. }