Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/osmparser.c
Parent Directory
|
Revision Log
Revision 1339 -
(show annotations)
(download)
(as text)
Thu May 23 17:47:16 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 37686 byte(s)
Thu May 23 17:47:16 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 37686 byte(s)
Don't create segments when parsing input file but create the segments later using the nodes stored in the ways file. This makes applying changes simpler (segments file is not kept with the --keep option) and handling changed ways is simpler than changed segments.
1 | /*************************************** |
2 | OSM file parser (either JOSM or planet) |
3 | |
4 | Part of the Routino routing software. |
5 | ******************/ /****************** |
6 | This file Copyright 2008-2013 Andrew M. Bishop |
7 | |
8 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by |
10 | the Free Software Foundation, either version 3 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | ***************************************/ |
21 | |
22 | |
23 | #include <stdlib.h> |
24 | #include <string.h> |
25 | #include <stdint.h> |
26 | #include <ctype.h> |
27 | |
28 | #include "types.h" |
29 | #include "typesx.h" |
30 | |
31 | #include "nodesx.h" |
32 | #include "waysx.h" |
33 | #include "relationsx.h" |
34 | |
35 | #include "osmparser.h" |
36 | #include "tagging.h" |
37 | #include "logging.h" |
38 | |
39 | |
40 | /* Macros */ |
41 | |
42 | /*+ Checks if a value in the XML is one of the allowed values for true. +*/ |
43 | #define ISTRUE(xx) (!strcmp(xx,"true") || !strcmp(xx,"yes") || !strcmp(xx,"1")) |
44 | |
45 | /*+ Checks if a value in the XML is one of the allowed values for false. +*/ |
46 | #define ISFALSE(xx) (!strcmp(xx,"false") || !strcmp(xx,"no") || !strcmp(xx,"0")) |
47 | |
48 | /* Local variables */ |
49 | |
50 | static NodesX *nodes; |
51 | static WaysX *ways; |
52 | static RelationsX *relations; |
53 | |
54 | static node_t *way_nodes=NULL; |
55 | static int way_nnodes=0; |
56 | |
57 | static node_t *relation_nodes=NULL; |
58 | static int relation_nnodes=0; |
59 | static way_t *relation_ways=NULL; |
60 | static int relation_nways=0; |
61 | static relation_t *relation_relations=NULL; |
62 | static int relation_nrelations=0; |
63 | static way_t relation_from=NO_WAY_ID; |
64 | static way_t relation_to=NO_WAY_ID; |
65 | static node_t relation_via=NO_NODE_ID; |
66 | |
67 | /* Local functions */ |
68 | |
69 | static double parse_speed(way_t id,const char *k,const char *v); |
70 | static double parse_weight(way_t id,const char *k,const char *v); |
71 | static double parse_length(way_t id,const char *k,const char *v); |
72 | |
73 | |
74 | /*++++++++++++++++++++++++++++++++++++++ |
75 | Parse an OSM XML file (from JOSM or planet download). |
76 | |
77 | int ParseOSMFile Returns 0 if OK or something else in case of an error. |
78 | |
79 | int fd The file descriptor of the file to read from. |
80 | |
81 | NodesX *OSMNodes The data structure of nodes to fill in. |
82 | |
83 | WaysX *OSMWays The data structure of ways to fill in. |
84 | |
85 | RelationsX *OSMRelations The data structure of relations to fill in. |
86 | ++++++++++++++++++++++++++++++++++++++*/ |
87 | |
88 | int ParseOSMFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
89 | { |
90 | int retval; |
91 | |
92 | /* Copy the function parameters and initialise the variables */ |
93 | |
94 | nodes=OSMNodes; |
95 | ways=OSMWays; |
96 | relations=OSMRelations; |
97 | |
98 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
99 | |
100 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
101 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); |
102 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); |
103 | |
104 | /* Parse the file */ |
105 | |
106 | retval=ParseXML(fd,xml_osm_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE); |
107 | |
108 | /* Free the variables */ |
109 | |
110 | free(way_nodes); |
111 | |
112 | free(relation_nodes); |
113 | free(relation_ways); |
114 | free(relation_relations); |
115 | |
116 | return(retval); |
117 | } |
118 | |
119 | |
120 | /*++++++++++++++++++++++++++++++++++++++ |
121 | Parse an OSC XML file (from planet download). |
122 | |
123 | int ParseOSCFile Returns 0 if OK or something else in case of an error. |
124 | |
125 | int fd The file descriptor of the file to read from. |
126 | |
127 | NodesX *OSMNodes The data structure of nodes to fill in. |
128 | |
129 | WaysX *OSMWays The data structure of ways to fill in. |
130 | |
131 | RelationsX *OSMRelations The data structure of relations to fill in. |
132 | ++++++++++++++++++++++++++++++++++++++*/ |
133 | |
134 | int ParseOSCFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
135 | { |
136 | int retval; |
137 | |
138 | /* Copy the function parameters and initialise the variables */ |
139 | |
140 | nodes=OSMNodes; |
141 | ways=OSMWays; |
142 | relations=OSMRelations; |
143 | |
144 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
145 | |
146 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
147 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); |
148 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); |
149 | |
150 | /* Parse the file */ |
151 | |
152 | retval=ParseXML(fd,xml_osc_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE); |
153 | |
154 | /* Free the variables */ |
155 | |
156 | free(way_nodes); |
157 | |
158 | free(relation_nodes); |
159 | free(relation_ways); |
160 | free(relation_relations); |
161 | |
162 | return(retval); |
163 | } |
164 | |
165 | |
166 | /*++++++++++++++++++++++++++++++++++++++ |
167 | Parse a PBF format OSM file (from planet download). |
168 | |
169 | int ParsePBFFile Returns 0 if OK or something else in case of an error. |
170 | |
171 | int fd The file descriptor of the file to read from. |
172 | |
173 | NodesX *OSMNodes The data structure of nodes to fill in. |
174 | |
175 | WaysX *OSMWays The data structure of ways to fill in. |
176 | |
177 | RelationsX *OSMRelations The data structure of relations to fill in. |
178 | ++++++++++++++++++++++++++++++++++++++*/ |
179 | |
180 | int ParsePBFFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
181 | { |
182 | int retval; |
183 | |
184 | /* Copy the function parameters and initialise the variables */ |
185 | |
186 | nodes=OSMNodes; |
187 | ways=OSMWays; |
188 | relations=OSMRelations; |
189 | |
190 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
191 | |
192 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
193 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); |
194 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); |
195 | |
196 | /* Parse the file */ |
197 | |
198 | retval=ParsePBF(fd); |
199 | |
200 | /* Free the variables */ |
201 | |
202 | free(way_nodes); |
203 | |
204 | free(relation_nodes); |
205 | free(relation_ways); |
206 | free(relation_relations); |
207 | |
208 | return(retval); |
209 | } |
210 | |
211 | |
212 | /*++++++++++++++++++++++++++++++++++++++ |
213 | Parse an O5M format OSM file (from planet download). |
214 | |
215 | int ParseO5MFile Returns 0 if OK or something else in case of an error. |
216 | |
217 | int fd The file descriptor of the file to read from. |
218 | |
219 | NodesX *OSMNodes The data structure of nodes to fill in. |
220 | |
221 | WaysX *OSMWays The data structure of ways to fill in. |
222 | |
223 | RelationsX *OSMRelations The data structure of relations to fill in. |
224 | ++++++++++++++++++++++++++++++++++++++*/ |
225 | |
226 | int ParseO5MFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
227 | { |
228 | int retval; |
229 | |
230 | /* Copy the function parameters and initialise the variables */ |
231 | |
232 | nodes=OSMNodes; |
233 | ways=OSMWays; |
234 | relations=OSMRelations; |
235 | |
236 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
237 | |
238 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
239 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); |
240 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); |
241 | |
242 | /* Parse the file */ |
243 | |
244 | retval=ParseO5M(fd,0); |
245 | |
246 | /* Free the variables */ |
247 | |
248 | free(way_nodes); |
249 | |
250 | free(relation_nodes); |
251 | free(relation_ways); |
252 | free(relation_relations); |
253 | |
254 | return(retval); |
255 | } |
256 | |
257 | |
258 | /*++++++++++++++++++++++++++++++++++++++ |
259 | Parse an O5C format OSM file (from planet download). |
260 | |
261 | int ParseO5CFile Returns 0 if OK or something else in case of an error. |
262 | |
263 | int fd The file descriptor of the file to read from. |
264 | |
265 | NodesX *OSMNodes The data structure of nodes to fill in. |
266 | |
267 | WaysX *OSMWays The data structure of ways to fill in. |
268 | |
269 | RelationsX *OSMRelations The data structure of relations to fill in. |
270 | ++++++++++++++++++++++++++++++++++++++*/ |
271 | |
272 | int ParseO5CFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
273 | { |
274 | int retval; |
275 | |
276 | /* Copy the function parameters and initialise the variables */ |
277 | |
278 | nodes=OSMNodes; |
279 | ways=OSMWays; |
280 | relations=OSMRelations; |
281 | |
282 | way_nodes=(node_t*)malloc(256*sizeof(node_t)); |
283 | |
284 | relation_nodes =(node_t *)malloc(256*sizeof(node_t)); |
285 | relation_ways =(way_t *)malloc(256*sizeof(way_t)); |
286 | relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); |
287 | |
288 | /* Parse the file */ |
289 | |
290 | retval=ParseO5M(fd,1); |
291 | |
292 | /* Free the variables */ |
293 | |
294 | free(way_nodes); |
295 | |
296 | free(relation_nodes); |
297 | free(relation_ways); |
298 | free(relation_relations); |
299 | |
300 | return(retval); |
301 | } |
302 | |
303 | |
304 | /*++++++++++++++++++++++++++++++++++++++ |
305 | Add node references to a way. |
306 | |
307 | int64_t node_id The node ID to add or zero to clear the list. |
308 | ++++++++++++++++++++++++++++++++++++++*/ |
309 | |
310 | void AddWayRefs(int64_t node_id) |
311 | { |
312 | if(node_id==0) |
313 | way_nnodes=0; |
314 | else |
315 | { |
316 | node_t id; |
317 | |
318 | if(way_nnodes && (way_nnodes%256)==0) |
319 | way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t)); |
320 | |
321 | id=(node_t)node_id; |
322 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ |
323 | |
324 | way_nodes[way_nnodes++]=id; |
325 | } |
326 | } |
327 | |
328 | |
329 | /*++++++++++++++++++++++++++++++++++++++ |
330 | Add node, way or relation references to a relation. |
331 | |
332 | int64_t node_id The node ID to add or zero if it is not a node. |
333 | |
334 | int64_t way_id The way ID to add or zero if it is not a way. |
335 | |
336 | int64_t relation_id The relation ID to add or zero if it is not a relation. |
337 | |
338 | const char *role The role played by this referenced item or NULL. |
339 | |
340 | If all of node_id, way_id and relation_id are zero then the list is cleared. |
341 | ++++++++++++++++++++++++++++++++++++++*/ |
342 | |
343 | void AddRelationRefs(int64_t node_id,int64_t way_id,int64_t relation_id,const char *role) |
344 | { |
345 | if(node_id==0 && way_id==0 && relation_id==0) |
346 | { |
347 | relation_nnodes=0; |
348 | relation_nways=0; |
349 | relation_nrelations=0; |
350 | |
351 | relation_from=NO_WAY_ID; |
352 | relation_via=NO_NODE_ID; |
353 | relation_to=NO_WAY_ID; |
354 | } |
355 | else if(node_id!=0) |
356 | { |
357 | node_t id; |
358 | |
359 | id=(node_t)node_id; |
360 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ |
361 | |
362 | if(relation_nnodes && (relation_nnodes%256)==0) |
363 | relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t)); |
364 | |
365 | relation_nodes[relation_nnodes++]=id; |
366 | |
367 | if(role) |
368 | { |
369 | if(!strcmp(role,"via")) |
370 | relation_via=id; |
371 | } |
372 | } |
373 | else if(way_id!=0) |
374 | { |
375 | way_t id; |
376 | |
377 | id=(way_t)way_id; |
378 | logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ |
379 | |
380 | if(relation_nways && (relation_nways%256)==0) |
381 | relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t)); |
382 | |
383 | relation_ways[relation_nways++]=id; |
384 | |
385 | if(role) |
386 | { |
387 | if(!strcmp(role,"from")) |
388 | relation_from=id; |
389 | else if(!strcmp(role,"to")) |
390 | relation_to=id; |
391 | } |
392 | } |
393 | else /* if(relation_id!=0) */ |
394 | { |
395 | relation_t id; |
396 | |
397 | id=(relation_t)relation_id; |
398 | logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ |
399 | |
400 | if(relation_nrelations && (relation_nrelations%256)==0) |
401 | relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t)); |
402 | |
403 | relation_relations[relation_nrelations++]=relation_id; |
404 | } |
405 | } |
406 | |
407 | |
408 | /*++++++++++++++++++++++++++++++++++++++ |
409 | Process the tags associated with a node. |
410 | |
411 | TagList *tags The list of node tags. |
412 | |
413 | int64_t node_id The id of the node. |
414 | |
415 | double latitude The latitude of the node. |
416 | |
417 | double longitude The longitude of the node. |
418 | |
419 | int mode The mode of operation to take (create, modify, delete). |
420 | ++++++++++++++++++++++++++++++++++++++*/ |
421 | |
422 | void ProcessNodeTags(TagList *tags,int64_t node_id,double latitude,double longitude,int mode) |
423 | { |
424 | transports_t allow=Transports_ALL; |
425 | nodeflags_t flags=0; |
426 | node_t id; |
427 | int i; |
428 | |
429 | /* Convert id */ |
430 | |
431 | id=(node_t)node_id; |
432 | logassert((int64_t)id==node_id,"Node ID too large (change node_t to 64-bits?)"); /* check node id can be stored in node_t data type. */ |
433 | |
434 | /* Delete */ |
435 | |
436 | if(mode==MODE_DELETE) |
437 | { |
438 | AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,NODE_DELETED); |
439 | |
440 | return; |
441 | } |
442 | |
443 | /* Parse the tags */ |
444 | |
445 | for(i=0;i<tags->ntags;i++) |
446 | { |
447 | int recognised=0; |
448 | char *k=tags->k[i]; |
449 | char *v=tags->v[i]; |
450 | |
451 | switch(*k) |
452 | { |
453 | case 'b': |
454 | if(!strcmp(k,"bicycle")) |
455 | { |
456 | if(ISFALSE(v)) |
457 | allow&=~Transports_Bicycle; |
458 | else if(!ISTRUE(v)) |
459 | logerror("Node %"Pnode_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
460 | recognised=1; break; |
461 | } |
462 | |
463 | break; |
464 | |
465 | case 'f': |
466 | if(!strcmp(k,"foot")) |
467 | { |
468 | if(ISFALSE(v)) |
469 | allow&=~Transports_Foot; |
470 | else if(!ISTRUE(v)) |
471 | logerror("Node %"Pnode_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
472 | recognised=1; break; |
473 | } |
474 | |
475 | break; |
476 | |
477 | case 'g': |
478 | if(!strcmp(k,"goods")) |
479 | { |
480 | if(ISFALSE(v)) |
481 | allow&=~Transports_Goods; |
482 | else if(!ISTRUE(v)) |
483 | logerror("Node %"Pnode_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
484 | recognised=1; break; |
485 | } |
486 | |
487 | break; |
488 | |
489 | case 'h': |
490 | if(!strcmp(k,"horse")) |
491 | { |
492 | if(ISFALSE(v)) |
493 | allow&=~Transports_Horse; |
494 | else if(!ISTRUE(v)) |
495 | logerror("Node %"Pnode_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
496 | recognised=1; break; |
497 | } |
498 | |
499 | if(!strcmp(k,"hgv")) |
500 | { |
501 | if(ISFALSE(v)) |
502 | allow&=~Transports_HGV; |
503 | else if(!ISTRUE(v)) |
504 | logerror("Node %"Pnode_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
505 | recognised=1; break; |
506 | } |
507 | |
508 | break; |
509 | |
510 | case 'm': |
511 | if(!strcmp(k,"moped")) |
512 | { |
513 | if(ISFALSE(v)) |
514 | allow&=~Transports_Moped; |
515 | else if(!ISTRUE(v)) |
516 | logerror("Node %"Pnode_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
517 | recognised=1; break; |
518 | } |
519 | |
520 | if(!strcmp(k,"motorcycle")) |
521 | { |
522 | if(ISFALSE(v)) |
523 | allow&=~Transports_Motorcycle; |
524 | else if(!ISTRUE(v)) |
525 | logerror("Node %"Pnode_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
526 | recognised=1; break; |
527 | } |
528 | |
529 | if(!strcmp(k,"motorcar")) |
530 | { |
531 | if(ISFALSE(v)) |
532 | allow&=~Transports_Motorcar; |
533 | else if(!ISTRUE(v)) |
534 | logerror("Node %"Pnode_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
535 | recognised=1; break; |
536 | } |
537 | |
538 | break; |
539 | |
540 | case 'p': |
541 | if(!strcmp(k,"psv")) |
542 | { |
543 | if(ISFALSE(v)) |
544 | allow&=~Transports_PSV; |
545 | else if(!ISTRUE(v)) |
546 | logerror("Node %"Pnode_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
547 | recognised=1; break; |
548 | } |
549 | |
550 | break; |
551 | |
552 | case 'r': |
553 | if(!strcmp(k,"roundabout")) |
554 | { |
555 | if(ISTRUE(v)) |
556 | flags|=NODE_MINIRNDBT; |
557 | else |
558 | logerror("Node %"Pnode_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",id,v); |
559 | recognised=1; break; |
560 | } |
561 | |
562 | break; |
563 | |
564 | case 'w': |
565 | if(!strcmp(k,"wheelchair")) |
566 | { |
567 | if(ISFALSE(v)) |
568 | allow&=~Transports_Wheelchair; |
569 | else if(!ISTRUE(v)) |
570 | logerror("Node %"Pnode_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'yes'.\n",logerror_node(id),v); |
571 | recognised=1; break; |
572 | } |
573 | |
574 | break; |
575 | |
576 | default: |
577 | break; |
578 | } |
579 | |
580 | if(!recognised) |
581 | logerror("Node %"Pnode_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_node(id),k,v); |
582 | } |
583 | |
584 | /* Create the node */ |
585 | |
586 | AppendNodeList(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow,flags); |
587 | } |
588 | |
589 | |
590 | /*++++++++++++++++++++++++++++++++++++++ |
591 | Process the tags associated with a way. |
592 | |
593 | TagList *tags The list of way tags. |
594 | |
595 | int64_t way_id The id of the way. |
596 | |
597 | int mode The mode of operation to take (create, modify, delete). |
598 | ++++++++++++++++++++++++++++++++++++++*/ |
599 | |
600 | void ProcessWayTags(TagList *tags,int64_t way_id,int mode) |
601 | { |
602 | Way way={0}; |
603 | int oneway=0,area=0; |
604 | int roundabout=0,lanes=0; |
605 | char *name=NULL,*ref=NULL,*refname=NULL; |
606 | way_t id; |
607 | int i,j; |
608 | |
609 | /* Convert id */ |
610 | |
611 | id=(way_t)way_id; |
612 | logassert((int64_t)id==way_id,"Way ID too large (change way_t to 64-bits?)"); /* check way id can be stored in way_t data type. */ |
613 | |
614 | /* Delete */ |
615 | |
616 | if(mode==MODE_DELETE || mode==MODE_MODIFY) |
617 | { |
618 | way.type=WAY_DELETED; |
619 | |
620 | AppendWayList(ways,id,&way,way_nodes,way_nnodes,""); |
621 | } |
622 | |
623 | if(mode==MODE_DELETE) |
624 | return; |
625 | |
626 | /* Sanity check */ |
627 | |
628 | if(way_nnodes==0) |
629 | { |
630 | logerror("Way %"Pway_t" has no nodes.\n",logerror_way(id)); |
631 | return; |
632 | } |
633 | |
634 | if(way_nnodes==1) |
635 | { |
636 | logerror_node(way_nodes[0]); /* Extra logerror information since way isn't stored */ |
637 | logerror("Way %"Pway_t" has only one node.\n",logerror_way(id)); |
638 | return; |
639 | } |
640 | |
641 | /* Parse the tags - just look for highway */ |
642 | |
643 | for(i=0;i<tags->ntags;i++) |
644 | { |
645 | char *k=tags->k[i]; |
646 | char *v=tags->v[i]; |
647 | |
648 | if(!strcmp(k,"highway")) |
649 | { |
650 | way.type=HighwayType(v); |
651 | |
652 | if(way.type==Highway_None) |
653 | logerror("Way %"Pway_t" has an unrecognised highway type '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); |
654 | |
655 | break; |
656 | } |
657 | } |
658 | |
659 | /* Don't continue if this is not a highway (bypass error logging) */ |
660 | |
661 | if(way.type==Highway_None) |
662 | return; |
663 | |
664 | /* Parse the tags - look for the others */ |
665 | |
666 | for(i=0;i<tags->ntags;i++) |
667 | { |
668 | int recognised=0; |
669 | char *k=tags->k[i]; |
670 | char *v=tags->v[i]; |
671 | |
672 | switch(*k) |
673 | { |
674 | case 'a': |
675 | if(!strcmp(k,"area")) |
676 | { |
677 | if(ISTRUE(v)) |
678 | area=1; |
679 | else if(!ISFALSE(v)) |
680 | logerror("Way %"Pway_t" has an unrecognised tag 'area' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
681 | recognised=1; break; |
682 | } |
683 | |
684 | break; |
685 | |
686 | case 'b': |
687 | if(!strcmp(k,"bicycle")) |
688 | { |
689 | if(ISTRUE(v)) |
690 | way.allow|=Transports_Bicycle; |
691 | else if(!ISFALSE(v)) |
692 | logerror("Way %"Pway_t" has an unrecognised tag 'bicycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
693 | recognised=1; break; |
694 | } |
695 | |
696 | if(!strcmp(k,"bicycleroute")) |
697 | { |
698 | if(ISTRUE(v)) |
699 | way.props|=Properties_BicycleRoute; |
700 | else if(!ISFALSE(v)) |
701 | logerror("Way %"Pway_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
702 | recognised=1; break; |
703 | } |
704 | |
705 | if(!strcmp(k,"bridge")) |
706 | { |
707 | if(ISTRUE(v)) |
708 | way.props|=Properties_Bridge; |
709 | else if(!ISFALSE(v)) |
710 | logerror("Way %"Pway_t" has an unrecognised tag 'bridge' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
711 | recognised=1; break; |
712 | } |
713 | |
714 | break; |
715 | |
716 | case 'f': |
717 | if(!strcmp(k,"foot")) |
718 | { |
719 | if(ISTRUE(v)) |
720 | way.allow|=Transports_Foot; |
721 | else if(!ISFALSE(v)) |
722 | logerror("Way %"Pway_t" has an unrecognised tag 'foot' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
723 | recognised=1; break; |
724 | } |
725 | |
726 | if(!strcmp(k,"footroute")) |
727 | { |
728 | if(ISTRUE(v)) |
729 | way.props|=Properties_FootRoute; |
730 | else if(!ISFALSE(v)) |
731 | logerror("Way %"Pway_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
732 | recognised=1; break; |
733 | } |
734 | |
735 | break; |
736 | |
737 | case 'g': |
738 | if(!strcmp(k,"goods")) |
739 | { |
740 | if(ISTRUE(v)) |
741 | way.allow|=Transports_Goods; |
742 | else if(!ISFALSE(v)) |
743 | logerror("Way %"Pway_t" has an unrecognised tag 'goods' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
744 | recognised=1; break; |
745 | } |
746 | |
747 | break; |
748 | |
749 | case 'h': |
750 | if(!strcmp(k,"highway")) |
751 | {recognised=1; break;} |
752 | |
753 | if(!strcmp(k,"horse")) |
754 | { |
755 | if(ISTRUE(v)) |
756 | way.allow|=Transports_Horse; |
757 | else if(!ISFALSE(v)) |
758 | logerror("Way %"Pway_t" has an unrecognised tag 'horse' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
759 | recognised=1; break; |
760 | } |
761 | |
762 | if(!strcmp(k,"hgv")) |
763 | { |
764 | if(ISTRUE(v)) |
765 | way.allow|=Transports_HGV; |
766 | else if(!ISFALSE(v)) |
767 | logerror("Way %"Pway_t" has an unrecognised tag 'hgv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
768 | recognised=1; break; |
769 | } |
770 | |
771 | break; |
772 | |
773 | case 'l': |
774 | if(!strcmp(k,"lanes")) |
775 | { |
776 | int en=0; |
777 | float lanesf; |
778 | if(sscanf(v,"%f%n",&lanesf,&en)==1 && en && !v[en]) |
779 | lanes=(int)lanesf; |
780 | else |
781 | logerror("Way %"Pway_t" has an unrecognised tag 'lanes' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),v); |
782 | recognised=1; break; |
783 | } |
784 | |
785 | break; |
786 | |
787 | case 'm': |
788 | if(!strncmp(k,"max",3)) |
789 | { |
790 | if(!strcmp(k+3,"speed")) |
791 | { |
792 | way.speed=kph_to_speed(parse_speed(id,k,v)); |
793 | recognised=1; break; |
794 | } |
795 | |
796 | if(!strcmp(k+3,"weight")) |
797 | { |
798 | way.weight=tonnes_to_weight(parse_weight(id,k,v)); |
799 | recognised=1; break; |
800 | } |
801 | |
802 | if(!strcmp(k+3,"height")) |
803 | { |
804 | way.height=metres_to_height(parse_length(id,k,v)); |
805 | recognised=1; break; |
806 | } |
807 | |
808 | if(!strcmp(k+3,"width")) |
809 | { |
810 | way.width=metres_to_height(parse_length(id,k,v)); |
811 | recognised=1; break; |
812 | } |
813 | |
814 | if(!strcmp(k+3,"length")) |
815 | { |
816 | way.length=metres_to_height(parse_length(id,k,v)); |
817 | recognised=1; break; |
818 | } |
819 | } |
820 | |
821 | if(!strcmp(k,"moped")) |
822 | { |
823 | if(ISTRUE(v)) |
824 | way.allow|=Transports_Moped; |
825 | else if(!ISFALSE(v)) |
826 | logerror("Way %"Pway_t" has an unrecognised tag 'moped' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
827 | recognised=1; break; |
828 | } |
829 | |
830 | if(!strcmp(k,"motorcycle")) |
831 | { |
832 | if(ISTRUE(v)) |
833 | way.allow|=Transports_Motorcycle; |
834 | else if(!ISFALSE(v)) |
835 | logerror("Way %"Pway_t" has an unrecognised tag 'motorcycle' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
836 | recognised=1; break; |
837 | } |
838 | |
839 | if(!strcmp(k,"motorcar")) |
840 | { |
841 | if(ISTRUE(v)) |
842 | way.allow|=Transports_Motorcar; |
843 | else if(!ISFALSE(v)) |
844 | logerror("Way %"Pway_t" has an unrecognised tag 'motorcar' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
845 | recognised=1; break; |
846 | } |
847 | |
848 | if(!strcmp(k,"multilane")) |
849 | { |
850 | if(ISTRUE(v)) |
851 | way.props|=Properties_Multilane; |
852 | else if(!ISFALSE(v)) |
853 | logerror("Way %"Pway_t" has an unrecognised tag 'multilane' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
854 | recognised=1; break; |
855 | } |
856 | |
857 | break; |
858 | |
859 | case 'n': |
860 | if(!strcmp(k,"name")) |
861 | { |
862 | name=v; |
863 | recognised=1; break; |
864 | } |
865 | |
866 | break; |
867 | |
868 | case 'o': |
869 | if(!strcmp(k,"oneway")) |
870 | { |
871 | if(ISTRUE(v)) |
872 | oneway=1; |
873 | else if(!strcmp(v,"-1")) |
874 | oneway=-1; |
875 | else if(!ISFALSE(v)) |
876 | logerror("Way %"Pway_t" has an unrecognised tag 'oneway' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
877 | recognised=1; break; |
878 | } |
879 | |
880 | break; |
881 | |
882 | case 'p': |
883 | if(!strcmp(k,"paved")) |
884 | { |
885 | if(ISTRUE(v)) |
886 | way.props|=Properties_Paved; |
887 | else if(!ISFALSE(v)) |
888 | logerror("Way %"Pway_t" has an unrecognised tag 'paved' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
889 | recognised=1; break; |
890 | } |
891 | |
892 | if(!strcmp(k,"psv")) |
893 | { |
894 | if(ISTRUE(v)) |
895 | way.allow|=Transports_PSV; |
896 | else if(!ISFALSE(v)) |
897 | logerror("Way %"Pway_t" has an unrecognised tag 'psv' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
898 | recognised=1; break; |
899 | } |
900 | |
901 | break; |
902 | |
903 | case 'r': |
904 | if(!strcmp(k,"ref")) |
905 | { |
906 | ref=v; |
907 | recognised=1; break; |
908 | } |
909 | |
910 | if(!strcmp(k,"roundabout")) |
911 | { |
912 | if(ISTRUE(v)) |
913 | roundabout=1; |
914 | else if(!ISFALSE(v)) |
915 | logerror("Way %"Pway_t" has an unrecognised tag 'roundabout' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
916 | recognised=1; break; |
917 | } |
918 | |
919 | break; |
920 | |
921 | case 't': |
922 | if(!strcmp(k,"tunnel")) |
923 | { |
924 | if(ISTRUE(v)) |
925 | way.props|=Properties_Tunnel; |
926 | else if(!ISFALSE(v)) |
927 | logerror("Way %"Pway_t" has an unrecognised tag 'tunnel' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
928 | recognised=1; break; |
929 | } |
930 | |
931 | break; |
932 | |
933 | case 'w': |
934 | if(!strcmp(k,"wheelchair")) |
935 | { |
936 | if(ISTRUE(v)) |
937 | way.allow|=Transports_Wheelchair; |
938 | else if(!ISFALSE(v)) |
939 | logerror("Way %"Pway_t" has an unrecognised tag 'wheelchair' = '%s' (after tagging rules); using 'no'.\n",logerror_way(id),v); |
940 | recognised=1; break; |
941 | } |
942 | |
943 | break; |
944 | |
945 | default: |
946 | break; |
947 | } |
948 | |
949 | if(!recognised) |
950 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
951 | } |
952 | |
953 | /* Create the way */ |
954 | |
955 | if(area && oneway) |
956 | { |
957 | logerror("Way %"Pway_t" is an area and oneway; ignoring area tagging.\n",logerror_way(id)); |
958 | area=0; |
959 | } |
960 | |
961 | if(!way.allow) |
962 | return; |
963 | |
964 | if(oneway) |
965 | { |
966 | way.type|=Highway_OneWay; |
967 | |
968 | if(oneway==-1) |
969 | for(i=0;i<way_nnodes/2;i++) |
970 | { |
971 | node_t temp; |
972 | |
973 | temp=way_nodes[i]; |
974 | way_nodes[i]=way_nodes[way_nnodes-i-1]; |
975 | way_nodes[way_nnodes-i-1]=temp; |
976 | } |
977 | } |
978 | |
979 | if(roundabout) |
980 | way.type|=Highway_Roundabout; |
981 | |
982 | if(area) |
983 | way.type|=Highway_Area; |
984 | |
985 | if(lanes) |
986 | { |
987 | if(oneway || (lanes/2)>1) |
988 | way.props|=Properties_Multilane; |
989 | |
990 | if(oneway && lanes==1) |
991 | way.props&=~Properties_Multilane; |
992 | } |
993 | |
994 | if(ref && name) |
995 | { |
996 | refname=(char*)malloc(strlen(ref)+strlen(name)+4); |
997 | sprintf(refname,"%s (%s)",name,ref); |
998 | } |
999 | else if(ref && !name) |
1000 | refname=ref; |
1001 | else if(!ref && name) |
1002 | refname=name; |
1003 | else /* if(!ref && !name) */ |
1004 | refname=""; |
1005 | |
1006 | AppendWayList(ways,id,&way,way_nodes,way_nnodes,refname); |
1007 | |
1008 | if(ref && name) |
1009 | free(refname); |
1010 | |
1011 | if(area && way_nodes[0]!=way_nodes[way_nnodes-1]) |
1012 | logerror("Way %"Pway_t" is an area but not closed.\n",logerror_way(id)); |
1013 | |
1014 | for(i=1;i<way_nnodes;i++) |
1015 | { |
1016 | node_t from=way_nodes[i-1]; |
1017 | node_t to =way_nodes[i]; |
1018 | |
1019 | if(from==to) |
1020 | logerror("Node %"Pnode_t" in way %"Pway_t" is connected to itself.\n",from,logerror_way(id)); |
1021 | else |
1022 | { |
1023 | int nto=1,duplicated=0; |
1024 | |
1025 | for(j=1;j<i;j++) |
1026 | { |
1027 | node_t n1=way_nodes[j-1]; |
1028 | node_t n2=way_nodes[j]; |
1029 | |
1030 | if(n1==to && (i!=way_nnodes-1 || j!=1)) |
1031 | nto++; |
1032 | |
1033 | if((n1==from && n2==to) || (n2==from && n1==to)) |
1034 | { |
1035 | duplicated=1; |
1036 | logerror("Segment connecting nodes %"Pnode_t" and %"Pnode_t" in way %"Pway_t" is duplicated.\n",logerror_node(n1),logerror_node(n2),logerror_way(id)); |
1037 | } |
1038 | } |
1039 | |
1040 | if(nto>=2 && !duplicated) |
1041 | logerror("Node %"Pnode_t" in way %"Pway_t" appears more than once.\n",logerror_node(to),logerror_way(id)); |
1042 | } |
1043 | } |
1044 | } |
1045 | |
1046 | |
1047 | /*++++++++++++++++++++++++++++++++++++++ |
1048 | Process the tags associated with a relation. |
1049 | |
1050 | TagList *tags The list of relation tags. |
1051 | |
1052 | int64_t relation_id The id of the relation. |
1053 | |
1054 | int mode The mode of operation to take (create, modify, delete). |
1055 | ++++++++++++++++++++++++++++++++++++++*/ |
1056 | |
1057 | void ProcessRelationTags(TagList *tags,int64_t relation_id,int mode) |
1058 | { |
1059 | transports_t routes=Transports_None; |
1060 | transports_t except=Transports_None; |
1061 | int relation_turn_restriction=0; |
1062 | TurnRestriction restriction=TurnRestrict_None; |
1063 | relation_t id; |
1064 | int i; |
1065 | |
1066 | /* Convert id */ |
1067 | |
1068 | id=(relation_t)relation_id; |
1069 | logassert((int64_t)id==relation_id,"Relation ID too large (change relation_t to 64-bits?)"); /* check relation id can be stored in relation_t data type. */ |
1070 | |
1071 | /* Delete */ |
1072 | |
1073 | if(mode==MODE_DELETE || mode==MODE_MODIFY) |
1074 | { |
1075 | AppendRouteRelationList(relations,id,RELATION_DELETED, |
1076 | relation_ways,relation_nways, |
1077 | relation_relations,relation_nrelations); |
1078 | |
1079 | AppendTurnRelationList(relations,id, |
1080 | relation_from,relation_to,relation_via, |
1081 | restriction,RELATION_DELETED); |
1082 | } |
1083 | |
1084 | if(mode==MODE_DELETE) |
1085 | return; |
1086 | |
1087 | /* Sanity check */ |
1088 | |
1089 | if(relation_nnodes==0 && relation_nways==0 && relation_nrelations==0) |
1090 | { |
1091 | logerror("Relation %"Prelation_t" has no nodes, ways or relations.\n",logerror_relation(id)); |
1092 | return; |
1093 | } |
1094 | |
1095 | /* Parse the tags */ |
1096 | |
1097 | for(i=0;i<tags->ntags;i++) |
1098 | { |
1099 | int recognised=0; |
1100 | char *k=tags->k[i]; |
1101 | char *v=tags->v[i]; |
1102 | |
1103 | switch(*k) |
1104 | { |
1105 | case 'b': |
1106 | if(!strcmp(k,"bicycleroute")) |
1107 | { |
1108 | if(ISTRUE(v)) |
1109 | routes|=Transports_Bicycle; |
1110 | else if(!ISFALSE(v)) |
1111 | logerror("Relation %"Prelation_t" has an unrecognised tag 'bicycleroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); |
1112 | recognised=1; break; |
1113 | } |
1114 | |
1115 | break; |
1116 | |
1117 | case 'e': |
1118 | if(!strcmp(k,"except")) |
1119 | { |
1120 | for(i=1;i<Transport_Count;i++) |
1121 | if(strstr(v,TransportName(i))) |
1122 | except|=TRANSPORTS(i); |
1123 | |
1124 | if(except==Transports_None) |
1125 | logerror("Relation %"Prelation_t" has an unrecognised tag 'except' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); |
1126 | |
1127 | recognised=1; break; |
1128 | } |
1129 | |
1130 | break; |
1131 | |
1132 | case 'f': |
1133 | if(!strcmp(k,"footroute")) |
1134 | { |
1135 | if(ISTRUE(v)) |
1136 | routes|=Transports_Foot; |
1137 | else if(!ISFALSE(v)) |
1138 | logerror("Relation %"Prelation_t" has an unrecognised tag 'footroute' = '%s' (after tagging rules); using 'no'.\n",logerror_relation(id),v); |
1139 | recognised=1; break; |
1140 | } |
1141 | |
1142 | break; |
1143 | |
1144 | case 'r': |
1145 | if(!strcmp(k,"restriction")) |
1146 | { |
1147 | if(!strcmp(v,"no_right_turn" )) restriction=TurnRestrict_no_right_turn; |
1148 | if(!strcmp(v,"no_left_turn" )) restriction=TurnRestrict_no_left_turn; |
1149 | if(!strcmp(v,"no_u_turn" )) restriction=TurnRestrict_no_u_turn; |
1150 | if(!strcmp(v,"no_straight_on" )) restriction=TurnRestrict_no_straight_on; |
1151 | if(!strcmp(v,"only_right_turn" )) restriction=TurnRestrict_only_right_turn; |
1152 | if(!strcmp(v,"only_left_turn" )) restriction=TurnRestrict_only_left_turn; |
1153 | if(!strcmp(v,"only_straight_on")) restriction=TurnRestrict_only_straight_on; |
1154 | |
1155 | if(restriction==TurnRestrict_None) |
1156 | logerror("Relation %"Prelation_t" has an unrecognised tag 'restriction' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),v); |
1157 | |
1158 | recognised=1; break; |
1159 | } |
1160 | |
1161 | break; |
1162 | |
1163 | case 't': |
1164 | if(!strcmp(k,"type")) |
1165 | { |
1166 | if(!strcmp(v,"restriction")) |
1167 | relation_turn_restriction=1; |
1168 | |
1169 | /* Don't log an error for relations of types that we don't handle - there are so many */ |
1170 | recognised=1; break; |
1171 | } |
1172 | |
1173 | break; |
1174 | |
1175 | default: |
1176 | break; |
1177 | } |
1178 | |
1179 | if(!recognised) |
1180 | logerror("Relation %"Prelation_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_relation(id),k,v); |
1181 | } |
1182 | |
1183 | /* Create the route relation (must store all relations that have ways or |
1184 | relations even if they are not routes because they might be referenced by |
1185 | other relations that are routes) */ |
1186 | |
1187 | if((relation_nways || relation_nrelations) && !relation_turn_restriction) |
1188 | AppendRouteRelationList(relations,id,routes, |
1189 | relation_ways,relation_nways, |
1190 | relation_relations,relation_nrelations); |
1191 | |
1192 | /* Create the turn restriction relation. */ |
1193 | |
1194 | if(relation_turn_restriction && restriction!=TurnRestrict_None) |
1195 | { |
1196 | if(relation_from==NO_WAY_ID) |
1197 | { |
1198 | /* Extra logerror information since relation isn't stored */ |
1199 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); |
1200 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); |
1201 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'from' way.\n",logerror_relation(id)); |
1202 | } |
1203 | if(relation_to==NO_WAY_ID) |
1204 | { |
1205 | /* Extra logerror information since relation isn't stored */ |
1206 | if(relation_via!=NO_NODE_ID) logerror_node(relation_via); |
1207 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); |
1208 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'to' way.\n",logerror_relation(id)); |
1209 | } |
1210 | if(relation_via==NO_NODE_ID) |
1211 | { |
1212 | /* Extra logerror information since relation isn't stored */ |
1213 | if(relation_to!=NO_WAY_ID) logerror_way(relation_to); |
1214 | if(relation_from!=NO_WAY_ID) logerror_way(relation_from); |
1215 | logerror("Relation %"Prelation_t" is a turn restriction but has no 'via' node.\n",logerror_relation(id)); |
1216 | } |
1217 | |
1218 | if(relation_from!=NO_WAY_ID && relation_to!=NO_WAY_ID && relation_via!=NO_NODE_ID) |
1219 | AppendTurnRelationList(relations,id, |
1220 | relation_from,relation_to,relation_via, |
1221 | restriction,except); |
1222 | } |
1223 | } |
1224 | |
1225 | |
1226 | /*++++++++++++++++++++++++++++++++++++++ |
1227 | Convert a string containing a speed into a double precision. |
1228 | |
1229 | double parse_speed Returns the speed in km/h if it can be parsed. |
1230 | |
1231 | way_t id The way being processed. |
1232 | |
1233 | const char *k The tag key. |
1234 | |
1235 | const char *v The tag value. |
1236 | ++++++++++++++++++++++++++++++++++++++*/ |
1237 | |
1238 | static double parse_speed(way_t id,const char *k,const char *v) |
1239 | { |
1240 | char *ev; |
1241 | double value=strtod(v,&ev); |
1242 | |
1243 | if(v==ev) |
1244 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1245 | else |
1246 | { |
1247 | while(isspace(*ev)) ev++; |
1248 | |
1249 | if(!strcmp(ev,"mph")) |
1250 | return(1.609*value); |
1251 | |
1252 | if(*ev==0 || !strcmp(ev,"kph")) |
1253 | return(value); |
1254 | |
1255 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1256 | } |
1257 | |
1258 | return(0); |
1259 | } |
1260 | |
1261 | |
1262 | /*++++++++++++++++++++++++++++++++++++++ |
1263 | Convert a string containing a weight into a double precision. |
1264 | |
1265 | double parse_weight Returns the weight in tonnes if it can be parsed. |
1266 | |
1267 | way_t id The way being processed. |
1268 | |
1269 | const char *k The tag key. |
1270 | |
1271 | const char *v The tag value. |
1272 | ++++++++++++++++++++++++++++++++++++++*/ |
1273 | |
1274 | static double parse_weight(way_t id,const char *k,const char *v) |
1275 | { |
1276 | char *ev; |
1277 | double value=strtod(v,&ev); |
1278 | |
1279 | if(v==ev) |
1280 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1281 | else |
1282 | { |
1283 | while(isspace(*ev)) ev++; |
1284 | |
1285 | if(!strcmp(ev,"kg")) |
1286 | return(value/1000.0); |
1287 | |
1288 | if(*ev==0 || !strcmp(ev,"T") || !strcmp(ev,"t") |
1289 | || !strcmp(ev,"ton") || !strcmp(ev,"tons") |
1290 | || !strcmp(ev,"tonne") || !strcmp(ev,"tonnes")) |
1291 | return(value); |
1292 | |
1293 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1294 | } |
1295 | |
1296 | return(0); |
1297 | } |
1298 | |
1299 | |
1300 | /*++++++++++++++++++++++++++++++++++++++ |
1301 | Convert a string containing a length into a double precision. |
1302 | |
1303 | double parse_length Returns the length in metres if it can be parsed. |
1304 | |
1305 | way_t id The way being processed. |
1306 | |
1307 | const char *k The tag key. |
1308 | |
1309 | const char *v The tag value. |
1310 | ++++++++++++++++++++++++++++++++++++++*/ |
1311 | |
1312 | static double parse_length(way_t id,const char *k,const char *v) |
1313 | { |
1314 | char *ev; |
1315 | double value=strtod(v,&ev); |
1316 | |
1317 | if(v==ev) |
1318 | logerror("Way %"Pway_t" has an unrecognised tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1319 | else |
1320 | { |
1321 | int en=0; |
1322 | int feet=0,inches=0; |
1323 | |
1324 | if(sscanf(v,"%d' %d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1325 | return((feet+(double)inches/12.0)*0.254); |
1326 | |
1327 | if(sscanf(v,"%d'%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1328 | return((feet+(double)inches/12.0)*0.254); |
1329 | |
1330 | if(sscanf(v,"%d'-%d\"%n",&feet,&inches,&en)==2 && en && !v[en]) |
1331 | return((feet+(double)inches/12.0)*0.254); |
1332 | |
1333 | if(sscanf(v,"%d - %d%n",&feet,&inches,&en)==2 && en && !v[en]) |
1334 | return((feet+(double)inches/12.0)*0.254); |
1335 | |
1336 | if(sscanf(v,"%d ft %d in%n",&feet,&inches,&en)==2 && en && !v[en]) |
1337 | return((feet+(double)inches/12.0)*0.254); |
1338 | |
1339 | if(sscanf(v,"%d feet %d inches%n",&feet,&inches,&en)==2 && en && !v[en]) |
1340 | return((feet+(double)inches/12.0)*0.254); |
1341 | |
1342 | if(!strcmp(ev,"'")) |
1343 | return(feet*0.254); |
1344 | |
1345 | while(isspace(*ev)) ev++; |
1346 | |
1347 | if(!strcmp(ev,"ft") || !strcmp(ev,"feet")) |
1348 | return(value*0.254); |
1349 | |
1350 | if(*ev==0 || !strcmp(ev,"m") || !strcmp(ev,"metre") || !strcmp(ev,"metres")) |
1351 | return(value); |
1352 | |
1353 | logerror("Way %"Pway_t" has an un-parseable tag '%s' = '%s' (after tagging rules); ignoring it.\n",logerror_way(id),k,v); |
1354 | } |
1355 | |
1356 | return(0); |
1357 | } |
Properties
Name | Value |
---|---|
cvs:description | OSM XML file parser. |