001    // License: GPL. Copyright 2007 by Immanuel Scholz and others
002    package org.openstreetmap.josm.data.projection;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import org.openstreetmap.josm.data.Bounds;
007    import org.openstreetmap.josm.data.coor.LatLon;
008    import org.openstreetmap.josm.data.projection.datum.WGS84Datum;
009    import org.openstreetmap.josm.data.projection.proj.ProjParameters;
010    
011    /**
012     *
013     * @author Dirk St??cker
014     * code based on JavaScript from Chuck Taylor
015     *
016     */
017    public class UTM extends AbstractProjection {
018    
019        private static final int DEFAULT_ZONE = 30;
020        private int zone;
021    
022        public enum Hemisphere { North, South }
023        private static final Hemisphere DEFAULT_HEMISPHERE = Hemisphere.North;
024        private Hemisphere hemisphere;
025    
026        public UTM() {
027            this(DEFAULT_ZONE, DEFAULT_HEMISPHERE);
028        }
029    
030        public UTM(int zone, Hemisphere hemisphere) {
031            if (zone < 1 || zone > 60)
032                throw new IllegalArgumentException();
033            ellps = Ellipsoid.WGS84;
034            proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
035            try {
036                proj.initialize(new ProjParameters() {{ ellps = UTM.this.ellps; }});
037            } catch (ProjectionConfigurationException e) {
038                throw new RuntimeException(e);
039            }
040            datum = WGS84Datum.INSTANCE;
041            this.zone = zone;
042            this.hemisphere = hemisphere;
043            x_0 = 500000;
044            y_0 = hemisphere == Hemisphere.North ? 0 : 10000000;
045            lon_0 = getUtmCentralMeridianDeg(zone);
046            k_0 = 0.9996;
047        }
048    
049        /*
050         * UTMCentralMeridian
051         *
052         * Determines the central meridian for the given UTM zone.
053         *
054         * Inputs:
055         *     zone - An integer value designating the UTM zone, range [1,60].
056         *
057         * Returns:
058         *   The central meridian for the given UTM zone, in radians, or zero
059         *   if the UTM zone parameter is outside the range [1,60].
060         *   Range of the central meridian is the radian equivalent of [-177,+177].
061         *
062         */
063        private double getUtmCentralMeridianDeg(int zone)
064        {
065            return -183.0 + (zone * 6.0);
066        }
067    
068        public int getzone() {
069            return zone;
070        }
071    
072        @Override
073        public String toString() {
074            return tr("UTM");
075        }
076    
077        @Override
078        public Integer getEpsgCode() {
079            return (32600 + getzone() + (hemisphere == Hemisphere.South?100:0));
080        }
081    
082        @Override
083        public int hashCode() {
084            return toCode().hashCode();
085        }
086    
087        @Override
088        public String getCacheDirectoryName() {
089            return "epsg"+ getEpsgCode();
090        }
091    
092        @Override
093        public Bounds getWorldBoundsLatLon()
094        {
095            if (hemisphere == Hemisphere.North)
096                return new Bounds(
097                        new LatLon(-5.0, getUtmCentralMeridianDeg(getzone())-5.0),
098                        new LatLon(85.0, getUtmCentralMeridianDeg(getzone())+5.0), false);
099            else
100                return new Bounds(
101                        new LatLon(-85.0, getUtmCentralMeridianDeg(getzone())-5.0),
102                        new LatLon(5.0, getUtmCentralMeridianDeg(getzone())+5.0), false);
103        }
104    
105    }