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"
25 static void __free_position_list(gpointer data)
30 LocationPosition *position = (LocationPosition *) data;
31 location_position_free(position);
34 static location_bounds_type_e __convert_bounds_type(LocationBoundaryType type)
36 location_bounds_type_e ret;
38 case LOCATION_BOUNDARY_CIRCLE:
39 ret = LOCATION_BOUNDS_CIRCLE;
41 case LOCATION_BOUNDARY_POLYGON:
42 ret = LOCATION_BOUNDS_POLYGON;
44 case LOCATION_BOUNDARY_NONE:
45 case LOCATION_BOUNDARY_RECT:
47 ret = LOCATION_BOUNDS_RECT;
53 EXPORT_API int location_bounds_create_rect(location_coords_s top_left, location_coords_s bottom_right, location_bounds_h *bounds)
55 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
56 LOCATIONS_NULL_ARG_CHECK(bounds);
57 LOCATIONS_CHECK_CONDITION(top_left.latitude >= -90 && top_left.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
58 LOCATIONS_CHECK_CONDITION(top_left.longitude >= -180 && top_left.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
59 LOCATIONS_CHECK_CONDITION(bottom_right.latitude >= -90 && bottom_right.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
60 LOCATIONS_CHECK_CONDITION(bottom_right.longitude >= -180 && bottom_right.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
62 if ((bottom_right.longitude - top_left.longitude) < 180 && (bottom_right.longitude - top_left.longitude) > -180) {
63 if (bottom_right.longitude <= top_left.longitude || bottom_right.latitude >= top_left.latitude)
64 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
66 if (bottom_right.latitude >= top_left.latitude)
67 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
70 LocationPosition *lt = location_position_new(0, top_left.latitude, top_left.longitude, 0, LOCATION_STATUS_2D_FIX);
72 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
73 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
76 LocationPosition *rb = location_position_new(0, bottom_right.latitude, bottom_right.longitude, 0, LOCATION_STATUS_2D_FIX);
78 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
79 location_position_free(lt);
80 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
83 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
85 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
86 location_position_free(rb);
87 location_position_free(lt);
88 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
90 memset(handle, 0, sizeof(location_bounds_s));
92 handle->is_added = FALSE;
93 handle->boundary = location_boundary_new_for_rect(lt, rb);
94 location_position_free(rb);
95 location_position_free(lt);
96 if (handle->boundary == NULL) {
97 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_rect", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
99 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
102 *bounds = (location_bounds_h) handle;
103 return LOCATION_BOUNDS_ERROR_NONE;
106 EXPORT_API int location_bounds_create_circle(location_coords_s center, double radius, location_bounds_h *bounds)
108 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
109 LOCATIONS_NULL_ARG_CHECK(bounds);
110 LOCATIONS_CHECK_CONDITION(radius > 0, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
111 LOCATIONS_CHECK_CONDITION(center.latitude >= -90 && center.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
112 LOCATIONS_CHECK_CONDITION(center.longitude >= -180 && center.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
114 LocationPosition *ct = location_position_new(0, center.latitude, center.longitude, 0, LOCATION_STATUS_2D_FIX);
116 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
117 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
120 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
121 if (handle == NULL) {
122 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
123 location_position_free(ct);
124 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
126 memset(handle, 0, sizeof(location_bounds_s));
128 handle->is_added = FALSE;
129 handle->boundary = location_boundary_new_for_circle(ct, radius);
130 location_position_free(ct);
131 if (handle->boundary == NULL) {
133 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_circle", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
134 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
137 *bounds = (location_bounds_h) handle;
138 return LOCATION_BOUNDS_ERROR_NONE;
141 EXPORT_API int location_bounds_create_polygon(location_coords_s *coords_list, int length, location_bounds_h *bounds)
143 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
144 LOCATIONS_NULL_ARG_CHECK(coords_list);
145 LOCATIONS_NULL_ARG_CHECK(bounds);
146 LOCATIONS_CHECK_CONDITION(length >= 3, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
149 GList *position_list = NULL;
150 LocationPosition *position = NULL;
153 for (i = 0; i < length; i++) {
154 if (coords_list[i].latitude < -90 || coords_list[i].latitude > 90 || coords_list[i].longitude < -180 || coords_list[i].longitude > 180) {
155 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INVALID_PARAMETER(0x%08x)", LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
159 position = location_position_new(0, coords_list[i].latitude, coords_list[i].longitude, 0.0, LOCATION_STATUS_2D_FIX);
160 position_list = g_list_append(position_list, position);
161 /* We should not remove position.
162 location_position_free(position);
168 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
169 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
172 if (position_list == NULL) {
173 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
174 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
175 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
178 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
179 if (handle == NULL) {
180 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
181 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
183 memset(handle, 0, sizeof(location_bounds_s));
185 handle->is_added = FALSE;
186 handle->boundary = location_boundary_new_for_polygon(position_list);
187 if (handle->boundary == NULL) {
189 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_polygon", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
190 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
193 *bounds = (location_bounds_h) handle;
194 return LOCATION_BOUNDS_ERROR_NONE;
197 EXPORT_API bool location_bounds_contains_coordinates(location_bounds_h bounds, location_coords_s coords)
199 if (__is_location_supported() == LOCATIONS_ERROR_NOT_SUPPORTED) {
200 set_last_result(LOCATIONS_ERROR_NOT_SUPPORTED);
205 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
209 if (coords.latitude < -90 || coords.latitude > 90 || coords.longitude < -180 || coords.longitude > 180) {
210 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
214 LocationPosition *pos = location_position_new(0, coords.latitude, coords.longitude, 0, LOCATION_STATUS_2D_FIX);
216 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
217 set_last_result(LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
220 location_bounds_s *handle = (location_bounds_s *) bounds;
221 gboolean is_inside = location_boundary_if_inside(handle->boundary, pos);
222 location_position_free(pos);
223 bool result = is_inside ? TRUE : FALSE;
225 set_last_result(LOCATION_BOUNDS_ERROR_NONE);
229 EXPORT_API int location_bounds_get_type(location_bounds_h bounds, location_bounds_type_e *type)
231 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
232 LOCATIONS_NULL_ARG_CHECK(bounds);
233 LOCATIONS_NULL_ARG_CHECK(type);
235 location_bounds_s *handle = (location_bounds_s *) bounds;
236 *type = __convert_bounds_type(handle->boundary->type);
237 return LOCATION_BOUNDS_ERROR_NONE;
240 EXPORT_API int location_bounds_get_rect_coords(location_bounds_h bounds, location_coords_s *top_left, location_coords_s *bottom_right)
242 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
243 LOCATIONS_NULL_ARG_CHECK(bounds);
244 LOCATIONS_NULL_ARG_CHECK(top_left);
245 LOCATIONS_NULL_ARG_CHECK(bottom_right);
247 location_bounds_s *handle = (location_bounds_s *) bounds;
248 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_RECT) {
249 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
250 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
253 top_left->latitude = handle->boundary->rect.left_top->latitude;
254 top_left->longitude = handle->boundary->rect.left_top->longitude;
255 bottom_right->latitude = handle->boundary->rect.right_bottom->latitude;
256 bottom_right->longitude = handle->boundary->rect.right_bottom->longitude;
257 return LOCATION_BOUNDS_ERROR_NONE;
260 EXPORT_API int location_bounds_get_circle_coords(location_bounds_h bounds, location_coords_s *center, double *radius)
262 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
263 LOCATIONS_NULL_ARG_CHECK(bounds);
264 LOCATIONS_NULL_ARG_CHECK(center);
265 LOCATIONS_NULL_ARG_CHECK(radius);
267 location_bounds_s *handle = (location_bounds_s *) bounds;
268 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_CIRCLE) {
269 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
270 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
273 center->latitude = handle->boundary->circle.center->latitude;
274 center->longitude = handle->boundary->circle.center->longitude;
275 *radius = handle->boundary->circle.radius;
276 return LOCATION_BOUNDS_ERROR_NONE;
279 EXPORT_API int location_bounds_foreach_polygon_coords(location_bounds_h bounds, polygon_coords_cb callback, void *user_data)
281 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
282 LOCATIONS_NULL_ARG_CHECK(bounds);
283 LOCATIONS_NULL_ARG_CHECK(callback);
285 location_bounds_s *handle = (location_bounds_s *) bounds;
286 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_POLYGON) {
287 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
288 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
291 GList *list = handle->boundary->polygon.position_list;
293 LocationPosition *pos = list->data;
294 location_coords_s coords;
295 coords.latitude = pos->latitude;
296 coords.longitude = pos->longitude;
298 if (callback(coords, user_data) != TRUE) {
299 LOCATIONS_LOGI("User quit the loop ");
302 list = g_list_next(list);
304 return LOCATION_BOUNDS_ERROR_NONE;
307 EXPORT_API int location_bounds_destroy(location_bounds_h bounds)
309 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
310 LOCATIONS_NULL_ARG_CHECK(bounds);
312 location_bounds_s *handle = (location_bounds_s *) bounds;
313 if (handle->is_added) {
314 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_IS_ADDED(0x%08x)", LOCATION_BOUNDS_ERROR_IS_ADDED);
315 return LOCATION_BOUNDS_ERROR_IS_ADDED;
317 location_boundary_free(handle->boundary);
318 handle->user_cb = NULL;
319 handle->user_data = NULL;
322 return LOCATION_BOUNDS_ERROR_NONE;
325 EXPORT_API int location_bounds_set_state_changed_cb(location_bounds_h bounds, location_bounds_state_changed_cb callback, void *user_data)
327 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
328 LOCATIONS_NULL_ARG_CHECK(bounds);
329 LOCATIONS_NULL_ARG_CHECK(callback);
331 location_bounds_s *handle = (location_bounds_s *) bounds;
332 handle->user_cb = callback;
333 handle->user_data = user_data;
334 return LOCATION_BOUNDS_ERROR_NONE;
337 EXPORT_API int location_bounds_unset_state_changed_cb(location_bounds_h bounds)
339 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
340 LOCATIONS_NULL_ARG_CHECK(bounds);
342 location_bounds_s *handle = (location_bounds_s *) bounds;
343 handle->user_cb = NULL;
344 handle->user_data = NULL;
345 return LOCATION_BOUNDS_ERROR_NONE;