📄 distancemousemode.java
字号:
//Title: DistanceMouseMode.//Version: 2.0//Copyright://// THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR DSTO BE LIABLE FOR// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH// DAMAGE.////Author: R. Wathelet//Company: Theatre Operations Branch, Defence Science & Technology//Organisation (DSTO)package com.bbn.openmap.event;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.event.MouseEvent;import java.util.Properties;import java.util.Vector;import com.bbn.openmap.InformationDelegator;import com.bbn.openmap.LatLonPoint;import com.bbn.openmap.MapBean;import com.bbn.openmap.MoreMath;import com.bbn.openmap.omGraphics.OMCircle;import com.bbn.openmap.omGraphics.OMGraphic;import com.bbn.openmap.omGraphics.OMLine;import com.bbn.openmap.proj.GreatCircle;import com.bbn.openmap.proj.Length;import com.bbn.openmap.proj.Planet;import com.bbn.openmap.proj.ProjMath;import com.bbn.openmap.proj.Projection;import com.bbn.openmap.util.Debug;import com.bbn.openmap.util.PropUtils;/** * This mouse mode draws a rubberband line and circle between each * mouse click as the mouse is moved and displays the cumulative * distance in nautical miles (nm), kilometers (km), statute miles * (miles) and the azimuth angle in decimal degrees from north on the * status bar. Several distance segments are allowed. To erase * (terminate) double click the mouse. * <p> * To use this mouse mode in the OpenMap demo (in setWidgets): create * the mouse mode, such as * <p> * DistanceMouseMode distMode = new DistanceMouseMode(true, id, * DistanceMouseMode.DISTANCE_ALL); * <p> * Add the distance mouse mode to the mouse delegator * md.addMouseMode(distMode); * <p> * This class can easily be extended, for example to create waypoints * for objects. * <p> * NOTE: If some lines are not properly erased (because the mouse went * outside the map for example), just use the redraw from the menu. * <P> * * You can set the units used for measurements by setting the * property: * * <pre> * * prefix.units= &lt name for Length.java (km, miles, meters, nm) &gt * * </pre> */public class DistanceMouseMode extends CoordMouseMode { /** * Mouse mode identifier, is "Distance". This is returned on * getID() */ public final static transient String modeID = "Distance".intern(); public final static String UnitProperty = "units"; public final static String ShowCircleProperty = "showCircle"; public final static String ShowAngleProperty = "showAngle"; public final static String RepaintToCleanProperty = "repaintToClean"; /** * rPoint1 is the anchor point of a line segment */ public LatLonPoint rPoint1; /** * rPoint2 is the new (current) point of a line segment */ public LatLonPoint rPoint2; /** * Flag, true if the mouse has already been pressed */ public boolean mousePressed = false; /** * Vector to store all distance segments, first point and last * point pairs */ public Vector segments = new Vector(); /** * Distance of the current segment */ public double distance = 0; /** * The cumulative distance from the first mouse click */ public double totalDistance = 0; /** * The line type to be displayed, see OMGraphic. * LINETYPE_GREATCIRCLE, LINETYPE_RHUMB, LINETYPE_STRAIGHT default * LINETYPE_GREATCIRCLE */ public static int lineType = OMGraphic.LINETYPE_GREATCIRCLE; /** * To display the rubberband circle, default true */ private boolean displayCircle = true; // The unit type, default mile private Length unit = Length.MILE; // Flag to display the azimuth angle. Default true boolean showAngle = true; // Flag to repaint the map to clean up boolean repaintToClean = false; // The map bean MapBean theMap; /** * Construct a DistanceMouseMode. Default constructor. Sets the ID * to the modeID, and the consume mode to true. You need to * setInfoDelegator, setUnit and setLineType if you use this * constructor. */ public DistanceMouseMode() { this(true); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); } /** * Construct a DistanceMouseMode. Lets you set the consume mode. * If the events are consumed, then a MouseEvent is sent only to * the first MapMouseListener that successfully processes the * event. If they are not consumed, then all of the listeners get * a chance to act on the event. You need to setInfoDelegator, * setUnit and setLineType if you use this constructor. * * @param consumeEvents the mode setting. */ public DistanceMouseMode(boolean consumeEvents) { super(modeID, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); } /** * Construct an DistanceMouseMode. For convenience for derived * classes. * * @param name the ID of the mode. * @param consumeEvents if true, events are propagated to the * first MapMouseListener that successfully processes the * event, if false, events are propagated to all * MapMouseListeners. You need to setInfoDelegator, setUnit * and setLineType if you use this constructor. */ public DistanceMouseMode(String name, boolean consumeEvents) { super(name, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); } /** * Construct a DistanceMouseMode. Lets you set the consume mode. * If the events are consumed, then a MouseEvent is sent only to * the first MapMouseListener that successfully processes the * event. If they are not consumed, then all of the listeners get * a chance to act on the event. You need to the setLineType if * you use this constructor. * * @param consumeEvents the mode setting. * @param id the calling object's info delegator. * @param units the unit of distance that will be displayed, such * as Length.NM, Length.KM or Length.MILE. If null, display * all of them. */ public DistanceMouseMode(boolean consumeEvents, InformationDelegator id, Length units) { super(modeID, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); infoDelegator = id; unit = units; } /** * Construct a DistanceMouseMode. Lets you set the consume mode. * If the events are consumed, then a MouseEvent is sent only to * the first MapMouseListener that successfully processes the * event. If they are not consumed, then all of the listeners get * a chance to act on the event. You need to the setLineType if * you use this constructor. * * @param consumeEvents the mode setting. * @param id the calling object's info delegator. * @param units the unit of distance that will be displayed, such * as Length.NM, Length.KM or Length.MILE. If null, display * all of them. * @param lType the line type that will be dispalyed such as * LINETYPE_GREATCIRCLE, LINETYPE_RHUMB, LINETYPE_STRAIGHT */ public DistanceMouseMode(boolean consumeEvents, InformationDelegator id, Length units, int lType) { super(modeID, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); infoDelegator = id; unit = units; lineType = lType; } /** * Construct a DistanceMouseMode. Lets you set the consume mode. * If the events are consumed, then a MouseEvent is sent only to * the first MapMouseListener that successfully processes the * event. If they are not consumed, then all of the listeners get * a chance to act on the event. * * @param consumeEvents the mode setting. * @param id the calling object's info delegator. */ public DistanceMouseMode(boolean consumeEvents, InformationDelegator id) { super(modeID, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); infoDelegator = id; } /** * Construct a DistanceMouseMode. For convenience for derived * classes. Lets you set the consume mode. If the events are * consumed, then a MouseEvent is sent only to the first * MapMouseListener that successfully processes the event. If they * are not consumed, then all of the listeners get a chance to act * on the event. * * @param name the ID of the mode. * @param consumeEvents the mode setting. * @param id the calling object's info delegator. */ public DistanceMouseMode(String name, boolean consumeEvents, InformationDelegator id) { super(name, consumeEvents); // if you really want to change the cursor shape // setModeCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR)); infoDelegator = id; } /** * Process a mouseClicked event. Erase all drawn lines and circles * upon a double mouse click * * @param e mouse event. */ public void mouseClicked(MouseEvent e) { if (e.getSource() instanceof MapBean) { // if double (or more) mouse clicked if (e.getClickCount() >= 2) { // end of distance path mousePressed = false; // add the last point to the line segments segments.addElement(rPoint2); if (!repaintToClean) { // erase all line segments eraseLines(); // erase the last circle eraseCircle(); } else { ((MapBean) e.getSource()).repaint(); } // cleanup cleanUp(); } } } /** * Process a mouse pressed event. Add the mouse location to the * segment vector. Calculate the cumulative total distance. * * @param e mouse event. */ public void mousePressed(MouseEvent e) { e.getComponent().requestFocus(); if (e.getSource() instanceof MapBean) { // mouse has now been pressed mousePressed = true; // erase the old circle if any eraseCircle(); if (theMap == null) { theMap = (MapBean) e.getSource(); } // anchor the new first point of the line rPoint1 = theMap.getProjection().inverse(e.getPoint()); // ensure the second point is not yet set. rPoint2 = null; // add the anchor point to the list of line segments segments.addElement(rPoint1); // add the distance to the total distance totalDistance = totalDistance + distance; } } /** * Draw a rubberband line and circle as the mouse is moved. * Calculate distance and azimuth angle as the mouse moves. * Display distance and azimuth angle in on the infoDelegator. * * @param e mouse event. */ public void mouseMoved(MouseEvent e) { if (e.getSource() instanceof MapBean) { // only when the mouse has already been pressed if (mousePressed) { float lat1, lat2, long1, long2; // set the map bean theMap = (MapBean) (e.getSource()); // erase the old line and circle first paintRubberband(rPoint1, rPoint2); // get the current mouse location in latlon rPoint2 = theMap.getProjection().inverse(e.getPoint()); // paint the new line and circle up to the current // mouse location paintRubberband(rPoint1, rPoint2); if (infoDelegator != null) { Debug.message("mousemodedetail", "DistanceMouseMode: firing mouse location"); // lat, lon of anchor point lat1 = rPoint1.getLatitude(); long1 = rPoint1.getLongitude(); // lat, lon of current mouse position lat2 = rPoint2.getLatitude(); long2 = rPoint2.getLongitude(); // calculate great circle distance in nm // distance = getGreatCircleDist(lat1, long1, // lat2, long2, Length.NM); distance = (double) GreatCircle.spherical_distance(ProjMath.degToRad(lat1), ProjMath.degToRad(long1), ProjMath.degToRad(lat2), ProjMath.degToRad(long2)); // calculate azimuth angle dec deg float azimuth = getSphericalAzimuth(lat1, long1, lat2, long2); // convert total distance into all distance units // String distNM = // df.format(totalDistance+distance); double tmpDistance = totalDistance + distance; String infoLine = createDistanceInformationLine(rPoint2, tmpDistance, azimuth); // setup the info event InfoDisplayEvent info = new InfoDisplayEvent(this, infoLine, InformationDelegator.COORDINATE_INFO_LINE); // ask the infoDelegator to display the info infoDelegator.requestInfoLine(info); } } else { fireMouseLocation(e); } } } protected String createDistanceInformationLine(LatLonPoint llp, double distance, double azimuth) { // setup the distance info to be displayed String unitInfo = null; // what unit is asked for if (unit == null) { unitInfo = df.format(Length.NM.fromRadians((float) distance)) + Length.NM.getAbbr() + ", " + df.format(Length.KM.fromRadians((float) distance)) + Length.KM.getAbbr() + ", " + df.format(Length.MILE.fromRadians((float) distance)) + Length.MILE.getAbbr() + " "; } else { unitInfo = unit.fromRadians((float) distance) + " " + unit.getAbbr(); } // add the mouse lat, lon String infoLine = "Lat, Lon (" + df.format(llp.getLatitude()) + ", " + df.format(llp.getLongitude()) + "), distance (";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -