📄 position.java
字号:
/* * $Header: /home/wistrand/cvs/knopflerfish.org/osgi/bundles/position/src/org/osgi/util/position/Position.java,v 1.1.1.1 2004/03/05 20:35:14 wistrand Exp $ * * Copyright (c) The Open Services Gateway Initiative (2002). * All Rights Reserved. * * Implementation of certain elements of the Open Services Gateway Initiative * (OSGI) Specification may be subject to third party intellectual property * rights, including without limitation, patent rights (such a third party may * or may not be a member of OSGi). OSGi is not responsible and shall not be * held responsible in any manner for identifying or failing to identify any or * all such third party intellectual property rights. * * This document and the information contained herein are provided on an "AS * IS" basis and OSGI DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL * NOT INFRINGE ANY RIGHTS AND ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL OSGI BE LIABLE FOR ANY * LOSS OF PROFITS, LOSS OF BUSINESS, LOSS OF USE OF DATA, INTERRUPTION OF * BUSINESS, OR FOR DIRECT, INDIRECT, SPECIAL OR EXEMPLARY, INCIDENTIAL, * PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH THIS * DOCUMENT OR THE INFORMATION CONTAINED HEREIN, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH LOSS OR DAMAGE. * * All Company, brand and product names may be trademarks that are the sole * property of their respective owners. All rights reserved. */package org.osgi.util.position;import org.osgi.util.measurement.*;/** * Position represents a geographic location, based on the WGS84 System * (World Geodetic System 1984).<p> * The <tt>org.osgi.util.measurement.Measurement</tt> class is used * to represent the values that make up a position.<p> * <p>A given position object may lack any of it's components, i.e. the altitude may not be known. * Such missing values will be represented by null. * <p>Position does not override the implementation of either equals() or hashCode() because it * is not clear how missing values should be handled. It is up to the user of a position to determine * how best to compare two position objects. * A <tt>Position</tt> object is immutable. */public class Position{ private Measurement altitude; private Measurement longitude; private Measurement latitude; private Measurement speed; private Measurement track; /** * Contructs a <tt>Position</tt> object with the given values. * @param lat a <tt>Measurement</tt> object specifying the latitude in radians, or null * @param lon a <tt>Measurement</tt> object specifying the longitude in radians, or null * @param alt a <tt>Measurement</tt> object specifying the altitude in meters, or null * @param speed a <tt>Measurement</tt> object specifying the speed in meters per second, or null * @param track a <tt>Measurement</tt> object specifying the track in radians, or null */ public Position(Measurement lat, Measurement lon, Measurement alt, Measurement speed, Measurement track) { if (lat != null) { if (!Unit.rad.equals(lat.getUnit())) { throw new IllegalArgumentException("Invalid Latitude"); } this.latitude =lat; } if (lon != null) { if (!Unit.rad.equals(lon.getUnit())) { throw new IllegalArgumentException("Invalid Longitude"); } this.longitude = lon; } normalizeLatLon(); if (alt != null) { if (!Unit.m.equals(alt.getUnit())) { throw new IllegalArgumentException("Invalid Altitude"); } this.altitude = alt; } if (speed != null) { if (!Unit.m_s.equals(speed.getUnit())) { throw new IllegalArgumentException("Invalid Speed"); } this.speed = speed; } if (track != null) { if (!Unit.rad.equals(track.getUnit())) { throw new IllegalArgumentException("Invalid Track"); } this.track = normalizeTrack(track); } } /** * Returns the altitude of this position in meters. * @return a <tt>Measurement</tt> object in <tt>Unit.m</tt> representing the altitude in meters above the ellipsoid <tt>null</tt> * if the altitude is not known. */ public Measurement getAltitude() { return altitude; } /** * Returns the longitude of this position in radians. * @return a <tt>Measurement</tt> object in <tt>Unit.rad</tt> representing the longitude, or <tt>null</tt> * if the longitude is not known. */ public Measurement getLongitude() { return longitude; } /** * Returns the latitude of this position in radians. * @return a <tt>Measurement</tt> object in <tt>Unit.rad</tt> representing the latitude, or <tt>null</tt> * if the latitude is not known.. */ public Measurement getLatitude() { return latitude; } /** * Returns the ground speed of this position in meters per second. * @return a <tt>Measurement</tt> object in <tt>Unit.m_s</tt> representing the speed, or <tt>null</tt> * if the speed is not known.. */ public Measurement getSpeed() { return speed; } /** * Returns the track of this position in radians as a compass heading. * The track is the extrapolation of previous previously measured positions * to a future position. * @return a <tt>Measurement</tt> object in <tt>Unit.rad</tt> representing the track, or <tt>null</tt> * if the track is not known.. */ public Measurement getTrack() { return track; } private static final double LON_RANGE = Math.PI; private static final double LAT_RANGE = Math.PI / 2.0D; /** * Verify the longitude and latitude parameters * so they fit the normal coordinate system. * A latitude is between -90 (south) and +90 (north). A * A longitude is between -180 (Western hemisphere) and +180 * (eastern hemisphere). * This method first normalizes the latitude and longitude * between +/- 180. If the |latitude| > 90, then the * longitude is added 180 and the latitude is normalized to * fit +/-90. * (Example are with degrees though radians are used)<br> * No normalization takes place when either lon or lat is null. */ private void normalizeLatLon() { if (longitude == null || latitude == null) return; double dlon = longitude.getValue(); double dlat = latitude.getValue(); if (dlon >= -LON_RANGE && dlon < LON_RANGE && dlat >= -LAT_RANGE && dlat <= LAT_RANGE) return; dlon = normalize( dlon, LON_RANGE ); dlat = normalize( dlat, LAT_RANGE * 2.0D ); // First over 180 degree // Check if we have to move to other side of the earth if (dlat > LAT_RANGE || dlat <-LAT_RANGE) { dlon = normalize( dlon - LON_RANGE, LON_RANGE ); dlat = normalize( (LAT_RANGE * 2.0D) - dlat, LAT_RANGE ); } longitude = new Measurement( dlon, longitude.getError(), longitude.getUnit(), longitude.getTime() ); latitude = new Measurement( dlat, latitude.getError(), latitude.getUnit(), latitude.getTime() ); } /** * This function normalizes the a value according to a range. * This is not simple modulo (as I thought when I started), but * requires some special handling. For positive numbers we subtract * 2*range from the number so that end up between -/+ range. For * negative numbers we add this value. For example, if the value * is 270 and the range is +/- 180. Then sign=1 so the (int) factor * becomes 270+180/360 = 1. This means that 270-360=-90 is the result. * (degrees are only used to make it easier to understand, this function * is agnostic for radians/degrees). The result will be in [range,range> * The algorithm is not very fast, but it handling the [> ranges * made it very messy using integer arithmetic, and this is very readable. Note * that it is highly unlikely that this method is called in normal * situations. Normally input values to position are already normalized * because they come from a GPS. And this is much more readable. * * @param value The value that needs adjusting * @param range -range =< value < range */ private double normalize( double value, double range ) { double twiceRange = 2.0D * range; while (value >= range) { value -= twiceRange; } while (value < -range) { value += twiceRange; } return value; } private static final double TRACK_RANGE = Math.PI * 2.0D; /** * Normalize track to be a value such that: 0 <= value < +2PI. * This corresponds to 0 deg to +360 deg. * 0 is North * 0.5*PI is East * PI is South * 1.5*PI is West * * @param track Value to be normalized * @return Normalized value */ private Measurement normalizeTrack(Measurement track) { double value = track.getValue(); if ((0.0D <= value) && (value < TRACK_RANGE)) { return track; /* value is already normalized */ } value %= TRACK_RANGE; if (value < 0.0D) { value += TRACK_RANGE; } return new Measurement(value, track.getError(), track.getUnit(), track.getTime()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -