Source code: jflight/model/BaseWpt.java
1
2 /*
3 Project name: JFlight
4 Hosted at: www.sourceforge.net
5 Homepage: jflight.sourceforge.net
6 Licence: GNU public licence (GPL)
7 Filename: BaseWpt.java
8 Package: jflight
9 */
10
11 package jflight.model;
12
13 import java.lang.Math;
14 import java.text.DecimalFormat;
15
16 /**
17 Waypoint data types, device independent
18
19
20 @since JDK1.1.x
21 @author R?diger Bien
22
23 CVS-section:
24 @file_version $Revision: 1.8 $
25
26 */
27
28 /** Pure waypoint-definition, just the coordinates */
29 public class BaseWpt {
30
31 /** latitude in degrees */
32 public double dlat;
33 /** longitude in degrees */
34 public double dlon;
35
36 /** coordinate in radians */
37 public double rlat;
38 /** coordinate in radians */
39 public double rlon;
40
41 // heighht in meters
42 public int height;
43
44 public static DecimalFormat longiFormat = new DecimalFormat("000.00000");
45 public static DecimalFormat latiFormat = new DecimalFormat("00.00000");
46
47 /**
48 * Constructor BaseWpt
49 *
50 * Sets coordinate to zero.
51 */
52 public BaseWpt() {
53 dlat = dlon = 0.0;
54 rlat = rlon = 0.0;
55 }
56
57 /**
58 * Constructor BaseWpt
59 *
60 * Sets coordinate to specified value.
61 */
62 public BaseWpt(double lat, double lon) {
63 dlat = lat;
64 dlon = lon;
65 rlat = dlat * Math.PI * 2 / 360;
66 rlon = dlon * Math.PI * 2 / 360;
67 }
68
69 /**
70 * Constructor BaseWpt
71 *
72 * Sets coordinate and height to specified value.
73 */
74 public BaseWpt(double lat, double lon, int height) {
75 dlat = lat;
76 dlon = lon;
77 rlat = dlat * Math.PI * 2 / 360;
78 rlon = dlon * Math.PI * 2 / 360;
79 this.height = height;
80 }
81 /**
82 * Method toString
83 *
84 *
85 * @return unformatted coordinates
86 *
87 */
88 public String toString() {
89
90 // unformatted !
91 return new String(dlat + " " + dlon + " " + height );
92 // return new String(dlat + " " + dlon + " " + rlat + " " + rlon);
93 }
94
95
96
97 /**
98 * Method dist <br>
99 * Calculates the distance between two waypoints
100 *
101 * @return distance in km
102 *
103 */
104 public double dist( BaseWpt wpt ) {
105 double dist,
106 d1,d2; // intermediate results
107
108 d1 = Math.sin((rlat-wpt.rlat)/2);
109 d1 = Math.pow(d1,2.0);
110 d2 = Math.cos(rlat)*Math.cos(wpt.rlat)*Math.pow(Math.sin(((rlon-wpt.rlon)/2)),2.0);
111 dist = 2*Math.asin(Math.sqrt(d1+d2));
112 dist = dist * 360 * 111.192926645 / (Math.PI * 2);
113 //System.out.println("distance = " + dist);
114 return dist;
115 }
116
117 /**
118 * Method tc<br>
119 * Course between points: We obtain the initial course, tc1, (at point 1) from point 1 to point 2 by the following. <br>
120 * For starting points other than the poles: <br>
121 * IF sin(lon2-lon1)<0 <br>
122 * tc1= acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1))) <br>
123 * ELSE <br>
124 * tc1=2*pi-acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1))) <br>
125 * ENDIF <br>
126 * Def.: wpt1 = "from wpt", wpt2 = "to wpt"<br>
127 * Could be more accurate !!!<br><br>
128 * @return true course (angle) in degrees
129 *
130 */
131 public double tc( BaseWpt wpt ) {
132 double dst, tc;
133 double d1,d2; // intermediate results
134
135 // we need the distance first:
136 d1 = Math.sin((rlat-wpt.rlat)/2);
137 d1 = Math.pow(d1,2.0);
138 d2 = Math.cos(rlat)*Math.cos(wpt.rlat)*Math.pow(Math.sin(((rlon-wpt.rlon)/2)),2.0);
139 dst = 2*Math.asin(Math.sqrt(d1+d2));
140 if( dst != 0 ) {
141 tc = (Math.sin(wpt.rlat)-(Math.sin(rlat)*Math.cos(dst)));
142 tc = tc / (Math.sin(dst)*Math.cos(rlat));
143 tc = Math.acos(tc);
144 if( Math.sin(wpt.rlon-rlon) < 0 ) {
145 tc = 2*Math.PI-tc;
146 }
147 tc = tc * 360 / (Math.PI * 2);
148 } else {
149 tc = 0;
150 }
151 // System.out.println("tc =" + tc);
152 return tc;
153 }
154
155 /** modulo function; for d2 > 0 */
156 public static double mod(double d1, double d2 ) {
157 double m;
158
159 if( d2 == 0 ) return 0; // wrong, but safe ;-)
160
161 if( d1 >= 0 ) {
162 m = d1 - d2*Math.floor(d1/d2);
163 }
164 else {
165 m = d1 - d2*(Math.floor(d1/d2)+1);
166 }
167 // System.out.println("mod(): " + d1 + " " + d2 + " " + m );
168 return m;
169 }
170
171 /**
172 * Method poc ("point on course")<br>
173 * Calculates a waypoint on the course<br>
174 * A point {lat,lon} is a distance d out on the tc radial from point 1 if:<br>
175 * lat=asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))<br>
176 * IF (cos(lat)=0)<br>
177 * lon=lon1 // endpoint a pole<br>
178 * ELSE<br>
179 * lon=mod(lon1-asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi<br>
180 * wrong? ->
181 * lon=mod(lon1+asin(sin(tc)*sin(d)/cos(lat))+pi,2*pi)-pi<br>
182 * ENDIF<br>
183 * This algorithm is limited to distances such that dlon <pi/2, i.e those that
184 * extend around less than one quarter of the circumference of the earth in longitude. <br>
185 * @return BaseWpt
186 *
187 */
188 public BaseWpt poc( double dist, double tc ) {
189 BaseWpt wpt = new BaseWpt();
190
191 if(dist>0) {
192 dist = dist * (Math.PI * 2)/ (360 * 111.192926645); // rad
193 tc = tc * (Math.PI * 2)/ 360; // rad
194 wpt.rlat = Math.asin(Math.sin(rlat)*Math.cos(dist)+Math.cos(rlat)*Math.sin(dist)*Math.cos(tc));
195 wpt.rlon = mod(rlon+(Math.asin(Math.sin(tc)*Math.sin(dist)/Math.cos(rlat)))+Math.PI,2*Math.PI)-Math.PI;
196 wpt.dlat = wpt.rlat * 360 / (Math.PI * 2);
197 wpt.dlon = wpt.rlon * 360 / (Math.PI * 2);
198 } else {
199 wpt.rlat = rlat;
200 wpt.rlon = rlon;
201 wpt.dlat = dlat;
202 wpt.dlon = dlon;
203 }
204 // System.out.println("poc(): " + wpt.toString() );
205 return wpt;
206 }
207
208 /** test coordinates only */
209 public boolean equalsCrdNearly(Object anObject) {
210
211 if (!(anObject instanceof BaseWpt)) return false;
212
213 // cast Object to Wpt:
214 BaseWpt aWpt= (BaseWpt)anObject;
215 // no equals()-method for basic types!
216 return ( ((aWpt.dlat/dlat-1)<0.01)
217 && ((aWpt.dlon/dlon-1)<0.01) );
218 }
219
220 /**
221 * Method getLatAsDDMMmmm
222 *
223 * @return the latitude value as DDMMmmm value
224 *
225 */
226 public double getLatAsDDMMmmm()
227 {
228 return degreeAsDDMMmmm(this.dlat);
229 }
230
231 /**
232 * Method getLatAsDDMMmmm
233 *
234 * @return the longitude value as DDMMmmm value
235 *
236 */
237 public double getLonAsDDMMmmm()
238 {
239 return degreeAsDDMMmmm(this.dlon);
240 }
241
242
243 /**
244 * Method getLatAsDDMMmmm
245 *
246 * @return the latitude value as DDMMmmm value
247 *
248 */
249 public int[] getLatSeparatedToDDMMmmm()
250 {
251 int[] values = new int[3];
252 String ddMMmmm = this.latiFormat.format(degreeAsDDMMmmm(this.dlat));
253 values[0] = Integer.parseInt(ddMMmmm.substring(0,2));
254 values[1] = Integer.parseInt(ddMMmmm.substring(3,5));
255 values[2] = Integer.parseInt(ddMMmmm.substring(5,8));
256 return values;
257 }
258
259 /**
260 * Method getLatAsDDMMmmm
261 *
262 * @return the longitude value as DDMMmmm value
263 *
264 */
265 public int[] getLonSeparatedToDDMMmmm()
266 {
267 int[] values = new int[3];
268 String dddMMmmm = this.longiFormat.format(degreeAsDDMMmmm(this.dlon));
269 values[0] = Integer.parseInt(dddMMmmm.substring(0,3));
270 values[1] = Integer.parseInt(dddMMmmm.substring(4,6));
271 values[2] = Integer.parseInt(dddMMmmm.substring(6,9));
272 return values;
273 }
274
275
276 private double degreeAsDDMMmmm(double value)
277 {
278 double gz = Math.floor(value);
279 double nk = value-gz;
280 nk *=(double)0.6;
281 return (gz+nk);
282 }
283
284 /** Getter for property dlat.
285 * @return Value of property dlat.
286 */
287 public double getDlat() {
288 return dlat;
289 }
290
291 /** Setter for property dlat.
292 * @param dlat New value of property dlat.
293 */
294 public void setDlat(double dlat) {
295 this.dlat = dlat;
296 }
297
298 /** Getter for property dlon.
299 * @return Value of property dlon.
300 */
301 public double getDlon() {
302 return dlon;
303 }
304
305 /** Setter for property dlon.
306 * @param dlon New value of property dlon.
307 */
308 public void setDlon(double dlon) {
309 this.dlon = dlon;
310 }
311
312 /** Getter for property rlat.
313 * @return Value of property rlat.
314 */
315 public double getRlat() {
316 return rlat;
317 }
318
319 /** Setter for property rlat.
320 * @param rlat New value of property rlat.
321 */
322 public void setRlat(double rlat) {
323 this.rlat = rlat;
324 }
325
326 /** Getter for property rlon.
327 * @return Value of property rlon.
328 */
329 public double getRlon() {
330 return rlon;
331 }
332
333 /** Setter for property rlon.
334 * @param rlon New value of property rlon.
335 */
336 public void setRlon(double rlon) {
337 this.rlon = rlon;
338 }
339
340 /** Getter for property height.
341 * @return Value of property height.
342 */
343 public int getHeight() {
344 if( height < 20000 ) {
345 return height;
346 }
347 else return height-20000;
348 }
349
350 /** Setter for property height.
351 * @param height New value of property height.
352 */
353 public void setHeight(int height) {
354 this.height = height;
355 }
356
357 }
358
359