1 |
/*
|
2 |
Copyright (C) 2007 Alexander Atanasov <aatanasov@gmail.com>
|
3 |
|
4 |
This program is free software; you can redistribute it and/or modify
|
5 |
it under the terms of the GNU General Public License as published by
|
6 |
the Free Software Foundation; version 2 of the License.
|
7 |
|
8 |
This program is distributed in the hope that it will be useful,
|
9 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11 |
GNU General Public License for more details.
|
12 |
|
13 |
You should have received a copy of the GNU General Public License
|
14 |
along with this program; if not, write to the Free Software
|
15 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
16 |
MA 02110-1301 USA
|
17 |
|
18 |
Garmin and MapSource are registered trademarks or trademarks
|
19 |
of Garmin Ltd. or one of its subsidiaries.
|
20 |
|
21 |
*/
|
22 |
|
23 |
#include <glib.h>
|
24 |
#include <stdlib.h>
|
25 |
#include <stdio.h>
|
26 |
#include <string.h>
|
27 |
#include <math.h>
|
28 |
#include <sys/types.h>
|
29 |
#include <sys/stat.h>
|
30 |
#include <unistd.h>
|
31 |
#include "config.h"
|
32 |
#include "plugin.h"
|
33 |
#include "data.h"
|
34 |
#include "projection.h"
|
35 |
#include "item.h"
|
36 |
#include "debug.h"
|
37 |
#include "map.h"
|
38 |
#include "maptype.h"
|
39 |
#include "attr.h"
|
40 |
#include "coord.h"
|
41 |
#include "transform.h"
|
42 |
#include <stdio.h>
|
43 |
#include "attr.h"
|
44 |
#include "coord.h"
|
45 |
#include <libgarmin.h>
|
46 |
#include "garmin.h"
|
47 |
#include "gar2navit.h"
|
48 |
|
49 |
|
50 |
static int map_id;
|
51 |
|
52 |
struct map_priv {
|
53 |
int id;
|
54 |
char *filename;
|
55 |
struct gar2nav_conv *conv;
|
56 |
struct gar *g;
|
57 |
};
|
58 |
|
59 |
struct map_rect_priv {
|
60 |
int id;
|
61 |
struct coord_rect r;
|
62 |
char *label; // FIXME: Register all strings for searches
|
63 |
int limit;
|
64 |
struct map_priv *mpriv;
|
65 |
struct gmap *gmap;
|
66 |
struct gobject *cobj;
|
67 |
struct gobject *objs;
|
68 |
struct item item;
|
69 |
unsigned int last_coord;
|
70 |
void *last_itterated;
|
71 |
struct coord last_c;
|
72 |
void *last_oattr;
|
73 |
unsigned int last_attr;
|
74 |
struct gar_search *search;
|
75 |
};
|
76 |
|
77 |
int garmin_debug = 10;
|
78 |
|
79 |
void
|
80 |
logfn(char *file, int line, int level, char *fmt, ...)
|
81 |
{
|
82 |
va_list ap;
|
83 |
char fileline[256];
|
84 |
int sz;
|
85 |
if (level > garmin_debug)
|
86 |
return;
|
87 |
va_start(ap, fmt);
|
88 |
sz = sprintf(fileline, "%s:%d:%d|", file, line, level);
|
89 |
debug_vprintf(0, "", strlen(""), fileline, sz,
|
90 |
1, fmt, ap);
|
91 |
va_end(ap);
|
92 |
}
|
93 |
// need a base map and a map
|
94 |
struct gscale {
|
95 |
char *label;
|
96 |
float scale;
|
97 |
int bits;
|
98 |
};
|
99 |
|
100 |
static struct gscale mapscales[] = {
|
101 |
{"7000 km", 70000.0, 8}
|
102 |
,{"5000 km", 50000.0, 8}
|
103 |
,{"3000 km", 30000.0, 9}
|
104 |
,{"2000 km", 20000.0, 9}
|
105 |
,{"1500 km", 15000.0, 10}
|
106 |
,{"1000 km", 10000.0, 10}
|
107 |
,{"700 km", 7000.0, 11}
|
108 |
,{"500 km", 5000.0, 11}
|
109 |
,{"300 km", 3000.0, 13}
|
110 |
,{"200 km", 2000.0, 13}
|
111 |
,{"150 km", 1500.0, 13}
|
112 |
,{"100 km", 1000.0, 14}
|
113 |
,{"70 km", 700.0, 15}
|
114 |
,{"50 km", 500.0, 16}
|
115 |
,{"30 km", 300.0, 16}
|
116 |
,{"20 km", 200.0, 17}
|
117 |
,{"15 km", 150.0, 17}
|
118 |
,{"10 km", 100.0, 18}
|
119 |
,{"7 km", 70.0, 18}
|
120 |
,{"5 km", 50.0, 19}
|
121 |
,{"3 km", 30.0, 19}
|
122 |
,{"2 km", 20.0, 20}
|
123 |
,{"1.5 km", 15.0, 22}
|
124 |
,{"1 km", 10.0, 24}
|
125 |
,{"700 m", 7.0, 24}
|
126 |
,{"500 m", 5.0, 24}
|
127 |
,{"300 m", 3.0, 24}
|
128 |
,{"200 m", 2.0, 24}
|
129 |
,{"150 m", 1.5, 24}
|
130 |
,{"100 m", 1.0, 24}
|
131 |
,{"70 m", 0.7, 24}
|
132 |
,{"50 m", 0.5, 24}
|
133 |
,{"30 m", 0.3, 24}
|
134 |
,{"20 m", 0.2, 24}
|
135 |
,{"15 m", 0.1, 24}
|
136 |
,{"10 m", 0.15, 24}
|
137 |
};
|
138 |
|
139 |
|
140 |
static int
|
141 |
garmin_object_label(struct gobject *o, struct attr *attr)
|
142 |
{
|
143 |
struct map_rect_priv *mr = o->priv_data;
|
144 |
char *codepage;
|
145 |
char *label;
|
146 |
if (!mr) {
|
147 |
dlog(1, "Error object do not have priv_data!!\n");
|
148 |
return 0;
|
149 |
}
|
150 |
if (mr->label) {
|
151 |
free(mr->label);
|
152 |
}
|
153 |
label = gar_get_object_lbl(o);
|
154 |
if (label) {
|
155 |
codepage = gar_obj_codepage(o);
|
156 |
if (*codepage != 'a') {
|
157 |
mr->label = g_convert(label, -1,"utf-8",codepage,NULL,NULL,NULL);
|
158 |
free(label);
|
159 |
} else
|
160 |
mr->label = label;
|
161 |
} else {
|
162 |
mr->label = NULL;
|
163 |
return 0;
|
164 |
}
|
165 |
if (mr->label) {
|
166 |
char *cp = mr->label;
|
167 |
#warning FIXME Process label and give only the visible part
|
168 |
if (*mr->label == '@' || *mr->label == '^')
|
169 |
cp++;
|
170 |
/* FIXME: If zoomlevel is high convert ^ in the string to spaces */
|
171 |
attr->u.str = cp;
|
172 |
return 1;
|
173 |
}
|
174 |
return 0;
|
175 |
}
|
176 |
|
177 |
static int
|
178 |
garmin_object_debug(struct gobject *o, struct attr *attr)
|
179 |
{
|
180 |
struct map_rect_priv *mr = o->priv_data;
|
181 |
if (!mr) {
|
182 |
dlog(1, "Error object do not have priv_data!!\n");
|
183 |
return 0;
|
184 |
}
|
185 |
if (mr->label)
|
186 |
free(mr->label);
|
187 |
mr->label = gar_object_debug_str(o);
|
188 |
if (mr->label) {
|
189 |
attr->u.str = mr->label;
|
190 |
return 1;
|
191 |
}
|
192 |
return 0;
|
193 |
}
|
194 |
|
195 |
|
196 |
static struct map_search_priv *
|
197 |
gmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
|
198 |
{
|
199 |
struct map_rect_priv *mr=g_new0(struct map_rect_priv, 1);
|
200 |
struct gar_search *gs;
|
201 |
int rc;
|
202 |
|
203 |
dlog(1, "Called!\n");
|
204 |
mr->mpriv=map;
|
205 |
gs = g_new0(struct gar_search,1);
|
206 |
if (!gs) {
|
207 |
dlog(1, "Can not init search \n");
|
208 |
free(mr);
|
209 |
return NULL;
|
210 |
}
|
211 |
mr->search = gs;
|
212 |
switch (search->type) {
|
213 |
case attr_country_name:
|
214 |
gs->type = GS_COUNTRY;
|
215 |
break;
|
216 |
case attr_town_name:
|
217 |
gs->type = GS_CITY;
|
218 |
break;
|
219 |
case attr_town_postal:
|
220 |
gs->type = GS_ZIP;
|
221 |
break;
|
222 |
case attr_street_name:
|
223 |
gs->type = GS_ROAD;
|
224 |
break;
|
225 |
#if someday
|
226 |
case attr_region_name:
|
227 |
case attr_intersection:
|
228 |
case attr_housenumber:
|
229 |
#endif
|
230 |
default:
|
231 |
dlog(1, "Don't know how to search for %d\n", search->type);
|
232 |
goto out_err;
|
233 |
}
|
234 |
gs->match = partial ? GM_START : GM_EXACT;
|
235 |
gs->needle = strdup(search->u.str);
|
236 |
dlog(5, "Needle: %s\n", gs->needle);
|
237 |
|
238 |
mr->gmap = gar_find_subfiles(mr->mpriv->g, gs, GO_GET_SEARCH);
|
239 |
if (!mr->gmap) {
|
240 |
dlog(1, "Can not init search \n");
|
241 |
goto out_err;
|
242 |
}
|
243 |
rc = gar_get_objects(mr->gmap, 0, gs, &mr->objs, GO_GET_SEARCH);
|
244 |
if (rc < 0) {
|
245 |
dlog(1, "Error loading objects\n");
|
246 |
goto out_err;
|
247 |
}
|
248 |
mr->cobj = mr->objs;
|
249 |
dlog(4, "Loaded %d objects\n", rc);
|
250 |
return (struct map_search_priv *)mr;
|
251 |
|
252 |
out_err:
|
253 |
free(gs);
|
254 |
free(mr);
|
255 |
return NULL;
|
256 |
}
|
257 |
|
258 |
/* Assumes that only one item will be itterated at time! */
|
259 |
static void
|
260 |
coord_rewind(void *priv_data)
|
261 |
{
|
262 |
struct gobject *g = priv_data;
|
263 |
struct map_rect_priv *mr = g->priv_data;
|
264 |
mr->last_coord = 0;
|
265 |
};
|
266 |
|
267 |
static void
|
268 |
attr_rewind(void *priv_data)
|
269 |
{
|
270 |
struct gobject *g = priv_data;
|
271 |
struct map_rect_priv *mr = g->priv_data;
|
272 |
mr->last_attr = 0;
|
273 |
};
|
274 |
|
275 |
static int
|
276 |
point_coord_get(void *priv_data, struct coord *c, int count)
|
277 |
{
|
278 |
struct gobject *g = priv_data;
|
279 |
struct map_rect_priv *mr = g->priv_data;
|
280 |
struct gcoord gc;
|
281 |
if (!count)
|
282 |
return 0;
|
283 |
if (g != mr->last_itterated) {
|
284 |
mr->last_itterated = g;
|
285 |
mr->last_coord = 0;
|
286 |
}
|
287 |
|
288 |
if (mr->last_coord > 0)
|
289 |
return 0;
|
290 |
|
291 |
gar_get_object_coord(mr->gmap, g, &gc);
|
292 |
c->x = gc.x;
|
293 |
c->y = gc.y;
|
294 |
mr->last_coord++;
|
295 |
// dlog(1,"point: x=%d y=%d\n", c->x, c->y);
|
296 |
// dlog(1, "point: x=%f y=%f\n", GARDEG(c->x), GARDEG(c->y));
|
297 |
return 1;
|
298 |
}
|
299 |
|
300 |
static int
|
301 |
coord_is_node(void *priv_data)
|
302 |
{
|
303 |
struct gobject *g = priv_data;
|
304 |
struct map_rect_priv *mr = g->priv_data;
|
305 |
|
306 |
return gar_is_object_dcoord_node(mr->gmap, g, mr->last_coord);
|
307 |
}
|
308 |
|
309 |
static int
|
310 |
poly_coord_get(void *priv_data, struct coord *c, int count)
|
311 |
{
|
312 |
struct gobject *g = priv_data;
|
313 |
struct map_rect_priv *mr = g->priv_data;
|
314 |
int ndeltas = 0, total = 0;
|
315 |
struct gcoord dc;
|
316 |
|
317 |
if (!count)
|
318 |
return 0;
|
319 |
|
320 |
if (g != mr->last_itterated) {
|
321 |
mr->last_itterated = g;
|
322 |
mr->last_coord = 0;
|
323 |
}
|
324 |
ndeltas = gar_get_object_deltas(g);
|
325 |
if (mr->last_coord > ndeltas + 1)
|
326 |
return 0;
|
327 |
while (count --) {
|
328 |
if (mr->last_coord == 0) {
|
329 |
gar_get_object_coord(mr->gmap, g, &dc);
|
330 |
mr->last_c.x = dc.x;
|
331 |
mr->last_c.y = dc.y;
|
332 |
} else {
|
333 |
if (!gar_get_object_dcoord(mr->gmap, g, mr->last_coord - 1, &dc)) {
|
334 |
mr->last_coord = ndeltas + 2;
|
335 |
return total;
|
336 |
}
|
337 |
mr->last_c.x += dc.x;
|
338 |
mr->last_c.y += dc.y;
|
339 |
}
|
340 |
c->x = mr->last_c.x;
|
341 |
c->y = mr->last_c.y;
|
342 |
ddlog(1, "poly: x=%f y=%f\n", GARDEG(c->x), GARDEG(c->y));
|
343 |
// dlog(1,"poly: x=%d y=%d\n", c->x, c->y);
|
344 |
c++;
|
345 |
total++;
|
346 |
mr->last_coord ++;
|
347 |
}
|
348 |
return total;
|
349 |
}
|
350 |
|
351 |
// for _any we must return one by one
|
352 |
static int
|
353 |
point_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
|
354 |
{
|
355 |
struct gobject *g = priv_data;
|
356 |
struct map_rect_priv *mr = g->priv_data;
|
357 |
int rc;
|
358 |
switch (attr_type) {
|
359 |
case attr_any:
|
360 |
if (g != mr->last_oattr) {
|
361 |
mr->last_oattr = g;
|
362 |
mr->last_attr = 0;
|
363 |
}
|
364 |
switch(mr->last_attr) {
|
365 |
case 0:
|
366 |
mr->last_attr++;
|
367 |
attr->type = attr_label;
|
368 |
rc = garmin_object_label(g, attr);
|
369 |
if (rc)
|
370 |
return rc;
|
371 |
case 1:
|
372 |
mr->last_attr++;
|
373 |
attr->type = attr_debug;
|
374 |
rc = garmin_object_debug(g, attr);
|
375 |
if (rc)
|
376 |
return rc;
|
377 |
case 2:
|
378 |
mr->last_attr++;
|
379 |
if (g->type == GO_POLYLINE) {
|
380 |
attr->type = attr_street_name;
|
381 |
rc = garmin_object_label(g, attr);
|
382 |
if (rc)
|
383 |
return rc;
|
384 |
}
|
385 |
case 3:
|
386 |
mr->last_attr++;
|
387 |
attr->type = attr_flags;
|
388 |
attr->u.num = 0;
|
389 |
rc = gar_object_flags(g);
|
390 |
if (rc & F_ONEWAY)
|
391 |
attr->u.num |= AF_ONEWAY;
|
392 |
if (rc & F_SEGMENTED)
|
393 |
attr->u.num |= AF_SEGMENTED;
|
394 |
return 1;
|
395 |
default:
|
396 |
return 0;
|
397 |
}
|
398 |
break;
|
399 |
case attr_label:
|
400 |
attr->type = attr_label;
|
401 |
return garmin_object_label(g, attr);
|
402 |
case attr_town_name:
|
403 |
attr->type = attr_town_name;
|
404 |
return garmin_object_label(g, attr);
|
405 |
case attr_street_name:
|
406 |
attr->type = attr_type;
|
407 |
return garmin_object_label(g, attr);
|
408 |
case attr_street_name_systematic:
|
409 |
/* TODO: Get secondary labels of roads */
|
410 |
return 0;
|
411 |
case attr_flags:
|
412 |
attr->type = attr_flags;
|
413 |
attr->u.num = 0;
|
414 |
rc = gar_object_flags(g);
|
415 |
if (rc & F_ONEWAY)
|
416 |
attr->u.num |= AF_ONEWAY;
|
417 |
if (rc & F_SEGMENTED)
|
418 |
attr->u.num |= AF_SEGMENTED;
|
419 |
return 1;
|
420 |
default:
|
421 |
dlog(1, "Don't know about attribute %d[%04X]=%s yet\n", attr_type,attr_type, attr_to_name(attr_type));
|
422 |
}
|
423 |
|
424 |
return 0;
|
425 |
}
|
426 |
|
427 |
static struct item_methods methods_garmin_point = {
|
428 |
coord_rewind,
|
429 |
point_coord_get,
|
430 |
attr_rewind,
|
431 |
point_attr_get,
|
432 |
};
|
433 |
|
434 |
static struct item_methods methods_garmin_poly = {
|
435 |
coord_rewind,
|
436 |
poly_coord_get,
|
437 |
attr_rewind, // point_attr_rewind,
|
438 |
point_attr_get, // poly_attr_get,
|
439 |
coord_is_node,
|
440 |
};
|
441 |
|
442 |
static int
|
443 |
search_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
|
444 |
{
|
445 |
struct gobject *g = priv_data;
|
446 |
struct map_rect_priv *mr = g->priv_data;
|
447 |
int rc;
|
448 |
switch (attr_type) {
|
449 |
case attr_any:
|
450 |
if (g != mr->last_oattr) {
|
451 |
mr->last_oattr = g;
|
452 |
mr->last_attr = 0;
|
453 |
}
|
454 |
switch(mr->last_attr) {
|
455 |
case 0:
|
456 |
mr->last_attr++;
|
457 |
attr->type = attr_label;
|
458 |
rc = garmin_object_label(g, attr);
|
459 |
if (rc)
|
460 |
return rc;
|
461 |
case 1:
|
462 |
mr->last_attr++;
|
463 |
attr->type = attr_debug;
|
464 |
rc = garmin_object_debug(g, attr);
|
465 |
if (rc)
|
466 |
return rc;
|
467 |
case 2:
|
468 |
mr->last_attr++;
|
469 |
if (g->type == GO_POLYLINE) {
|
470 |
attr->type = attr_street_name;
|
471 |
rc = garmin_object_label(g, attr);
|
472 |
if (rc)
|
473 |
return rc;
|
474 |
}
|
475 |
case 3:
|
476 |
mr->last_attr++;
|
477 |
attr->type = attr_flags;
|
478 |
attr->u.num = 0;
|
479 |
rc = gar_object_flags(g);
|
480 |
if (rc & F_ONEWAY)
|
481 |
attr->u.num |= AF_ONEWAY;
|
482 |
if (rc & F_SEGMENTED)
|
483 |
attr->u.num |= AF_SEGMENTED;
|
484 |
return 1;
|
485 |
default:
|
486 |
return 0;
|
487 |
}
|
488 |
break;
|
489 |
case attr_label:
|
490 |
attr->type = attr_label;
|
491 |
return garmin_object_label(g, attr);
|
492 |
case attr_town_name:
|
493 |
attr->type = attr_town_name;
|
494 |
if (mr->label)
|
495 |
free(mr->label);
|
496 |
mr->label = gar_srch_get_city(g);
|
497 |
attr->u.str = mr->label;
|
498 |
if (attr->u.str)
|
499 |
return 1;
|
500 |
return 0;
|
501 |
case attr_town_id:
|
502 |
rc = gar_srch_get_cityid(g);
|
503 |
if (rc) {
|
504 |
attr->type = attr_town_id;
|
505 |
attr->u.num = rc;
|
506 |
return 1;
|
507 |
}
|
508 |
return 0;
|
509 |
case attr_town_postal:
|
510 |
attr->type = attr_town_postal;
|
511 |
attr->u.str = gar_srch_get_zip(g);
|
512 |
if (attr->u.str)
|
513 |
return 1;
|
514 |
return 0;
|
515 |
case attr_street_name:
|
516 |
attr->type = attr_street_name;
|
517 |
if (mr->label)
|
518 |
free(mr->label);
|
519 |
mr->label = gar_srch_get_roadname(g);
|
520 |
attr->u.str = mr->label;
|
521 |
if (attr->u.str)
|
522 |
return 1;
|
523 |
return 0;
|
524 |
case attr_street_id:
|
525 |
attr->type = attr_street_id;
|
526 |
attr->u.num = gar_srch_get_roadid(g);
|
527 |
if (attr->u.num)
|
528 |
return 1;
|
529 |
return 0;
|
530 |
case attr_flags:
|
531 |
attr->type = attr_flags;
|
532 |
attr->u.num = 0;
|
533 |
rc = gar_object_flags(g);
|
534 |
if (rc & F_ONEWAY)
|
535 |
attr->u.num |= AF_ONEWAY;
|
536 |
if (rc & F_SEGMENTED)
|
537 |
attr->u.num |= AF_SEGMENTED;
|
538 |
return 1;
|
539 |
case attr_country_id:
|
540 |
rc = gar_srch_get_countryid(g);
|
541 |
if (rc) {
|
542 |
attr->type = attr_country_id;
|
543 |
attr->u.num = rc;
|
544 |
return 1;
|
545 |
}
|
546 |
return 0;
|
547 |
case attr_country_name:
|
548 |
attr->type = attr_country_name;
|
549 |
attr->u.str = gar_srch_get_country(g);
|
550 |
if (attr->u.str)
|
551 |
return 1;
|
552 |
return 0;
|
553 |
case attr_district_id:
|
554 |
rc = gar_srch_get_regionid(g);
|
555 |
if (rc) {
|
556 |
attr->type = attr_district_id;
|
557 |
attr->u.num = rc;
|
558 |
return 1;
|
559 |
}
|
560 |
return 0;
|
561 |
case attr_district_name:
|
562 |
attr->type = attr_district_name;
|
563 |
attr->u.str = gar_srch_get_region(g);
|
564 |
if (attr->u.str)
|
565 |
return 1;
|
566 |
return 0;
|
567 |
case attr_town_streets_item:
|
568 |
return 0;
|
569 |
default:
|
570 |
dlog(1, "Don't know about attribute %d[%04X]=%s yet\n",
|
571 |
attr_type,attr_type, attr_to_name(attr_type));
|
572 |
}
|
573 |
|
574 |
return 0;
|
575 |
}
|
576 |
|
577 |
static int
|
578 |
search_coord_get(void *priv_data, struct coord *c, int count)
|
579 |
{
|
580 |
struct gobject *g = priv_data;
|
581 |
struct map_rect_priv *mr = g->priv_data;
|
582 |
struct gcoord gc;
|
583 |
if (!count)
|
584 |
return 0;
|
585 |
if (g != mr->last_itterated) {
|
586 |
mr->last_itterated = g;
|
587 |
mr->last_coord = 0;
|
588 |
}
|
589 |
|
590 |
if (mr->last_coord > 0)
|
591 |
return 0;
|
592 |
|
593 |
if (gar_get_object_coord(mr->gmap, g, &gc)) {
|
594 |
c->x = gc.x;
|
595 |
c->y = gc.y;
|
596 |
mr->last_coord++;
|
597 |
return 1;
|
598 |
}
|
599 |
return 0;
|
600 |
}
|
601 |
|
602 |
static struct item_methods methods_garmin_search = {
|
603 |
coord_rewind,
|
604 |
search_coord_get,
|
605 |
attr_rewind,
|
606 |
search_attr_get,
|
607 |
};
|
608 |
|
609 |
|
610 |
static struct item *
|
611 |
garmin_poi2item(struct map_rect_priv *mr, struct gobject *o, unsigned short otype)
|
612 |
{
|
613 |
if (mr->mpriv->conv) {
|
614 |
int mask = gar_object_group(o) << G2N_KIND_SHIFT;
|
615 |
mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POINT|mask, otype);
|
616 |
}
|
617 |
mr->item.meth = &methods_garmin_point;
|
618 |
return &mr->item;
|
619 |
}
|
620 |
|
621 |
static struct item *
|
622 |
garmin_pl2item(struct map_rect_priv *mr, struct gobject *o, unsigned short otype)
|
623 |
{
|
624 |
if (mr->mpriv->conv) {
|
625 |
int mask = gar_object_group(o) << G2N_KIND_SHIFT;
|
626 |
mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POLYLINE|mask, otype);
|
627 |
}
|
628 |
mr->item.meth = &methods_garmin_poly;
|
629 |
return &mr->item;
|
630 |
}
|
631 |
|
632 |
static struct item *
|
633 |
garmin_pg2item(struct map_rect_priv *mr, struct gobject *o, unsigned short otype)
|
634 |
{
|
635 |
if (mr->mpriv->conv) {
|
636 |
int mask = gar_object_group(o) << G2N_KIND_SHIFT;
|
637 |
mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POLYGONE|mask, otype);
|
638 |
}
|
639 |
mr->item.meth = &methods_garmin_poly;
|
640 |
return &mr->item;
|
641 |
}
|
642 |
|
643 |
static struct item *
|
644 |
garmin_srch2item(struct map_rect_priv *mr, struct gobject *o, unsigned short otype)
|
645 |
{
|
646 |
mr->item.type = type_country_label;
|
647 |
mr->item.meth = &methods_garmin_search;
|
648 |
return &mr->item;
|
649 |
}
|
650 |
|
651 |
static struct item *
|
652 |
garmin_obj2item(struct map_rect_priv *mr, struct gobject *o)
|
653 |
{
|
654 |
unsigned short otype;
|
655 |
otype = gar_obj_type(o);
|
656 |
mr->item.type = type_none;
|
657 |
switch (o->type) {
|
658 |
case GO_POINT:
|
659 |
return garmin_poi2item(mr, o, otype);
|
660 |
case GO_POLYLINE:
|
661 |
return garmin_pl2item(mr, o, otype);
|
662 |
case GO_POLYGON:
|
663 |
return garmin_pg2item(mr, o, otype);
|
664 |
case GO_ROAD:
|
665 |
return garmin_pl2item(mr, o, otype);
|
666 |
#if 0
|
667 |
case GO_SEARCH:
|
668 |
return garmin_srch2item(mr, o, otype);
|
669 |
#endif
|
670 |
default:
|
671 |
dlog(1, "Unknown garmin object type:%d\n",
|
672 |
o->type);
|
673 |
}
|
674 |
return NULL;
|
675 |
}
|
676 |
|
677 |
static struct item *
|
678 |
gmap_rect_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
|
679 |
{
|
680 |
struct gobject *o;
|
681 |
o = mr->objs = gar_get_object_by_id(mr->mpriv->g, id_hi, id_lo);
|
682 |
if (!o) {
|
683 |
dlog(1, "Can not find object\n");
|
684 |
return NULL;
|
685 |
}
|
686 |
|
687 |
mr->item.id_hi = id_hi;
|
688 |
mr->item.id_lo = id_lo;
|
689 |
mr->item.priv_data = o;
|
690 |
mr->item.type = type_none;
|
691 |
o->priv_data = mr;
|
692 |
if (!garmin_obj2item(mr, o))
|
693 |
return NULL;
|
694 |
return &mr->item;
|
695 |
}
|
696 |
|
697 |
static struct item *
|
698 |
gmap_rect_get_item(struct map_rect_priv *mr)
|
699 |
{
|
700 |
struct gobject *o;
|
701 |
if (!mr->objs)
|
702 |
return NULL;
|
703 |
if (!mr->cobj)
|
704 |
return NULL;
|
705 |
// mr->cobj = mr->objs;
|
706 |
o = mr->cobj;
|
707 |
// dlog(1, "gi:o=%p\n", o);
|
708 |
mr->cobj = mr->cobj->next;
|
709 |
if (o) {
|
710 |
mr->item.id_hi = gar_object_mapid(o);
|
711 |
mr->item.id_lo = gar_object_index(o);
|
712 |
mr->item.priv_data = o;
|
713 |
mr->item.type = type_none;
|
714 |
o->priv_data = mr;
|
715 |
if (!garmin_obj2item(mr, o))
|
716 |
return NULL;
|
717 |
return &mr->item;
|
718 |
}
|
719 |
return NULL;
|
720 |
}
|
721 |
|
722 |
#define max(a,b) ((a) > (b) ? (a) : (b))
|
723 |
struct nl2gl_t {
|
724 |
int g;
|
725 |
int bits;
|
726 |
char *descr;
|
727 |
};
|
728 |
|
729 |
struct nl2gl_t nl2gl_1[] = {
|
730 |
{ /* 0 */ .g = 12, .descr = "0-120m", },
|
731 |
{ /* 1 */ .g = 11, .descr = "0-120m", },
|
732 |
{ /* 2 */ .g = 10, .descr = "0-120m", },
|
733 |
{ /* 3 */ .g = 9, .descr = "0-120m", },
|
734 |
{ /* 4 */ .g = 8, .descr = "0-120m", },
|
735 |
{ /* 5 */ .g = 7, .descr = "0-120m", },
|
736 |
{ /* 6 */ .g = 6, .descr = "0-120m", },
|
737 |
{ /* 7 */ .g = 5, .descr = "0-120m", },
|
738 |
{ /* 8 */ .g = 4, .descr = "0-120m", },
|
739 |
{ /* 9 */ .g = 4, .descr = "0-120m", },
|
740 |
{ /* 10 */ .g = 3, .descr = "0-120m", },
|
741 |
{ /* 11 */ .g = 3, .descr = "0-120m", },
|
742 |
{ /* 12 */ .g = 2, .descr = "0-120m", },
|
743 |
{ /* 13 */ .g = 2, .descr = "0-120m", },
|
744 |
{ /* 14 */ .g = 2, .descr = "0-120m", },
|
745 |
{ /* 15 */ .g = 1, .descr = "0-120m", },
|
746 |
{ /* 16 */ .g = 1, .descr = "0-120m", },
|
747 |
{ /* 17 */ .g = 1, .descr = "0-120m", },
|
748 |
{ /* 18 */ .g = 0, .descr = "0-120m", },
|
749 |
};
|
750 |
|
751 |
struct nl2gl_t nl2gl[] = {
|
752 |
{ /* 0 */ .g = 9, .descr = "0-120m", },
|
753 |
{ /* 1 */ .g = 9, .descr = "0-120m", },
|
754 |
{ /* 2 */ .g = 8, .descr = "0-120m", },
|
755 |
{ /* 3 */ .g = 8, .descr = "0-120m", },
|
756 |
{ /* 4 */ .g = 7, .descr = "0-120m", },
|
757 |
{ /* 5 */ .g = 7, .descr = "0-120m", },
|
758 |
{ /* 6 */ .g = 6, .descr = "0-120m", },
|
759 |
{ /* 7 */ .g = 6, .descr = "0-120m", },
|
760 |
{ /* 8 */ .g = 5, .descr = "0-120m", },
|
761 |
{ /* 9 */ .g = 5, .descr = "0-120m", },
|
762 |
{ /* 10 */ .g = 4, .descr = "0-120m", },
|
763 |
{ /* 11 */ .g = 4, .descr = "0-120m", },
|
764 |
{ /* 12 */ .g = 3, .descr = "0-120m", },
|
765 |
{ /* 13 */ .g = 3, .descr = "0-120m", },
|
766 |
{ /* 14 */ .g = 2, .descr = "0-120m", },
|
767 |
{ /* 15 */ .g = 2, .descr = "0-120m", },
|
768 |
{ /* 16 */ .g = 1, .descr = "0-120m", },
|
769 |
{ /* 17 */ .g = 1, .descr = "0-120m", },
|
770 |
{ /* 18 */ .g = 0, .descr = "0-120m", },
|
771 |
};
|
772 |
|
773 |
static int
|
774 |
get_level(struct map_selection *sel)
|
775 |
{
|
776 |
return sel->order;
|
777 |
}
|
778 |
|
779 |
static int
|
780 |
garmin_get_selection(struct map_rect_priv *map, struct map_selection *sel)
|
781 |
{
|
782 |
struct gar_rect r;
|
783 |
struct gmap *gm;
|
784 |
struct gobject **glast = NULL;
|
785 |
int rc;
|
786 |
int sl, el;
|
787 |
int level = 0; // 18; /* max level for maps, overview maps can have bigger
|
788 |
/* levels we do not deal w/ them
|
789 |
*/
|
790 |
int flags = 0;
|
791 |
if (sel && sel->range.min == type_street_0 && sel->range.max == type_ferry) {
|
792 |
// Get all roads
|
793 |
flags = GO_GET_ROUTABLE;
|
794 |
} else if (sel)
|
795 |
flags = GO_GET_SORTED;
|
796 |
|
797 |
if (sel) {
|
798 |
r.lulat = sel->u.c_rect.lu.y;
|
799 |
r.lulong = sel->u.c_rect.lu.x;
|
800 |
r.rllat = sel->u.c_rect.rl.y;
|
801 |
r.rllong = sel->u.c_rect.rl.x;
|
802 |
level = get_level(sel);
|
803 |
// level = nl2gl[level].g;
|
804 |
dlog(2, "Looking level=%d for %f %f %f %f\n",
|
805 |
level, r.lulat, r.lulong, r.rllat, r.rllong);
|
806 |
}
|
807 |
gm = gar_find_subfiles(map->mpriv->g, sel ? &r : NULL, flags);
|
808 |
if (!gm) {
|
809 |
if (sel) {
|
810 |
dlog(1, "Can not find map data for the area: %f %f %f %f\n",
|
811 |
r.lulat, r.lulong, r.rllat, r.rllong);
|
812 |
} else {
|
813 |
dlog(1, "Can not find map data\n");
|
814 |
}
|
815 |
return -1;
|
816 |
}
|
817 |
#if 0
|
818 |
sl = (18-(gm->maxlevel - gm->minlevel))/2;
|
819 |
el = sl + (gm->maxlevel - gm->minlevel);
|
820 |
if (level < sl)
|
821 |
level = sl;
|
822 |
if (level > el)
|
823 |
level = el;
|
824 |
level = level - sl;
|
825 |
level = (gm->maxlevel - gm->minlevel) - level;
|
826 |
dlog(3, "sl=%d el=%d level=%d\n", sl, el, level);
|
827 |
#endif
|
828 |
sl = (18-gm->zoomlevels)/2;
|
829 |
el = sl + gm->zoomlevels;
|
830 |
if (level < sl)
|
831 |
level = sl;
|
832 |
if (level > el)
|
833 |
level = el;
|
834 |
level = level - sl;
|
835 |
level = gm->basebits + level;
|
836 |
dlog(3, "sl=%d el=%d level=%d\n", sl, el, level);
|
837 |
map->gmap = gm;
|
838 |
glast = &map->objs;
|
839 |
while (*glast) {
|
840 |
if ((*glast)->next) {
|
841 |
*glast = (*glast)->next;
|
842 |
} else
|
843 |
break;
|
844 |
}
|
845 |
rc = gar_get_objects(gm, level, sel ? &r : NULL, glast, flags);
|
846 |
if (rc < 0) {
|
847 |
dlog(1, "Error loading objects\n");
|
848 |
return -1;
|
849 |
}
|
850 |
map->cobj = map->objs;
|
851 |
dlog(2, "Loaded %d objects\n", rc);
|
852 |
return rc;
|
853 |
}
|
854 |
// Can not return NULL, navit segfaults
|
855 |
static struct map_rect_priv *
|
856 |
gmap_rect_new(struct map_priv *map, struct map_selection *sel)
|
857 |
{
|
858 |
struct map_selection *ms = sel;
|
859 |
struct map_rect_priv *mr;
|
860 |
|
861 |
if (!map)
|
862 |
return NULL;
|
863 |
mr = calloc(1, sizeof(*mr));
|
864 |
if (!mr)
|
865 |
return mr;
|
866 |
mr->mpriv = map;
|
867 |
if (!sel) {
|
868 |
return mr;
|
869 |
} else {
|
870 |
while (ms) {
|
871 |
dlog(2, "order %d\n", ms->order);
|
872 |
if (garmin_get_selection(mr, ms) < 0) {
|
873 |
// free(mr);
|
874 |
// return NULL;
|
875 |
}
|
876 |
ms = ms->next;
|
877 |
}
|
878 |
}
|
879 |
return mr;
|
880 |
}
|
881 |
|
882 |
static void
|
883 |
gmap_rect_destroy(struct map_rect_priv *mr)
|
884 |
{
|
885 |
dlog(11,"destroy maprect\n");
|
886 |
if (mr->gmap)
|
887 |
gar_free_gmap(mr->gmap);
|
888 |
if (mr->objs)
|
889 |
gar_free_objects(mr->objs);
|
890 |
if (mr->label)
|
891 |
free(mr->label);
|
892 |
free(mr);
|
893 |
}
|
894 |
|
895 |
static void
|
896 |
gmap_search_destroy(struct map_search_priv *ms)
|
897 |
{
|
898 |
gmap_rect_destroy((struct map_rect_priv *)ms);
|
899 |
}
|
900 |
|
901 |
static void
|
902 |
gmap_destroy(struct map_priv *m)
|
903 |
{
|
904 |
dlog(5, "garmin_map_destroy\n");
|
905 |
if (m->g)
|
906 |
gar_free(m->g);
|
907 |
if (m->filename)
|
908 |
free(m->filename);
|
909 |
free(m);
|
910 |
}
|
911 |
|
912 |
static struct map_methods map_methods = {
|
913 |
projection_garmin,
|
914 |
"utf-8",
|
915 |
gmap_destroy,
|
916 |
gmap_rect_new,
|
917 |
gmap_rect_destroy,
|
918 |
gmap_rect_get_item,
|
919 |
gmap_rect_get_item_byid,
|
920 |
gmap_search_new,
|
921 |
gmap_search_destroy,
|
922 |
NULL,
|
923 |
};
|
924 |
|
925 |
static struct map_priv *
|
926 |
gmap_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
|
927 |
{
|
928 |
struct map_priv *m;
|
929 |
struct attr *data;
|
930 |
struct attr *debug;
|
931 |
struct attr *flags;
|
932 |
char buf[PATH_MAX];
|
933 |
struct stat st;
|
934 |
int dl = 1;
|
935 |
struct gar_config cfg;
|
936 |
int debugmask = 0;
|
937 |
|
938 |
data=attr_search(attrs, NULL, attr_data);
|
939 |
if (! data)
|
940 |
return NULL;
|
941 |
debug=attr_search(attrs, NULL, attr_debug);
|
942 |
if (debug) {
|
943 |
dl = atoi(debug->u.str);
|
944 |
if (!dl)
|
945 |
dl = 1;
|
946 |
}
|
947 |
flags=attr_search(attrs, NULL, attr_flags);
|
948 |
if (flags) {
|
949 |
debugmask = flags->u.num;
|
950 |
}
|
951 |
m=g_new(struct map_priv, 1);
|
952 |
m->id=++map_id;
|
953 |
m->filename = strdup(data->u.str);
|
954 |
if (!m->filename) {
|
955 |
g_free(m);
|
956 |
return NULL;
|
957 |
}
|
958 |
memset(&cfg, 0, sizeof(struct gar_config));
|
959 |
cfg.opm = OPM_GPS;
|
960 |
cfg.debuglevel = dl;
|
961 |
cfg.debugmask = debugmask;
|
962 |
garmin_debug = dl;
|
963 |
m->g = gar_init_cfg(NULL, logfn, &cfg);
|
964 |
if (!m->g) {
|
965 |
g_free(m->filename);
|
966 |
g_free(m);
|
967 |
return NULL;
|
968 |
}
|
969 |
// we want the data now, later we can load only what's necessery
|
970 |
if (gar_img_load(m->g, m->filename, 1) < 0) {
|
971 |
gar_free(m->g);
|
972 |
g_free(m->filename);
|
973 |
g_free(m);
|
974 |
return NULL;
|
975 |
}
|
976 |
m->conv = NULL;
|
977 |
snprintf(buf, sizeof(buf), "%s.types", m->filename);
|
978 |
if (!stat(buf, &st)) {
|
979 |
dlog(1, "Loading custom types from %s\n", buf);
|
980 |
m->conv = g2n_conv_load(buf);
|
981 |
}
|
982 |
if (!m->conv) {
|
983 |
dlog(1, "Using builtin types\n");
|
984 |
m->conv = g2n_default_conv();
|
985 |
}
|
986 |
if (!m->conv) {
|
987 |
dlog(1, "Failed to load map types\n");
|
988 |
}
|
989 |
*meth=map_methods;
|
990 |
return m;
|
991 |
}
|
992 |
|
993 |
void
|
994 |
plugin_init(void)
|
995 |
{
|
996 |
plugin_register_map_type("garmin", gmap_new);
|
997 |
}
|