/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * This package contains documentation from OpenGIS specifications. * OpenGIS consortium's work is fully acknowledged here. */ package org.geotools.referencing.cs; import java.util.Map; import javax.measure.unit.Unit; import javax.measure.converter.UnitConverter; import org.opengis.referencing.cs.AxisDirection; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.geometry.MismatchedDimensionException; import org.geotools.measure.Measure; import org.geotools.resources.i18n.Errors; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.VocabularyKeys; /** * A 1-, 2-, or 3-dimensional coordinate system. Gives the position of points relative to * orthogonal straight axes in the 2- and 3-dimensional cases. In the 1-dimensional case, * it contains a single straight coordinate axis. In the multi-dimensional case, all axes * shall have the same length unit of measure. A {@code CartesianCS} shall have one, * two, or three {@linkplain #getAxis axis}. * * * *
Used with CRS type(s)
* {@link org.geotools.referencing.crs.DefaultGeocentricCRS Geocentric}, * {@link org.geotools.referencing.crs.DefaultProjectedCRS Projected}, * {@link org.geotools.referencing.crs.DefaultEngineeringCRS Engineering}, * {@link org.geotools.referencing.crs.DefaultImageCRS Image} *
* * @since 2.1 * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) * * @see DefaultAffineCS */ public class DefaultCartesianCS extends DefaultAffineCS implements CartesianCS { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = -6182037957705712945L; /** * A two-dimensional cartesian CS with * {@linkplain DefaultCoordinateSystemAxis#EASTING Easting}, * {@linkplain DefaultCoordinateSystemAxis#NORTHING Northing} * axis in metres. */ public static DefaultCartesianCS PROJECTED = new DefaultCartesianCS( name(VocabularyKeys.PROJECTED), DefaultCoordinateSystemAxis.EASTING, DefaultCoordinateSystemAxis.NORTHING); /** * A three-dimensional cartesian CS with geocentric * {@linkplain DefaultCoordinateSystemAxis#GEOCENTRIC_X x}, * {@linkplain DefaultCoordinateSystemAxis#GEOCENTRIC_Y y}, * {@linkplain DefaultCoordinateSystemAxis#GEOCENTRIC_Z z} * axis in metres. * * @see DefaultSphericalCS#GEOCENTRIC */ public static DefaultCartesianCS GEOCENTRIC = new DefaultCartesianCS( name(VocabularyKeys.GEOCENTRIC), DefaultCoordinateSystemAxis.GEOCENTRIC_X, DefaultCoordinateSystemAxis.GEOCENTRIC_Y, DefaultCoordinateSystemAxis.GEOCENTRIC_Z); /** * A two-dimensional cartesian CS with * {@linkplain DefaultCoordinateSystemAxis#X x}, * {@linkplain DefaultCoordinateSystemAxis#Y y} * axis in metres. */ public static DefaultCartesianCS GENERIC_2D = new DefaultCartesianCS( name(VocabularyKeys.CARTESIAN_2D), DefaultCoordinateSystemAxis.X, DefaultCoordinateSystemAxis.Y); /** * A three-dimensional cartesian CS with * {@linkplain DefaultCoordinateSystemAxis#X x}, * {@linkplain DefaultCoordinateSystemAxis#Y y}, * {@linkplain DefaultCoordinateSystemAxis#Z z} * axis in metres. */ public static DefaultCartesianCS GENERIC_3D = new DefaultCartesianCS( name(VocabularyKeys.CARTESIAN_3D), DefaultCoordinateSystemAxis.X, DefaultCoordinateSystemAxis.Y, DefaultCoordinateSystemAxis.Z); /** * A two-dimensional cartesian CS with * {@linkplain DefaultCoordinateSystemAxis#COLUMN column}, * {@linkplain DefaultCoordinateSystemAxis#ROW row} * axis. */ public static DefaultCartesianCS GRID = new DefaultCartesianCS( name(VocabularyKeys.GRID), DefaultCoordinateSystemAxis.COLUMN, DefaultCoordinateSystemAxis.ROW); /** * A two-dimensional cartesian CS with * {@linkplain DefaultCoordinateSystemAxis#DISPLAY_X display x}, * {@linkplain DefaultCoordinateSystemAxis#DISPLAY_Y display y} * axis. * * @since 2.2 */ public static DefaultCartesianCS DISPLAY = new DefaultCartesianCS( name(VocabularyKeys.DISPLAY), DefaultCoordinateSystemAxis.DISPLAY_X, DefaultCoordinateSystemAxis.DISPLAY_Y); /** * Converters from {@linkplain CoordinateSystemAxis#getUnit axis units} to * {@linkplain #getDistanceUnit distance unit}. Will be constructed only when * first needed. */ private transient UnitConverter[] converters; /** * Constructs a new coordinate system with the same values than the specified one. * This copy constructor provides a way to wrap an arbitrary implementation into a * Geotools one or a user-defined one (as a subclass), usually in order to leverage * some implementation-specific API. This constructor performs a shallow copy, * i.e. the properties are not cloned. * * @param cs The coordinate system to copy. * * @since 2.2 */ public DefaultCartesianCS(final CartesianCS cs) { super(cs); ensurePerpendicularAxis(); } /** * Constructs a two-dimensional coordinate system from a name. * * @param name The coordinate system name. * @param axis0 The first axis. * @param axis1 The second axis. */ public DefaultCartesianCS(final String name, final CoordinateSystemAxis axis0, final CoordinateSystemAxis axis1) { super(name, axis0, axis1); ensurePerpendicularAxis(); } /** * Constructs a three-dimensional coordinate system from a name. * * @param name The coordinate system name. * @param axis0 The first axis. * @param axis1 The second axis. * @param axis2 The third axis. */ public DefaultCartesianCS(final String name, final CoordinateSystemAxis axis0, final CoordinateSystemAxis axis1, final CoordinateSystemAxis axis2) { super(name, axis0, axis1, axis2); ensurePerpendicularAxis(); } /** * Constructs a two-dimensional coordinate system from a set of properties. * The properties map is given unchanged to the * {@linkplain AbstractCS#AbstractCS(Map,CoordinateSystemAxis[]) super-class constructor}. * * @param properties Set of properties. Should contains at least {@code "name"}. * @param axis0 The first axis. * @param axis1 The second axis. */ public DefaultCartesianCS(final Map properties, final CoordinateSystemAxis axis0, final CoordinateSystemAxis axis1) { super(properties, axis0, axis1); ensurePerpendicularAxis(); } /** * Constructs a three-dimensional coordinate system from a set of properties. * The properties map is given unchanged to the * {@linkplain AbstractCS#AbstractCS(Map,CoordinateSystemAxis[]) super-class constructor}. * * @param properties Set of properties. Should contains at least {@code "name"}. * @param axis0 The first axis. * @param axis1 The second axis. * @param axis2 The third axis. */ public DefaultCartesianCS(final Map properties, final CoordinateSystemAxis axis0, final CoordinateSystemAxis axis1, final CoordinateSystemAxis axis2) { super(properties, axis0, axis1, axis2); ensurePerpendicularAxis(); } /** * For {@link #usingUnit} and {@link PredefinedCS#rightHanded} usage only. */ DefaultCartesianCS(final Map properties, final CoordinateSystemAxis[] axis) { super(properties, axis); ensurePerpendicularAxis(); } /** * Ensures that all axis are perpendicular. */ private void ensurePerpendicularAxis() throws IllegalArgumentException { final int dimension = getDimension(); for (int i=0; i DirectionAlongMeridian.EPS) { throw new IllegalArgumentException(Errors.format( ErrorKeys.NON_PERPENDICULAR_AXIS_$2, axis0.name(), axis1.name())); } } } } /** * Computes the distance between two points. * * @param coord1 Coordinates of the first point. * @param coord2 Coordinates of the second point. * @return The distance between {@code coord1} and {@code coord2}. * @throws MismatchedDimensionException if a coordinate doesn't have the expected dimension. */ @Override public Measure distance(final double[] coord1, final double[] coord2) throws MismatchedDimensionException { ensureDimensionMatch("coord1", coord1); ensureDimensionMatch("coord2", coord2); final Unit unit = getDistanceUnit(); UnitConverter[] converters = this.converters; // Avoid the need for synchronization. if (converters == null) { converters = new UnitConverter[getDimension()]; for (int i=0; i unit) throws IllegalArgumentException { final CoordinateSystemAxis[] axis = axisUsingUnit(unit); if (axis == null) { return this; } return new DefaultCartesianCS(getProperties(this, null), axis); } }