• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "location.h"
17 
18 #include <parcel.h>
19 #include <string>
20 #include "string_ex.h"
21 #include <iostream>
22 #include <cmath>
23 
24 namespace OHOS {
25 namespace Location {
26 static constexpr double MIN_LATITUDE = -90.0;
27 static constexpr double MIN_LONGITUDE = -180.0;
28 static constexpr int MAX_POI_ARRAY_SIZE = 20;
29 static constexpr double MAX_LATITUDE = 90.0;
30 static constexpr double MAX_LONGITUDE = 180.0;
31 const double PI = 3.1415926;
32 const double DEGREE_PI = 180.0;
33 const double POW_PARAMETER_TOW = 2;
34 const double NUM_DOUBLE = 2;
35 const double EARTH_SEMI_AXIS = 6378137.0;
36 const double EARTH_FLATTENING = 6356752.3142;
37 const double EARTH_SEMI_MINOR = (EARTH_SEMI_AXIS - EARTH_FLATTENING) / EARTH_SEMI_AXIS;
38 
Location()39 Location::Location()
40 {
41     latitude_ = MIN_LATITUDE - 1;
42     longitude_ = MIN_LONGITUDE - 1;
43     altitude_ = 0.0;
44     accuracy_ = 0.0;
45     speed_ = 0.0;
46     direction_ = 0.0;
47     timeStamp_ = 0;
48     timeSinceBoot_ = 0;
49     additionSize_ = 0;
50     isFromMock_ = false;
51     isSystemApp_ = 0;
52     floorNo_ = 0;
53     floorAccuracy_ = 0.0;
54     altitudeAccuracy_ = 0.0;
55     speedAccuracy_ = 0.0;
56     directionAccuracy_ = 0.0;
57     uncertaintyOfTimeSinceBoot_ = 0;
58     locationSourceType_ = 0;
59     uuid_ = "";
60     fieldValidity_ = 0;
61 }
62 
Location(const Location & location)63 Location::Location(const Location& location)
64 {
65     latitude_ = location.GetLatitude();
66     longitude_ = location.GetLongitude();
67     altitude_ = location.GetAltitude();
68     accuracy_ = location.GetAccuracy();
69     speed_ = location.GetSpeed();
70     direction_ = location.GetDirection();
71     timeStamp_ = location.GetTimeStamp();
72     timeSinceBoot_ = location.GetTimeSinceBoot();
73     floorNo_ = location.GetFloorNo();
74     floorAccuracy_ = location.GetFloorAccuracy();
75     additions_ = location.GetAdditions();
76     additionsMap_ = location.GetAdditionsMap();
77     additionSize_ = location.GetAdditionSize();
78     isFromMock_ = location.GetIsFromMock();
79     isSystemApp_ = location.GetIsSystemApp();
80     altitudeAccuracy_ = location.GetAltitudeAccuracy();
81     speedAccuracy_ = location.GetSpeedAccuracy();
82     directionAccuracy_ = location.GetDirectionAccuracy();
83     uncertaintyOfTimeSinceBoot_ = location.GetUncertaintyOfTimeSinceBoot();
84     locationSourceType_ = location.GetLocationSourceType();
85     uuid_ = location.GetUuid();
86     fieldValidity_ = location.GetFieldValidity();
87     poiInfo_ = location.GetPoiInfo();
88 }
89 
ReadFromParcel(Parcel & parcel)90 void Location::ReadFromParcel(Parcel& parcel)
91 {
92     latitude_ = parcel.ReadDouble();
93     longitude_ = parcel.ReadDouble();
94     altitude_ = parcel.ReadDouble();
95     accuracy_ = parcel.ReadDouble();
96     speed_ = parcel.ReadDouble();
97     direction_ = parcel.ReadDouble();
98     timeStamp_ = parcel.ReadInt64();
99     timeSinceBoot_ = parcel.ReadInt64();
100     additionSize_ = parcel.ReadInt64();
101     std::vector<std::u16string> additions;
102     parcel.ReadString16Vector(&additions);
103     isFromMock_ = parcel.ReadBool();
104     isSystemApp_ = parcel.ReadInt32();
105     altitudeAccuracy_ = parcel.ReadDouble();
106     speedAccuracy_ = parcel.ReadDouble();
107     directionAccuracy_ = parcel.ReadDouble();
108     uncertaintyOfTimeSinceBoot_ = parcel.ReadInt64();
109     locationSourceType_ = parcel.ReadInt32();
110     uuid_ = Str16ToStr8(parcel.ReadString16());
111     fieldValidity_ = parcel.ReadInt32();
112     VectorString16ToVectorString8(additions);
113     poiInfo_ = ReadPoiInfoFromParcel(parcel);
114 }
115 
VectorString16ToVectorString8(const std::vector<std::u16string> & additions)116 void Location::VectorString16ToVectorString8(const std::vector<std::u16string>& additions)
117 {
118     for (auto &addition : additions) {
119         auto additionString = Str16ToStr8(addition);
120         if (additionString.size() == 0) {
121             continue;
122         }
123         additions_.push_back(additionString);
124         auto pos = additionString.find(":");
125         auto key = additionString.substr(0, pos);
126         auto value = additionString.substr(pos + 1, additionString.size() - 1);
127         additionsMap_[key] = value;
128     }
129 }
130 
UnmarshallingShared(Parcel & parcel)131 std::shared_ptr<Location> Location::UnmarshallingShared(Parcel& parcel)
132 {
133     std::shared_ptr<Location> location = std::make_shared<Location>();
134     location->ReadFromParcel(parcel);
135     return location;
136 }
137 
Unmarshalling(Parcel & parcel)138 Location* Location::Unmarshalling(Parcel& parcel)
139 {
140     auto location = new Location();
141     location->ReadFromParcel(parcel);
142     return location;
143 }
144 
UnmarshallingMakeUnique(Parcel & parcel)145 std::unique_ptr<Location> Location::UnmarshallingMakeUnique(Parcel& parcel)
146 {
147     std::unique_ptr<Location> location = std::make_unique<Location>();
148     location->ReadFromParcel(parcel);
149     return location;
150 }
151 
Marshalling(Parcel & parcel) const152 bool Location::Marshalling(Parcel& parcel) const
153 {
154     auto additions = VectorString8ToVectorString16();
155     return parcel.WriteDouble(latitude_) &&
156            parcel.WriteDouble(longitude_) &&
157            parcel.WriteDouble(altitude_) &&
158            parcel.WriteDouble(accuracy_) &&
159            parcel.WriteDouble(speed_) &&
160            parcel.WriteDouble(direction_) &&
161            parcel.WriteInt64(timeStamp_) &&
162            parcel.WriteInt64(timeSinceBoot_) &&
163            parcel.WriteInt64(additionSize_) &&
164            parcel.WriteString16Vector(additions) &&
165            parcel.WriteBool(isFromMock_) &&
166            parcel.WriteInt32(isSystemApp_) &&
167            parcel.WriteDouble(altitudeAccuracy_) &&
168            parcel.WriteDouble(speedAccuracy_) &&
169            parcel.WriteDouble(directionAccuracy_) &&
170            parcel.WriteInt64(uncertaintyOfTimeSinceBoot_) &&
171            parcel.WriteInt32(locationSourceType_) &&
172            parcel.WriteString16(Str8ToStr16(uuid_)) &&
173            parcel.WriteInt32(fieldValidity_) &&
174            WritePoiInfoToParcel(poiInfo_, parcel);
175 }
176 
VectorString8ToVectorString16() const177 std::vector<std::u16string> Location::VectorString8ToVectorString16() const
178 {
179     std::vector<std::u16string> additions;
180     for (auto &addition : additions_) {
181         auto additionString = Str8ToStr16(addition);
182         additions.push_back(additionString);
183     }
184     return additions;
185 }
186 
WritePoiInfoToParcel(const PoiInfo & data,Parcel & parcel)187 bool Location::WritePoiInfoToParcel(const PoiInfo& data, Parcel& parcel)
188 {
189     bool parcelState = true;
190     parcelState = parcelState && parcel.WriteUint64(data.timestamp);
191     parcelState = parcelState && parcel.WriteUint32(data.poiArray.size());
192     for (const auto& poi : data.poiArray) {
193         parcelState = parcelState && parcel.WriteString(poi.id);
194         parcelState = parcelState && parcel.WriteDouble(poi.confidence);
195         parcelState = parcelState && parcel.WriteString(poi.name);
196         parcelState = parcelState && parcel.WriteDouble(poi.latitude);
197         parcelState = parcelState && parcel.WriteDouble(poi.longitude);
198         parcelState = parcelState && parcel.WriteString(poi.administrativeArea);
199         parcelState = parcelState && parcel.WriteString(poi.subAdministrativeArea);
200         parcelState = parcelState && parcel.WriteString(poi.locality);
201         parcelState = parcelState && parcel.WriteString(poi.subLocality);
202         parcelState = parcelState && parcel.WriteString(poi.address);
203     }
204     return parcelState;
205 }
206 
ReadPoiInfoFromParcel(Parcel & parcel)207 PoiInfo Location::ReadPoiInfoFromParcel(Parcel& parcel)
208 {
209     PoiInfo data;
210     data.timestamp = parcel.ReadUint64();
211     uint32_t size = parcel.ReadUint32();
212     if (size > MAX_POI_ARRAY_SIZE) {
213         size = MAX_POI_ARRAY_SIZE;
214     }
215     data.poiArray.resize(size);
216     for (auto& poi : data.poiArray) {
217         poi.id = parcel.ReadString();
218         poi.confidence = parcel.ReadDouble();
219         poi.name = parcel.ReadString();
220         poi.latitude = parcel.ReadDouble();
221         poi.longitude = parcel.ReadDouble();
222         poi.administrativeArea = parcel.ReadString();
223         poi.subAdministrativeArea = parcel.ReadString();
224         poi.locality = parcel.ReadString();
225         poi.subLocality = parcel.ReadString();
226         poi.address = parcel.ReadString();
227     }
228     return data;
229 }
230 
ToString() const231 std::string Location::ToString() const
232 {
233     std::string str =
234         ", altitude : " + std::to_string(altitude_) +
235         ", accuracy : " + std::to_string(accuracy_) +
236         ", speed : " + std::to_string(speed_) +
237         ", direction : " + std::to_string(direction_) +
238         ", timeStamp : " + std::to_string(timeStamp_) +
239         ", timeSinceBoot : " + std::to_string(timeSinceBoot_) +
240         ", additionSize : " + std::to_string(additionSize_) +
241         ", isFromMock : " + std::to_string(isFromMock_) +
242         ", isSystemApp : " + std::to_string(isSystemApp_) +
243         ", altitudeAccuracy : " + std::to_string(altitudeAccuracy_) +
244         ", speedAccuracy : " + std::to_string(speedAccuracy_) +
245         ", directionAccuracy : " + std::to_string(directionAccuracy_) +
246         ", uncertaintyOfTimeSinceBoot : " + std::to_string(uncertaintyOfTimeSinceBoot_) +
247         ", locationSourceType : " + std::to_string(locationSourceType_) +
248         ", uuid : " + uuid_ +
249         ", fieldValidity : " + std::to_string(fieldValidity_);
250     return str;
251 }
252 
LocationEqual(const std::unique_ptr<Location> & location)253 bool Location::LocationEqual(const std::unique_ptr<Location>& location)
254 {
255     if (location == nullptr) {
256         return false;
257     }
258     if (this->GetLatitude() == location->GetLatitude() &&
259         this->GetLongitude() == location->GetLongitude() &&
260         this->GetAltitude() == location->GetAltitude() &&
261         this->GetAccuracy() == location->GetAccuracy() &&
262         this->GetSpeed() == location->GetSpeed() &&
263         this->GetDirection() == location->GetDirection() &&
264         this->GetTimeStamp() == location->GetTimeStamp() &&
265         this->GetTimeSinceBoot() == location->GetTimeSinceBoot() &&
266         this->AdditionEqual(location) &&
267         this->GetAdditionSize() == location->GetAdditionSize() &&
268         this->GetIsFromMock() == location->GetIsFromMock()) {
269         return true;
270     }
271     return false;
272 }
273 
AdditionEqual(const std::unique_ptr<Location> & location)274 bool Location::AdditionEqual(const std::unique_ptr<Location>& location)
275 {
276     if (location == nullptr) {
277         return false;
278     }
279     std::vector<std::string> additionA = this->GetAdditions();
280     std::vector<std::string> additionB = location->GetAdditions();
281     if (additionA.size() != additionB.size()) {
282         return false;
283     }
284     for (size_t i = 0; i < additionA.size(); i++) {
285         if (additionA[i].compare(additionB[i]) != 0) {
286             return false;
287         }
288     }
289     return true;
290 }
291 
isValidLatitude(double latitude)292 bool Location::isValidLatitude(double latitude)
293 {
294     return latitude >= MIN_LATITUDE && latitude <= MAX_LATITUDE;
295 }
296 
isValidLongitude(double longitude)297 bool Location::isValidLongitude(double longitude)
298 {
299     return longitude >= MIN_LONGITUDE && longitude <= MAX_LONGITUDE;
300 }
301 
GetDistanceBetweenLocations(const double lat1,const double lon1,const double lat2,const double lon2)302 double Location::GetDistanceBetweenLocations(const double lat1, const double lon1, const double lat2, const double lon2)
303 {
304     double radLat1 = lat1 * PI / DEGREE_PI;
305     double radLat2 = lat2 * PI / DEGREE_PI;
306     double radLon1 = lon1 * PI / DEGREE_PI;
307     double radLon2 = lon2 * PI / DEGREE_PI;
308 
309     double deltaLon = radLon2 - radLon1;
310     double reducedLat1 = atan((1 - EARTH_SEMI_MINOR) * tan(radLat1));
311     double reducedLat2 = atan((1 - EARTH_SEMI_MINOR) * tan(radLat2));
312 
313     double sinReducedLat1 = sin(reducedLat1);
314     double cosReducedLat1 = cos(reducedLat1);
315     double sinReducedLat2 = sin(reducedLat2);
316     double cosReducedLat2 = cos(reducedLat2);
317 
318     double lambda = deltaLon;
319     double lambdaP = 100;
320     double iterLimit = 20;
321     double sinAlpha = 0.0;
322     double cosSqAlpha = 0.0;
323     double sinSigma = 0.0;
324     double cos2SigmaM = 0.0;
325     double cosSigma = 0.0;
326     double sigma = 0.0;
327     double sinLambda = 0.0;
328     double cosLambda = 0.0;
329 
330     for (int iter = 0; iter < iterLimit; iter++) {
331         sinLambda = sin(lambda);
332         cosLambda = cos(lambda);
333         sinSigma = sqrt(pow(cosReducedLat2 * sinLambda, POW_PARAMETER_TOW) +
334             pow(cosReducedLat1 * sinReducedLat2 - sinReducedLat1 * cosReducedLat2 * cosLambda, POW_PARAMETER_TOW));
335         if (sinSigma == 0) {
336             return 0;
337         }
338         cosSigma = sinReducedLat1 * sinReducedLat2 + cosReducedLat1 * cosReducedLat2 * cosLambda;
339         sigma = atan2(sinSigma, cosSigma);
340         sinAlpha = cosReducedLat1 * cosReducedLat2 * sinLambda / sinSigma;
341         cosSqAlpha = 1 - sinAlpha * sinAlpha;
342         cos2SigmaM = (cosSqAlpha != 0) ? (cosSigma - NUM_DOUBLE * sinReducedLat1 * sinReducedLat2 / cosSqAlpha) : 0;
343         double correction = EARTH_SEMI_MINOR / 16 * cosSqAlpha * (4 + EARTH_SEMI_MINOR * (4 - 3 * cosSqAlpha));
344 
345         lambdaP = lambda;
346         lambda = deltaLon + (1 - correction) * EARTH_SEMI_MINOR * sinAlpha  *
347             (sigma + correction * sinSigma *
348             (cos2SigmaM + correction * cosSigma * (-1 + NUM_DOUBLE * pow(cos2SigmaM, POW_PARAMETER_TOW))));
349         if (fabs(lambda - lambdaP) < 1e-12) {
350             break;
351         }
352     }
353     double uSquared = cosSqAlpha * (EARTH_SEMI_AXIS * EARTH_SEMI_AXIS - EARTH_FLATTENING * EARTH_FLATTENING) /
354         (EARTH_FLATTENING * EARTH_FLATTENING);
355     double highOrderCorrection = 1 + uSquared / 16384 * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)));
356     double highOrderTerm = uSquared / 1024 * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)));
357     double deltaSigma = highOrderTerm * sinSigma *
358         (cos2SigmaM + highOrderTerm / 4 * (cosSigma * (-1 + 2 * pow(cos2SigmaM, POW_PARAMETER_TOW)) -
359             highOrderTerm / 6 * cos2SigmaM * (-3 + 4 * pow(sinSigma, POW_PARAMETER_TOW)) *
360             (-3 + 4 * pow(cos2SigmaM, POW_PARAMETER_TOW))));
361 
362     double distance = EARTH_FLATTENING * highOrderCorrection * (sigma - deltaSigma);
363     return distance;
364 }
365 } // namespace Location
366 } // namespace OHOS