| | 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 | } |