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;
67 if (bottom_right.latitude >= top_left.latitude) {
68 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
72 LocationPosition *lt = location_position_new(0, top_left.latitude, top_left.longitude, 0, LOCATION_STATUS_2D_FIX);
74 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
75 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
78 LocationPosition *rb = location_position_new(0, bottom_right.latitude, bottom_right.longitude, 0, LOCATION_STATUS_2D_FIX);
80 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
81 location_position_free(lt);
82 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
85 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
87 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
88 location_position_free(rb);
89 location_position_free(lt);
90 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
92 memset(handle, 0, sizeof(location_bounds_s));
94 handle->is_added = FALSE;
95 handle->boundary = location_boundary_new_for_rect(lt, rb);
96 location_position_free(rb);
97 location_position_free(lt);
98 if (handle->boundary == NULL) {
99 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_rect", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
101 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
104 *bounds = (location_bounds_h) handle;
105 return LOCATION_BOUNDS_ERROR_NONE;
108 EXPORT_API int location_bounds_create_circle(location_coords_s center, double radius, location_bounds_h *bounds)
110 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
111 LOCATIONS_NULL_ARG_CHECK(bounds);
112 LOCATIONS_CHECK_CONDITION(radius > 0, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
113 LOCATIONS_CHECK_CONDITION(center.latitude >= -90 && center.latitude <= 90, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
114 LOCATIONS_CHECK_CONDITION(center.longitude >= -180 && center.longitude <= 180, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
116 LocationPosition *ct = location_position_new(0, center.latitude, center.longitude, 0, LOCATION_STATUS_2D_FIX);
118 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
119 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
122 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
123 if (handle == NULL) {
124 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
125 location_position_free(ct);
126 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
128 memset(handle, 0, sizeof(location_bounds_s));
130 handle->is_added = FALSE;
131 handle->boundary = location_boundary_new_for_circle(ct, radius);
132 location_position_free(ct);
133 if (handle->boundary == NULL) {
135 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_circle", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
136 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
139 *bounds = (location_bounds_h) handle;
140 return LOCATION_BOUNDS_ERROR_NONE;
143 EXPORT_API int location_bounds_create_polygon(location_coords_s *coords_list, int length, location_bounds_h *bounds)
145 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
146 LOCATIONS_NULL_ARG_CHECK(coords_list);
147 LOCATIONS_NULL_ARG_CHECK(bounds);
148 LOCATIONS_CHECK_CONDITION(length >= 3, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
151 GList *position_list = NULL;
152 LocationPosition *position = NULL;
155 for (i = 0; i < length; i++) {
156 if (coords_list[i].latitude < -90 || coords_list[i].latitude > 90 || coords_list[i].longitude < -180 || coords_list[i].longitude > 180) {
157 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INVALID_PARAMETER(0x%08x)", LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
161 position = location_position_new(0, coords_list[i].latitude, coords_list[i].longitude, 0.0, LOCATION_STATUS_2D_FIX);
162 position_list = g_list_append(position_list, position);
163 /* We should not remove position.
164 location_position_free(position);
170 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
171 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
174 if (position_list == NULL) {
175 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
176 g_list_free_full(position_list, (GDestroyNotify) __free_position_list);
177 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
180 location_bounds_s *handle = (location_bounds_s *) malloc(sizeof(location_bounds_s));
181 if (handle == NULL) {
182 LOCATIONS_LOGE("OUT_OF_MEMORY(0x%08x)", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
183 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
185 memset(handle, 0, sizeof(location_bounds_s));
187 handle->is_added = FALSE;
188 handle->boundary = location_boundary_new_for_polygon(position_list);
189 if (handle->boundary == NULL) {
191 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_polygon", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
192 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
195 *bounds = (location_bounds_h) handle;
196 return LOCATION_BOUNDS_ERROR_NONE;
199 EXPORT_API bool location_bounds_contains_coordinates(location_bounds_h bounds, location_coords_s coords)
201 if (__is_location_supported() == LOCATIONS_ERROR_NOT_SUPPORTED) {
202 set_last_result(LOCATIONS_ERROR_NOT_SUPPORTED);
207 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
211 if (coords.latitude < -90 || coords.latitude > 90 || coords.longitude < -180 || coords.longitude > 180) {
212 set_last_result(LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
216 LocationPosition *pos = location_position_new(0, coords.latitude, coords.longitude, 0, LOCATION_STATUS_2D_FIX);
218 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
219 set_last_result(LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
222 location_bounds_s *handle = (location_bounds_s *) bounds;
223 gboolean is_inside = location_boundary_if_inside(handle->boundary, pos);
224 location_position_free(pos);
225 bool result = is_inside ? TRUE : FALSE;
227 set_last_result(LOCATION_BOUNDS_ERROR_NONE);
231 EXPORT_API int location_bounds_get_type(location_bounds_h bounds, location_bounds_type_e *type)
233 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
234 LOCATIONS_NULL_ARG_CHECK(bounds);
235 LOCATIONS_NULL_ARG_CHECK(type);
237 location_bounds_s *handle = (location_bounds_s *) bounds;
238 *type = __convert_bounds_type(handle->boundary->type);
239 return LOCATION_BOUNDS_ERROR_NONE;
242 EXPORT_API int location_bounds_get_rect_coords(location_bounds_h bounds, location_coords_s *top_left, location_coords_s *bottom_right)
244 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
245 LOCATIONS_NULL_ARG_CHECK(bounds);
246 LOCATIONS_NULL_ARG_CHECK(top_left);
247 LOCATIONS_NULL_ARG_CHECK(bottom_right);
249 location_bounds_s *handle = (location_bounds_s *) bounds;
250 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_RECT) {
251 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
252 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
255 top_left->latitude = handle->boundary->rect.left_top->latitude;
256 top_left->longitude = handle->boundary->rect.left_top->longitude;
257 bottom_right->latitude = handle->boundary->rect.right_bottom->latitude;
258 bottom_right->longitude = handle->boundary->rect.right_bottom->longitude;
259 return LOCATION_BOUNDS_ERROR_NONE;
262 EXPORT_API int location_bounds_get_circle_coords(location_bounds_h bounds, location_coords_s *center, double *radius)
264 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
265 LOCATIONS_NULL_ARG_CHECK(bounds);
266 LOCATIONS_NULL_ARG_CHECK(center);
267 LOCATIONS_NULL_ARG_CHECK(radius);
269 location_bounds_s *handle = (location_bounds_s *) bounds;
270 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_CIRCLE) {
271 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
272 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
275 center->latitude = handle->boundary->circle.center->latitude;
276 center->longitude = handle->boundary->circle.center->longitude;
277 *radius = handle->boundary->circle.radius;
278 return LOCATION_BOUNDS_ERROR_NONE;
281 EXPORT_API int location_bounds_foreach_polygon_coords(location_bounds_h bounds, polygon_coords_cb callback, void *user_data)
283 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
284 LOCATIONS_NULL_ARG_CHECK(bounds);
285 LOCATIONS_NULL_ARG_CHECK(callback);
287 location_bounds_s *handle = (location_bounds_s *) bounds;
288 if (__convert_bounds_type(handle->boundary->type) != LOCATION_BOUNDS_POLYGON) {
289 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
290 return LOCATION_BOUNDS_ERROR_INCORRECT_TYPE;
293 GList *list = handle->boundary->polygon.position_list;
295 LocationPosition *pos = list->data;
296 location_coords_s coords;
297 coords.latitude = pos->latitude;
298 coords.longitude = pos->longitude;
300 if (callback(coords, user_data) != TRUE) {
301 LOCATIONS_LOGI("User quit the loop ");
304 list = g_list_next(list);
306 return LOCATION_BOUNDS_ERROR_NONE;
309 EXPORT_API int location_bounds_destroy(location_bounds_h bounds)
311 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
312 LOCATIONS_NULL_ARG_CHECK(bounds);
314 location_bounds_s *handle = (location_bounds_s *) bounds;
315 if (handle->is_added) {
316 LOCATIONS_LOGE("LOCATION_BOUNDS_ERROR_IS_ADDED(0x%08x)", LOCATION_BOUNDS_ERROR_IS_ADDED);
317 return LOCATION_BOUNDS_ERROR_IS_ADDED;
319 location_boundary_free(handle->boundary);
320 handle->user_cb = NULL;
321 handle->user_data = NULL;
324 return LOCATION_BOUNDS_ERROR_NONE;
327 EXPORT_API int location_bounds_set_state_changed_cb(location_bounds_h bounds, location_bounds_state_changed_cb callback, void *user_data)
329 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
330 LOCATIONS_NULL_ARG_CHECK(bounds);
331 LOCATIONS_NULL_ARG_CHECK(callback);
333 location_bounds_s *handle = (location_bounds_s *) bounds;
334 handle->user_cb = callback;
335 handle->user_data = user_data;
336 return LOCATION_BOUNDS_ERROR_NONE;
339 EXPORT_API int location_bounds_unset_state_changed_cb(location_bounds_h bounds)
341 LOCATIONS_NOT_SUPPORTED_CHECK(__is_location_supported());
342 LOCATIONS_NULL_ARG_CHECK(bounds);
344 location_bounds_s *handle = (location_bounds_s *) bounds;
345 handle->user_cb = NULL;
346 handle->user_data = NULL;
347 return LOCATION_BOUNDS_ERROR_NONE;