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