|
1 /** |
|
2 * Location.js |
|
3 * |
|
4 * Nokia Web Runtime Service API emulation |
|
5 * WRT v1.1 |
|
6 * |
|
7 * Copyright 2009 Nokia Corporation. All rights reserved. |
|
8 */ |
|
9 |
|
10 |
|
11 (function(){ |
|
12 |
|
13 var provider = 'Service.Location', |
|
14 Interface = 'ILocation'; |
|
15 |
|
16 /** |
|
17 * Landmark service |
|
18 */ |
|
19 var LocationService = function(){ |
|
20 this.GetLocation = __GetLocation; |
|
21 this.Trace = __Trace; |
|
22 this.Calculate = __Calculate; |
|
23 this.CancelNotification = __CancelNotification; |
|
24 } |
|
25 |
|
26 device.implementation.extend(provider, Interface, new LocationService() ); |
|
27 |
|
28 |
|
29 /******************************************************/ |
|
30 /******************************************************/ |
|
31 /******************************************************/ |
|
32 |
|
33 var context = device.implementation.context, |
|
34 _t = context._t, |
|
35 method = '', |
|
36 result = false, |
|
37 DBase = null; |
|
38 |
|
39 |
|
40 var transactionIds = new Array(); |
|
41 var tTransactionId = -1; |
|
42 var isTraceInProgress = false; |
|
43 var criteriaTrace; |
|
44 var callbackTrace; |
|
45 |
|
46 /** |
|
47 * Landmarks: GetLocation |
|
48 * @param {Object} criteria |
|
49 */ |
|
50 function __GetLocation(criteria, callback, flag){ |
|
51 method = "GetLocation"; |
|
52 // Async call |
|
53 flag = flag || false; |
|
54 |
|
55 if (!criteria) { |
|
56 criteria = new Object(); |
|
57 } |
|
58 |
|
59 if(typeof criteria.LocationInformationClass == "undefined") |
|
60 criteria.LocationInformationClass = "BasicLocationInformation"; // Default value of LocationInformationClass is "BasicLocationInformation" if not provided |
|
61 |
|
62 var result = validateArgument('GetLocation',criteria); |
|
63 if(result.ErrorCode != 0) |
|
64 return result; |
|
65 |
|
66 if (typeof callback == 'function') { |
|
67 |
|
68 var retVal = context.callAsync(this, arguments.callee, criteria, callback,true); |
|
69 transactionIds.push(retVal.TransactionID); // all transaction ids are pushed on this variable, because CancelNotification function of SAPI doesn't take TransactioID as input |
|
70 return retVal; |
|
71 } |
|
72 |
|
73 if(flag) |
|
74 { |
|
75 transactionIds.shift(); // Remove oldest TransactionID(FIFO) (Async call) |
|
76 } |
|
77 |
|
78 DBase = context.getData(provider); |
|
79 var returnValue = DBase[criteria.LocationInformationClass]; |
|
80 locationNotify(criteria.Updateoptions); |
|
81 return context.Result(returnValue); |
|
82 } |
|
83 |
|
84 /** |
|
85 * Location: Trace |
|
86 * @param {Object} criteria |
|
87 * @param {Function} callback function for async call |
|
88 */ |
|
89 function __Trace(criteria, callback){ |
|
90 method = "Trace"; |
|
91 |
|
92 if (!criteria) { |
|
93 criteria = new Object(); |
|
94 } |
|
95 |
|
96 if(typeof criteria.LocationInformationClass == "undefined") |
|
97 criteria.LocationInformationClass = "BasicLocationInformation"; // Default value of LocationInformationClass is "BasicLocationInformation" if not provided |
|
98 |
|
99 if (typeof callback != 'function') { // callback should be valid function |
|
100 return error(device.implementation.ERR_SERVICE_NOT_SUPPORTED,msg.msgCommandNotFound); |
|
101 } |
|
102 |
|
103 var result = validateArgument('Trace',criteria); |
|
104 if(result.ErrorCode != 0) |
|
105 return result; |
|
106 |
|
107 criteriaTrace = criteria; |
|
108 callbackTrace = callback; |
|
109 isTraceInProgress = true; |
|
110 locationNotify(criteria.Updateoptions); |
|
111 |
|
112 return traceCall(criteria,callback); |
|
113 } |
|
114 |
|
115 /** |
|
116 * Location: Calculate |
|
117 * @param {Object} criteria |
|
118 */ |
|
119 function __Calculate(criteria){ |
|
120 method = "Calculate"; |
|
121 if(!criteria || !criteria.MathRequest) |
|
122 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcMissingMathReq); |
|
123 |
|
124 if(typeof criteria.MathRequest != "string" || (criteria.MathRequest != "FindDistance" && criteria.MathRequest != "FindBearingTo" && criteria.MathRequest != "MoveCoordinates")) // Error check for wrong MathRequest criteria |
|
125 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcWrongTypeMathReq); |
|
126 |
|
127 if(typeof criteria.DistanceParamSource != "object" || (typeof criteria.DistanceParamSource.Latitude != "number" || typeof criteria.DistanceParamSource.Longitude != "number" || typeof criteria.DistanceParamSource.Altitude != "number")) |
|
128 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcMissingArgLocCord); |
|
129 |
|
130 if(criteria.MathRequest == "FindDistance" || criteria.MathRequest == "FindBearingTo") |
|
131 { |
|
132 if(typeof criteria.DistanceParamSource != "object" || (typeof criteria.DistanceParamDestination.Latitude != "number" || typeof criteria.DistanceParamDestination.Longitude != "number" || typeof criteria.DistanceParamDestination.Altitude != "number")) |
|
133 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcMissingArgLocCord); |
|
134 if (criteria.MathRequest == "FindDistance") { |
|
135 var dist = LatLon.distHaversine(criteria.DistanceParamDestination.Latitude, criteria.DistanceParamDestination.Longitude, criteria.DistanceParamSource.Latitude, criteria.DistanceParamSource.Longitude)*1000; |
|
136 if (typeof criteria.DistanceParamDestination.Altitude == "number" && typeof criteria.DistanceParamSource.Altitude == "number") { |
|
137 var delta = criteria.DistanceParamDestination.Altitude - criteria.DistanceParamSource.Altitude |
|
138 dist = Math.sqrt(dist * dist + delta * delta); |
|
139 } |
|
140 return context.Result(dist); |
|
141 } |
|
142 else if (criteria.MathRequest == "FindBearingTo"){ |
|
143 var bearing = LatLon.bearing( criteria.DistanceParamSource.Latitude, criteria.DistanceParamSource.Longitude,criteria.DistanceParamDestination.Latitude, criteria.DistanceParamDestination.Longitude); |
|
144 return context.Result(bearing); |
|
145 } |
|
146 } |
|
147 else if(criteria.MathRequest == "MoveCoordinates"){ |
|
148 |
|
149 if(typeof criteria.MoveByThisDistance == "undefined") |
|
150 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcMissingArgMoveDist); |
|
151 |
|
152 if(typeof criteria.MoveByThisBearing == "undefined") |
|
153 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcMissingArgMoveBear); |
|
154 |
|
155 |
|
156 if(typeof criteria.MoveByThisDistance != "number") |
|
157 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcWrongTypeMoveDist); |
|
158 |
|
159 if(typeof criteria.MoveByThisBearing != "number") |
|
160 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCalcWrongTypeMoveBear); |
|
161 |
|
162 var latLon = new LatLon(criteria.DistanceParamSource.Latitude, criteria.DistanceParamSource.Longitude); |
|
163 var dlatLon = latLon.destPoint(criteria.MoveByThisBearing, criteria.MoveByThisDistance/1000); |
|
164 var retVal = new Object(); |
|
165 retVal.Longitude = dlatLon.lon; |
|
166 retVal.Latitude = dlatLon.lat; |
|
167 retVal.Altitude = criteria.DistanceParamSource.Altitude; |
|
168 return context.Result(retVal); |
|
169 } |
|
170 } |
|
171 |
|
172 /** |
|
173 * Location: CancelNotification |
|
174 * @param {Object} criteria |
|
175 */ |
|
176 function __CancelNotification(criteria){ |
|
177 method = "Cancel"; |
|
178 if(!criteria) |
|
179 return error(device.implementation.ERR_MISSING_ARGUMENT,msg.msgCancelMissingType); |
|
180 |
|
181 var arr = new Array(); |
|
182 var i = 0; |
|
183 var key |
|
184 for(key in criteria); |
|
185 arr[i++] = key; |
|
186 |
|
187 if(!criteria.CancelRequestType && arr.length) |
|
188 return error(device.implementation.ERR_NOT_FOUND,msg.msgCancelMissingType); |
|
189 |
|
190 if(criteria.CancelRequestType != "GetLocCancel" && criteria.CancelRequestType != "TraceCancel") |
|
191 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgCancelWrongType); |
|
192 |
|
193 if (criteria.CancelRequestType == "GetLocCancel") { |
|
194 for (var i = 0; i < transactionIds.length; i++) { |
|
195 clearTimeout(transactionIds[i]) |
|
196 } |
|
197 } |
|
198 |
|
199 if (criteria.CancelRequestType == "TraceCancel") |
|
200 { |
|
201 isTraceInProgress = false; |
|
202 tTransactionId = -1; |
|
203 } |
|
204 return context.ErrorResult(device.implementation.ERR_SUCCESS); |
|
205 } |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 /******************************* |
|
211 * helper functions |
|
212 *******************************/ |
|
213 |
|
214 /** |
|
215 * Location: traceCall |
|
216 * @param {} |
|
217 * This function emulates repetitive trace calls,It calls specified callback function after every UpdateInterval untill |
|
218 * CancelNotification is called |
|
219 */ |
|
220 function traceCall(){ |
|
221 var tid = setTimeout(function(){ |
|
222 if(!isTraceInProgress) |
|
223 return; |
|
224 |
|
225 DBase = context.getData(provider); |
|
226 var returnValue = DBase[criteriaTrace.LocationInformationClass]; |
|
227 var result, |
|
228 eventCode = {completed:2, error:4, progress:9}, |
|
229 code = eventCode.completed; |
|
230 |
|
231 callbackTrace(tTransactionId,code,context.Result(returnValue,0)); |
|
232 traceCall(); |
|
233 }, criteriaTrace.Updateoptions.UpdateInterval/1000); |
|
234 if(tTransactionId == -1) |
|
235 tTransactionId = tid; |
|
236 return context.AsyncResult(tTransactionId); |
|
237 } |
|
238 |
|
239 /** |
|
240 * Location: validateArgument |
|
241 * @param {string,object} callingMethod and criteria |
|
242 * Validates arguments |
|
243 */ |
|
244 function validateArgument(fun,criteria) |
|
245 { |
|
246 method = fun; |
|
247 if(typeof criteria.Updateoptions != "undefined") |
|
248 { |
|
249 if(typeof criteria.Updateoptions != "object") // Checking for error in UpdateOptions criteria |
|
250 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationBadArg); |
|
251 |
|
252 if(typeof criteria.Updateoptions.UpdateInterval != "undefined" && typeof criteria.Updateoptions.UpdateInterval != "number") |
|
253 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationWrongType); |
|
254 |
|
255 if(typeof criteria.Updateoptions.UpdateTimeOut != "undefined" && typeof criteria.Updateoptions.UpdateTimeOut != "number") |
|
256 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationWrongType); |
|
257 |
|
258 if(typeof criteria.Updateoptions.UpdateMaxAge != "undefined" && typeof criteria.Updateoptions.UpdateMaxAge != "number") |
|
259 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationWrongType); |
|
260 |
|
261 if(typeof criteria.Updateoptions.PartialUpdates != "undefined" && typeof criteria.Updateoptions.PartialUpdates != "boolean") |
|
262 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationWrongType); |
|
263 |
|
264 if((typeof criteria.Updateoptions.UpdateInterval != "undefined" && criteria.Updateoptions.UpdateInterval < 0) || |
|
265 (typeof criteria.Updateoptions.UpdateTimeOut != "undefined" && criteria.Updateoptions.UpdateTimeOut < 0) || |
|
266 (typeof criteria.Updateoptions.UpdateMaxAge != "undefined" && criteria.Updateoptions.UpdateMaxAge < 0)) |
|
267 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationNegInt); |
|
268 |
|
269 if(typeof criteria.Updateoptions.UpdateTimeOut != "undefined" && typeof criteria.Updateoptions.UpdateInterval != "undefined" && criteria.Updateoptions.UpdateInterval > criteria.Updateoptions.UpdateTimeOut) |
|
270 { |
|
271 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgNone); |
|
272 } |
|
273 |
|
274 /*if((typeof criteria.Updateoptions.UpdateTimeOut != "undefined" && criteria.Updateoptions.UpdateTimeOut <= 1000000))// || (typeof criteria.Updateoptions.UpdateInterval != "undefined" && criteria.Updateoptions.UpdateInterval <= 1000000)) |
|
275 { |
|
276 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgNone); |
|
277 }*/ |
|
278 } |
|
279 |
|
280 if(typeof criteria.LocationInformationClass != "undefined" && criteria.LocationInformationClass != "BasicLocationInformation" && criteria.LocationInformationClass != "GenericLocationInfo") // checking for errors in LocationInformationClass criteria |
|
281 return error(device.implementation.ERR_BAD_ARGUMENT_TYPE,msg.msgGetLocationWrongCat); |
|
282 |
|
283 if (/^Trace$/i.test(fun)&&(!criteria.Updateoptions || typeof criteria.Updateoptions.UpdateInterval == "undefined")) { |
|
284 if(!criteria.Updateoptions) |
|
285 { |
|
286 criteria.Updateoptions = new Object(); |
|
287 } |
|
288 criteria.Updateoptions.UpdateInterval = 1000000; // Emulation only!! for convenience UpdateInterval is set to 1 second is not specified or if it less than 1 second |
|
289 context.notify("Using default UpdateInterval(1000000 micro seconds)"); |
|
290 } |
|
291 |
|
292 return context.ErrorResult(device.implementation.ERR_SUCCESS, ""); |
|
293 |
|
294 } |
|
295 |
|
296 /** |
|
297 * Location: error |
|
298 * @param {number,string} ErrorCode and ErrorString |
|
299 * Replaces Error String with method name |
|
300 */ |
|
301 function error(code, msg /*, args...*/){ |
|
302 |
|
303 var args = ['location',method].concat([].slice.call(arguments,2)); |
|
304 msg = msg ? _t().arg.apply(msg,args) : undefined; |
|
305 return context.ErrorResult(code, msg); |
|
306 } |
|
307 |
|
308 function locationNotify(updateoptions) { |
|
309 if(!updateoptions) |
|
310 return; |
|
311 if(typeof updateoptions.UpdateTimeOut != "undefined") |
|
312 context.notify(_t("%s:: %s : Updateoptions.UpdateTimeOut not implemented in preview").arg(provider, method)); |
|
313 |
|
314 if(typeof updateoptions.UpdateMaxAge != "undefined") |
|
315 context.notify(_t("%s:: %s : Updateoptions.UpdateMaxAge not implemented in preview").arg(provider, method)); |
|
316 |
|
317 if(typeof updateoptions.PartialUpdates != "undefined") |
|
318 context.notify(_t("%s:: %s : Updateoptions.PartialUpdates not implemented in preview").arg(provider, method)); |
|
319 } |
|
320 |
|
321 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
|
322 /* Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2009 */ |
|
323 /* http://www.movable-type.co.uk/scripts/latlong.html */ |
|
324 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
|
325 |
|
326 /* |
|
327 * Use Haversine formula to Calculate distance (in km) between two points specified by |
|
328 * latitude/longitude (in numeric degrees) |
|
329 * |
|
330 * example usage from form: |
|
331 * result.value = LatLon.distHaversine(lat1.value.parseDeg(), long1.value.parseDeg(), |
|
332 * lat2.value.parseDeg(), long2.value.parseDeg()); |
|
333 * where lat1, long1, lat2, long2, and result are form fields |
|
334 */ |
|
335 |
|
336 |
|
337 LatLon.distHaversine = function(lat1, lon1, lat2, lon2) { |
|
338 var R = 6371; // earth's mean radius in km |
|
339 var dLat = toRad(lat2-lat1); |
|
340 var dLon = toRad(lon2-lon1); |
|
341 lat1 = toRad(lat1), lat2 = toRad(lat2); |
|
342 |
|
343 var a = Math.sin(dLat/2) * Math.sin(dLat/2) + |
|
344 Math.cos(lat1) * Math.cos(lat2) * |
|
345 Math.sin(dLon/2) * Math.sin(dLon/2); |
|
346 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); |
|
347 var d = R * c; |
|
348 return d; |
|
349 } |
|
350 |
|
351 |
|
352 /* |
|
353 * ditto using Law of Cosines |
|
354 */ |
|
355 LatLon.distCosineLaw = function(lat1, lon1, lat2, lon2) { |
|
356 var R = 6371; // earth's mean radius in km |
|
357 var d = Math.acos(Math.sin(toRad(lat1))*Math.sin(toRad(lat2)) + |
|
358 Math.cos(toRad(lat1))*Math.cos(toRad(lat2))*Math.cos(toRad(lon2-lon1))) * R; |
|
359 return d; |
|
360 } |
|
361 |
|
362 |
|
363 /* |
|
364 * calculate (initial) bearing between two points |
|
365 * see http://williams.best.vwh.net/avform.htm#Crs |
|
366 */ |
|
367 LatLon.bearing = function(lat1, lon1, lat2, lon2) { |
|
368 lat1 = toRad(lat1); lat2 = toRad(lat2); |
|
369 var dLon = toRad(lon2-lon1); |
|
370 |
|
371 var y = Math.sin(dLon) * Math.cos(lat2); |
|
372 var x = Math.cos(lat1)*Math.sin(lat2) - |
|
373 Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); |
|
374 return toBrng(Math.atan2(y, x)); |
|
375 } |
|
376 |
|
377 |
|
378 /* |
|
379 * calculate destination point given start point, initial bearing (deg) and distance (km) |
|
380 * see http://williams.best.vwh.net/avform.htm#LL |
|
381 */ |
|
382 LatLon.prototype.destPoint = function(brng, d) { |
|
383 var R = 6371; // earth's mean radius in km |
|
384 var lat1 = toRad(this.lat), lon1 = toRad(this.lon); |
|
385 brng = toRad(brng); |
|
386 |
|
387 var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + |
|
388 Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) ); |
|
389 var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), |
|
390 Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2)); |
|
391 lon2 = (lon2+Math.PI)%(2*Math.PI) - Math.PI; // normalise to -180...+180 |
|
392 |
|
393 if (isNaN(lat2) || isNaN(lon2)) return null; |
|
394 return new LatLon(toDeg(lat2), toDeg(lon2)); |
|
395 } |
|
396 |
|
397 |
|
398 /* |
|
399 * construct a LatLon object: arguments in numeric degrees |
|
400 * |
|
401 * note all LatLong methods expect & return numeric degrees (for lat/long & for bearings) |
|
402 */ |
|
403 function LatLon(lat, lon) { |
|
404 this.lat = lat; |
|
405 this.lon = lon; |
|
406 } |
|
407 |
|
408 |
|
409 /* |
|
410 * represent point {lat, lon} in standard representation |
|
411 */ |
|
412 LatLon.prototype.toString = function() { |
|
413 return this.lat.toLat() + ', ' + this.lon.toLon(); |
|
414 } |
|
415 |
|
416 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
|
417 |
|
418 // extend String object with method for parsing degrees or lat/long values to numeric degrees |
|
419 // |
|
420 // this is very flexible on formats, allowing signed decimal degrees, or deg-min-sec suffixed by |
|
421 // compass direction (NSEW). A variety of separators are accepted (eg 3º 37' 09"W) or fixed-width |
|
422 // format without separators (eg 0033709W). Seconds and minutes may be omitted. (Minimal validation |
|
423 // is done). |
|
424 |
|
425 function parseDeg (str) { |
|
426 if (!isNaN(str)) return Number(str); // signed decimal degrees without NSEW |
|
427 |
|
428 var degLL = str.replace(/^-/,'').replace(/[NSEW]/i,''); // strip off any sign or compass dir'n |
|
429 var dms = degLL.split(/[^0-9.]+/); // split out separate d/m/s |
|
430 for (var i in dms) if (dms[i]=='') dms.splice(i,1); // remove empty elements (see note below) |
|
431 switch (dms.length) { // convert to decimal degrees... |
|
432 case 3: // interpret 3-part result as d/m/s |
|
433 var deg = dms[0]/1 + dms[1]/60 + dms[2]/3600; break; |
|
434 case 2: // interpret 2-part result as d/m |
|
435 var deg = dms[0]/1 + dms[1]/60; break; |
|
436 case 1: // decimal or non-separated dddmmss |
|
437 if (/[NS]/i.test(str)) degLL = '0' + degLL; // - normalise N/S to 3-digit degrees |
|
438 var deg = dms[0].slice(0,3)/1 + dms[0].slice(3,5)/60 + dms[0].slice(5)/3600; break; |
|
439 default: return NaN; |
|
440 } |
|
441 if (/^-/.test(str) || /[WS]/i.test(str)) deg = -deg; // take '-', west and south as -ve |
|
442 return deg; |
|
443 } |
|
444 // note: whitespace at start/end will split() into empty elements (except in IE) |
|
445 |
|
446 |
|
447 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
|
448 |
|
449 // extend Number object with methods for converting degrees/radians |
|
450 |
|
451 function toRad (deg) { // convert degrees to radians |
|
452 return deg * Math.PI / 180; |
|
453 } |
|
454 |
|
455 function toDeg (rad) { // convert radians to degrees (signed) |
|
456 return rad * 180 / Math.PI; |
|
457 } |
|
458 |
|
459 function toBrng (rad) { // convert radians to degrees (as bearing: 0...360) |
|
460 return (toDeg(rad)+360) % 360; |
|
461 } |
|
462 |
|
463 |
|
464 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
|
465 |
|
466 // extend Number object with methods for presenting bearings & lat/longs |
|
467 |
|
468 function toDMS (num) { // convert numeric degrees to deg/min/sec |
|
469 var d = Math.abs(num); // (unsigned result ready for appending compass dir'n) |
|
470 d += 1/7200; // add ½ second for rounding |
|
471 var deg = Math.floor(d); |
|
472 var min = Math.floor((d-deg)*60); |
|
473 var sec = Math.floor((d-deg-min/60)*3600); |
|
474 // add leading zeros if required |
|
475 if (deg<100) deg = '0' + deg; if (deg<10) deg = '0' + deg; |
|
476 if (min<10) min = '0' + min; |
|
477 if (sec<10) sec = '0' + sec; |
|
478 return deg + '\u00B0' + min + '\u2032' + sec + '\u2033'; |
|
479 } |
|
480 |
|
481 function toLat (deg) { // convert numeric degrees to deg/min/sec latitude |
|
482 return toDMS(deg).slice(1) + (deg<0 ? 'S' : 'N'); // knock off initial '0' for lat! |
|
483 } |
|
484 |
|
485 function toLon (deg) { // convert numeric degrees to deg/min/sec longitude |
|
486 return toDMS(deg) + (deg>0 ? 'E' : 'W'); |
|
487 } |
|
488 |
|
489 function toPrecision (num,fig) { // override toPrecision method with one which displays |
|
490 if (num == 0) return 0; // trailing zeros in place of exponential notation |
|
491 var scale = Math.ceil(Math.log(num)*Math.LOG10E); |
|
492 var mult = Math.pow(10, fig-scale); |
|
493 return Math.round(num*mult)/mult; |
|
494 } |
|
495 |
|
496 |
|
497 /** |
|
498 * error messages |
|
499 * order of %s args: Service name, method name, parameter name |
|
500 */ |
|
501 var msg = { |
|
502 msgCommandNotFound : '%s : Command Not found', |
|
503 msgGetLocationWrongCat : '%s : %s : wrong category info should be BasicLocationInformation/GenericLocationInfo ', |
|
504 msgGetLocationBadArg : '%s : %s : BadArgument - Updateoptions', |
|
505 msgGetLocationNegInt : '%s : %s : Negative Time Interval', |
|
506 msgGetLocationWrongType : '%s : %s : UpdateOptions Type mismatch', |
|
507 msgTraceWrongCat : '%s : %s : Invalid LocationInformationClass', |
|
508 msgCalcMissingMathReq : '%s : %s : Missing argument - MathRequest', |
|
509 msgCalcWrongTypeMathReq : '%s : %s : Wrong argument - MathRequest', |
|
510 msgCalcMissingArgLocCord : '%s : %s : Missing argument - locationcoordinate', |
|
511 msgCalcMissingArgMoveDist : '%s : %s : Missing argument - MoveByThisDistance', |
|
512 msgCalcMissingArgMoveBear : '%s : %s : Missing argument - MoveByThisBearing', |
|
513 msgCalcWrongTypeMoveDist : '%s : %s : TypeMismatch - MoveByThisDistance', |
|
514 msgCalcWrongTypeMoveBear : '%s : %s : TypeMismatch - MoveByThisBearing', |
|
515 msgCancelBadArg : '%s : %s : BadArgument – cancel type', |
|
516 msgCancelMissingType : '%s : %s : Missing cancel type', |
|
517 msgCancelWrongType : '%s : %s : Wrong cancel type' , |
|
518 msgNone : '' |
|
519 }; |
|
520 |
|
521 |
|
522 }) () |
|
523 |