/*
 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
 * Copyright (C) 2006 - JScience (http://jscience.org/)
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */
package org.jscience.geography.coordinates;

import javax.measure.Measure;
import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Angle;
import static javax.measure.unit.NonSI.DEGREE_ANGLE;
import static javax.measure.unit.SI.RADIAN;
import javax.measure.unit.Unit;

import javolution.context.ObjectFactory;
import javolution.xml.XMLFormat;
import javolution.xml.stream.XMLStreamException;

import org.jscience.geography.coordinates.crs.GeographicCRS;
import org.opengis.referencing.cs.CoordinateSystem;

/**
 * This class represents the {@link GeographicCRS geographic} latitude/longitude
 * coordinates onto the WGS84 ellipsoid.
 * 
 * @author Jean-Marie Dautelle
 * @version 3.0, February 13, 2006
 */
public final class LatLong extends Coordinates> {

    /**
     * Holds the coordinate reference system for all instances of this class. 
     */
    public static final GeographicCRS CRS = new GeographicCRS() {

        @Override
        protected LatLong coordinatesOf(AbsolutePosition position) {
            return LatLong.valueOf(position.latitudeWGS84.doubleValue(DEGREE_ANGLE),
                    position.longitudeWGS84.doubleValue(DEGREE_ANGLE), DEGREE_ANGLE);
        }

        @Override
        protected AbsolutePosition positionOf(LatLong coordinates,
                AbsolutePosition position) {
            position.latitudeWGS84 = Measure.valueOf(coordinates._latitude,
                    DEGREE_ANGLE);
            position.longitudeWGS84 = Measure.valueOf(coordinates._longitude,
                    DEGREE_ANGLE);
            return position;
        }

        @Override
        public CoordinateSystem getCoordinateSystem() {
            return GeographicCRS.LATITUDE_LONGITUDE_CS;
        }

    };

    /**
     * Holds converter from degree to radian. 
     */
    private static final UnitConverter DEGREE_TO_RADIAN = DEGREE_ANGLE
            .getConverterTo(RADIAN);

    /**
     * Holds converter from radian to degree. 
     */
    private static final UnitConverter RADIAN_TO_DEGREE = DEGREE_TO_RADIAN
            .inverse();

    /**
     * Holds the latitude in degrees. 
     */
    private double _latitude;

    /**
     * Holds the longitude in degrees. 
     */
    private double _longitude;

    /**
     * Returns the surface position corresponding to the specified coordinates.
     * 
     * @param latitude the latitude value stated in the specified unit.
     * @param longitude the longitude value stated in the specified unit.
     * @param unit the angle unit in which the coordinates are stated
     *        ({@link javax.measure.unit.NonSI#DEGREE_ANGLE Degree} typically).
     * @return the corresponding surface position.
     */
    public static LatLong valueOf(double latitude, double longitude,
            Unit unit) {
        LatLong latLong = FACTORY.object();
        if (unit == DEGREE_ANGLE) {
            latLong._latitude = latitude;
            latLong._longitude = longitude;
        } else if (unit == RADIAN) {
            latLong._latitude = RADIAN_TO_DEGREE.convert(latitude);
            latLong._longitude = RADIAN_TO_DEGREE.convert(longitude);
        } else { // Other angle unit.
            UnitConverter toDegree = unit.getConverterTo(DEGREE_ANGLE);
            latLong._latitude = toDegree.convert(latitude);
            latLong._longitude = toDegree.convert(longitude);
        }
        return latLong;
    }

    private static final ObjectFactory FACTORY = new ObjectFactory() {

        @Override
        protected LatLong create() {
            return new LatLong();
        }
    };

    private LatLong() {
    }

    /**
     * Returns the latitude value as double
     * 
     * @param unit the angle unit of the latitude to return.
     * @return the latitude stated in the specified unit.
     */
    public final double latitudeValue(Unit unit) {
        return (unit == DEGREE_ANGLE) ? _latitude
                : (unit == RADIAN) ? DEGREE_TO_RADIAN.convert(_latitude)
                        : DEGREE_ANGLE.getConverterTo(unit).convert(_latitude);
    }

    /**
     * Returns the longitude value as double
     * 
     * @param unit the angle unit of the longitude to return.
     * @return the longitude stated in the specified unit.
     */
    public final double longitudeValue(Unit unit) {
        return (unit == DEGREE_ANGLE) ? _longitude
                : (unit == RADIAN) ? DEGREE_TO_RADIAN.convert(_longitude)
                        : DEGREE_ANGLE.getConverterTo(unit).convert(_longitude);
    }

    @Override
    public GeographicCRS getCoordinateReferenceSystem() {
        return CRS;
    }

    // OpenGIS Interface.
    public int getDimension() {
        return 2;
    }

    // OpenGIS Interface.
    public double getOrdinate(int dimension) throws IndexOutOfBoundsException {
        if (dimension == 0) {
            Unit u = GeographicCRS.LATITUDE_LONGITUDE_CS.getAxis(0).getUnit();
            return DEGREE_ANGLE.getConverterTo(u).convert(_latitude);
        } else if (dimension == 1) {
            Unit u = GeographicCRS.LATITUDE_LONGITUDE_CS.getAxis(1).getUnit();
            return DEGREE_ANGLE.getConverterTo(u).convert(_longitude);
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

    // Implements Realtime.
    public LatLong copy() {
        return LatLong.valueOf(_latitude, _longitude, DEGREE_ANGLE);
    }

    // Default serialization.
    //

    static final XMLFormat XML = new XMLFormat(LatLong.class) {

        @Override
        public LatLong newInstance(Class cls, InputElement xml)
                throws XMLStreamException {
            return FACTORY.object();
        }

        public void write(LatLong latLong, OutputElement xml)
                throws XMLStreamException {
            xml.setAttribute("latitude", latLong._latitude);
            xml.setAttribute("longitude", latLong._longitude);
        }

        public void read(InputElement xml, LatLong latLong)
                throws XMLStreamException {
            latLong._latitude = xml.getAttribute("latitude", 0.0);
            latLong._longitude = xml.getAttribute("longitude", 0.0);
        }
    };

    private static final long serialVersionUID = 1L;
}
 

Ads help maintain this website.