1 /***************************************
2 $Header: /home/amb/routino/src/RCS/filedumper.c,v 1.43 2010/05/30 12:52:16 amb Exp $
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ***************************************/
33 #include "functions.h"
34 #include "visualiser.h"
43 static void print_node(Nodes* nodes,index_t item);
44 static void print_segment(Segments *segments,index_t item);
45 static void print_way(Ways *ways,index_t item);
47 static void print_head_osm(void);
48 static void print_node_osm(Nodes* nodes,index_t item);
49 static void print_segment_osm(Segments *segments,index_t item,Ways *ways);
50 static void print_tail_osm(void);
52 static char *RFC822Date(time_t t);
54 static void print_usage(int detail);
57 /*++++++++++++++++++++++++++++++++++++++
58 The main program for the file dumper.
59 ++++++++++++++++++++++++++++++++++++++*/
61 int main(int argc,char** argv)
64 Segments *OSMSegments;
67 char *dirname=NULL,*prefix=NULL;
68 char *nodes_filename,*segments_filename,*ways_filename;
69 int option_statistics=0;
70 int option_visualiser=0,coordcount=0;
71 double latmin=0,latmax=0,lonmin=0,lonmax=0;
72 char *option_data=NULL;
74 int option_dump_osm=0,option_no_super=0;
76 /* Parse the command line arguments */
78 for(arg=1;arg<argc;arg++)
80 if(!strcmp(argv[arg],"--help"))
82 else if(!strncmp(argv[arg],"--dir=",6))
83 dirname=&argv[arg][6];
84 else if(!strncmp(argv[arg],"--prefix=",9))
86 else if(!strcmp(argv[arg],"--statistics"))
88 else if(!strcmp(argv[arg],"--visualiser"))
90 else if(!strcmp(argv[arg],"--dump"))
92 else if(!strcmp(argv[arg],"--dump-osm"))
94 else if(!strncmp(argv[arg],"--latmin",8) && argv[arg][8]=='=')
95 {latmin=degrees_to_radians(atof(&argv[arg][9]));coordcount++;}
96 else if(!strncmp(argv[arg],"--latmax",8) && argv[arg][8]=='=')
97 {latmax=degrees_to_radians(atof(&argv[arg][9]));coordcount++;}
98 else if(!strncmp(argv[arg],"--lonmin",8) && argv[arg][8]=='=')
99 {lonmin=degrees_to_radians(atof(&argv[arg][9]));coordcount++;}
100 else if(!strncmp(argv[arg],"--lonmax",8) && argv[arg][8]=='=')
101 {lonmax=degrees_to_radians(atof(&argv[arg][9]));coordcount++;}
102 else if(!strncmp(argv[arg],"--data",6) && argv[arg][6]=='=')
103 option_data=&argv[arg][7];
104 else if(!strcmp(argv[arg],"--no-super"))
106 else if(!strncmp(argv[arg],"--node=",7))
108 else if(!strncmp(argv[arg],"--segment=",10))
110 else if(!strncmp(argv[arg],"--way=",6))
116 if(!option_statistics && !option_visualiser && !option_dump && !option_dump_osm)
119 /* Load in the data - Note: No error checking because Load*List() will call exit() in case of an error. */
121 OSMNodes=LoadNodeList(nodes_filename=FileName(dirname,prefix,"nodes.mem"));
123 OSMSegments=LoadSegmentList(segments_filename=FileName(dirname,prefix,"segments.mem"));
125 OSMWays=LoadWayList(ways_filename=FileName(dirname,prefix,"ways.mem"));
127 /* Write out the visualiser data */
129 if(option_visualiser)
133 fprintf(stderr,"The --visualiser option must have --latmin, --latmax, --lonmin, --lonmax.\n");
139 fprintf(stderr,"The --visualiser option must have --data.\n");
143 if(!strcmp(option_data,"junctions"))
144 OutputJunctions(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
145 else if(!strcmp(option_data,"super"))
146 OutputSuper(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
147 else if(!strcmp(option_data,"oneway"))
148 OutputOneway(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
149 else if(!strcmp(option_data,"speed"))
150 OutputSpeedLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
151 else if(!strcmp(option_data,"weight"))
152 OutputWeightLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
153 else if(!strcmp(option_data,"height"))
154 OutputHeightLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
155 else if(!strcmp(option_data,"width"))
156 OutputWidthLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
157 else if(!strcmp(option_data,"length"))
158 OutputLengthLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
161 fprintf(stderr,"Unrecognised data option '%s' with --visualiser.\n",option_data);
166 /* Print out statistics */
168 if(option_statistics)
172 /* Examine the files */
178 stat(nodes_filename,&buf);
180 printf("'%s%snodes.mem' - %9lld Bytes\n",prefix?prefix:"",prefix?"-":"",(long long)buf.st_size);
181 printf("%s\n",RFC822Date(buf.st_mtime));
184 stat(segments_filename,&buf);
186 printf("'%s%ssegments.mem' - %9lld Bytes\n",prefix?prefix:"",prefix?"-":"",(long long)buf.st_size);
187 printf("%s\n",RFC822Date(buf.st_mtime));
190 stat(ways_filename,&buf);
192 printf("'%s%sways.mem' - %9lld Bytes\n",prefix?prefix:"",prefix?"-":"",(long long)buf.st_size);
193 printf("%s\n",RFC822Date(buf.st_mtime));
196 /* Examine the nodes */
202 printf("sizeof(Node) =%9d Bytes\n",sizeof(Node));
203 printf("Number =%9d\n",OSMNodes->number);
204 printf("Number(super)=%9d\n",OSMNodes->snumber);
207 printf("Lat bins= %4d\n",OSMNodes->latbins);
208 printf("Lon bins= %4d\n",OSMNodes->lonbins);
211 printf("Lat zero=%5d (%8.4f deg)\n",OSMNodes->latzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->latzero))));
212 printf("Lon zero=%5d (%8.4f deg)\n",OSMNodes->lonzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->lonzero))));
214 /* Examine the segments */
217 printf("Segments\n");
218 printf("--------\n");
221 printf("sizeof(Segment)=%9d Bytes\n",sizeof(Segment));
222 printf("Number(total) =%9d\n",OSMSegments->number);
223 printf("Number(super) =%9d\n",OSMSegments->snumber);
224 printf("Number(normal) =%9d\n",OSMSegments->nnumber);
226 /* Examine the ways */
233 printf("sizeof(Way) =%9d Bytes\n",sizeof(Way));
234 printf("Number(compacted)=%9d\n",OSMWays->number);
235 printf("Number(original) =%9d\n",OSMWays->onumber);
238 printf("Total names =%9ld Bytes\n",(long)buf.st_size-sizeof(Ways)-OSMWays->number*sizeof(Way));
241 printf("Included transports: %s\n",AllowedNameList(OSMWays->allow));
242 printf("Included properties: %s\n",PropertiesNameList(OSMWays->props));
245 /* Print out internal data */
251 for(arg=1;arg<argc;arg++)
252 if(!strcmp(argv[arg],"--node=all"))
254 for(item=0;item<OSMNodes->number;item++)
255 print_node(OSMNodes,item);
257 else if(!strncmp(argv[arg],"--node=",7))
259 item=atoi(&argv[arg][7]);
261 if(item>=0 && item<OSMNodes->number)
262 print_node(OSMNodes,item);
264 printf("Invalid node number; minimum=0, maximum=%d.\n",OSMNodes->number-1);
266 else if(!strcmp(argv[arg],"--segment=all"))
268 for(item=0;item<OSMSegments->number;item++)
269 print_segment(OSMSegments,item);
271 else if(!strncmp(argv[arg],"--segment=",10))
273 item=atoi(&argv[arg][10]);
275 if(item>=0 && item<OSMSegments->number)
276 print_segment(OSMSegments,item);
278 printf("Invalid segment number; minimum=0, maximum=%d.\n",OSMSegments->number-1);
280 else if(!strcmp(argv[arg],"--way=all"))
282 for(item=0;item<OSMWays->number;item++)
283 print_way(OSMWays,item);
285 else if(!strncmp(argv[arg],"--way=",6))
287 item=atoi(&argv[arg][6]);
289 if(item>=0 && item<OSMWays->number)
290 print_way(OSMWays,item);
292 printf("Invalid way number; minimum=0, maximum=%d.\n",OSMWays->number-1);
296 /* Print out internal data in XML format */
300 if(coordcount>0 && coordcount!=4)
302 fprintf(stderr,"The --dump-osm option must have all of --latmin, --latmax, --lonmin, --lonmax or none.\n");
310 int32_t latminbin=latlong_to_bin(radians_to_latlong(latmin))-OSMNodes->latzero;
311 int32_t latmaxbin=latlong_to_bin(radians_to_latlong(latmax))-OSMNodes->latzero;
312 int32_t lonminbin=latlong_to_bin(radians_to_latlong(lonmin))-OSMNodes->lonzero;
313 int32_t lonmaxbin=latlong_to_bin(radians_to_latlong(lonmax))-OSMNodes->lonzero;
317 /* Loop through all of the nodes. */
319 for(latb=latminbin;latb<=latmaxbin;latb++)
320 for(lonb=lonminbin;lonb<=lonmaxbin;lonb++)
322 llbin=lonb*OSMNodes->latbins+latb;
324 if(llbin<0 || llbin>(OSMNodes->latbins*OSMNodes->lonbins))
327 for(node=OSMNodes->offsets[llbin];node<OSMNodes->offsets[llbin+1];node++)
329 double lat=latlong_to_radians(bin_to_latlong(OSMNodes->latzero+latb)+off_to_latlong(OSMNodes->nodes[node].latoffset));
330 double lon=latlong_to_radians(bin_to_latlong(OSMNodes->lonzero+lonb)+off_to_latlong(OSMNodes->nodes[node].lonoffset));
332 if(lat>latmin && lat<latmax && lon>lonmin && lon<lonmax)
336 print_node_osm(OSMNodes,node);
338 segment=FirstSegment(OSMSegments,OSMNodes,node);
342 if(node>OtherNode(segment,node))
343 if(!option_no_super || IsNormalSegment(segment))
344 print_segment_osm(OSMSegments,IndexSegment(OSMSegments,segment),OSMWays);
346 segment=NextSegment(OSMSegments,segment,node);
356 for(item=0;item<OSMNodes->number;item++)
357 print_node_osm(OSMNodes,item);
359 for(item=0;item<OSMSegments->number;item++)
360 if(!option_no_super || IsNormalSegment(LookupSegment(OSMSegments,item)))
361 print_segment_osm(OSMSegments,item,OSMWays);
371 /*++++++++++++++++++++++++++++++++++++++
372 Print out the contents of a node from the routing database.
374 Nodes *nodes The set of nodes to use.
376 index_t item The node index to print.
377 ++++++++++++++++++++++++++++++++++++++*/
379 static void print_node(Nodes* nodes,index_t item)
381 Node *node=LookupNode(nodes,item);
382 double latitude,longitude;
384 GetLatLong(nodes,item,&latitude,&longitude);
386 printf("Node %d\n",item);
387 printf(" firstseg=%d\n",SEGMENT(node->firstseg));
388 printf(" latoffset=%d lonoffset=%d (latitude=%.6f longitude=%.6f)\n",node->latoffset,node->lonoffset,radians_to_degrees(latitude),radians_to_degrees(longitude));
389 if(IsSuperNode(nodes,item))
390 printf(" Super-Node\n");
394 /*++++++++++++++++++++++++++++++++++++++
395 Print out the contents of a segment from the routing database.
397 Segments *segments The set of segments to use.
399 index_t item The segment index to print.
400 ++++++++++++++++++++++++++++++++++++++*/
402 static void print_segment(Segments *segments,index_t item)
404 Segment *segment=LookupSegment(segments,item);
406 printf("Segment %d\n",item);
407 printf(" node1=%d node2=%d\n",segment->node1,segment->node2);
408 printf(" next2=%d\n",segment->next2);
409 printf(" way=%d\n",segment->way);
410 printf(" distance=%d (%.3f km)\n",DISTANCE(segment->distance),distance_to_km(DISTANCE(segment->distance)));
411 if(IsSuperSegment(segment) && IsNormalSegment(segment))
412 printf(" Super-Segment AND normal Segment\n");
413 else if(IsSuperSegment(segment) && !IsNormalSegment(segment))
414 printf(" Super-Segment\n");
415 if(IsOnewayTo(segment,segment->node1))
416 printf(" One-Way from node2 to node1\n");
417 if(IsOnewayTo(segment,segment->node2))
418 printf(" One-Way from node1 to node2\n");
422 /*++++++++++++++++++++++++++++++++++++++
423 Print out the contents of a way from the routing database.
425 Ways *ways The set of ways to use.
427 index_t item The way index to print.
428 ++++++++++++++++++++++++++++++++++++++*/
430 static void print_way(Ways *ways,index_t item)
432 Way *way=LookupWay(ways,item);
434 printf("Way %d\n",item);
435 printf(" name=%s\n",WayNameHighway(ways,way));
436 printf(" type=%02x (%s%s%s)\n",way->type,HighwayName(HIGHWAY(way->type)),way->type&Way_OneWay?",One-Way":"",way->type&Way_Roundabout?",Roundabout":"");
437 printf(" allow=%02x (%s)\n",way->allow,AllowedNameList(way->allow));
439 printf(" props=%02x (%s)\n",way->props,PropertiesNameList(way->props));
441 printf(" speed=%d (%d km/hr)\n",way->speed,speed_to_kph(way->speed));
443 printf(" weight=%d (%.1f tonnes)\n",way->weight,weight_to_tonnes(way->weight));
445 printf(" height=%d (%.1f m)\n",way->height,height_to_metres(way->height));
447 printf(" width=%d (%.1f m)\n",way->width,width_to_metres(way->width));
449 printf(" length=%d (%.1f m)\n",way->length,length_to_metres(way->length));
453 /*++++++++++++++++++++++++++++++++++++++
454 Print out a header in OSM XML format.
455 ++++++++++++++++++++++++++++++++++++++*/
457 static void print_head_osm(void)
459 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
460 printf("<osm version='0.6' generator='JOSM'>\n");
464 /*++++++++++++++++++++++++++++++++++++++
465 Print out the contents of a node from the routing database in OSM XML format.
467 Nodes *nodes The set of nodes to use.
469 index_t item The node index to print.
470 ++++++++++++++++++++++++++++++++++++++*/
472 static void print_node_osm(Nodes* nodes,index_t item)
474 double latitude,longitude;
476 GetLatLong(nodes,item,&latitude,&longitude);
478 if(IsSuperNode(nodes,item))
480 printf(" <node id='%lu' lat='%.7f' lon='%.7f' version='1'>\n",(unsigned long)item+1,radians_to_degrees(latitude),radians_to_degrees(longitude));
481 printf(" <tag k='routino:super' v='yes' />\n");
482 printf(" </node>\n");
485 printf(" <node id='%lu' lat='%.7f' lon='%.7f' version='1' />\n",(unsigned long)item+1,radians_to_degrees(latitude),radians_to_degrees(longitude));
489 /*++++++++++++++++++++++++++++++++++++++
490 Print out the contents of a segment from the routing database as a way in OSM XML format.
492 Segments *segments The set of segments to use.
494 index_t item The segment index to print.
496 Ways *ways The set of ways to use.
497 ++++++++++++++++++++++++++++++++++++++*/
499 static void print_segment_osm(Segments *segments,index_t item,Ways *ways)
501 Segment *segment=LookupSegment(segments,item);
502 Way *way=LookupWay(ways,segment->way);
505 printf(" <way id='%lu' version='1'>\n",(unsigned long)item+1);
507 if(IsOnewayTo(segment,segment->node1))
509 printf(" <nd ref='%lu' />\n",(unsigned long)segment->node2+1);
510 printf(" <nd ref='%lu' />\n",(unsigned long)segment->node1+1);
514 printf(" <nd ref='%lu' />\n",(unsigned long)segment->node1+1);
515 printf(" <nd ref='%lu' />\n",(unsigned long)segment->node2+1);
518 if(IsSuperSegment(segment))
519 printf(" <tag k='routino:super' v='yes' />\n");
520 if(IsNormalSegment(segment))
521 printf(" <tag k='routino:normal' v='yes' />\n");
523 if(way->type & Way_OneWay)
524 printf(" <tag k='oneway' v='yes' />\n");
525 if(way->type & Way_Roundabout)
526 printf(" <tag k='junction' v='roundabout' />\n");
528 printf(" <tag k='highway' v='%s' />\n",HighwayName(HIGHWAY(way->type)));
530 if(IsNormalSegment(segment) && WayNamed(ways,way))
531 printf(" <tag k='name' v='%s' />\n",ParseXML_Encode_Safe_XML(WayNameHighway(ways,way)));
533 for(i=1;i<Transport_Count;i++)
534 if(way->allow & ALLOWED(i))
535 printf(" <tag k='%s' v='yes' />\n",TransportName(i));
537 for(i=1;i<Property_Count;i++)
538 if(way->props & PROPERTIES(i))
539 printf(" <tag k='%s' v='yes' />\n",PropertyName(i));
542 printf(" <tag k='maxspeed' v='%d' />\n",speed_to_kph(way->speed));
545 printf(" <tag k='maxweight' v='%.1f' />\n",weight_to_tonnes(way->weight));
547 printf(" <tag k='maxheight' v='%.1f' />\n",height_to_metres(way->height));
549 printf(" <tag k='maxwidth' v='%.1f' />\n",width_to_metres(way->width));
551 printf(" <tag k='maxlength' v='%.1f' />\n",length_to_metres(way->length));
557 /*++++++++++++++++++++++++++++++++++++++
558 Print out a tail in OSM XML format.
559 ++++++++++++++++++++++++++++++++++++++*/
561 static void print_tail_osm(void)
567 /*+ Conversion from time_t to date string (day of week). +*/
568 static const char* const weekdays[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
570 /*+ Conversion from time_t to date string (month of year). +*/
571 static const char* const months[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
574 /*++++++++++++++++++++++++++++++++++++++
575 Convert the time into an RFC 822 compliant date.
577 char *RFC822Date Returns a pointer to a fixed string containing the date.
580 ++++++++++++++++++++++++++++++++++++++*/
582 static char *RFC822Date(time_t t)
584 static char value[32];
591 strcpy(weekday,weekdays[tim->tm_wday]);
592 strcpy(month,months[tim->tm_mon]);
594 /* Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 */
596 sprintf(value,"%3s, %02d %3s %4d %02d:%02d:%02d %s",
611 /*++++++++++++++++++++++++++++++++++++++
612 Print out the usage information.
614 int detail The level of detail to use - 0 = low, 1 = high.
615 ++++++++++++++++++++++++++++++++++++++*/
617 static void print_usage(int detail)
620 "Usage: filedumper [--help]\n"
621 " [--dir=<dirname>] [--prefix=<name>]\n"
623 " [--visualiser --latmin=<latmin> --latmax=<latmax>\n"
624 " --lonmin=<lonmin> --lonmax=<lonmax>\n"
625 " --data=<data-type>]\n"
626 " [--dump [--node=<node> ...]\n"
627 " [--segment=<segment> ...]\n"
628 " [--way=<way> ...]]\n"
629 " [--dump-osm [--no-super]\n"
630 " [--latmin=<latmin> --latmax=<latmax>\n"
631 " --lonmin=<lonmin> --lonmax=<lonmax>]]\n");
636 "--help Prints this information.\n"
638 "--dir=<dirname> The directory containing the routing database.\n"
639 "--prefix=<name> The filename prefix for the routing database.\n"
641 "--statistics Print statistics about the routing database.\n"
643 "--visualiser Extract selected data from the routing database:\n"
644 " --latmin=<latmin> * the minimum latitude (degrees N).\n"
645 " --latmax=<latmax> * the maximum latitude (degrees N).\n"
646 " --lonmin=<lonmin> * the minimum longitude (degrees E).\n"
647 " --lonmax=<lonmax> * the maximum longitude (degrees E).\n"
648 " --data=<data-type> * the type of data to select.\n"
650 " <data-type> can be selected from:\n"
651 " junctions = segment count at each junction.\n"
652 " super = super-node and super-segments.\n"
653 " oneway = oneway segments.\n"
654 " speed = speed limits.\n"
655 " weight = weight limits.\n"
656 " height = height limits.\n"
657 " width = width limits.\n"
658 " length = length limits.\n"
660 "--dump Dump selected contents of the database.\n"
661 " --node=<node> * the node with the selected number.\n"
662 " --segment=<segment> * the segment with the selected number.\n"
663 " --way=<way> * the way with the selected number.\n"
664 " Use 'all' instead of a number to get all of them.\n"
666 "--dump-osm Dump all or part of the database as an XML file.\n"
667 " --no-super * exclude the super-segments.\n"
668 " --latmin=<latmin> * the minimum latitude (degrees N).\n"
669 " --latmax=<latmax> * the maximum latitude (degrees N).\n"
670 " --lonmin=<lonmin> * the minimum longitude (degrees E).\n"
671 " --lonmax=<lonmax> * the maximum longitude (degrees E).\n");