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    }