1 7 8 package java.awt.geom; 9 10 import java.awt.Shape ; 11 import java.awt.Rectangle ; 12 import java.util.Vector ; 13 import java.util.Enumeration ; 14 import java.util.NoSuchElementException ; 15 import sun.awt.geom.Curve; 16 import sun.awt.geom.Crossings; 17 import sun.awt.geom.AreaOp; 18 19 28 public class Area implements Shape , Cloneable { 29 private static Vector EmptyCurves = new Vector (); 30 31 private Vector curves; 32 33 36 public Area() { 37 curves = EmptyCurves; 38 } 39 40 48 public Area(Shape s) { 49 if (s instanceof Area ) { 50 curves = ((Area ) s).curves; 51 return; 52 } 53 curves = new Vector (); 54 PathIterator pi = s.getPathIterator(null); 55 int windingRule = pi.getWindingRule(); 56 double coords[] = new double[23]; 71 double movx = 0, movy = 0; 72 double curx = 0, cury = 0; 73 double newx, newy; 74 while (!pi.isDone()) { 75 switch (pi.currentSegment(coords)) { 76 case PathIterator.SEG_MOVETO: 77 Curve.insertLine(curves, curx, cury, movx, movy); 78 curx = movx = coords[0]; 79 cury = movy = coords[1]; 80 Curve.insertMove(curves, movx, movy); 81 break; 82 case PathIterator.SEG_LINETO: 83 newx = coords[0]; 84 newy = coords[1]; 85 Curve.insertLine(curves, curx, cury, newx, newy); 86 curx = newx; 87 cury = newy; 88 break; 89 case PathIterator.SEG_QUADTO: 90 newx = coords[2]; 91 newy = coords[3]; 92 Curve.insertQuad(curves, curx, cury, coords); 93 curx = newx; 94 cury = newy; 95 break; 96 case PathIterator.SEG_CUBICTO: 97 newx = coords[4]; 98 newy = coords[5]; 99 Curve.insertCubic(curves, curx, cury, coords); 100 curx = newx; 101 cury = newy; 102 break; 103 case PathIterator.SEG_CLOSE: 104 Curve.insertLine(curves, curx, cury, movx, movy); 105 curx = movx; 106 cury = movy; 107 break; 108 } 109 pi.next(); 110 } 111 Curve.insertLine(curves, curx, cury, movx, movy); 112 AreaOp operator; 113 if (windingRule == PathIterator.WIND_EVEN_ODD) { 114 operator = new AreaOp.EOWindOp(); 115 } else { 116 operator = new AreaOp.NZWindOp(); 117 } 118 curves = operator.calculate(this.curves, EmptyCurves); 119 } 120 121 128 public void add(Area rhs) { 129 curves = new AreaOp.AddOp().calculate(this.curves, rhs.curves); 130 invalidateBounds(); 131 } 132 133 139 public void subtract(Area rhs) { 140 curves = new AreaOp.SubOp().calculate(this.curves, rhs.curves); 141 invalidateBounds(); 142 } 143 144 150 public void intersect(Area rhs) { 151 curves = new AreaOp.IntOp().calculate(this.curves, rhs.curves); 152 invalidateBounds(); 153 } 154 155 162 public void exclusiveOr(Area rhs) { 163 curves = new AreaOp.XorOp().calculate(this.curves, rhs.curves); 164 invalidateBounds(); 165 } 166 167 171 public void reset() { 172 curves = new Vector (); 173 invalidateBounds(); 174 } 175 176 181 public boolean isEmpty() { 182 return (curves.size() == 0); 183 } 184 185 192 public boolean isPolygonal() { 193 Enumeration enum_ = curves.elements(); 194 while (enum_.hasMoreElements()) { 195 if (((Curve) enum_.nextElement()).getOrder() > 1) { 196 return false; 197 } 198 } 199 return true; 200 } 201 202 208 public boolean isRectangular() { 209 int size = curves.size(); 210 if (size == 0) { 211 return true; 212 } 213 if (size > 3) { 214 return false; 215 } 216 Curve c1 = (Curve) curves.get(1); 217 Curve c2 = (Curve) curves.get(2); 218 if (c1.getOrder() != 1 || c2.getOrder() != 1) { 219 return false; 220 } 221 if (c1.getXTop() != c1.getXBot() || c2.getXTop() != c2.getXBot()) { 222 return false; 223 } 224 if (c1.getYTop() != c2.getYTop() || c1.getYBot() != c2.getYBot()) { 225 return false; 227 } 228 return true; 229 } 230 231 241 public boolean isSingular() { 242 if (curves.size() < 3) { 243 return true; 244 } 245 Enumeration enum_ = curves.elements(); 246 enum_.nextElement(); while (enum_.hasMoreElements()) { 248 if (((Curve) enum_.nextElement()).getOrder() == 0) { 249 return false; 250 } 251 } 252 return true; 253 } 254 255 private Rectangle2D cachedBounds; 256 private void invalidateBounds() { 257 cachedBounds = null; 258 } 259 private Rectangle2D getCachedBounds() { 260 if (cachedBounds != null) { 261 return cachedBounds; 262 } 263 Rectangle2D r = new Rectangle2D.Double (); 264 if (curves.size() > 0) { 265 Curve c = (Curve) curves.get(0); 266 r.setRect(c.getX0(), c.getY0(), 0, 0); 268 for (int i = 1; i < curves.size(); i++) { 269 ((Curve) curves.get(i)).enlarge(r); 270 } 271 } 272 return (cachedBounds = r); 273 } 274 275 287 public Rectangle2D getBounds2D() { 288 return getCachedBounds().getBounds2D(); 289 } 290 291 306 public Rectangle getBounds() { 307 return getCachedBounds().getBounds(); 308 } 309 310 314 public Object clone() { 315 return new Area (this); 316 } 317 318 326 public boolean equals(Area other) { 327 if (other == this) { 331 return true; 332 } 333 if (other == null) { 334 return false; 335 } 336 Vector c = new AreaOp.XorOp().calculate(this.curves, other.curves); 337 return c.isEmpty(); 338 } 339 340 346 public void transform(AffineTransform t) { 347 curves = new Area (t.createTransformedShape(this)).curves; 352 invalidateBounds(); 353 } 354 355 365 public Area createTransformedArea(AffineTransform t) { 366 return new Area (t.createTransformedShape(this)); 371 } 372 373 381 public boolean contains(double x, double y) { 382 if (!getCachedBounds().contains(x, y)) { 383 return false; 384 } 385 Enumeration enum_ = curves.elements(); 386 int crossings = 0; 387 while (enum_.hasMoreElements()) { 388 Curve c = (Curve) enum_.nextElement(); 389 crossings += c.crossingsFor(x, y); 390 } 391 return ((crossings & 1) == 1); 392 } 393 394 402 public boolean contains(Point2D p) { 403 return contains(p.getX(), p.getY()); 404 } 405 406 417 public boolean contains(double x, double y, double w, double h) { 418 if (w < 0 || h < 0) { 419 return false; 420 } 421 if (!getCachedBounds().contains(x, y, w, h)) { 422 return false; 423 } 424 Crossings c = Crossings.findCrossings(curves, x, y, x+w, y+h); 425 return (c != null && c.covers(y, y+h)); 426 } 427 428 436 public boolean contains(Rectangle2D p) { 437 return contains(p.getX(), p.getY(), p.getWidth(), p.getHeight()); 438 } 439 440 450 public boolean intersects(double x, double y, double w, double h) { 451 if (w < 0 || h < 0) { 452 return false; 453 } 454 if (!getCachedBounds().intersects(x, y, w, h)) { 455 return false; 456 } 457 Crossings c = Crossings.findCrossings(curves, x, y, x+w, y+h); 458 return (c == null || !c.isEmpty()); 459 } 460 461 469 public boolean intersects(Rectangle2D p) { 470 return intersects(p.getX(), p.getY(), p.getWidth(), p.getHeight()); 471 } 472 473 483 public PathIterator getPathIterator(AffineTransform at) { 484 return new AreaIterator(curves, at); 485 } 486 487 504 public PathIterator getPathIterator(AffineTransform at, double flatness) { 505 return new FlatteningPathIterator (getPathIterator(at), flatness); 506 } 507 } 508 509 class AreaIterator implements PathIterator { 510 private AffineTransform transform; 511 private Vector curves; 512 private int index; 513 private Curve prevcurve; 514 private Curve thiscurve; 515 516 public AreaIterator(Vector curves, AffineTransform at) { 517 this.curves = curves; 518 this.transform = at; 519 if (curves.size() >= 1) { 520 thiscurve = (Curve) curves.get(0); 521 } 522 } 523 524 public int getWindingRule() { 525 return WIND_NON_ZERO; 529 } 530 531 public boolean isDone() { 532 return (prevcurve == null && thiscurve == null); 533 } 534 535 public void next() { 536 if (prevcurve != null) { 537 prevcurve = null; 538 } else { 539 prevcurve = thiscurve; 540 index++; 541 if (index < curves.size()) { 542 thiscurve = (Curve) curves.get(index); 543 if (thiscurve.getOrder() != 0 && 544 prevcurve.getX1() == thiscurve.getX0() && 545 prevcurve.getY1() == thiscurve.getY0()) 546 { 547 prevcurve = null; 548 } 549 } else { 550 thiscurve = null; 551 } 552 } 553 } 554 555 public int currentSegment(float coords[]) { 556 double dcoords[] = new double[6]; 557 int segtype = currentSegment(dcoords); 558 int numpoints = (segtype == SEG_CLOSE ? 0 559 : (segtype == SEG_QUADTO ? 2 560 : (segtype == SEG_CUBICTO ? 3 561 : 1))); 562 for (int i = 0; i < numpoints * 2; i++) { 563 coords[i] = (float) dcoords[i]; 564 } 565 return segtype; 566 } 567 568 public int currentSegment(double coords[]) { 569 int segtype; 570 int numpoints; 571 if (prevcurve != null) { 572 if (thiscurve == null || thiscurve.getOrder() == 0) { 574 return SEG_CLOSE; 575 } 576 coords[0] = thiscurve.getX0(); 577 coords[1] = thiscurve.getY0(); 578 segtype = SEG_LINETO; 579 numpoints = 1; 580 } else if (thiscurve == null) { 581 throw new NoSuchElementException ("area iterator out of bounds"); 582 } else { 583 segtype = thiscurve.getSegment(coords); 584 numpoints = thiscurve.getOrder(); 585 if (numpoints == 0) { 586 numpoints = 1; 587 } 588 } 589 if (transform != null) { 590 transform.transform(coords, 0, coords, 0, numpoints); 591 } 592 return segtype; 593 } 594 } 595 | Popular Tags |