48 |
* |
* |
49 |
* @author Tom Tromey <tromey@cygnus.com> |
* @author Tom Tromey <tromey@cygnus.com> |
50 |
* @author Eric Blake <ebb9@email.byu.edu> |
* @author Eric Blake <ebb9@email.byu.edu> |
51 |
|
* @author David Gilbert |
52 |
* @since 1.2 |
* @since 1.2 |
53 |
* @status updated to 1.4 |
* @status updated to 1.4 |
54 |
*/ |
*/ |
236 |
} |
} |
237 |
|
|
238 |
/** |
/** |
239 |
* Test if the line segment (x1,y1)->(x2,y2) intersects the line segment |
* 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). |
* (x3,y3)->(x4,y4). |
287 |
* |
* |
288 |
* @param x1 the first x coordinate of the first segment |
* @param x1 the first x coordinate of the first segment |
289 |
* @param y1 the first y coordinate of the first segment |
* @param y1 the first y coordinate of the first segment |
290 |
* @param x2 the second x coordinate of the first segment |
* @param x2 the second x coordinate of the first segment |
291 |
* @param y2 the second y coordinate of the first segment |
* @param y2 the second y coordinate of the first segment |
292 |
* @param x3 the first x coordinate of the second segment |
* @param x3 the first x coordinate of the second segment |
296 |
* @return true if the segments intersect |
* @return true if the segments intersect |
297 |
*/ |
*/ |
298 |
public static boolean linesIntersect(double x1, double y1, |
public static boolean linesIntersect(double x1, double y1, |
299 |
double x2, double y2, |
double x2, double y2, |
300 |
double x3, double y3, |
double x3, double y3, |
301 |
double x4, double y4) |
double x4, double y4) |
302 |
{ |
{ |
303 |
double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3)) |
double a1, a2, a3, a4; |
304 |
/ ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3))); |
|
305 |
if (beta < 0.0 || beta > 1.0) |
// deal with special cases |
306 |
return false; |
if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0) |
307 |
double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3); |
{ |
308 |
return alpha >= 0.0 && alpha <= 1.0; |
// 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 |
/** |
/** |