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