2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
20 #include <FBaseDouble.h>
21 #include <FBaseInteger.h>
22 #include <FBaseSysLog.h>
23 #include <FBaseUtilMath.h>
24 #include <FBaseUtilStringTokenizer.h>
25 #include <FLocCoordinates.h>
26 #include "FLoc_EllipsoidModel.h"
27 #include "FLoc_MathUtils.h"
28 #include "FLoc_Types.h"
30 using namespace Tizen::Base;
31 using namespace Tizen::Base::Utility;
33 namespace Tizen { namespace Locations
35 Coordinates::Coordinates(void)
36 : Tizen::Base::Object()
37 , __latitude(Tizen::Locations::NaN)
38 , __longitude(Tizen::Locations::NaN)
39 , __altitude(Tizen::Locations::NaN)
42 SysAssertf(Double::IsNaN(__latitude), "Latitude is not initialized to NaN");
43 SysAssertf(Double::IsNaN(__longitude), "Longitude is not initialized to NaN");
44 SysAssertf(Double::IsNaN(__altitude), "Altitude is not initialized to NaN");
47 Coordinates::Coordinates(const Coordinates& rhs)
48 : Tizen::Base::Object()
49 , __latitude(rhs.__latitude)
50 , __longitude(rhs.__longitude)
51 , __altitude(rhs.__altitude)
56 Coordinates::~Coordinates(void)
61 Coordinates::Equals(const Tizen::Base::Object& rhs) const
63 const Coordinates* pRhs = dynamic_cast< const Coordinates* >(&rhs);
70 bool latitudeCheck = false;
71 bool longitudeCheck = false;
72 bool altitudeCheck = false;
74 if (Double::IsNaN(__latitude) || Double::IsNaN(pRhs->__latitude))
76 if (Double::IsNaN(__latitude) && Double::IsNaN(pRhs->__latitude))
81 else if (Double::Compare(__latitude, pRhs->__latitude) == 0)
86 if (Double::IsNaN(__longitude) || Double::IsNaN(pRhs->__longitude))
88 if (Double::IsNaN(__longitude) && Double::IsNaN(pRhs->__longitude))
90 longitudeCheck = true;
95 if (Double::Compare(__longitude, pRhs->__longitude) == 0)
97 longitudeCheck = true;
99 // Min and max longitudes lines meet together. (longitude -180 == +180)
100 else if (Double::Compare(fabs(__longitude) + fabs(pRhs->__longitude), MAX_LONGITUDE * 2) == 0)
102 SysLog(NID_LOC, "Both longitudes are equal as 180 is equal to -180");
103 longitudeCheck = true;
107 if (Double::IsNaN(__altitude) || Double::IsNaN(pRhs->__altitude))
109 if (Double::IsNaN(__altitude) && Double::IsNaN(pRhs->__altitude))
111 altitudeCheck = true;
114 else if (Double::Compare(__altitude, pRhs->__altitude) == 0)
116 altitudeCheck = true;
119 return (latitudeCheck && longitudeCheck && altitudeCheck);
123 Coordinates::GetHashCode(void) const
125 int hashCode = Double::GetHashCode(__latitude) * 37;
127 hashCode += Double::GetHashCode(__longitude) * 37;
128 hashCode += Double::GetHashCode(__altitude) * 37;
134 Coordinates::Set(double latitude, double longitude, double altitude)
136 SysTryReturn(NID_LOC, (MIN_LATITUDE <= latitude) && (latitude <= MAX_LATITUDE),
137 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The latitude(%lf) must be in the range [-90.0, 90.0].", latitude);
139 SysTryReturn(NID_LOC, (MIN_LONGITUDE <= longitude) && (longitude <= MAX_LONGITUDE),
140 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The longitude(%lf) must be in the range [-180.0, 180.0].", longitude);
142 __latitude = latitude;
143 __longitude = longitude;
144 __altitude = altitude;
150 Coordinates::SetLatitude(double latitude)
152 SysTryReturn(NID_LOC, (MIN_LATITUDE <= latitude) && (latitude <= MAX_LATITUDE),
153 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The latitude(%lf) must be in the range [-90.0, 90.0].", latitude);
155 __latitude = latitude;
160 Coordinates::SetLongitude(double longitude)
162 SysTryReturn(NID_LOC, (MIN_LONGITUDE <= longitude) && (longitude <= MAX_LONGITUDE),
163 E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The longitude(%lf) must be in the range [-180.0, 180.0].", longitude);
165 __longitude = longitude;
170 Coordinates::SetAltitude(double altitude)
172 __altitude = altitude;
176 Coordinates::GetLatitude(void) const
182 Coordinates::GetLongitude(void) const
188 Coordinates::GetAltitude(void) const
194 Coordinates::GetAzimuth(const Coordinates& dest) const
196 if ((Double::IsNaN(dest.GetLatitude()) == true) || (Double::IsNaN(dest.GetLongitude()) == true) || (Double::IsNaN(__latitude) == true) || (Double::IsNaN(__longitude) == true))
198 return Tizen::Locations::NaN;
201 if (Double::Compare(MAX_LATITUDE, GetLatitude()) == 0 && Double::Compare(MAX_LATITUDE, dest.GetLatitude()) != 0)
206 if (Double::Compare(MIN_LATITUDE, GetLatitude()) == 0 && Double::Compare(MIN_LATITUDE, dest.GetLatitude()) != 0)
212 (Double::Compare(MIN_LATITUDE, GetLatitude()) == 0 && Double::Compare(MIN_LATITUDE, dest.GetLatitude()) == 0) ||
213 (Double::Compare(MAX_LATITUDE, GetLatitude()) == 0 && Double::Compare(MAX_LATITUDE, dest.GetLatitude()) == 0))
218 return _EllipsoidModel::GetAzimuth(GetLatitude(), GetLongitude(), dest.GetLatitude(), dest.GetLongitude());
222 Coordinates::GetDistanceTo(const Coordinates& to) const
224 if ((Double::IsNaN(to.GetLatitude()) == true) || (Double::IsNaN(to.GetLongitude()) == true) || (Double::IsNaN(__latitude) == true) || (Double::IsNaN(__longitude) == true))
226 return Tizen::Locations::NaN;
229 return _EllipsoidModel::GetDistance(GetLatitude(), GetLongitude(), to.GetLatitude(), to.GetLongitude());
233 Coordinates::ToString(double degree, CoordinateFormat format, Tizen::Base::String& string)
235 SysTryReturn(NID_LOC, format == COORDINATE_FORMAT_DEGREE_MINUTE || format == COORDINATE_FORMAT_DEGREE_MINUTE_SECOND, E_INVALID_ARG, E_INVALID_ARG,
236 "[E_INVALID_ARG] The specified format(%x) is not proper.", format);
238 SysTryReturn(NID_LOC, MIN_LONGITUDE <= degree && degree < MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG,
239 "[E_INVALID_ARG] The supplied degree(%lf) is out of [-180, 180] range.", degree);
241 double intPart = 0.0;
242 double fractionalPart = 0.0;
244 fractionalPart = modf(degree, &intPart);
245 int degreeValue = (int) intPart;
249 fractionalPart *= -1.0;
253 const int bufferSize = 20;
254 if (format == COORDINATE_FORMAT_DEGREE_MINUTE)
256 double minute = fractionalPart * 60;
257 double minuteFraction = modf(minute, &intPart);
259 if (Double::Compare(minuteFraction, 0.0) == 0)
261 ret.Format(bufferSize, L"%d:%02d", degreeValue, (int) minute);
265 ret.Format(bufferSize, L"%d:%02.5f", degreeValue, minute);
268 else // if (COORDINATE_FORMAT_DEGREE_MINUTE_SECOND == outputType)
270 fractionalPart = modf(fractionalPart * 60, &intPart);
272 int minute = (int) intPart;
273 double second = fractionalPart * 60;
274 double secondFraction = modf(second, &intPart);
276 if (Double::Compare(second, 0.0) == 0 && Double::Compare(secondFraction, 0.0) == 0)
278 ret.Format(bufferSize, L"%d:%02d", degreeValue, (int) minute);
282 if (Double::Compare(secondFraction, 0.0) == 0)
284 ret.Format(bufferSize, L"%d:%02d:%02d", degreeValue, (int) minute, (int) second);
288 ret.Format(bufferSize, L"%d:%02d:%02.3f", degreeValue, (int) minute, second);
298 Coordinates::Parse(const Tizen::Base::String& string, double& degree)
300 result r = E_SUCCESS;
302 CoordinateFormat type = COORDINATE_FORMAT_DEGREE_MINUTE;
304 StringTokenizer tokenizer(string, L":");
305 SysTryReturn(NID_LOC, tokenizer.GetTokenCount() <= 3, E_INVALID_ARG, E_INVALID_ARG,
306 "[E_INVALID_ARG] The coordinate(%ls) is in invalid format.", string.GetPointer());
308 if (3 == tokenizer.GetTokenCount())
310 type = COORDINATE_FORMAT_DEGREE_MINUTE_SECOND;
313 String degreeValue(L"0");
314 tokenizer.GetNextToken(degreeValue);
318 r = Integer::Decode(degreeValue, degreeInt);
319 SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the degree part.");
320 SysTryReturn(NID_LOC, MIN_LONGITUDE <= degreeInt && degreeInt <= MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG,
321 "[E_INVALID_ARG] Degree(%d) is out of [-180, 180] range.", degreeInt);
324 if (E_OUT_OF_RANGE == tokenizer.GetNextToken(minute))
336 if (COORDINATE_FORMAT_DEGREE_MINUTE == type) // "DD:MM.DM"
338 SysTryReturn(NID_LOC, minute.GetLength() <= 8, E_INVALID_ARG, E_INVALID_ARG,
339 "[E_INVALID_ARG] Minute(%ls) is too long.", minute.GetPointer());
341 double minuteDouble = 0.0;
342 r = Double::Parse(minute, minuteDouble);
343 SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the minute part.");
344 SysTryReturn(NID_LOC, 0.0 <= minuteDouble && minuteDouble < 60.0, E_INVALID_ARG, E_INVALID_ARG,
345 "[E_INVALID_ARG] Minute(%f) is out of [0, 60] range.", minuteDouble);
346 ret = sign * (((double) degreeInt) + (minuteDouble / 60.0));
348 else // if (COORDINATE_FORMAT_DEGREE_MINUTE_SECOND == type) "DD:MM:SS.SM"
351 tokenizer.GetNextToken(second);
352 SysTryReturn(NID_LOC, second.GetLength() <= 6, E_INVALID_ARG, E_INVALID_ARG,
353 "[E_INVALID_ARG] Second(%ls) is too long.", second.GetPointer());
356 r = Integer::Decode(minute, minuteInt);
357 SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the minute part.");
358 SysTryReturn(NID_LOC, 0 <= minuteInt && minuteInt <= 59, E_INVALID_ARG, E_INVALID_ARG,
359 "[E_INVALID_ARG] Minute(%d) is out of [0, 59] range.", minuteInt);
361 double secondDouble = 0.0;
362 r = Double::Parse(second, secondDouble);
363 SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the second part.");
364 SysTryReturn(NID_LOC, 0.0 <= secondDouble && secondDouble < 60.0, E_INVALID_ARG, E_INVALID_ARG,
365 "[E_INVALID_ARG] Second(%f) is out of [0, 60] range.", secondDouble);
367 ret = sign * (((double) degreeInt) + ((double) minuteInt / 60.0) + (secondDouble / 3600.0));
370 SysTryReturn(NID_LOC, MIN_LONGITUDE <= ret && ret < MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG,
371 "[E_INVALID_ARG] Converted coordinate(%f) is out of [-180, 180] range.", ret);
378 Coordinates::operator =(const Coordinates& rhs)
385 __latitude = rhs.__latitude;
386 __longitude = rhs.__longitude;
387 __altitude = rhs.__altitude;