| 1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others |
| 2 | // 2009 by Łukasz Stelmach |
| 3 | package org.openstreetmap.josm.data.projection; |
| 4 | |
| 5 | import java.text.DecimalFormat; |
| 6 | |
| 7 | import static org.openstreetmap.josm.tools.I18n.tr; |
| 8 | |
| 9 | import java.awt.GridBagLayout; |
| 10 | import java.util.Collection; |
| 11 | import java.util.Collections; |
| 12 | |
| 13 | import javax.swing.JComboBox; |
| 14 | import javax.swing.JLabel; |
| 15 | import javax.swing.JPanel; |
| 16 | |
| 17 | import org.openstreetmap.josm.data.Bounds; |
| 18 | import org.openstreetmap.josm.data.coor.EastNorth; |
| 19 | import org.openstreetmap.josm.data.coor.LatLon; |
| 20 | import org.openstreetmap.josm.tools.GBC; |
| 21 | |
| 22 | /** |
| 23 | * PUWG 1992 and 2000 are the official cordinate systems in Poland. |
| 24 | * They use the same math as UTM only with different constants. |
| 25 | * |
| 26 | * @author steelman |
| 27 | */ |
| 28 | public class Puwg extends UTM implements Projection,ProjectionSubPrefs { |
| 29 | public static final int DEFAULT_ZONE = 0; |
| 30 | private int zone = DEFAULT_ZONE; |
| 31 | |
| 32 | private static PuwgData[] Zones = new PuwgData[]{ |
| 33 | new Epsg2180(), |
| 34 | new Epsg2176(), |
| 35 | new Epsg2177(), |
| 36 | new Epsg2178(), |
| 37 | new Epsg2179() |
| 38 | }; |
| 39 | |
| 40 | private static DecimalFormat decFormatter = new DecimalFormat("###0"); |
| 41 | |
| 42 | public EastNorth latlon2eastNorth(LatLon p) { |
| 43 | PuwgData z = Zones[zone]; |
| 44 | double easting = z.getPuwgFalseEasting(); |
| 45 | double northing = z.getPuwgFalseNorthing(); |
| 46 | double scale = z.getPuwgScaleFactor(); |
| 47 | double center = z.getPuwgCentralMeridian(); /* in radians */ |
| 48 | EastNorth a = MapLatLonToXY(Math.toRadians(p.lat()), Math.toRadians(p.lon()), center); |
| 49 | return new EastNorth(a.east() * scale + easting, a.north() * scale + northing); |
| 50 | } |
| 51 | |
| 52 | public LatLon eastNorth2latlon(EastNorth p) { |
| 53 | PuwgData z = Zones[zone]; |
| 54 | double easting = z.getPuwgFalseEasting(); |
| 55 | double northing = z.getPuwgFalseNorthing(); |
| 56 | double scale = z.getPuwgScaleFactor(); |
| 57 | double center = z.getPuwgCentralMeridian(); /* in radians */ |
| 58 | return MapXYToLatLon((p.east() - easting)/scale, (p.north() - northing)/scale, center); |
| 59 | } |
| 60 | |
| 61 | @Override public String toString() { |
| 62 | return tr("PUWG (Poland)"); |
| 63 | } |
| 64 | |
| 65 | public String toCode() { |
| 66 | return Zones[zone].toCode(); |
| 67 | } |
| 68 | |
| 69 | public String getCacheDirectoryName() { |
| 70 | return Zones[zone].getCacheDirectoryName(); |
| 71 | } |
| 72 | |
| 73 | public Bounds getWorldBoundsLatLon() { |
| 74 | return Zones[zone].getWorldBoundsLatLon(); |
| 75 | } |
| 76 | |
| 77 | public double getDefaultZoomInPPD() { |
| 78 | // This will set the scale bar to about 100 km |
| 79 | return 0.009; |
| 80 | } |
| 81 | |
| 82 | public String eastToString(EastNorth p) { |
| 83 | return decFormatter.format(p.east()); |
| 84 | } |
| 85 | |
| 86 | public String northToString(EastNorth p) { |
| 87 | return decFormatter.format(p.north()); |
| 88 | } |
| 89 | |
| 90 | public void setupPreferencePanel(JPanel p) { |
| 91 | JComboBox prefcb = new JComboBox(Puwg.Zones); |
| 92 | |
| 93 | prefcb.setSelectedIndex(zone); |
| 94 | p.setLayout(new GridBagLayout()); |
| 95 | p.add(new JLabel(tr("PUWG Zone")), GBC.std().insets(5,5,0,5)); |
| 96 | p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL)); |
| 97 | /* Note: we use component position 2 below to find this again */ |
| 98 | p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL)); |
| 99 | p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH)); |
| 100 | } |
| 101 | |
| 102 | public Collection<String> getPreferences(JPanel p) { |
| 103 | Object prefcb = p.getComponent(2); |
| 104 | if(!(prefcb instanceof JComboBox)) |
| 105 | return null; |
| 106 | int zone = ((JComboBox)prefcb).getSelectedIndex(); |
| 107 | return Collections.singleton((Puwg.Zones[zone]).toCode()); |
| 108 | } |
| 109 | |
| 110 | public Collection<String> getPreferencesFromCode(String code) |
| 111 | { |
| 112 | for (Projection p : Puwg.Zones) |
| 113 | { |
| 114 | if(code.equals(p.toCode())) |
| 115 | return Collections.singleton(code); |
| 116 | } |
| 117 | return null; |
| 118 | } |
| 119 | |
| 120 | public void setPreferences(Collection<String> args) |
| 121 | { |
| 122 | zone = DEFAULT_ZONE; |
| 123 | try { |
| 124 | for(String s : args) |
| 125 | { |
| 126 | for (int i=0; i < Puwg.Zones.length; ++i) |
| 127 | if(s.equals(Zones[i].toCode())) |
| 128 | zone = i; |
| 129 | break; |
| 130 | } |
| 131 | } catch (NullPointerException e) {}; |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | interface PuwgData extends Projection { |
| 136 | public double getPuwgCentralMeridianDeg(); |
| 137 | public double getPuwgCentralMeridian(); |
| 138 | public double getPuwgFalseEasting(); |
| 139 | public double getPuwgFalseNorthing(); |
| 140 | public double getPuwgScaleFactor(); |
| 141 | } |
| 142 | |
| 143 | |
| 144 | class Epsg2180 implements PuwgData { |
| 145 | |
| 146 | final private double Epsg2180FalseEasting = 500000.0; /* y */ |
| 147 | final private double Epsg2180FalseNorthing = -5300000.0; /* x */ |
| 148 | final private double Epsg2180ScaleFactor = 0.9993; |
| 149 | final private double Epsg2180CentralMeridian = 19.0; |
| 150 | private static DecimalFormat decFormatter = new DecimalFormat("###0"); |
| 151 | |
| 152 | @Override public String toString() { |
| 153 | return tr("PUWG 1992 (Poland)"); |
| 154 | } |
| 155 | |
| 156 | public String toCode() { |
| 157 | return "EPSG:2180"; |
| 158 | } |
| 159 | |
| 160 | public String getCacheDirectoryName() { |
| 161 | return "epsg2180"; |
| 162 | } |
| 163 | |
| 164 | public Bounds getWorldBoundsLatLon() |
| 165 | { |
| 166 | return new Bounds( |
| 167 | new LatLon(49.00, 14.12), |
| 168 | new LatLon(54.84, 24.15)); |
| 169 | } |
| 170 | |
| 171 | /* These two MUST NOT be used. Use Puwg implementation instead. */ |
| 172 | public EastNorth latlon2eastNorth(LatLon p) { return null; } |
| 173 | public LatLon eastNorth2latlon(EastNorth p) { return null; } |
| 174 | |
| 175 | public double getPuwgCentralMeridianDeg() { return Epsg2180CentralMeridian; } |
| 176 | public double getPuwgCentralMeridian() { return Math.toRadians(Epsg2180CentralMeridian); } |
| 177 | public double getPuwgFalseEasting() { return Epsg2180FalseEasting; } |
| 178 | public double getPuwgFalseNorthing() { return Epsg2180FalseNorthing; } |
| 179 | public double getPuwgScaleFactor() { return Epsg2180ScaleFactor; } |
| 180 | |
| 181 | public double getDefaultZoomInPPD() { |
| 182 | // This will set the scale bar to about 100 km |
| 183 | return 0.009; |
| 184 | } |
| 185 | |
| 186 | public String eastToString(EastNorth p) { |
| 187 | return decFormatter.format(p.east()); |
| 188 | } |
| 189 | |
| 190 | public String northToString(EastNorth p) { |
| 191 | return decFormatter.format(p.north()); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | abstract class Puwg2000 implements PuwgData { |
| 196 | |
| 197 | final private double PuwgFalseEasting = 500000.0; |
| 198 | final private double PuwgFalseNorthing = 0; |
| 199 | final private double PuwgScaleFactor = 0.999923; |
| 200 | final private double[] Puwg2000CentralMeridian = {15.0, 18.0, 21.0, 24.0}; |
| 201 | final private String[] Puwg2000Code = { "EPSG:2176", "EPSG:2177", "EPSG:2178", "EPSG:2179"}; |
| 202 | final private String[] Puwg2000CDName = { "epsg2176", "epsg2177", "epsg2178", "epsg2179"}; |
| 203 | private static DecimalFormat decFormatter = new DecimalFormat("###0.00"); |
| 204 | |
| 205 | @Override public String toString() { |
| 206 | return tr("PUWG 2000 Zone {0} (Poland)", Integer.toString(getZone())); |
| 207 | } |
| 208 | |
| 209 | public String toCode() { |
| 210 | return Puwg2000Code[getZoneIndex()]; |
| 211 | } |
| 212 | |
| 213 | public String getCacheDirectoryName() { |
| 214 | return Puwg2000CDName[getZoneIndex()]; |
| 215 | } |
| 216 | |
| 217 | public Bounds getWorldBoundsLatLon() |
| 218 | { |
| 219 | return new Bounds( |
| 220 | new LatLon(49.00, (3 * getZone()) - 1.5), |
| 221 | new LatLon(54.84, (3 * getZone()) + 1.5)); |
| 222 | } |
| 223 | |
| 224 | /* These two MUST NOT be used. Use Puwg implementation instead. */ |
| 225 | public EastNorth latlon2eastNorth(LatLon p) { return null; } |
| 226 | public LatLon eastNorth2latlon(EastNorth p) { return null; } |
| 227 | |
| 228 | public double getPuwgCentralMeridianDeg() { return getZone() * 3.0; } |
| 229 | public double getPuwgCentralMeridian() { return Math.toRadians(getZone() * 3.0); } |
| 230 | public double getPuwgFalseNorthing() { return PuwgFalseNorthing;} |
| 231 | public double getPuwgFalseEasting() { return 1e6 * getZone() + PuwgFalseEasting; } |
| 232 | public double getPuwgScaleFactor() { return PuwgScaleFactor; } |
| 233 | public abstract int getZone(); |
| 234 | |
| 235 | public int getZoneIndex() { return getZone() - 5; } |
| 236 | |
| 237 | public double getDefaultZoomInPPD() { |
| 238 | // This will set the scale bar to about 100 km |
| 239 | return 0.009; |
| 240 | } |
| 241 | |
| 242 | public String eastToString(EastNorth p) { |
| 243 | return Integer.toString(getZone()) + decFormatter.format(p.east()); |
| 244 | } |
| 245 | |
| 246 | public String northToString(EastNorth p) { |
| 247 | return decFormatter.format(p.north()); |
| 248 | } |
| 249 | |
| 250 | } |
| 251 | |
| 252 | class Epsg2176 extends Puwg2000 implements Projection { |
| 253 | final private int PuwgZone = 5; |
| 254 | |
| 255 | public int getZone() { return PuwgZone; } |
| 256 | } |
| 257 | |
| 258 | class Epsg2177 extends Puwg2000 implements Projection { |
| 259 | final private int PuwgZone = 6; |
| 260 | |
| 261 | public int getZone() { return PuwgZone; } |
| 262 | } |
| 263 | |
| 264 | class Epsg2178 extends Puwg2000 implements Projection { |
| 265 | final private int PuwgZone = 7; |
| 266 | |
| 267 | public int getZone() { return PuwgZone; } |
| 268 | } |
| 269 | |
| 270 | class Epsg2179 extends Puwg2000 implements Projection { |
| 271 | final private int PuwgZone = 8; |
| 272 | |
| 273 | public int getZone() { return PuwgZone; } |
| 274 | } |