4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7 * Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
30 #include "location-position.h"
31 #include "location-setting.h"
32 #include "location-log.h"
34 #define DEG2RAD(x) ((x) * M_PI / 180)
37 location_position_get_type (void)
39 static volatile gsize type_volatile = 0;
40 if(g_once_init_enter(&type_volatile)) {
41 GType type = g_boxed_type_register_static (
42 g_intern_static_string ("LocationPosition"),
43 (GBoxedCopyFunc) location_position_copy,
44 (GBoxedFreeFunc) location_position_free);
45 g_once_init_leave(&type_volatile, type);
50 EXPORT_API LocationPosition *
51 location_position_new (guint timestamp,
55 LocationStatus status)
57 if (latitude < -90 || latitude > 90) return NULL;
58 if (longitude < -180 || longitude > 180) return NULL;
60 LocationPosition* position = g_slice_new0(LocationPosition);
61 position->timestamp = timestamp;
62 position->latitude = latitude;
63 position->longitude = longitude;
64 position->altitude = altitude;
65 position->status = status;
70 location_position_free (LocationPosition* position)
72 g_return_if_fail(position);
73 g_slice_free(LocationPosition, position);
77 location_position_equal (const LocationPosition *position1, const LocationPosition *position2)
79 g_return_val_if_fail(position1, FALSE);
80 g_return_val_if_fail(position2, FALSE);
82 if (position1->latitude == position2->latitude &&
83 position1->longitude == position2->longitude &&
84 position1->altitude == position2->altitude)
89 EXPORT_API LocationPosition*
90 location_position_copy (const LocationPosition *position)
92 g_return_val_if_fail(position, NULL);
94 LocationPosition *new_position = NULL;
96 new_position = location_position_new (position->timestamp,
106 /* Vincenty formula. WGS-84 */
108 location_get_distance(const LocationPosition *pos1, const LocationPosition *pos2, gulong *distance)
110 g_return_val_if_fail(pos1, LOCATION_ERROR_PARAMETER);
111 g_return_val_if_fail(pos2, LOCATION_ERROR_PARAMETER);
112 g_return_val_if_fail(distance, LOCATION_ERROR_PARAMETER);
116 const double a = 6378137.0, b = 6356752.314245, f = 1/298.257223563;
117 double delta_lon = DEG2RAD(pos2->longitude-pos1->longitude);
118 double u_1 = atan((1-f) * tan(DEG2RAD(pos1->latitude)));
119 double u_2 = atan((1-f) * tan(DEG2RAD(pos2->latitude)));
121 double lambdaP, iter_limit = 100.0;
122 double lambda = delta_lon;
124 double sin_sigma, sin_alpha, cos_sigma, sigma, sq_cos_alpha, cos_2sigma, C;
125 double sq_u, cal1, cal2, delta_sigma, cal_dist;
126 double sin_lambda, cos_lambda;
128 double sin_u1 = sin(u_1);
129 double cos_u1 = cos(u_1);
130 double sin_u2 = sin(u_2);
131 double cos_u2 = cos(u_2);
134 sin_lambda = sin(lambda);
135 cos_lambda = cos(lambda);
137 sin_sigma = sqrt((cos_u2*sin_lambda)*(cos_u2*sin_lambda) + \
138 (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda) * \
139 (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda));
142 return LOCATION_ERROR_NONE; // co-incident points
144 cos_sigma = sin_u1*sin_u2 + cos_u1*cos_u2*cos_lambda;
145 sigma = atan2(sin_sigma, cos_sigma);
147 sin_alpha = cos_u1 * cos_u2 * sin_lambda / sin_sigma;
148 sq_cos_alpha = 1.0 - sin_alpha*sin_alpha;
149 cos_2sigma = cos_sigma - 2.0*sin_u1*sin_u2/sq_cos_alpha;
151 if (isnan(cos_2sigma))
154 C = f/16.0*sq_cos_alpha*(4.0+f*(4.0-3.0*sq_cos_alpha));
157 lambda = delta_lon + (1.0-C) * f * sin_alpha * \
158 (sigma + C*sin_sigma*(cos_2sigma+C*cos_sigma*(-1.0+2.0*cos_2sigma*cos_2sigma)));
160 } while (abs(lambda-lambdaP) > 1e-12 && --iter_limit>0);
162 if (iter_limit==0) return LOCATION_ERROR_UNKNOWN;
164 sq_u = sq_cos_alpha * (a*a - b*b) / (b*b);
166 cal1 = 1.0 + sq_u/16384.0*(4096.0+sq_u*(-768.0+sq_u*(320.0-175.0*sq_u)));
167 cal2 = sq_u/1024.0 * (256.0+sq_u*(-128.0+sq_u*(74.0-47.0*sq_u)));
169 delta_sigma = cal2*sin_sigma*(cos_2sigma+cal2/4.0*(cos_sigma*(-1.0+2.0*cos_2sigma*cos_2sigma)- \
170 cal2/6.0*cos_2sigma*(-3.0+4.0*sin_sigma*sin_sigma)*(-3.0+4.0*cos_2sigma*cos_2sigma)));
171 cal_dist = b*cal1*(sigma-delta_sigma);
173 *distance = (gulong) cal_dist;
175 return LOCATION_ERROR_NONE;
180 location_last_position_a2i(char *position, int *lat, int *lon)
183 char latitude[HALF_KEY_LENGTH];
184 char longitude[HALF_KEY_LENGTH];
186 memcpy(latitude, position + 1, HALF_KEY_LENGTH - 1);
187 memcpy(longitude, position + HALF_KEY_LENGTH + 1, HALF_KEY_LENGTH - 1);
188 latitude[HALF_KEY_LENGTH - 1] = '\0';
189 longitude[HALF_KEY_LENGTH - 1] = '\0';
191 d_lon = position + HALF_KEY_LENGTH;
193 *lat = atoi(latitude);
194 *lon = atoi(longitude);