RectangularShape.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* RectangularShape.java -- a rectangular frame for several generic shapes
  2. Copyright (C) 2000, 2002 Free Software Foundation
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.awt.geom;
  32. import java.awt.Rectangle;
  33. import java.awt.Shape;
  34. /**
  35. * This class provides a generic framework, and several helper methods, for
  36. * subclasses which represent geometric objects inside a rectangular frame.
  37. * This does not specify any geometry except for the bounding box.
  38. *
  39. * @author Tom Tromey <tromey@cygnus.com>
  40. * @author Eric Blake <ebb9@email.byu.edu>
  41. * @since 1.2
  42. * @see Arc2D
  43. * @see Ellipse2D
  44. * @see Rectangle2D
  45. * @see RoundRectangle2D
  46. * @status updated to 1.4
  47. */
  48. public abstract class RectangularShape implements Shape, Cloneable
  49. {
  50. /**
  51. * Default constructor.
  52. */
  53. protected RectangularShape()
  54. {
  55. }
  56. /**
  57. * Get the x coordinate of the upper-left corner of the framing rectangle.
  58. *
  59. * @return the x coordinate
  60. */
  61. public abstract double getX();
  62. /**
  63. * Get the y coordinate of the upper-left corner of the framing rectangle.
  64. *
  65. * @return the y coordinate
  66. */
  67. public abstract double getY();
  68. /**
  69. * Get the width of the framing rectangle.
  70. *
  71. * @return the width
  72. */
  73. public abstract double getWidth();
  74. /**
  75. * Get the height of the framing rectangle.
  76. *
  77. * @return the height
  78. */
  79. public abstract double getHeight();
  80. /**
  81. * Get the minimum x coordinate in the frame. This is misnamed, or else
  82. * Sun has a bug, because the implementation returns getX() even when
  83. * getWidth() is negative.
  84. *
  85. * @return the minimum x coordinate
  86. */
  87. public double getMinX()
  88. {
  89. return getX();
  90. }
  91. /**
  92. * Get the minimum y coordinate in the frame. This is misnamed, or else
  93. * Sun has a bug, because the implementation returns getY() even when
  94. * getHeight() is negative.
  95. *
  96. * @return the minimum y coordinate
  97. */
  98. public double getMinY()
  99. {
  100. return getY();
  101. }
  102. /**
  103. * Get the maximum x coordinate in the frame. This is misnamed, or else
  104. * Sun has a bug, because the implementation returns getX()+getWidth() even
  105. * when getWidth() is negative.
  106. *
  107. * @return the maximum x coordinate
  108. */
  109. public double getMaxX()
  110. {
  111. return getX() + getWidth();
  112. }
  113. /**
  114. * Get the maximum y coordinate in the frame. This is misnamed, or else
  115. * Sun has a bug, because the implementation returns getY()+getHeight() even
  116. * when getHeight() is negative.
  117. *
  118. * @return the maximum y coordinate
  119. */
  120. public double getMaxY()
  121. {
  122. return getY() + getHeight();
  123. }
  124. /**
  125. * Return the x coordinate of the center point of the framing rectangle.
  126. *
  127. * @return the central x coordinate
  128. */
  129. public double getCenterX()
  130. {
  131. return getX() + getWidth() / 2;
  132. }
  133. /**
  134. * Return the y coordinate of the center point of the framing rectangle.
  135. *
  136. * @return the central y coordinate
  137. */
  138. public double getCenterY()
  139. {
  140. return getY() + getHeight() / 2;
  141. }
  142. /**
  143. * Return the frame around this object. Note that this may be a looser
  144. * bounding box than getBounds2D.
  145. *
  146. * @return the frame, in double precision
  147. * @see #setFrame(double, double, double, double)
  148. */
  149. public Rectangle2D getFrame()
  150. {
  151. return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
  152. }
  153. /**
  154. * Test if the shape is empty, meaning that no points are inside it.
  155. *
  156. * @return true if the shape is empty
  157. */
  158. public abstract boolean isEmpty();
  159. /**
  160. * Set the framing rectangle of this shape to the given coordinate and size.
  161. *
  162. * @param x the new x coordinate
  163. * @param y the new y coordinate
  164. * @param w the new width
  165. * @param h the new height
  166. * @see #getFrame()
  167. */
  168. public abstract void setFrame(double x, double y, double w, double h);
  169. /**
  170. * Set the framing rectangle of this shape to the given coordinate and size.
  171. *
  172. * @param p the new point
  173. * @param d the new dimension
  174. * @throws NullPointerException if p or d is null
  175. * @see #getFrame()
  176. */
  177. public void setFrame(Point2D p, Dimension2D d)
  178. {
  179. setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight());
  180. }
  181. /**
  182. * Set the framing rectangle of this shape to the given rectangle.
  183. *
  184. * @param r the new framing rectangle
  185. * @throws NullPointerException if r is null
  186. * @see #getFrame()
  187. */
  188. public void setFrame(Rectangle2D r)
  189. {
  190. setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  191. }
  192. /**
  193. * Set the framing rectangle of this shape using two points on a diagonal.
  194. * The area will be positive.
  195. *
  196. * @param x1 the first x coordinate
  197. * @param y1 the first y coordinate
  198. * @param x2 the second x coordinate
  199. * @param y2 the second y coordinate
  200. */
  201. public void setFrameFromDiagonal(double x1, double y1, double x2, double y2)
  202. {
  203. if (x1 > x2)
  204. {
  205. double t = x2;
  206. x2 = x1;
  207. x1 = t;
  208. }
  209. if (y1 > y2)
  210. {
  211. double t = y2;
  212. y2 = y1;
  213. y1 = t;
  214. }
  215. setFrame(x1, y1, x2 - x1, y2 - y1);
  216. }
  217. /**
  218. * Set the framing rectangle of this shape using two points on a diagonal.
  219. * The area will be positive.
  220. *
  221. * @param p1 the first point
  222. * @param p2 the second point
  223. * @throws NullPointerException if either point is null
  224. */
  225. public void setFrameFromDiagonal(Point2D p1, Point2D p2)
  226. {
  227. setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
  228. }
  229. /**
  230. * Set the framing rectangle of this shape using the center of the frame,
  231. * and one of the four corners. The area will be positive.
  232. *
  233. * @param centerX the x coordinate at the center
  234. * @param centerY the y coordinate at the center
  235. * @param cornerX the x coordinate at a corner
  236. * @param cornerY the y coordinate at a corner
  237. */
  238. public void setFrameFromCenter(double centerX, double centerY,
  239. double cornerX, double cornerY)
  240. {
  241. double halfw = Math.abs(cornerX - centerX);
  242. double halfh = Math.abs(cornerY - centerY);
  243. setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh);
  244. }
  245. /**
  246. * Set the framing rectangle of this shape using the center of the frame,
  247. * and one of the four corners. The area will be positive.
  248. *
  249. * @param center the center point
  250. * @param corner a corner point
  251. * @throws NullPointerException if either point is null
  252. */
  253. public void setFrameFromCenter(Point2D center, Point2D corner)
  254. {
  255. setFrameFromCenter(center.getX(), center.getY(),
  256. corner.getX(), corner.getY());
  257. }
  258. /**
  259. * Tests if a point is inside the boundary of the shape.
  260. *
  261. * @param p the point to test
  262. * @return true if the point is inside the shape
  263. * @throws NullPointerException if p is null
  264. * @see #contains(double, double)
  265. */
  266. public boolean contains(Point2D p)
  267. {
  268. return contains(p.getX(), p.getY());
  269. }
  270. /**
  271. * Tests if a rectangle and this shape share common internal points.
  272. *
  273. * @param r the rectangle to test
  274. * @return true if the rectangle intersects this shpae
  275. * @throws NullPointerException if r is null
  276. * @see #intersects(double, double, double, double)
  277. */
  278. public boolean intersects(Rectangle2D r)
  279. {
  280. return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  281. }
  282. /**
  283. * Tests if the shape completely contains the given rectangle.
  284. *
  285. * @param r the rectangle to test
  286. * @return true if r is contained in this shape
  287. * @throws NullPointerException if r is null
  288. * @see #contains(double, double, double, double)
  289. */
  290. public boolean contains(Rectangle2D r)
  291. {
  292. return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
  293. }
  294. /**
  295. * Returns a bounding box for this shape, in integer format. Notice that you
  296. * may get a tighter bound with getBounds2D. If the frame is empty, the
  297. * box is the default empty box at the origin.
  298. *
  299. * @return a bounding box
  300. */
  301. public Rectangle getBounds()
  302. {
  303. if (isEmpty())
  304. return new Rectangle();
  305. double x = getX();
  306. double y = getY();
  307. double maxx = Math.ceil(x + getWidth());
  308. double maxy = Math.ceil(y + getHeight());
  309. x = Math.floor(x);
  310. y = Math.floor(y);
  311. return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y));
  312. }
  313. /**
  314. * Return an iterator along the shape boundary. If the optional transform
  315. * is provided, the iterator is transformed accordingly. The path is
  316. * flattened until all segments differ from the curve by at most the value
  317. * of the flatness parameter, within the limits of the default interpolation
  318. * recursion limit of 1024 segments between actual points. Each call
  319. * returns a new object, independent from others in use. The result is
  320. * threadsafe if and only if the iterator returned by
  321. * {@link #getPathIterator(AffineTransform)} is as well.
  322. *
  323. * @param transform an optional transform to apply to the iterator
  324. * @param flatness the desired flatness
  325. * @return a new iterator over the boundary
  326. * @throws IllegalArgumentException if flatness is invalid
  327. * @since 1.2
  328. */
  329. public PathIterator getPathIterator(AffineTransform at, double flatness)
  330. {
  331. return new FlatteningPathIterator(getPathIterator(at), flatness);
  332. }
  333. /**
  334. * Create a new shape of the same run-time type with the same contents as
  335. * this one.
  336. *
  337. * @return the clone
  338. */
  339. public Object clone()
  340. {
  341. try
  342. {
  343. return super.clone();
  344. }
  345. catch (CloneNotSupportedException e)
  346. {
  347. throw (Error) new InternalError().initCause(e); // Impossible
  348. }
  349. }
  350. } // class RectangularShape