//********************************************************************** // // <copyright> // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // </copyright> // ********************************************************************** // // $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/proj/coords/UPSPoint.java,v $ // $RCSfile: UPSPoint.java,v $ // $Revision: 1.9 $ // $Date: 2009/02/25 22:34:04 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.proj.coords; /** * Class UPSPoint. * <p> * This class encapsulates a UPS point. * <p> * UPS is known as (Universal Polar Stereographic). * <p> * UPS is a coordinate system of Earth's polar regions north of * <p> * 84 degrees north, and south of 80 degrees south. * <p> * This class defaults to WGS-1984. * <p> * * @author Bob Hayes */ public class UPSPoint { /** Easting */ protected double easting; /** Northing */ protected double northing; /** Hemisphere */ // protected boolean southernHemisphere; private double Degree = Math.PI / 180.0; // WGS-1984: 6378137.0, 298.257223563 0.00669438d /** Constructor for the UPSPoint object */ public UPSPoint() { this.easting = 0; this.northing = 0; // southernHemisphere = false; } /** * Constructor for the UPSPoint object * * @param easting easting * @param northing northing */ public UPSPoint(double easting, double northing) { this.easting = easting; this.northing = northing; // southernHemisphere = southern; } /** * Static method to create a UPSPoint object from lat/lon coordinates. * Method avoids conflict with (double, double) constructor. * * @param lat latitude in decimal degrees * @param lon longitude in decimal degrees */ public static UPSPoint createUPSPoint(double lat, double lon) { UPSPoint ups = new UPSPoint(); ups.toUPS(lat, lon); return ups; } /** * Constructor for the UPSPoint object * * @param llpt LatLonPoint */ public UPSPoint(LatLonPoint llpt) { this.toUPS(llpt.getY(), llpt.getX()); } /** * Converts a lat-lon pair to UPS point * * @param lat latitude in decimal degrees * @param lon longitude in decimal degrees */ public void toUPS(double lat, double lon) { double a = 0; double t = 0; double e = 0; double es = 0; double rho = 0; double x; double y; final double k0 = 0.994; double lambda = lon * Degree; double phi = Math.abs(lat * Degree); // double phi = (lat * Degree); a = 6378137.0; es = 0.00669438d; e = Math.sqrt(es); t = Math.tan(Math.PI / 4.0 - phi / 2.0) / Math.pow((1.0 - e * Math.sin(phi)) / (1.0 + e * Math.sin(phi)), (e / 2.0)); rho = 2.0 * a * k0 * t / Math.sqrt(Math.pow(1.0 + e, 1.0 + e) * Math.pow(1.0 - e, 1.0 - e)); x = rho * Math.sin(lambda); y = rho * Math.cos(lambda); if (lat > 0.0) { // Northern hemisphere y = -(y); // southernHemisphere = false; } x += 2.0e6; // Add in false easting and northing y += 2.0e6; easting = x; northing = y; } /* * --------------------------------------------------------------------------------- */ /** * Convert a UPSPoint to a LatLonPoint * * @return returns a LatLonPoint */ public LatLonPoint toLatLonPoint(boolean southernHemisphere) { LatLonPoint llp = new LatLonPoint.Double(); double lon = 0; double lat = 0; double a = 0; double es = 0; double e = 0; double t = 0; double rho = 0; double x = easting; double y = northing; final double k0 = 0.994; a = 6378137.0; es = 0.00669438d; e = Math.sqrt(es); x -= 2.0e6; // Remove false easting and northing y -= 2.0e6; rho = Math.sqrt(x * x + y * y); t = rho * Math.sqrt(Math.pow(1.0 + e, 1.0 + e) * Math.pow(1.0 - e, 1.0 - e)) / (2.0 * a * k0); lat = calcPhi(e, t); lat /= Degree; if (y != 0.0) { t = Math.atan(Math.abs(x / y)); } else { t = Math.PI / 2.0; if (x < 0.0) { t = -t; } } if (southernHemisphere == false) { y = -y; } else { lat = -lat; } if (y < 0.0) { t = Math.PI - t; } if (x < 0.0) { t = -t; } lon = t / Degree; llp.setLatitude((float) lat); llp.setLongitude((float) lon); return llp; } /* * --------------------------------------------------------------------------------- */ /** * Sets the northing attribute * * @param northing The new northing value */ public void setNorthing(double northing) { this.northing = northing; } /** * Sets the easting attribute * * @param easting The new easting value */ public void setEasting(double easting) { this.easting = easting; } /** * Gets the easting attribute * * @return The easting value */ public double getNorthing() { return northing; } /** * Gets the easting attribute * * @return The easting value */ public double getEasting() { return easting; } /** * Description of the Method * * @return returns a string representation of the object */ public String toString() { return "Easting:" + easting + " Northing:" + northing; } /** * Calculate phi (latitude) * * @param e * @param t * @return phi */ static double calcPhi(double e, double t) { double phi = 0; double old = Math.PI / 2.0 - 2.0 * Math.atan(t); short maxIterations = 20; while ((Math.abs((phi - old) / phi) > 1.0e-8) && (maxIterations != 0)) { old = phi; phi = Math.PI / 2.0 - 2.0 * Math.atan(t * Math.pow((1.0 - e * Math.sin(phi)) / ((1.0 + e * Math.sin(phi))), (e / 2.0))); maxIterations--; } return phi; } /** * Tested against the NIMA calculator */ public static void main(String[] args) { // TEST1 - NORTH & WEST LatLonPoint llpt1 = new LatLonPoint.Double(87.00, -74.50); System.out.println(llpt1.toString()); UPSPoint ups = new UPSPoint(llpt1); System.out.println(ups.toString()); LatLonPoint llpt2 = ups.toLatLonPoint(false); System.out.println(llpt2.toString()); // TEST2 - SOUTH & EAST System.out.println("--------------------------------------------"); llpt1 = new LatLonPoint.Double(-89.00, 110.50); System.out.println(llpt1.toString()); ups = new UPSPoint(llpt1); System.out.println(ups.toString()); llpt2 = ups.toLatLonPoint(true); System.out.println(llpt2.toString()); } }