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 javolution.lang.Realtime;
012import javolution.lang.ValueType;
013import javolution.text.Text;
014import javolution.text.TextBuilder;
015import javolution.xml.XMLSerializable;
016
017import org.jscience.geography.coordinates.crs.CoordinateReferenceSystem;
018import org.opengis.referencing.cs.CoordinateSystem;
019import org.opengis.spatialschema.geometry.DirectPosition;
020
021/**
022 * This class designates the position that a point occupies in a given
023 * n-dimensional reference frame or system.
024 * This implementation is compatible with OpenGIS® DirectPosition. 
025 * 
026 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
027 * @version 4.0, April 9, 2007
028 * @see <a href="http://www.opengeospatial.org">Open Geospatial Consortium, Inc.</a>  
029 */
030public abstract class Coordinates<R extends CoordinateReferenceSystem<?>>
031    implements DirectPosition, Realtime, ValueType, XMLSerializable {
032
033    /**
034     * Default constructor.
035     */
036    protected Coordinates() {
037    }
038
039    /**
040     * Returns the reference system for this coordinates.
041     * 
042     * @return the associated coordinate reference system.
043     */
044    public abstract R getCoordinateReferenceSystem();
045
046    /////////////
047    // OpenGIS //
048    /////////////
049
050    /**
051     * OpenGIS&reg; - The length of coordinate sequence (the number of entries). 
052     * This is determined by the {@linkplain #getCoordinateReferenceSystem() 
053     * coordinate reference system}.
054     *
055     * @return the dimensionality of this position.
056     */
057    public abstract int getDimension();
058
059    /**
060     * OpenGIS&reg; - Returns the ordinate at the specified dimension.
061     *
062     * @param  dimension The dimension in the range 0 to 
063     *         {@linkplain #getDimension dimension}-1.
064     * @return The coordinate at the specified dimension.
065     * @throws IndexOutOfBoundsException if the specified dimension is out
066     *         of bounds.
067     */
068    public abstract double getOrdinate(int dimension)
069            throws IndexOutOfBoundsException;
070
071    /**
072     * OpenGIS&reg; - Throws <code>UnsupportedOperationException</code> as 
073     * <b>J</b>Science coordinates are immutable.
074     */
075    public final void setOrdinate(int dimension, double value)
076            throws IndexOutOfBoundsException {
077        throw new UnsupportedOperationException("Immutable coordinates");
078    }
079
080    /**
081     * OpenGIS&reg; - Returns the sequence of numbers that hold the coordinate 
082     * of this position in its reference system.
083     * 
084     * @return a copy of the coordinates. Changes in the returned array will 
085     *         not be reflected back in this {@code DirectPosition} object.
086     */
087    public final double[] getCoordinates() {
088        double[] coordinates = new double[getDimension()];
089        for (int i = 0; i < coordinates.length; i++) {
090            coordinates[i] = getOrdinate(i);
091        }
092        return coordinates;
093    }
094
095    /**
096     * OpenGIS&reg; - Returns the direct position for this position.
097     * 
098     * @return <code>this</code>
099     */
100    public final DirectPosition getPosition() {
101        return this;
102    }
103
104    /**
105     * OpenGIS&reg; - Makes an exact copy of this coordinate.
106     * 
107     * @return the copy.
108     */
109    public final Coordinates<R> clone() {
110        return this.clone();
111    }
112
113    /**
114     * Returns the string representation of this coordinates.
115     * 
116     * @return the coordinates values/units.
117     */
118    public Text toText() {
119        double[] coordinates = getCoordinates();
120        CoordinateSystem cs = this.getCoordinateReferenceSystem().getCoordinateSystem();
121        TextBuilder tb = TextBuilder.newInstance();
122        tb.append('[');
123        for (int i=0; i < coordinates.length; i++) {
124            if (i != 0) {
125                tb.append(", ");
126            }
127            tb.append(getOrdinate(i));
128            tb.append(' ');
129            tb.append(cs.getAxis(i).getUnit());
130        }
131        tb.append(']');
132        return tb.toText();
133    }
134
135    /**
136     * Returns the text representation of these coordinates as a 
137     * <code>java.lang.String</code>.
138     * 
139     * @return <code>toText().toString()</code>
140     */
141    public final String toString() {
142        return toText().toString();
143    }
144
145    /**
146     * Returns a copy of these coordinates 
147     * {@link javolution.context.AllocatorContext allocated} 
148     * by the calling thread (possibly on the stack).
149     *     
150     * @return an identical and independant copy of these coordinates .
151     */
152    public abstract Coordinates<?> copy();
153    
154}