All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotoolkit.referencing.operation.projection.Equirectangular Maven / Gradle / Ivy

Go to download

Implementations of Coordinate Reference Systems (CRS), conversion and transformation services derived from ISO 19111.

There is a newer version: 3.20-geoapi-3.0
Show newest version
/*
 *    Geotoolkit.org - An Open Source Java GIS Toolkit
 *    http://www.geotoolkit.org
 *
 *    (C) 2005-2011, Open Source Geospatial Foundation (OSGeo)
 *    (C) 2009-2011, Geomatys
 *
 *    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.
 */
package org.geotoolkit.referencing.operation.projection;

import java.awt.geom.AffineTransform;
import net.jcip.annotations.Immutable;

import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.referencing.operation.MathTransform2D;
import org.opengis.referencing.operation.TransformException;

import org.geotoolkit.internal.referencing.ParameterizedAffine;
import org.geotoolkit.referencing.operation.transform.Parameterized;
import org.geotoolkit.referencing.operation.provider.EquidistantCylindrical;

import static java.lang.Math.*;
import static org.geotoolkit.internal.referencing.Identifiers.*;


/**
 * Equidistant Cylindrical projection (EPSG codes 1028, 1029, 9842, 9823). See the
 * Cylindrical
 * Equidistant projection on MathWorld for an overview. See any of the following providers
 * for a list of programmatic parameters:
 * 

*

    *
  • {@link org.geotoolkit.referencing.operation.provider.EquidistantCylindrical}
  • *
  • {@link org.geotoolkit.referencing.operation.provider.PlateCarree}
  • *
* * {@section Description} * * In the particular case where the latitude of natural origin is at the equator, * this projection is also called Plate Carrée. This is used for example * in WGS84 / Plate Carrée (EPSG:32662). * * {@section References} *
    *
  • John P. Snyder (Map Projections - A Working Manual,
    * U.S. Geological Survey Professional Paper 1395, 1987)
  • *
  • "Coordinate Conversions and Transformations including Formulas",
    * EPSG Guidance Note Number 7 part 2, Version 24.
  • *
* * @author John Grange * @author Martin Desruisseaux (IRD, Geomatys) * @version 3.00 * * @since 2.2 * @module */ @Immutable public class Equirectangular extends UnitaryProjection { /** * For cross-version compatibility. */ private static final long serialVersionUID = -848975059471102069L; /** * Creates an Equidistant Cylindrical projection from the given parameters. The * descriptor argument is usually one of the {@code PARAMETERS} constants defined * in the {@link EquidistantCylindrical} class or a subclass, but is not restricted to. * If a different descriptor is supplied, it is user's responsibility to ensure that it * is suitable to an Equidistant Cylindrical projection. * * @param descriptor Typically {@link EquidistantCylindrical#PARAMETERS}. * @param values The parameter values of the projection to create. * @return The map projection. * * @since 3.00 */ public static MathTransform2D create(final ParameterDescriptorGroup descriptor, final ParameterValueGroup values) { final Parameters parameters = new Parameters(descriptor, values); final Equirectangular projection = new Equirectangular(parameters); MathTransform2D tr = projection.createConcatenatedTransform(); if (tr instanceof AffineTransform) { tr = new Affine((AffineTransform) tr, parameters); } return tr; } /** * Constructs a new map projection from the supplied parameters. * * @param parameters The parameters of the projection to be created. */ protected Equirectangular(final Parameters parameters) { super(parameters); if (parameters.standardParallels.length != 0) { throw unknownParameter(STANDARD_PARALLEL_1); } double p = abs(parameters.latitudeOfOrigin); parameters.latitudeOfOrigin = p; parameters.normalize(true).scale(cos(p = toRadians(p)), 1); parameters.validate(); p = sin(p); p = sqrt(1 - excentricitySquared) / (1 - (p*p)*excentricitySquared); parameters.normalize(false).scale(p, p); finish(); } /** * Returns {@code true} since this projection is implemented using spherical formulas. */ @Override boolean isSpherical() { return true; } /** * Returns the parameter descriptors for this unitary projection. Note that * the returned descriptor is about the unitary projection, not the full one. */ @Override public ParameterDescriptorGroup getParameterDescriptors() { return EquidistantCylindrical.PARAMETERS; } // No need to override getParameterValues() because no additional // parameter are significant to a unitary Mercator projection. /** * An affine transform that remember the projection parameters. This is useful only to * the Equirectangular projection because it is the only one that may be simplified to * an affine transform. * * @author Martin Desruisseaux (Geomatys) * @version 3.00 * * @since 3.00 * @module */ private static final class Affine extends ParameterizedAffine { /** For cross-version compatibility. */ private static final long serialVersionUID = -4667404054723855507L; /** Creates a new transform from the given affine and parameters. */ public Affine(final AffineTransform transform, final Parameterized parameters) { super(transform, parameters); } /** Returns the parameter descriptors for this map projection. */ @Override public ParameterDescriptorGroup getParameterDescriptors() { return parameters.getParameterDescriptors(); } /** Returns the parameter values for this map projection. */ @Override public ParameterValueGroup getParameterValues() { return parameters.getParameterValues(); } } /** * Transforms the specified (λ,φ) coordinates * (units in radians) and stores the result in {@code dstPts} (linear distance * on a unit sphere). */ @Override protected void transform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff) throws ProjectionException { final double λ = srcPts[srcOff + 1]; // Must be before writing x. dstPts[dstOff] = rollLongitude(srcPts[srcOff]); dstPts[dstOff + 1] = λ; } /** * Converts a list of coordinate point ordinal values. * * {@note We override the super-class method only as an optimization in the special case * where the target coordinates are written at the same locations than the source * coordinates. In such case, we can take advantage of the fact that the φ value * is not modified by the unitary Equirectangular projection.} */ @Override public void transform(final double[] srcPts, int srcOff, final double[] dstPts, int dstOff, int numPts) throws TransformException { if (srcPts != dstPts || srcOff != dstOff) { super.transform(srcPts, srcOff, dstPts, dstOff, numPts); return; } if (verifyCoordinateRanges()) { verifyGeographicRanges(srcPts, srcOff, numPts); } while (--numPts >= 0) { dstPts[dstOff] = rollLongitude(dstPts[dstOff]); dstOff += 2; } // Invoking Assertions.checkReciprocal(...) here would be // useless since it works only for non-overlapping arrays. } /** * Transforms the specified (x,y) coordinates * and stores the result in {@code dstPts} (angles in radians). */ @Override protected void inverseTransform(final double[] srcPts, final int srcOff, final double[] dstPts, final int dstOff) throws ProjectionException { final double y = srcPts[srcOff + 1]; // Must be before writing x. dstPts[dstOff] = unrollLongitude(srcPts[srcOff]); // Must be before writing y. dstPts[dstOff+1] = y; } /** * Returns {@code true} if this unitary projection is the identity transform. * The kernel of an equirectangular projection is an identity transform if it * doesn't performs {@linkplain #rollLongitude(double) longitude rolling}. */ @Override public boolean isIdentity() { return !rollLongitude(); } /** * Returns an estimation of the error in linear distance on the unit ellipse. In * the case of Equirectangular projection the error is close to zero everywhere. */ @Override double getErrorEstimate(final double λ, final double φ) { return 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy