001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/csct/ct/MercatorProjection.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/exse/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification 012 (C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/) 013 SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite 014 Institut de Recherche pour le D�veloppement / US-Espace 015 mailto:seasnet@teledetection.fr 016 017 018 This library is free software; you can redistribute it and/or 019 modify it under the terms of the GNU Lesser General Public 020 License as published by the Free Software Foundation; either 021 version 2.1 of the License, or (at your option) any later version. 022 023 This library is distributed in the hope that it will be useful, 024 but WITHOUT ANY WARRANTY; without even the implied warranty of 025 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 026 Lesser General Public License for more details. 027 028 You should have received a copy of the GNU Lesser General Public 029 License along with this library; if not, write to the Free Software 030 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 031 032 Contact: 033 034 Andreas Poth 035 lat/lon GmbH 036 Aennchenstr. 19 037 53115 Bonn 038 Germany 039 E-Mail: poth@lat-lon.de 040 041 Klaus Greve 042 Department of Geography 043 University of Bonn 044 Meckenheimer Allee 166 045 53115 Bonn 046 Germany 047 E-Mail: klaus.greve@uni-bonn.de 048 049 050 ---------------------------------------------------------------------------*/ 051 package org.deegree.model.csct.ct; 052 053 // OpenGIS (SEAS) dependencies 054 import java.awt.geom.Point2D; 055 056 import org.deegree.model.csct.cs.Projection; 057 import org.deegree.model.csct.pt.Latitude; 058 import org.deegree.model.csct.resources.css.ResourceKeys; 059 import org.deegree.model.csct.resources.css.Resources; 060 061 062 /** 063 * Projection cylindrique de Mercator. Les parall�les et les m�ridients apparaissent 064 * comme des lignes droites et se croisent � angles droits; cette projection produit 065 * donc des cartes rectangulaires. L'�chelle est vrai le long de l'�quateur (par d�faut) 066 * ou le long de deux parall�les �quidistants de l'�quateur. Cette projection est utilis�e 067 * pour repr�senter des r�gions pr�s de l'�quateur. Elle est aussi souvent utilis�e pour la 068 * navigation maritime parce que toutes les lignes droites sur la carte sont des lignes 069 * <em>loxodromiques</em>, c'est-�-dire qu'un navire suivant cette ligne garderait un azimuth 070 * constant sur son compas. 071 * <br><br> 072 * 073 * R�f�rence: John P. Snyder (Map Projections - A Working Manual, 074 * U.S. Geological Survey Professional Paper 1395, 1987) 075 * 076 * @version 1.0 077 * @author Andr� Gosselin 078 * @author Martin Desruisseaux 079 */ 080 final class MercatorProjection extends CylindricalProjection 081 { 082 /** 083 * Global scale factor. Value <code>ak0</code> 084 * is equals to <code>{@link #a}*k0</code>. 085 */ 086 private final double ak0; 087 088 /** 089 * Construct a new map projection from the suplied parameters. 090 * 091 * @param parameters The parameter values in standard units. 092 * @throws MissingParameterException if a mandatory parameter is missing. 093 */ 094 protected MercatorProjection(final Projection parameters) throws MissingParameterException 095 { 096 ////////////////////////// 097 // Fetch parameters // 098 ////////////////////////// 099 super(parameters); 100 centralLatitude = latitudeToRadians(parameters.getValue("latitude_of_origin", 0), false); 101 final double latitudeTrueScale = Math.abs(centralLatitude); 102 103 ////////////////////////// 104 // Compute constants // 105 ////////////////////////// 106 if (isSpherical) 107 { 108 ak0 = a*Math.cos(latitudeTrueScale); 109 } 110 else 111 { 112 ak0 = a*msfn(Math.sin(latitudeTrueScale), Math.cos(latitudeTrueScale)); 113 } 114 } 115 116 /** 117 * Returns a human readable name localized for the specified locale. 118 */ 119 public String getName() 120 {return Resources.getResources(null).getString(ResourceKeys.CYLINDRICAL_MERCATOR_PROJECTION);} 121 122 /** 123 * Transforms the specified (<var>x</var>,<var>y</var>) coordinate 124 * and stores the result in <code>ptDst</code>. 125 */ 126 protected Point2D transform(double x, double y, final Point2D ptDst) throws TransformException 127 { 128 if (Math.abs(y) > (Math.PI/2 - EPS)) 129 { 130 throw new TransformException(Resources.format(ResourceKeys.ERROR_POLE_PROJECTION_$1, new Latitude(Math.toDegrees(y)))); 131 } 132 x = (x-centralMeridian)*ak0; 133 if (isSpherical) 134 { 135 y = ak0*Math.log(Math.tan((Math.PI/4.0) + 0.5*y)); 136 } 137 else 138 { 139 y = -ak0*Math.log(tsfn(y, Math.sin(y))); 140 } 141 if (ptDst!=null) 142 { 143 ptDst.setLocation(x,y); 144 return ptDst; 145 } 146 return new Point2D.Double(x,y); 147 } 148 149 /** 150 * Transforms the specified (<var>x</var>,<var>y</var>) coordinate 151 * and stores the result in <code>ptDst</code>. 152 */ 153 protected Point2D inverseTransform(double x, double y, final Point2D ptDst) throws TransformException 154 { 155 x = x/ak0 + centralMeridian; 156 y = Math.exp(-y/ak0); 157 if (isSpherical) 158 { 159 y = (Math.PI/2.0) - 2.0*Math.atan(y); 160 } 161 else 162 { 163 y = cphi2(y); 164 } 165 if (ptDst!=null) 166 { 167 ptDst.setLocation(x,y); 168 return ptDst; 169 } 170 return new Point2D.Double(x,y); 171 } 172 173 /** 174 * Returns a hash value for this projection. 175 */ 176 public int hashCode() 177 { 178 final long code = Double.doubleToLongBits(ak0); 179 return ((int)code ^ (int)(code >>> 32)) + 37*super.hashCode(); 180 } 181 182 /** 183 * Compares the specified object with 184 * this map projection for equality. 185 */ 186 public boolean equals(final Object object) 187 { 188 if (object==this) return true; // Slight optimization 189 if (super.equals(object)) 190 { 191 final MercatorProjection that = (MercatorProjection) object; 192 return Double.doubleToLongBits(this.ak0) == Double.doubleToLongBits(that.ak0); 193 } 194 return false; 195 } 196 197 /** 198 * Informations about a {@link MercatorProjection}. 199 * 200 * @version 1.0 201 * @author Martin Desruisseaux 202 */ 203 static final class Provider extends MapProjection.Provider 204 { 205 /** 206 * Construct a new provider. 207 */ 208 public Provider() 209 {super("Mercator_1SP", ResourceKeys.CYLINDRICAL_MERCATOR_PROJECTION);} 210 211 /** 212 * Create a new map projection. 213 */ 214 protected Object create(final Projection parameters) 215 {return new MercatorProjection(parameters);} 216 } 217 }