001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.data.projection; 003 004 import org.openstreetmap.josm.data.coor.EastNorth; 005 import org.openstreetmap.josm.data.coor.LatLon; 006 import org.openstreetmap.josm.data.projection.datum.Datum; 007 import org.openstreetmap.josm.data.projection.proj.Proj; 008 009 /** 010 * Implementation of the Projection interface that represents a coordinate reference system and delegates 011 * the real projection and datum conversion to other classes. 012 * 013 * It handles false easting and northing, central meridian and general scale factor before calling the 014 * delegate projection. 015 * 016 * Forwards lat/lon values to the real projection in units of radians. 017 * 018 * The fields are named after Proj.4 parameters. 019 * 020 * Subclasses of AbstractProjection must set ellps and proj to a non-null value. 021 * In addition, either datum or nadgrid has to be initialized to some value. 022 */ 023 abstract public class AbstractProjection implements Projection { 024 025 protected Ellipsoid ellps; 026 protected Datum datum; 027 protected Proj proj; 028 protected double x_0 = 0.0; /* false easting (in meters) */ 029 protected double y_0 = 0.0; /* false northing (in meters) */ 030 protected double lon_0 = 0.0; /* central meridian */ 031 protected double k_0 = 1.0; /* general scale factor */ 032 033 public final Ellipsoid getEllipsoid() { 034 return ellps; 035 } 036 037 public final Datum getDatum() { 038 return datum; 039 } 040 041 public final Proj getProj() { 042 return proj; 043 } 044 045 public final double getFalseEasting() { 046 return x_0; 047 } 048 049 public final double getFalseNorthing() { 050 return y_0; 051 } 052 053 public final double getCentralMeridian() { 054 return lon_0; 055 } 056 057 public final double getScaleFactor() { 058 return k_0; 059 } 060 061 @Override 062 public EastNorth latlon2eastNorth(LatLon ll) { 063 ll = datum.fromWGS84(ll); 064 double[] en = proj.project(Math.toRadians(ll.lat()), Math.toRadians(ll.lon() - lon_0)); 065 return new EastNorth(ellps.a * k_0 * en[0] + x_0, ellps.a * k_0 * en[1] + y_0); 066 } 067 068 @Override 069 public LatLon eastNorth2latlon(EastNorth en) { 070 double[] latlon_rad = proj.invproject((en.east() - x_0) / ellps.a / k_0, (en.north() - y_0) / ellps.a / k_0); 071 LatLon ll = new LatLon(Math.toDegrees(latlon_rad[0]), Math.toDegrees(latlon_rad[1]) + lon_0); 072 return datum.toWGS84(ll); 073 } 074 075 @Override 076 public double getDefaultZoomInPPD() { 077 // this will set the map scaler to about 1000 m 078 return 10; 079 } 080 081 /** 082 * @return The EPSG Code of this CRS, null if it doesn't have one. 083 */ 084 public abstract Integer getEpsgCode(); 085 086 /** 087 * Default implementation of toCode(). 088 * Should be overridden, if there is no EPSG code for this CRS. 089 */ 090 @Override 091 public String toCode() { 092 return "EPSG:" + getEpsgCode(); 093 } 094 095 protected static final double convertMinuteSecond(double minute, double second) { 096 return (minute/60.0) + (second/3600.0); 097 } 098 099 protected static final double convertDegreeMinuteSecond(double degree, double minute, double second) { 100 return degree + (minute/60.0) + (second/3600.0); 101 } 102 103 public void dump() { 104 System.err.println("x_0="+x_0); 105 System.err.println("y_0="+y_0); 106 System.err.println("lon_0="+lon_0); 107 System.err.println("k_0="+k_0); 108 System.err.println("ellps="+ellps); 109 System.err.println("proj="+proj); 110 System.err.println("datum="+datum); 111 } 112 113 }