1 |
/* Copyright (C) 2000, 2001, 2002 Free Software Foundation |
/* 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. |
This file is part of GNU Classpath. |
5 |
|
|
39 |
|
|
40 |
import java.awt.Rectangle; |
import java.awt.Rectangle; |
41 |
import java.awt.Shape; |
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> |
* @author Tom Tromey <tromey@cygnus.com> |
50 |
* @date April 21, 2001 |
* @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 |
public abstract class Line2D implements Shape, Cloneable |
55 |
{ |
{ |
56 |
protected Line2D () |
/** |
57 |
{ |
* The default constructor. |
58 |
} |
*/ |
59 |
|
protected Line2D() |
60 |
public Object clone () |
{ |
61 |
{ |
} |
62 |
try |
|
63 |
{ |
/** |
64 |
return super.clone (); |
* Return the x coordinate of the first point. |
65 |
} |
* |
66 |
catch (CloneNotSupportedException _) |
* @return the starting x coordinate |
67 |
{ |
*/ |
68 |
// Can't happen. |
public abstract double getX1(); |
69 |
return null; |
|
70 |
} |
/** |
71 |
} |
* Return the y coordinate of the first point. |
72 |
|
* |
73 |
public boolean contains (double x, double y) |
* @return the starting y coordinate |
74 |
{ |
*/ |
75 |
double x1 = getX1 (); |
public abstract double getY1(); |
76 |
double t1 = (x - x1) / (getX2 () - x1); |
|
77 |
if (t1 < 0 || t1 > 1) |
/** |
78 |
return false; |
* Return the first point. |
79 |
double y1 = getY1 (); |
* |
80 |
double t2 = (y - y1) / (getY2 () - y1); |
* @return the starting point |
81 |
// FIXME: use of == here is bogus |
*/ |
82 |
return t2 >= 0 && t2 <= 1 && t1 == t2; |
public abstract Point2D getP1(); |
83 |
} |
|
84 |
|
/** |
85 |
public boolean contains (double x, double y, double w, double h) |
* Return the x coordinate of the second point. |
86 |
{ |
* |
87 |
return false; |
* @return the ending x coordinate |
88 |
} |
*/ |
89 |
|
public abstract double getX2(); |
90 |
public boolean contains (Point2D p) |
|
91 |
{ |
/** |
92 |
return contains (p.getX (), p.getY ()); |
* Return the y coordinate of the second point. |
93 |
} |
* |
94 |
|
* @return the ending y coordinate |
95 |
public boolean contains (Rectangle2D r) |
*/ |
96 |
{ |
public abstract double getY2(); |
97 |
return false; |
|
98 |
} |
/** |
99 |
|
* Return the second point. |
100 |
public Rectangle getBounds () |
* |
101 |
{ |
* @return the ending point |
102 |
double x1 = getX1 (); |
*/ |
103 |
double y1 = getY1 (); |
public abstract Point2D getP2(); |
104 |
double x2 = getX2 (); |
|
105 |
double y2 = getY2 (); |
/** |
106 |
|
* Set the coordinates of the line to the given coordinates. Loss of |
107 |
double x = Math.min (x1, x2); |
* precision may occur due to rounding issues. |
108 |
double y = Math.min (y1, y2); |
* |
109 |
double w = Math.abs (x1 - x2); |
* @param x1 the first x coordinate |
110 |
double h = Math.abs (y1 - y2); |
* @param y1 the first y coordinate |
111 |
|
* @param x2 the second x coordinate |
112 |
return new Rectangle ((int) x, (int) y, (int) w, (int) h); |
* @param y2 the second y coordinate |
113 |
} |
*/ |
114 |
|
public abstract void setLine(double x1, double y1, double x2, double y2); |
115 |
public abstract Point2D getP1 (); |
|
116 |
public abstract Point2D getP2 (); |
/** |
117 |
|
* Set the coordinates to the given points. |
118 |
public PathIterator getPathIterator (AffineTransform at) |
* |
119 |
{ |
* @param p1 the first point |
120 |
return getPathIterator (at, 0); |
* @param p2 the second point |
121 |
} |
* @throws NullPointerException if either point is null |
122 |
|
*/ |
123 |
public PathIterator getPathIterator (AffineTransform at, double flatness) |
public void setLine(Point2D p1, Point2D p2) |
124 |
{ |
{ |
125 |
return at.new Iterator (new Iterator ()); |
setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY()); |
126 |
} |
} |
127 |
|
|
128 |
public abstract double getX1 (); |
/** |
129 |
public abstract double getY1 (); |
* Set the coordinates to those of the given line. |
130 |
public abstract double getX2 (); |
* |
131 |
public abstract double getY2 (); |
* @param l the line to copy |
132 |
|
* @throws NullPointerException if l is null |
133 |
public boolean intersects (double x, double y, double w, double h) |
*/ |
134 |
{ |
public void setLine(Line2D l) |
135 |
double x1 = getX1 (); |
{ |
136 |
double y1 = getY1 (); |
setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); |
137 |
double x2 = getX2 (); |
} |
138 |
double y2 = getY2 (); |
|
139 |
|
/** |
140 |
if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y +h) |
* Computes the relative rotation direction needed to pivot the line about |
141 |
return true; |
* the first point in order to have the second point colinear with point p. |
142 |
if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y +h) |
* Because of floating point rounding, don't expect this to be a perfect |
143 |
return true; |
* 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 |
double x3 = x + w; |
* (counter-clockwise in the default Java coordinate system), or -1 if the |
146 |
double y3 = y + h; |
* 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 |
return (linesIntersect (x1, y1, x2, y2, x, y, x, y3) |
* point, 0 if it lies in the segment, or 1 if it lies beyond the second |
149 |
|| linesIntersect (x1, y1, x2, y2, x, y3, x3, y3) |
* point. If the first and second point are coincident, this returns 0. |
150 |
|| linesIntersect (x1, y1, x2, y2, x3, y3, x3, y) |
* |
151 |
|| linesIntersect (x1, y1, x2, y2, x3, y, x, y)); |
* @param x1 the first x coordinate |
152 |
} |
* @param y1 the first y coordinate |
153 |
|
* @param x2 the second x coordinate |
154 |
public boolean intersects (Rectangle2D r) |
* @param y2 the second y coordinate |
155 |
{ |
* @param px the reference x coordinate |
156 |
return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); |
* @param py the reference y coordinate |
157 |
} |
* @return the relative rotation direction |
158 |
|
*/ |
159 |
public boolean intersectsLine (double x1, double y1, double x2, double y2) |
public static int relativeCCW(double x1, double y1, double x2, double y2, |
160 |
{ |
double px, double py) |
161 |
return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(), |
{ |
162 |
x1, y1, x2, y2); |
if ((x1 == x2 && y1 == y2) |
163 |
} |
|| (x1 == px && y1 == py)) |
164 |
|
return 0; // Coincident points. |
165 |
public boolean intersectsLine (Line2D l) |
// Translate to the origin. |
166 |
{ |
x2 -= x1; |
167 |
return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(), |
y2 -= y1; |
168 |
l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ()); |
px -= x1; |
169 |
} |
py -= y1; |
170 |
|
double slope2 = y2 / x2; |
171 |
public static boolean linesIntersect (double x1, double y1, |
double slopep = py / px; |
172 |
double x2, double y2, |
if (slope2 == slopep || (x2 == 0 && px == 0)) |
173 |
double x3,double y3, |
return y2 > 0 // Colinear. |
174 |
double x4, double y4) |
? (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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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)) |
double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3)) |
257 |
/ ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3))); |
/ ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3))); |
258 |
if (beta < 0.0 || beta > 1.0) |
if (beta < 0.0 || beta > 1.0) |
259 |
return false; |
return false; |
260 |
double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3); |
double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3); |
261 |
return alpha >= 0.0 && alpha <= 1.0; |
return alpha >= 0.0 && alpha <= 1.0; |
262 |
} |
} |
263 |
|
|
264 |
public double ptLineDist (double px, double py) |
/** |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
311 |
|
public static double ptSegDistSq(double x1, double y1, double x2, double y2, |
312 |
|
double px, double py) |
313 |
{ |
{ |
314 |
return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (), |
double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); |
|
px, py); |
|
|
} |
|
315 |
|
|
316 |
public static double ptLineDist (double x1, double y1, |
double x, y; |
317 |
double x2, double y2, |
if (pd2 == 0) |
318 |
double px, double py) |
{ |
319 |
{ |
// Points are coincident. |
320 |
return Math.sqrt (ptLineDistSq (x1, y1, x2, y2, px, py)); |
x = x1; |
321 |
} |
y = y2; |
322 |
|
} |
323 |
|
else |
324 |
|
{ |
325 |
|
double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; |
326 |
|
|
327 |
public double ptLineDist (Point2D p) |
if (u < 0) |
328 |
{ |
{ |
329 |
return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (), |
// "Off the end" |
330 |
p.getX (), p.getY ()); |
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 |
public double ptLineDistSq (double px, double py) |
return (x - px) * (x - px) + (y - py) * (y - py); |
|
{ |
|
|
return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (), |
|
|
px, py); |
|
346 |
} |
} |
347 |
|
|
348 |
public static double ptLineDistSq (double x1, double y1, |
/** |
349 |
double x2, double y2, |
* Measures the shortest distance from the reference point to a point on |
350 |
double px, double py) |
* 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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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); |
double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); |
446 |
|
|
447 |
double x, y; |
double x, y; |
448 |
if (pd2 == 0) |
if (pd2 == 0) |
449 |
{ |
{ |
450 |
// Points are coincident. |
// Points are coincident. |
451 |
x = x1; |
x = x1; |
452 |
y = y2; |
y = y2; |
453 |
} |
} |
454 |
else |
else |
455 |
{ |
{ |
456 |
double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; |
double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; |
457 |
x = x1 + u * (x2 - x1); |
x = x1 + u * (x2 - x1); |
458 |
y = y1 + u * (y2 - y1); |
y = y1 + u * (y2 - y1); |
459 |
} |
} |
460 |
|
|
461 |
return (x - px) * (x - px) + (y - py) * (y - py); |
return (x - px) * (x - px) + (y - py) * (y - py); |
462 |
} |
} |
463 |
|
|
464 |
public double ptLineDistSq (Point2D p) |
/** |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
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 |
|
*/ |
560 |
|
public boolean contains(double x, double y) |
561 |
{ |
{ |
562 |
return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (), |
return false; |
|
p.getX (), p.getY ()); |
|
563 |
} |
} |
564 |
|
|
565 |
public double ptSegDist (double px, double py) |
/** |
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 |
|
*/ |
572 |
|
public boolean contains(Point2D p) |
573 |
{ |
{ |
574 |
return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (), |
return false; |
|
px, py); |
|
575 |
} |
} |
576 |
|
|
577 |
public static double ptSegDist (double x1, double y1, |
/** |
578 |
double x2, double y2, |
* Tests if this line intersects the interior of the specified rectangle. |
579 |
double px, double py) |
* |
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 |
|
*/ |
586 |
|
public boolean intersects(double x, double y, double w, double h) |
587 |
{ |
{ |
588 |
return Math.sqrt (ptSegDistSq (x1, y1, x2, y2, px, py)); |
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 |
public double ptSegDist (Point2D p) |
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 |
|
*/ |
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 |
|
*/ |
631 |
|
public boolean contains(double x, double y, double w, double h) |
632 |
{ |
{ |
633 |
return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (), |
return false; |
|
p.getX (), p.getY ()); |
|
634 |
} |
} |
635 |
|
|
636 |
public double ptSegDistSq (double px, double py) |
/** |
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 |
|
*/ |
643 |
|
public boolean contains(Rectangle2D r) |
644 |
{ |
{ |
645 |
return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (), |
return false; |
|
px, py); |
|
646 |
} |
} |
647 |
|
|
648 |
public static double ptSegDistSq (double x1, double y1, |
/** |
649 |
double x2, double y2, |
* Gets a bounding box (not necessarily minimal) for this line. |
650 |
double px, double py) |
* |
651 |
|
* @return the integer bounding box |
652 |
|
* @see #getBounds2D() |
653 |
|
*/ |
654 |
|
public Rectangle getBounds() |
655 |
|
{ |
656 |
|
double x1 = getX1(); |
657 |
|
double y1 = getY1(); |
658 |
|
double x2 = getX2(); |
659 |
|
double y2 = getY2(); |
660 |
|
double minx = Math.floor(Math.min(x1, x2)); |
661 |
|
double miny = Math.floor(Math.min(y1, y2)); |
662 |
|
double maxx = Math.ceil(Math.max(x1, x2)); |
663 |
|
double maxy = Math.ceil(Math.max(y1, y2)); |
664 |
|
return new Rectangle((int) minx, (int) miny, |
665 |
|
(int) (maxx - minx), (int) (maxy - miny)); |
666 |
|
} |
667 |
|
|
668 |
|
/** |
669 |
|
* Return a path iterator, possibly applying a transform on the result. This |
670 |
|
* iterator is not threadsafe. |
671 |
|
* |
672 |
|
* @param at the transform, or null |
673 |
|
* @return a new path iterator |
674 |
|
*/ |
675 |
|
public PathIterator getPathIterator(final AffineTransform at) |
676 |
{ |
{ |
677 |
double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); |
return new PathIterator() |
678 |
|
{ |
679 |
|
/** Current coordinate. */ |
680 |
|
private int current; |
681 |
|
|
682 |
double x, y; |
public int getWindingRule() |
|
if (pd2 == 0) |
|
683 |
{ |
{ |
684 |
// Points are coincident. |
return WIND_EVEN_ODD; |
|
x = x1; |
|
|
y = y2; |
|
685 |
} |
} |
|
else |
|
|
{ |
|
|
double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; |
|
686 |
|
|
687 |
if (u < 0) |
public boolean isDone() |
688 |
{ |
{ |
689 |
// "Off the end" |
return current < 2; |
|
x = x1; |
|
|
y = y1; |
|
|
} |
|
|
else if (u > 1.0) |
|
|
{ |
|
|
x = x2; |
|
|
y = y2; |
|
|
} |
|
|
else |
|
|
{ |
|
|
x = x1 + u * (x2 - x1); |
|
|
y = y1 + u * (y2 - y1); |
|
|
} |
|
690 |
} |
} |
691 |
|
|
692 |
return (x - px) * (x - px) + (y - py) * (y - py); |
public void next() |
693 |
} |
{ |
694 |
|
current++; |
695 |
public double ptSegDistSq (Point2D p) |
} |
|
{ |
|
|
return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (), |
|
|
p.getX (), p.getY ()); |
|
|
} |
|
|
|
|
|
public int relativeCCW (double px, double py) |
|
|
{ |
|
|
return relativeCCW (getX1 (), getY1 (), |
|
|
getX2 (), getY2 (), |
|
|
px, py); |
|
|
} |
|
|
|
|
|
public static int relativeCCW (double x1, double y1, |
|
|
double x2, double y2, |
|
|
double px, double py) |
|
|
{ |
|
|
// This is a somewhat silly way to compute this. |
|
|
// Please write a better one. |
|
|
double a1 = Math.atan2 (y2 - y1, x2 - x1); |
|
|
double a2 = Math.atan2 (py - y1, px - x1); |
|
696 |
|
|
697 |
double a = (a1 - a2) % (2 * Math.PI); |
public int currentSegment(float[] coords) |
|
if (a == 0 || a == Math.PI) |
|
698 |
{ |
{ |
699 |
double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)); |
int result; |
700 |
if (u < 0.0) |
switch (current) |
701 |
return 1; |
{ |
702 |
else if (u > 1.0) |
case 0: |
703 |
return -1; |
coords[0] = (float) getX1(); |
704 |
else |
coords[1] = (float) getY1(); |
705 |
return 0; |
result = SEG_MOVETO; |
706 |
|
break; |
707 |
|
case 1: |
708 |
|
coords[0] = (float) getX2(); |
709 |
|
coords[1] = (float) getY2(); |
710 |
|
result = SEG_LINETO; |
711 |
|
break; |
712 |
|
default: |
713 |
|
throw new NoSuchElementException("line iterator out of bounds"); |
714 |
|
} |
715 |
|
if (at != null) |
716 |
|
at.transform(coords, 0, coords, 0, 1); |
717 |
|
return result; |
718 |
} |
} |
719 |
|
|
720 |
return (a > 0 && a < Math.PI) ? 1 : -1; |
public int currentSegment(double[] coords) |
721 |
|
{ |
722 |
|
int result; |
723 |
|
switch (current) |
724 |
|
{ |
725 |
|
case 0: |
726 |
|
coords[0] = getX1(); |
727 |
|
coords[1] = getY1(); |
728 |
|
result = SEG_MOVETO; |
729 |
|
break; |
730 |
|
case 1: |
731 |
|
coords[0] = getX2(); |
732 |
|
coords[1] = getY2(); |
733 |
|
result = SEG_LINETO; |
734 |
|
break; |
735 |
|
default: |
736 |
|
throw new NoSuchElementException("line iterator out of bounds"); |
737 |
|
} |
738 |
|
if (at != null) |
739 |
|
at.transform(coords, 0, coords, 0, 1); |
740 |
|
return result; |
741 |
|
} |
742 |
|
}; |
743 |
} |
} |
744 |
|
|
745 |
public int relativeCCW (Point2D p) |
/** |
746 |
|
* Return a flat path iterator, possibly applying a transform on the result. |
747 |
|
* This iterator is not threadsafe. |
748 |
|
* |
749 |
|
* @param at the transform, or null |
750 |
|
* @param flatness ignored, since lines are already flat |
751 |
|
* @return a new path iterator |
752 |
|
* @see #getPathIterator(AffineTransform) |
753 |
|
*/ |
754 |
|
public PathIterator getPathIterator(AffineTransform at, double flatness) |
755 |
|
{ |
756 |
|
return getPathIterator(at); |
757 |
|
} |
758 |
|
|
759 |
|
/** |
760 |
|
* Create a new line of the same run-time type with the same contents as |
761 |
|
* this one. |
762 |
|
* |
763 |
|
* @return the clone |
764 |
|
*/ |
765 |
|
public Object clone() |
766 |
{ |
{ |
767 |
return relativeCCW (getX1 (), getY1 (), |
try |
768 |
getX2 (), getY2 (), |
{ |
769 |
p.getX (), p.getY ()); |
return super.clone(); |
770 |
|
} |
771 |
|
catch (CloneNotSupportedException e) |
772 |
|
{ |
773 |
|
throw (Error) new InternalError().initCause(e); // Impossible |
774 |
|
} |
775 |
} |
} |
776 |
|
|
777 |
public abstract void setLine (double x1, double y1, double x2, double y2); |
/** |
778 |
|
* This class defines a point in <code>double</code> precision. |
779 |
public void setLine (Line2D l) |
* |
780 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
781 |
|
* @since 1.2 |
782 |
|
* @status updated to 1.4 |
783 |
|
*/ |
784 |
|
public static class Double extends Line2D |
785 |
{ |
{ |
786 |
setLine (l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ()); |
/** The x coordinate of the first point. */ |
787 |
} |
public double x1; |
788 |
|
|
789 |
public void setLine (Point2D p1, Point2D p2) |
/** The y coordinate of the first point. */ |
790 |
{ |
public double y1; |
|
setLine (p1.getX (), p1.getY (), p2.getX (), p2.getY ()); |
|
|
} |
|
791 |
|
|
792 |
public static class Float extends Line2D |
/** The x coordinate of the second point. */ |
793 |
{ |
public double x2; |
|
float x1, y1, x2, y2; |
|
794 |
|
|
795 |
public Float () |
/** The y coordinate of the second point. */ |
796 |
|
public double y2; |
797 |
|
|
798 |
|
/** |
799 |
|
* Construct the line segment (0,0)->(0,0). |
800 |
|
*/ |
801 |
|
public Double() |
802 |
{ |
{ |
|
this (0.0F, 0.0F, 0.0F, 0.0F); |
|
803 |
} |
} |
804 |
|
|
805 |
public Float (float x1, float y1, float x2, float y2) |
/** |
806 |
|
* Construct the line segment with the specified points. |
807 |
|
* |
808 |
|
* @param x1 the x coordinate of the first point |
809 |
|
* @param y1 the y coordinate of the first point |
810 |
|
* @param x2 the x coordinate of the second point |
811 |
|
* @param y2 the y coordinate of the second point |
812 |
|
*/ |
813 |
|
public Double(double x1, double y1, double x2, double y2) |
814 |
{ |
{ |
815 |
this.x1 = x1; |
this.x1 = x1; |
816 |
this.y1 = y1; |
this.y1 = y1; |
818 |
this.y2 = y2; |
this.y2 = y2; |
819 |
} |
} |
820 |
|
|
821 |
public Float (Point2D p1, Point2D p2) |
/** |
822 |
{ |
* Construct the line segment with the specified points. |
823 |
this.x1 = (float) p1.getX (); |
* |
824 |
this.y1 = (float) p1.getY (); |
* @param p1 the first point |
825 |
this.x2 = (float) p2.getX (); |
* @param p2 the second point |
826 |
this.y2 = (float) p2.getY (); |
* @throws NullPointerException if either point is null |
827 |
} |
*/ |
828 |
|
public Double(Point2D p1, Point2D p2) |
829 |
public Rectangle2D getBounds2D () |
{ |
830 |
{ |
x1 = p1.getX(); |
831 |
float x = Math.min (x1, x2); |
y1 = p1.getY(); |
832 |
float w = Math.abs (x1 - x2); |
x2 = p2.getX(); |
833 |
float y = Math.min (y1, y2); |
y2 = p2.getY(); |
834 |
float h = Math.abs (y1 - y2); |
} |
835 |
return new Rectangle2D.Float (x, y, w, h); |
|
836 |
} |
/** |
837 |
|
* Return the x coordinate of the first point. |
838 |
public Point2D getP1 () |
* |
839 |
{ |
* @return the value of x1 |
840 |
return new Point2D.Float (x1, y1); |
*/ |
841 |
} |
public double getX1() |
|
|
|
|
public Point2D getP2 () |
|
|
{ |
|
|
return new Point2D.Float (x2, y2); |
|
|
} |
|
|
|
|
|
public double getX1 () |
|
842 |
{ |
{ |
843 |
return x1; |
return x1; |
844 |
} |
} |
845 |
|
|
846 |
public double getY1 () |
/** |
847 |
|
* Return the y coordinate of the first point. |
848 |
|
* |
849 |
|
* @return the value of y1 |
850 |
|
*/ |
851 |
|
public double getY1() |
852 |
{ |
{ |
853 |
return y1; |
return y1; |
854 |
} |
} |
855 |
|
|
856 |
public double getX2 () |
/** |
857 |
|
* Return the first point. |
858 |
|
* |
859 |
|
* @return the point (x1,y1) |
860 |
|
*/ |
861 |
|
public Point2D getP1() |
862 |
|
{ |
863 |
|
return new Point2D.Double(x1, y1); |
864 |
|
} |
865 |
|
|
866 |
|
/** |
867 |
|
* Return the x coordinate of the second point. |
868 |
|
* |
869 |
|
* @return the value of x2 |
870 |
|
*/ |
871 |
|
public double getX2() |
872 |
{ |
{ |
873 |
return x2; |
return x2; |
874 |
} |
} |
875 |
|
|
876 |
public double getY2 () |
/** |
877 |
|
* Return the y coordinate of the second point. |
878 |
|
* |
879 |
|
* @return the value of y2 |
880 |
|
*/ |
881 |
|
public double getY2() |
882 |
{ |
{ |
883 |
return y2; |
return y2; |
884 |
} |
} |
885 |
|
|
886 |
public void setLine (double x1, double y1, double x2, double y2) |
/** |
887 |
{ |
* Return the second point. |
888 |
this.x1 = (float) x1; |
* |
889 |
this.y1 = (float) y1; |
* @return the point (x2,y2) |
890 |
this.x2 = (float) x2; |
*/ |
891 |
this.y2 = (float) y2; |
public Point2D getP2() |
892 |
} |
{ |
893 |
|
return new Point2D.Double(x2, y2); |
894 |
public void setLine (float x1, float y1, float x2, float y2) |
} |
895 |
|
|
896 |
|
/** |
897 |
|
* Set this line to the given points. |
898 |
|
* |
899 |
|
* @param x1 the new x coordinate of the first point |
900 |
|
* @param y1 the new y coordinate of the first point |
901 |
|
* @param x2 the new x coordinate of the second point |
902 |
|
* @param y2 the new y coordinate of the second point |
903 |
|
*/ |
904 |
|
public void setLine(double x1, double y1, double x2, double y2) |
905 |
{ |
{ |
906 |
this.x1 = x1; |
this.x1 = x1; |
907 |
this.y1 = y1; |
this.y1 = y1; |
908 |
this.x2 = x2; |
this.x2 = x2; |
909 |
this.y2 = y2; |
this.y2 = y2; |
910 |
} |
} |
|
} |
|
911 |
|
|
912 |
public static class Double extends Line2D |
/** |
913 |
|
* Return the exact bounds of this line segment. |
914 |
|
* |
915 |
|
* @return the bounding box |
916 |
|
*/ |
917 |
|
public Rectangle2D getBounds2D() |
918 |
|
{ |
919 |
|
double x = Math.min(x1, x2); |
920 |
|
double y = Math.min(y1, y2); |
921 |
|
double w = Math.abs(x1 - x2); |
922 |
|
double h = Math.abs(y1 - y2); |
923 |
|
return new Rectangle2D.Double(x, y, w, h); |
924 |
|
} |
925 |
|
} // class Double |
926 |
|
|
927 |
|
/** |
928 |
|
* This class defines a point in <code>float</code> precision. |
929 |
|
* |
930 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
931 |
|
* @since 1.2 |
932 |
|
* @status updated to 1.4 |
933 |
|
*/ |
934 |
|
public static class Float extends Line2D |
935 |
{ |
{ |
936 |
double x1, y1, x2, y2; |
/** The x coordinate of the first point. */ |
937 |
|
public float x1; |
938 |
|
|
939 |
|
/** The y coordinate of the first point. */ |
940 |
|
public float y1; |
941 |
|
|
942 |
public Double () |
/** The x coordinate of the second point. */ |
943 |
|
public float x2; |
944 |
|
|
945 |
|
/** The y coordinate of the second point. */ |
946 |
|
public float y2; |
947 |
|
|
948 |
|
/** |
949 |
|
* Construct the line segment (0,0)->(0,0). |
950 |
|
*/ |
951 |
|
public Float() |
952 |
{ |
{ |
|
this (0.0, 0.0, 0.0, 0.0); |
|
953 |
} |
} |
954 |
|
|
955 |
public Double (double x1, double y1, double x2, double y2) |
/** |
956 |
|
* Construct the line segment with the specified points. |
957 |
|
* |
958 |
|
* @param x1 the x coordinate of the first point |
959 |
|
* @param y1 the y coordinate of the first point |
960 |
|
* @param x2 the x coordinate of the second point |
961 |
|
* @param y2 the y coordinate of the second point |
962 |
|
*/ |
963 |
|
public Float(float x1, float y1, float x2, float y2) |
964 |
{ |
{ |
965 |
this.x1 = x1; |
this.x1 = x1; |
966 |
this.y1 = y1; |
this.y1 = y1; |
968 |
this.y2 = y2; |
this.y2 = y2; |
969 |
} |
} |
970 |
|
|
971 |
public Double (Point2D p1, Point2D p2) |
/** |
972 |
{ |
* Construct the line segment with the specified points. |
973 |
this.x1 = (double) p1.getX (); |
* |
974 |
this.y1 = p1.getY (); |
* @param p1 the first point |
975 |
this.x2 = p2.getX (); |
* @param p2 the second point |
976 |
this.y2 = p2.getY (); |
* @throws NullPointerException if either point is null |
977 |
} |
*/ |
978 |
|
public Float(Point2D p1, Point2D p2) |
979 |
public Rectangle2D getBounds2D () |
{ |
980 |
{ |
x1 = (float) p1.getX(); |
981 |
double x = Math.min (x1, x2); |
y1 = (float) p1.getY(); |
982 |
double w = Math.abs (x1 - x2); |
x2 = (float) p2.getX(); |
983 |
double y = Math.min (y1, y2); |
y2 = (float) p2.getY(); |
984 |
double h = Math.abs (y1 - y2); |
} |
985 |
return new Rectangle2D.Double (x, y, w, h); |
|
986 |
} |
/** |
987 |
|
* Return the x coordinate of the first point. |
988 |
public Point2D getP1 () |
* |
989 |
{ |
* @return the value of x1 |
990 |
return new Point2D.Double (x1, y1); |
*/ |
991 |
} |
public double getX1() |
|
|
|
|
public Point2D getP2 () |
|
|
{ |
|
|
return new Point2D.Double (x2, y2); |
|
|
} |
|
|
|
|
|
public double getX1 () |
|
992 |
{ |
{ |
993 |
return x1; |
return x1; |
994 |
} |
} |
995 |
|
|
996 |
public double getY1 () |
/** |
997 |
|
* Return the y coordinate of the first point. |
998 |
|
* |
999 |
|
* @return the value of y1 |
1000 |
|
*/ |
1001 |
|
public double getY1() |
1002 |
{ |
{ |
1003 |
return y1; |
return y1; |
1004 |
} |
} |
1005 |
|
|
1006 |
public double getX2 () |
/** |
1007 |
|
* Return the first point. |
1008 |
|
* |
1009 |
|
* @return the point (x1,y1) |
1010 |
|
*/ |
1011 |
|
public Point2D getP1() |
1012 |
|
{ |
1013 |
|
return new Point2D.Float(x1, y1); |
1014 |
|
} |
1015 |
|
|
1016 |
|
/** |
1017 |
|
* Return the x coordinate of the second point. |
1018 |
|
* |
1019 |
|
* @return the value of x2 |
1020 |
|
*/ |
1021 |
|
public double getX2() |
1022 |
{ |
{ |
1023 |
return x2; |
return x2; |
1024 |
} |
} |
1025 |
|
|
1026 |
public double getY2 () |
/** |
1027 |
|
* Return the y coordinate of the second point. |
1028 |
|
* |
1029 |
|
* @return the value of y2 |
1030 |
|
*/ |
1031 |
|
public double getY2() |
1032 |
{ |
{ |
1033 |
return y2; |
return y2; |
1034 |
} |
} |
1035 |
|
|
1036 |
public void setLine (double x1, double y1, double x2, double y2) |
/** |
1037 |
|
* Return the second point. |
1038 |
|
* |
1039 |
|
* @return the point (x2,y2) |
1040 |
|
*/ |
1041 |
|
public Point2D getP2() |
1042 |
|
{ |
1043 |
|
return new Point2D.Float(x2, y2); |
1044 |
|
} |
1045 |
|
|
1046 |
|
/** |
1047 |
|
* Set this line to the given points. |
1048 |
|
* |
1049 |
|
* @param x1 the new x coordinate of the first point |
1050 |
|
* @param y1 the new y coordinate of the first point |
1051 |
|
* @param x2 the new x coordinate of the second point |
1052 |
|
* @param y2 the new y coordinate of the second point |
1053 |
|
*/ |
1054 |
|
public void setLine(double x1, double y1, double x2, double y2) |
1055 |
|
{ |
1056 |
|
this.x1 = (float) x1; |
1057 |
|
this.y1 = (float) y1; |
1058 |
|
this.x2 = (float) x2; |
1059 |
|
this.y2 = (float) y2; |
1060 |
|
} |
1061 |
|
|
1062 |
|
/** |
1063 |
|
* Set this line to the given points. |
1064 |
|
* |
1065 |
|
* @param x1 the new x coordinate of the first point |
1066 |
|
* @param y1 the new y coordinate of the first point |
1067 |
|
* @param x2 the new x coordinate of the second point |
1068 |
|
* @param y2 the new y coordinate of the second point |
1069 |
|
*/ |
1070 |
|
public void setLine(float x1, float y1, float x2, float y2) |
1071 |
{ |
{ |
1072 |
this.x1 = x1; |
this.x1 = x1; |
1073 |
this.y1 = y1; |
this.y1 = y1; |
1074 |
this.x2 = x2; |
this.x2 = x2; |
1075 |
this.y2 = y2; |
this.y2 = y2; |
1076 |
} |
} |
|
} |
|
|
|
|
|
// This implements the PathIterator for all line objects that don't |
|
|
// override getPathIterator. |
|
|
private class Iterator implements PathIterator |
|
|
{ |
|
|
// Current coordinate. |
|
|
private int coord; |
|
|
|
|
|
private static final int START = 0; |
|
|
private static final int END_PLUS_ONE = 2; |
|
|
|
|
|
public Iterator () |
|
|
{ |
|
|
coord = START; |
|
|
} |
|
|
|
|
|
public int currentSegment (double[] coords) |
|
|
{ |
|
|
int r = SEG_MOVETO; |
|
|
if (coord == 0) |
|
|
{ |
|
|
coords[0] = getX1 (); |
|
|
coords[1] = getY1 (); |
|
|
} |
|
|
else if (coord == 1) |
|
|
{ |
|
|
coords[0] = getX2 (); |
|
|
coords[1] = getY2 (); |
|
|
} |
|
|
else |
|
|
r = SEG_CLOSE; |
|
1077 |
|
|
1078 |
return r; |
/** |
1079 |
|
* Return the exact bounds of this line segment. |
1080 |
|
* |
1081 |
|
* @return the bounding box |
1082 |
|
*/ |
1083 |
|
public Rectangle2D getBounds2D() |
1084 |
|
{ |
1085 |
|
float x = Math.min(x1, x2); |
1086 |
|
float y = Math.min(y1, y2); |
1087 |
|
float w = Math.abs(x1 - x2); |
1088 |
|
float h = Math.abs(y1 - y2); |
1089 |
|
return new Rectangle2D.Float(x, y, w, h); |
1090 |
} |
} |
1091 |
|
} // class Float |
1092 |
public int currentSegment (float[] coords) |
} // class Line2D |
|
{ |
|
|
int r = SEG_MOVETO; |
|
|
if (coord == 0) |
|
|
{ |
|
|
coords[0] = (float) getX1 (); |
|
|
coords[1] = (float) getY1 (); |
|
|
} |
|
|
else if (coord == 1) |
|
|
{ |
|
|
coords[0] = (float) getX2 (); |
|
|
coords[1] = (float) getY2 (); |
|
|
} |
|
|
else |
|
|
r = SEG_CLOSE; |
|
|
|
|
|
return r; |
|
|
} |
|
|
|
|
|
public int getWindingRule () |
|
|
{ |
|
|
return WIND_NON_ZERO; |
|
|
} |
|
|
|
|
|
public boolean isDone () |
|
|
{ |
|
|
return coord == END_PLUS_ONE; |
|
|
} |
|
|
|
|
|
public void next () |
|
|
{ |
|
|
if (coord < END_PLUS_ONE) |
|
|
++coord; |
|
|
} |
|
|
} |
|
|
} |
|