caf66cde7e6c3865b8627733092a84121d30856b
[framework/api/location-manager.git] / src / location_bounds.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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. 
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <locations_private.h>
21 #include <dlog.h>
22
23 #ifdef LOG_TAG
24 #undef LOG_TAG
25 #endif
26 #define LOG_TAG "TIZEN_N_LOCATION_MANAGER"
27
28 /*
29 * Internal Macros
30 */
31 #define LOCATIONS_CHECK_CONDITION(condition,error,msg)  \
32                 if(condition) {} else \
33                 { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
34
35 #define LOCATIONS_NULL_ARG_CHECK(arg)   \
36         LOCATIONS_CHECK_CONDITION(arg != NULL,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER") \
37
38 static void __free_position_list(gpointer data)
39 {
40         if (data == NULL) return;
41
42         LocationPosition *position = (LocationPosition*) data;
43         location_position_free(position);
44 }
45
46 static location_bounds_type_e __convert_bounds_type(LocationBoundaryType type)
47 {
48         location_bounds_type_e ret;
49         switch(type)
50         {
51         case LOCATION_BOUNDARY_NONE:
52         case LOCATION_BOUNDARY_RECT:
53                 ret = LOCATION_BOUNDS_RECT;
54                 break;
55         case LOCATION_BOUNDARY_CIRCLE:
56                 ret = LOCATION_BOUNDS_CIRCLE;
57                 break;
58         case LOCATION_BOUNDARY_POLYGON:
59                 ret = LOCATION_BOUNDS_POLYGON;
60                 break;
61         }
62         return ret;
63 }
64
65 int location_bounds_create_rect(location_coords_s top_left, location_coords_s bottom_right, location_bounds_h* bounds)
66 {
67         LOCATIONS_NULL_ARG_CHECK(bounds);
68         LOCATIONS_CHECK_CONDITION(top_left.latitude>=-90 && top_left.latitude<=90,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
69         LOCATIONS_CHECK_CONDITION(top_left.longitude>=-180 && top_left.longitude<=180,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
70         LOCATIONS_CHECK_CONDITION(bottom_right.latitude>=-90 && bottom_right.latitude<=90,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
71         LOCATIONS_CHECK_CONDITION(bottom_right.longitude>=-180 && bottom_right.longitude<=180,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
72
73         LocationPosition *lt = location_position_new(0, top_left.latitude, top_left.longitude, 0, LOCATION_STATUS_2D_FIX);
74         if (lt ==NULL)
75         {
76                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
77                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
78         }
79
80         LocationPosition *rb = location_position_new(0, bottom_right.latitude, bottom_right.longitude, 0, LOCATION_STATUS_2D_FIX);
81         if (rb ==NULL)
82         {
83                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
84                 location_position_free (lt);
85                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
86         }
87
88         LocationBoundary *boundary = location_boundary_new_for_rect(lt, rb);
89         location_position_free (rb);
90         location_position_free (lt);
91
92         if(!boundary)
93         {
94                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_rect", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
95                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
96         }
97
98         *bounds = (location_bounds_h)boundary;
99         return LOCATION_BOUNDS_ERROR_NONE;
100 }
101
102 int location_bounds_create_circle(location_coords_s center, double radius, location_bounds_h* bounds)
103 {
104         LOCATIONS_NULL_ARG_CHECK(bounds);
105         LOCATIONS_CHECK_CONDITION(radius>=0,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
106         LOCATIONS_CHECK_CONDITION(center.latitude>=-90 && center.latitude<=90,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
107         LOCATIONS_CHECK_CONDITION(center.longitude>=-180 && center.longitude<=180,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER, "LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
108
109         LocationPosition *ct = location_position_new(0, center.latitude, center.longitude, 0, LOCATION_STATUS_2D_FIX);
110         if (ct ==NULL)
111         {
112                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
113                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
114         }
115
116         LocationBoundary *boundary = location_boundary_new_for_circle(ct,radius);
117         location_position_free (ct);
118
119         if(!boundary)
120         {
121                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_circle", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
122                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
123         }
124
125         *bounds = (location_bounds_h)boundary;
126         return LOCATION_BOUNDS_ERROR_NONE;
127 }
128
129 int location_bounds_create_polygon(location_coords_s* coords_list, int length, location_bounds_h* bounds)
130 {
131         LOCATIONS_NULL_ARG_CHECK(coords_list);
132         LOCATIONS_NULL_ARG_CHECK(bounds);
133         LOCATIONS_CHECK_CONDITION(length>=3,LOCATION_BOUNDS_ERROR_INVALID_PARAMETER,"LOCATION_BOUNDS_ERROR_INVALID_PARAMETER");
134
135         int i;
136         GList* position_list = NULL;
137         LocationPosition *position = NULL;
138         bool isValid;
139         
140         for(i=0;i<length;i++)
141         {
142                 if(coords_list[i].latitude < -90 || coords_list[i].latitude > 90 || coords_list[i].longitude < -180 || coords_list[i].longitude > 180)
143                 {
144                         LOGE("[%s] LOCATION_BOUNDS_ERROR_INVALID_PARAMETER(0x%08x)", __FUNCTION__, LOCATION_BOUNDS_ERROR_INVALID_PARAMETER);
145                         isValid = FALSE;
146                         break;
147                 }       
148
149                 position = location_position_new(0, coords_list[i].latitude, coords_list[i].longitude, 0.0, LOCATION_STATUS_2D_FIX);
150                 position_list = g_list_append(position_list,position);
151                 location_position_free(position);
152                 isValid = TRUE;
153         }
154
155         if(!isValid)
156         {
157                 g_list_free_full(position_list, (GDestroyNotify)__free_position_list);
158                 return LOCATION_BOUNDS_ERROR_INVALID_PARAMETER;
159         }
160                 
161         if (position_list ==NULL)
162         {
163                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_position_new", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
164                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
165         }
166
167         LocationBoundary *boundary =  location_boundary_new_for_polygon(position_list);
168
169         if(!boundary)
170         {
171                 LOGE("[%s] LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY(0x%08x) : fail to location_boundary_new_for_rect", __FUNCTION__, LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY);
172                 return LOCATION_BOUNDS_ERROR_OUT_OF_MEMORY;
173         }
174
175         *bounds = (location_bounds_h)boundary;
176         return LOCATION_BOUNDS_ERROR_NONE;
177 }
178
179 bool location_bounds_is_contains_coordinates(location_bounds_h bounds, location_coords_s coords)
180 {
181         if (!bounds)
182                 return FALSE;
183
184         if (coords.latitude < -90 ||  coords.latitude > 90 || coords.longitude < -180 || coords.longitude > 180)
185                 return FALSE;
186
187         LocationPosition *pos = location_position_new(0, coords.latitude, coords.longitude, 0, LOCATION_STATUS_2D_FIX);
188         if (!pos)
189                 return FALSE;
190
191         gboolean is_inside = location_boundary_if_inside((LocationBoundary*)bounds, pos);
192         location_position_free (pos);
193         bool result = is_inside?TRUE:FALSE;
194         return result;
195 }
196
197 int location_bounds_get_type(location_bounds_h bounds, location_bounds_type_e *type)
198 {
199         LOCATIONS_NULL_ARG_CHECK(bounds);
200         LOCATIONS_NULL_ARG_CHECK(type); 
201         *type = __convert_bounds_type(((LocationBoundary*)bounds)->type);
202         return LOCATION_BOUNDS_ERROR_NONE;
203 }
204
205 int location_bounds_get_rect_coords(location_bounds_h bounds, location_coords_s  *top_left, location_coords_s  *bottom_right)
206 {
207         LOCATIONS_NULL_ARG_CHECK(bounds);
208         LOCATIONS_NULL_ARG_CHECK(top_left);
209         LOCATIONS_NULL_ARG_CHECK(bottom_right);
210         if( __convert_bounds_type(((LocationBoundary*)bounds)->type) != LOCATION_BOUNDS_RECT)
211         {
212                 LOGE("[%s] LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", __FUNCTION__, LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
213         }
214
215         top_left->latitude = ((LocationBoundary*)bounds)->rect.left_top->latitude;
216         top_left->longitude = ((LocationBoundary*)bounds)->rect.left_top->longitude;
217         bottom_right->latitude =((LocationBoundary*)bounds)->rect.right_bottom->latitude;
218         bottom_right->longitude = ((LocationBoundary*)bounds)->rect.right_bottom->longitude;
219         return LOCATION_BOUNDS_ERROR_NONE;
220 }
221
222 int location_bounds_get_circle_coords(location_bounds_h bounds, location_coords_s  *center, double *radius)
223 {
224         LOCATIONS_NULL_ARG_CHECK(bounds);
225         LOCATIONS_NULL_ARG_CHECK(center);
226         LOCATIONS_NULL_ARG_CHECK(radius);
227         if( __convert_bounds_type(((LocationBoundary*)bounds)->type) != LOCATION_BOUNDS_CIRCLE)
228         {
229                 LOGE("[%s] LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", __FUNCTION__, LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
230         }
231
232         center->latitude = ((LocationBoundary*)bounds)->circle.center->latitude;
233         center->longitude =((LocationBoundary*)bounds)->circle.center->longitude;
234         *radius = ((LocationBoundary*)bounds)->circle.radius;
235         return LOCATION_BOUNDS_ERROR_NONE;
236 }
237
238 int location_bounds_foreach_polygon_coords(location_bounds_h bounds, polygon_coords_cb callback, void *user_data)
239 {
240         LOCATIONS_NULL_ARG_CHECK(bounds);
241         LOCATIONS_NULL_ARG_CHECK(callback);     
242         if( __convert_bounds_type(((LocationBoundary*)bounds)->type) != LOCATION_BOUNDS_POLYGON)
243         {
244                 LOGE("[%s] LOCATION_BOUNDS_ERROR_INCORRECT_TYPE(0x%08x)", __FUNCTION__, LOCATION_BOUNDS_ERROR_INCORRECT_TYPE);
245         }
246
247         GList *list = ((LocationBoundary*)bounds)->polygon.position_list;
248         while(list)
249         {
250                 LocationPosition *pos = list->data;
251                 location_coords_s coords;
252                 coords.latitude = pos->latitude;
253                 coords.longitude = pos->longitude;
254                 
255                 if ( callback(coords, user_data) != TRUE )
256                 {
257                         LOGI("[%s] User quit the loop ",  __FUNCTION__);
258                         break;
259                 }
260                 list = g_list_next(list);
261         }
262         return LOCATION_BOUNDS_ERROR_NONE;
263 }
264
265 int location_bounds_destroy(location_bounds_h bounds)
266 {
267         LOCATIONS_NULL_ARG_CHECK(bounds);
268         location_boundary_free((LocationBoundary*)bounds);
269         return LOCATION_BOUNDS_ERROR_NONE;
270 }
271