001/* 002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. 003 * Copyright (C) 2006 - JScience (http://jscience.org/) 004 * All rights reserved. 005 * 006 * Permission to use, copy, modify, and distribute this software is 007 * freely granted, provided that this notice is preserved. 008 */ 009package org.jscience.geography.coordinates; 010 011import javax.measure.Measure; 012import javax.measure.converter.UnitConverter; 013import javax.measure.quantity.Angle; 014import static javax.measure.unit.NonSI.DEGREE_ANGLE; 015import static javax.measure.unit.SI.RADIAN; 016import javax.measure.unit.Unit; 017 018import javolution.context.ObjectFactory; 019import javolution.xml.XMLFormat; 020import javolution.xml.stream.XMLStreamException; 021 022import org.jscience.geography.coordinates.crs.GeographicCRS; 023import org.opengis.referencing.cs.CoordinateSystem; 024 025/** 026 * This class represents the {@link GeographicCRS geographic} latitude/longitude 027 * coordinates onto the WGS84 ellipsoid. 028 * 029 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 030 * @version 3.0, February 13, 2006 031 */ 032public final class LatLong extends Coordinates<GeographicCRS<?>> { 033 034 /** 035 * Holds the coordinate reference system for all instances of this class. 036 */ 037 public static final GeographicCRS<LatLong> CRS = new GeographicCRS<LatLong>() { 038 039 @Override 040 protected LatLong coordinatesOf(AbsolutePosition position) { 041 return LatLong.valueOf(position.latitudeWGS84.doubleValue(DEGREE_ANGLE), 042 position.longitudeWGS84.doubleValue(DEGREE_ANGLE), DEGREE_ANGLE); 043 } 044 045 @Override 046 protected AbsolutePosition positionOf(LatLong coordinates, 047 AbsolutePosition position) { 048 position.latitudeWGS84 = Measure.valueOf(coordinates._latitude, 049 DEGREE_ANGLE); 050 position.longitudeWGS84 = Measure.valueOf(coordinates._longitude, 051 DEGREE_ANGLE); 052 return position; 053 } 054 055 @Override 056 public CoordinateSystem getCoordinateSystem() { 057 return GeographicCRS.LATITUDE_LONGITUDE_CS; 058 } 059 060 }; 061 062 /** 063 * Holds converter from degree to radian. 064 */ 065 private static final UnitConverter DEGREE_TO_RADIAN = DEGREE_ANGLE 066 .getConverterTo(RADIAN); 067 068 /** 069 * Holds converter from radian to degree. 070 */ 071 private static final UnitConverter RADIAN_TO_DEGREE = DEGREE_TO_RADIAN 072 .inverse(); 073 074 /** 075 * Holds the latitude in degrees. 076 */ 077 private double _latitude; 078 079 /** 080 * Holds the longitude in degrees. 081 */ 082 private double _longitude; 083 084 /** 085 * Returns the surface position corresponding to the specified coordinates. 086 * 087 * @param latitude the latitude value stated in the specified unit. 088 * @param longitude the longitude value stated in the specified unit. 089 * @param unit the angle unit in which the coordinates are stated 090 * ({@link javax.measure.unit.NonSI#DEGREE_ANGLE Degree} typically). 091 * @return the corresponding surface position. 092 */ 093 public static LatLong valueOf(double latitude, double longitude, 094 Unit<Angle> unit) { 095 LatLong latLong = FACTORY.object(); 096 if (unit == DEGREE_ANGLE) { 097 latLong._latitude = latitude; 098 latLong._longitude = longitude; 099 } else if (unit == RADIAN) { 100 latLong._latitude = RADIAN_TO_DEGREE.convert(latitude); 101 latLong._longitude = RADIAN_TO_DEGREE.convert(longitude); 102 } else { // Other angle unit. 103 UnitConverter toDegree = unit.getConverterTo(DEGREE_ANGLE); 104 latLong._latitude = toDegree.convert(latitude); 105 latLong._longitude = toDegree.convert(longitude); 106 } 107 return latLong; 108 } 109 110 private static final ObjectFactory<LatLong> FACTORY = new ObjectFactory<LatLong>() { 111 112 @Override 113 protected LatLong create() { 114 return new LatLong(); 115 } 116 }; 117 118 private LatLong() { 119 } 120 121 /** 122 * Returns the latitude value as <code>double</code> 123 * 124 * @param unit the angle unit of the latitude to return. 125 * @return the latitude stated in the specified unit. 126 */ 127 public final double latitudeValue(Unit<Angle> unit) { 128 return (unit == DEGREE_ANGLE) ? _latitude 129 : (unit == RADIAN) ? DEGREE_TO_RADIAN.convert(_latitude) 130 : DEGREE_ANGLE.getConverterTo(unit).convert(_latitude); 131 } 132 133 /** 134 * Returns the longitude value as <code>double</code> 135 * 136 * @param unit the angle unit of the longitude to return. 137 * @return the longitude stated in the specified unit. 138 */ 139 public final double longitudeValue(Unit<Angle> unit) { 140 return (unit == DEGREE_ANGLE) ? _longitude 141 : (unit == RADIAN) ? DEGREE_TO_RADIAN.convert(_longitude) 142 : DEGREE_ANGLE.getConverterTo(unit).convert(_longitude); 143 } 144 145 @Override 146 public GeographicCRS<LatLong> getCoordinateReferenceSystem() { 147 return CRS; 148 } 149 150 // OpenGIS Interface. 151 public int getDimension() { 152 return 2; 153 } 154 155 // OpenGIS Interface. 156 public double getOrdinate(int dimension) throws IndexOutOfBoundsException { 157 if (dimension == 0) { 158 Unit<?> u = GeographicCRS.LATITUDE_LONGITUDE_CS.getAxis(0).getUnit(); 159 return DEGREE_ANGLE.getConverterTo(u).convert(_latitude); 160 } else if (dimension == 1) { 161 Unit<?> u = GeographicCRS.LATITUDE_LONGITUDE_CS.getAxis(1).getUnit(); 162 return DEGREE_ANGLE.getConverterTo(u).convert(_longitude); 163 } else { 164 throw new IndexOutOfBoundsException(); 165 } 166 } 167 168 // Implements Realtime. 169 public LatLong copy() { 170 return LatLong.valueOf(_latitude, _longitude, DEGREE_ANGLE); 171 } 172 173 // Default serialization. 174 // 175 176 static final XMLFormat<LatLong> XML = new XMLFormat<LatLong>(LatLong.class) { 177 178 @Override 179 public LatLong newInstance(Class<LatLong> cls, InputElement xml) 180 throws XMLStreamException { 181 return FACTORY.object(); 182 } 183 184 public void write(LatLong latLong, OutputElement xml) 185 throws XMLStreamException { 186 xml.setAttribute("latitude", latLong._latitude); 187 xml.setAttribute("longitude", latLong._longitude); 188 } 189 190 public void read(InputElement xml, LatLong latLong) 191 throws XMLStreamException { 192 latLong._latitude = xml.getAttribute("latitude", 0.0); 193 latLong._longitude = xml.getAttribute("longitude", 0.0); 194 } 195 }; 196 197 private static final long serialVersionUID = 1L; 198}