* @return the closest corner of rect measured from point
*/
public static Point2D closestCornerBox(Rectangle2D rect, Line2D line, Point2D point) {
Point2D closest, candidate, furthest;
double closestDist, candidateDist, furthestDist;
Line2D closestLine, furthestLine;
Point2D topLeft = new Point2D.Double(rect.getX(), rect.getY());
Point2D topRight = new Point2D.Double(rect.getX()+rect.getWidth(), rect.getY());
Point2D bottomLeft = new Point2D.Double(rect.getX(), rect.getY()+rect.getHeight());
Point2D bottomRight = new Point2D.Double(rect.getX()+rect.getWidth(),rect.getY()+rect.getHeight() );
//System.out.println("closestCornerBox: " + rect + " line1: " + line.getP1() + " line2: " + line.getP2()+ " point: " + point);
// find the closest and furthest points of intersection
// top of rectangle
Line2D top = new Line2D.Double(topLeft, topRight);
furthest = closest = GraphicsGems.intersectSegments(line, top);
furthestDist = closestDist = point.distance(closest);
closestLine = furthestLine = top;
if (Double.isInfinite(furthestDist)) {
furthestDist = -1;
}
//System.out.println("1Closest :" + closest + " furthest: " + furthest);
// left of rectangle
Line2D left = new Line2D.Double(topLeft, bottomLeft);
candidate = GraphicsGems.intersectSegments(line, left);
candidateDist = point.distance(candidate);
if (!Double.isInfinite(candidateDist)) {
if (candidateDist < closestDist) {
closestDist = candidateDist;
closest = candidate;
closestLine = left;
}
if (candidateDist > furthestDist) {
furthestDist = candidateDist;
furthest = candidate;
furthestLine = left;
}
//System.out.println("2Closest :" + closest + " furthest: " + furthest);
}
// right of rectangle
Line2D right = new Line2D.Double(topRight, bottomRight);
candidate = GraphicsGems.intersectSegments(line, right);
candidateDist = point.distance(candidate);
if (!Double.isInfinite(candidateDist)) {
if (candidateDist < closestDist) {
closestDist = candidateDist;
closest = candidate;
closestLine = right;
}
if (candidateDist > furthestDist) {
furthestDist = candidateDist;
furthest = candidate;
furthestLine = right;
}
//System.out.println("3Closest :" + closest + " furthest: " + furthest);
}
// bottom of rectangle
Line2D bottom = new Line2D.Double(bottomLeft, bottomRight);
candidate = GraphicsGems.intersectSegments(line, bottom);
candidateDist = point.distance(candidate);
if (!Double.isInfinite(candidateDist)) {
if (candidateDist < closestDist) {
closestDist = candidateDist;
closest = candidate;
closestLine = bottom;
}
if (candidateDist > furthestDist) {
furthestDist = candidateDist;
furthest = candidate;
furthestLine = bottom;
}
//System.out.println("4Closest :" + closest + " furthest: " + furthest);
}
// now we have the closest and furthest distances, check to see if the things that were
// intersected are on opposite sides, or adjacent
// if closest == furthest, it is the corner point
if (closest == furthest)
return null;
assert(!Double.isInfinite(closestDist) && !Double.isInfinite(furthestDist));
// if lines are adjacent
Point2D adjacentPoint = areLinesAdjacent(closestLine, furthestLine);
//System.out.println("Are lines adjacent: closestLine " + closestLine.getP1() + "," + closestLine.getP2() + " furthest: " + furthestLine.getP1() + "," + furthestLine.getP2());
//System.out.println("adjacent? " + (adjacentPoint != null));
// that adjacent point is the corner point!
//System.out.println("ClosestPoint: " + closest + " point: " + point);
if (adjacentPoint != null) {
//System.out.println("GraphicsGems. closestCorner is a triangle.");
return adjacentPoint;
// we also want to return the corner point if the given point is on the rectangle itself
// this is a degenerate case
} else if (closest.equals(point)){
//System.out.println("GraphicsGems. closestCorner handling triangle degeneracy.");
// find those adjacent lines
boolean foundOne = false;
Line2D candidate1 = null;
Line2D candidate2 = null;
if (isPointOnLine(top, point )) {
foundOne = true;
candidate1 = top;
}
if (isPointOnLine(bottom, point)) {
if (foundOne) {
candidate2 = bottom;
}
else {
candidate1 = bottom;
foundOne = true;
}
}
if (isPointOnLine(right, point)) {
if (foundOne) {
candidate2 = right;
}
else {
candidate1 = right;
foundOne = true;
}
}
if (isPointOnLine(left, point)) {
if (foundOne) {
candidate2 = left;
}
else {
candidate1 = left;
foundOne = true;
}
}
assert((candidate1 != null) && (candidate2 != null));
// now find the adjacent lines
Point2D onePt = areLinesAdjacent(candidate1, furthestLine);
Point2D twoPt = areLinesAdjacent(candidate2, furthestLine);
if (onePt == null) {
assert(twoPt != null);
return twoPt;
} else {
assert(onePt != null);
return onePt;
}
// if lines are opposite one another, find corner by doing area calculation
} else {
//System.out.println("GraphicsGems. closestCorner is a trapezoid.");
// 1. compute area of rectangle
double boxArea = rect.getWidth() * rect.getHeight();
Line2D heightLine;//, otherLine;
// 2. pick a line that is not closest or further line, call it the heightLine,
// (for the height of the trapezoid), call the remaining line the otherLine
// note we know that the lines have to be opposite each other, so this make it easier
if ((top != closestLine) && (top != furthestLine) && (bottom != closestLine) && (bottom != furthestLine)) {
heightLine = top;
// otherLine = bottom;
} else {
heightLine = left;
// otherLine = right;
}
// 3. get adjacent point of closestLine and heightLine, to compute b1
Point2D b1Point = areLinesAdjacent(closestLine, heightLine);
assert (b1Point != null);
double b1 = b1Point.distance(closest);
// 4. get adjacent point of furthestLine and heightLine, to compute b2
Point2D b2Point = areLinesAdjacent(furthestLine, heightLine);
assert(b2Point != null);
double b2 = b2Point.distance(furthest);
// 5. compute height by getting length of heightLine
double h = heightLine.getP1().distance(heightLine.getP2());
// 6. compute area of trapezoid
//System.out.println("b1: " + b1 + " b2: " + b2 + " h: " + h);
double trapezoidArea = .5*(b1+b2)*h;
//System.out.println( "boxArea :" + boxArea + " trapezoid Area: " + trapezoidArea);