001/* Line2D.java -- represents a line in 2-D space, plus operations on a line 002 Copyright (C) 2000, 2001, 2002 Free Software Foundation 003 004This file is part of GNU Classpath. 005 006GNU Classpath is free software; you can redistribute it and/or modify 007it under the terms of the GNU General Public License as published by 008the Free Software Foundation; either version 2, or (at your option) 009any later version. 010 011GNU Classpath is distributed in the hope that it will be useful, but 012WITHOUT ANY WARRANTY; without even the implied warranty of 013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014General Public License for more details. 015 016You should have received a copy of the GNU General Public License 017along with GNU Classpath; see the file COPYING. If not, write to the 018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 01902110-1301 USA. 020 021Linking this library statically or dynamically with other modules is 022making a combined work based on this library. Thus, the terms and 023conditions of the GNU General Public License cover the whole 024combination. 025 026As a special exception, the copyright holders of this library give you 027permission to link this library with independent modules to produce an 028executable, regardless of the license terms of these independent 029modules, and to copy and distribute the resulting executable under 030terms of your choice, provided that you also meet, for each linked 031independent module, the terms and conditions of the license of that 032module. An independent module is a module which is not derived from 033or based on this library. If you modify this library, you may extend 034this exception to your version of the library, but you are not 035obligated to do so. If you do not wish to do so, delete this 036exception statement from your version. */ 037 038package java.awt.geom; 039 040import java.awt.Rectangle; 041import java.awt.Shape; 042import java.util.NoSuchElementException; 043 044/** 045 * Represents a directed line bewteen two points in (x,y) Cartesian space. 046 * Remember, on-screen graphics have increasing x from left-to-right, and 047 * increasing y from top-to-bottom. The storage is left to subclasses. 048 * 049 * @author Tom Tromey (tromey@cygnus.com) 050 * @author Eric Blake (ebb9@email.byu.edu) 051 * @author David Gilbert 052 * @since 1.2 053 * @status updated to 1.4 054 */ 055public abstract class Line2D implements Shape, Cloneable 056{ 057 /** 058 * The default constructor. 059 */ 060 protected Line2D() 061 { 062 } 063 064 /** 065 * Return the x coordinate of the first point. 066 * 067 * @return the starting x coordinate 068 */ 069 public abstract double getX1(); 070 071 /** 072 * Return the y coordinate of the first point. 073 * 074 * @return the starting y coordinate 075 */ 076 public abstract double getY1(); 077 078 /** 079 * Return the first point. 080 * 081 * @return the starting point 082 */ 083 public abstract Point2D getP1(); 084 085 /** 086 * Return the x coordinate of the second point. 087 * 088 * @return the ending x coordinate 089 */ 090 public abstract double getX2(); 091 092 /** 093 * Return the y coordinate of the second point. 094 * 095 * @return the ending y coordinate 096 */ 097 public abstract double getY2(); 098 099 /** 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)->(x2,y2) intersects the line segment 286 * (x3,y3)->(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)->(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)->(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)->(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