1. /*
  2. * @(#)EllipseIterator.java 1.12 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.geom;
  8. import java.util.*;
  9. /**
  10. * A utility class to iterate over the path segments of an ellipse
  11. * through the PathIterator interface.
  12. *
  13. * @version 10 Feb 1997
  14. * @author Jim Graham
  15. */
  16. class EllipseIterator implements PathIterator {
  17. double x, y, w, h;
  18. AffineTransform affine;
  19. int index;
  20. EllipseIterator(Ellipse2D e, AffineTransform at) {
  21. this.x = e.getX();
  22. this.y = e.getY();
  23. this.w = e.getWidth();
  24. this.h = e.getHeight();
  25. this.affine = at;
  26. if (w < 0 || h < 0) {
  27. index = 6;
  28. }
  29. }
  30. /**
  31. * Return the winding rule for determining the insideness of the
  32. * path.
  33. * @see #WIND_EVEN_ODD
  34. * @see #WIND_NON_ZERO
  35. */
  36. public int getWindingRule() {
  37. return WIND_NON_ZERO;
  38. }
  39. /**
  40. * Tests if there are more points to read.
  41. * @return true if there are more points to read
  42. */
  43. public boolean isDone() {
  44. return index > 5;
  45. }
  46. /**
  47. * Moves the iterator to the next segment of the path forwards
  48. * along the primary direction of traversal as long as there are
  49. * more points in that direction.
  50. */
  51. public void next() {
  52. index++;
  53. }
  54. // ArcIterator.btan(Math.PI/2)
  55. public static final double CtrlVal = 0.5522847498307933;
  56. /*
  57. * ctrlpts contains the control points for a set of 4 cubic
  58. * bezier curves that approximate a circle of radius 0.5
  59. * centered at 0.5, 0.5
  60. */
  61. private static final double pcv = 0.5 + CtrlVal * 0.5;
  62. private static final double ncv = 0.5 - CtrlVal * 0.5;
  63. private static double ctrlpts[][] = {
  64. { 1.0, pcv, pcv, 1.0, 0.5, 1.0 },
  65. { ncv, 1.0, 0.0, pcv, 0.0, 0.5 },
  66. { 0.0, ncv, ncv, 0.0, 0.5, 0.0 },
  67. { pcv, 0.0, 1.0, ncv, 1.0, 0.5 }
  68. };
  69. /**
  70. * Returns the coordinates and type of the current path segment in
  71. * the iteration.
  72. * The return value is the path segment type:
  73. * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
  74. * A float array of length 6 must be passed in and may be used to
  75. * store the coordinates of the point(s).
  76. * Each point is stored as a pair of float x,y coordinates.
  77. * SEG_MOVETO and SEG_LINETO types will return one point,
  78. * SEG_QUADTO will return two points,
  79. * SEG_CUBICTO will return 3 points
  80. * and SEG_CLOSE will not return any points.
  81. * @see #SEG_MOVETO
  82. * @see #SEG_LINETO
  83. * @see #SEG_QUADTO
  84. * @see #SEG_CUBICTO
  85. * @see #SEG_CLOSE
  86. */
  87. public int currentSegment(float[] coords) {
  88. if (isDone()) {
  89. throw new NoSuchElementException("ellipse iterator out of bounds");
  90. }
  91. if (index == 5) {
  92. return SEG_CLOSE;
  93. }
  94. if (index == 0) {
  95. double ctrls[] = ctrlpts[3];
  96. coords[0] = (float) (x + ctrls[4] * w);
  97. coords[1] = (float) (y + ctrls[5] * h);
  98. if (affine != null) {
  99. affine.transform(coords, 0, coords, 0, 1);
  100. }
  101. return SEG_MOVETO;
  102. }
  103. double ctrls[] = ctrlpts[index - 1];
  104. coords[0] = (float) (x + ctrls[0] * w);
  105. coords[1] = (float) (y + ctrls[1] * h);
  106. coords[2] = (float) (x + ctrls[2] * w);
  107. coords[3] = (float) (y + ctrls[3] * h);
  108. coords[4] = (float) (x + ctrls[4] * w);
  109. coords[5] = (float) (y + ctrls[5] * h);
  110. if (affine != null) {
  111. affine.transform(coords, 0, coords, 0, 3);
  112. }
  113. return SEG_CUBICTO;
  114. }
  115. /**
  116. * Returns the coordinates and type of the current path segment in
  117. * the iteration.
  118. * The return value is the path segment type:
  119. * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE.
  120. * A double array of length 6 must be passed in and may be used to
  121. * store the coordinates of the point(s).
  122. * Each point is stored as a pair of double x,y coordinates.
  123. * SEG_MOVETO and SEG_LINETO types will return one point,
  124. * SEG_QUADTO will return two points,
  125. * SEG_CUBICTO will return 3 points
  126. * and SEG_CLOSE will not return any points.
  127. * @see #SEG_MOVETO
  128. * @see #SEG_LINETO
  129. * @see #SEG_QUADTO
  130. * @see #SEG_CUBICTO
  131. * @see #SEG_CLOSE
  132. */
  133. public int currentSegment(double[] coords) {
  134. if (isDone()) {
  135. throw new NoSuchElementException("ellipse iterator out of bounds");
  136. }
  137. if (index == 5) {
  138. return SEG_CLOSE;
  139. }
  140. if (index == 0) {
  141. double ctrls[] = ctrlpts[3];
  142. coords[0] = x + ctrls[4] * w;
  143. coords[1] = y + ctrls[5] * h;
  144. if (affine != null) {
  145. affine.transform(coords, 0, coords, 0, 1);
  146. }
  147. return SEG_MOVETO;
  148. }
  149. double ctrls[] = ctrlpts[index - 1];
  150. coords[0] = x + ctrls[0] * w;
  151. coords[1] = y + ctrls[1] * h;
  152. coords[2] = x + ctrls[2] * w;
  153. coords[3] = y + ctrls[3] * h;
  154. coords[4] = x + ctrls[4] * w;
  155. coords[5] = y + ctrls[5] * h;
  156. if (affine != null) {
  157. affine.transform(coords, 0, coords, 0, 3);
  158. }
  159. return SEG_CUBICTO;
  160. }
  161. }