001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/crs/projections/conic/ConicProjection.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036
037 package org.deegree.crs.projections.conic;
038
039 import static org.deegree.crs.projections.ProjectionUtils.EPS11;
040 import static org.deegree.crs.projections.ProjectionUtils.WORLD_BOUNDS_RAD;
041
042 import javax.vecmath.Point2d;
043
044 import org.deegree.crs.Identifiable;
045 import org.deegree.crs.components.Unit;
046 import org.deegree.crs.coordinatesystems.GeographicCRS;
047 import org.deegree.crs.projections.Projection;
048
049 /**
050 * The <code>ConicProjection</code> is a super class for all conic projections.
051 * <p>
052 * <q>(From Snyder p.97)</q>
053 * </p>
054 * <p>
055 * To show a region for which the greatest extent is from east to west in the temperate zones, conic projections are
056 * usually preferable to cylindrical projections.
057 * </p>
058 * <p>
059 * Normal conic projections are distinguished by the use of arcs of concentric circles for parallesl of latitude and
060 * equally spaced straight radii of these circles for meridians. The angles between the meridians on the map are smaller
061 * than the actual differences in longitude. The circular arcs may or may not be equally spaced, depending on the
062 * projections. The polyconic projections and the oblique conic projections have characteristcs different from these.
063 * </p>
064 * <p>
065 * There are three important classes of conic projections:
066 * <ul>
067 * <li>The equidistant</li>
068 * <li>the conformal</li>
069 * <li>the equal area</li>
070 * </ul>
071 * </p>
072 *
073 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
074 *
075 * @author last edited by: $Author: mschneider $
076 *
077 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
078 *
079 */
080
081 public abstract class ConicProjection extends Projection {
082
083 private static final long serialVersionUID = -1642488930917290590L;
084
085 private double firstParallelLatitude;
086
087 private double secondParallelLatitude;
088
089 /**
090 * @param firstParallelLatitude
091 * the latitude (in radians) of the first parallel. (Snyder phi_1).
092 * @param secondParallelLatitude
093 * the latitude (in radians) of the second parallel. (Snyder phi_2).
094 * @param geographicCRS
095 * @param falseNorthing
096 * @param falseEasting
097 * @param naturalOrigin
098 * @param units
099 * @param scale
100 * @param conformal
101 * @param equalArea
102 * @param id
103 * an identifiable instance containing information about this projection
104 */
105 public ConicProjection( double firstParallelLatitude, double secondParallelLatitude, GeographicCRS geographicCRS,
106 double falseNorthing, double falseEasting, Point2d naturalOrigin, Unit units, double scale,
107 boolean conformal, boolean equalArea, Identifiable id ) {
108 super( geographicCRS, falseNorthing, falseEasting, naturalOrigin, units, scale, conformal, equalArea, id );
109
110 if ( Double.isNaN( firstParallelLatitude ) || firstParallelLatitude == 0
111 || Math.abs( firstParallelLatitude ) < EPS11 || firstParallelLatitude < WORLD_BOUNDS_RAD.getMinY()
112 || firstParallelLatitude > WORLD_BOUNDS_RAD.getMaxY() ) {
113 this.firstParallelLatitude = getProjectionLatitude();
114 this.secondParallelLatitude = getProjectionLatitude();
115 } else {
116 this.firstParallelLatitude = firstParallelLatitude;
117 this.secondParallelLatitude = secondParallelLatitude;
118 if ( this.secondParallelLatitude < WORLD_BOUNDS_RAD.getMinY()
119 || this.secondParallelLatitude > WORLD_BOUNDS_RAD.getMaxY() ) {
120 this.secondParallelLatitude = Double.NaN;
121 }
122 }
123 }
124
125 /**
126 * @return the latitude of the first parallel which is the intersection of the earth with the cone or the
127 * projectionLatitude if the cone is tangential with earth (e.g. one standard parallel).
128 */
129 public final double getFirstParallelLatitude() {
130 return firstParallelLatitude;
131 }
132
133 /**
134 * @return the latitude of the first parallel which is the intersection of the earth with the cone or the
135 * projectionLatitude if the cone is tangential with earth (e.g. one standard parallel).
136 */
137 public final double getSecondParallelLatitude() {
138 return secondParallelLatitude;
139 }
140
141 @Override
142 public boolean equals( Object other ) {
143 if ( other != null && other instanceof ConicProjection ) {
144 final ConicProjection that = (ConicProjection) other;
145 return super.equals( other )
146 && ( Double.isNaN( this.firstParallelLatitude ) ? Double.isNaN( that.firstParallelLatitude )
147 : Math.abs( this.firstParallelLatitude
148 - that.firstParallelLatitude ) < EPS11 )
149 && ( Double.isNaN( this.secondParallelLatitude ) ? Double.isNaN( that.secondParallelLatitude )
150 : Math.abs( this.secondParallelLatitude
151 - that.secondParallelLatitude ) < EPS11 );
152 }
153 return false;
154 }
155
156 /**
157 * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
158 * distribution and is relatively fast. It is created from field <b>f</b> as follows:
159 * <ul>
160 * <li>boolean -- code = (f ? 0 : 1)</li>
161 * <li>byte, char, short, int -- code = (int)f</li>
162 * <li>long -- code = (int)(f ^ (f >>>32))</li>
163 * <li>float -- code = Float.floatToIntBits(f);</li>
164 * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l >>> 32))</li>
165 * <li>all Objects, (where equals( ) calls equals( ) for this field) -- code = f.hashCode( )</li>
166 * <li>Array -- Apply above rules to each element</li>
167 * </ul>
168 * <p>
169 * Combining the hash code(s) computed above: result = 37 * result + code;
170 * </p>
171 *
172 * @return (int) ( result >>> 32 ) ^ (int) result;
173 *
174 * @see java.lang.Object#hashCode()
175 */
176 @Override
177 public int hashCode() {
178 // the 2nd millionth prime, :-)
179 long code = 32452843;
180 code = code * 37 + super.hashCode();
181
182 long tmp = Double.doubleToLongBits( firstParallelLatitude );
183 code = code * 37 + (int) ( tmp ^ ( tmp >>> 32 ) );
184
185 tmp = Double.doubleToLongBits( secondParallelLatitude );
186 code = code * 37 + (int) ( tmp ^ ( tmp >>> 32 ) );
187
188 return (int) ( code >>> 32 ) ^ (int) code;
189 }
190 }