4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7 * Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
22 #include <Elementary.h>
35 #define M_PI 3.1415926535897932384626433832795
36 #define DECARTA_URL_LENGTH 512
38 static Eina_Bool init = EINA_FALSE;
39 static Evas_Object *init_obj = NULL;
40 static char source_url[ZOOM_MAX+1][PATH_MAX];
41 static int source_req_done[ZOOM_MAX+1];
42 static Eina_Bool decarta_init = EINA_FALSE;
44 typedef struct _Grid_Pos
50 static Eina_Bool url_fixed[ZOOM_MAX + 1] = {EINA_FALSE};
51 static Grid_Pos map_center[ZOOM_MAX + 1] =
53 {-180.000000,85.084059},
54 {-90.000000,66.653476},
55 {-135.000000,79.242052},
56 {-174.375000,84.577645},
57 {-168.750000,84.019227},
58 {-174.375000,84.577645},
59 {-177.187500,84.837041},
60 {-178.593750,84.962060},
61 {-179.296875,85.023432},
62 {-179.648438,85.053838},
63 {-179.824219,85.068972},
64 {-179.912109,85.076521},
65 {-179.956055,85.080292},
66 {-179.978027,85.082176},
67 {-179.989014,85.083117},
68 {-179.994507,85.083588},
69 {-179.997253,85.083824},
70 {-179.998627,85.083941},
71 {-179.999313,85.084000}};
72 /* {-179.999657,85.084030},
73 {-179.999828,85.084044}};*/
75 static Grid_Pos map_init[ZOOM_MAX+1] =
77 {-180.000000,0.000000 },
78 {-180.000000,66.653476},
79 {-180.000000,79.242052},
80 {-180.000000,82.724733},
81 {-180.000000,84.019227},
82 {-180.000000,84.577645},
83 {-180.000000,84.837041},
84 {-180.000000,84.962060},
85 {-180.000000,85.023432},
86 {-180.000000,85.053838},
87 {-180.000000,85.068972},
88 {-180.000000,85.076521},
89 {-180.000000,85.080292},
90 {-180.000000,85.082176},
91 {-180.000000,85.083117},
92 {-180.000000,85.083588},
93 {-180.000000,85.083824},
94 {-180.000000,85.083941},
95 {-180.000000,85.084000}};
96 /* {-180.000000,85.084030},
97 {-180.000000,85.084044}};*/
99 static void map_callback(DecartaError error, const DecartaMap *map, void *data)
103 int zoom = (int)data;
105 if ((error == DECARTA_ERROR_NONE) && (map) && (map->tile_url)) {
106 source_url[zoom][DECARTA_URL_LENGTH - 1] = '\0';
107 url_fixed[zoom] = EINA_TRUE;
108 strncpy(source_url[zoom], map->tile_url, DECARTA_URL_LENGTH);
111 if (strlen(source_url[zoom]) == 0 || error != DECARTA_ERROR_NONE) {
112 g_debug("map_callback() failed: zoom[%d], error[%d]", zoom, error);
113 source_req_done[zoom] = -1;
115 g_debug("map_callback() success: zoom[%d], error[%d]", zoom, error);
116 source_req_done[zoom] = 1;
119 for (idx = ZOOM_MIN; idx <= ZOOM_MAX; idx++) {
120 if (source_req_done[idx] <= 0) {
123 if (idx == ZOOM_MAX) {
128 if ((init) && (init_obj)) {
130 elm_map_region_get(init_obj, &lon, &lat);
131 elm_map_region_bring_in(init_obj, lon - 0.00001, lat - 0.00001);
132 elm_map_region_show(init_obj, lon, lat);
136 static void map_request(int zoom)
138 strncpy(source_url[zoom], "", 1);
141 DecartaPosition *position = decarta_position_new (map_init[zoom].lat, map_init[zoom].lon);
142 re = decarta_search_map_async(position, zoom, &map_callback, (void*)zoom);
144 g_debug("decarta_search_map_async failed!!!, re[%d]\n", re);
145 decarta_init = EINA_FALSE;
147 decarta_init = EINA_TRUE;
149 decarta_position_free(position);
152 static double mercator_unproject(double t)
154 return ((double)(M_PI) / 2.0) - 2.0 * atan(t);
157 static double find_rad_phi(double phi, double t)
159 double ecc = 0.08181919084262157;
160 double eSinPhi = ecc * sin(phi);
162 double precalculate = t * pow(((1 - eSinPhi) / (1 + eSinPhi)), (ecc / 2));
163 double result = (M_PI / 2) - (2 * (atan(precalculate)));
168 EAPI char *map_module_source_name_get(void)
170 return strdup("Decarta Normal");
173 EAPI int map_module_tile_zoom_min_get(void)
178 EAPI int map_module_tile_zoom_max_get(void)
183 EAPI char *map_module_tile_url_get(Evas_Object *obj, int x, int y, int zoom)
187 if (source_req_done[zoom] != 1) {
188 g_debug("source_req_done[%d] != 1 \n", zoom);
192 if (strlen(source_url[zoom])) {
193 char *n, *nn, *e, *ee;
194 char strn[10], stre[10];
195 char buf[PATH_MAX] = {'\0'};
196 char buf2[PATH_MAX] = {'\0'};
197 char _source_url[PATH_MAX] = {'\0'};
203 strncpy(_source_url, source_url[zoom], PATH_MAX - 1);
204 n = strstr(_source_url, "&N=");
205 nn = strstr(n+1, "&");
207 nn = _source_url + strlen(_source_url);
210 e = strstr(_source_url, "&E=");
211 ee = strstr(e+1, "&");
213 ee = _source_url + strlen(_source_url);
216 strncat(strn, n + 3, nn - n - 3);
217 strncat(stre, e + 3, ee - e - 3);
219 strncat(buf2, _source_url, n - _source_url);
220 snprintf(buf, PATH_MAX, "%s&N=%d&E=%d", buf2, atoi(strn) - y, atoi(stre) + x);
227 EAPI double map_module_tile_scale_get(const Evas_Object *obj, double lon, double lat, int zoom)
232 EAPI int map_module_route_source_get(void)
237 EAPI char *map_module_route_url_get(const Evas_Object *obj,
238 const char *type_name,
248 EAPI char *map_module_name_url_get(Evas_Object *obj, int method, char *name, double lon, double lat)
253 EAPI Eina_Bool map_module_tile_geo_to_coord(const Evas_Object *obj,
262 *x = floor((lon + 180.0) / 360.0 * size);
265 double radLat = (lat * (2.0 * M_PI)) / 360.0;
266 double ecc = 0.08181919084262157;
268 double sinPhi = sin(radLat);
269 double eSinPhi = ecc * sinPhi;
271 double pw = pow((1.0 - eSinPhi) / (1.0 + eSinPhi), ecc);
272 double retVal = log(((1.0 + sinPhi) / (1.0 - sinPhi)) * pw) / 2.0;
274 double y1 = retVal / (2 * M_PI / (double)size);
276 double real_zoom = log2(size/256.0);
277 int floored_zoom = floor(real_zoom);
279 if (floored_zoom >= ZOOM_MAX) {
280 lat = map_center[ZOOM_MAX].lat;
282 lat = map_center[floored_zoom].lat + (map_center[floored_zoom + 1].lat - map_center[floored_zoom].lat) * (real_zoom - floored_zoom);
285 radLat = (lat * (2.0 * M_PI)) / 360.0;
286 ecc = 0.08181919084262157;
288 sinPhi = sin(radLat);
289 eSinPhi = ecc * sinPhi;
291 pw = pow((1.0 - eSinPhi) / (1.0 + eSinPhi), ecc);
292 retVal = log(((1.0 + sinPhi) / (1.0 - sinPhi)) * pw) / 2.0;
294 double y2 = retVal / (2 * M_PI / (double)size);
297 *y = floor(y2-y1) + 128;
303 EAPI Eina_Bool map_module_tile_coord_to_geo(const Evas_Object *obj,
312 *lon = x / (double)size * 360.0 - 180;
316 double real_zoom = log2(size/256.0);
317 int floored_zoom = floor(real_zoom);
320 if (floored_zoom >= ZOOM_MAX) {
321 lat1 = map_center[ZOOM_MAX].lat;
323 lat1 = map_center[floored_zoom].lat + (map_center[floored_zoom + 1].lat - map_center[floored_zoom].lat) * (real_zoom - floored_zoom);
326 double radLat = (lat1 * (2.0 * M_PI)) / 360.0;
327 double ecc = 0.08181919084262157;
329 double sinPhi = sin(radLat);
330 double eSinPhi = ecc * sinPhi;
332 double pw = pow((1.0 - eSinPhi) / (1.0 + eSinPhi), ecc);
333 double retVal = log(((1.0 + sinPhi) / (1.0 - sinPhi)) * pw) / 2.0;
335 double yy = retVal / (2 * M_PI / (double)size);
337 double phiEpsilon = 1E-7;
338 double phiMaxIter = 12.0;
340 static double E = 2.718281828459045;
341 double t = pow(E, (-(floor(yy+128-y)) * (2 * M_PI / (double)size)));
343 double prevPhi = mercator_unproject(t);
344 double newPhi = find_rad_phi(prevPhi, t);
346 double iterCount = 0.0;
348 while ((iterCount < phiMaxIter) && (fabs(prevPhi - newPhi) > phiEpsilon)) {
350 newPhi = find_rad_phi(prevPhi, t);
353 *lat = newPhi * 180.0 / M_PI;
359 static Eina_Bool _module_init(void)
362 for (z = ZOOM_MIN; z <= ZOOM_MAX; z++){
363 source_req_done[z] = 0;
370 static void _module_shutdown(void)
373 decarta_search_map_async_cancel();
377 EINA_MODULE_INIT(_module_init);
378 EINA_MODULE_SHUTDOWN(_module_shutdown);