001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }