optimized zoom and rotation gesture 35/92935/8
authorchanywa <cbible.kim@samsung.com>
Wed, 19 Oct 2016 11:39:42 +0000 (20:39 +0900)
committerchanywa <cbible.kim@samsung.com>
Fri, 11 Nov 2016 04:29:15 +0000 (13:29 +0900)
Change-Id: I4f8201b359d8d16e3125482e83378b8eecdff99a

13 files changed:
src/api/maps_coordinates.cpp
src/api/maps_view.cpp
src/maps_util.cpp
src/maps_util.h
src/view/gesture_detector.cpp
src/view/gesture_detector.h
src/view/gesture_detector_statemachine.cpp
src/view/gesture_detector_statemachine.h
src/view/gesture_processor.cpp
src/view/gesture_processor.h
src/view/inertial_camera.cpp
src/view/inertial_gesture.cpp
src/view/runtime_data.cpp

index 34be975..fbb47f9 100644 (file)
@@ -129,9 +129,8 @@ EXPORT_API int maps_coordinates_set_latitude(maps_coordinates_h coords,
                return MAPS_ERROR_NOT_SUPPORTED;
        if (!coords)
                return MAPS_ERROR_INVALID_PARAMETER;
-       MAPS_CHECK_CONDITION(latitude >= -90
-               && latitude <= 90, MAPS_ERROR_INVALID_PARAMETER,
-               "MAPS_ERROR_INVALID_PARAMETER");
+       MAPS_CHECK_CONDITION(latitude >= -90 && latitude <= 90,
+               MAPS_ERROR_INVALID_PARAMETER, "MAPS_ERROR_INVALID_PARAMETER");
        ((maps_coordinates_s *) coords)->latitude = latitude;
        return MAPS_ERROR_NONE;
 }
@@ -143,32 +142,38 @@ EXPORT_API int maps_coordinates_set_longitude(maps_coordinates_h coords,
                return MAPS_ERROR_NOT_SUPPORTED;
        if (!coords)
                return MAPS_ERROR_INVALID_PARAMETER;
-       MAPS_CHECK_CONDITION(longitude >= -180
-               && longitude <= 180, MAPS_ERROR_INVALID_PARAMETER,
-               "MAPS_ERROR_INVALID_PARAMETER");
+       MAPS_CHECK_CONDITION(longitude >= -180 && longitude <= 180,
+               MAPS_ERROR_INVALID_PARAMETER, "MAPS_ERROR_INVALID_PARAMETER");
        ((maps_coordinates_s *) coords)->longitude = longitude;
        return MAPS_ERROR_NONE;
 }
 
 EXPORT_API int maps_coordinates_set_latitude_longitude(maps_coordinates_h coords,
-       const double latitude,
-       const double longitude)
+       const double latitude, const double longitude)
 {
        if (!maps_condition_check_maps_feature())
                return MAPS_ERROR_NOT_SUPPORTED;
        if (!coords)
                return MAPS_ERROR_INVALID_PARAMETER;
-       MAPS_CHECK_CONDITION(latitude >= -90
-               && latitude <= 90, MAPS_ERROR_INVALID_PARAMETER,
-               "MAPS_ERROR_INVALID_PARAMETER");
-       MAPS_CHECK_CONDITION(longitude >= -180
-               && longitude <= 180, MAPS_ERROR_INVALID_PARAMETER,
-               "MAPS_ERROR_INVALID_PARAMETER");
+       MAPS_CHECK_CONDITION(latitude >= -90 && latitude <= 90,
+               MAPS_ERROR_INVALID_PARAMETER, "MAPS_ERROR_INVALID_PARAMETER");
+       MAPS_CHECK_CONDITION(longitude >= -180 && longitude <= 180,
+               MAPS_ERROR_INVALID_PARAMETER, "MAPS_ERROR_INVALID_PARAMETER");
        ((maps_coordinates_s *) coords)->latitude = latitude;
        ((maps_coordinates_s *) coords)->longitude = longitude;
        return MAPS_ERROR_NONE;
 }
 
+int _maps_coordinates_copy(maps_coordinates_h orig, maps_coordinates_h dest)
+{
+       if (!orig || !dest)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       ((maps_coordinates_s *)dest)->latitude  = ((maps_coordinates_s *)orig)->latitude;
+       ((maps_coordinates_s *)dest)->longitude = ((maps_coordinates_s *)orig)->longitude;
+       return MAPS_ERROR_NONE;
+}
+
 /*
  * Tizen 3.0
  */
index 69efd26..0cf6c25 100644 (file)
@@ -149,6 +149,7 @@ extern int _maps_view_object_overlay_operation(maps_view_h view, maps_view_objec
 static int __maps_view_set_center(maps_view_h view, maps_coordinates_h coordinates, bool internal);
 int _maps_view_move_center(maps_view_h view, const int delta_x, const int delta_y);
 int _maps_view_get_plugin_center(const maps_view_h view, maps_coordinates_h *center);
+int _maps_coordinates_copy(maps_coordinates_h orig, maps_coordinates_h dest);
 
 /* ---------------------------------------------------------------------------*/
 
@@ -397,6 +398,8 @@ static Eina_Bool __maps_view_on_idle_cb(void *data)
                                         ic->get_cur_center(),
                                         ic->get_cur_zoom_factor(),
                                         ic->get_cur_rotation_angle());
+               _maps_coordinates_copy(ic->get_cur_center(), v->center);
+
                _maps_view_on_overlay_update_all(v);
                g_usleep(10*1000);
        }
@@ -491,7 +494,6 @@ static void __maps_view_create_panel(maps_view_h view, Evas_Object *obj)
                evas_object_event_callback_add(v->panel, EVAS_CALLBACK_RESIZE, __maps_view_panel_resize_cb, v);
        } else {
                /* if obj is the other kind of (smart) objects */
-               MAPS_LOGD("The panel is not a Evas_Image");
                v->parent = obj;
                v->panel = evas_object_image_add(evas_object_evas_get(v->parent));
                evas_object_smart_member_add(v->panel, v->parent);
@@ -606,12 +608,14 @@ EXPORT_API int maps_view_create(maps_service_h maps, Evas_Object *obj, maps_view
        /* Set up the output pointer to the Maps View */
        *view = (maps_view_h) v;
 
-       /* Notify the Plugin, that the view is created */
-       __get_plugin_interface(v)->maps_plugin_create_map_view(*view, __maps_view_ready);
+       if (__get_plugin_interface(v)) {
+               /* Notify the Plugin, that the view is created */
+               __get_plugin_interface(v)->maps_plugin_create_map_view(*view, __maps_view_ready);
 
-       /* Set up zoom and rotation */
-       __get_plugin_interface(v)->maps_plugin_get_min_zoom_level(v, &v->min_zoom_level);
-       __get_plugin_interface(v)->maps_plugin_get_max_zoom_level(v, &v->max_zoom_level);
+               /* Set up zoom and rotation */
+               __get_plugin_interface(v)->maps_plugin_get_min_zoom_level(v, &v->min_zoom_level);
+               __get_plugin_interface(v)->maps_plugin_get_max_zoom_level(v, &v->max_zoom_level);
+       }
 
        if (v->min_zoom_level <= 0)
                v->min_zoom_level = 2;
@@ -630,7 +634,7 @@ EXPORT_API int maps_view_create(maps_service_h maps, Evas_Object *obj, maps_view
        v->public_transit_enabled = false;
 
        /* To check hit_test */
-       v->screen_dpi = maps_get_display_dpi();
+       maps_get_screen_dpi(&v->screen_dpi);
        v->min_hit_area = MAX(20, v->screen_dpi / 5);
 
        /* Update map view */
index 41c8871..652e9e0 100644 (file)
@@ -39,9 +39,14 @@ int maps_get_string(const char *src, const int max_length, char **dst)
        return MAPS_ERROR_NONE;
 }
 
-int maps_get_display_dpi()
+int maps_get_screen_dpi(int *dpi)
 {
-    int dpi = DEFAULT_UNKNOWN_DPI;
-    system_info_get_platform_int("http://tizen.org/feature/screen.dpi", &dpi);
-    return dpi;
+       if (!dpi)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       static int __dpi = DEFAULT_UNKNOWN_DPI;
+       if (__dpi == DEFAULT_UNKNOWN_DPI)
+               system_info_get_platform_int("http://tizen.org/feature/screen.dpi", &__dpi);
+       *dpi = __dpi;
+       return MAPS_ERROR_NONE;
 }
index 5f9f2df..1f08715 100755 (executable)
@@ -109,7 +109,17 @@ int maps_set_string(const char *src, const int max_length, char **dst);
  */
 int maps_get_string(const char *src, const int max_length, char **dst);
 
-int maps_get_display_dpi();
+/**
+ * @brief      Get the screen dpi of current device.
+ * @details This function gets the screen dpi of current device.
+ *
+ * @param[out] dpi             The screen dpi of current device.
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #MAPS_ERROR_NONE Successful
+ * @retval     #MAPS_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int maps_get_screen_dpi(int *dpi);
+
 
 /* Prevent utility highlights defects in std::vector and std::string, so
 *  simplified versions of that classes are implemented */
index c9e3dcc..614de96 100644 (file)
@@ -26,6 +26,7 @@ extern bool _maps_view_is_gesture_available(maps_view_h view,
 
 /*----------------------------------------------------------------------------*/
 
+int view::gesture_detector::__CLICK_AREA = 50;
 
 view::gesture_detector::gesture_detector(maps_view_h v)
        : _view(v)
@@ -33,6 +34,9 @@ view::gesture_detector::gesture_detector(maps_view_h v)
        , _tap_timer(NULL)
        , _long_press_timer(NULL)
 {
+       int dpi;
+       if (maps_get_screen_dpi(&dpi) == MAPS_ERROR_NONE)
+               __CLICK_AREA = dpi / 5; /* expected about 0.5cm */
 }
 
 view::gesture_detector::~gesture_detector()
index 64ca050..46368c5 100644 (file)
@@ -62,7 +62,7 @@ namespace view
                 * TODO: It is needed to calculate this value accordingly to the
                 *  device pixel dencity
                 */
-               static const int __CLICK_AREA = 50;
+               static int __CLICK_AREA;
 
        public:
                gesture_detector(maps_view_h v);
index 20e3ff0..322c5e5 100644 (file)
@@ -24,6 +24,7 @@ view::gesture_detector_statemachine::gesture_detector_statemachine(maps_view_h v
        , _current_state(STATE_NONE)
        , is_rotating(false)
        , is_zoomming(false)
+       , is_2fingers_panning(false)
 {
        for(int i = 0; i < MAX_FINGERS; i ++)
                is_panning[i] = false;
@@ -459,6 +460,7 @@ void view::gesture_detector_statemachine::state_machine_on_event(view_event_e ev
                if(event != FINGER_MOVE && event != FINGER2_MOVE) {
                        finish_zoomming();
                        finish_rotating();
+                       finish_2fingers_panning();
                }
 
                switch(event) {
@@ -552,6 +554,7 @@ void view::gesture_detector_statemachine::state_machine_on_event(view_event_e ev
                if(event != FINGER_MOVE && event != FINGER2_MOVE) {
                        finish_zoomming();
                        finish_rotating();
+                       finish_2fingers_panning();
                        _info._start_view_state.capture(_view);
                }
 
@@ -675,27 +678,33 @@ void view::gesture_detector_statemachine::detected_finger2_pan()  /* Pan (second
 void view::gesture_detector_statemachine::detected_zoom_rotate()
 {
        if (!is_gesture_available(MAPS_VIEW_GESTURE_ZOOM)
-           && !is_gesture_available(MAPS_VIEW_GESTURE_ROTATE))
+           && !is_gesture_available(MAPS_VIEW_GESTURE_ROTATE)
+           && !is_gesture_available(MAPS_VIEW_GESTURE_SCROLL))
                return;
 
        log("GESTURE ZOOM ROTATE DETECTED", FG_GREEN);
-#if 1
+
        bool zoom_changed = false;
        bool rotation_changed = false;
+       bool panning_changed = false;
        double zoom_factor = .0;
        double rotation_angle = .0;
+       int panning_x = 0;
+       int panning_y = 0;
 
-       zoom_changed = _gp.on_zoom(is_zoomming, zoom_factor);
+       zoom_changed = _gp.on_zoom(is_zoomming, is_rotating, zoom_factor);
        if (zoom_changed)
                start_zoomming();
-       rotation_changed = _gp.on_rotate(is_rotating, rotation_angle);
+
+       rotation_changed = _gp.on_rotate(is_zoomming, is_rotating, rotation_angle);
        if (rotation_changed)
                start_rotating();
 
-       _gp.on_zoom_rotate(zoom_changed, zoom_factor, rotation_changed, rotation_angle);
-#else
-       _gp.on_zoom_rotate();
-#endif
+       panning_changed = _gp.on_two_fingers_pan(is_2fingers_panning, &panning_x, &panning_y);
+       if (panning_changed)
+               start_2fingers_panning();
+
+       _gp.on_zoom_rotate(zoom_changed, zoom_factor, rotation_changed, rotation_angle, panning_changed, panning_x, panning_y);
 }
 
 void view::gesture_detector_statemachine::detected_2finger_tap()       /* 2Finger Tap */
index f93255d..24e3378 100644 (file)
@@ -91,6 +91,7 @@ namespace view
                bool is_panning[MAX_FINGERS];
                bool is_rotating;
                bool is_zoomming;
+               bool is_2fingers_panning;
 
        public:
                gesture_detector_statemachine(maps_view_h v);
@@ -121,6 +122,8 @@ namespace view
                void finish_rotating() { is_rotating = false; }
                void start_zoomming() { is_zoomming = true; }
                void finish_zoomming() { is_zoomming = false; }
+               void start_2fingers_panning() { is_2fingers_panning = true; }
+               void finish_2fingers_panning() { is_2fingers_panning = false; }
 
        private:
                void log_state(view_event_e event, detector_states_e state);
index 64b168b..3100dd1 100644 (file)
 #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
 
 /*----------------------------------------------------------------------------*/
 
@@ -66,8 +71,7 @@ view::zoom_calculator::zoom_calculator(const touch_point &start_tp_f1,
        /* 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;
@@ -76,10 +80,18 @@ view::zoom_calculator::zoom_calculator(const touch_point &start_tp_f1,
 
        /* 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;
        }
 
@@ -95,7 +107,7 @@ view::zoom_calculator::zoom_calculator(const touch_point &start_tp_f1,
                _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;
        }
 }
@@ -448,24 +460,30 @@ double view::gesture_processor::calc_angle(
                                                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];
@@ -475,21 +493,6 @@ bool view::gesture_processor::on_zoom(bool zoom_changed, double &zoom_factor)
        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();
@@ -505,22 +508,28 @@ bool view::gesture_processor::on_zoom(bool zoom_changed, double &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)
@@ -530,15 +539,13 @@ bool view::gesture_processor::on_zoom(bool zoom_changed, double &zoom_factor)
        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];
@@ -548,21 +555,6 @@ bool view::gesture_processor::on_rotate(bool rotation_changed, double &rotation_
        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();
@@ -572,22 +564,26 @@ bool view::gesture_processor::on_rotate(bool rotation_changed, double &rotation_
                /* 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)
@@ -597,9 +593,15 @@ bool view::gesture_processor::on_rotate(bool rotation_changed, double &rotation_
        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];
 
@@ -607,133 +609,88 @@ void view::gesture_processor::on_zoom_rotate(bool zoom_changed, double zoom_fact
        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, &center_x, &center_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, &center);
 
-#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, &center_x, &center_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
 }
 
 
index b8a1255..594c04b 100644 (file)
@@ -101,9 +101,10 @@ namespace view
                void on_two_finger_tap();
                void on_pan(int finger_no);
                void on_panning_finished(int finger_no);
-               bool on_zoom(bool zoom_changed, double &zoom_factor);
-               bool on_rotate(bool rotation_changed, double &rotation_angle);
-               void on_zoom_rotate(bool zoom_changed, double zoom_factor, bool rotation_changed, double rotation_angle);
+               bool on_zoom(bool zoom_changed, bool rotation_changed, double &zoom_factor);
+               bool on_rotate(bool zoom_changed, bool rotation_changed, double &rotation_angle);
+               bool on_two_fingers_pan(bool panning_changed, int *delta_x, int *delta_y);
+               void on_zoom_rotate(bool zoom_changed, double zoom_factor, bool rotation_changed, double rotation_angle, bool panning_changed, int panning_x, int panning_y);
        private:
                session::command_queue *q();
                void *get_maps();
@@ -115,10 +116,9 @@ namespace view
                                                const bool rotation_changed,
                                                const double angle);
        protected:
-               touch_point calc_center(const touch_point &tp1,
-                                               const touch_point &tp2) const;
-               double calc_angle(const double angle1,
-                                               const double angle2) const;
+               touch_point calc_center(const touch_point &tp1, const touch_point &tp2) const;
+               double calc_angle(const double angle1, const double angle2) const;
+               double calc_angle(const touch_point tp1, const touch_point tp2) const;
        };
 
 
index 14b27c7..43ea5b2 100644 (file)
@@ -20,6 +20,7 @@
 #include "maps_view_plugin.h"
 #include <glib.h>
 
+int _maps_coordinates_copy(maps_coordinates_h orig, maps_coordinates_h dest);
 
 view::inertial_camera::inertial_camera(maps_view_h view)
        : _view(view)
@@ -77,9 +78,11 @@ void view::inertial_camera::set_targets(const maps_coordinates_h center,
                return;
 
        /* Store the targets */
-       if (!target_center)
-               maps_coordinates_destroy(target_center);
-       maps_coordinates_clone(center, &target_center);
+       if (!target_center) {
+               maps_coordinates_clone(center, &target_center);
+       } else {
+               _maps_coordinates_copy(center, target_center);
+       }
 
        target_zoom_factor = zoom_factor;
        target_rotation_angle = rotation_angle;
@@ -98,9 +101,11 @@ void view::inertial_camera::set_center_target(const maps_coordinates_h center)
                return;
 
        /* Store the target */
-       if (!target_center)
-               maps_coordinates_destroy(target_center);
-       maps_coordinates_clone(center, &target_center);
+       if (!target_center) {
+               maps_coordinates_clone(center, &target_center);
+       } else {
+               _maps_coordinates_copy(center, target_center);
+       }
 
        /* Store current state */
        if (!transiting)
index 88ad7a1..84b7c0b 100644 (file)
@@ -122,8 +122,7 @@ void view::inertial_gesture::move(int finger_no, const touch_point &tp)
 
 void view::inertial_gesture::up(int finger_no, const touch_point &tp)
 {
-       MAPS_LOGI("TRANSITION finger %d up time: %d",
-                 finger_no, tp._timestamp);
+       MAPS_LOGI("TRANSITION finger %d up time: %d", finger_no, tp._timestamp);
 
        _last[finger_no] = tp;
 
@@ -134,11 +133,12 @@ void view::inertial_gesture::up(int finger_no, const touch_point &tp)
        /* check if moved enough as much as effective length */
        int trajectory_total = get_trajectory_effective_length(_down[finger_no], tp);
        int trajectory_last  = get_trajectory_effective_length(_prev[finger_no], tp);
-       MAPS_LOGD("trajectory total=%d, local=%d dx=%d, dy=%d, dt=%d",
-               trajectory_total, trajectory_last, delta_x, delta_y, dt);
 
+       /* check minimal size of click-area to be recognized as a valid gesture */
        if (trajectory_total >= __CLICK_AREA)
                transiting_trajectory = true;
+
+       /* to prevent inertial movement even by tapping gesture */
        if (trajectory_last <= __CLICK_AREA / 3.)
                transiting_trajectory = false;
 
@@ -169,7 +169,6 @@ bool view::inertial_gesture::next_transition_step()
 
                transiting_part[i] = false;
 
-#if 1
                if ((ABS(_derivative_x[i]) > __ACCURACY) || (ABS(_derivative_y[i]) > __ACCURACY)) {
                        _cur_x[i] = get_next_point(_cur_x[i], _derivative_x[i], _dt[i]);
                        _derivative_x[i] = get_next_derivative(_derivative_x[i], _dt[i]);
@@ -179,28 +178,15 @@ bool view::inertial_gesture::next_transition_step()
                        _derivative_y[i] = get_next_derivative(_derivative_y[i], _dt[i]);
                        transiting_part[i] |= ABS(_derivative_y[i]) > __ACCURACY;
                }
-#else
-               if (ABS(_derivative_x[i]) > __ACCURACY) {
-                       _cur_x[i] = get_next_point(_cur_x[i], _derivative_x[i], _dt[i]);
-                       _derivative_x[i] = get_next_derivative(_derivative_x[i], _dt[i]);
-                       transiting_part[i] |= ABS(_derivative_x[i]) > __ACCURACY;
-               }
-
-               if (ABS(_derivative_y[i]) > __ACCURACY) {
-                       _cur_y[i] = get_next_point(_cur_y[i], _derivative_y[i], _dt[i]);
-                       _derivative_y[i] = get_next_derivative(_derivative_y[i], _dt[i]);
-                       transiting_part[i] |= ABS(_derivative_y[i]) > __ACCURACY;
-               }
-#endif
 
                unsigned int timestamp = _last[i]._timestamp + get_transition_time(i);
 
                const touch_point tp(_cur_x[i], _cur_y[i], timestamp);
                if (transiting_part[i]) {
-                       MAPS_LOGI("TRANSITION finger %d move FAKE time: %d", i, tp._timestamp);
+                       /* MAPS_LOGI("TRANSITION finger %d move FAKE time: %d", i, tp._timestamp); */
                        _d->move(i, tp);
                } else {
-                       MAPS_LOGI("TRANSITION finger %d up FAKE time: %d", i, tp._timestamp);
+                       /* MAPS_LOGI("TRANSITION finger %d up FAKE time: %d", i, tp._timestamp); */
                        _d->up(i, tp);
                }
 
index 3534886..bbc26f4 100644 (file)
@@ -130,11 +130,13 @@ void view::map_state::reset()
        _prev_zoom_factor = .1;
        _prev_rotation_angle = .0;
 
+/*
        MAPS_LOGI("%c[%d;%d;%dm"
                  "central coordinates: RESET"
                  "%c[%d;%d;%dm",
                  0x1B, 1, 0, 31,
                  0x1B, 0, 0, 0);
+*/
 }
 
 void view::map_state::capture(maps_view_h view)