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