/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.awt.geom;
import java.awt.geom.Rectangle2D;
/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class PolyLine {
/**
* Does the polyline described by the given line points contain
* (x,y)
*
* @param linePoints
* @param x
* @param y
* @return True if the point is contained, false otherwise
*/
public static boolean contains(double[] linePoints, double x, double y) {
int wind = 0;
final int cnt = linePoints.length;
double lastX = linePoints[cnt - 2];
double lastY = linePoints[cnt - 1];
int oldquad = whichquad(lastX, lastY, x, y); /* get starting angle */
for (int i = 0; i < cnt; i += 2) { /* for each point in the polygon */
final double thisX = linePoints[i];
final double thisY = linePoints[i + 1];
final int newquad = whichquad(thisX, thisY, x, y);
if (oldquad != newquad) { /* adjust wind */
/*
* use mod 4 comparsions to see if we have
* advanced or backed up one quadrant
*/
if (((oldquad + 1) & 3) == newquad)
wind++;
else if (((newquad + 1) & 3) == oldquad) {
wind--;
} else {
/*
* upper left to lower right, or
* upper right to lower left. Determine
* direction of winding by intersection
* with x==0.
*/
double a = lastY - thisY;
a *= (x - lastX);
double b = lastX - thisX;
a += lastY * b;
b *= y;
if (a > b) {
wind += 2;
} else {
wind -= 2;
}
//System.out.println("x=" + x + "\ty=" + y + "\ta=" + a + "\tb=" + b + "\twind=" + wind);
}
}
lastX = thisX;
lastY = thisY;
oldquad = newquad;
}
return (wind != 0); /* non zero means point in poly */
}
/**
* Gets the bounding box of a PolyLine.
*
* @param linePoints
* @return The calculated bounding box
*/
public static Rectangle2D getBounds(double[] linePoints) {
double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE;
double maxY = Double.MIN_VALUE;
final int cnt = linePoints.length;
for (int i = 0; i < cnt; i += 2) {
final double x = linePoints[i];
final double y = linePoints[i + 1];
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
final double w = (maxX - minX) + 1;
final double h = (maxY - minY) + 1;
return new Rectangle2D.Double(minX, minY, w, h);
}
/**
* Figure out which quadrent pt is in with respect to orig
*
* @param x
* @param y
* @param origX
* @param origY
* @return The quadrant
*/
private static int whichquad(double x, double y, double origX, double origY) {
final int quad;
if (x < origX) {
if (y < origY) {
quad = 2;
} else {
quad = 1;
}
} else {
if (y < origY) {
quad = 3;
} else {
quad = 0;
}
}
return quad;
}
}