2 * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <system_info.h>
21 #include "location_bounds.h"
22 #include "location_internal.h"
26 static void __free_position_list(gpointer data)
31 LocationPosition *position = (LocationPosition *) data;
32 location_position_free(position);
36 static location_bounds_type_e __convert_bounds_type(LocationBoundaryType type)
38 location_bounds_type_e ret;
40 case LOCATION_BOUNDARY_CIRCLE:
41 ret = LOCATION_BOUNDS_CIRCLE;
43 case LOCATION_BOUNDARY_POLYGON:
44 ret = LOCATION_BOUNDS_POLYGON;
46 case LOCATION_BOUNDARY_NONE:
47 case LOCATION_BOUNDARY_RECT:
49 ret = LOCATION_BOUNDS_RECT;
55 EXPORT_API int location_bounds_create_rect(location_coords_s top_left, location_coords_s bottom_right, location_bounds_h *bounds)
57 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
58 LOCATIONS_NULL_ARG_CHECK(bounds);
59 LOCATIONS_CHECK_CONDITION(top_left.latitude >= -90 && top_left.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
60 LOCATIONS_CHECK_CONDITION(top_left.longitude >= -180 && top_left.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
61 LOCATIONS_CHECK_CONDITION(bottom_right.latitude >= -90 && bottom_right.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
62 LOCATIONS_CHECK_CONDITION(bottom_right.longitude >= -180 && bottom_right.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
64 if ((bottom_right.longitude - top_left.longitude) < 180 && (bottom_right.longitude - top_left.longitude) > -180) {
65 if (bottom_right.longitude <= top_left.longitude || bottom_right.latitude >= top_left.latitude)
66 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
68 if (bottom_right.latitude >= top_left.latitude)
69 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
72 LocationPosition *lt = location_position_new(0, top_left.latitude, top_left.longitude, 0, LOCATION_STATUS_2D_FIX);
75 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
76 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
80 LocationPosition *rb = location_position_new(0, bottom_right.latitude, bottom_right.longitude, 0, LOCATION_STATUS_2D_FIX);
83 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
84 location_position_free(lt);
85 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
89 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
92 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
93 location_position_free(rb);
94 location_position_free(lt);
95 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
98 memset(handle, 0, sizeof(location_bounds_s));
100 handle->is_added = FALSE;
101 handle->boundary = location_boundary_new_for_rect(lt, rb);
102 location_position_free(rb);
103 location_position_free(lt);
104 if (handle->boundary == NULL) {
106 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_rect", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
108 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
112 *bounds = (location_bounds_h) handle;
113 return LOCATION_BOUNDS_ERROR_NONE;
116 EXPORT_API int location_bounds_create_circle(location_coords_s center, double radius, location_bounds_h *bounds)
118 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
119 LOCATIONS_NULL_ARG_CHECK(bounds);
120 LOCATIONS_CHECK_CONDITION(radius > 0, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
121 LOCATIONS_CHECK_CONDITION(center.latitude >= -90 && center.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
122 LOCATIONS_CHECK_CONDITION(center.longitude >= -180 && center.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
124 LocationPosition *ct = location_position_new(0, center.latitude, center.longitude, 0, LOCATION_STATUS_2D_FIX);
127 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
128 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
132 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
133 if (handle == NULL) {
135 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
136 location_position_free(ct);
137 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
140 memset(handle, 0, sizeof(location_bounds_s));
142 handle->is_added = FALSE;
143 handle->boundary = location_boundary_new_for_circle(ct, radius);
144 location_position_free(ct);
145 if (handle->boundary == NULL) {
148 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_circle", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
149 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
153 *bounds = (location_bounds_h) handle;
154 return LOCATION_BOUNDS_ERROR_NONE;
157 EXPORT_API int location_bounds_create_polygon(location_coords_s *coords_list, int length, location_bounds_h *bounds)
159 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
160 LOCATIONS_NULL_ARG_CHECK(coords_list);
161 LOCATIONS_NULL_ARG_CHECK(bounds);
162 LOCATIONS_CHECK_CONDITION(length >= 3, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
165 GList *position_list = NULL;
166 LocationPosition *position = NULL;
169 for (i = 0; i < length; i++) {
170 if (coords_list[i].latitude < -90 || coords_list[i].latitude > 90 || coords_list[i].longitude < -180 || coords_list[i].longitude > 180) {
171 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INVALID_PARAMETER(0x%08x)", LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
175 position = location_position_new(0, coords_list[i].latitude, coords_list[i].longitude, 0.0, LOCATION_STATUS_2D_FIX);
176 position_list = g_list_append(position_list, position);
177 /* We should not remove position.
178 location_position_free(position);
184 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
185 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
188 if (position_list == NULL) {
190 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
191 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
192 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
196 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
197 if (handle == NULL) {
199 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
200 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
203 memset(handle, 0, sizeof(location_bounds_s));
205 handle->is_added = FALSE;
206 handle->boundary = location_boundary_new_for_polygon(position_list);
207 if (handle->boundary == NULL) {
210 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_polygon", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
211 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
215 *bounds = (location_bounds_h) handle;
216 return LOCATION_BOUNDS_ERROR_NONE;
219 EXPORT_API bool location_bounds_contains_coordinates(location_bounds_h bounds, location_coords_s coords)
221 if (__is_location_supported() == LOCATIONS_ERROR_NOT_SUPPORTED) {
223 set_last_result(LOCATIONS_ERROR_NOT_SUPPORTED);
229 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
233 if (coords.latitude < -90 || coords.latitude > 90 || coords.longitude < -180 || coords.longitude > 180) {
234 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
238 LocationPosition *pos = location_position_new(0, coords.latitude, coords.longitude, 0, LOCATION_STATUS_2D_FIX);
241 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
242 set_last_result(LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
246 location_bounds_s *handle = (location_bounds_s *) bounds;
247 gboolean is_inside = location_boundary_if_inside(handle->boundary, pos);
248 location_position_free(pos);
249 bool result = is_inside ? TRUE : FALSE;
251 set_last_result(LOCATION_BOUNDS_ERROR_NONE);
255 EXPORT_API int location_bounds_get_type(location_bounds_h bounds, location_bounds_type_e *type)
257 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
258 LOCATIONS_NULL_ARG_CHECK(bounds);
259 LOCATIONS_NULL_ARG_CHECK(type);
261 location_bounds_s *handle = (location_bounds_s *) bounds;
262 *type = __convert_bounds_type(handle->boundary->type);
263 return LOCATION_BOUNDS_ERROR_NONE;
266 EXPORT_API int location_bounds_get_rect_coords(location_bounds_h bounds, location_coords_s *top_left, location_coords_s *bottom_right)
268 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
269 LOCATIONS_NULL_ARG_CHECK(bounds);
270 LOCATIONS_NULL_ARG_CHECK(top_left);
271 LOCATIONS_NULL_ARG_CHECK(bottom_right);
273 location_bounds_s *handle = (location_bounds_s *) bounds;
274 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_RECT) {
275 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
276 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
279 top_left->latitude = handle->boundary->rect.left_top->latitude;
280 top_left->longitude = handle->boundary->rect.left_top->longitude;
281 bottom_right->latitude = handle->boundary->rect.right_bottom->latitude;
282 bottom_right->longitude = handle->boundary->rect.right_bottom->longitude;
283 return LOCATION_BOUNDS_ERROR_NONE;
286 EXPORT_API int location_bounds_get_circle_coords(location_bounds_h bounds, location_coords_s *center, double *radius)
288 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
289 LOCATIONS_NULL_ARG_CHECK(bounds);
290 LOCATIONS_NULL_ARG_CHECK(center);
291 LOCATIONS_NULL_ARG_CHECK(radius);
293 location_bounds_s *handle = (location_bounds_s *) bounds;
294 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_CIRCLE) {
295 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
296 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
299 center->latitude = handle->boundary->circle.center->latitude;
300 center->longitude = handle->boundary->circle.center->longitude;
301 *radius = handle->boundary->circle.radius;
302 return LOCATION_BOUNDS_ERROR_NONE;
305 EXPORT_API int location_bounds_foreach_polygon_coords(location_bounds_h bounds, polygon_coords_cb callback, void *user_data)
307 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
308 LOCATIONS_NULL_ARG_CHECK(bounds);
309 LOCATIONS_NULL_ARG_CHECK(callback);
311 location_bounds_s *handle = (location_bounds_s *) bounds;
312 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_POLYGON) {
313 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
314 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
317 GList *list = handle->boundary->polygon.position_list;
319 LocationPosition *pos = list->data;
320 location_coords_s coords;
321 coords.latitude = pos->latitude;
322 coords.longitude = pos->longitude;
324 if (callback(coords, user_data) != TRUE) {
325 LOCATIONS_LOGI("User quit the loop ");
328 list = g_list_next(list);
330 return LOCATION_BOUNDS_ERROR_NONE;
333 EXPORT_API int location_bounds_destroy(location_bounds_h bounds)
335 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
336 LOCATIONS_NULL_ARG_CHECK(bounds);
338 location_bounds_s *handle = (location_bounds_s *) bounds;
339 if (handle->is_added) {
340 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_IS_ADDED(0x%08x)", LOCATION_BOUNDS_ERROR_IS_ADDED);
341 return LOCATION_BOUNDS_ERROR_IS_ADDED;
343 location_boundary_free(handle->boundary);
344 handle->user_cb = NULL;
345 handle->user_data = NULL;
348 return LOCATION_BOUNDS_ERROR_NONE;
351 EXPORT_API int location_bounds_set_state_changed_cb(location_bounds_h bounds, location_bounds_state_changed_cb callback, void *user_data)
353 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
354 LOCATIONS_NULL_ARG_CHECK(bounds);
355 LOCATIONS_NULL_ARG_CHECK(callback);
357 location_bounds_s *handle = (location_bounds_s *) bounds;
358 handle->user_cb = callback;
359 handle->user_data = user_data;
360 return LOCATION_BOUNDS_ERROR_NONE;
363 EXPORT_API int location_bounds_unset_state_changed_cb(location_bounds_h bounds)
365 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
366 LOCATIONS_NULL_ARG_CHECK(bounds);
368 location_bounds_s *handle = (location_bounds_s *) bounds;
369 handle->user_cb = NULL;
370 handle->user_data = NULL;
371 return LOCATION_BOUNDS_ERROR_NONE;