Java examples for java.lang:Math Geometry
Return the geometry of an ellipse based on its four top points.
public class Main{ /**/*from w w w.j a va 2 s . c o m*/ * Return the geometry of an ellipse based on its four top points. Integer * domain. The method use the generic createEllipse() method for the main * task, and then transforms this according to any rotation or skew defined * by the given top points. * * @param x X array of four top points of ellipse. * @param y Y array of four top points of ellipse. * @return Geometry of ellipse [x,y,x,y...]. */ public static int[] createEllipse(int[] x, int[] y) { // Center of ellipse int x0 = (x[0] + x[2]) / 2; int y0 = (y[0] + y[2]) / 2; // Angle between axis define skew double[] p0 = { (double) x0, (double) y0, 0.0 }; double[] p1 = { (double) x[0], (double) y[0], 0.0 }; double[] p2 = { (double) x[1], (double) y[1], 0.0 }; double axisAngle = GeometryUtils.computeAngle(p0, p1, p2); // dx / dy double dx = GeometryUtils.length(x0, y0, x[1], y[1]); double dy = GeometryUtils.length(x0, y0, x[0], y[0]) * Math.sin(axisAngle); // Create geometry for unrotated / unsheared ellipse int[] ellipse = createEllipse(x0, y0, (int) Math.round(dx), (int) Math.round(dy)); int nPoints = ellipse.length / 2; // Shear if neccessary. If angle is close to 90 there is no shear. // If angle is close to 0 or 180 shear is infinite, and we set // it to zero as well. if (!GeometryUtils.equals(axisAngle, Math.PI / 2.0, 0.1) && !GeometryUtils.equals(axisAngle, Math.PI, 0.1) && !GeometryUtils.equals(axisAngle, 0.0, 0.1)) { double xShear = 1.0 / Math.tan(axisAngle); for (int i = 0; i < nPoints; i++) { ellipse[i * 2 + 0] += Math.round((ellipse[i * 2 + 1] - y0) * xShear); } } // Rotate int ddx = x[1] - x0; int ddy = y0 - y[1]; double angle; if (ddx == 0 && ddy == 0) { angle = 0.0; } else if (ddx == 0) { angle = Math.PI / 2.0; } else { angle = Math.atan((double) ddy / (double) ddx); } double cosAngle = Math.cos(angle); double sinAngle = Math.sin(angle); for (int i = 0; i < nPoints; i++) { int xr = (int) Math.round(x0 + (ellipse[i * 2 + 0] - x0) * cosAngle - (ellipse[i * 2 + 1] - y0) * sinAngle); int yr = (int) Math.round(y0 - (ellipse[i * 2 + 1] - y0) * cosAngle - (ellipse[i * 2 + 0] - x0) * sinAngle); ellipse[i * 2 + 0] = xr; ellipse[i * 2 + 1] = yr; } return ellipse; } /** * Create the geometry for an unrotated, unskewed ellipse. Integer domain. * * @param x0 X center of ellipse. * @param y0 Y center of ellipse. * @param dx X ellipse radius. * @param dy Y ellipse radius. * @return Ellipse geometry [x,y,x,y,...]. */ public static int[] createEllipse(int x0, int y0, int dx, int dy) { // Make sure deltas are positive dx = Math.abs(dx); dy = Math.abs(dy); // This is an approximate number of points we need to make a smooth // surface on a quater of the ellipse int nPoints = dx > dy ? dx : dy; nPoints /= 2; if (nPoints < 1) { nPoints = 1; } // Allocate arrays for holding the complete set of vertices around // the ellipse. Note that this is a complete ellipse: First and last // point coincide. int[] ellipse = new int[nPoints * 8 + 2]; // Compute some intermediate results to save time in the inner loop int dxdy = dx * dy; int dx2 = dx * dx; int dy2 = dy * dy; // Handcode the entries in the four "corner" points of the ellipse, // i.e. at point 0, 90, 180, 270 and 360 degrees ellipse[nPoints * 0 + 0] = x0 + dx; ellipse[nPoints * 0 + 1] = y0; ellipse[nPoints * 8 + 0] = x0 + dx; ellipse[nPoints * 8 + 1] = y0; ellipse[nPoints * 2 + 0] = x0; ellipse[nPoints * 2 + 1] = y0 - dy; ellipse[nPoints * 4 + 0] = x0 - dx; ellipse[nPoints * 4 + 1] = y0; ellipse[nPoints * 6 + 0] = x0; ellipse[nPoints * 6 + 1] = y0 + dy; // Find the angle step double angleStep = nPoints > 0 ? Math.PI / 2.0 / nPoints : 0.0; // Loop over angles from 0 to 90. The rest of the ellipse can be derrived // from this first quadrant. For each angle set the four corresponding // ellipse points. double a = 0.0; for (int i = 1; i < nPoints; i++) { a += angleStep; double t = Math.tan(a); double x = (double) dxdy / Math.sqrt(t * t * dx2 + dy2); double y = x * t + 0.5; int xi = (int) (x + 0.5); int yi = (int) (y + 0.5); ellipse[(nPoints * 0 + i) * 2 + 0] = x0 + xi; ellipse[(nPoints * 2 - i) * 2 + 0] = x0 - xi; ellipse[(nPoints * 2 + i) * 2 + 0] = x0 - xi; ellipse[(nPoints * 4 - i) * 2 + 0] = x0 + xi; ellipse[(nPoints * 0 + i) * 2 + 1] = y0 - yi; ellipse[(nPoints * 2 - i) * 2 + 1] = y0 - yi; ellipse[(nPoints * 2 + i) * 2 + 1] = y0 + yi; ellipse[(nPoints * 4 - i) * 2 + 1] = y0 + yi; } return ellipse; } /** * Create the geometry for an unrotated, unskewed ellipse. Floating point * domain. * * @param x0 X center of ellipse. * @param y0 Y center of ellipse. * @param dx X ellipse radius. * @param dy Y ellipse radius. * @return Ellipse geometry [x,y,x,y,...]. */ public static double[] createEllipse(double x0, double y0, double dx, double dy) { // Make sure deltas are positive dx = Math.abs(dx); dy = Math.abs(dy); // As we don't know the resolution of the appliance of the ellipse // we create one vertex per 2nd degree. The nPoints variable holds // number of points in a quater of the ellipse. int nPoints = 45; // Allocate arrays for holding the complete set of vertices around // the ellipse. Note that this is a complete ellipse: First and last // point coincide. double[] ellipse = new double[nPoints * 8 + 2]; // Compute some intermediate results to save time in the inner loop double dxdy = dx * dy; double dx2 = dx * dx; double dy2 = dy * dy; // Handcode the entries in the four "corner" points of the ellipse, // i.e. at point 0, 90, 180, 270 and 360 degrees ellipse[nPoints * 0 + 0] = x0 + dx; ellipse[nPoints * 0 + 1] = y0; ellipse[nPoints * 8 + 0] = x0 + dx; ellipse[nPoints * 8 + 1] = y0; ellipse[nPoints * 2 + 0] = x0; ellipse[nPoints * 2 + 1] = y0 - dy; ellipse[nPoints * 4 + 0] = x0 - dx; ellipse[nPoints * 4 + 1] = y0; ellipse[nPoints * 6 + 0] = x0; ellipse[nPoints * 6 + 1] = y0 + dy; // Find the angle step double angleStep = nPoints > 0 ? Math.PI / 2.0 / nPoints : 0.0; // Loop over angles from 0 to 90. The rest of the ellipse can be derrived // from this first quadrant. For each angle set the four corresponding // ellipse points. double a = 0.0; for (int i = 1; i < nPoints; i++) { a += angleStep; double t = Math.tan(a); double x = (double) dxdy / Math.sqrt(t * t * dx2 + dy2); double y = x * t + 0.5; ellipse[(nPoints * 0 + i) * 2 + 0] = x0 + x; ellipse[(nPoints * 2 - i) * 2 + 0] = x0 - x; ellipse[(nPoints * 2 + i) * 2 + 0] = x0 - x; ellipse[(nPoints * 4 - i) * 2 + 0] = x0 + x; ellipse[(nPoints * 0 + i) * 2 + 1] = y0 - y; ellipse[(nPoints * 2 - i) * 2 + 1] = y0 - y; ellipse[(nPoints * 2 + i) * 2 + 1] = y0 + y; ellipse[(nPoints * 4 - i) * 2 + 1] = y0 + y; } return ellipse; } /** * Find the angle between three points. P0 is center point * * @param p0, p1, p2 Three points finding angle between [x,y,z]. * @return Angle (in radians) between given points. */ public static double computeAngle(double[] p0, double[] p1, double[] p2) { double[] v0 = GeometryUtils.createVector(p0, p1); double[] v1 = GeometryUtils.createVector(p0, p2); double dotProduct = GeometryUtils.computeDotProduct(v0, v1); double length1 = GeometryUtils.length(v0); double length2 = GeometryUtils.length(v1); double denominator = length1 * length2; double product = denominator != 0.0 ? dotProduct / denominator : 0.0; double angle = Math.acos(product); return angle; } /** * Return the length of a vector. * * @param v Vector to compute length of [x,y,z]. * @return Length of vector. */ public static double length(double[] v) { return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); } /** * Compute distance between two points. * * @param p0, p1 Points to compute distance between [x,y,z]. * @return Distance between points. */ public static double length(double[] p0, double[] p1) { double[] v = GeometryUtils.createVector(p0, p1); return length(v); } /** * Compute the length of the line from (x0,y0) to (x1,y1) * * @param x0, y0 First line end point. * @param x1, y1 Second line end point. * @return Length of line from (x0,y0) to (x1,y1). */ public static double length(int x0, int y0, int x1, int y1) { return GeometryUtils.length((double) x0, (double) y0, (double) x1, (double) y1); } /** * Compute the length of the line from (x0,y0) to (x1,y1) * * @param x0, y0 First line end point. * @param x1, y1 Second line end point. * @return Length of line from (x0,y0) to (x1,y1). */ public static double length(double x0, double y0, double x1, double y1) { double dx = x1 - x0; double dy = y1 - y0; return Math.sqrt(dx * dx + dy * dy); } /** * Compute the length of a polyline. * * @param x, y Arrays of x,y coordinates * @param nPoints Number of elements in the above. * @param isClosed True if this is a closed polygon, false otherwise * @return Length of polyline defined by x, y and nPoints. */ public static double length(int[] x, int[] y, boolean isClosed) { double length = 0.0; int nPoints = x.length; for (int i = 0; i < nPoints - 1; i++) { length += GeometryUtils.length(x[i], y[i], x[i + 1], y[i + 1]); } // Add last leg if this is a polygon if (isClosed && nPoints > 1) { length += GeometryUtils.length(x[nPoints - 1], y[nPoints - 1], x[0], y[0]); } return length; } /** * Check if two double precision numbers are "equal", i.e. close enough to a * given limit. * * @param a First number to check * @param b Second number to check * @param limit The definition of "equal". * @return True if the twho numbers are "equal", false otherwise */ private static boolean equals(double a, double b, double limit) { return Math.abs(a - b) < limit; } /** * Check if two double precision numbers are "equal", i.e. close enough to a * prespecified limit. * * @param a First number to check * @param b Second number to check * @return True if the twho numbers are "equal", false otherwise */ private static boolean equals(double a, double b) { return equals(a, b, 1.0e-5); } /** * Construct the vector specified by two points. * * @param p0, p1 Points the construct vector between [x,y,z]. * @return v Vector from p0 to p1 [x,y,z]. */ public static double[] createVector(double[] p0, double[] p1) { double v[] = { p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2] }; return v; } /** * Compute the dot product (a scalar) between two vectors. * * @param v0, v1 Vectors to compute dot product between [x,y,z]. * @return Dot product of given vectors. */ public static double computeDotProduct(double[] v0, double[] v1) { return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2]; } }