Add LCOV remarkers to increase line coverage rate
[platform/core/api/maps-service.git] / src / view / inertial_camera.cpp
1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
2  *
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
18 #include "inertial_camera.h"
19 #include "maps_util.h"
20 #include "maps_view_plugin.h"
21 #include <glib.h>
22
23 int _maps_coordinates_copy(maps_coordinates_h orig, maps_coordinates_h dest);
24
25 //LCOV_EXCL_START
26 view::inertial_camera::inertial_camera(maps_view_h view)
27         : _view(view)
28           , target_zoom_factor(.0)
29           , target_rotation_angle(.0)
30           , target_center(NULL)
31           , cur_zoom_factor(.0)
32           , cur_rotation_angle(.0)
33           , cur_center(NULL)
34           , transiting(false)
35 {
36 }
37
38 view::inertial_camera::inertial_camera(const inertial_camera &src)
39         : _view(NULL)
40           , target_zoom_factor(.0)
41           , target_rotation_angle(.0)
42           , target_center(NULL)
43           , cur_zoom_factor(.0)
44           , cur_rotation_angle(.0)
45           , cur_center(NULL)
46           , transiting(false)
47 {
48 }
49
50 view::inertial_camera &view::inertial_camera::operator=(const inertial_camera
51                                                         &src)
52 {
53         return *this;
54 }
55
56 view::inertial_camera::~inertial_camera()
57 {
58         maps_coordinates_destroy(target_center);
59         maps_coordinates_destroy(cur_center);
60 }
61
62 void view::inertial_camera::set_cur_state()
63 {
64         if (!_view)
65                 return;
66
67         if (!cur_center)
68                 maps_coordinates_destroy(cur_center);
69         maps_view_get_center(_view, &cur_center);
70         maps_view_get_zoom_factor(_view, &cur_zoom_factor);
71         maps_view_get_orientation(_view, &cur_rotation_angle);
72 }
73
74 void view::inertial_camera::set_targets(const maps_coordinates_h center,
75                                         const double &zoom_factor,
76                                         const double &rotation_angle)
77 {
78         if (!_view)
79                 return;
80
81         /* Store the targets */
82         if (!target_center) {
83                 maps_coordinates_clone(center, &target_center);
84         } else {
85                 _maps_coordinates_copy(center, target_center);
86         }
87
88         target_zoom_factor = zoom_factor;
89         target_rotation_angle = rotation_angle;
90
91         /* Store current state */
92         if (!transiting)
93                 set_cur_state();
94
95         /* Start transition */
96         transiting = true;
97 }
98
99 void view::inertial_camera::set_center_target(const maps_coordinates_h center)
100 {
101         if (!_view)
102                 return;
103
104         /* Store the target */
105         if (!target_center) {
106                 maps_coordinates_clone(center, &target_center);
107         } else {
108                 _maps_coordinates_copy(center, target_center);
109         }
110
111         /* Store current state */
112         if (!transiting)
113                 set_cur_state();
114
115         /* Start transition */
116         transiting = true;
117 }
118
119 void view::inertial_camera::set_zoom_target(const double &zoom_factor)
120 {
121         if (!_view)
122                 return;
123
124         /* Store the target */
125         target_zoom_factor = zoom_factor;
126
127         /* Store current state */
128         if (!transiting)
129                 set_cur_state();
130
131         /* Start transition */
132         transiting = true;
133 }
134
135 void view::inertial_camera::set_rotation_target(const double &rotation_angle)
136 {
137         if (!_view)
138                 return;
139
140         /* Store the target */
141         target_rotation_angle = rotation_angle;
142
143         /* Store current state */
144         if (!transiting)
145                 set_cur_state();
146
147         /* Start transition */
148         transiting = true;
149 }
150
151 double view::inertial_camera::calc_next_step(const double &start,
152                                              const double &finish,
153                                              const double step_ratio) const
154 {
155         if (start == finish)
156                 return start;
157
158         /* Expanential transition */
159         double step = (finish - start) * step_ratio;
160         double new_pos = start + step;
161         if (finish > start) {
162                 new_pos = MAX(new_pos, start);
163                 new_pos = MIN(new_pos, finish);
164         } else {
165                 new_pos = MIN(new_pos, start);
166                 new_pos = MAX(new_pos, finish);
167         }
168         return new_pos;
169 }
170
171 double view::inertial_camera::calc_next_step_lon(const double &start,
172                                              const double &finish,
173                                              const double step_ratio) const
174 {
175         if (start == finish)
176                 return start;
177
178         double _f = finish;
179         double _s = start;
180         if (_f < 0) _f += 360;
181         if (_s < 0) _s += 360;
182
183         double gap, gap1, gap2;
184         if (_f > _s) {
185                 gap1 = _f - _s;
186                 gap2 = (360 - _f) + _s;
187                 if (gap1 < gap2)
188                         gap = gap1;
189                 else
190                         gap = gap2 * -1;
191         } else {
192                 gap1 = _s - _f;
193                 gap2 = (360 - _s) + _f;
194                 if (gap1 < gap2)
195                         gap = gap1 * -1;
196                 else
197                         gap = gap2;
198         }
199
200         double step = gap * step_ratio;
201         double new_pos = start + step;
202         if (new_pos > 180)
203                 new_pos -= 360;
204         else if (new_pos < -180)
205                 new_pos += 360;
206
207         return new_pos;
208 }
209
210 bool view::inertial_camera::next_transition_step()
211 {
212         if (!_view)
213                 return false;
214
215         transiting = false;
216
217         double prev_lat = .0;
218         double prev_lon = .0;
219         double target_lat = .0;
220         double target_lon = .0;
221         maps_coordinates_get_latitude_longitude(cur_center, &prev_lat, &prev_lon);
222         maps_coordinates_get_latitude_longitude(target_center, &target_lat, &target_lon);
223
224         /* Transiting map center */
225         double next_lat = calc_next_step(prev_lat, target_lat, .15);
226         if (next_lat != prev_lat) transiting = true;
227
228         double next_lon = calc_next_step_lon(prev_lon, target_lon, .15);
229         if (next_lon != prev_lon) transiting = true;
230
231         if (transiting)
232         {
233                 int tx, ty, nx, ny;
234                 maps_coordinates_s next_center_s = { next_lat, next_lon };
235                 maps_view_geolocation_to_screen(_view, &next_center_s, &nx, &ny);
236                 maps_view_geolocation_to_screen(_view, target_center, &tx, &ty);
237                 if (nx == tx && ny == ty) {
238                         transiting = false;
239                         next_lat = target_lat;
240                         next_lon = target_lon;
241                 }
242         }
243
244         maps_coordinates_set_latitude_longitude(cur_center, next_lat, next_lon);
245
246         /* Transiting zoom */
247         cur_zoom_factor = calc_next_step(cur_zoom_factor, target_zoom_factor, .2);
248         if (ABS(cur_zoom_factor - target_zoom_factor) > __ZOOM_ACCURACY)
249                 transiting = true;
250         else
251                 cur_zoom_factor = target_zoom_factor;
252
253         /* Transizint orientation */
254         if (target_rotation_angle - cur_rotation_angle > 180.)
255                 target_rotation_angle -= 360.;
256         else if (target_rotation_angle - cur_rotation_angle < -180.)
257                 target_rotation_angle += 360.;
258
259         cur_rotation_angle = calc_next_step(cur_rotation_angle, target_rotation_angle, .5);
260         if (ABS(cur_rotation_angle - target_rotation_angle) > __ROTATE_ACCURACY)
261                 transiting = true;
262         else
263                 cur_rotation_angle = target_rotation_angle;
264
265         return transiting;
266 }
267 //LCOV_EXCL_STOP