• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * To change this template, choose Tools | Templates
3  * and open the template in the editor.
4  */
5 package jme3tools.navigation;
6 
7 import java.text.DecimalFormat;
8 
9 /**
10  * Coordinate class. Used to store a coordinate in [DD]D MM.M format.
11  *
12  * @author Benjamin Jakobus (based on JMarine by Benjamin Jakobus and Cormac Gebruers)
13  * @version 1.0
14  * @since 1.0
15  */
16 public class Coordinate {
17 
18     /* the degree part of the position (+ N/E, -W/S) */
19     private int deg;
20 
21     /* the decimals of a minute */
22     private double minsDecMins;
23 
24     /* the coordinate as a decimal*/
25     private double decCoordinate;
26 
27     /* whether this coordinate is a latitude or a longitude: : LAT==0, LONG==1  */
28     private int coOrdinate;
29 
30     /* The minutes trailing decimal precision to use for positions */
31     public static final int MINPRECISION = 4;
32     /* The degrees trailing decimal precision to use for positions */
33     public static final int DEGPRECISION = 7;
34 
35     /* typeDefs for coOrdinates */
36     public static final int LAT = 0;
37     public static final int LNG = 1;
38 
39     /* typeDefs for quadrant */
40     public static final int E = 0;
41     public static final int S = 1;
42     public static final int W = 2;
43     public static final int N = 3;
44 
45     /**
46      * Constructor
47      *
48      * @param deg
49      * @param minsDecMins
50      * @param coOrdinate
51      * @param quad
52      * @throws InvalidPositionException
53      * @since 1.0
54      */
Coordinate(int deg, float minsDecMins, int coOrdinate, int quad)55     public Coordinate(int deg, float minsDecMins, int coOrdinate,
56             int quad) throws InvalidPositionException {
57         buildCoOrdinate(deg, minsDecMins, coOrdinate, quad);
58         if (verify()) {
59         } else {
60             throw new InvalidPositionException();
61         }
62     }
63 
64     /**
65      * Constructor
66      * @param decCoordinate
67      * @param coOrdinate
68      * @throws InvalidPositionException
69      * @since 1.0
70      */
Coordinate(double decCoordinate, int coOrdinate)71     public Coordinate(double decCoordinate, int coOrdinate) throws InvalidPositionException {
72         DecimalFormat form = new DecimalFormat("#.#######");
73 
74         this.decCoordinate = decCoordinate;
75         this.coOrdinate = coOrdinate;
76         if (verify()) {
77             deg = new Float(decCoordinate).intValue();
78             if (deg < 0) {
79                 minsDecMins = Double.parseDouble(form.format((Math.abs(decCoordinate) - Math.abs(deg)) * 60));
80             } else {
81                 minsDecMins = Double.parseDouble(form.format((decCoordinate - deg) * 60));
82             }
83         } else {
84             throw new InvalidPositionException();
85         }
86     }
87 
88     /**
89      * This constructor takes a coordinate in the ALRS formats i.e
90      * 38∞31.64'N for lat, and 28∞19.12'W for long
91      * Note: ALRS positions are occasionally written with the decimal minutes
92      * apostrophe in the 'wrong' place and with an non CP1252 compliant decimal character.
93      * This issue has to be corrected in the source database
94      * @param coOrdinate
95      * @throws InvalidPositionException
96      * @since 1.0
97      */
Coordinate(String coOrdinate)98     public Coordinate(String coOrdinate) throws InvalidPositionException {
99         //firstly split it into its component parts and dispose of the unneeded characters
100         String[] items = coOrdinate.split("°");
101         int deg = Integer.valueOf(items[0]);
102 
103         items = items[1].split("'");
104         float minsDecMins = Float.valueOf(items[0]);
105         char quad = items[1].charAt(0);
106 
107         switch (quad) {
108             case 'N':
109                 buildCoOrdinate(deg, minsDecMins, Coordinate.LAT, Coordinate.N);
110                 break;
111             case 'S':
112                 buildCoOrdinate(deg, minsDecMins, Coordinate.LAT, Coordinate.S);
113                 break;
114             case 'E':
115                 buildCoOrdinate(deg, minsDecMins, Coordinate.LNG, Coordinate.E);
116                 break;
117             case 'W':
118                 buildCoOrdinate(deg, minsDecMins, Coordinate.LNG, Coordinate.W);
119         }
120         if (verify()) {
121         } else {
122             throw new InvalidPositionException();
123         }
124     }
125 
126     /**
127      * Prints out a coordinate as a string
128      * @return the coordinate in decimal format
129      * @since 1.0
130      */
toStringDegMin()131     public String toStringDegMin() {
132         String str = "";
133         String quad = "";
134         StringUtil su = new StringUtil();
135         switch (coOrdinate) {
136             case LAT:
137                 if (decCoordinate >= 0) {
138                     quad = "N";
139                 } else {
140                     quad = "S";
141                 }
142                 str = su.padNumZero(Math.abs(deg), 2);
143                 str += "\u00b0" + su.padNumZero(Math.abs(minsDecMins), 2, MINPRECISION) + "'" + quad;
144                 break;
145             case LNG:
146                 if (decCoordinate >= 0) {
147                     quad = "E";
148                 } else {
149                     quad = "W";
150                 }
151                 str = su.padNumZero(Math.abs(deg), 3);
152                 str += "\u00b0" + su.padNumZero(Math.abs(minsDecMins), 2, MINPRECISION) + "'" + quad;
153                 break;
154         }
155         return str;
156     }
157 
158     /**
159      * Prints out a coordinate as a string
160      * @return the coordinate in decimal format
161      * @since 1.0
162      */
toStringDec()163     public String toStringDec() {
164         StringUtil u = new StringUtil();
165         switch (coOrdinate) {
166             case LAT:
167                 return u.padNumZero(decCoordinate, 2, DEGPRECISION);
168             case LNG:
169                 return u.padNumZero(decCoordinate, 3, DEGPRECISION);
170         }
171         return "error";
172     }
173 
174     /**
175      * Returns the coordinate's decimal value
176      * @return float the decimal value of the coordinate
177      * @since 1.0
178      */
decVal()179     public double decVal() {
180         return decCoordinate;
181     }
182 
183     /**
184      * Determines whether a decimal position is valid
185      * @return result of validity test
186      * @since 1.0
187      */
verify()188     private boolean verify() {
189         switch (coOrdinate) {
190             case LAT:
191                 if (Math.abs(decCoordinate) > 90.0) {
192                     return false;
193                 }
194                 break;
195 
196             case LNG:
197                 if (Math.abs(decCoordinate) > 180) {
198                     return false;
199                 }
200         }
201         return true;
202     }
203 
204     /**
205      * Populate this object by parsing the arguments to the function
206      * Placed here to allow multiple constructors to use it
207      * @since 1.0
208      */
buildCoOrdinate(int deg, float minsDecMins, int coOrdinate, int quad)209     private void buildCoOrdinate(int deg, float minsDecMins, int coOrdinate,
210             int quad) {
211         NumUtil nu = new NumUtil();
212 
213         switch (coOrdinate) {
214             case LAT:
215                 switch (quad) {
216                     case N:
217                         this.deg = deg;
218                         this.minsDecMins = minsDecMins;
219                         this.coOrdinate = coOrdinate;
220                         decCoordinate = nu.Round(this.deg + (float) this.minsDecMins / 60, Coordinate.MINPRECISION);
221                         break;
222 
223                     case S:
224                         this.deg = -deg;
225                         this.minsDecMins = minsDecMins;
226                         this.coOrdinate = coOrdinate;
227                         decCoordinate = nu.Round(this.deg - ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
228                 }
229 
230             case LNG:
231                 switch (quad) {
232                     case E:
233                         this.deg = deg;
234                         this.minsDecMins = minsDecMins;
235                         this.coOrdinate = coOrdinate;
236                         decCoordinate = nu.Round(this.deg + ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
237                         break;
238 
239                     case W:
240                         this.deg = -deg;
241                         this.minsDecMins = minsDecMins;
242                         this.coOrdinate = coOrdinate;
243                         decCoordinate = nu.Round(this.deg - ((float) this.minsDecMins / 60), Coordinate.MINPRECISION);
244                 }
245         }
246     }
247 }
248