/*
GNU General Public License
CacheWolf is a software for PocketPC, Win and Linux that
enables paperless caching.
It supports the sites geocaching.com and opencaching.de
Copyright (C) 2006 CacheWolf development team
See http://www.cachewolf.de/ for more information.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package CacheWolf.navi;
import CacheWolf.database.CWPoint;
import CacheWolf.database.CoordinatePoint;
public final class ProjectedPoint {
public static final LambertProjection PJ_AUSTRIAN_LAMBERT_OLD = new LambertProjection(TransformCoordinates.EPSG_AUSTRIAN_LAMBERT_OLD, TransformCoordinates.BESSEL);
public static final LambertProjection PJ_AUSTRIAN_LAMBERT_NEW = new LambertProjection(TransformCoordinates.EPSG_AUSTRIAN_LAMBERT_NEW, TransformCoordinates.WGS84);
public static final LambertProjection PJ_FRENCH_LAMBERT_NTF_II = new LambertProjection(TransformCoordinates.EPSG_FRENCH_LAMBERT_NTF_II, TransformCoordinates.CLARKE1880IGN);
public static final LambertProjection PJ_TEST = new LambertProjection(TransformCoordinates.EPSG_TEST, TransformCoordinates.CLARKE1866);
static {
PJ_AUSTRIAN_LAMBERT_OLD.setup(400000, 400000, 49.0, 46.0, 1, 47.5, 13.333333);
PJ_AUSTRIAN_LAMBERT_NEW.setup(400000, 400000, 49.0, 46.0, 1, 47.5, 13.333333);
PJ_FRENCH_LAMBERT_NTF_II.setup(2200000, 600000, 46.8, 46.8, 0.99987742, 46.8, 2.337229172 /*(2+20/60+14.025/3600) */);
PJ_TEST.setup(150000, 250000, 18, 18, 1, 18, -77);
}
public static final GkProjection PJ_GERMAN_GK = new GkProjection(TransformCoordinates.EPSG_GERMAN_GK2 - 2, 0, 500000, 3, 1000000, 0, 1, TransformCoordinates.BESSEL);
public static final GkProjection PJ_ITALIAN_GB = new GkProjection(TransformCoordinates.EPSG_ITALIAN_GB_EW1 - 1, 0, 500000, 6, 1000000, 0, 0.9996, TransformCoordinates.HAYFORD1909);
public static final UTMProjection PJ_UTM_WGS84 = new UTMProjection(TransformCoordinates.WGS84);
public static final UTMProjectionFixZone PJ_UTM_WGS84FZ = new UTMProjectionFixZone(TransformCoordinates.WGS84);
public double rawNorthing;
public double rawEasting;
// because it is not clear for routines from outside if the stripe number is included, make this available only through methods
public int zone;
public Projection projection;
public ProjectedPoint() {
}
public ProjectedPoint(Projection projection) {
this.projection = projection;
}
public ProjectedPoint(ProjectedPoint pp) {
rawNorthing = pp.rawNorthing;
rawEasting = pp.rawEasting;
zone = pp.zone;
this.projection = pp.projection;
}
public ProjectedPoint(CWPoint wgs84, Projection projection) {
this.projection = projection;
this.projection.project(wgs84, this);
}
/**
* automatically projects wgs84 onto epsg OR
* creates an ProjectedPoint with <br>
* lat/lon = northing/easting (in local notation)
*
* @param p Point to be projected OR lat/lon = northing/easting
* @param epsg_localsystem EPSG-Code OR ProjecetPoint.LOCALSYSTEM_XXX
* @param isProjected if true, p contains northing in lat and easting in lon <br>
* if false p will be projected to epsg
*/
public ProjectedPoint(CWPoint p, int epsg_localsystem, boolean isProjected, boolean isLocalsystem) {
if (isProjected)
set(p, null, epsg_localsystem, isLocalsystem);
else {
projection = (isLocalsystem ? getProjectionFromLs(epsg_localsystem) : getProjection(epsg_localsystem));
if (projection.epsgCode == 0) {
if (isLocalsystem)
projection.epsgCode = projection.getEpsgcode(epsg_localsystem);
else
projection.epsgCode = epsg_localsystem; // pass the epsg code to the projection if the projection works for several epsg code which are not directly one after the other
}
if (isLocalsystem)
projection.project(p, this);
else
projection.project(p, this, epsg_localsystem); // the epsg is required here because each zone has a different epsg, so the zone is already fixed
}
}
/**
* Set with local notation, incl. falsenorthing and -easting
* @param northing_
* @param easting_
* @param zone only put something here if the zone is not included in easting or northing and must be known, otherwise zone should be null
*/
public void set(CWPoint projected, String zone, int epsg_localsystem, boolean isLocalsystem) {
projection = (isLocalsystem ? getProjectionFromLs(epsg_localsystem) : getProjection(epsg_localsystem));
if (projection.epsgCode == 0) {
if (isLocalsystem)
projection.epsgCode = projection.getEpsgcode(epsg_localsystem);
else
projection.epsgCode = epsg_localsystem; // pass the epsg code to the projection if the projection works for several epsg code which are not directly one after the other
}
set(projected.latDec, projected.lonDec, zone);
}
/**
* easting measured in meters from stripe middle
* @return
*/
public double getRawEasting() {
return rawEasting;
}
/**
* northing measured in meters from stripe middle
* @return
*/
public double getRawNorthing() {
return rawNorthing;
}
public void setRaw(double northing_, double easting_) {
rawNorthing = northing_;
rawEasting = easting_;
}
static Projection getProjection(int epsg) {
if (epsg >= 25828 && epsg <= 25838)
return PJ_UTM_WGS84FZ;
switch (epsg) {
case TransformCoordinates.EPSG_AUSTRIAN_LAMBERT_OLD:
return PJ_AUSTRIAN_LAMBERT_OLD;
case TransformCoordinates.EPSG_AUSTRIAN_LAMBERT_NEW:
return PJ_AUSTRIAN_LAMBERT_NEW;
case TransformCoordinates.EPSG_GERMAN_GK2:
case TransformCoordinates.EPSG_GERMAN_GK3:
case TransformCoordinates.EPSG_GERMAN_GK4:
case TransformCoordinates.EPSG_GERMAN_GK5:
return PJ_GERMAN_GK;
case TransformCoordinates.EPSG_ITALIAN_GB_EW1:
case TransformCoordinates.EPSG_ITALIAN_GB_EW2:
return PJ_ITALIAN_GB;
case TransformCoordinates.EPSG_FRENCH_LAMBERT_NTF_II:
return PJ_FRENCH_LAMBERT_NTF_II;
case TransformCoordinates.LOCALSYSTEM_UTM_WGS84:
return PJ_UTM_WGS84;
case TransformCoordinates.EPSG_SwedenUTM:
return PJ_UTM_WGS84FZ;
default:
throw new IllegalArgumentException("ProjectedPoint.getProjection: epsg-code: " + epsg + "not supported");
}
}
private static Projection getProjectionFromLs(int localsystem) {
switch (localsystem) {
case TransformCoordinates.LOCALSYSTEM_AUSTRIAN_LAMBERT_OLD:
return PJ_AUSTRIAN_LAMBERT_OLD;
case TransformCoordinates.LOCALSYSTEM_AUSTRIAN_LAMBERT_NEW:
return PJ_AUSTRIAN_LAMBERT_NEW;
case TransformCoordinates.LOCALSYSTEM_GERMAN_GK:
return PJ_GERMAN_GK;
case TransformCoordinates.LOCALSYSTEM_ITALIAN_GB:
return PJ_ITALIAN_GB;
case TransformCoordinates.LOCALSYSTEM_FRANCE_LAMBERT_IIE:
return PJ_FRENCH_LAMBERT_NTF_II;
case TransformCoordinates.LOCALSYSTEM_UTM_WGS84:
return PJ_UTM_WGS84;
case TransformCoordinates.LOCALSYSTEM_SWEDEN:
return PJ_UTM_WGS84FZ;
case TransformCoordinates.LOCALSYSTEM_UTM28Nto38N:
return PJ_UTM_WGS84FZ;
default:
throw new IllegalArgumentException("ProjectedPoint(CWPoint, int): region " + localsystem + " not supported");
}
}
public ProjectedPoint(CWPoint p, String zone, int epsg_localsystem, boolean isLocalsystem) {
set(p, zone, epsg_localsystem, isLocalsystem);
}
public double getNorthing() {
return projection.getNorthing(this);
}
public double getEasting() {
return projection.getEasting(this);
}
public ProjectedPoint cloneIt() {
return new ProjectedPoint(this);
}
public CoordinatePoint toCoordinatePoint() {
return new CoordinatePoint(getNorthing(), getEasting());
}
public void setzone(int z) {
zone = z;
}
public int getZone() {
return zone;
}
public String getZoneString() {
if (projection.zoneSeperately)
return projection.getZone(this);
else
return "";
}
public int getEpsgCode() {
return projection.getEpsgcode(this);
}
/**
* Set with local notation, incl. falsenorthing and -easting
* @param northing_
* @param easting_
* @param zone only put something here if the zone is not included in easting or northing and must be known, otherwise zone should be null
*/
public void set(double northing_, double easting_, String zone) {
if (zone == null)
projection.set(northing_, easting_, this);
else
projection.set(northing_, easting_, zone, this);
}
public CWPoint unproject() {
return projection.unproject(this);
}
public String toString() {
return toString(2, "", " ");
}
public String toHumanReadableString() {
return toString(0, "", " ");
}
public String toString(int decimalplaces, String prefix, String seperator) {
ewe.sys.Double n = new ewe.sys.Double();
ewe.sys.Double e = new ewe.sys.Double();
n.set(projection.getNorthing(this));
e.set(projection.getEasting(this));
n.decimalPlaces = decimalplaces;
e.decimalPlaces = decimalplaces;
String z = (projection.zoneSeperately ? projection.getZone(this) + " " : "");
return z + prefix + e.toString().replace(',', '.') + seperator + n.toString().replace(',', '.');
}
/**
* shift the point
* @param meters positive to north (east), negative to south (west)
* @param direction 0 north-south, 1 east-west
*/
public void shift(double meters, int direction) {
switch (direction) { // TODO this works correctly only within a stripe/zone
case 0:
rawNorthing += meters;
return;
case 1:
rawEasting += meters;
return;
}
}
}