#include "maps_view_plugin.h"
+#define GESTURE_ZOOM_STATIC_FRICTION 0.15
+#define GESTURE_ZOOM_MOVEMENT_UNIT 0.02
+
+#define GESTURE_ROTATION_STATIC_FRICTION 15.0
+#define GESTURE_ROTATION_MOVEMENT_UNIT 0.15
/*----------------------------------------------------------------------------*/
/* Finding the start radius */
const int start_dx = _start_tp_f2._x - _start_tp_f1._x;
const int start_dy = _start_tp_f2._y - _start_tp_f1._y;
- const double start_r =
- sqrt(start_dx * start_dx + start_dy * start_dy) / 2;
+ const double start_r = sqrt(start_dx * start_dx + start_dy * start_dy) / 2;
/* Finding the cur radius */
const int cur_dx = _cur_tp_f2._x - _cur_tp_f1._x;
/* Calculating the zoom factor */
if ((start_r != .0) && (cur_r != .0) && (start_r != cur_r)) {
- if (cur_r > start_r)
- _new_zoom_factor = (cur_r / start_r) - 1;
- else
- _new_zoom_factor = -((start_r / cur_r) - 1);
+ int dpi;
+ maps_get_screen_dpi(&dpi);
+
+ /* basically change 1 zoom level per inch */
+ /* additional adjust depending on the size of gesture which a user operates */
+ if (cur_r > start_r) {
+ _new_zoom_factor = ((cur_r - start_r) / dpi)
+ + ((cur_r / start_r) - 1) * 0.05;
+ } else {
+ _new_zoom_factor = -((start_r - cur_r) / dpi)
+ + -((start_r / cur_r) - 1) * 0.05;
+ }
_zoom_happend = true;
}
_new_rotation_angle = (angle / M_PI * 180.);
_rotation_happend = true;
} else if (curl > 0) {
- _new_rotation_angle = 360 - (angle / M_PI * 180.);
+ _new_rotation_angle = -(angle / M_PI * 180.);
_rotation_happend = true;
}
}
const double angle1,
const double angle2) const
{
- const double _angle1 = (angle1 >= 0 ? angle1 : angle1 + 360);
- const double _angle2 = (angle2 >= 0 ? angle2 : angle2 + 360);
+ if (angle2 - angle1 <= 180)
+ return (angle2 - angle1);
+ else
+ return -(angle1 + (360 - angle2));
+}
- const double angle = (_angle1 > _angle2)
- ? MIN(_angle1 - _angle2, (360 - angle1) + _angle2)
- : MIN(_angle2 - _angle1, (360 - angle2) + _angle1);
+double view::gesture_processor::calc_angle(
+ const touch_point tp1,
+ const touch_point tp2) const
+{
+ const int dx = tp2._x - tp1._x;
+ const int dy = tp2._y - tp1._y;
+// const double r = sqrt(dx * dx + dy * dy) / 2;
+ const double angle = atan2(dy, dx) / M_PI * 180. + 180.0;
return angle;
}
-bool view::gesture_processor::on_zoom(bool zoom_changed, double &zoom_factor)
+bool view::gesture_processor::on_zoom(bool zoom_changed, bool rotation_changed, double &zoom_factor)
{
/* Check if the gesture is available */
if (!_maps_view_is_gesture_available(_gd->_view, MAPS_VIEW_GESTURE_ZOOM))
return false;
- gesture_detector::log("view::gesture_processor::on_zoom",
- gesture_detector::FG_LITE_GREEN);
- /* Assumed that we can zoom&rotate using only a pair of fingers */
+ /* gesture_detector::log("view::gesture_processor::on_zoom", gesture_detector::FG_LITE_GREEN); */
/* First finger effective way by now */
const touch_point start_tp_f1 = _gd->_info._finger_down[0];
const touch_point start_tp_f2 = _gd->_info._finger_down[1];
const touch_point cur_tp_f2 = _gd->_info._finger_move[1];
- /***********************/
- MAPS_LOGI("%c[%d;%d;%dm"
- "Finger1: start(%d, %d), cur(%d, %d)\t"
- "Finger2: start(%d, %d), cur(%d, %d)\t"
- "%c[%d;%d;%dm",
- 0x1B, 1, 0, gesture_detector::FG_YELLOW,
- start_tp_f1._x, start_tp_f1._y, cur_tp_f1._x, cur_tp_f1._y,
- start_tp_f2._x, start_tp_f2._y, cur_tp_f2._x, cur_tp_f2._y,
- 0x1B, 0, 0, 0);
- /***********************/
-
- /* Calcurating center position */
- const touch_point start_center = calc_center(start_tp_f1, start_tp_f2);
- const touch_point cur_center = calc_center(cur_tp_f1, cur_tp_f2);
-
/* Calculating the current zoom factor, accordingly to effecitve ways of fingers */
zoom_calculator zc(start_tp_f1, cur_tp_f1, start_tp_f2, cur_tp_f2);
double new_zoom_factor = zc.get_zoom_factor();
int max_zoom_level = 0;
maps_view_get_min_zoom_level(_gd->_view, &min_zoom_level);
maps_view_get_max_zoom_level(_gd->_view, &max_zoom_level);
- if (new_zoom_factor < min_zoom_level)
- new_zoom_factor = min_zoom_level;
- if (new_zoom_factor > max_zoom_level)
- new_zoom_factor = max_zoom_level;
+ new_zoom_factor = MIN(MAX(new_zoom_factor, min_zoom_level), max_zoom_level);
/* Check if the zoom changed relatively to initial state */
- double diff = _gd->_info._start_view_state._prev_zoom_factor - new_zoom_factor;
- if ((!zoom_changed && (diff > 0.10 || diff < -0.10)) ||
- (zoom_changed && (diff > 0.02 || diff < -0.02))) {
- _gd->_info._start_view_state._prev_zoom_factor = new_zoom_factor;
+ double diff = new_zoom_factor - _gd->_info._start_view_state._prev_zoom_factor;
+ static double compensation = 0.;
+ static double prev_diff = 0.;
+
+ if (!zoom_changed && (fabs(diff) > GESTURE_ZOOM_STATIC_FRICTION * (1 + rotation_changed))) {
+ compensation = diff * -1;
+ zoom_changed = true;
+ } else if (zoom_changed && (fabs(diff - prev_diff) > GESTURE_ZOOM_MOVEMENT_UNIT)) {
zoom_changed = true;
- MAPS_LOGD("[zoom_changed] %f, %f -> %f",
- diff, _gd->_info._start_view_state._prev_zoom_factor, new_zoom_factor);
} else {
zoom_changed = false;
}
+
+ if (zoom_changed) {
+ new_zoom_factor += compensation;
+ MAPS_LOGD("[zoom_changed] %f + %f -> %f",
+ _gd->_info._start_view_state._prev_zoom_factor, diff - prev_diff, new_zoom_factor);
+ prev_diff = diff;
+ }
}
if (!zoom_changed)
return true;
}
-bool view::gesture_processor::on_rotate(bool rotation_changed, double &rotation_angle)
+bool view::gesture_processor::on_rotate(bool zoom_changed, bool rotation_changed, double &rotation_angle)
{
/* Check if the gesture is available */
if (!_maps_view_is_gesture_available(_gd->_view, MAPS_VIEW_GESTURE_ROTATE))
return false;
- gesture_detector::log("view::gesture_processor::on_zoom",
- gesture_detector::FG_LITE_GREEN);
- /* Assumed that we can zoom&rotate using only a pair of fingers */
+ /* gesture_detector::log("view::gesture_processor::on_rotate", gesture_detector::FG_LITE_GREEN); */
/* First finger effective way by now */
const touch_point start_tp_f1 = _gd->_info._finger_down[0];
const touch_point start_tp_f2 = _gd->_info._finger_down[1];
const touch_point cur_tp_f2 = _gd->_info._finger_move[1];
- /***********************/
- MAPS_LOGI("%c[%d;%d;%dm"
- "Finger1: start(%d, %d), cur(%d, %d)\t"
- "Finger2: start(%d, %d), cur(%d, %d)\t"
- "%c[%d;%d;%dm",
- 0x1B, 1, 0, gesture_detector::FG_YELLOW,
- start_tp_f1._x, start_tp_f1._y, cur_tp_f1._x, cur_tp_f1._y,
- start_tp_f2._x, start_tp_f2._y, cur_tp_f2._x, cur_tp_f2._y,
- 0x1B, 0, 0, 0);
- /***********************/
-
- /* Calcurating center position */
- const touch_point start_center = calc_center(start_tp_f1, start_tp_f2);
- const touch_point cur_center = calc_center(cur_tp_f1, cur_tp_f2);
-
/* Calculating the current zoom factor, accordingly to effecitve ways of fingers */
zoom_calculator zc(start_tp_f1, cur_tp_f1, start_tp_f2, cur_tp_f2);
double new_rotation_angle = zc.get_rotation_angle();
/* Apply newly calculated rotation angle */
new_rotation_angle += _gd->_info._start_view_state._rotation_angle;
- /* Correct the rotation angle to normalize it
- * inside the diapazone of 0..360 degree */
- new_rotation_angle -= 360. * (int(new_rotation_angle) / 360);
- new_rotation_angle += 360. * (int(new_rotation_angle) / 360);
-
/* Check if the zoom changed relatively to initial state */
double diff = calc_angle(_gd->_info._start_view_state._prev_rotation_angle, new_rotation_angle);
- if ((!rotation_changed && (diff > 4.0 || diff < -4.0)) ||
- (rotation_changed && (diff > 0.5 || diff < -0.5))) {
- _gd->_info._start_view_state._prev_rotation_angle = new_rotation_angle;
+ static double compensation = 0.;
+ static double prev_diff = 0.;
+
+ if (!rotation_changed && (fabs(diff) > GESTURE_ROTATION_STATIC_FRICTION * (1 + zoom_changed))) {
+ compensation = diff * -1;
+ rotation_changed = true;
+ } else if (rotation_changed && (fabs(diff - prev_diff) > GESTURE_ROTATION_MOVEMENT_UNIT)) {
rotation_changed = true;
- MAPS_LOGD("[rotation_changed] %f, %f -> %f",
- diff, _gd->_info._start_view_state._prev_rotation_angle, new_rotation_angle);
} else {
rotation_changed = false;
}
+
+ if (rotation_changed) {
+ new_rotation_angle = fmod(new_rotation_angle + compensation, 360.);
+ MAPS_LOGD("[rotation_changed] %f + %f -> %f",
+ _gd->_info._start_view_state._prev_rotation_angle, diff - prev_diff, new_rotation_angle);
+ prev_diff = diff;
+ }
}
if (!rotation_changed)
return true;
}
-void view::gesture_processor::on_zoom_rotate(bool zoom_changed, double zoom_factor, bool rotation_changed, double rotation_angle)
+bool view::gesture_processor::on_two_fingers_pan(bool panning_changed, int *delta_x, int *delta_y)
{
-#if 1
+ /* Check if the gesture is available */
+ if (!_maps_view_is_gesture_available(_gd->_view, MAPS_VIEW_GESTURE_SCROLL))
+ return false;
+
+ /* gesture_detector::log("view::gesture_processor::on_two_fingers_pan", gesture_detector::FG_LITE_GREEN); */
+
+ /* First finger effective way by now */
const touch_point start_tp_f1 = _gd->_info._finger_down[0];
const touch_point cur_tp_f1 = _gd->_info._finger_move[0];
const touch_point start_tp_f2 = _gd->_info._finger_down[1];
const touch_point cur_tp_f2 = _gd->_info._finger_move[1];
- /* Calcurating center position */
const touch_point start_center = calc_center(start_tp_f1, start_tp_f2);
const touch_point cur_center = calc_center(cur_tp_f1, cur_tp_f2);
- /* a. Find delta in screen coordinates */
- const int delta_x = cur_center._x - start_center._x;
- const int delta_y = cur_center._y - start_center._y;
+ int diff = _gd->get_trajectory_effective_length(start_center, cur_center);
+ static int compen_x = 0;
+ static int compen_y = 0;
+
+ if (!panning_changed && diff > _gd->__CLICK_AREA * 2) {
+ compen_x = cur_center._x - start_center._x;
+ compen_y = cur_center._y - start_center._y;
+ if (delta_x) *delta_x = 0;
+ if (delta_y) *delta_y = 0;
+ panning_changed = true;
+ } else if (panning_changed && diff > 1) {
+ if (delta_x) *delta_x = (cur_center._x - start_center._x) - compen_x;
+ if (delta_y) *delta_y = (cur_center._y - start_center._y) - compen_y;
+ panning_changed = true;
+ } else {
+ panning_changed = false;
+ }
- /* b. Get the initial screen coordinates of the center */
+ if (!panning_changed)
+ return false;
+
+ return true;
+}
+
+
+void view::gesture_processor::on_zoom_rotate(bool zoom_changed, double zoom_factor, bool rotation_changed, double rotation_angle, bool panning_changed,
+ int panning_x, int panning_y)
+{
+ if (!zoom_changed && !rotation_changed && !panning_changed)
+ return;
+
+ /* a. Get the initial screen coordinates of the center */
int center_x = 0;
int center_y = 0;
- double lat, lon;
- maps_coordinates_get_latitude_longitude(_gd->_info._start_view_state._center, &lat, &lon);
maps_view_geolocation_to_screen(_gd->_view, _gd->_info._start_view_state._center, ¢er_x, ¢er_y);
- /* c. Apply the delta to the intital center coordinates */
- center_x -= delta_x;
- center_y -= delta_y;
+ /* b. Apply the delta to the intital center coordinates */
+ if (panning_changed) {
+ center_x -= panning_x;
+ center_y -= panning_y;
+ }
- /* d. Send event data */
+ /* c. Send event data */
maps_coordinates_h center = NULL;
maps_view_screen_to_geolocation(_gd->_view, center_x, center_y, ¢er);
-#if 1
- if (zoom_changed || rotation_changed) {
- maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_GESTURE);
- if (ed) {
- _maps_view_event_data_set_position(ed, cur_center._x, cur_center._y);
- _maps_view_event_data_set_coordinates(ed, center);
- _maps_view_event_data_set_fingers(ed, 2);
-
- if (zoom_changed) {
- _maps_view_event_data_set_gesture_type(ed, MAPS_VIEW_GESTURE_ZOOM);
- _maps_view_event_data_set_zoom_factor(ed, zoom_factor);
- _maps_view_event_data_set_rotation_angle(ed, 0.);
- _maps_view_invoke_event_callback(_gd->_view, ed);
- }
- if (rotation_changed) {
- _maps_view_event_data_set_gesture_type(ed, MAPS_VIEW_GESTURE_ROTATE);
- _maps_view_event_data_set_zoom_factor(ed, 0.);
- _maps_view_event_data_set_rotation_angle(ed, rotation_angle);
- _maps_view_invoke_event_callback(_gd->_view, ed);
- }
- maps_view_event_data_destroy(ed);
- }
- }
-#else
- if (zoom_changed) {
- maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_GESTURE);
- if (ed) {
+ maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_GESTURE);
+ if (ed) {
+ _maps_view_event_data_set_position(ed, center_x, center_y);
+ _maps_view_event_data_set_coordinates(ed, center);
+ _maps_view_event_data_set_fingers(ed, 2);
+
+ if (zoom_changed) {
_maps_view_event_data_set_gesture_type(ed, MAPS_VIEW_GESTURE_ZOOM);
- _maps_view_event_data_set_position(ed, cur_center._x, cur_center._y);
- _maps_view_event_data_set_coordinates(ed, center);
- _maps_view_event_data_set_fingers(ed, 2);
_maps_view_event_data_set_zoom_factor(ed, zoom_factor);
- _maps_view_event_data_set_rotation_angle(ed, rotation_angle);
+ _maps_view_event_data_set_rotation_angle(ed, 0.);
_maps_view_invoke_event_callback(_gd->_view, ed);
- maps_view_event_data_destroy(ed);
}
- }
-
- if (rotation_changed) {
- maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_GESTURE);
- if (ed) {
+ if (rotation_changed) {
_maps_view_event_data_set_gesture_type(ed, MAPS_VIEW_GESTURE_ROTATE);
- _maps_view_event_data_set_position(ed, cur_center._x, cur_center._y);
- _maps_view_event_data_set_coordinates(ed, center);
- _maps_view_event_data_set_fingers(ed, 2);
- _maps_view_event_data_set_zoom_factor(ed, zoom_factor);
+ _maps_view_event_data_set_zoom_factor(ed, 0.);
_maps_view_event_data_set_rotation_angle(ed, rotation_angle);
_maps_view_invoke_event_callback(_gd->_view, ed);
- maps_view_event_data_destroy(ed);
}
+ maps_view_event_data_destroy(ed);
}
-#endif
- /* e. Enque the command to move the center */
+ /* d. Enque the command to move the center */
q()->push(new session::command_view_set_center(get_maps(), _gd->_view, center));
- /* f. Enqueue the detected zomm command */
- maps_view_gesture_e gesture = (zoom_changed ? MAPS_VIEW_GESTURE_ZOOM : MAPS_VIEW_GESTURE_ROTATE);
+ /* e. Enqueue the detected zomm command */
+ maps_view_gesture_e gesture = MAPS_VIEW_GESTURE_SCROLL;
+ if (zoom_changed) gesture = MAPS_VIEW_GESTURE_ZOOM;
+ if (rotation_changed) gesture = MAPS_VIEW_GESTURE_ROTATE;
+
q()->push(construct_gesture_command(gesture, center,
zoom_changed, zoom_factor, rotation_changed, rotation_angle));
maps_coordinates_destroy(center);
-#else
- const touch_point start_tp_f1 = _gd->_info._finger_down[0];
- const touch_point cur_tp_f1 = _gd->_info._finger_move[0];
-
- /* Second finger effective way by now */
- const touch_point start_tp_f2 = _gd->_info._finger_down[1];
- const touch_point cur_tp_f2 = _gd->_info._finger_move[1];
-
- /* Calcurating center position */
- const touch_point start_center = calc_center(start_tp_f1, start_tp_f2);
- const touch_point cur_center = calc_center(cur_tp_f1, cur_tp_f2);
-
- /* a. Find delta in screen coordinates */
- const int delta_x = cur_center._x - start_center._x;
- const int delta_y = cur_center._y - start_center._y;
-
- /* b. Get the initial screen coordinates of the center */
- int center_x = 0;
- int center_y = 0;
- double lat, lon;
- maps_coordinates_get_latitude_longitude(_gd->_info._start_view_state._center, &lat, &lon);
- maps_view_geolocation_to_screen(_gd->_view, _gd->_info._start_view_state._center, ¢er_x, ¢er_y);
-
- /* c. Apply the delta to the intital center coordinates */
- center_x -= delta_x;
- center_y -= delta_y;
-
- /* d. Converting screent coordinates of new center to
- * the geographical */
- maps_coordinates_h new_center = NULL;
- maps_view_screen_to_geolocation(_gd->_view, center_x, center_y, &new_center);
-
- /* e. Enque the command to move the center */
- q()->push(new session::command_view_set_center(get_maps(), _gd->_view, new_center));
-
- /* f. Enqueue the detected zomm command */
- maps_view_gesture_e gesture = (zoom_changed ? MAPS_VIEW_GESTURE_ZOOM : MAPS_VIEW_GESTURE_ROTATE);
- q()->push(construct_gesture_command(gesture, new_center,
- zoom_changed, zoom_factor, rotation_changed, rotation_angle));
-
- maps_coordinates_destroy(new_center);
-#endif
}