📄 arccalc.java
字号:
// **********************************************************************// // <copyright>// // BBN Technologies// 10 Moulton Street// Cambridge, MA 02138// (617) 873-8000// // Copyright (C) BBNT Solutions LLC. All rights reserved.// // </copyright>// **********************************************************************// // $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/omGraphics/util/ArcCalc.java,v $// $RCSfile: ArcCalc.java,v $// $Revision: 1.3.2.2 $// $Date: 2005/08/10 22:45:14 $// $Author: dietrick $// // **********************************************************************package com.bbn.openmap.omGraphics.util;import java.awt.Graphics;import java.awt.Point;import java.io.Serializable;import com.bbn.openmap.MoreMath;import com.bbn.openmap.omGraphics.OMColor;import com.bbn.openmap.omGraphics.OMGraphicList;import com.bbn.openmap.omGraphics.OMLine;import com.bbn.openmap.omGraphics.OMRect;import com.bbn.openmap.proj.Projection;import com.bbn.openmap.util.Debug;/** * A class that calculates an arc between two points, given the point * coordinates, and an arc measurement that represents, in radians, * the length of the part of the circle that should be represented by * the arc. */public class ArcCalc implements Serializable { /** Debugging list showing algorithm points. */ protected transient OMGraphicList arcGraphics = null; protected transient int[] xpoints; protected transient int[] ypoints; /** * This setting is the amount of an angle, limited to a * semi-circle (PI) that the curve will represent. In other words, * the arc between the two end points is going to look like a 0 * degrees of a circle (straight line, which is the default), or * 180 degrees of a circle (full semi-circle). Given in radians, * though, not degrees. OK? */ protected double arcAngle = 0; /** * For x-y and offset lines that have an arc drawn between them, * tell which way the arc should be drawn, toward the Equator, or * away from it, generally. Default is true, to make it look like * great circle line for northern hemishere lines. */ protected boolean arcUp = true; /** * Set to true if the points for the arc line up from x2, y2 to * x1, y1 */ protected boolean reversed = false; /** * Set the arc that is drawn between the points of a x-y or offset * line. If the arc amount is negative, the arc will be flipped * over. * * @param aa arcAngle, in radians, between 0-PI. * @param putArcUp arc peak above points. */ public ArcCalc(double aa, boolean putArcUp) { arcAngle = aa; arcUp = putArcUp; // If it's negative, flip it over... if (aa < 0) { arcAngle *= -1.0; arcUp = !arcUp; } if (arcAngle > Math.PI) { arcAngle = Math.PI; } } /** * Return the arc angle set for this line. Will only be set if it * was set externally. * * @return arc angle in radians. */ public double getArcAngle() { return arcAngle; } /** * Returns true if the arc direction setting is upward, meaning * that the peak of the arc is above (or more so) the line that * goes between the two points. */ public boolean isArcUp() { return arcUp; } /** * Generate the points that will generate the curved line between * two points. The arcAngle is the number of radians of a circle * that the arc should represent. Math.PI is the Max. The * setArcAngle should be called before this method is called, so * that the method knoes what to create. */ public void generate(int x1, int y1, int x2, int y2) { // The algorithm. // // Draw a straight line between the points, and figure out the // center point between them on the line. Then, on another // line that is perpendicular to the first line, figure out // where the point is that will act as a center of a circle. // That circle needs to pass through both points, and the // radius is such that the arc angle of the circle between the // points is the same as the arcAngle set for the ArcCalc. // Then, the arc needs to be generated. This is done by // looking at the circle, and figuring out the angle (from 0 // to 2PI) that the line from the center to point 1, and then // the center to point 2. This gives us the angular extents // of the arc. Then we need to figure out the angle // increments needed to get good coordinates for the arc. // Then, starting at the low arc angle, we increment it to get // the coordinates for the arced line, a given radius away // from the circle center, between the arc angle extents. Point midPoint = new Point(); Point arcCenter = new Point(); Point peakPoint = new Point(); // pixel distance between points. double distance = Math.sqrt(Math.pow(Math.abs(y2 - y1), 2.0) + Math.pow(Math.abs(x2 - x1), 2.0)); // slope of straight line between points. double straightLineSlope = Math.atan((double) (y2 - y1) / (double) (x2 - x1)); // slope of line that the arc focus will reside on. double inverseSlope = straightLineSlope - (Math.PI / 2.0); if (Debug.debugging("arc")) { Debug.output("ArcCalc.generate: Slope is " + (straightLineSlope * 180.0 / Math.PI) + " degrees, distance = " + distance + " pixels."); } // centerX/Y is the midpoint between the two points. midPoint.x = x1 + ((x2 - x1) / 2); midPoint.y = y1 + ((y2 - y1) / 2); if (Debug.debugging("arc")) { Debug.output("ArcCalc.generate: Center point for (" + x1 + ", " + y1 + ") to (" + x2 + ", " + y2 + ") is (" + midPoint.x + ", " + midPoint.y + ")"); } double arccos = Math.cos(arcAngle); double arcRadius; if (arccos != 1.0) { arcRadius = distance / Math.sqrt(2.0 * (1.0 - Math.cos(arcAngle))); } else { arcRadius = distance / Math.sqrt(2.0); } if (Debug.debugging("arc")) { Debug.output("ArcCalc.generate: radius of arc = " + arcRadius); } // R' is the distance down the inverse negative slope of the // line that the focus of the arc is located. // x is the distance along the right leg of the arc that is // left over after Rcos(arcAngle) is subtracted from it, in // order to derive the angle of the straight line between the // two points. double x = arcRadius - arcRadius * Math.cos(arcAngle); double rPrime = (distance / 2.0) * (Math.sqrt(1.0 - Math.pow(x / distance, 2.0))) / Math.sin(arcAngle / 2.0); if (Debug.debugging("arc")) { Debug.output("ArcCalc.generate: rPrime = " + rPrime); } int direction = 1; if (arcUp) direction = -1; // arcCenter.x and arcCenter.y are the coordinates of the // focus of the Arc. arcCenter.x = midPoint.x + (direction * (int) (rPrime * Math.cos(inverseSlope))); arcCenter.y = midPoint.y + (direction * (int) (rPrime * Math.sin(inverseSlope)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -