1 7 8 package java.awt.geom; 9 10 import java.awt.Shape ; 11 import java.awt.Rectangle ; 12 import java.util.Arrays ; 13 14 26 public abstract class CubicCurve2D implements Shape , Cloneable { 27 30 public static class Float extends CubicCurve2D { 31 35 public float x1; 36 37 41 public float y1; 42 43 47 public float ctrlx1; 48 49 53 public float ctrly1; 54 55 59 public float ctrlx2; 60 61 65 public float ctrly2; 66 67 71 public float x2; 72 73 77 public float y2; 78 79 83 public Float() { 84 } 85 86 100 public Float(float x1, float y1, 101 float ctrlx1, float ctrly1, 102 float ctrlx2, float ctrly2, 103 float x2, float y2) { 104 setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); 105 } 106 107 113 public double getX1() { 114 return (double) x1; 115 } 116 117 123 public double getY1() { 124 return (double) y1; 125 } 126 127 132 public Point2D getP1() { 133 return new Point2D.Float (x1, y1); 134 } 135 136 142 public double getCtrlX1() { 143 return (double) ctrlx1; 144 } 145 146 152 public double getCtrlY1() { 153 return (double) ctrly1; 154 } 155 156 161 public Point2D getCtrlP1() { 162 return new Point2D.Float (ctrlx1, ctrly1); 163 } 164 165 171 public double getCtrlX2() { 172 return (double) ctrlx2; 173 } 174 175 181 public double getCtrlY2() { 182 return (double) ctrly2; 183 } 184 185 190 public Point2D getCtrlP2() { 191 return new Point2D.Float (ctrlx2, ctrly2); 192 } 193 194 200 public double getX2() { 201 return (double) x2; 202 } 203 204 210 public double getY2() { 211 return (double) y2; 212 } 213 214 219 public Point2D getP2() { 220 return new Point2D.Float (x2, y2); 221 } 222 223 236 public void setCurve(double x1, double y1, 237 double ctrlx1, double ctrly1, 238 double ctrlx2, double ctrly2, 239 double x2, double y2) { 240 this.x1 = (float) x1; 241 this.y1 = (float) y1; 242 this.ctrlx1 = (float) ctrlx1; 243 this.ctrly1 = (float) ctrly1; 244 this.ctrlx2 = (float) ctrlx2; 245 this.ctrly2 = (float) ctrly2; 246 this.x2 = (float) x2; 247 this.y2 = (float) y2; 248 } 249 250 262 public void setCurve(float x1, float y1, 263 float ctrlx1, float ctrly1, 264 float ctrlx2, float ctrly2, 265 float x2, float y2) { 266 this.x1 = x1; 267 this.y1 = y1; 268 this.ctrlx1 = ctrlx1; 269 this.ctrly1 = ctrly1; 270 this.ctrlx2 = ctrlx2; 271 this.ctrly2 = ctrly2; 272 this.x2 = x2; 273 this.y2 = y2; 274 } 275 276 281 public Rectangle2D getBounds2D() { 282 float left = Math.min(Math.min(x1, x2), 283 Math.min(ctrlx1, ctrlx2)); 284 float top = Math.min(Math.min(y1, y2), 285 Math.min(ctrly1, ctrly2)); 286 float right = Math.max(Math.max(x1, x2), 287 Math.max(ctrlx1, ctrlx2)); 288 float bottom = Math.max(Math.max(y1, y2), 289 Math.max(ctrly1, ctrly2)); 290 return new Rectangle2D.Float (left, top, 291 right - left, bottom - top); 292 } 293 } 294 295 298 public static class Double extends CubicCurve2D { 299 303 public double x1; 304 305 309 public double y1; 310 311 315 public double ctrlx1; 316 317 321 public double ctrly1; 322 323 327 public double ctrlx2; 328 329 333 public double ctrly2; 334 335 339 public double x2; 340 341 345 public double y2; 346 347 351 public Double() { 352 } 353 354 368 public Double(double x1, double y1, 369 double ctrlx1, double ctrly1, 370 double ctrlx2, double ctrly2, 371 double x2, double y2) { 372 setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); 373 } 374 375 381 public double getX1() { 382 return x1; 383 } 384 385 391 public double getY1() { 392 return y1; 393 } 394 395 400 public Point2D getP1() { 401 return new Point2D.Double (x1, y1); 402 } 403 404 410 public double getCtrlX1() { 411 return ctrlx1; 412 } 413 414 420 public double getCtrlY1() { 421 return ctrly1; 422 } 423 424 429 public Point2D getCtrlP1() { 430 return new Point2D.Double (ctrlx1, ctrly1); 431 } 432 433 439 public double getCtrlX2() { 440 return ctrlx2; 441 } 442 443 449 public double getCtrlY2() { 450 return ctrly2; 451 } 452 453 458 public Point2D getCtrlP2() { 459 return new Point2D.Double (ctrlx2, ctrly2); 460 } 461 462 468 public double getX2() { 469 return x2; 470 } 471 472 478 public double getY2() { 479 return y2; 480 } 481 482 487 public Point2D getP2() { 488 return new Point2D.Double (x2, y2); 489 } 490 491 503 public void setCurve(double x1, double y1, 504 double ctrlx1, double ctrly1, 505 double ctrlx2, double ctrly2, 506 double x2, double y2) { 507 this.x1 = x1; 508 this.y1 = y1; 509 this.ctrlx1 = ctrlx1; 510 this.ctrly1 = ctrly1; 511 this.ctrlx2 = ctrlx2; 512 this.ctrly2 = ctrly2; 513 this.x2 = x2; 514 this.y2 = y2; 515 } 516 517 522 public Rectangle2D getBounds2D() { 523 double left = Math.min(Math.min(x1, x2), 524 Math.min(ctrlx1, ctrlx2)); 525 double top = Math.min(Math.min(y1, y2), 526 Math.min(ctrly1, ctrly2)); 527 double right = Math.max(Math.max(x1, x2), 528 Math.max(ctrlx1, ctrlx2)); 529 double bottom = Math.max(Math.max(y1, y2), 530 Math.max(ctrly1, ctrly2)); 531 return new Rectangle2D.Double (left, top, 532 right - left, bottom - top); 533 } 534 } 535 536 546 protected CubicCurve2D() { 547 } 548 549 554 public abstract double getX1(); 555 556 561 public abstract double getY1(); 562 563 568 public abstract Point2D getP1(); 569 570 575 public abstract double getCtrlX1(); 576 577 582 public abstract double getCtrlY1(); 583 584 589 public abstract Point2D getCtrlP1(); 590 591 597 public abstract double getCtrlX2(); 598 599 605 public abstract double getCtrlY2(); 606 607 612 public abstract Point2D getCtrlP2(); 613 614 619 public abstract double getX2(); 620 621 626 public abstract double getY2(); 627 628 633 public abstract Point2D getP2(); 634 635 647 public abstract void setCurve(double x1, double y1, 648 double ctrlx1, double ctrly1, 649 double ctrlx2, double ctrly2, 650 double x2, double y2); 651 652 661 public void setCurve(double[] coords, int offset) { 662 setCurve(coords[offset + 0], coords[offset + 1], 663 coords[offset + 2], coords[offset + 3], 664 coords[offset + 4], coords[offset + 5], 665 coords[offset + 6], coords[offset + 7]); 666 } 667 668 680 public void setCurve(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2) { 681 setCurve(p1.getX(), p1.getY(), cp1.getX(), cp1.getY(), 682 cp2.getX(), cp2.getY(), p2.getX(), p2.getY()); 683 } 684 685 694 public void setCurve(Point2D [] pts, int offset) { 695 setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(), 696 pts[offset + 1].getX(), pts[offset + 1].getY(), 697 pts[offset + 2].getX(), pts[offset + 2].getY(), 698 pts[offset + 3].getX(), pts[offset + 3].getY()); 699 } 700 701 706 public void setCurve(CubicCurve2D c) { 707 setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(), 708 c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); 709 } 710 711 726 public static double getFlatnessSq(double x1, double y1, 727 double ctrlx1, double ctrly1, 728 double ctrlx2, double ctrly2, 729 double x2, double y2) { 730 return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx1, ctrly1), 731 Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx2, ctrly2)); 732 733 } 734 735 750 public static double getFlatness(double x1, double y1, 751 double ctrlx1, double ctrly1, 752 double ctrlx2, double ctrly2, 753 double x2, double y2) { 754 return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1, 755 ctrlx2, ctrly2, x2, y2)); 756 } 757 758 771 public static double getFlatnessSq(double coords[], int offset) { 772 return getFlatnessSq(coords[offset + 0], coords[offset + 1], 773 coords[offset + 2], coords[offset + 3], 774 coords[offset + 4], coords[offset + 5], 775 coords[offset + 6], coords[offset + 7]); 776 } 777 778 791 public static double getFlatness(double coords[], int offset) { 792 return getFlatness(coords[offset + 0], coords[offset + 1], 793 coords[offset + 2], coords[offset + 3], 794 coords[offset + 4], coords[offset + 5], 795 coords[offset + 6], coords[offset + 7]); 796 } 797 798 804 public double getFlatnessSq() { 805 return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), 806 getCtrlX2(), getCtrlY2(), getX2(), getY2()); 807 } 808 809 815 public double getFlatness() { 816 return getFlatness(getX1(), getY1(), getCtrlX1(), getCtrlY1(), 817 getCtrlX2(), getCtrlY2(), getX2(), getY2()); 818 } 819 820 830 public void subdivide(CubicCurve2D left, CubicCurve2D right) { 831 subdivide(this, left, right); 832 } 833 834 846 public static void subdivide(CubicCurve2D src, 847 CubicCurve2D left, 848 CubicCurve2D right) { 849 double x1 = src.getX1(); 850 double y1 = src.getY1(); 851 double ctrlx1 = src.getCtrlX1(); 852 double ctrly1 = src.getCtrlY1(); 853 double ctrlx2 = src.getCtrlX2(); 854 double ctrly2 = src.getCtrlY2(); 855 double x2 = src.getX2(); 856 double y2 = src.getY2(); 857 double centerx = (ctrlx1 + ctrlx2) / 2.0; 858 double centery = (ctrly1 + ctrly2) / 2.0; 859 ctrlx1 = (x1 + ctrlx1) / 2.0; 860 ctrly1 = (y1 + ctrly1) / 2.0; 861 ctrlx2 = (x2 + ctrlx2) / 2.0; 862 ctrly2 = (y2 + ctrly2) / 2.0; 863 double ctrlx12 = (ctrlx1 + centerx) / 2.0; 864 double ctrly12 = (ctrly1 + centery) / 2.0; 865 double ctrlx21 = (ctrlx2 + centerx) / 2.0; 866 double ctrly21 = (ctrly2 + centery) / 2.0; 867 centerx = (ctrlx12 + ctrlx21) / 2.0; 868 centery = (ctrly12 + ctrly21) / 2.0; 869 if (left != null) { 870 left.setCurve(x1, y1, ctrlx1, ctrly1, 871 ctrlx12, ctrly12, centerx, centery); 872 } 873 if (right != null) { 874 right.setCurve(centerx, centery, ctrlx21, ctrly21, 875 ctrlx2, ctrly2, x2, y2); 876 } 877 } 878 879 906 public static void subdivide(double src[], int srcoff, 907 double left[], int leftoff, 908 double right[], int rightoff) { 909 double x1 = src[srcoff + 0]; 910 double y1 = src[srcoff + 1]; 911 double ctrlx1 = src[srcoff + 2]; 912 double ctrly1 = src[srcoff + 3]; 913 double ctrlx2 = src[srcoff + 4]; 914 double ctrly2 = src[srcoff + 5]; 915 double x2 = src[srcoff + 6]; 916 double y2 = src[srcoff + 7]; 917 if (left != null) { 918 left[leftoff + 0] = x1; 919 left[leftoff + 1] = y1; 920 } 921 if (right != null) { 922 right[rightoff + 6] = x2; 923 right[rightoff + 7] = y2; 924 } 925 x1 = (x1 + ctrlx1) / 2.0; 926 y1 = (y1 + ctrly1) / 2.0; 927 x2 = (x2 + ctrlx2) / 2.0; 928 y2 = (y2 + ctrly2) / 2.0; 929 double centerx = (ctrlx1 + ctrlx2) / 2.0; 930 double centery = (ctrly1 + ctrly2) / 2.0; 931 ctrlx1 = (x1 + centerx) / 2.0; 932 ctrly1 = (y1 + centery) / 2.0; 933 ctrlx2 = (x2 + centerx) / 2.0; 934 ctrly2 = (y2 + centery) / 2.0; 935 centerx = (ctrlx1 + ctrlx2) / 2.0; 936 centery = (ctrly1 + ctrly2) / 2.0; 937 if (left != null) { 938 left[leftoff + 2] = x1; 939 left[leftoff + 3] = y1; 940 left[leftoff + 4] = ctrlx1; 941 left[leftoff + 5] = ctrly1; 942 left[leftoff + 6] = centerx; 943 left[leftoff + 7] = centery; 944 } 945 if (right != null) { 946 right[rightoff + 0] = centerx; 947 right[rightoff + 1] = centery; 948 right[rightoff + 2] = ctrlx2; 949 right[rightoff + 3] = ctrly2; 950 right[rightoff + 4] = x2; 951 right[rightoff + 5] = y2; 952 } 953 } 954 955 970 public static int solveCubic(double eqn[]) { 971 return solveCubic(eqn, eqn); 972 } 973 974 990 public static int solveCubic(double eqn[], double res[]) { 991 double d = eqn[3]; 993 if (d == 0.0) { 994 return QuadCurve2D.solveQuadratic(eqn, res); 996 } 997 double a = eqn[2] / d; 998 double b = eqn[1] / d; 999 double c = eqn[0] / d; 1000 int roots = 0; 1001 double Q = (a * a - 3.0 * b) / 9.0; 1002 double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0; 1003 double R2 = R * R; 1004 double Q3 = Q * Q * Q; 1005 a = a / 3.0; 1006 if (R2 < Q3) { 1007 double theta = Math.acos(R / Math.sqrt(Q3)); 1008 Q = -2.0 * Math.sqrt(Q); 1009 if (res == eqn) { 1010 eqn = new double[4]; 1014 System.arraycopy(res, 0, eqn, 0, 4); 1015 } 1016 res[roots++] = Q * Math.cos(theta / 3.0) - a; 1017 res[roots++] = Q * Math.cos((theta + Math.PI * 2.0)/ 3.0) - a; 1018 res[roots++] = Q * Math.cos((theta - Math.PI * 2.0)/ 3.0) - a; 1019 fixRoots(res, eqn); 1020 } else { 1021 boolean neg = (R < 0.0); 1022 double S = Math.sqrt(R2 - Q3); 1023 if (neg) { 1024 R = -R; 1025 } 1026 double A = Math.pow(R + S, 1.0 / 3.0); 1027 if (!neg) { 1028 A = -A; 1029 } 1030 double B = (A == 0.0) ? 0.0 : (Q / A); 1031 res[roots++] = (A + B) - a; 1032 } 1033 return roots; 1034 } 1035 1036 1070 private static void fixRoots(double res[], double eqn[]) { 1071 final double EPSILON = 1E-5; 1072 for (int i = 0; i < 3; i++) { 1073 double t = res[i]; 1074 if (Math.abs(t) < EPSILON) { 1075 res[i] = findZero(t, 0, eqn); 1076 } else if (Math.abs(t - 1) < EPSILON) { 1077 res[i] = findZero(t, 1, eqn); 1078 } 1079 } 1080 } 1081 1082 private static double solveEqn(double eqn[], int order, double t) { 1083 double v = eqn[order]; 1084 while (--order >= 0) { 1085 v = v * t + eqn[order]; 1086 } 1087 return v; 1088 } 1089 1090 private static double findZero(double t, double target, double eqn[]) { 1091 double slopeqn[] = {eqn[1], 2*eqn[2], 3*eqn[3]}; 1092 double slope; 1093 double origdelta = 0; 1094 double origt = t; 1095 while (true) { 1096 slope = solveEqn(slopeqn, 2, t); 1097 if (slope == 0) { 1098 return t; 1100 } 1101 double y = solveEqn(eqn, 3, t); 1102 if (y == 0) { 1103 return t; 1105 } 1106 double delta = - (y / slope); 1108 if (origdelta == 0) { 1110 origdelta = delta; 1111 } 1112 if (t < target) { 1113 if (delta < 0) return t; 1114 } else if (t > target) { 1115 if (delta > 0) return t; 1116 } else { 1117 return (delta > 0 1118 ? (target + java.lang.Double.MIN_VALUE) 1119 : (target - java.lang.Double.MIN_VALUE)); 1120 } 1121 double newt = t + delta; 1122 if (t == newt) { 1123 return t; 1125 } 1126 if (delta * origdelta < 0) { 1127 int tag = (origt < t 1129 ? getTag(target, origt, t) 1130 : getTag(target, t, origt)); 1131 if (tag != INSIDE) { 1132 return (origt + t) / 2; 1134 } 1135 t = target; 1138 } else { 1139 t = newt; 1140 } 1141 } 1142 } 1143 1144 1150 public boolean contains(double x, double y) { 1151 int crossings = 0; 1154 double x1 = getX1(); 1155 double y1 = getY1(); 1156 double x2 = getX2(); 1157 double y2 = getY2(); 1158 double dy = y2 - y1; 1160 if ((dy > 0.0 && y >= y1 && y <= y2) || 1161 (dy < 0.0 && y <= y1 && y >= y2)) 1162 { 1163 if (x < x1 + (y - y1) * (x2 - x1) / dy) { 1164 crossings++; 1165 } 1166 } 1167 double ctrlx1 = getCtrlX1(); 1169 double ctrly1 = getCtrlY1(); 1170 double ctrlx2 = getCtrlX2(); 1171 double ctrly2 = getCtrlY2(); 1172 boolean include0 = ((y2 - y1) * (ctrly1 - y1) >= 0); 1173 boolean include1 = ((y1 - y2) * (ctrly2 - y2) >= 0); 1174 double eqn[] = new double[4]; 1175 double res[] = new double[4]; 1176 fillEqn(eqn, y, y1, ctrly1, ctrly2, y2); 1177 int roots = solveCubic(eqn, res); 1178 roots = evalCubic(res, roots, 1179 include0, include1, eqn, 1180 x1, ctrlx1, ctrlx2, x2); 1181 while (--roots >= 0) { 1182 if (x < res[roots]) { 1183 crossings++; 1184 } 1185 } 1186 return ((crossings & 1) == 1); 1187 } 1188 1189 1196 public boolean contains(Point2D p) { 1197 return contains(p.getX(), p.getY()); 1198 } 1199 1200 1226 private static void fillEqn(double eqn[], double val, 1227 double c1, double cp1, double cp2, double c2) { 1228 eqn[0] = c1 - val; 1229 eqn[1] = (cp1 - c1) * 3.0; 1230 eqn[2] = (cp2 - cp1 - cp1 + c1) * 3.0; 1231 eqn[3] = c2 + (cp1 - cp2) * 3.0 - c1; 1232 return; 1233 } 1234 1235 1244 private static int evalCubic(double vals[], int num, 1245 boolean include0, 1246 boolean include1, 1247 double inflect[], 1248 double c1, double cp1, 1249 double cp2, double c2) { 1250 int j = 0; 1251 for (int i = 0; i < num; i++) { 1252 double t = vals[i]; 1253 if ((include0 ? t >= 0 : t > 0) && 1254 (include1 ? t <= 1 : t < 1) && 1255 (inflect == null || 1256 inflect[1] + (2*inflect[2] + 3*inflect[3]*t)*t != 0)) 1257 { 1258 double u = 1 - t; 1259 vals[j++] = c1*u*u*u + 3*cp1*t*u*u + 3*cp2*t*t*u + c2*t*t*t; 1260 } 1261 } 1262 return j; 1263 } 1264 1265 private static final int BELOW = -2; 1266 private static final int LOWEDGE = -1; 1267 private static final int INSIDE = 0; 1268 private static final int HIGHEDGE = 1; 1269 private static final int ABOVE = 2; 1270 1271 1277 private static int getTag(double coord, double low, double high) { 1278 if (coord <= low) { 1279 return (coord < low ? BELOW : LOWEDGE); 1280 } 1281 if (coord >= high) { 1282 return (coord > high ? ABOVE : HIGHEDGE); 1283 } 1284 return INSIDE; 1285 } 1286 1287 1294 private static boolean inwards(int pttag, int opt1tag, int opt2tag) { 1295 switch (pttag) { 1296 case BELOW: 1297 case ABOVE: 1298 default: 1299 return false; 1300 case LOWEDGE: 1301 return (opt1tag >= INSIDE || opt2tag >= INSIDE); 1302 case INSIDE: 1303 return true; 1304 case HIGHEDGE: 1305 return (opt1tag <= INSIDE || opt2tag <= INSIDE); 1306 } 1307 } 1308 1309 1320 public boolean intersects(double x, double y, double w, double h) { 1321 if (w < 0 || h < 0) { 1323 return false; 1324 } 1325 1326 double x1 = getX1(); 1331 double y1 = getY1(); 1332 int x1tag = getTag(x1, x, x+w); 1333 int y1tag = getTag(y1, y, y+h); 1334 if (x1tag == INSIDE && y1tag == INSIDE) { 1335 return true; 1336 } 1337 double x2 = getX2(); 1338 double y2 = getY2(); 1339 int x2tag = getTag(x2, x, x+w); 1340 int y2tag = getTag(y2, y, y+h); 1341 if (x2tag == INSIDE && y2tag == INSIDE) { 1342 return true; 1343 } 1344 1345 double ctrlx1 = getCtrlX1(); 1346 double ctrly1 = getCtrlY1(); 1347 double ctrlx2 = getCtrlX2(); 1348 double ctrly2 = getCtrlY2(); 1349 int ctrlx1tag = getTag(ctrlx1, x, x+w); 1350 int ctrly1tag = getTag(ctrly1, y, y+h); 1351 int ctrlx2tag = getTag(ctrlx2, x, x+w); 1352 int ctrly2tag = getTag(ctrly2, y, y+h); 1353 1354 if (x1tag < INSIDE && x2tag < INSIDE && 1357 ctrlx1tag < INSIDE && ctrlx2tag < INSIDE) 1358 { 1359 return false; } 1361 if (y1tag < INSIDE && y2tag < INSIDE && 1362 ctrly1tag < INSIDE && ctrly2tag < INSIDE) 1363 { 1364 return false; } 1366 if (x1tag > INSIDE && x2tag > INSIDE && 1367 ctrlx1tag > INSIDE && ctrlx2tag > INSIDE) 1368 { 1369 return false; } 1371 if (y1tag > INSIDE && y2tag > INSIDE && 1372 ctrly1tag > INSIDE && ctrly2tag > INSIDE) 1373 { 1374 return false; } 1376 1377 if (inwards(x1tag, x2tag, ctrlx1tag) && 1383 inwards(y1tag, y2tag, ctrly1tag)) 1384 { 1385 return true; 1387 } 1388 if (inwards(x2tag, x1tag, ctrlx2tag) && 1389 inwards(y2tag, y1tag, ctrly2tag)) 1390 { 1391 return true; 1393 } 1394 1395 boolean xoverlap = (x1tag * x2tag <= 0); 1397 boolean yoverlap = (y1tag * y2tag <= 0); 1398 if (x1tag == INSIDE && x2tag == INSIDE && yoverlap) { 1399 return true; 1400 } 1401 if (y1tag == INSIDE && y2tag == INSIDE && xoverlap) { 1402 return true; 1403 } 1404 1405 1411 double[] eqn = new double[4]; 1412 double[] res = new double[4]; 1413 if (!yoverlap) { 1414 fillEqn(eqn, (y1tag < INSIDE ? y : y+h), y1, ctrly1, ctrly2, y2); 1420 int num = solveCubic(eqn, res); 1421 num = evalCubic(res, num, true, true, null, 1422 x1, ctrlx1, ctrlx2, x2); 1423 return (num == 2 && 1427 getTag(res[0], x, x+w) * getTag(res[1], x, x+w) <= 0); 1428 } 1429 1430 if (!xoverlap) { 1432 fillEqn(eqn, (x1tag < INSIDE ? x : x+w), x1, ctrlx1, ctrlx2, x2); 1438 int num = solveCubic(eqn, res); 1439 num = evalCubic(res, num, true, true, null, 1440 y1, ctrly1, ctrly2, y2); 1441 return (num == 2 && 1445 getTag(res[0], y, y+h) * getTag(res[1], y, y+h) <= 0); 1446 } 1447 1448 double dx = x2 - x1; 1452 double dy = y2 - y1; 1453 double k = y2 * x1 - x2 * y1; 1454 int c1tag, c2tag; 1455 if (y1tag == INSIDE) { 1456 c1tag = x1tag; 1457 } else { 1458 c1tag = getTag((k + dx * (y1tag < INSIDE ? y : y+h)) / dy, x, x+w); 1459 } 1460 if (y2tag == INSIDE) { 1461 c2tag = x2tag; 1462 } else { 1463 c2tag = getTag((k + dx * (y2tag < INSIDE ? y : y+h)) / dy, x, x+w); 1464 } 1465 if (c1tag * c2tag <= 0) { 1468 return true; 1469 } 1470 1471 1492 c1tag = ((c1tag * x1tag <= 0) ? y1tag : y2tag); 1499 1500 fillEqn(eqn, (c2tag < INSIDE ? x : x+w), x1, ctrlx1, ctrlx2, x2); 1509 int num = solveCubic(eqn, res); 1510 num = evalCubic(res, num, true, true, null, y1, ctrly1, ctrly2, y2); 1511 1512 int tags[] = new int[num+1]; 1516 for (int i = 0; i < num; i++) { 1517 tags[i] = getTag(res[i], y, y+h); 1518 } 1519 tags[num] = c1tag; 1520 Arrays.sort(tags); 1521 return ((num >= 1 && tags[0] * tags[1] <= 0) || 1522 (num >= 3 && tags[2] * tags[3] <= 0)); 1523 } 1524 1525 1533 public boolean intersects(Rectangle2D r) { 1534 return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 1535 } 1536 1537 1548 public boolean contains(double x, double y, double w, double h) { 1549 if (!(contains(x, y) && 1553 contains(x + w, y) && 1554 contains(x + w, y + h) && 1555 contains(x, y + h))) { 1556 return false; 1557 } 1558 Rectangle2D rect = new Rectangle2D.Double (x, y, w, h); 1562 return !rect.intersectsLine(getX1(), getY1(), getX2(), getY2()); 1563 } 1564 1565 1573 public boolean contains(Rectangle2D r) { 1574 return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); 1575 } 1576 1577 1581 public Rectangle getBounds() { 1582 return getBounds2D().getBounds(); 1583 } 1584 1585 1600 public PathIterator getPathIterator(AffineTransform at) { 1601 return new CubicIterator (this, at); 1602 } 1603 1604 1621 public PathIterator getPathIterator(AffineTransform at, double flatness) { 1622 return new FlatteningPathIterator (getPathIterator(at), flatness); 1623 } 1624 1625 1633 public Object clone() { 1634 try { 1635 return super.clone(); 1636 } catch (CloneNotSupportedException e) { 1637 throw new InternalError (); 1639 } 1640 } 1641} 1642 | Popular Tags |