/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/exse/ lat/lon GmbH http://www.lat-lon.de It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification (C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/) SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite Institut de Recherche pour le D�veloppement / US-Espace mailto:seasnet@teledetection.fr 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn Germany E-Mail: poth@lat-lon.de Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: klaus.greve@uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.model.csct.ct; // OpenGIS (SEAS) dependencies import java.awt.geom.Point2D; import java.util.Locale; import org.deegree.model.csct.cs.Projection; import org.deegree.model.csct.pt.Latitude; import org.deegree.model.csct.resources.css.ResourceKeys; import org.deegree.model.csct.resources.css.Resources; /** * Projection cylindrique de Mercator. Les parall�les et les m�ridients apparaissent * comme des lignes droites et se croisent � angles droits; cette projection produit * donc des cartes rectangulaires. L'�chelle est vrai le long de l'�quateur (par d�faut) * ou le long de deux parall�les �quidistants de l'�quateur. Cette projection est utilis�e * pour repr�senter des r�gions pr�s de l'�quateur. Elle est aussi souvent utilis�e pour la * navigation maritime parce que toutes les lignes droites sur la carte sont des lignes * <em>loxodromiques</em>, c'est-�-dire qu'un navire suivant cette ligne garderait un azimuth * constant sur son compas. * <br><br> * * R�f�rence: John P. Snyder (Map Projections - A Working Manual, * U.S. Geological Survey Professional Paper 1395, 1987) * * @version 1.0 * @author Andr� Gosselin * @author Martin Desruisseaux */ final class MercatorProjection extends CylindricalProjection { /** * Global scale factor. Value <code>ak0</code> * is equals to <code>{@link #a}*k0</code>. */ private final double ak0; /** * Construct a new map projection from the suplied parameters. * * @param parameters The parameter values in standard units. * @throws MissingParameterException if a mandatory parameter is missing. */ protected MercatorProjection(final Projection parameters) throws MissingParameterException { ////////////////////////// // Fetch parameters // ////////////////////////// super(parameters); centralLatitude = latitudeToRadians(parameters.getValue("latitude_of_origin", 0), false); final double latitudeTrueScale = Math.abs(centralLatitude); ////////////////////////// // Compute constants // ////////////////////////// if (isSpherical) { ak0 = a*Math.cos(latitudeTrueScale); } else { ak0 = a*msfn(Math.sin(latitudeTrueScale), Math.cos(latitudeTrueScale)); } } /** * Returns a human readable name localized for the specified locale. */ public String getName(final Locale locale) {return Resources.getResources(locale).getString(ResourceKeys.CYLINDRICAL_MERCATOR_PROJECTION);} /** * Transforms the specified (<var>x</var>,<var>y</var>) coordinate * and stores the result in <code>ptDst</code>. */ protected Point2D transform(double x, double y, final Point2D ptDst) throws TransformException { if (Math.abs(y) > (Math.PI/2 - EPS)) { throw new TransformException(Resources.format(ResourceKeys.ERROR_POLE_PROJECTION_$1, new Latitude(Math.toDegrees(y)))); } x = (x-centralMeridian)*ak0; if (isSpherical) { y = ak0*Math.log(Math.tan((Math.PI/4.0) + 0.5*y)); } else { y = -ak0*Math.log(tsfn(y, Math.sin(y))); } if (ptDst!=null) { ptDst.setLocation(x,y); return ptDst; } return new Point2D.Double(x,y); } /** * Transforms the specified (<var>x</var>,<var>y</var>) coordinate * and stores the result in <code>ptDst</code>. */ protected Point2D inverseTransform(double x, double y, final Point2D ptDst) throws TransformException { x = x/ak0 + centralMeridian; y = Math.exp(-y/ak0); if (isSpherical) { y = (Math.PI/2.0) - 2.0*Math.atan(y); } else { y = cphi2(y); } if (ptDst!=null) { ptDst.setLocation(x,y); return ptDst; } return new Point2D.Double(x,y); } /** * Returns a hash value for this projection. */ public int hashCode() { final long code = Double.doubleToLongBits(ak0); return ((int)code ^ (int)(code >>> 32)) + 37*super.hashCode(); } /** * Compares the specified object with * this map projection for equality. */ public boolean equals(final Object object) { if (object==this) return true; // Slight optimization if (super.equals(object)) { final MercatorProjection that = (MercatorProjection) object; return Double.doubleToLongBits(this.ak0) == Double.doubleToLongBits(that.ak0); } return false; } /** * Informations about a {@link MercatorProjection}. * * @version 1.0 * @author Martin Desruisseaux */ static final class Provider extends MapProjection.Provider { /** * Construct a new provider. */ public Provider() {super("Mercator_1SP", ResourceKeys.CYLINDRICAL_MERCATOR_PROJECTION);} /** * Create a new map projection. */ protected Object create(final Projection parameters) {return new MercatorProjection(parameters);} } }