// // Open Service Platform // Copyright (c) 2012 Samsung Electronics Co., Ltd. // // Licensed under the Apache License, Version 2.0 (the License); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include #include #include #include #include #include #include #include "FLoc_EllipsoidModel.h" #include "FLoc_MathUtils.h" #include "FLoc_Types.h" using namespace Tizen::Base; using namespace Tizen::Base::Utility; namespace Tizen { namespace Locations { Coordinates::Coordinates(void) : Tizen::Base::Object() , __latitude(Tizen::Locations::NaN) , __longitude(Tizen::Locations::NaN) , __altitude(Tizen::Locations::NaN) , __pImpl(null) { SysAssertf(Double::IsNaN(__latitude), "Latitude is not initialized to NaN"); SysAssertf(Double::IsNaN(__longitude), "Longitude is not initialized to NaN"); SysAssertf(Double::IsNaN(__altitude), "Altitude is not initialized to NaN"); } Coordinates::Coordinates(const Coordinates& rhs) : Tizen::Base::Object() , __latitude(rhs.__latitude) , __longitude(rhs.__longitude) , __altitude(rhs.__altitude) , __pImpl(null) { } Coordinates::~Coordinates(void) { } bool Coordinates::Equals(const Tizen::Base::Object& rhs) const { const Coordinates* pRhs = dynamic_cast< const Coordinates* >(&rhs); if (pRhs == null) { return false; } bool latitudeCheck = false; bool longitudeCheck = false; bool altitudeCheck = false; if (Double::IsNaN(__latitude) || Double::IsNaN(pRhs->__latitude)) { if (Double::IsNaN(__latitude) && Double::IsNaN(pRhs->__latitude)) { latitudeCheck = true; } } else if (Double::Compare(__latitude, pRhs->__latitude) == 0) { latitudeCheck = true; } if (Double::IsNaN(__longitude) || Double::IsNaN(pRhs->__longitude)) { if (Double::IsNaN(__longitude) && Double::IsNaN(pRhs->__longitude)) { longitudeCheck = true; } } else { if (Double::Compare(__longitude, pRhs->__longitude) == 0) { longitudeCheck = true; } // Min and max longitudes lines meet together. (longitude -180 == +180) else if (Double::Compare(fabs(__longitude) + fabs(pRhs->__longitude), MAX_LONGITUDE * 2) == 0) { SysLog(NID_LOC, "Both longitudes are equal as 180 is equal to -180"); longitudeCheck = true; } } if (Double::IsNaN(__altitude) || Double::IsNaN(pRhs->__altitude)) { if (Double::IsNaN(__altitude) && Double::IsNaN(pRhs->__altitude)) { altitudeCheck = true; } } else if (Double::Compare(__altitude, pRhs->__altitude) == 0) { altitudeCheck = true; } return (latitudeCheck && longitudeCheck && altitudeCheck); } int Coordinates::GetHashCode(void) const { int hashCode = Double::GetHashCode(__latitude) * 37; hashCode += Double::GetHashCode(__longitude) * 37; hashCode += Double::GetHashCode(__altitude) * 37; return hashCode; } result Coordinates::Set(double latitude, double longitude, double altitude) { SysSecureTryReturn(NID_LOC, (MIN_LATITUDE <= latitude) && (latitude <= MAX_LATITUDE), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The latitude(%lf) must be in the range [-90.0, 90.0].", latitude); SysSecureTryReturn(NID_LOC, (MIN_LONGITUDE <= longitude) && (longitude <= MAX_LONGITUDE), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The longitude(%lf) must be in the range [-180.0, 180.0].", longitude); __latitude = latitude; __longitude = longitude; __altitude = altitude; return E_SUCCESS; } result Coordinates::SetLatitude(double latitude) { SysSecureTryReturn(NID_LOC, (MIN_LATITUDE <= latitude) && (latitude <= MAX_LATITUDE), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The latitude(%lf) must be in the range [-90.0, 90.0].", latitude); __latitude = latitude; return E_SUCCESS; } result Coordinates::SetLongitude(double longitude) { SysSecureTryReturn(NID_LOC, (MIN_LONGITUDE <= longitude) && (longitude <= MAX_LONGITUDE), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The longitude(%lf) must be in the range [-180.0, 180.0].", longitude); __longitude = longitude; return E_SUCCESS; } void Coordinates::SetAltitude(double altitude) { __altitude = altitude; } double Coordinates::GetLatitude(void) const { return __latitude; } double Coordinates::GetLongitude(void) const { return __longitude; } double Coordinates::GetAltitude(void) const { return __altitude; } double Coordinates::GetAzimuth(const Coordinates& dest) const { if ((Double::IsNaN(dest.GetLatitude()) == true) || (Double::IsNaN(dest.GetLongitude()) == true) || (Double::IsNaN(__latitude) == true) || (Double::IsNaN(__longitude) == true)) { return Tizen::Locations::NaN; } if (Double::Compare(MAX_LATITUDE, GetLatitude()) == 0 && Double::Compare(MAX_LATITUDE, dest.GetLatitude()) != 0) { return 180.0; } if (Double::Compare(MIN_LATITUDE, GetLatitude()) == 0 && Double::Compare(MIN_LATITUDE, dest.GetLatitude()) != 0) { return 0.0; } if (Equals(dest) || (Double::Compare(MIN_LATITUDE, GetLatitude()) == 0 && Double::Compare(MIN_LATITUDE, dest.GetLatitude()) == 0) || (Double::Compare(MAX_LATITUDE, GetLatitude()) == 0 && Double::Compare(MAX_LATITUDE, dest.GetLatitude()) == 0)) { return 0.0; } return _EllipsoidModel::GetAzimuth(GetLatitude(), GetLongitude(), dest.GetLatitude(), dest.GetLongitude()); } double Coordinates::GetDistanceTo(const Coordinates& to) const { if ((Double::IsNaN(to.GetLatitude()) == true) || (Double::IsNaN(to.GetLongitude()) == true) || (Double::IsNaN(__latitude) == true) || (Double::IsNaN(__longitude) == true)) { return Tizen::Locations::NaN; } return _EllipsoidModel::GetDistance(GetLatitude(), GetLongitude(), to.GetLatitude(), to.GetLongitude()); } result Coordinates::ToString(double degree, CoordinateFormat format, Tizen::Base::String& string) { SysTryReturn(NID_LOC, format == COORDINATE_FORMAT_DEGREE_MINUTE || format == COORDINATE_FORMAT_DEGREE_MINUTE_SECOND, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified format(%x) is not proper.", format); SysTryReturn(NID_LOC, MIN_LONGITUDE <= degree && degree < MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The supplied degree(%lf) is out of [-180, 180] range.", degree); double intPart = 0.0; double fractionalPart = 0.0; fractionalPart = modf(degree, &intPart); int degreeValue = (int) intPart; if (degree < 0) { fractionalPart *= -1.0; } String ret; const int bufferSize = 20; if (format == COORDINATE_FORMAT_DEGREE_MINUTE) { double minute = fractionalPart * 60; double minuteFraction = modf(minute, &intPart); if (Double::Compare(minuteFraction, 0.0) == 0) { ret.Format(bufferSize, L"%d:%02d", degreeValue, (int) minute); } else { ret.Format(bufferSize, L"%d:%02.5f", degreeValue, minute); } } else // if (COORDINATE_FORMAT_DEGREE_MINUTE_SECOND == outputType) { fractionalPart = modf(fractionalPart * 60, &intPart); int minute = (int) intPart; double second = fractionalPart * 60; double secondFraction = modf(second, &intPart); if (Double::Compare(second, 0.0) == 0 && Double::Compare(secondFraction, 0.0) == 0) { ret.Format(bufferSize, L"%d:%02d", degreeValue, (int) minute); } else { if (Double::Compare(secondFraction, 0.0) == 0) { ret.Format(bufferSize, L"%d:%02d:%02d", degreeValue, (int) minute, (int) second); } else { ret.Format(bufferSize, L"%d:%02d:%02.3f", degreeValue, (int) minute, second); } } } string = ret; return E_SUCCESS; } result Coordinates::Parse(const Tizen::Base::String& string, double& degree) { double ret = 0.0; CoordinateFormat type = COORDINATE_FORMAT_DEGREE_MINUTE; StringTokenizer tokenizer(string, L":"); SysTryReturn(NID_LOC, tokenizer.GetTokenCount() <= 3, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The coordinate(%ls) is in invalid format.", string.GetPointer()); if (3 == tokenizer.GetTokenCount()) { type = COORDINATE_FORMAT_DEGREE_MINUTE_SECOND; } String degreeValue(L"0"); tokenizer.GetNextToken(degreeValue); int sign = 1; int degreeInt = 0; result r = Integer::Decode(degreeValue, degreeInt); SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the degree part."); SysTryReturn(NID_LOC, MIN_LONGITUDE <= degreeInt && degreeInt <= MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Degree(%d) is out of [-180, 180] range.", degreeInt); String minute(L"0"); if (E_OUT_OF_RANGE == tokenizer.GetNextToken(minute)) { degree = degreeInt; return E_SUCCESS; } if (degreeInt < 0) { sign = -1; degreeInt *= sign; } if (COORDINATE_FORMAT_DEGREE_MINUTE == type) // "DD:MM.DM" { SysTryReturn(NID_LOC, minute.GetLength() <= 8, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Minute(%ls) is too long.", minute.GetPointer()); double minuteDouble = 0.0; r = Double::Parse(minute, minuteDouble); SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the minute part."); SysTryReturn(NID_LOC, 0.0 <= minuteDouble && minuteDouble < 60.0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Minute(%f) is out of [0, 60] range.", minuteDouble); ret = sign * (((double) degreeInt) + (minuteDouble / 60.0)); } else // if (COORDINATE_FORMAT_DEGREE_MINUTE_SECOND == type) "DD:MM:SS.SM" { String second(L"0"); tokenizer.GetNextToken(second); SysTryReturn(NID_LOC, second.GetLength() <= 6, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Second(%ls) is too long.", second.GetPointer()); int minuteInt = 0; r = Integer::Decode(minute, minuteInt); SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the minute part."); SysTryReturn(NID_LOC, 0 <= minuteInt && minuteInt <= 59, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Minute(%d) is out of [0, 59] range.", minuteInt); double secondDouble = 0.0; r = Double::Parse(second, secondDouble); SysTryReturn(NID_LOC, r == E_SUCCESS, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to decode the second part."); SysTryReturn(NID_LOC, 0.0 <= secondDouble && secondDouble < 60.0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Second(%f) is out of [0, 60] range.", secondDouble); ret = sign * (((double) degreeInt) + ((double) minuteInt / 60.0) + (secondDouble / 3600.0)); } SysTryReturn(NID_LOC, MIN_LONGITUDE <= ret && ret < MAX_LONGITUDE, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Converted coordinate(%f) is out of [-180, 180] range.", ret); degree = ret; return E_SUCCESS; } Coordinates& Coordinates::operator =(const Coordinates& rhs) { if (this == &rhs) { return *this; } __latitude = rhs.__latitude; __longitude = rhs.__longitude; __altitude = rhs.__altitude; return *this; } }}