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,
105: double secondParallelLatitude, GeographicCRS geographicCRS,
106: double falseNorthing, double falseEasting,
107: Point2d naturalOrigin, Unit units, double scale,
108: boolean conformal, boolean equalArea, String[] identifiers,
109: String[] names, String[] versions, String[] descriptions,
110: String[] areasOfUse) {
111: super (geographicCRS, falseNorthing, falseEasting,
112: naturalOrigin, units, scale, conformal, equalArea,
113: identifiers, names, versions, descriptions, areasOfUse);
114:
115: if (Double.isNaN(firstParallelLatitude)
116: || firstParallelLatitude == 0
117: || Math.abs(firstParallelLatitude) < ProjectionUtils.EPS10
118: || firstParallelLatitude < ProjectionUtils.WORLD_BOUNDS_RAD
119: .getMinY()
120: || firstParallelLatitude > ProjectionUtils.WORLD_BOUNDS_RAD
121: .getMaxY()) {
122: this .firstParallelLatitude = getProjectionLatitude();
123: this .secondParallelLatitude = getProjectionLatitude();
124: } else {
125: this .firstParallelLatitude = firstParallelLatitude;
126: this .secondParallelLatitude = secondParallelLatitude;
127: if (this .secondParallelLatitude < ProjectionUtils.WORLD_BOUNDS_RAD
128: .getMinY()
129: || this .secondParallelLatitude > ProjectionUtils.WORLD_BOUNDS_RAD
130: .getMaxY()) {
131: // System.out.println( "setting to nan");
132: this .secondParallelLatitude = Double.NaN;
133: }
134: // System.out.println( "given latitude and longitude: " + Math.toDegrees( this.firstParallelLatitude ) + "
135: // and " + Math.toDegrees( this.secondParallelLatitude ));
136: }
137: }
138:
139: /**
140: * @return the latitude of the first parallel which is the intersection of the earth with the cone or the
141: * projectionLatitude if the cone is tangential with earth (e.g. one standard parallel).
142: */
143: public final double getFirstParallelLatitude() {
144: return firstParallelLatitude;
145: }
146:
147: /**
148: * @return the latitude of the first parallel which is the intersection of the earth with the cone or the
149: * projectionLatitude if the cone is tangential with earth (e.g. one standard parallel).
150: */
151: public final double getSecondParallelLatitude() {
152: return secondParallelLatitude;
153: }
154:
155: @Override
156: public boolean equals(Object other) {
157: if (other != null && other instanceof ConicProjection) {
158: final ConicProjection that = (ConicProjection) other;
159: return super .equals(other)
160: && Math.abs(this .firstParallelLatitude
161: - that.firstParallelLatitude) < ProjectionUtils.EPS11
162: && Math.abs(this .secondParallelLatitude
163: - that.secondParallelLatitude) < ProjectionUtils.EPS11;
164: }
165: return false;
166: }
167:
168: /**
169: * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
170: * distribution and is relatively fast. It is created from field <b>f</b> as follows:
171: * <ul>
172: * <li>boolean -- code = (f ? 0 : 1)</li>
173: * <li>byte, char, short, int -- code = (int)f </li>
174: * <li>long -- code = (int)(f ^ (f >>>32))</li>
175: * <li>float -- code = Float.floatToIntBits(f);</li>
176: * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l >>> 32))</li>
177: * <li>all Objects, (where equals( ) calls equals( ) for this field) -- code = f.hashCode( )</li>
178: * <li>Array -- Apply above rules to each element</li>
179: * </ul>
180: * <p>
181: * Combining the hash code(s) computed above: result = 37 * result + code;
182: * </p>
183: *
184: * @return (int) ( result >>> 32 ) ^ (int) result;
185: *
186: * @see java.lang.Object#hashCode()
187: */
188: @Override
189: public int hashCode() {
190: // the 2nd millionth prime, :-)
191: long code = 32452843;
192: code = code * 37 + super .hashCode();
193:
194: long tmp = Double.doubleToLongBits(firstParallelLatitude);
195: code = code * 37 + (int) (tmp ^ (tmp >>> 32));
196:
197: tmp = Double.doubleToLongBits(secondParallelLatitude);
198: code = code * 37 + (int) (tmp ^ (tmp >>> 32));
199:
200: return (int) (code >>> 32) ^ (int) code;
201: }
202: }
|