📄 geometry.java
字号:
// 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; } /** * Create geometry for a circle. Integer domain. * * @param x0 X center of circle. * @param y0 Y center of circle. * @param radius Radius of circle. * @return Geometry of circle [x,y,...] */ public static int[] createCircle (int x0, int y0, int radius) { return createEllipse (x0, y0, radius, radius); } /** * Create geometry for a circle. Floating point domain. * * @param x0 X center of circle. * @param y0 Y center of circle. * @param radius Radius of circle. * @return Geometry of circle [x,y,...] */ public static double[] createCircle (double x0, double y0, double radius) { return createEllipse (x0, y0, radius, radius); } /** * Create the geometry of a sector of an ellipse. * * @param x0 X coordinate of center of ellipse. * @param y0 Y coordinate of center of ellipse. * @param dx X radius of ellipse. * @param dy Y radius of ellipse. * @param angle0 First angle of sector (in radians). * @param angle1 Second angle of sector (in radians). * @return Geometry of secor [x,y,...] */ public static int[] createSector (int x0, int y0, int dx, int dy, double angle0, double angle1) { // Determine a sensible number of points for arc double angleSpan = Math.abs (angle1 - angle0); double arcDistance = Math.max (dx, dy) * angleSpan; int nPoints = (int) Math.round (arcDistance / 15); double angleStep = angleSpan / (nPoints - 1); int[] xy = new int[nPoints*2 + 4]; int index = 0; for (int i = 0; i < nPoints; i++) { double angle = angle0 + angleStep * i; double x = dx * Math.cos (angle); double y = dy * Math.sin (angle); xy[index+0] = x0 + (int) Math.round (x); xy[index+1] = y0 - (int) Math.round (y); index += 2; } // Start and end geometry at center of ellipse to make it a closed polygon xy[nPoints*2 + 0] = x0; xy[nPoints*2 + 1] = y0; xy[nPoints*2 + 2] = xy[0]; xy[nPoints*2 + 3] = xy[1]; return xy; } /** * Create the geometry of a sector of a circle. * * @param x0 X coordinate of center of ellipse. * @param y0 Y coordinate of center of ellipse. * @param dx X radius of ellipse. * @param dy Y radius of ellipse. * @param angle0 First angle of sector (in radians). * @param angle1 Second angle of sector (in radians). * @return Geometry of secor [x,y,...] */ public static int[] createSector (int x0, int y0, int radius, double angle0, double angle1) { return createSector (x0, y0, radius, radius, angle0, angle1); } /** * Create the geometry of an arrow. The arrow is positioned at the * end (last point) of the specified polyline, as follows: * * 0,4--, * \ --, * \ --, * \ --, * \ --, * -------------------------3-----------1 * / --' * / --' * / --' * / --' * 2--' * * @param x X coordinates of polyline of where arrow is positioned * in the end. Must contain at least two points. * @param y Y coordinates of polyline of where arrow is positioned * in the end. * @param length Length along the main axis from point 1 to the * projection of point 0. * @param angle Angle between the main axis and the line 1,0 * (and 1,2) in radians. * @param inset Specification of point 3 [0.0-1.0], 1.0 will put * point 3 at distance length from 1, 0.0 will put it * at point 1. * @return Array of the five coordinates [x,y,...]. */ public static int[] createArrow (int[] x, int[] y, double length, double angle, double inset) { int[] arrow = new int[10]; int x0 = x[x.length - 1]; int y0 = y[y.length - 1]; arrow[2] = x0; arrow[3] = y0; // Find position of interior of the arrow along the polyline int[] pos1 = new int[2]; Geometry.findPolygonPosition (x, y, length, pos1); // Angles double dx = x0 - pos1[0]; double dy = y0 - pos1[1]; // Polyline angle double v = dx == 0.0 ? Math.PI / 2.0 : Math.atan (Math.abs (dy / dx)); v = dx > 0.0 && dy <= 0.0 ? Math.PI + v : dx > 0.0 && dy >= 0.0 ? Math.PI - v : dx <= 0.0 && dy < 0.0 ? -v : dx <= 0.0 && dy > 0.0 ? +v : 0.0; double v0 = v + angle; double v1 = v - angle; double edgeLength = length / Math.cos (angle); arrow[0] = x0 + (int) Math.round (edgeLength * Math.cos (v0)); arrow[1] = y0 - (int) Math.round (edgeLength * Math.sin (v0)); arrow[4] = x0 + (int) Math.round (edgeLength * Math.cos (v1)); arrow[5] = y0 - (int) Math.round (edgeLength * Math.sin (v1)); double c1 = inset * length; arrow[6] = x0 + (int) Math.round (c1 * Math.cos (v)); arrow[7] = y0 - (int) Math.round (c1 * Math.sin (v)); // Close polygon arrow[8] = arrow[0]; arrow[9] = arrow[1]; return arrow; } /** * Create geometry for an arrow along the specified line and with * tip at x1,y1. See general method above. * * @param x0 X first end point of line. * @param y0 Y first end point of line. * @param x1 X second end point of line. * @param y1 Y second end point of line. * @param length Length along the main axis from point 1 to the * projection of point 0. * @param angle Angle between the main axis and the line 1,0 * (and 1.2) * @param inset Specification of point 3 [0.0-1.0], 1.0 will put * point 3 at distance length from 1, 0.0 will put it * at point 1. * @return Array of the four coordinates [x,y,...]. */ public static int[] createArrow (int x0, int y0, int x1, int y1, double length, double angle, double inset) { int[] x = {x0, x1}; int[] y = {y0, y1}; return createArrow (x, y, length, angle, inset); } /** * Create geometry for a rectangle. Returns a closed polygon; first * and last points matches. Integer domain. * * @param x0 X corner of rectangle. * @param y0 Y corner of rectangle. * @param width Width (may be negative to indicate leftwards direction) * @param height Height (may be negative to indicaten upwards direction) */ public static int[] createRectangle (int x0, int y0, int width, int height) { return new int[] {x0, y0, x0 + (width - 1), y0, x0 + (width - 1), y0 + (height - 1), x0, y0 + (height - 1), x0, y0}; } /** * Create geometry for a rectangle. Returns a closed polygon; first * and last points matches. Floating point domain. * * @param x0 X corner of rectangle. * @param y0 Y corner of rectangle. * @param width Width (may be negative to indicate leftwards direction) * @param height Height (may be negative to indicaten upwards direction) */ public static double[] createRectangle (double x0, double y0, double width, double height) { return new double[] {x0, y0, x0 + width, y0, x0 + width, y0 + height, x0, y0 + height, x0, y0}; } /** * Create geometry of a star. Integer domain. * * @param x0 X center of star. * @param y0 Y center of star. * @param innerRadius Inner radis of arms. * @param outerRadius Outer radius of arms. * @param nArms Number of arms. * @return Geometry of star [x,y,x,y,...]. */ public static int[] createStar (int x0, int y0, int innerRadius, int outerRadius, int nArms) { int nPoints = nArms * 2 + 1; int[] xy = new int[nPoints * 2]; double angleStep = 2.0 * Math.PI / nArms / 2.0; for (int i = 0; i < nArms * 2; i++) { double angle = i * angleStep; double radius = (i % 2) == 0 ? innerRadius : outerRadius; double x = x0 + radius * Math.cos (angle); double y = y0 + radius * Math.sin (angle); xy[i*2 + 0] = (int) Math.round (x); xy[i*2 + 1] = (int) Math.round (y); } // Close polygon xy[nPoints*2 - 2] = xy[0]; xy[nPoints*2 - 1] = xy[1]; return xy; } /** * Create geometry of a star. Floating point domain. * * @param x0 X center of star. * @param y0 Y center of star. * @param innerRadius Inner radis of arms. * @param outerRadius Outer radius of arms. * @param nArms Number of arms. * @return Geometry of star [x,y,x,y,...]. */ public static double[] createStar (double x0, double y0, double innerRadius, double outerRadius, int nArms) { int nPoints = nArms * 2 + 1; double[] xy = new double[nPoints * 2]; double angleStep = 2.0 * Math.PI / nArms / 2.0; for (int i = 0; i < nArms * 2; i++) { double angle = i * angleStep; double radius = (i % 2) == 0 ? innerRadius : outerRadius; xy[i*2 + 0] = x0 + radius * Math.cos (angle); xy[i*2 + 1] = y0 + radius * Math.sin (angle); } // Close polygon xy[nPoints*2 - 2] = xy[0]; xy[nPoints*2 - 1] = xy[1]; return xy; } /** * Return the x,y position at distance "length" into the given polyline. * * @param x X coordinates of polyline * @param y Y coordinates of polyline * @param length Requested position * @param position Preallocated to int[2] * @return True if point is within polyline, false otherwise */ public static boolean findPolygonPosition (int[] x, int[] y, double length, int[] position) { if (length < 0) return false; double accumulatedLength = 0.0; for (int i = 1; i < x.length; i++) { double legLength = Geometry.length (x[i-1], y[i-1], x[i], y[i]); if (legLength + accumulatedLength >= length) { double part = length - accumulatedLength; double fraction = part / legLength; position[0] = (int) Math.round (x[i-1] + fraction * (x[i] - x[i-1])); position[1] = (int) Math.round (y[i-1] + fraction * (y[i] - y[i-1])); return true; } accumulatedLength += legLength; } // Length is longer than polyline return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -