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