/[zanavi_public1]/navit/navit/map/mg/street.c
ZANavi

Contents of /navit/navit/map/mg/street.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (9 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 36285 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include "debug.h"
25 #include "mg.h"
26
27 int coord_debug;
28
29 #if 0
30 static void street_name_numbers_get(struct street_name_numbers *name_numbers, unsigned char **p);
31 static void street_name_number_get(struct street_name_number *name_number, unsigned char **p);
32
33 static void
34 street_name_debug(struct street_name *sn, FILE *out)
35 {
36 struct street_name_numbers nns;
37 unsigned char *p=sn->aux_data;
38 unsigned char *end=p+sn->aux_len;
39 int i;
40
41 while (p < end) {
42 unsigned char *pn,*pn_end;
43 struct street_name_number nn;
44 street_name_numbers_get(&nns, &p);
45 fprintf(out,"0x%x 0x%x type=town_label label=\"%s(%d):0x%x:%d%s-%d%s\" debug=\"len=0x%x\"",nns.c->x,nns.c->y,sn->name2, sn->segment_count, nns.tag, nns.first.number,nns.first.suffix,nns.last.number,nns.last.suffix,nns.len);
46 for (i = 0 ; i < sn->segment_count ; i++) {
47 fprintf(out," debug=\"segment(%d)=0x%x\"",i,sn->segments[i].segid);
48 }
49 fprintf(out,"\n");
50 pn=nns.aux_data;
51 pn_end=nns.aux_data+nns.aux_len;
52 while (pn < pn_end) {
53 street_name_number_get(&nn, &pn);
54 fprintf(out,"0x%x 0x%x type=town_label label=\"%s:0x%x:%d%s-%d%s\" debug=\"len=0x%x\"\n", nn.c->x, nn.c->y, sn->name2, nn.tag, nn.first.number, nn.first.suffix, nn.last.number,nn.last.suffix,nn.len);
55 }
56 }
57 fflush(out);
58 }
59 #endif
60
61 static void
62 street_name_get(struct street_name *name, unsigned char **p)
63 {
64 #if 0
65 static FILE *out;
66 static GHashTable *hash;
67 #endif
68 unsigned char *start=*p;
69 name->len=get_u16_unal(p);
70 name->country=get_u16_unal(p);
71 name->townassoc=get_u32_unal(p);
72 name->name1=get_string(p);
73 name->name2=get_string(p);
74 name->segment_count=get_u32_unal(p);
75 name->segments=(struct street_name_segment *)(*p);
76 (*p)+=(sizeof (struct street_name_segment))*name->segment_count;
77 name->aux_len=name->len-(*p-start);
78 name->aux_data=*p;
79 name->tmp_len=name->aux_len;
80 name->tmp_data=name->aux_data;
81 *p=start+name->len;
82 #if 0
83 if (! out) {
84 out=fopen("hn.txt","a");
85 }
86 if (! hash) {
87 hash=g_hash_table_new(NULL,NULL);
88 }
89 if (! g_hash_table_lookup(hash, *p)) {
90 g_hash_table_insert(hash, *p, (void *)1);
91 street_name_debug(name, out);
92 }
93 #endif
94 }
95
96 static int
97 street_name_eod(struct street_name *name)
98 {
99 return (name->tmp_data >= name->aux_data+name->aux_len);
100 }
101
102 static void
103 street_name_numbers_get(struct street_name_numbers *name_numbers, unsigned char **p)
104 {
105 unsigned char *start=*p;
106 name_numbers->len=get_u16_unal(p);
107 name_numbers->tag=get_u8(p);
108 name_numbers->dist=get_u32_unal(p);
109 name_numbers->country=get_u32_unal(p);
110 name_numbers->c=coord_get(p);
111 name_numbers->first.number=get_u16_unal(p);
112 name_numbers->first.suffix=get_string(p);
113 name_numbers->last.number=get_u16_unal(p);
114 name_numbers->last.suffix=get_string(p);
115 name_numbers->segment_count=get_u32_unal(p);
116 name_numbers->segments=(struct street_name_segment *)(*p);
117 (*p)+=sizeof(struct street_name_segment)*name_numbers->segment_count;
118 name_numbers->aux_len=name_numbers->len-(*p-start);
119 name_numbers->aux_data=*p;
120 name_numbers->tmp_len=name_numbers->aux_len;
121 name_numbers->tmp_data=name_numbers->aux_data;
122 *p=start+name_numbers->len;
123 }
124
125 static int
126 street_name_numbers_eod(struct street_name_numbers *name_numbers)
127 {
128 return (name_numbers->tmp_data >= name_numbers->aux_data+name_numbers->aux_len);
129 }
130
131
132 static int
133 street_name_numbers_get_byid(struct street_name_numbers *name_numbers, struct street_name *name, int id)
134 {
135 unsigned char *p=name->aux_data;
136 unsigned char *end=p+name->aux_len;
137 while (id >= 0) {
138 if (p >= end)
139 return 0;
140 street_name_numbers_get(name_numbers, &p);
141 id--;
142 }
143 return 1;
144 }
145
146 static void
147 street_name_number_get(struct street_name_number *name_number, unsigned char **p)
148 {
149 unsigned char *start=*p;
150 name_number->len=get_u16_unal(p);
151 name_number->tag=get_u8(p);
152 name_number->c=coord_get(p);
153 name_number->first.number=get_u16_unal(p);
154 name_number->first.suffix=get_string(p);
155 name_number->last.number=get_u16_unal(p);
156 name_number->last.suffix=get_string(p);
157 name_number->segment=(struct street_name_segment *)p;
158 *p=start+name_number->len;
159 }
160
161 static int
162 street_name_number_get_byid(struct street_name_number *name_number, struct street_name_numbers *name_numbers, int id)
163 {
164 unsigned char *p=name_numbers->tmp_data;
165 unsigned char *end=p+name_numbers->tmp_len;
166 while (id >= 0) {
167 if (p >= end)
168 return 0;
169 street_name_number_get(name_number, &p);
170 id--;
171 }
172 return 1;
173 }
174
175 static void
176 street_name_get_by_id(struct street_name *name, struct file *file, unsigned long id)
177 {
178 unsigned char *p;
179 if (id) {
180 p=file->begin+id+0x2000;
181 street_name_get(name, &p);
182 }
183 }
184
185 static int street_get_bytes(struct coord_rect *r)
186 {
187 int bytes,dx,dy;
188 bytes=2;
189 dx=r->rl.x-r->lu.x;
190 dy=r->lu.y-r->rl.y;
191 dbg_assert(dx > 0);
192 dbg_assert(dy > 0);
193 if (dx > 32767 || dy > 32767)
194 bytes=3;
195 if (dx > 8388608 || dy > 8388608)
196 bytes=4;
197
198 return bytes;
199 }
200
201 static int street_get_coord(unsigned char **pos, int bytes, struct coord_rect *ref, struct coord *f)
202 {
203 unsigned char *p;
204 int x,y,flags=0;
205
206 p=*pos;
207 x=*p++;
208 x|=(*p++) << 8;
209 if (bytes == 2) {
210 if ( x > 0x7fff) {
211 x=0x10000-x;
212 flags=1;
213 }
214 }
215 else if (bytes == 3) {
216 x|=(*p++) << 16;
217 if ( x > 0x7fffff) {
218 x=0x1000000-x;
219 flags=1;
220 }
221 } else {
222 x|=(*p++) << 16;
223 x|=(*p++) << 24;
224 if (x < 0) {
225 x=-x;
226 flags=1;
227 }
228 }
229 y=*p++;
230 y|=(*p++) << 8;
231 if (bytes == 3) {
232 y|=(*p++) << 16;
233 } else if (bytes == 4) {
234 y|=(*p++) << 16;
235 y|=(*p++) << 24;
236 }
237 if (f) {
238 f->x=ref->lu.x+x;
239 f->y=ref->rl.y+y;
240 dbg(1,"0x%x,0x%x + 0x%x,0x%x = 0x%x,0x%x\n", x, y, ref->lu.x, ref->rl.y, f->x, f->y);
241 }
242 *pos=p;
243 return flags;
244 }
245
246 static void
247 street_coord_get_begin(unsigned char **p)
248 {
249 struct street_str *str;
250
251 str=(struct street_str *)(*p);
252 while (street_str_get_segid(str)) {
253 str++;
254 }
255 (*p)=(unsigned char *)str;
256 (*p)+=4;
257 }
258
259
260 static void
261 street_coord_rewind(void *priv_data)
262 {
263 struct street_priv *street=priv_data;
264
265 street->p=street->next=NULL;
266 street->status=street->status_rewind;
267 }
268
269 static int
270 street_coord_get_helper(struct street_priv *street, struct coord *c)
271 {
272 unsigned char *n;
273 if (street->p+street->bytes*2 >= street->end)
274 return 0;
275 if (street->status >= 4)
276 return 0;
277 n=street->p;
278 if (street_get_coord(&street->p, street->bytes, &street->ref, c)) {
279 if (street->status)
280 street->next=n;
281 street->status+=2;
282 if (street->status == 5)
283 return 0;
284 }
285 return 1;
286 }
287
288 static int
289 street_coord_get(void *priv_data, struct coord *c, int count)
290 {
291 struct street_priv *street=priv_data;
292 int ret=0,i,scount;
293 #ifdef DEBUG_COORD_GET
294 int segid,debug=0;
295 #endif
296
297 if (! street->p && count) {
298 street->p=street->coord_begin;
299 scount=street->str-street->str_start;
300 for (i = 0 ; i < scount ; i++) {
301 street->status=street_str_get_segid(&street->str[i+1]) >= 0 ? 0:1;
302 while (street_coord_get_helper(street, c));
303 street->p=street->next;
304 }
305 street->status_rewind=street->status=street_str_get_segid(&street->str[1]) >= 0 ? 0:1;
306 }
307 #ifdef DEBUG_COORD_GET
308 segid=street_str_get_segid(&street->str[0]);
309 if (segid < 0)
310 segid=-segid;
311 if (segid == 0x15)
312 debug=1;
313 if (debug) {
314 dbg(0,"enter 0x%x\n",segid);
315 }
316 #endif
317 while (count > 0) {
318 if (street_coord_get_helper(street, c)) {
319 #ifdef DEBUG_COORD_GET
320 if (debug) {
321 dbg(0,"0x%x,0x%x\n", c->x, c->y);
322 }
323 #endif
324 c++;
325 ret++;
326 count--;
327 } else {
328 street->more=0;
329 return ret;
330 }
331 }
332 return ret;
333 }
334
335 static void
336 street_attr_rewind(void *priv_data)
337 {
338 /* struct street_priv *street=priv_data; */
339
340 }
341
342 static int
343 street_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
344 {
345 struct street_priv *street=priv_data;
346 int nameid;
347
348 dbg(1,"segid 0x%x\n", street_str_get_segid(street->str));
349 attr->type=attr_type;
350 switch (attr_type) {
351 case attr_any:
352 while (street->attr_next != attr_none) {
353 if (street_attr_get(street, street->attr_next, attr))
354 return 1;
355 }
356 return 0;
357 case attr_label:
358 street->attr_next=attr_street_name;
359 nameid=street_str_get_nameid(street->str);
360 if (! nameid)
361 return 0;
362 if (! street->name.len)
363 street_name_get_by_id(&street->name,street->name_file,nameid);
364 attr->u.str=street->name.name2;
365 if (attr->u.str && attr->u.str[0])
366 return 1;
367 attr->u.str=street->name.name1;
368 if (attr->u.str && attr->u.str[0])
369 return 1;
370 return 0;
371 case attr_street_name:
372 street->attr_next=attr_street_name_systematic;
373 nameid=street_str_get_nameid(street->str);
374 if (! nameid)
375 return 0;
376 if (! street->name.len)
377 street_name_get_by_id(&street->name,street->name_file,nameid);
378 attr->u.str=street->name.name2;
379 return ((attr->u.str && attr->u.str[0]) ? 1:0);
380 case attr_street_name_systematic:
381 street->attr_next=attr_flags;
382 nameid=street_str_get_nameid(street->str);
383 if (! nameid)
384 return 0;
385 if (! street->name.len)
386 street_name_get_by_id(&street->name,street->name_file,nameid);
387 attr->u.str=street->name.name1;
388 return ((attr->u.str && attr->u.str[0]) ? 1:0);
389 case attr_flags:
390 attr->u.num=street->flags;
391 street->attr_next=attr_country_id;
392 return 1;
393 case attr_country_id:
394 street->attr_next=attr_debug;
395 nameid=street_str_get_nameid(street->str);
396 if (! nameid)
397 return 0;
398 if (! street->name.len)
399 street_name_get_by_id(&street->name,street->name_file,nameid);
400 attr->u.num=mg_country_to_isonum(street->name.country);
401 return 1;
402 case attr_debug:
403 street->attr_next=attr_none;
404 {
405 struct street_str *str=street->str;
406 sprintf(street->debug,"order:0x%x\nsegid:0x%x\nlimit:0x%x\nunknown2:0x%x\nunknown3:0x%x\ntype:0x%x\nnameid:0x%x\ntownassoc:0x%x",street_header_get_order(street->header),street_str_get_segid(str),street_str_get_limit(str),street_str_get_unknown2(str),street_str_get_unknown3(str),street_str_get_type(str),street_str_get_nameid(str), street->name.len ? street->name.townassoc : 0);
407 attr->u.str=street->debug;
408 }
409 return 1;
410 default:
411 return 0;
412 }
413 return 1;
414 }
415
416 static struct item_methods street_meth = {
417 street_coord_rewind,
418 street_coord_get,
419 street_attr_rewind,
420 street_attr_get,
421 };
422
423 static void
424 street_get_data(struct street_priv *street, unsigned char **p)
425 {
426 street->header=(struct street_header *)(*p);
427 (*p)+=sizeof(struct street_header);
428 street->type_count=street_header_get_count(street->header);
429 street->type=(struct street_type *)(*p);
430 (*p)+=street->type_count*sizeof(struct street_type);
431 }
432
433
434 static void
435 street_housenumber_coord_rewind(void *priv_data)
436 {
437 struct street_priv *street=priv_data;
438 street->cidx=0;
439 }
440
441 static void
442 street_housenumber_attr_rewind(void *priv_data)
443 {
444 /* struct street_priv *street=priv_data; */
445
446 }
447
448 static int
449 street_housenumber_coord_get(void *priv_data, struct coord *c, int count)
450 {
451 struct street_priv *street=priv_data;
452 if (street->cidx || !count || !street->name.len)
453 return 0;
454 *c=street->hnc[street->housenumber-2];
455 street->cidx=1;
456 return 1;
457 }
458
459 static int
460 street_housenumber_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
461 {
462 struct street_priv *street=priv_data;
463 struct housenumber *hn;
464 attr->type=attr_type;
465 switch (attr_type) {
466 case attr_label:
467 hn=&street->hn[street->housenumber-2];
468 sprintf(street->debug,"%d%s",hn->number,hn->suffix);
469 attr->u.str=street->debug;
470 return 1;
471 default:
472 dbg(0,"unknown item\n");
473 return 0;
474 }
475 }
476
477 static struct item_methods street_housenumber_meth = {
478 street_housenumber_coord_rewind,
479 street_housenumber_coord_get,
480 street_housenumber_attr_rewind,
481 street_housenumber_attr_get,
482 };
483
484 static void
485 project(struct coord *c, int count, int di, int dlr, struct coord *ch)
486 {
487 struct coord cr;
488 int dx,dy;
489 int l;
490
491 if (di > 0) {
492 dx=c[1].x-c[0].x;
493 dy=c[1].y-c[0].y;
494 cr=c[0];
495 } else if (di < 0) {
496 dx=c[count-1].x-c[count-2].x;
497 dy=c[count-1].y-c[count-2].y;
498 cr=c[count-1];
499 } else {
500 dx=c[1].x-c[0].x;
501 dy=c[1].y-c[0].y;
502 di=0;
503 if (count % 2) {
504 cr=c[count/2];
505 } else {
506 cr.x=(c[count/2-1].x+c[count/2].x)/2;
507 cr.y=(c[count/2-1].y+c[count/2].y)/2;
508 }
509 }
510 l=sqrtf(dx*dx+dy*dy);
511 if (!l) {
512 *ch=cr;
513 return;
514 }
515 ch->x=cr.x+(di*dx+dlr*dy)/l;
516 ch->y=cr.y+(di*dy-dlr*dx)/l;
517 }
518
519 static int
520 street_lookup_housenumber(struct street_priv *street)
521 {
522 int i,count,scount,maxcount=16384;
523 struct coord c[maxcount];
524 struct street_name_numbers nns;
525 unsigned char *p=street->name.aux_data;
526 unsigned char *end=p+street->name.aux_len;
527 unsigned char *pn,*pn_end;
528
529 street->hn_count=0;
530 street_coord_rewind(street);
531 scount=street_coord_get(street, c, maxcount/2);
532 if (scount >= maxcount/2) {
533 dbg(0,"overflow");
534 }
535 for (i = 0 ; i < scount-1 ; i++) {
536 c[scount+i].x=(c[i].x+c[i+1].x)/2;
537 c[scount+i].y=(c[i].y+c[i+1].y)/2;
538 }
539 count=scount*2-1;
540 while (p < end) {
541 struct street_name_number nn;
542 street_name_numbers_get(&nns, &p);
543 pn=nns.aux_data;
544 pn_end=nns.aux_data+nns.aux_len;
545 while (pn < pn_end) {
546 street_name_number_get(&nn, &pn);
547 for (i = 0 ; i < count ; i++) {
548 int dx=nn.c->x-c[i].x;
549 int dy=nn.c->y-c[i].y;
550 int dlr,dir;
551 if (dx < 3 && dx > -3 && dy < 3 && dy > -3) {
552 dir=15;
553 dlr=15;
554 switch (nn.tag & 0xf) {
555 case 0xa:
556 break;
557 case 0xb:
558 dlr=-dlr;
559 dir=-dir;
560 break;
561 case 0xe:
562 dlr=-dlr;
563 break;
564 case 0xf:
565 dir=-dir;
566 break;
567 default:
568 dbg(0,"unknown tag 0x%x\n",nn.tag);
569 #if 0
570 continue;
571 #endif
572 }
573 if (street_str_get_type(street->str) & 0x40) {
574 dir=-dir;
575 dlr=-dlr;
576 }
577 if (nn.first.number == nn.last.number && !strcmp(nn.first.suffix, nn.last.suffix))
578 dir=0;
579 project(c, scount, dir, dlr, &street->hnc[street->hn_count]);
580 street->hn[street->hn_count]=nn.first;
581 street->hn_count++;
582 dbg_assert(street->hn_count < 100);
583 project(c, scount, -dir, dlr, &street->hnc[street->hn_count]);
584 street->hn[street->hn_count]=nn.last;
585 street->hn_count++;
586 dbg_assert(street->hn_count < 100);
587 dbg(1,"found %d%s %d%s\n",nn.first.number,nn.first.suffix,nn.last.number,nn.last.suffix);
588 }
589 }
590 }
591 }
592 return 1;
593 }
594
595 static int
596 street_get_housenumber(struct map_rect_priv *mr, struct street_priv *street, struct item *item)
597 {
598 int nameid;
599 nameid=street_str_get_nameid(street->str);
600 if (! nameid)
601 return 0;
602 if (! street->name.len)
603 street_name_get_by_id(&street->name,street->name_file,nameid);
604 if (! street->name.aux_len)
605 return 0;
606 if (!street->hn_count)
607 street_lookup_housenumber(street);
608 if (street->housenumber > street->hn_count)
609 return 0;
610 item->type=type_town_label;
611 item->id_hi = (item->id_hi & 0xffffff) | (street->housenumber*0x10000000+0x1000000);
612 item->meth=&street_housenumber_meth;
613 street->cidx=0;
614 street->housenumber++;
615 return 1;
616 }
617
618 /*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */
619 static unsigned char limit[]={0,0,1,1,1,2,2,4,6,6,12,13,14,20,20,20,20,20,20};
620
621 int
622 street_get(struct map_rect_priv *mr, struct street_priv *street, struct item *item)
623 {
624 int *flags;
625 struct coord_rect r;
626 for (;;) {
627 while (street->more) {
628 struct coord c;
629 street_coord_get(street, &c, 1);
630 }
631 #if 0
632 if (street->housenumber) {
633 if (street_get_housenumber(mr, street, item))
634 return 1;
635 street->housenumber=0;
636 }
637 #endif
638 if (mr->b.p == mr->b.p_start) {
639 street_get_data(street, &mr->b.p);
640 street->name_file=mr->m->file[file_strname_stn];
641 if (mr->cur_sel && street_header_get_order(street->header) > limit[mr->cur_sel->order])
642 return 0;
643 street->end=mr->b.end;
644 block_get_r(mr->b.b, &r);
645 street->ref=r;
646 street->bytes=street_get_bytes(&r);
647 street->str_start=street->str=(struct street_str *)mr->b.p;
648 street->coord_begin=mr->b.p;
649 street_coord_get_begin(&street->coord_begin);
650 street->p=street->coord_begin;
651 street->type--;
652 item->meth=&street_meth;
653 item->priv_data=street;
654 } else {
655 street->str++;
656 street->p=street->next;
657 }
658 if (! street_str_get_segid(street->str))
659 return 0;
660 if (street_str_get_segid(street->str) < 0)
661 street->type++;
662 #if 0
663 dbg_assert(street->p != NULL);
664 #endif
665 street->next=NULL;
666 street->status_rewind=street->status=street_str_get_segid(&street->str[1]) >= 0 ? 0:1;
667 #if 0
668 if (street->type->country != 0x31) {
669 printf("country=0x%x\n", street->type->country);
670 }
671 #endif
672 item->id_hi=street_type_get_country(street->type) | (mr->current_file << 16);
673 item->id_lo=street_str_get_segid(street->str) > 0 ? street_str_get_segid(street->str) : -street_str_get_segid(street->str);
674 switch(street_str_get_type(street->str) & 0x1f) {
675 case 0xf: /* very small street */
676 if (street_str_get_limit(street->str) == 0x33)
677 item->type=type_street_nopass;
678 else
679 item->type=type_street_0;
680 break;
681 case 0xd:
682 item->type=type_ferry;
683 break;
684 case 0xc: /* small street */
685 item->type=type_street_1_city;
686 break;
687 case 0xb:
688 item->type=type_street_2_city;
689 break;
690 case 0xa:
691 if ((street_str_get_limit(street->str) == 0x03 || street_str_get_limit(street->str) == 0x30) && street_header_get_order(street->header) < 4)
692 item->type=type_street_4_city;
693 else
694 item->type=type_street_3_city;
695 break;
696 case 0x9:
697 if (street_header_get_order(street->header) < 5)
698 item->type=type_street_4_city;
699 else if (street_header_get_order(street->header) < 7)
700 item->type=type_street_2_city;
701 else
702 item->type=type_street_1_city;
703 break;
704 case 0x8:
705 item->type=type_street_2_land;
706 break;
707 case 0x7:
708 if ((street_str_get_limit(street->str) == 0x03 || street_str_get_limit(street->str) == 0x30) && street_header_get_order(street->header) < 4)
709 item->type=type_street_4_city;
710 else
711 item->type=type_street_3_land;
712 break;
713 case 0x6:
714 item->type=type_ramp;
715 break;
716 case 0x5:
717 item->type=type_street_4_land;
718 break;
719 case 0x4:
720 item->type=type_street_4_land;
721 break;
722 case 0x3:
723 item->type=type_street_n_lanes;
724 break;
725 case 0x2:
726 item->type=type_highway_city;
727 break;
728 case 0x1:
729 item->type=type_highway_land;
730 break;
731 default:
732 item->type=type_street_unkn;
733 dbg(0,"unknown type 0x%x\n",street_str_get_type(street->str));
734 }
735 flags=item_get_default_flags(item->type);
736 if (flags)
737 street->flags=*flags;
738 else
739 street->flags=0;
740 if (street_str_get_type(street->str) & 0x40) {
741 street->flags|=(street_str_get_limit(street->str) & 0x30) ? AF_ONEWAYREV:0;
742 street->flags|=(street_str_get_limit(street->str) & 0x03) ? AF_ONEWAY:0;
743 } else {
744 street->flags|=(street_str_get_limit(street->str) & 0x30) ? AF_ONEWAY:0;
745 street->flags|=(street_str_get_limit(street->str) & 0x03) ? AF_ONEWAYREV:0;
746 }
747 #if 0
748 coord_debug=(street->str->unknown2 != 0x40 || street->str->unknown3 != 0x40);
749 if (coord_debug) {
750 item->type=type_street_unkn;
751 printf("%d %02x %02x %02x %02x\n", street->str->segid, street->str->type, street->str->limit, street->str->unknown2, street->str->unknown3);
752 }
753 #endif
754 street->p_rewind=street->p;
755 street->name.len=0;
756 street->attr_next=attr_label;
757 street->more=1;
758 street->housenumber=1;
759 street->hn_count=0;
760 if (!map_selection_contains_item(mr->cur_sel, 0, item->type))
761 continue;
762 item->meth=&street_meth;
763 item->priv_data=street;
764 return 1;
765 }
766 }
767
768 int
769 street_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item)
770 {
771 int country=id_hi & 0xffff;
772 int res;
773 struct coord_rect r;
774 dbg(1,"enter(%p,%p,0x%x,0x%x,%p)\n", mr, street, id_hi, id_lo, item);
775 if (! country)
776 return 0;
777 if (! tree_search_hv(mr->m->dirname, "street", (id_lo >> 8) | (country << 24), id_lo & 0xff, &res))
778 return 0;
779 dbg(1,"res=0x%x (blk=0x%x)\n", res, res >> 12);
780 block_get_byindex(mr->m->file[mr->current_file], res >> 12, &mr->b);
781 street_get_data(street, &mr->b.p);
782 street->name_file=mr->m->file[file_strname_stn];
783 street->end=mr->b.end;
784 block_get_r(mr->b.b, &r);
785 street->ref=r;
786 street->bytes=street_get_bytes(&r);
787 street->str_start=street->str=(struct street_str *)mr->b.p;
788 street->coord_begin=mr->b.p;
789 street_coord_get_begin(&street->coord_begin);
790 street->p=street->coord_begin;
791 street->type--;
792 item->meth=&street_meth;
793 item->priv_data=street;
794 street->str+=(res & 0xfff)-1;
795 dbg(1,"segid 0x%x\n", street_str_get_segid(&street->str[1]));
796 return street_get(mr, street, item);
797 #if 0
798 mr->b.p=mr->b.block_start+(res & 0xffff);
799 return town_get(mr, twn, item);
800 #endif
801
802 return 0;
803 }
804
805 struct street_name_index {
806 int block;
807 unsigned short country;
808 int town_assoc;
809 char name[0];
810 } __attribute__((packed));
811
812 static unsigned char
813 latin1_tolower(unsigned char c)
814 {
815 if (c >= 'A' && c <= 'Z')
816 return c - 'A' + 'a';
817 if (c == 0xc4 || c == 0xc9 || c == 0xd6 || c == 0xdc)
818 return c+0x20;
819 return c;
820 }
821
822 static unsigned char
823 latin1_tolower_ascii(unsigned char c)
824 {
825 unsigned char ret=latin1_tolower(c);
826 switch (ret) {
827 case 0xe4:
828 return 'a';
829 case 0xe9:
830 return 'e';
831 case 0xf6:
832 return 'o';
833 case 0xfc:
834 return 'u';
835 default:
836 if (ret >= 0x80)
837 dbg(1,"ret=0x%x\n",c);
838 return ret;
839 }
840 }
841
842 static int
843 strncasecmp_latin1(char *str1, char *str2, int len)
844 {
845 int d;
846 while (len--) {
847 d=latin1_tolower((unsigned char)(*str1))-latin1_tolower((unsigned char)(*str2));
848 if (d)
849 return d;
850 if (! *str1)
851 return 0;
852 str1++;
853 str2++;
854 }
855 return 0;
856 }
857
858 static int
859 strncasecmp_latin1_ascii(char *str1, char *str2, int len)
860 {
861 int d;
862 while (len--) {
863 d=latin1_tolower_ascii((unsigned char)(*str1))-latin1_tolower_ascii((unsigned char)(*str2));
864 if (d)
865 return d;
866 if (! *str1)
867 return 0;
868 str1++;
869 str2++;
870 }
871 return 0;
872 }
873
874 static int
875 street_search_compare_do(struct map_rect_priv *mr, int country, int town_assoc, char *name)
876 {
877 int d,len;
878
879 dbg(1,"enter");
880 dbg(1,"country 0x%x town_assoc 0x%x name '%s'\n", country, town_assoc, name);
881 d=(mr->search_item.id_hi & 0xffff)-country;
882 dbg(1,"country %d (%d vs %d)\n", d, mr->search_item.id_hi & 0xffff, country);
883 if (!d) {
884 if (mr->search_item.id_lo == town_assoc ) {
885 dbg(1,"town_assoc match (0x%x)\n", town_assoc);
886 len=mr->search_partial ? strlen(mr->search_str):INT_MAX;
887 d=strncasecmp_latin1(mr->search_str, name, len);
888 if (!strncasecmp_latin1_ascii(mr->search_str, name, len))
889 d=0;
890 dbg(1,"string %d\n", d);
891 } else {
892 if (town_assoc < mr->search_item.id_lo)
893 d=1;
894 else
895 d=-1;
896 dbg(1,"assoc %d 0x%x-0x%x\n",d, mr->search_item.id_lo, town_assoc);
897 }
898 }
899 dbg(1,"d=%d\n", d);
900 return d;
901 }
902
903 static int
904 street_search_compare(unsigned char **p, struct map_rect_priv *mr)
905 {
906 struct street_name_index *i;
907 int ret;
908
909 dbg(1,"enter\n");
910 i=(struct street_name_index *)(*p);
911 *p+=sizeof(*i)+strlen(i->name)+1;
912
913 dbg(1,"block 0x%x\n", i->block);
914
915 ret=street_search_compare_do(mr, i->country, i->town_assoc, i->name);
916 if (ret <= 0)
917 mr->search_block=i->block;
918 return ret;
919 }
920
921 static void
922 street_name_numbers_coord_rewind(void *priv_data)
923 {
924 /* struct street_priv *street=priv_data; */
925
926 }
927
928 static void
929 street_name_numbers_attr_rewind(void *priv_data)
930 {
931 /* struct street_priv *street=priv_data; */
932
933 }
934
935 static int
936 street_name_numbers_coord_get(void *priv_data, struct coord *c, int count)
937 {
938 return 0;
939 }
940
941 static int
942 street_name_numbers_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
943 {
944 attr->type=attr_type;
945 switch (attr_type) {
946 default:
947 dbg(0,"unknown item\n");
948 return 0;
949 }
950 }
951
952
953
954
955
956 static struct item_methods street_name_numbers_meth = {
957 street_name_numbers_coord_rewind,
958 street_name_numbers_coord_get,
959 street_name_numbers_attr_rewind,
960 street_name_numbers_attr_get,
961 };
962
963
964 static void
965 street_name_coord_rewind(void *priv_data)
966 {
967 /* struct street_priv *street=priv_data; */
968
969 }
970
971 static void
972 street_name_attr_rewind(void *priv_data)
973 {
974 /* struct street_priv *street=priv_data; */
975
976 }
977
978 static int
979 street_name_coord_get(void *priv_data, struct coord *c, int count)
980 {
981 struct map_rect_priv *mr=priv_data;
982 struct street_name_numbers snns;
983 unsigned char *p=mr->street.name.aux_data;
984
985 dbg(1,"aux_data=%p\n", p);
986 if (count) {
987 street_name_numbers_get(&snns, &p);
988 street_name_numbers_get_coord(&snns, c);
989 return 1;
990 }
991
992 return 0;
993 }
994
995 #if 0
996 static void
997 debug(struct map_rect_priv *mr)
998 {
999 int i;
1000 struct street_name_numbers nns;
1001 unsigned char *p=mr->street.name.aux_data;
1002 unsigned char *end=p+mr->street.name.aux_len;
1003 printf("len=0x%x\n", mr->street.name.aux_len);
1004 for (i = 0 ; i < mr->street.name.aux_len ; i++) {
1005 printf("%02x ",mr->street.name.aux_data[i]);
1006 }
1007 printf("\n");
1008 {
1009 while (p < end) {
1010 unsigned char *pn,*pn_end;
1011 struct street_name_number nn;
1012 street_name_numbers_get(&nns, &p);
1013 printf("name_numbers:\n");
1014 printf(" len 0x%x\n", nns.len);
1015 printf(" tag 0x%x\n", nns.tag);
1016 printf(" dist 0x%x\n", nns.dist);
1017 printf(" country 0x%x\n", nns.country);
1018 printf(" coord 0x%x,0x%x\n", nns.c->x, nns.c->y);
1019 printf(" first %d\n", nns.first.number);
1020 printf(" last %d\n", nns.last.number);
1021 printf(" segment count 0x%x\n", nns.segment_count);
1022 printf(" aux_len 0x%x\n", nns.aux_len);
1023 pn=nns.aux_data;
1024 pn_end=nns.aux_data+nns.aux_len;
1025 while (pn < pn_end) {
1026 printf(" number:\n");
1027 street_name_number_get(&nn, &pn);
1028 printf(" len 0x%x\n", nn.len);
1029 printf(" tag 0x%x\n", nn.tag);
1030 printf(" coord 0x%x,0x%x\n", nn.c->x, nn.c->y);
1031 printf(" first %d\n", nn.first.number);
1032 printf(" last %d\n", nn.last.number);
1033 }
1034 }
1035 }
1036 }
1037 #endif
1038
1039 static int
1040 street_name_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1041 {
1042 struct map_rect_priv *mr=priv_data;
1043
1044 attr->type=attr_type;
1045 switch (attr_type) {
1046 case attr_street_name:
1047 attr->u.str=mr->street.name.name2;
1048 return ((attr->u.str && attr->u.str[0]) ? 1:0);
1049 case attr_street_name_systematic:
1050 attr->u.str=mr->street.name.name1;
1051 return ((attr->u.str && attr->u.str[0]) ? 1:0);
1052 case attr_town_name:
1053 case attr_district_name:
1054 case attr_postal:
1055 if (!mr->search_item_tmp)
1056 mr->search_item_tmp=map_rect_get_item_byid_mg(mr->search_mr_tmp, mr->street.name_numbers.country | (file_town_twn << 16), mr->street.name_numbers.dist);
1057 if (!mr->search_item_tmp)
1058 return 0;
1059 return item_attr_get(mr->search_item_tmp, attr_type, attr);
1060 default:
1061 dbg(0,"%p\n",mr->street.name_numbers.dist);
1062 dbg(0,"unknown attr %s\n",attr_to_name(attr_type));
1063 return 0;
1064 }
1065 }
1066
1067
1068
1069
1070
1071 static struct item_methods street_name_meth = {
1072 street_name_coord_rewind,
1073 street_name_coord_get,
1074 street_name_attr_rewind,
1075 street_name_attr_get,
1076 };
1077
1078
1079 int
1080 street_name_get_byid(struct map_rect_priv *mr, struct street_priv *street, int id_hi, int id_lo, struct item *item)
1081 {
1082 mr->current_file=id_hi >> 16;
1083 street->name_file=mr->m->file[mr->current_file];
1084 item->type=type_street_name;
1085 item->id_hi=id_hi;
1086 item->id_lo=id_lo;
1087 item->meth=&street_name_meth;
1088 item->map=NULL;
1089 item->priv_data=mr;
1090 mr->b.p=street->name_file->begin+item->id_lo;
1091 dbg(1,"last %p map %p file %d begin %p\n", mr->b.p, mr->m, mr->current_file, mr->m->file[mr->current_file]->begin);
1092 street_name_get(&street->name, &mr->b.p);
1093 return 1;
1094 }
1095
1096 static struct item *
1097 street_search_get_item_street_name(struct map_rect_priv *mr)
1098 {
1099 int dir=1,leaf;
1100 unsigned char *last;
1101
1102 dbg(1,"enter\n");
1103 if (! mr->search_blk_count) {
1104 dbg(1,"partial 0x%x '%s' ***\n", mr->town.street_assoc, mr->search_str);
1105 if (mr->search_linear)
1106 return NULL;
1107 dbg(1,"tree_search_next\n");
1108 mr->search_block=-1;
1109 while ((leaf=tree_search_next(&mr->ts, &mr->search_p, dir)) != -1) {
1110 dir=street_search_compare(&mr->search_p, mr);
1111 }
1112 dbg(1,"dir=%d mr->search_block=0x%x\n", dir, mr->search_block);
1113 if (mr->search_block == -1)
1114 return NULL;
1115 mr->search_blk_count=1;
1116 block_get_byindex(mr->m->file[file_strname_stn], mr->search_block, &mr->b);
1117 mr->b.p=mr->b.block_start+12;
1118 }
1119 dbg(1,"name id 0x%x\n", mr->b.p-mr->m->file[file_strname_stn]->begin);
1120 if (! mr->search_blk_count)
1121 return NULL;
1122 for (;;) {
1123 if (mr->b.p >= mr->b.end) {
1124 if (!block_next_lin(mr)) {
1125 dbg(1,"end of blocks in %p, %p\n", mr->m->file[file_strname_stn]->begin, mr->m->file[file_strname_stn]->end);
1126 return NULL;
1127 }
1128 mr->b.p=mr->b.block_start+12;
1129 }
1130 while (mr->b.p < mr->b.end) {
1131 last=mr->b.p;
1132 street_name_get(&mr->street.name, &mr->b.p);
1133 dir=street_search_compare_do(mr, mr->street.name.country, mr->street.name.townassoc, mr->street.name.name2);
1134 dbg(1,"country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir);
1135 if (dir < 0) {
1136 dbg(1,"end of data\n");
1137 mr->search_blk_count=0;
1138 return NULL;
1139 }
1140 if (!dir) {
1141 dbg(1,"result country 0x%x assoc 0x%x name1 '%s' name2 '%s' dir=%d aux_data=%p len=0x%x\n", mr->street.name.country, mr->street.name.townassoc, mr->street.name.name1, mr->street.name.name2, dir, mr->street.name.aux_data, mr->street.name.aux_len);
1142 mr->item.type = type_street_name;
1143 mr->item.id_hi=(file_strname_stn << 16);
1144 mr->item.id_lo=last-mr->m->file[file_strname_stn]->begin;
1145 dbg(1,"id 0x%x 0x%x last %p map %p file %d begin %p\n", mr->item.id_hi, mr->item.id_lo, last, mr->m, mr->current_file, mr->m->file[mr->current_file]->begin);
1146 mr->item.meth=&street_name_meth;
1147 mr->item.map=NULL;
1148 mr->item.priv_data=mr;
1149 /* debug(mr); */
1150 dbg(1,"last %p\n",last);
1151 return &mr->item;
1152 }
1153 }
1154 }
1155 }
1156
1157 static void
1158 district_debug(struct map_rect_priv *mr, int country, int dist)
1159 {
1160 struct map_rect_priv *mrt;
1161 struct item *item;
1162 struct attr attrn;
1163
1164 mrt=map_rect_new_mg(mr->m, NULL);
1165 item=map_rect_get_item_byid_mg(mrt, country | (file_town_twn << 16), dist);
1166 dbg(0,"item=%p\n",item);
1167 if (item_attr_get(item, attr_town_postal, &attrn))
1168 dbg(0,"postal=%s\n",attrn.u.str);
1169 if (item_attr_get(item, attr_town_name, &attrn))
1170 dbg(0,"town_name=%s\n",attrn.u.str);
1171 if (item_attr_get(item, attr_district_name, &attrn))
1172 dbg(0,"district_name=%s\n",attrn.u.str);
1173 map_rect_destroy_mg(mrt);
1174 }
1175
1176 static int
1177 street_name_numbers_get_next(struct map_rect_priv *mr, struct street_name *name, char *start, unsigned char **p, int mode, int *id, struct street_name_numbers *ret)
1178 {
1179 struct street_name_numbers tmp;
1180 unsigned char *ps,*pt;
1181 int found;
1182 while (*p < name->aux_data+name->aux_len) {
1183 ps=*p;
1184 street_name_numbers_get(ret, p);
1185 (*id)++;
1186 found=0;
1187 pt=name->aux_data;
1188 while (pt < ps) {
1189 street_name_numbers_get(&tmp, &pt);
1190 if (tmp.country == ret->country && tmp.dist == ret->dist) {
1191 found=1;
1192 break;
1193 }
1194 }
1195 if (!found) {
1196 dbg(0,"district 0x%x\n",ret->dist);
1197 district_debug(mr, ret->country, ret->dist);
1198 return 1;
1199 }
1200 }
1201 return 0;
1202 }
1203
1204
1205 static struct item *
1206 street_search_get_item_street_name_district(struct map_rect_priv *mr, int flag)
1207 {
1208 if (street_name_eod(&mr->street.name))
1209 return NULL;
1210 if (!street_name_numbers_get_next(mr, &mr->street.name, NULL, &mr->street.name.tmp_data, 1, &mr->item.id_hi, &mr->street.name_numbers))
1211 return NULL;
1212 return &mr->item;
1213 }
1214
1215 struct item *
1216 street_search_get_item(struct map_rect_priv *mr)
1217 {
1218 struct item *item;
1219 for (;;) {
1220 if (!mr->street.name.tmp_data || street_name_eod(&mr->street.name)) {
1221 item=street_search_get_item_street_name(mr);
1222 if (!item)
1223 return NULL;
1224 if (!mr->street.name.aux_len)
1225 return item;
1226 }
1227 mr->item.id_hi++;
1228 street_name_numbers_get(&mr->street.name_numbers, &mr->street.name.tmp_data);
1229 mr->search_item_tmp=NULL;
1230 return &mr->item;
1231 }
1232 }
1233
1234 static int
1235 street_name_numbers_next(struct map_rect_priv *mr)
1236 {
1237 if (street_name_eod(&mr->street.name))
1238 return 0;
1239 dbg(1,"%p vs %p\n",mr->street.name.tmp_data, mr->street.name.aux_data);
1240 street_name_numbers_get(&mr->street.name_numbers, &mr->street.name.tmp_data);
1241 return 1;
1242 }
1243
1244 static int
1245 street_name_number_next(struct map_rect_priv *mr)
1246 {
1247 if (street_name_numbers_eod(&mr->street.name_numbers))
1248 return 0;
1249 street_name_number_get(&mr->street.name_number, &mr->street.name_numbers.tmp_data);
1250 sprintf(mr->street.first_number,"%d%s",mr->street.name_number.first.number,mr->street.name_number.first.suffix);
1251 sprintf(mr->street.last_number,"%d%s",mr->street.name_number.last.number,mr->street.name_number.last.suffix);
1252 mr->street.current_number[0]='\0';
1253 return 1;
1254 }
1255
1256 static void
1257 housenumber_coord_rewind(void *priv_data)
1258 {
1259 /* struct street_priv *street=priv_data; */
1260
1261 }
1262
1263 static void
1264 housenumber_attr_rewind(void *priv_data)
1265 {
1266 /* struct street_priv *street=priv_data; */
1267
1268 }
1269
1270 static int
1271 housenumber_coord_get(void *priv_data, struct coord *c, int count)
1272 {
1273 return 0;
1274 }
1275
1276 static int
1277 housenumber_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1278 {
1279 struct map_rect_priv *mr=priv_data;
1280 attr->type=attr_type;
1281 switch (attr_type) {
1282 case attr_house_number:
1283 attr->u.str=mr->street.current_number;
1284 return 1;
1285 case attr_town_name:
1286 case attr_district_name:
1287 case attr_postal:
1288 if (!mr->search_item_tmp)
1289 mr->search_item_tmp=map_rect_get_item_byid_mg(mr->search_mr_tmp, mr->street.name_numbers.country | (file_town_twn << 16), mr->street.name_numbers.dist);
1290 if (!mr->search_item_tmp)
1291 return 0;
1292 return item_attr_get(mr->search_item_tmp, attr_type, attr);
1293 default:
1294 dbg(0,"unknown attr %s\n",attr_to_name(attr_type));
1295 return 0;
1296 }
1297 }
1298
1299
1300 static struct item_methods housenumber_meth = {
1301 housenumber_coord_rewind,
1302 housenumber_coord_get,
1303 housenumber_attr_rewind,
1304 housenumber_attr_get,
1305 };
1306
1307 int
1308 housenumber_search_setup(struct map_rect_priv *mr)
1309 {
1310 dbg(1,"enter (0x%x,0x%x)\n",mr->search_item.id_hi,mr->search_item.id_lo);
1311 int id=mr->search_item.id_hi & 0xff;
1312 mr->current_file=file_strname_stn;
1313 mr->street.name_file=mr->m->file[mr->current_file];
1314 mr->b.p=mr->street.name_file->begin+mr->search_item.id_lo;
1315 mr->search_str=g_strdup(mr->search_attr->u.str);
1316 dbg(1,"last %p\n",mr->b.p);
1317 street_name_get(&mr->street.name, &mr->b.p);
1318 #if 0
1319 debug(mr);
1320 #endif
1321 while (id > 0) {
1322 id--;
1323 dbg(1,"loop\n");
1324 if (!street_name_numbers_next(mr))
1325 return 0;
1326 }
1327 mr->item.type=type_house_number;
1328 mr->item.priv_data=mr;
1329 mr->item.id_hi=mr->search_item.id_hi + 0x100;
1330 mr->item.meth=&housenumber_meth;
1331 if (!id)
1332 mr->item.id_hi+=1;
1333 mr->item.id_lo=mr->search_item.id_lo;
1334 dbg(1,"getting name_number %p vs %p + %d\n",mr->street.name_numbers.tmp_data,mr->street.name_numbers.aux_data, mr->street.name_numbers.aux_len);
1335 if (!street_name_number_next(mr))
1336 return 0;
1337 dbg(1,"enter\n");
1338 // debug(mr);
1339 return 1;
1340 }
1341
1342 static int
1343 house_number_next(char *number, char *first, char *last, int interpolation, int *percentage)
1344 {
1345 int firstn=atoi(first);
1346 int lastn=atoi(last);
1347 int current,delta,len=lastn-firstn;
1348 if (interpolation) {
1349 len/=2;
1350 }
1351 if (!number[0]) {
1352 strcpy(number,first);
1353 delta=0;
1354 } else {
1355 current=atoi(number)+(interpolation ? 2:1);
1356 if (current > lastn)
1357 return 0;
1358 sprintf(number,"%d",current);
1359 delta=current-firstn;
1360 }
1361 if (percentage) {
1362 if (len)
1363 *percentage=delta*100/len;
1364 else
1365 *percentage=50;
1366 }
1367 return 1;
1368 }
1369
1370 struct item *
1371 housenumber_search_get_item(struct map_rect_priv *mr)
1372 {
1373 int d;
1374 dbg(1,"enter %s %s\n",mr->street.first_number,mr->street.last_number);
1375 for (;;) {
1376 if (!house_number_next(mr->street.current_number, mr->street.first_number, mr->street.last_number, 0, NULL)) {
1377 if (!street_name_number_next(mr))
1378 return NULL;
1379 continue;
1380 }
1381 if (mr->search_partial)
1382 d=strncasecmp(mr->search_str, mr->street.current_number, strlen(mr->search_str));
1383 else
1384 d=strcasecmp(mr->search_str, mr->street.current_number);
1385 if (!d) {
1386 mr->search_item_tmp=NULL;
1387 return &mr->item;
1388 }
1389 }
1390 }

   
Visit the ZANavi Wiki