001    // License: GPL. Copyright 2007 by Immanuel Scholz and others
002    //                         2009 by ??ukasz Stelmach
003    package org.openstreetmap.josm.data.projection;
004    
005    import static org.openstreetmap.josm.tools.I18n.tr;
006    
007    import org.openstreetmap.josm.data.Bounds;
008    import org.openstreetmap.josm.data.coor.LatLon;
009    import org.openstreetmap.josm.data.projection.datum.GRS80Datum;
010    import org.openstreetmap.josm.data.projection.proj.ProjParameters;
011    
012    /**
013     * PUWG 1992 and 2000 are the official cordinate systems in Poland.
014     * They use the same math as UTM only with different constants.
015     *
016     * @author steelman
017     */
018    public class Puwg extends AbstractProjection {
019    
020        public static final int DEFAULT_ZONE = 0;
021    
022        private final int zone;
023    
024        static public PuwgData[] zones = new PuwgData[] {
025            new Epsg2180(),
026            new Epsg2176(),
027            new Epsg2177(),
028            new Epsg2178(),
029            new Epsg2179()
030        };
031    
032        public Puwg() {
033            this(DEFAULT_ZONE);
034        }
035    
036        public Puwg(int zone) {
037            if (zone < 0 || zone >= zones.length)
038                throw new IllegalArgumentException();
039            ellps = Ellipsoid.GRS80;
040            proj = new org.openstreetmap.josm.data.projection.proj.TransverseMercator();
041            try {
042                proj.initialize(new ProjParameters() {{ ellps = Puwg.this.ellps; }});
043            } catch (ProjectionConfigurationException e) {
044                throw new RuntimeException(e);
045            }
046            datum = GRS80Datum.INSTANCE;
047            this.zone = zone;
048            PuwgData z = zones[zone];
049            x_0 = z.getPuwgFalseEasting();
050            y_0 = z.getPuwgFalseNorthing();
051            lon_0 = z.getPuwgCentralMeridianDeg();
052            k_0 = z.getPuwgScaleFactor();
053        }
054    
055        @Override
056        public String toString() {
057            return tr("PUWG (Poland)");
058        }
059    
060        @Override
061        public Integer getEpsgCode() {
062            return zones[zone].getEpsgCode();
063        }
064    
065        @Override
066        public int hashCode() {
067            return getClass().getName().hashCode()+zone; // our only real variable
068        }
069    
070        @Override
071        public String getCacheDirectoryName() {
072            return zones[zone].getCacheDirectoryName();
073        }
074    
075        @Override
076        public Bounds getWorldBoundsLatLon() {
077            return zones[zone].getWorldBoundsLatLon();
078        }
079    
080        public interface PuwgData {
081            double getPuwgCentralMeridianDeg();
082            double getPuwgCentralMeridian();
083            double getPuwgFalseEasting();
084            double getPuwgFalseNorthing();
085            double getPuwgScaleFactor();
086    
087            // Projection methods
088            Integer getEpsgCode();
089            String toCode();
090            String getCacheDirectoryName();
091            Bounds getWorldBoundsLatLon();
092        }
093    
094        public static class Epsg2180 implements PuwgData {
095    
096            private static final double Epsg2180FalseEasting = 500000.0; /* y */
097            private static final double Epsg2180FalseNorthing = -5300000.0; /* x */
098            private static final double Epsg2180ScaleFactor = 0.9993;
099            private static final double Epsg2180CentralMeridian = 19.0;
100    
101            @Override public String toString() {
102                return tr("PUWG 1992 (Poland)");
103            }
104    
105            @Override
106            public Integer getEpsgCode() {
107                return 2180;
108            }
109    
110            @Override
111            public String toCode() {
112                return "EPSG:" + getEpsgCode();
113            }
114    
115            @Override
116            public String getCacheDirectoryName() {
117                return "epsg2180";
118            }
119    
120            @Override
121            public Bounds getWorldBoundsLatLon()
122            {
123                return new Bounds(
124                        new LatLon(49.00, 14.12),
125                        new LatLon(54.84, 24.15), false);
126            }
127    
128            @Override public double getPuwgCentralMeridianDeg() { return Epsg2180CentralMeridian; }
129            @Override public double getPuwgCentralMeridian() { return Math.toRadians(Epsg2180CentralMeridian); }
130            @Override public double getPuwgFalseEasting() { return Epsg2180FalseEasting; }
131            @Override public double getPuwgFalseNorthing() { return Epsg2180FalseNorthing; }
132            @Override public double getPuwgScaleFactor() { return Epsg2180ScaleFactor; }
133        }
134    
135        abstract static class Puwg2000 implements PuwgData {
136    
137            private static final double PuwgFalseEasting = 500000.0;
138            private static final double PuwgFalseNorthing = 0;
139            private static final double PuwgScaleFactor = 0.999923;
140            //final private double[] Puwg2000CentralMeridian = {15.0, 18.0, 21.0, 24.0};
141            final private Integer[] Puwg2000Code = { 2176,  2177, 2178, 2179 };
142            final private String[] Puwg2000CDName = { "epsg2176",  "epsg2177", "epsg2178", "epsg2179" };
143    
144            @Override public String toString() {
145                return tr("PUWG 2000 Zone {0} (Poland)", Integer.toString(getZone()));
146            }
147    
148            @Override
149            public Integer getEpsgCode() {
150                return Puwg2000Code[getZoneIndex()];
151            }
152    
153            @Override
154            public String toCode() {
155                return "EPSG:" + getEpsgCode();
156            }
157    
158            @Override
159            public String getCacheDirectoryName() {
160                return Puwg2000CDName[getZoneIndex()];
161            }
162    
163            @Override
164            public Bounds getWorldBoundsLatLon()
165            {
166                return new Bounds(
167                        new LatLon(49.00, (3 * getZone()) - 1.5),
168                        new LatLon(54.84, (3 * getZone()) + 1.5), false);
169            }
170    
171            @Override public double getPuwgCentralMeridianDeg() { return getZone() * 3.0; }
172            @Override public double getPuwgCentralMeridian() { return Math.toRadians(getZone() * 3.0); }
173            @Override public double getPuwgFalseNorthing() { return PuwgFalseNorthing;}
174            @Override public double getPuwgFalseEasting() { return 1e6 * getZone() + PuwgFalseEasting; }
175            @Override public double getPuwgScaleFactor() { return PuwgScaleFactor; }
176            public abstract int getZone();
177    
178            public int getZoneIndex() { return getZone() - 5; }
179    
180        }
181    
182        public static class Epsg2176 extends Puwg2000 {
183            private static final int PuwgZone = 5;
184    
185            @Override
186            public int getZone() { return PuwgZone; }
187        }
188    
189        public static class Epsg2177 extends Puwg2000 {
190            private static final int PuwgZone = 6;
191    
192            @Override
193            public int getZone() { return PuwgZone; }
194        }
195    
196        public static class Epsg2178 extends Puwg2000 {
197            private static final int PuwgZone = 7;
198    
199            @Override
200            public int getZone() { return PuwgZone; }
201        }
202    
203        public static class Epsg2179 extends Puwg2000 {
204            private static final int PuwgZone = 8;
205    
206            @Override
207            public int getZone() { return PuwgZone; }
208        }
209    }