// License: GPL. Copyright 2007 by Immanuel Scholz and others
// 2009 by Ćukasz Stelmach
package org.openstreetmap.josm.data.projection;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.GridBagLayout;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.Collections;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.openstreetmap.josm.data.Bounds;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.tools.GBC;
/**
* PUWG 1992 and 2000 are the official cordinate systems in Poland.
* They use the same math as UTM only with different constants.
*
* @author steelman
*/
public class Puwg extends UTM implements Projection,ProjectionSubPrefs {
public static final int DEFAULT_ZONE = 0;
private int zone = DEFAULT_ZONE;
private static PuwgData[] Zones = new PuwgData[]{
new Epsg2180(),
new Epsg2176(),
new Epsg2177(),
new Epsg2178(),
new Epsg2179()
};
private static DecimalFormat decFormatter = new DecimalFormat("###0");
@Override
public EastNorth latlon2eastNorth(LatLon p) {
PuwgData z = Zones[zone];
double easting = z.getPuwgFalseEasting();
double northing = z.getPuwgFalseNorthing();
double scale = z.getPuwgScaleFactor();
double center = z.getPuwgCentralMeridian(); /* in radians */
EastNorth a = mapLatLonToXY(Math.toRadians(p.lat()), Math.toRadians(p.lon()), center);
return new EastNorth(a.east() * scale + easting, a.north() * scale + northing);
}
@Override
public LatLon eastNorth2latlon(EastNorth p) {
PuwgData z = Zones[zone];
double easting = z.getPuwgFalseEasting();
double northing = z.getPuwgFalseNorthing();
double scale = z.getPuwgScaleFactor();
double center = z.getPuwgCentralMeridian(); /* in radians */
return mapXYToLatLon((p.east() - easting)/scale, (p.north() - northing)/scale, center);
}
@Override public String toString() {
return tr("PUWG (Poland)");
}
@Override
public String toCode() {
return Zones[zone].toCode();
}
@Override
public int hashCode() {
return getClass().getName().hashCode()+zone; // our only real variable
}
@Override
public String getCacheDirectoryName() {
return Zones[zone].getCacheDirectoryName();
}
@Override
public Bounds getWorldBoundsLatLon() {
return Zones[zone].getWorldBoundsLatLon();
}
@Override
public double getDefaultZoomInPPD() {
// This will set the scale bar to about 100 km
return 0.009;
}
public String eastToString(EastNorth p) {
return decFormatter.format(p.east());
}
public String northToString(EastNorth p) {
return decFormatter.format(p.north());
}
@Override
public void setupPreferencePanel(JPanel p) {
JComboBox prefcb = new JComboBox(Puwg.Zones);
prefcb.setSelectedIndex(zone);
p.setLayout(new GridBagLayout());
p.add(new JLabel(tr("PUWG Zone")), GBC.std().insets(5,5,0,5));
p.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
/* Note: we use component position 2 below to find this again */
p.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL));
p.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
}
@Override
public Collection<String> getPreferences(JPanel p) {
Object prefcb = p.getComponent(2);
if(!(prefcb instanceof JComboBox))
return null;
int zone = ((JComboBox)prefcb).getSelectedIndex();
return Collections.singleton((Puwg.Zones[zone]).toCode());
}
@Override
public Collection<String> getPreferencesFromCode(String code)
{
for (Projection p : Puwg.Zones)
{
if(code.equals(p.toCode()))
return Collections.singleton(code);
}
return null;
}
@Override
public void setPreferences(Collection<String> args)
{
zone = DEFAULT_ZONE;
if(args != null)
{
try {
for(String s : args)
{
for (int i=0; i < Puwg.Zones.length; ++i)
if(s.equals(Zones[i].toCode())) {
zone = i;
}
break;
}
} catch (NullPointerException e) {}
}
}
}
interface PuwgData extends Projection {
public double getPuwgCentralMeridianDeg();
public double getPuwgCentralMeridian();
public double getPuwgFalseEasting();
public double getPuwgFalseNorthing();
public double getPuwgScaleFactor();
}
class Epsg2180 implements PuwgData {
private static final double Epsg2180FalseEasting = 500000.0; /* y */
private static final double Epsg2180FalseNorthing = -5300000.0; /* x */
private static final double Epsg2180ScaleFactor = 0.9993;
private static final double Epsg2180CentralMeridian = 19.0;
private static DecimalFormat decFormatter = new DecimalFormat("###0");
@Override public String toString() {
return tr("PUWG 1992 (Poland)");
}
public String toCode() {
return "EPSG:2180";
}
public String getCacheDirectoryName() {
return "epsg2180";
}
public Bounds getWorldBoundsLatLon()
{
return new Bounds(
new LatLon(49.00, 14.12),
new LatLon(54.84, 24.15));
}
/* These two MUST NOT be used. Use Puwg implementation instead. */
public EastNorth latlon2eastNorth(LatLon p) { return null; }
public LatLon eastNorth2latlon(EastNorth p) { return null; }
public double getPuwgCentralMeridianDeg() { return Epsg2180CentralMeridian; }
public double getPuwgCentralMeridian() { return Math.toRadians(Epsg2180CentralMeridian); }
public double getPuwgFalseEasting() { return Epsg2180FalseEasting; }
public double getPuwgFalseNorthing() { return Epsg2180FalseNorthing; }
public double getPuwgScaleFactor() { return Epsg2180ScaleFactor; }
public double getDefaultZoomInPPD() {
// This will set the scale bar to about 100 km
return 0.009;
}
public String eastToString(EastNorth p) {
return decFormatter.format(p.east());
}
public String northToString(EastNorth p) {
return decFormatter.format(p.north());
}
}
abstract class Puwg2000 implements PuwgData {
private static final double PuwgFalseEasting = 500000.0;
private static final double PuwgFalseNorthing = 0;
private static final double PuwgScaleFactor = 0.999923;
//final private double[] Puwg2000CentralMeridian = {15.0, 18.0, 21.0, 24.0};
final private String[] Puwg2000Code = { "EPSG:2176", "EPSG:2177", "EPSG:2178", "EPSG:2179"};
final private String[] Puwg2000CDName = { "epsg2176", "epsg2177", "epsg2178", "epsg2179"};
private static DecimalFormat decFormatter = new DecimalFormat("###0.00");
@Override public String toString() {
return tr("PUWG 2000 Zone {0} (Poland)", Integer.toString(getZone()));
}
public String toCode() {
return Puwg2000Code[getZoneIndex()];
}
public String getCacheDirectoryName() {
return Puwg2000CDName[getZoneIndex()];
}
public Bounds getWorldBoundsLatLon()
{
return new Bounds(
new LatLon(49.00, (3 * getZone()) - 1.5),
new LatLon(54.84, (3 * getZone()) + 1.5));
}
/* These two MUST NOT be used. Use Puwg implementation instead. */
public EastNorth latlon2eastNorth(LatLon p) { return null; }
public LatLon eastNorth2latlon(EastNorth p) { return null; }
public double getPuwgCentralMeridianDeg() { return getZone() * 3.0; }
public double getPuwgCentralMeridian() { return Math.toRadians(getZone() * 3.0); }
public double getPuwgFalseNorthing() { return PuwgFalseNorthing;}
public double getPuwgFalseEasting() { return 1e6 * getZone() + PuwgFalseEasting; }
public double getPuwgScaleFactor() { return PuwgScaleFactor; }
public abstract int getZone();
public int getZoneIndex() { return getZone() - 5; }
public double getDefaultZoomInPPD() {
// This will set the scale bar to about 100 km
return 0.009;
}
public String eastToString(EastNorth p) {
return Integer.toString(getZone()) + decFormatter.format(p.east());
}
public String northToString(EastNorth p) {
return decFormatter.format(p.north());
}
}
class Epsg2176 extends Puwg2000 implements Projection {
private static final int PuwgZone = 5;
@Override
public int getZone() { return PuwgZone; }
}
class Epsg2177 extends Puwg2000 implements Projection {
private static final int PuwgZone = 6;
@Override
public int getZone() { return PuwgZone; }
}
class Epsg2178 extends Puwg2000 implements Projection {
private static final int PuwgZone = 7;
@Override
public int getZone() { return PuwgZone; }
}
class Epsg2179 extends Puwg2000 implements Projection {
private static final int PuwgZone = 8;
@Override
public int getZone() { return PuwgZone; }
}