4 * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include "location-position.h"
28 #include "location-setting.h"
29 #include "location-log.h"
31 #define DEG2RAD(x) ((x) * M_PI / 180)
34 location_position_get_type(void)
36 static volatile gsize type_volatile = 0;
37 if (g_once_init_enter(&type_volatile)) {
38 GType type = g_boxed_type_register_static(
39 g_intern_static_string("LocationPosition"),
40 (GBoxedCopyFunc) location_position_copy,
41 (GBoxedFreeFunc) location_position_free);
42 g_once_init_leave(&type_volatile, type);
47 EXPORT_API LocationPosition *
48 location_position_new(guint timestamp, gdouble latitude, gdouble longitude, gdouble altitude, LocationStatus status)
50 if (latitude < -90 || latitude > 90) return NULL;
51 if (longitude < -180 || longitude > 180) return NULL;
53 LocationPosition *position = g_slice_new0(LocationPosition);
54 g_return_val_if_fail(position, NULL);
56 position->timestamp = timestamp;
57 position->latitude = latitude;
58 position->longitude = longitude;
59 position->altitude = altitude;
60 position->status = status;
65 location_position_free(LocationPosition *position)
67 g_return_if_fail(position);
68 g_slice_free(LocationPosition, position);
72 location_position_equal(const LocationPosition *position1, const LocationPosition *position2)
74 g_return_val_if_fail(position1, FALSE);
75 g_return_val_if_fail(position2, FALSE);
77 if (position1->latitude == position2->latitude &&
78 position1->longitude == position2->longitude &&
79 position1->altitude == position2->altitude)
84 EXPORT_API LocationPosition *
85 location_position_copy(const LocationPosition *position)
87 g_return_val_if_fail(position, NULL);
89 LocationPosition *new_position = NULL;
91 new_position = location_position_new(position->timestamp, position->latitude, position->longitude, position->altitude, position->status);
97 /* Vincenty formula. WGS-84 */
99 location_get_distance(const LocationPosition *pos1, const LocationPosition *pos2, gulong *distance)
101 g_return_val_if_fail(pos1, LOCATION_ERROR_PARAMETER);
102 g_return_val_if_fail(pos2, LOCATION_ERROR_PARAMETER);
103 g_return_val_if_fail(distance, LOCATION_ERROR_PARAMETER);
107 const double a = 6378137.0, b = 6356752.314245, f = 1 / 298.257223563;
108 double delta_lon = DEG2RAD(pos2->longitude - pos1->longitude);
109 double u_1 = atan((1 - f) * tan(DEG2RAD(pos1->latitude)));
110 double u_2 = atan((1 - f) * tan(DEG2RAD(pos2->latitude)));
112 double lambdaP, iter_limit = 100.0;
113 double lambda = delta_lon;
115 double sin_sigma, sin_alpha, cos_sigma, sigma, sq_cos_alpha, cos_2sigma, C;
116 double sq_u, cal1, cal2, delta_sigma, cal_dist;
117 double sin_lambda, cos_lambda;
119 double sin_u1 = sin(u_1);
120 double cos_u1 = cos(u_1);
121 double sin_u2 = sin(u_2);
122 double cos_u2 = cos(u_2);
125 sin_lambda = sin(lambda);
126 cos_lambda = cos(lambda);
128 sin_sigma = sqrt((cos_u2 * sin_lambda) * (cos_u2 * sin_lambda) + \
129 (cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda) * \
130 (cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos_lambda));
133 return LOCATION_ERROR_NONE; /* co-incident points */
135 cos_sigma = sin_u1 * sin_u2 + cos_u1 * cos_u2 * cos_lambda;
136 sigma = atan2(sin_sigma, cos_sigma);
138 sin_alpha = cos_u1 * cos_u2 * sin_lambda / sin_sigma;
139 sq_cos_alpha = 1.0 - sin_alpha * sin_alpha;
140 cos_2sigma = cos_sigma - 2.0 * sin_u1 * sin_u2 / sq_cos_alpha;
142 if (isnan(cos_2sigma))
145 C = f / 16.0 * sq_cos_alpha * (4.0 + f * (4.0 - 3.0 * sq_cos_alpha));
148 lambda = delta_lon + (1.0 - C) * f * sin_alpha * \
149 (sigma + C * sin_sigma * (cos_2sigma + C * cos_sigma * (-1.0 + 2.0 * cos_2sigma * cos_2sigma)));
151 } while (abs(lambda - lambdaP) > 1e-12 && --iter_limit > 0);
153 if (iter_limit == 0) return LOCATION_ERROR_UNKNOWN;
155 sq_u = sq_cos_alpha * (a * a - b * b) / (b * b);
157 cal1 = 1.0 + sq_u / 16384.0 * (4096.0 + sq_u * (-768.0 + sq_u * (320.0 - 175.0 * sq_u)));
158 cal2 = sq_u / 1024.0 * (256.0 + sq_u * (-128.0 + sq_u * (74.0 - 47.0 * sq_u)));
160 delta_sigma = cal2 * sin_sigma * (cos_2sigma + cal2 / 4.0 * (cos_sigma * (-1.0 + 2.0 * cos_2sigma * cos_2sigma) - \
161 cal2 / 6.0 * cos_2sigma * (-3.0 + 4.0 * sin_sigma * sin_sigma) * (-3.0 + 4.0 * cos_2sigma * cos_2sigma)));
162 cal_dist = b * cal1 * (sigma - delta_sigma);
164 *distance = (gulong) cal_dist;
166 return LOCATION_ERROR_NONE;
171 location_last_position_a2i(char *position, int *lat, int *lon)
174 char latitude[HALF_KEY_LENGTH];
175 char longitude[HALF_KEY_LENGTH];
177 memcpy(latitude, position + 1, HALF_KEY_LENGTH - 1);
178 memcpy(longitude, position + HALF_KEY_LENGTH + 1, HALF_KEY_LENGTH - 1);
179 latitude[HALF_KEY_LENGTH - 1] = '\0';
180 longitude[HALF_KEY_LENGTH - 1] = '\0';
182 d_lon = position + HALF_KEY_LENGTH;
184 *lat = atoi(latitude);
185 *lon = atoi(longitude);