Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for java.awt.geom.Line2D

 1:  /* Line2D.java -- represents a line in 2-D space, plus operations on a line
 2:  Copyright (C) 2000, 2001, 2002 Free Software Foundation
 3: 
 4: This file is part of GNU Classpath.
 5: 
 6: GNU Classpath is free software; you can redistribute it and/or modify
 7: it under the terms of the GNU General Public License as published by
 8: the Free Software Foundation; either version 2, or (at your option)
 9: any later version.
 10: 
 11: GNU Classpath is distributed in the hope that it will be useful, but
 12: WITHOUT ANY WARRANTY; without even the implied warranty of
 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14: General Public License for more details.
 15: 
 16: You should have received a copy of the GNU General Public License
 17: along with GNU Classpath; see the file COPYING. If not, write to the
 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19: 02110-1301 USA.
 20: 
 21: Linking this library statically or dynamically with other modules is
 22: making a combined work based on this library. Thus, the terms and
 23: conditions of the GNU General Public License cover the whole
 24: combination.
 25: 
 26: As a special exception, the copyright holders of this library give you
 27: permission to link this library with independent modules to produce an
 28: executable, regardless of the license terms of these independent
 29: modules, and to copy and distribute the resulting executable under
 30: terms of your choice, provided that you also meet, for each linked
 31: independent module, the terms and conditions of the license of that
 32: module. An independent module is a module which is not derived from
 33: or based on this library. If you modify this library, you may extend
 34: this exception to your version of the library, but you are not
 35: obligated to do so. If you do not wish to do so, delete this
 36: exception statement from your version. */
 37: 
 38:  package java.awt.geom;
 39: 
 40:  import java.awt.Rectangle;
 41:  import java.awt.Shape;
 42:  import java.util.NoSuchElementException;
 43: 
 44:  /**
 45:  * Represents a directed line bewteen two points in (x,y) Cartesian space.
 46:  * Remember, on-screen graphics have increasing x from left-to-right, and
 47:  * increasing y from top-to-bottom. The storage is left to subclasses.
 48:  *
 49:  * @author Tom Tromey (tromey@cygnus.com)
 50:  * @author Eric Blake (ebb9@email.byu.edu)
 51:  * @author David Gilbert
 52:  * @since 1.2
 53:  * @status updated to 1.4
 54:  */
 55:  public abstract class Line2D implements Shape, Cloneable
 56: {
 57:  /**
 58:  * The default constructor.
 59:  */
 60:  protected Line2D()
 61:  {
 62:  }
 63: 
 64:  /**
 65:  * Return the x coordinate of the first point.
 66:  *
 67:  * @return the starting x coordinate
 68:  */
 69:  public abstract double getX1();
 70: 
 71:  /**
 72:  * Return the y coordinate of the first point.
 73:  *
 74:  * @return the starting y coordinate
 75:  */
 76:  public abstract double getY1();
 77: 
 78:  /**
 79:  * Return the first point.
 80:  *
 81:  * @return the starting point
 82:  */
 83:  public abstract Point2D getP1();
 84: 
 85:  /**
 86:  * Return the x coordinate of the second point.
 87:  *
 88:  * @return the ending x coordinate
 89:  */
 90:  public abstract double getX2();
 91: 
 92:  /**
 93:  * Return the y coordinate of the second point.
 94:  *
 95:  * @return the ending y coordinate
 96:  */
 97:  public abstract double getY2();
 98: 
 99:  /**
 100:  * Return the second point.
 101:  *
 102:  * @return the ending point
 103:  */
 104:  public abstract Point2D getP2();
 105: 
 106:  /**
 107:  * Set the coordinates of the line to the given coordinates. Loss of
 108:  * precision may occur due to rounding issues.
 109:  *
 110:  * @param x1 the first x coordinate
 111:  * @param y1 the first y coordinate
 112:  * @param x2 the second x coordinate
 113:  * @param y2 the second y coordinate
 114:  */
 115:  public abstract void setLine(double x1, double y1, double x2, double y2);
 116: 
 117:  /**
 118:  * Set the coordinates to the given points.
 119:  *
 120:  * @param p1 the first point
 121:  * @param p2 the second point
 122:  * @throws NullPointerException if either point is null
 123:  */
 124:  public void setLine(Point2D p1, Point2D p2)
 125:  {
 126:  setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
 127:  }
 128: 
 129:  /**
 130:  * Set the coordinates to those of the given line.
 131:  *
 132:  * @param l the line to copy
 133:  * @throws NullPointerException if l is null
 134:  */
 135:  public void setLine(Line2D l)
 136:  {
 137:  setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
 138:  }
 139: 
 140:  /**
 141:  * Computes the relative rotation direction needed to pivot the line about
 142:  * the first point in order to have the second point colinear with point p.
 143:  * Because of floating point rounding, don't expect this to be a perfect
 144:  * measure of colinearity. The answer is 1 if the line has a shorter rotation
 145:  * in the direction of the positive X axis to the negative Y axis
 146:  * (counter-clockwise in the default Java coordinate system), or -1 if the
 147:  * shortest rotation is in the opposite direction (clockwise). If p
 148:  * is already colinear, the return value is -1 if it lies beyond the first
 149:  * point, 0 if it lies in the segment, or 1 if it lies beyond the second
 150:  * point. If the first and second point are coincident, this returns 0.
 151:  *
 152:  * @param x1 the first x coordinate
 153:  * @param y1 the first y coordinate
 154:  * @param x2 the second x coordinate
 155:  * @param y2 the second y coordinate
 156:  * @param px the reference x coordinate
 157:  * @param py the reference y coordinate
 158:  * @return the relative rotation direction
 159:  */
 160:  public static int relativeCCW(double x1, double y1, double x2, double y2,
 161:  double px, double py)
 162:  {
 163:  if ((x1 == x2 && y1 == y2)
 164:  || (x1 == px && y1 == py))
 165:  return 0; // Coincident points.
 166:  // Translate to the origin.
 167:  x2 -= x1;
 168:  y2 -= y1;
 169:  px -= x1;
 170:  py -= y1;
 171:  double slope2 = y2 / x2;
 172:  double slopep = py / px;
 173:  if (slope2 == slopep || (x2 == 0 && px == 0))
 174:  return y2 > 0 // Colinear.
 175:  ? (py < 0 ? -1 : py > y2 ? 1 : 0)
 176:  : (py > 0 ? -1 : py < y2 ? 1 : 0);
 177:  if (x2 >= 0 && slope2 >= 0)
 178:  return px >= 0 // Quadrant 1.
 179:  ? (slope2 > slopep ? 1 : -1)
 180:  : (slope2 < slopep ? 1 : -1);
 181:  if (y2 > 0)
 182:  return px < 0 // Quadrant 2.
 183:  ? (slope2 > slopep ? 1 : -1)
 184:  : (slope2 < slopep ? 1 : -1);
 185:  if (slope2 >= 0.0)
 186:  return px >= 0 // Quadrant 3.
 187:  ? (slope2 < slopep ? 1 : -1)
 188:  : (slope2 > slopep ? 1 : -1);
 189:  return px < 0 // Quadrant 4.
 190:  ? (slope2 < slopep ? 1 : -1)
 191:  : (slope2 > slopep ? 1 : -1);
 192:  }
 193: 
 194:  /**
 195:  * Computes the relative rotation direction needed to pivot this line about
 196:  * the first point in order to have the second point colinear with point p.
 197:  * Because of floating point rounding, don't expect this to be a perfect
 198:  * measure of colinearity. The answer is 1 if the line has a shorter rotation
 199:  * in the direction of the positive X axis to the negative Y axis
 200:  * (counter-clockwise in the default Java coordinate system), or -1 if the
 201:  * shortest rotation is in the opposite direction (clockwise). If p
 202:  * is already colinear, the return value is -1 if it lies beyond the first
 203:  * point, 0 if it lies in the segment, or 1 if it lies beyond the second
 204:  * point. If the first and second point are coincident, this returns 0.
 205:  *
 206:  * @param px the reference x coordinate
 207:  * @param py the reference y coordinate
 208:  * @return the relative rotation direction
 209:  * @see #relativeCCW(double, double, double, double, double, double)
 210:  */
 211:  public int relativeCCW(double px, double py)
 212:  {
 213:  return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
 214:  }
 215: 
 216:  /**
 217:  * Computes the relative rotation direction needed to pivot this line about
 218:  * the first point in order to have the second point colinear with point p.
 219:  * Because of floating point rounding, don't expect this to be a perfect
 220:  * measure of colinearity. The answer is 1 if the line has a shorter rotation
 221:  * in the direction of the positive X axis to the negative Y axis
 222:  * (counter-clockwise in the default Java coordinate system), or -1 if the
 223:  * shortest rotation is in the opposite direction (clockwise). If p
 224:  * is already colinear, the return value is -1 if it lies beyond the first
 225:  * point, 0 if it lies in the segment, or 1 if it lies beyond the second
 226:  * point. If the first and second point are coincident, this returns 0.
 227:  *
 228:  * @param p the reference point
 229:  * @return the relative rotation direction
 230:  * @throws NullPointerException if p is null
 231:  * @see #relativeCCW(double, double, double, double, double, double)
 232:  */
 233:  public int relativeCCW(Point2D p)
 234:  {
 235:  return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
 236:  }
 237: 
 238:  /**
 239:  * Computes twice the (signed) area of the triangle defined by the three
 240:  * points. This method is used for intersection testing.
 241:  * 
 242:  * @param x1 the x-coordinate of the first point.
 243:  * @param y1 the y-coordinate of the first point.
 244:  * @param x2 the x-coordinate of the second point.
 245:  * @param y2 the y-coordinate of the second point.
 246:  * @param x3 the x-coordinate of the third point.
 247:  * @param y3 the y-coordinate of the third point.
 248:  * 
 249:  * @return Twice the area.
 250:  */
 251:  private static double area2(double x1, double y1,
 252:  double x2, double y2,
 253:  double x3, double y3) 
 254:  {
 255:  return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); 
 256:  }
 257: 
 258:  /**
 259:  * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2),
 260:  * and false otherwise, This test assumes that the three points are 
 261:  * collinear, and is used for intersection testing.
 262:  * 
 263:  * @param x1 the x-coordinate of the first point.
 264:  * @param y1 the y-coordinate of the first point.
 265:  * @param x2 the x-coordinate of the second point.
 266:  * @param y2 the y-coordinate of the second point.
 267:  * @param x3 the x-coordinate of the third point.
 268:  * @param y3 the y-coordinate of the third point.
 269:  * 
 270:  * @return A boolean.
 271:  */
 272:  private static boolean between(double x1, double y1, 
 273:  double x2, double y2, 
 274:  double x3, double y3) 
 275:  {
 276:  if (x1 != x2) {
 277:  return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2); 
 278:  }
 279:  else {
 280:  return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2); 
 281:  }
 282:  }
 283: 
 284:  /**
 285:  * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment 
 286:  * (x3,y3)-&gt;(x4,y4).
 287:  *
 288:  * @param x1 the first x coordinate of the first segment
 289:  * @param y1 the first y coordinate of the first segment 
 290:  * @param x2 the second x coordinate of the first segment
 291:  * @param y2 the second y coordinate of the first segment
 292:  * @param x3 the first x coordinate of the second segment
 293:  * @param y3 the first y coordinate of the second segment
 294:  * @param x4 the second x coordinate of the second segment
 295:  * @param y4 the second y coordinate of the second segment
 296:  * @return true if the segments intersect
 297:  */
 298:  public static boolean linesIntersect(double x1, double y1,
 299:  double x2, double y2,
 300:  double x3, double y3,
 301:  double x4, double y4)
 302:  {
 303:  double a1, a2, a3, a4;
 304:  
 305:  // deal with special cases
 306:  if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0) 
 307:  {
 308:  // check if p3 is between p1 and p2 OR
 309:  // p4 is collinear also AND either between p1 and p2 OR at opposite ends
 310:  if (between(x1, y1, x2, y2, x3, y3)) 
 311:  {
 312:  return true;
 313:  }
 314:  else 
 315:  {
 316:  if (area2(x1, y1, x2, y2, x4, y4) == 0.0) 
 317:  {
 318:  return between(x3, y3, x4, y4, x1, y1) 
 319:  || between (x3, y3, x4, y4, x2, y2);
 320:  }
 321:  else {
 322:  return false;
 323:  }
 324:  }
 325:  }
 326:  else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0) 
 327:  {
 328:  // check if p4 is between p1 and p2 (we already know p3 is not
 329:  // collinear)
 330:  return between(x1, y1, x2, y2, x4, y4);
 331:  }
 332:  
 333:  if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) {
 334:  // check if p1 is between p3 and p4 OR
 335:  // p2 is collinear also AND either between p1 and p2 OR at opposite ends
 336:  if (between(x3, y3, x4, y4, x1, y1)) {
 337:  return true;
 338:  }
 339:  else {
 340:  if (area2(x3, y3, x4, y4, x2, y2) == 0.0) {
 341:  return between(x1, y1, x2, y2, x3, y3) 
 342:  || between (x1, y1, x2, y2, x4, y4);
 343:  }
 344:  else {
 345:  return false;
 346:  }
 347:  }
 348:  }
 349:  else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) {
 350:  // check if p2 is between p3 and p4 (we already know p1 is not
 351:  // collinear)
 352:  return between(x3, y3, x4, y4, x2, y2);
 353:  }
 354:  else { // test for regular intersection
 355:  return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0));
 356:  } 
 357:  }
 358: 
 359:  /**
 360:  * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
 361:  *
 362:  * @param x1 the first x coordinate of the other segment
 363:  * @param y1 the first y coordinate of the other segment
 364:  * @param x2 the second x coordinate of the other segment
 365:  * @param y2 the second y coordinate of the other segment
 366:  * @return true if the segments intersect
 367:  * @see #linesIntersect(double, double, double, double,
 368:  * double, double, double, double)
 369:  */
 370:  public boolean intersectsLine(double x1, double y1, double x2, double y2)
 371:  {
 372:  return linesIntersect(getX1(), getY1(), getX2(), getY2(),
 373:  x1, y1, x2, y2);
 374:  }
 375: 
 376:  /**
 377:  * Test if this line intersects the given line.
 378:  *
 379:  * @param l the other segment
 380:  * @return true if the segments intersect
 381:  * @throws NullPointerException if l is null
 382:  * @see #linesIntersect(double, double, double, double,
 383:  * double, double, double, double)
 384:  */
 385:  public boolean intersectsLine(Line2D l)
 386:  {
 387:  return linesIntersect(getX1(), getY1(), getX2(), getY2(),
 388:  l.getX1(), l.getY1(), l.getX2(), l.getY2());
 389:  }
 390: 
 391:  /**
 392:  * Measures the square of the shortest distance from the reference point
 393:  * to a point on the line segment. If the point is on the segment, the
 394:  * result will be 0.
 395:  *
 396:  * @param x1 the first x coordinate of the segment
 397:  * @param y1 the first y coordinate of the segment
 398:  * @param x2 the second x coordinate of the segment
 399:  * @param y2 the second y coordinate of the segment
 400:  * @param px the x coordinate of the point
 401:  * @param py the y coordinate of the point
 402:  * @return the square of the distance from the point to the segment
 403:  * @see #ptSegDist(double, double, double, double, double, double)
 404:  * @see #ptLineDistSq(double, double, double, double, double, double)
 405:  */
 406:  public static double ptSegDistSq(double x1, double y1, double x2, double y2,
 407:  double px, double py)
 408:  {
 409:  double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
 410: 
 411:  double x, y;
 412:  if (pd2 == 0)
 413:  {
 414:  // Points are coincident.
 415:  x = x1;
 416:  y = y2;
 417:  }
 418:  else
 419:  {
 420:  double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
 421: 
 422:  if (u < 0)
 423:  {
 424:  // "Off the end"
 425:  x = x1;
 426:  y = y1;
 427:  }
 428:  else if (u > 1.0)
 429:  {
 430:  x = x2;
 431:  y = y2;
 432:  }
 433:  else
 434:  {
 435:  x = x1 + u * (x2 - x1);
 436:  y = y1 + u * (y2 - y1);
 437:  }
 438:  }
 439: 
 440:  return (x - px) * (x - px) + (y - py) * (y - py);
 441:  }
 442: 
 443:  /**
 444:  * Measures the shortest distance from the reference point to a point on
 445:  * the line segment. If the point is on the segment, the result will be 0.
 446:  *
 447:  * @param x1 the first x coordinate of the segment
 448:  * @param y1 the first y coordinate of the segment
 449:  * @param x2 the second x coordinate of the segment
 450:  * @param y2 the second y coordinate of the segment
 451:  * @param px the x coordinate of the point
 452:  * @param py the y coordinate of the point
 453:  * @return the distance from the point to the segment
 454:  * @see #ptSegDistSq(double, double, double, double, double, double)
 455:  * @see #ptLineDist(double, double, double, double, double, double)
 456:  */
 457:  public static double ptSegDist(double x1, double y1, double x2, double y2,
 458:  double px, double py)
 459:  {
 460:  return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
 461:  }
 462: 
 463:  /**
 464:  * Measures the square of the shortest distance from the reference point
 465:  * to a point on this line segment. If the point is on the segment, the
 466:  * result will be 0.
 467:  *
 468:  * @param px the x coordinate of the point
 469:  * @param py the y coordinate of the point
 470:  * @return the square of the distance from the point to the segment
 471:  * @see #ptSegDistSq(double, double, double, double, double, double)
 472:  */
 473:  public double ptSegDistSq(double px, double py)
 474:  {
 475:  return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
 476:  }
 477: 
 478:  /**
 479:  * Measures the square of the shortest distance from the reference point
 480:  * to a point on this line segment. If the point is on the segment, the
 481:  * result will be 0.
 482:  *
 483:  * @param p the point
 484:  * @return the square of the distance from the point to the segment
 485:  * @throws NullPointerException if p is null
 486:  * @see #ptSegDistSq(double, double, double, double, double, double)
 487:  */
 488:  public double ptSegDistSq(Point2D p)
 489:  {
 490:  return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
 491:  }
 492: 
 493:  /**
 494:  * Measures the shortest distance from the reference point to a point on
 495:  * this line segment. If the point is on the segment, the result will be 0.
 496:  *
 497:  * @param px the x coordinate of the point
 498:  * @param py the y coordinate of the point
 499:  * @return the distance from the point to the segment
 500:  * @see #ptSegDist(double, double, double, double, double, double)
 501:  */
 502:  public double ptSegDist(double px, double py)
 503:  {
 504:  return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
 505:  }
 506: 
 507:  /**
 508:  * Measures the shortest distance from the reference point to a point on
 509:  * this line segment. If the point is on the segment, the result will be 0.
 510:  *
 511:  * @param p the point
 512:  * @return the distance from the point to the segment
 513:  * @throws NullPointerException if p is null
 514:  * @see #ptSegDist(double, double, double, double, double, double)
 515:  */
 516:  public double ptSegDist(Point2D p)
 517:  {
 518:  return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
 519:  }
 520: 
 521:  /**
 522:  * Measures the square of the shortest distance from the reference point
 523:  * to a point on the infinite line extended from the segment. If the point
 524:  * is on the segment, the result will be 0. If the segment is length 0,
 525:  * the distance is to the common endpoint.
 526:  *
 527:  * @param x1 the first x coordinate of the segment
 528:  * @param y1 the first y coordinate of the segment
 529:  * @param x2 the second x coordinate of the segment
 530:  * @param y2 the second y coordinate of the segment
 531:  * @param px the x coordinate of the point
 532:  * @param py the y coordinate of the point
 533:  * @return the square of the distance from the point to the extended line
 534:  * @see #ptLineDist(double, double, double, double, double, double)
 535:  * @see #ptSegDistSq(double, double, double, double, double, double)
 536:  */
 537:  public static double ptLineDistSq(double x1, double y1, double x2, double y2,
 538:  double px, double py)
 539:  {
 540:  double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
 541: 
 542:  double x, y;
 543:  if (pd2 == 0)
 544:  {
 545:  // Points are coincident.
 546:  x = x1;
 547:  y = y2;
 548:  }
 549:  else
 550:  {
 551:  double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
 552:  x = x1 + u * (x2 - x1);
 553:  y = y1 + u * (y2 - y1);
 554:  }
 555: 
 556:  return (x - px) * (x - px) + (y - py) * (y - py);
 557:  }
 558: 
 559:  /**
 560:  * Measures the shortest distance from the reference point to a point on
 561:  * the infinite line extended from the segment. If the point is on the
 562:  * segment, the result will be 0. If the segment is length 0, the distance
 563:  * is to the common endpoint.
 564:  *
 565:  * @param x1 the first x coordinate of the segment
 566:  * @param y1 the first y coordinate of the segment
 567:  * @param x2 the second x coordinate of the segment
 568:  * @param y2 the second y coordinate of the segment
 569:  * @param px the x coordinate of the point
 570:  * @param py the y coordinate of the point
 571:  * @return the distance from the point to the extended line
 572:  * @see #ptLineDistSq(double, double, double, double, double, double)
 573:  * @see #ptSegDist(double, double, double, double, double, double)
 574:  */
 575:  public static double ptLineDist(double x1, double y1,
 576:  double x2, double y2,
 577:  double px, double py)
 578:  {
 579:  return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
 580:  }
 581: 
 582:  /**
 583:  * Measures the square of the shortest distance from the reference point
 584:  * to a point on the infinite line extended from this segment. If the point
 585:  * is on the segment, the result will be 0. If the segment is length 0,
 586:  * the distance is to the common endpoint.
 587:  *
 588:  * @param px the x coordinate of the point
 589:  * @param py the y coordinate of the point
 590:  * @return the square of the distance from the point to the extended line
 591:  * @see #ptLineDistSq(double, double, double, double, double, double)
 592:  */
 593:  public double ptLineDistSq(double px, double py)
 594:  {
 595:  return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
 596:  }
 597: 
 598:  /**
 599:  * Measures the square of the shortest distance from the reference point
 600:  * to a point on the infinite line extended from this segment. If the point
 601:  * is on the segment, the result will be 0. If the segment is length 0,
 602:  * the distance is to the common endpoint.
 603:  *
 604:  * @param p the point
 605:  * @return the square of the distance from the point to the extended line
 606:  * @throws NullPointerException if p is null
 607:  * @see #ptLineDistSq(double, double, double, double, double, double)
 608:  */
 609:  public double ptLineDistSq(Point2D p)
 610:  {
 611:  return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
 612:  p.getX(), p.getY());
 613:  }
 614: 
 615:  /**
 616:  * Measures the shortest distance from the reference point to a point on
 617:  * the infinite line extended from this segment. If the point is on the
 618:  * segment, the result will be 0. If the segment is length 0, the distance
 619:  * is to the common endpoint.
 620:  *
 621:  * @param px the x coordinate of the point
 622:  * @param py the y coordinate of the point
 623:  * @return the distance from the point to the extended line
 624:  * @see #ptLineDist(double, double, double, double, double, double)
 625:  */
 626:  public double ptLineDist(double px, double py)
 627:  {
 628:  return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
 629:  }
 630: 
 631:  /**
 632:  * Measures the shortest distance from the reference point to a point on
 633:  * the infinite line extended from this segment. If the point is on the
 634:  * segment, the result will be 0. If the segment is length 0, the distance
 635:  * is to the common endpoint.
 636:  *
 637:  * @param p the point
 638:  * @return the distance from the point to the extended line
 639:  * @throws NullPointerException if p is null
 640:  * @see #ptLineDist(double, double, double, double, double, double)
 641:  */
 642:  public double ptLineDist(Point2D p)
 643:  {
 644:  return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
 645:  }
 646: 
 647:  /**
 648:  * Test if a point is contained inside the line. Since a line has no area,
 649:  * this returns false.
 650:  *
 651:  * @param x the x coordinate
 652:  * @param y the y coordinate
 653:  * @return false; the line does not contain points
 654:  */
 655:  public boolean contains(double x, double y)
 656:  {
 657:  return false;
 658:  }
 659: 
 660:  /**
 661:  * Test if a point is contained inside the line. Since a line has no area,
 662:  * this returns false.
 663:  *
 664:  * @param p the point
 665:  * @return false; the line does not contain points
 666:  */
 667:  public boolean contains(Point2D p)
 668:  {
 669:  return false;
 670:  }
 671: 
 672:  /**
 673:  * Tests if this line intersects the interior of the specified rectangle.
 674:  *
 675:  * @param x the x coordinate of the rectangle
 676:  * @param y the y coordinate of the rectangle
 677:  * @param w the width of the rectangle
 678:  * @param h the height of the rectangle
 679:  * @return true if the line intersects the rectangle
 680:  */
 681:  public boolean intersects(double x, double y, double w, double h)
 682:  {
 683:  if (w <= 0 || h <= 0)
 684:  return false;
 685:  double x1 = getX1();
 686:  double y1 = getY1();
 687:  double x2 = getX2();
 688:  double y2 = getY2();
 689: 
 690:  if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
 691:  return true;
 692:  if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
 693:  return true;
 694: 
 695:  double x3 = x + w;
 696:  double y3 = y + h;
 697: 
 698:  return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
 699:  || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
 700:  || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
 701:  || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
 702:  }
 703: 
 704:  /**
 705:  * Tests if this line intersects the interior of the specified rectangle.
 706:  *
 707:  * @param r the rectangle
 708:  * @return true if the line intersects the rectangle
 709:  * @throws NullPointerException if r is null
 710:  */
 711:  public boolean intersects(Rectangle2D r)
 712:  {
 713:  return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
 714:  }
 715: 
 716:  /**
 717:  * Tests if the line contains a rectangle. Since lines have no area, this
 718:  * always returns false.
 719:  *
 720:  * @param x the x coordinate of the rectangle
 721:  * @param y the y coordinate of the rectangle
 722:  * @param w the width of the rectangle
 723:  * @param h the height of the rectangle
 724:  * @return false; the line does not contain points
 725:  */
 726:  public boolean contains(double x, double y, double w, double h)
 727:  {
 728:  return false;
 729:  }
 730: 
 731:  /**
 732:  * Tests if the line contains a rectangle. Since lines have no area, this
 733:  * always returns false.
 734:  *
 735:  * @param r the rectangle
 736:  * @return false; the line does not contain points
 737:  */
 738:  public boolean contains(Rectangle2D r)
 739:  {
 740:  return false;
 741:  }
 742: 
 743:  /**
 744:  * Gets a bounding box (not necessarily minimal) for this line.
 745:  *
 746:  * @return the integer bounding box
 747:  * @see #getBounds2D()
 748:  */
 749:  public Rectangle getBounds()
 750:  {
 751:  return getBounds2D().getBounds();
 752:  }
 753: 
 754:  /**
 755:  * Return a path iterator, possibly applying a transform on the result. This
 756:  * iterator is not threadsafe.
 757:  *
 758:  * @param at the transform, or null
 759:  * @return a new path iterator
 760:  */
 761:  public PathIterator getPathIterator(final AffineTransform at)
 762:  {
 763:  return new PathIterator()
 764:  {
 765:  /** Current coordinate. */
 766:  private int current = 0;
 767: 
 768:  public int getWindingRule()
 769:  {
 770:  return WIND_NON_ZERO;
 771:  }
 772: 
 773:  public boolean isDone()
 774:  {
 775:  return current >= 2;
 776:  }
 777: 
 778:  public void next()
 779:  {
 780:  current++;
 781:  }
 782: 
 783:  public int currentSegment(float[] coords)
 784:  {
 785:  int result;
 786:  switch (current)
 787:  {
 788:  case 0:
 789:  coords[0] = (float) getX1();
 790:  coords[1] = (float) getY1();
 791:  result = SEG_MOVETO;
 792:  break;
 793:  case 1:
 794:  coords[0] = (float) getX2();
 795:  coords[1] = (float) getY2();
 796:  result = SEG_LINETO;
 797:  break;
 798:  default:
 799:  throw new NoSuchElementException("line iterator out of bounds");
 800:  }
 801:  if (at != null)
 802:  at.transform(coords, 0, coords, 0, 1);
 803:  return result;
 804:  }
 805: 
 806:  public int currentSegment(double[] coords)
 807:  {
 808:  int result;
 809:  switch (current)
 810:  {
 811:  case 0:
 812:  coords[0] = getX1();
 813:  coords[1] = getY1();
 814:  result = SEG_MOVETO;
 815:  break;
 816:  case 1:
 817:  coords[0] = getX2();
 818:  coords[1] = getY2();
 819:  result = SEG_LINETO;
 820:  break;
 821:  default:
 822:  throw new NoSuchElementException("line iterator out of bounds");
 823:  }
 824:  if (at != null)
 825:  at.transform(coords, 0, coords, 0, 1);
 826:  return result;
 827:  }
 828:  };
 829:  }
 830: 
 831:  /**
 832:  * Return a flat path iterator, possibly applying a transform on the result.
 833:  * This iterator is not threadsafe.
 834:  *
 835:  * @param at the transform, or null
 836:  * @param flatness ignored, since lines are already flat
 837:  * @return a new path iterator
 838:  * @see #getPathIterator(AffineTransform)
 839:  */
 840:  public PathIterator getPathIterator(AffineTransform at, double flatness)
 841:  {
 842:  return getPathIterator(at);
 843:  }
 844: 
 845:  /**
 846:  * Create a new line of the same run-time type with the same contents as
 847:  * this one.
 848:  *
 849:  * @return the clone
 850:  *
 851:  * @exception OutOfMemoryError If there is not enough memory available.
 852:  *
 853:  * @since 1.2
 854:  */
 855:  public Object clone()
 856:  {
 857:  try
 858:  {
 859:  return super.clone();
 860:  }
 861:  catch (CloneNotSupportedException e)
 862:  {
 863:  throw (Error) new InternalError().initCause(e); // Impossible
 864:  }
 865:  }
 866: 
 867:  /**
 868:  * This class defines a point in <code>double</code> precision.
 869:  *
 870:  * @author Eric Blake (ebb9@email.byu.edu)
 871:  * @since 1.2
 872:  * @status updated to 1.4
 873:  */
 874:  public static class Double extends Line2D
 875:  {
 876:  /** The x coordinate of the first point. */
 877:  public double x1;
 878: 
 879:  /** The y coordinate of the first point. */
 880:  public double y1;
 881: 
 882:  /** The x coordinate of the second point. */
 883:  public double x2;
 884: 
 885:  /** The y coordinate of the second point. */
 886:  public double y2;
 887: 
 888:  /**
 889:  * Construct the line segment (0,0)-&gt;(0,0).
 890:  */
 891:  public Double()
 892:  {
 893:  }
 894: 
 895:  /**
 896:  * Construct the line segment with the specified points.
 897:  *
 898:  * @param x1 the x coordinate of the first point
 899:  * @param y1 the y coordinate of the first point
 900:  * @param x2 the x coordinate of the second point
 901:  * @param y2 the y coordinate of the second point
 902:  */
 903:  public Double(double x1, double y1, double x2, double y2)
 904:  {
 905:  this.x1 = x1;
 906:  this.y1 = y1;
 907:  this.x2 = x2;
 908:  this.y2 = y2;
 909:  }
 910: 
 911:  /**
 912:  * Construct the line segment with the specified points.
 913:  *
 914:  * @param p1 the first point
 915:  * @param p2 the second point
 916:  * @throws NullPointerException if either point is null
 917:  */
 918:  public Double(Point2D p1, Point2D p2)
 919:  {
 920:  x1 = p1.getX();
 921:  y1 = p1.getY();
 922:  x2 = p2.getX();
 923:  y2 = p2.getY();
 924:  }
 925: 
 926:  /**
 927:  * Return the x coordinate of the first point.
 928:  *
 929:  * @return the value of x1
 930:  */
 931:  public double getX1()
 932:  {
 933:  return x1;
 934:  }
 935: 
 936:  /**
 937:  * Return the y coordinate of the first point.
 938:  *
 939:  * @return the value of y1
 940:  */
 941:  public double getY1()
 942:  {
 943:  return y1;
 944:  }
 945: 
 946:  /**
 947:  * Return the first point.
 948:  *
 949:  * @return the point (x1,y1)
 950:  */
 951:  public Point2D getP1()
 952:  {
 953:  return new Point2D.Double(x1, y1);
 954:  }
 955: 
 956:  /**
 957:  * Return the x coordinate of the second point.
 958:  *
 959:  * @return the value of x2
 960:  */
 961:  public double getX2()
 962:  {
 963:  return x2;
 964:  }
 965: 
 966:  /**
 967:  * Return the y coordinate of the second point.
 968:  *
 969:  * @return the value of y2
 970:  */
 971:  public double getY2()
 972:  {
 973:  return y2;
 974:  }
 975: 
 976:  /**
 977:  * Return the second point.
 978:  *
 979:  * @return the point (x2,y2)
 980:  */
 981:  public Point2D getP2()
 982:  {
 983:  return new Point2D.Double(x2, y2);
 984:  }
 985: 
 986:  /**
 987:  * Set this line to the given points.
 988:  *
 989:  * @param x1 the new x coordinate of the first point
 990:  * @param y1 the new y coordinate of the first point
 991:  * @param x2 the new x coordinate of the second point
 992:  * @param y2 the new y coordinate of the second point
 993:  */
 994:  public void setLine(double x1, double y1, double x2, double y2)
 995:  {
 996:  this.x1 = x1;
 997:  this.y1 = y1;
 998:  this.x2 = x2;
 999:  this.y2 = y2;
1000:  }
1001: 
1002:  /**
1003:  * Return the exact bounds of this line segment.
1004:  *
1005:  * @return the bounding box
1006:  */
1007:  public Rectangle2D getBounds2D()
1008:  {
1009:  double x = Math.min(x1, x2);
1010:  double y = Math.min(y1, y2);
1011:  double w = Math.abs(x1 - x2);
1012:  double h = Math.abs(y1 - y2);
1013:  return new Rectangle2D.Double(x, y, w, h);
1014:  }
1015:  } // class Double
1016: 
1017:  /**
1018:  * This class defines a point in <code>float</code> precision.
1019:  *
1020:  * @author Eric Blake (ebb9@email.byu.edu)
1021:  * @since 1.2
1022:  * @status updated to 1.4
1023:  */
1024:  public static class Float extends Line2D
1025:  {
1026:  /** The x coordinate of the first point. */
1027:  public float x1;
1028: 
1029:  /** The y coordinate of the first point. */
1030:  public float y1;
1031: 
1032:  /** The x coordinate of the second point. */
1033:  public float x2;
1034: 
1035:  /** The y coordinate of the second point. */
1036:  public float y2;
1037: 
1038:  /**
1039:  * Construct the line segment (0,0)-&gt;(0,0).
1040:  */
1041:  public Float()
1042:  {
1043:  }
1044: 
1045:  /**
1046:  * Construct the line segment with the specified points.
1047:  *
1048:  * @param x1 the x coordinate of the first point
1049:  * @param y1 the y coordinate of the first point
1050:  * @param x2 the x coordinate of the second point
1051:  * @param y2 the y coordinate of the second point
1052:  */
1053:  public Float(float x1, float y1, float x2, float y2)
1054:  {
1055:  this.x1 = x1;
1056:  this.y1 = y1;
1057:  this.x2 = x2;
1058:  this.y2 = y2;
1059:  }
1060: 
1061:  /**
1062:  * Construct the line segment with the specified points.
1063:  *
1064:  * @param p1 the first point
1065:  * @param p2 the second point
1066:  * @throws NullPointerException if either point is null
1067:  */
1068:  public Float(Point2D p1, Point2D p2)
1069:  {
1070:  x1 = (float) p1.getX();
1071:  y1 = (float) p1.getY();
1072:  x2 = (float) p2.getX();
1073:  y2 = (float) p2.getY();
1074:  }
1075: 
1076:  /**
1077:  * Return the x coordinate of the first point.
1078:  *
1079:  * @return the value of x1
1080:  */
1081:  public double getX1()
1082:  {
1083:  return x1;
1084:  }
1085: 
1086:  /**
1087:  * Return the y coordinate of the first point.
1088:  *
1089:  * @return the value of y1
1090:  */
1091:  public double getY1()
1092:  {
1093:  return y1;
1094:  }
1095: 
1096:  /**
1097:  * Return the first point.
1098:  *
1099:  * @return the point (x1,y1)
1100:  */
1101:  public Point2D getP1()
1102:  {
1103:  return new Point2D.Float(x1, y1);
1104:  }
1105: 
1106:  /**
1107:  * Return the x coordinate of the second point.
1108:  *
1109:  * @return the value of x2
1110:  */
1111:  public double getX2()
1112:  {
1113:  return x2;
1114:  }
1115: 
1116:  /**
1117:  * Return the y coordinate of the second point.
1118:  *
1119:  * @return the value of y2
1120:  */
1121:  public double getY2()
1122:  {
1123:  return y2;
1124:  }
1125: 
1126:  /**
1127:  * Return the second point.
1128:  *
1129:  * @return the point (x2,y2)
1130:  */
1131:  public Point2D getP2()
1132:  {
1133:  return new Point2D.Float(x2, y2);
1134:  }
1135: 
1136:  /**
1137:  * Set this line to the given points.
1138:  *
1139:  * @param x1 the new x coordinate of the first point
1140:  * @param y1 the new y coordinate of the first point
1141:  * @param x2 the new x coordinate of the second point
1142:  * @param y2 the new y coordinate of the second point
1143:  */
1144:  public void setLine(double x1, double y1, double x2, double y2)
1145:  {
1146:  this.x1 = (float) x1;
1147:  this.y1 = (float) y1;
1148:  this.x2 = (float) x2;
1149:  this.y2 = (float) y2;
1150:  }
1151: 
1152:  /**
1153:  * Set this line to the given points.
1154:  *
1155:  * @param x1 the new x coordinate of the first point
1156:  * @param y1 the new y coordinate of the first point
1157:  * @param x2 the new x coordinate of the second point
1158:  * @param y2 the new y coordinate of the second point
1159:  */
1160:  public void setLine(float x1, float y1, float x2, float y2)
1161:  {
1162:  this.x1 = x1;
1163:  this.y1 = y1;
1164:  this.x2 = x2;
1165:  this.y2 = y2;
1166:  }
1167: 
1168:  /**
1169:  * Return the exact bounds of this line segment.
1170:  *
1171:  * @return the bounding box
1172:  */
1173:  public Rectangle2D getBounds2D()
1174:  {
1175:  float x = Math.min(x1, x2);
1176:  float y = Math.min(y1, y2);
1177:  float w = Math.abs(x1 - x2);
1178:  float h = Math.abs(y1 - y2);
1179:  return new Rectangle2D.Float(x, y, w, h);
1180:  }
1181:  } // class Float
1182: } // class Line2D
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /