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 }