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 }