1 7 8 package java.awt.geom; 9 10 32 public abstract class Arc2D extends RectangularShape { 33 37 public final static int OPEN = 0; 38 39 44 public final static int CHORD = 1; 45 46 51 public final static int PIE = 2; 52 53 56 public static class Float extends Arc2D { 57 58 61 public float x; 62 63 66 public float y; 67 68 73 public float width; 74 75 80 public float height; 81 82 85 public float start; 86 87 90 public float extent; 91 92 96 public Float() { 97 super(OPEN); 98 } 99 100 108 public Float(int type) { 109 super(type); 110 } 111 112 129 public Float(float x, float y, float w, float h, 130 float start, float extent, int type) { 131 super(type); 132 this.x = x; 133 this.y = y; 134 this.width = w; 135 this.height = h; 136 this.start = start; 137 this.extent = extent; 138 } 139 140 154 public Float(Rectangle2D ellipseBounds, 155 float start, float extent, int type) { 156 super(type); 157 this.x = (float) ellipseBounds.getX(); 158 this.y = (float) ellipseBounds.getY(); 159 this.width = (float) ellipseBounds.getWidth(); 160 this.height = (float) ellipseBounds.getHeight(); 161 this.start = start; 162 this.extent = extent; 163 } 164 165 171 public double getX() { 172 return (double) x; 173 } 174 175 181 public double getY() { 182 return (double) y; 183 } 184 185 192 public double getWidth() { 193 return (double) width; 194 } 195 196 203 public double getHeight() { 204 return (double) height; 205 } 206 207 214 public double getAngleStart() { 215 return (double) start; 216 } 217 218 225 public double getAngleExtent() { 226 return (double) extent; 227 } 228 229 235 public boolean isEmpty() { 236 return (width <= 0.0 || height <= 0.0); 237 } 238 239 254 public void setArc(double x, double y, double w, double h, 255 double angSt, double angExt, int closure) { 256 this.setArcType(closure); 257 this.x = (float) x; 258 this.y = (float) y; 259 this.width = (float) w; 260 this.height = (float) h; 261 this.start = (float) angSt; 262 this.extent = (float) angExt; 263 } 264 265 272 public void setAngleStart(double angSt) { 273 this.start = (float) angSt; 274 } 275 276 283 public void setAngleExtent(double angExt) { 284 this.extent = (float) angExt; 285 } 286 287 299 protected Rectangle2D makeBounds(double x, double y, 300 double w, double h) { 301 return new Rectangle2D.Float ((float) x, (float) y, 302 (float) w, (float) h); 303 } 304 } 305 306 309 public static class Double extends Arc2D { 310 313 public double x; 314 315 318 public double y; 319 320 324 public double width; 325 326 330 public double height; 331 332 335 public double start; 336 337 340 public double extent; 341 342 346 public Double() { 347 super(OPEN); 348 } 349 350 358 public Double(int type) { 359 super(type); 360 } 361 362 379 public Double(double x, double y, double w, double h, 380 double start, double extent, int type) { 381 super(type); 382 this.x = x; 383 this.y = y; 384 this.width = w; 385 this.height = h; 386 this.start = start; 387 this.extent = extent; 388 } 389 390 404 public Double(Rectangle2D ellipseBounds, 405 double start, double extent, int type) { 406 super(type); 407 this.x = ellipseBounds.getX(); 408 this.y = ellipseBounds.getY(); 409 this.width = ellipseBounds.getWidth(); 410 this.height = ellipseBounds.getHeight(); 411 this.start = start; 412 this.extent = extent; 413 } 414 415 421 public double getX() { 422 return x; 423 } 424 425 431 public double getY() { 432 return y; 433 } 434 435 442 public double getWidth() { 443 return width; 444 } 445 446 453 public double getHeight() { 454 return height; 455 } 456 457 464 public double getAngleStart() { 465 return start; 466 } 467 468 475 public double getAngleExtent() { 476 return extent; 477 } 478 479 485 public boolean isEmpty() { 486 return (width <= 0.0 || height <= 0.0); 487 } 488 489 504 public void setArc(double x, double y, double w, double h, 505 double angSt, double angExt, int closure) { 506 this.setArcType(closure); 507 this.x = x; 508 this.y = y; 509 this.width = w; 510 this.height = h; 511 this.start = angSt; 512 this.extent = angExt; 513 } 514 515 522 public void setAngleStart(double angSt) { 523 this.start = angSt; 524 } 525 526 533 public void setAngleExtent(double angExt) { 534 this.extent = angExt; 535 } 536 537 549 protected Rectangle2D makeBounds(double x, double y, 550 double w, double h) { 551 return new Rectangle2D.Double (x, y, w, h); 552 } 553 } 554 555 private int type; 556 557 569 protected Arc2D(int type) { 570 setArcType(type); 571 } 572 573 580 public abstract double getAngleStart(); 581 582 589 public abstract double getAngleExtent(); 590 591 598 public int getArcType() { 599 return type; 600 } 601 602 610 public Point2D getStartPoint() { 611 double angle = Math.toRadians(-getAngleStart()); 612 double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth(); 613 double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight(); 614 return new Point2D.Double (x, y); 615 } 616 617 626 public Point2D getEndPoint() { 627 double angle = Math.toRadians(-getAngleStart() - getAngleExtent()); 628 double x = getX() + (Math.cos(angle) * 0.5 + 0.5) * getWidth(); 629 double y = getY() + (Math.sin(angle) * 0.5 + 0.5) * getHeight(); 630 return new Point2D.Double (x, y); 631 } 632 633 648 public abstract void setArc(double x, double y, double w, double h, 649 double angSt, double angExt, int closure); 650 651 667 public void setArc(Point2D loc, Dimension2D size, 668 double angSt, double angExt, int closure) { 669 setArc(loc.getX(), loc.getY(), size.getWidth(), size.getHeight(), 670 angSt, angExt, closure); 671 } 672 673 687 public void setArc(Rectangle2D rect, double angSt, double angExt, 688 int closure) { 689 setArc(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight(), 690 angSt, angExt, closure); 691 } 692 693 698 public void setArc(Arc2D a) { 699 setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), 700 a.getAngleStart(), a.getAngleExtent(), a.type); 701 } 702 703 718 public void setArcByCenter(double x, double y, double radius, 719 double angSt, double angExt, int closure) { 720 setArc(x - radius, y - radius, radius * 2.0, radius * 2.0, 721 angSt, angExt, closure); 722 } 723 724 741 public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, 742 double radius) { 743 double ang1 = Math.atan2(p1.getY() - p2.getY(), 744 p1.getX() - p2.getX()); 745 double ang2 = Math.atan2(p3.getY() - p2.getY(), 746 p3.getX() - p2.getX()); 747 double diff = ang2 - ang1; 748 if (diff > Math.PI) { 749 ang2 -= Math.PI * 2.0; 750 } else if (diff < -Math.PI) { 751 ang2 += Math.PI * 2.0; 752 } 753 double bisect = (ang1 + ang2) / 2.0; 754 double theta = Math.abs(ang2 - bisect); 755 double dist = radius / Math.sin(theta); 756 double x = p2.getX() + dist * Math.cos(bisect); 757 double y = p2.getY() + dist * Math.sin(bisect); 758 if (ang1 < ang2) { 760 ang1 -= Math.PI / 2.0; 761 ang2 += Math.PI / 2.0; 762 } else { 763 ang1 += Math.PI / 2.0; 764 ang2 -= Math.PI / 2.0; 765 } 766 ang1 = Math.toDegrees(-ang1); 767 ang2 = Math.toDegrees(-ang2); 768 diff = ang2 - ang1; 769 if (diff < 0) { 770 diff += 360; 771 } else { 772 diff -= 360; 773 } 774 setArcByCenter(x, y, radius, ang1, diff, type); 775 } 776 777 784 public abstract void setAngleStart(double angSt); 785 786 793 public abstract void setAngleExtent(double angExt); 794 795 803 public void setAngleStart(Point2D p) { 804 double dx = getHeight() * (p.getX() - getCenterX()); 806 double dy = getWidth() * (p.getY() - getCenterY()); 807 setAngleStart(-Math.toDegrees(Math.atan2(dy, dx))); 808 } 809 810 822 public void setAngles(double x1, double y1, double x2, double y2) { 823 double x = getCenterX(); 824 double y = getCenterY(); 825 double w = getWidth(); 826 double h = getHeight(); 827 double ang1 = Math.atan2(w * (y - y1), h * (x1 - x)); 831 double ang2 = Math.atan2(w * (y - y2), h * (x2 - x)); 832 ang2 -= ang1; 833 if (ang2 <= 0.0) { 834 ang2 += Math.PI * 2.0; 835 } 836 setAngleStart(Math.toDegrees(ang1)); 837 setAngleExtent(Math.toDegrees(ang2)); 838 } 839 840 854 public void setAngles(Point2D p1, Point2D p2) { 855 setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY()); 856 } 857 858 870 public void setArcType(int type) { 871 if (type < OPEN || type > PIE) { 872 throw new IllegalArgumentException ("invalid type for Arc: "+type); 873 } 874 this.type = type; 875 } 876 877 888 public void setFrame(double x, double y, double w, double h) { 889 setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type); 890 } 891 892 907 public Rectangle2D getBounds2D() { 908 if (isEmpty()) { 909 return makeBounds(getX(), getY(), getWidth(), getHeight()); 910 } 911 double x1, y1, x2, y2; 912 if (getArcType() == PIE) { 913 x1 = y1 = x2 = y2 = 0.0; 914 } else { 915 x1 = y1 = 1.0; 916 x2 = y2 = -1.0; 917 } 918 double angle = 0.0; 919 for (int i = 0; i < 6; i++) { 920 if (i < 4) { 921 angle += 90.0; 923 if (!containsAngle(angle)) { 924 continue; 925 } 926 } else if (i == 4) { 927 angle = getAngleStart(); 929 } else { 930 angle += getAngleExtent(); 932 } 933 double rads = Math.toRadians(-angle); 934 double xe = Math.cos(rads); 935 double ye = Math.sin(rads); 936 x1 = Math.min(x1, xe); 937 y1 = Math.min(y1, ye); 938 x2 = Math.max(x2, xe); 939 y2 = Math.max(y2, ye); 940 } 941 double w = getWidth(); 942 double h = getHeight(); 943 x2 = (x2 - x1) * 0.5 * w; 944 y2 = (y2 - y1) * 0.5 * h; 945 x1 = getX() + (x1 * 0.5 + 0.5) * w; 946 y1 = getY() + (y1 * 0.5 + 0.5) * h; 947 return makeBounds(x1, y1, x2, y2); 948 } 949 950 964 protected abstract Rectangle2D makeBounds(double x, double y, 965 double w, double h); 966 967 970 static double normalizeDegrees(double angle) { 971 if (angle > 180.0) { 972 if (angle <= (180.0 + 360.0)) { 973 angle = angle - 360.0; 974 } else { 975 angle = Math.IEEEremainder(angle, 360.0); 976 if (angle == -180.0) { 978 angle = 180.0; 979 } 980 } 981 } else if (angle <= -180.0) { 982 if (angle > (-180.0 - 360.0)) { 983 angle = angle + 360.0; 984 } else { 985 angle = Math.IEEEremainder(angle, 360.0); 986 if (angle == -180.0) { 988 angle = 180.0; 989 } 990 } 991 } 992 return angle; 993 } 994 995 1004 public boolean containsAngle(double angle) { 1005 double angExt = getAngleExtent(); 1006 boolean backwards = (angExt < 0.0); 1007 if (backwards) { 1008 angExt = -angExt; 1009 } 1010 if (angExt >= 360.0) { 1011 return true; 1012 } 1013 angle = normalizeDegrees(angle) - normalizeDegrees(getAngleStart()); 1014 if (backwards) { 1015 angle = -angle; 1016 } 1017 if (angle < 0.0) { 1018 angle += 360.0; 1019 } 1020 1021 1022 return (angle >= 0.0) && (angle < angExt); 1023 } 1024 1025 1036 public boolean contains(double x, double y) { 1037 double ellw = getWidth(); 1040 if (ellw <= 0.0) { 1041 return false; 1042 } 1043 double normx = (x - getX()) / ellw - 0.5; 1044 double ellh = getHeight(); 1045 if (ellh <= 0.0) { 1046 return false; 1047 } 1048 double normy = (y - getY()) / ellh - 0.5; 1049 double distSq = (normx * normx + normy * normy); 1050 if (distSq >= 0.25) { 1051 return false; 1052 } 1053 double angExt = Math.abs(getAngleExtent()); 1054 if (angExt >= 360.0) { 1055 return true; 1056 } 1057 boolean inarc = containsAngle(-Math.toDegrees(Math.atan2(normy, 1058 normx))); 1059 if (type == PIE) { 1060 return inarc; 1061 } 1062 if (inarc) { 1064 if (angExt >= 180.0) { 1065 return true; 1066 } 1067 } else { 1069 if (angExt <= 180.0) { 1070 return false; 1071 } 1072 } 1074 double angle = Math.toRadians(-getAngleStart()); 1077 double x1 = Math.cos(angle); 1078 double y1 = Math.sin(angle); 1079 angle += Math.toRadians(-getAngleExtent()); 1080 double x2 = Math.cos(angle); 1081 double y2 = Math.sin(angle); 1082 boolean inside = (Line2D.relativeCCW(x1, y1, x2, y2, 2*normx, 2*normy) * 1083 Line2D.relativeCCW(x1, y1, x2, y2, 0, 0) >= 0); 1084 return inarc ? !inside : inside; 1085 } 1086 1087 1099 1100 public boolean intersects(double x, double y, double w, double h) { 1101 1102 double aw = getWidth(); 1103 double ah = getHeight(); 1104 1105 if ( w <= 0 || h <= 0 || aw <= 0 || ah <= 0 ) { 1106 return false; 1107 } 1108 double ext = getAngleExtent(); 1109 if (ext == 0) { 1110 return false; 1111 } 1112 1113 double ax = getX(); 1114 double ay = getY(); 1115 double axw = ax + aw; 1116 double ayh = ay + ah; 1117 double xw = x + w; 1118 double yh = y + h; 1119 1120 if (x >= axw || y >= ayh || xw <= ax || yh <= ay) { 1122 return false; 1123 } 1124 1125 double axc = getCenterX(); 1127 double ayc = getCenterY(); 1128 Point2D sp = getStartPoint(); 1129 Point2D ep = getEndPoint(); 1130 double sx = sp.getX(); 1131 double sy = sp.getY(); 1132 double ex = ep.getX(); 1133 double ey = ep.getY(); 1134 1135 1145 if (ayc >= y && ayc <= yh) { if ((sx < xw && ex < xw && axc < xw && 1147 axw > x && containsAngle(0)) || 1148 (sx > x && ex > x && axc > x && 1149 ax < xw && containsAngle(180))) { 1150 return true; 1151 } 1152 } 1153 if (axc >= x && axc <= xw) { if ((sy > y && ey > y && ayc > y && 1155 ay < yh && containsAngle(90)) || 1156 (sy < yh && ey < yh && ayc < yh && 1157 ayh > y && containsAngle(270))) { 1158 return true; 1159 } 1160 } 1161 1162 1169 Rectangle2D rect = new Rectangle2D.Double (x, y, w, h); 1170 if (type == PIE || Math.abs(ext) > 180) { 1171 if (rect.intersectsLine(axc, ayc, sx, sy) || 1173 rect.intersectsLine(axc, ayc, ex, ey)) { 1174 return true; 1175 } 1176 } else { 1177 if (rect.intersectsLine(sx, sy, ex, ey)) { 1179 return true; 1180 } 1181 } 1182 1183 if (contains(x, y) || contains(x + w, y) || 1185 contains(x, y + h) || contains(x + w, y + h)) { 1186 return true; 1187 } 1188 1189 return false; 1190 } 1191 1192 1204 public boolean contains(double x, double y, double w, double h) { 1205 return contains(x, y, w, h, null); 1206 } 1207 1208 1217 public boolean contains(Rectangle2D r) { 1218 return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight(), r); 1219 } 1220 1221 private boolean contains(double x, double y, double w, double h, 1222 Rectangle2D origrect) { 1223 if (!(contains(x, y) && 1224 contains(x + w, y) && 1225 contains(x, y + h) && 1226 contains(x + w, y + h))) { 1227 return false; 1228 } 1229 if (type != PIE || Math.abs(getAngleExtent()) <= 180.0) { 1233 return true; 1234 } 1235 if (origrect == null) { 1242 origrect = new Rectangle2D.Double (x, y, w, h); 1243 } 1244 double halfW = getWidth() / 2.0; 1245 double halfH = getHeight() / 2.0; 1246 double xc = getX() + halfW; 1247 double yc = getY() + halfH; 1248 double angle = Math.toRadians(-getAngleStart()); 1249 double xe = xc + halfW * Math.cos(angle); 1250 double ye = yc + halfH * Math.sin(angle); 1251 if (origrect.intersectsLine(xc, yc, xe, ye)) { 1252 return false; 1253 } 1254 angle += Math.toRadians(-getAngleExtent()); 1255 xe = xc + halfW * Math.cos(angle); 1256 ye = yc + halfH * Math.sin(angle); 1257 return !origrect.intersectsLine(xc, yc, xe, ye); 1258 } 1259 1260 1275 public PathIterator getPathIterator(AffineTransform at) { 1276 return new ArcIterator (this, at); 1277 } 1278} 1279 | Popular Tags |