forked from enlightenment/efl
From: Bluezery <ohpowel@gmail.com>
Subject: [E-devel] [Patch][elm_map] Fix zoom & rotated coordinates bug In my point of view, elm_map did not consider zooming & rotation by using Evas_Map initially. There are no problems if you use only elm_map_zoom_set(). But if you use pinch gesture or wheel to do subtle zooming & rotating, the calculations of coordinates are not correct currently. I have fixed these problem and also made some utility APIs for user convenience. I made following 3 APIs. 1. elm_map_utils_size_get() Currently users can only get integer zoom level by using elm_map_zoom_get(). So if user want to calculate full map size, user should calculate pow(2.0, zoom level) * tile size. Furthermore, user assumes tile size as 256. (tile size can be changed!!) Also it's not correct sometimes because Evas_map is used for subtle zooming between zoom levels. Above APIs return correct full map size. 2. elm_map_utils_region_get() It can used for getting left top coordinates, center coordinates and width, height of currently shown map area. 3. elm_map_utils_convert_canvas_into_geo() Currently it is hard to converting x, y coordinates to geographical longitude, latitude because of subtle zooming & rotating. If use wants to get it, user uses combination of above functions and more. It is harsh job. This function is used for getting longitude, latitude from x, y coordinates of current viewport. SVN revision: 67286
This commit is contained in:
parent
c575025a4a
commit
80a3a87fa9
|
@ -86,59 +86,36 @@ my_map_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_inf
|
|||
}
|
||||
|
||||
static void
|
||||
my_map_longpressed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
|
||||
my_map_longpressed(void *data __UNUSED__, Evas_Object *obj, void *event_info)
|
||||
{
|
||||
printf("longpressed\n");
|
||||
double lon, lat;
|
||||
Evas_Coord ox, oy, x, y, w, h;
|
||||
int zoom;
|
||||
Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info;
|
||||
if (!down) return;
|
||||
if (elm_map_zoom_get(obj) < 5) return;
|
||||
|
||||
evas_object_geometry_get(data, &ox, &oy, &w, &h);
|
||||
zoom = elm_map_zoom_get(data);
|
||||
elm_map_geo_region_get(obj, &lon, &lat);
|
||||
elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, zoom) * 256, &x, &y);
|
||||
x += down->canvas.x - (w / 2) - ox;
|
||||
y += down->canvas.y - (h / 2) - oy;
|
||||
elm_map_utils_convert_coord_into_geo(obj, x, y, pow(2.0, zoom) * 256, &lon, &lat);
|
||||
|
||||
name = elm_map_utils_convert_coord_into_name(data, lon, lat);
|
||||
elm_map_canvas_to_geo_convert(obj, down->canvas.x, down->canvas.y, &lon, &lat);
|
||||
printf("x:%d, y:%d, lon:%lf, lat:%lf\n", down->canvas.x, down->canvas.y, lon, lat);
|
||||
name = elm_map_utils_convert_coord_into_name(obj, lon, lat);
|
||||
}
|
||||
|
||||
static void
|
||||
my_map_clicked_double(void *data, Evas_Object *obj, void *event_info)
|
||||
my_map_clicked_double(void *data __UNUSED__, Evas_Object *obj, void *event_info)
|
||||
{
|
||||
printf("clicked,double\n");
|
||||
double lon, lat;
|
||||
double flon, flat, tlon, tlat;
|
||||
Evas_Coord ox, oy, x, y, w, h, rx, ry, tx, ty;
|
||||
double d;
|
||||
int zoom;
|
||||
Evas_Coord size;
|
||||
Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info;
|
||||
if (!down) return;
|
||||
if (elm_map_zoom_get(obj) < 5) return;
|
||||
|
||||
evas_object_geometry_get(data, &ox, &oy, &w, &h);
|
||||
zoom = elm_map_zoom_get(data);
|
||||
if (zoom < 5) return;
|
||||
size = pow(2.0, zoom) * 256;
|
||||
elm_map_geo_region_get(obj, &lon, &lat);
|
||||
elm_map_utils_convert_geo_into_coord(obj, lon, lat, size, &x, &y);
|
||||
|
||||
rx = x;
|
||||
ry = y;
|
||||
x += down->canvas.x - ((float)w * 0.5) - ox;
|
||||
y += down->canvas.y - ((float)h * 0.5) - oy;
|
||||
elm_map_rotate_get(data, &d, NULL, NULL);
|
||||
elm_map_utils_rotate_coord(data, x, y, rx, ry, -d, &tx, &ty);
|
||||
elm_map_utils_convert_coord_into_geo(obj, tx, ty, size, &lon, &lat);
|
||||
|
||||
itc1 = elm_map_marker_class_new(data);
|
||||
elm_map_canvas_to_geo_convert(obj, down->canvas.x, down->canvas.y, &lon, &lat);
|
||||
printf("x:%d, y:%d, lon:%lf, lat:%lf\n", down->canvas.x, down->canvas.y, lon, lat);
|
||||
itc1 = elm_map_marker_class_new(obj);
|
||||
|
||||
elm_map_marker_class_del_cb_set(itc1, NULL);
|
||||
|
||||
itc_group1 = elm_map_group_class_new(data);
|
||||
itc_group1 = elm_map_group_class_new(obj);
|
||||
elm_map_group_class_icon_cb_set(itc_group1, _group_icon_get);
|
||||
elm_map_group_class_data_set(itc_group1, (void *)PACKAGE_DATA_DIR"/images/bubble.png");
|
||||
elm_map_group_class_style_set(itc_group1, "empty");
|
||||
|
@ -153,14 +130,14 @@ my_map_clicked_double(void *data, Evas_Object *obj, void *event_info)
|
|||
elm_map_route_remove(route);
|
||||
}
|
||||
|
||||
if (!route_from) route_from = elm_map_marker_add(data, lon, lat, itc1, itc_group1, NULL);
|
||||
else route_to = elm_map_marker_add(data, lon, lat, itc1, itc_group1, NULL);
|
||||
if (!route_from) route_from = elm_map_marker_add(obj, lon, lat, itc1, itc_group1, NULL);
|
||||
else route_to = elm_map_marker_add(obj, lon, lat, itc1, itc_group1, NULL);
|
||||
|
||||
if (route_from && route_to)
|
||||
{
|
||||
elm_map_marker_region_get(route_from, &flon, &flat);
|
||||
elm_map_marker_region_get(route_to, &tlon, &tlat);
|
||||
route = elm_map_route_add(data, ELM_MAP_ROUTE_TYPE_MOTOCAR, ELM_MAP_ROUTE_METHOD_FASTEST, flon, flat, tlon, tlat);
|
||||
route = elm_map_route_add(obj, ELM_MAP_ROUTE_TYPE_MOTOCAR, ELM_MAP_ROUTE_METHOD_FASTEST, flon, flat, tlon, tlat);
|
||||
elm_map_route_color_set(route, 255, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3561,3 +3561,20 @@ EAPI Evas_Object *elm_entry_end_get(const Evas_Object *obj);
|
|||
*/
|
||||
EINA_DEPRECATED EAPI Evas_Object *elm_entry_end_unset(Evas_Object *obj);
|
||||
|
||||
/**
|
||||
* Convert a pixel coordinate into a rotated pixel coordinate.
|
||||
*
|
||||
* @param obj The map object.
|
||||
* @param x horizontal coordinate of the point to rotate.
|
||||
* @param y vertical coordinate of the point to rotate.
|
||||
* @param cx rotation's center horizontal position.
|
||||
* @param cy rotation's center vertical position.
|
||||
* @param degree amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
|
||||
* @param xx Pointer where to store rotated x.
|
||||
* @param yy Pointer where to store rotated y.
|
||||
*
|
||||
* @ingroup Map
|
||||
* @deprecated Rotation is not needed to know. Use elm_map_canvas_to_geo_convert() instead
|
||||
*/
|
||||
EINA_DEPRECATED EAPI void elm_map_utils_rotate_coord(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy);
|
||||
|
||||
|
|
|
@ -2964,6 +2964,72 @@ rotate_end_cb(void *data, void *event_info __UNUSED__)
|
|||
return EVAS_EVENT_FLAG_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
_region_get(Widget_Data *wd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *w, Evas_Coord *h)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(wd);
|
||||
Evas_Coord sx, sy, tx, ty, tcx, tcy, sw, sh, tw, th, rw, rh;
|
||||
|
||||
elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
|
||||
elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
|
||||
rw = wd->size.w * wd->pinch.level;
|
||||
rh = wd->size.h * wd->pinch.level;
|
||||
|
||||
if (wd->size.w < sw)
|
||||
{
|
||||
tw = rw;
|
||||
tcx = sx + tw/2;
|
||||
tx = sx + (sw - tw)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
tw = sw;
|
||||
tcx = (sx + tw/2) * wd->pinch.level;
|
||||
tx = tcx - tw/2;
|
||||
|
||||
}
|
||||
if (wd->size.h < sh)
|
||||
{
|
||||
th = rh;
|
||||
ty = sy + (sh - th)/2;
|
||||
tcy = sy + th/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
th = sw;
|
||||
tcy = (sy + th/2) * wd->pinch.level;
|
||||
ty = tcy - th/2;
|
||||
}
|
||||
|
||||
if (x) *x = tx;
|
||||
if (y) *y = ty;
|
||||
if (cx) *cx= tcx;
|
||||
if (cy) *cy = tcy;
|
||||
if (w) *w = tw;
|
||||
if (h) *h = th;
|
||||
}
|
||||
|
||||
static void
|
||||
_coord_rotate(const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(xx);
|
||||
EINA_SAFETY_ON_NULL_RETURN(yy);
|
||||
|
||||
double r = (degree * M_PI) / 180.0;
|
||||
double tx, ty, ttx, tty;
|
||||
|
||||
tx = x - cx;
|
||||
ty = y - cy;
|
||||
|
||||
ttx = tx * cos(r);
|
||||
tty = tx * sin(r);
|
||||
tx = ttx + (ty * cos(r + M_PI_2));
|
||||
ty = tty + (ty * sin(r + M_PI_2));
|
||||
|
||||
*xx = tx + cx;
|
||||
*yy = ty + cy;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EAPI Evas_Object *
|
||||
|
@ -3373,17 +3439,16 @@ elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat)
|
|||
#ifdef HAVE_ELEMENTARY_ECORE_CON
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Evas_Coord sx, sy, sw, sh;
|
||||
Evas_Coord cx, cy;
|
||||
int rw;
|
||||
double tlon, tlat;
|
||||
EINA_SAFETY_ON_NULL_RETURN(wd);
|
||||
|
||||
if (!wd) return;
|
||||
elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
|
||||
elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
|
||||
if (wd->size.w < sw) sw = wd->size.w;
|
||||
if (wd->size.h < sh) sh = wd->size.h;
|
||||
sx += sw / 2;
|
||||
sy += sh / 2;
|
||||
|
||||
elm_map_utils_convert_coord_into_geo(obj, sx, sy, wd->size.w, lon, lat);
|
||||
_region_get(wd, NULL, NULL, &cx, &cy, NULL, NULL);
|
||||
rw = wd->size.w * wd->pinch.level;
|
||||
elm_map_utils_convert_coord_into_geo(obj, cx, cy, rw, &tlon, &tlat);
|
||||
if (lon) *lon = tlon;
|
||||
if (lat) *lat = tlat;
|
||||
#else
|
||||
(void) obj;
|
||||
(void) lon;
|
||||
|
@ -3584,25 +3649,12 @@ elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address)
|
|||
#endif
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_map_utils_rotate_coord(const Evas_Object *obj __UNUSED__, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy)
|
||||
EINA_DEPRECATED EAPI void
|
||||
elm_map_utils_rotate_coord(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy)
|
||||
{
|
||||
#ifdef HAVE_ELEMENTARY_ECORE_CON
|
||||
if ((!xx) || (!yy)) return;
|
||||
|
||||
double r = (degree * M_PI) / 180.0;
|
||||
double tx, ty, ttx, tty;
|
||||
|
||||
tx = x - cx;
|
||||
ty = y - cy;
|
||||
|
||||
ttx = tx * cos(r);
|
||||
tty = tx * sin(r);
|
||||
tx = ttx + (ty * cos(r + M_PI_2));
|
||||
ty = tty + (ty * sin(r + M_PI_2));
|
||||
|
||||
*xx = tx + cx;
|
||||
*yy = ty + cy;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
_coord_rotate(x, y, cx, cy, degree, xx, yy);
|
||||
#else
|
||||
(void) x;
|
||||
(void) y;
|
||||
|
@ -3614,6 +3666,44 @@ elm_map_utils_rotate_coord(const Evas_Object *obj __UNUSED__, const Evas_Coord x
|
|||
#endif
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, double *lon, double *lat)
|
||||
{
|
||||
#ifdef HAVE_ELEMENTARY_ECORE_CON
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
EINA_SAFETY_ON_NULL_RETURN(lon);
|
||||
EINA_SAFETY_ON_NULL_RETURN(lat);
|
||||
EINA_SAFETY_ON_NULL_RETURN(wd);
|
||||
|
||||
Evas_Coord xx, yy, w, h, mw, tx, ty, cx, cy;
|
||||
double d;
|
||||
|
||||
_region_get(wd, &xx, &yy, &cx, &cy, &w, &h);
|
||||
mw = wd->size.w * wd->pinch.level;
|
||||
if (w < mw)
|
||||
{
|
||||
xx += x;
|
||||
yy += y;
|
||||
}
|
||||
else
|
||||
{
|
||||
xx = x - xx;
|
||||
yy = y - yy;
|
||||
}
|
||||
|
||||
elm_map_rotate_get(obj, &d, NULL, NULL);
|
||||
_coord_rotate(xx, yy, cx, cy, -d, &tx, &ty);
|
||||
elm_map_utils_convert_coord_into_geo(obj, tx, ty, mw, lon, lat);
|
||||
#else
|
||||
(void) obj;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) lon;
|
||||
(void) lat;
|
||||
#endif
|
||||
}
|
||||
|
||||
EAPI Elm_Map_Marker *
|
||||
elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data)
|
||||
{
|
||||
|
|
|
@ -266,7 +266,7 @@ EAPI void elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_
|
|||
EAPI Elm_Map_Zoom_Mode elm_map_zoom_mode_get(const Evas_Object *obj);
|
||||
|
||||
/**
|
||||
* Get the current coordinates of the map.
|
||||
* Get the current geographic coordinates of the map.
|
||||
*
|
||||
* @param obj The map object.
|
||||
* @param lon Pointer where to store longitude.
|
||||
|
@ -494,20 +494,26 @@ EAPI Elm_Map_Name *elm_map_utils_convert_coord_into_name(const Evas_Obje
|
|||
EAPI Elm_Map_Name *elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address);
|
||||
|
||||
/**
|
||||
* Convert a pixel coordinate into a rotated pixel coordinate.
|
||||
* Convert canvas coordinates into a geographic coordinate
|
||||
* (longitude, latitude).
|
||||
*
|
||||
* @param obj The map object.
|
||||
* @param x horizontal coordinate of the point to rotate.
|
||||
* @param y vertical coordinate of the point to rotate.
|
||||
* @param cx rotation's center horizontal position.
|
||||
* @param cy rotation's center vertical position.
|
||||
* @param degree amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
|
||||
* @param xx Pointer where to store rotated x.
|
||||
* @param yy Pointer where to store rotated y.
|
||||
* @param x horizontal coordinate of the point to convert.
|
||||
* @param y vertical coordinate of the point to convert.
|
||||
* @param lon A poniter to the longitude.
|
||||
* @param lat A pointer to the latitude.
|
||||
*
|
||||
* This gets longitude and latitude from canvas x, y coordinates. The canvas
|
||||
* coordinates mean x, y coordinate from current viewport.
|
||||
* elm_map_utils_convert_coord_into_geo() internally to get the geographic
|
||||
* location.
|
||||
*
|
||||
* see elm_map_rotate_get()
|
||||
* see elm_map_utils_convert_coord_into_geo()
|
||||
*
|
||||
* @ingroup Map
|
||||
*/
|
||||
EAPI void elm_map_utils_rotate_coord(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy);
|
||||
EAPI void elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, double *lon, double *lat);
|
||||
|
||||
/**
|
||||
* Add a new marker to the map object.
|
||||
|
|
Loading…
Reference in New Issue