blob: 6e2c2d2383a98a1a60a39b8532de9341bc616357 [file] [log] [blame]
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jme3tools.navigation;
import java.text.DecimalFormat;
/**
* Coordinate class. Used to store a coordinate in [DD]D MM.M format.
*
* @author Benjamin Jakobus (based on JMarine by Benjamin Jakobus and Cormac Gebruers)
* @version 1.0
* @since 1.0
*/
public class Coordinate {
/* the degree part of the position (+ N/E, -W/S) */
private int deg;
/* the decimals of a minute */
private double minsDecMins;
/* the coordinate as a decimal*/
private double decCoordinate;
/* whether this coordinate is a latitude or a longitude: : LAT==0, LONG==1 */
private int coOrdinate;
/* The minutes trailing decimal precision to use for positions */
public static final int MINPRECISION = 4;
/* The degrees trailing decimal precision to use for positions */
public static final int DEGPRECISION = 7;
/* typeDefs for coOrdinates */
public static final int LAT = 0;
public static final int LNG = 1;
/* typeDefs for quadrant */
public static final int E = 0;
public static final int S = 1;
public static final int W = 2;
public static final int N = 3;
/**
* Constructor
*
* @param deg
* @param minsDecMins
* @param coOrdinate
* @param quad
* @throws InvalidPositionException
* @since 1.0
*/
public Coordinate(int deg, float minsDecMins, int coOrdinate,
int quad) throws InvalidPositionException {
buildCoOrdinate(deg, minsDecMins, coOrdinate, quad);
if (verify()) {
} else {
throw new InvalidPositionException();
}
}
/**
* Constructor
* @param decCoordinate
* @param coOrdinate
* @throws InvalidPositionException
* @since 1.0
*/
public Coordinate(double decCoordinate, int coOrdinate) throws InvalidPositionException {
DecimalFormat form = new DecimalFormat("#.#######");
this.decCoordinate = decCoordinate;
this.coOrdinate = coOrdinate;
if (verify()) {
deg = new Float(decCoordinate).intValue();
if (deg < 0) {
minsDecMins = Double.parseDouble(form.format((Math.abs(decCoordinate) - Math.abs(deg)) * 60));
} else {
minsDecMins = Double.parseDouble(form.format((decCoordinate - deg) * 60));
}
} else {
throw new InvalidPositionException();
}
}
/**
* This constructor takes a coordinate in the ALRS formats i.e
* 38∞31.64'N for lat, and 28∞19.12'W for long
* Note: ALRS positions are occasionally written with the decimal minutes
* apostrophe in the 'wrong' place and with an non CP1252 compliant decimal character.
* This issue has to be corrected in the source database
* @param coOrdinate
* @throws InvalidPositionException
* @since 1.0
*/
public Coordinate(String coOrdinate) throws InvalidPositionException {
//firstly split it into its component parts and dispose of the unneeded characters
String[] items = coOrdinate.split("°");
int deg = Integer.valueOf(items[0]);
items = items[1].split("'");
float minsDecMins = Float.valueOf(items[0]);
char quad = items[1].charAt(0);
switch (quad) {
case 'N':
buildCoOrdinate(deg, minsDecMins, Coordinate.LAT, Coordinate.N);
break;
case 'S':
buildCoOrdinate(deg, minsDecMins, Coordinate.LAT, Coordinate.S);
break;
case 'E':
buildCoOrdinate(deg, minsDecMins, Coordinate.LNG, Coordinate.E);
break;
case 'W':
buildCoOrdinate(deg, minsDecMins, Coordinate.LNG, Coordinate.W);
}
if (verify()) {
} else {
throw new InvalidPositionException();
}
}
/**
* Prints out a coordinate as a string
* @return the coordinate in decimal format
* @since 1.0
*/
public String toStringDegMin() {
String str = "";
String quad = "";
StringUtil su = new StringUtil();
switch (coOrdinate) {
case LAT:
if (decCoordinate >= 0) {
quad = "N";
} else {
quad = "S";
}
str = su.padNumZero(Math.abs(deg), 2);
str += "\u00b0" + su.padNumZero(Math.abs(minsDecMins), 2, MINPRECISION) + "'" + quad;
break;
case LNG:
if (decCoordinate >= 0) {
quad = "E";
} else {
quad = "W";
}
str = su.padNumZero(Math.abs(deg), 3);
str += "\u00b0" + su.padNumZero(Math.abs(minsDecMins), 2, MINPRECISION) + "'" + quad;
break;
}
return str;
}
/**
* Prints out a coordinate as a string
* @return the coordinate in decimal format
* @since 1.0
*/
public String toStringDec() {
StringUtil u = new StringUtil();
switch (coOrdinate) {
case LAT:
return u.padNumZero(decCoordinate, 2, DEGPRECISION);
case LNG:
return u.padNumZero(decCoordinate, 3, DEGPRECISION);
}
return "error";
}
/**
* Returns the coordinate's decimal value
* @return float the decimal value of the coordinate
* @since 1.0
*/
public double decVal() {
return decCoordinate;
}
/**
* Determines whether a decimal position is valid
* @return result of validity test
* @since 1.0
*/
private boolean verify() {
switch (coOrdinate) {
case LAT:
if (Math.abs(decCoordinate) > 90.0) {
return false;
}
break;
case LNG:
if (Math.abs(decCoordinate) > 180) {
return false;
}
}
return true;
}
/**
* Populate this object by parsing the arguments to the function
* Placed here to allow multiple constructors to use it
* @since 1.0
*/
private void buildCoOrdinate(int deg, float minsDecMins, int coOrdinate,
int quad) {
NumUtil nu = new NumUtil();
switch (coOrdinate) {
case LAT:
switch (quad) {
case N:
this.deg = deg;
this.minsDecMins = minsDecMins;
this.coOrdinate = coOrdinate;
decCoordinate = nu.Round(this.deg + (float) this.minsDecMins / 60, Coordinate.MINPRECISION);
break;
case S:
this.deg = -deg;
this.minsDecMins = minsDecMins;
this.coOrdinate = coOrdinate;
decCoordinate = nu.Round(this.deg - ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
}
case LNG:
switch (quad) {
case E:
this.deg = deg;
this.minsDecMins = minsDecMins;
this.coOrdinate = coOrdinate;
decCoordinate = nu.Round(this.deg + ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
break;
case W:
this.deg = -deg;
this.minsDecMins = minsDecMins;
this.coOrdinate = coOrdinate;
decCoordinate = nu.Round(this.deg - ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
}
}
}
}