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 bool location_bounds_contains_coordinates_on_edge(location_bounds_h bounds, location_coords_s coords, double tolerance)
257 if (__is_location_supported() == LOCATIONS_ERROR_NOT_SUPPORTED) {
259 set_last_result(LOCATIONS_ERROR_NOT_SUPPORTED);
265 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
269 if (coords.latitude < -90 || coords.latitude > 90 || coords.longitude < -180 || coords.longitude > 180) {
270 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
274 if (tolerance < 0.0) {
275 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
279 LocationPosition *pos = location_position_new(0, coords.latitude, coords.longitude, 0, LOCATION_STATUS_2D_FIX);
282 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
283 set_last_result(LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
287 location_bounds_s *handle = (location_bounds_s *) bounds;
288 gboolean on_path = location_boundary_on_path(handle->boundary, pos, tolerance);
289 location_position_free(pos);
290 bool result = on_path ? TRUE : FALSE;
292 set_last_result(LOCATION_BOUNDS_ERROR_NONE);
296 EXPORT_API int location_bounds_get_type(location_bounds_h bounds, location_bounds_type_e *type)
298 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
299 LOCATIONS_NULL_ARG_CHECK(bounds);
300 LOCATIONS_NULL_ARG_CHECK(type);
302 location_bounds_s *handle = (location_bounds_s *) bounds;
303 *type = __convert_bounds_type(handle->boundary->type);
304 return LOCATION_BOUNDS_ERROR_NONE;
307 EXPORT_API int location_bounds_get_rect_coords(location_bounds_h bounds, location_coords_s *top_left, location_coords_s *bottom_right)
309 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
310 LOCATIONS_NULL_ARG_CHECK(bounds);
311 LOCATIONS_NULL_ARG_CHECK(top_left);
312 LOCATIONS_NULL_ARG_CHECK(bottom_right);
314 location_bounds_s *handle = (location_bounds_s *) bounds;
315 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_RECT) {
316 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
317 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
320 top_left->latitude = handle->boundary->rect.left_top->latitude;
321 top_left->longitude = handle->boundary->rect.left_top->longitude;
322 bottom_right->latitude = handle->boundary->rect.right_bottom->latitude;
323 bottom_right->longitude = handle->boundary->rect.right_bottom->longitude;
324 return LOCATION_BOUNDS_ERROR_NONE;
327 EXPORT_API int location_bounds_get_circle_coords(location_bounds_h bounds, location_coords_s *center, double *radius)
329 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
330 LOCATIONS_NULL_ARG_CHECK(bounds);
331 LOCATIONS_NULL_ARG_CHECK(center);
332 LOCATIONS_NULL_ARG_CHECK(radius);
334 location_bounds_s *handle = (location_bounds_s *) bounds;
335 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_CIRCLE) {
336 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
337 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
340 center->latitude = handle->boundary->circle.center->latitude;
341 center->longitude = handle->boundary->circle.center->longitude;
342 *radius = handle->boundary->circle.radius;
343 return LOCATION_BOUNDS_ERROR_NONE;
346 EXPORT_API int location_bounds_foreach_polygon_coords(location_bounds_h bounds, polygon_coords_cb callback, void *user_data)
348 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
349 LOCATIONS_NULL_ARG_CHECK(bounds);
350 LOCATIONS_NULL_ARG_CHECK(callback);
352 location_bounds_s *handle = (location_bounds_s *) bounds;
353 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_POLYGON) {
354 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
355 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
358 GList *list = handle->boundary->polygon.position_list;
360 LocationPosition *pos = list->data;
361 location_coords_s coords;
362 coords.latitude = pos->latitude;
363 coords.longitude = pos->longitude;
365 if (callback(coords, user_data) != TRUE) {
366 LOCATIONS_LOGI("User quit the loop ");
369 list = g_list_next(list);
371 return LOCATION_BOUNDS_ERROR_NONE;
374 EXPORT_API int location_bounds_destroy(location_bounds_h bounds)
376 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
377 LOCATIONS_NULL_ARG_CHECK(bounds);
379 location_bounds_s *handle = (location_bounds_s *) bounds;
380 if (handle->is_added) {
381 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_IS_ADDED(0x%08x)", LOCATION_BOUNDS_ERROR_IS_ADDED);
382 return LOCATION_BOUNDS_ERROR_IS_ADDED;
384 location_boundary_free(handle->boundary);
385 handle->user_cb = NULL;
386 handle->user_data = NULL;
389 return LOCATION_BOUNDS_ERROR_NONE;
392 EXPORT_API int location_bounds_set_state_changed_cb(location_bounds_h bounds, location_bounds_state_changed_cb callback, void *user_data)
394 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
395 LOCATIONS_NULL_ARG_CHECK(bounds);
396 LOCATIONS_NULL_ARG_CHECK(callback);
398 location_bounds_s *handle = (location_bounds_s *) bounds;
399 handle->user_cb = callback;
400 handle->user_data = user_data;
401 return LOCATION_BOUNDS_ERROR_NONE;
404 EXPORT_API int location_bounds_unset_state_changed_cb(location_bounds_h bounds)
406 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
407 LOCATIONS_NULL_ARG_CHECK(bounds);
409 location_bounds_s *handle = (location_bounds_s *) bounds;
410 handle->user_cb = NULL;
411 handle->user_data = NULL;
412 return LOCATION_BOUNDS_ERROR_NONE;