/***************************************
- $Header: /home/amb/routino/src/RCS/router.c,v 1.83 2010/06/28 17:56:26 amb Exp $
+ $Header: /home/amb/routino/src/RCS/router.c,v 1.89 2010/09/15 18:19:36 amb Exp $
OSM router.
#include <ctype.h>
#include "types.h"
-#include "functions.h"
-#include "translations.h"
-#include "profiles.h"
#include "nodes.h"
#include "segments.h"
#include "ways.h"
+#include "files.h"
+#include "functions.h"
+#include "translations.h"
+#include "profiles.h"
-/*+ The number of waypoints allowed to be specified. +*/
-#define NWAYPOINTS 99
/*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
#define MAXSEARCH 1
-/*+ The minimum distance along a segment from a node to insert a fake node. (in km). +*/
-#define MINSEGMENT 0.005
-
-
-/*+ A set of fake segments to allow start/finish in the middle of a segment. +*/
-static Segment fake_segments[2*NWAYPOINTS];
-/*+ A set of fake node latitudes and longitudes. +*/
+/*+ A set of waypoint latitudes and longitudes. +*/
static double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
/*+ The option not to print any progress information. +*/
/* Local functions */
-static void print_usage(int detail);
+static void print_usage(int detail,const char *argerr,const char *err);
/*++++++++++++++++++++++++++++++++++++++
/* Parse the command line arguments */
if(argc<2)
- print_usage(0);
+ print_usage(0,NULL,NULL);
/* Get the non-routing, general program options */
for(arg=1;arg<argc;arg++)
{
if(!strcmp(argv[arg],"--help"))
- print_usage(1);
+ print_usage(1,NULL,NULL);
else if(!strcmp(argv[arg],"--help-profile"))
help_profile=1;
else if(!strcmp(argv[arg],"--help-profile-xml"))
transport=TransportType(&argv[arg][12]);
if(transport==Transport_None)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
}
else
continue;
{
if(ExistsFile(FileName(dirname,prefix,"profiles.xml")))
profiles=FileName(dirname,prefix,"profiles.xml");
+ else if(ExistsFile(FileName(DATADIR,NULL,"tagging.xml")))
+ profiles=FileName(DATADIR,NULL,"profiles.xml");
else
{
fprintf(stderr,"Error: The '--profiles' option was not used and the default 'profiles.xml' does not exist.\n");
}
}
- if(profiles && ParseXMLProfiles(profiles))
+ if(ParseXMLProfiles(profiles))
{
fprintf(stderr,"Error: Cannot read the profiles in the file '%s'.\n",profiles);
return(1);
char *p=&argv[arg][6];
while(isdigit(*p)) p++;
if(*p++!='=')
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
point=atoi(&argv[arg][5]);
if(point>NWAYPOINTS || point_used[point]&1)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
point_lon[point]=degrees_to_radians(atof(p));
point_used[point]+=1;
char *p=&argv[arg][6];
while(isdigit(*p)) p++;
if(*p++!='=')
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
point=atoi(&argv[arg][5]);
if(point>NWAYPOINTS || point_used[point]&2)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
point_lat[point]=degrees_to_radians(atof(p));
point_used[point]+=2;
char *string;
if(!equal)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10);
string[equal-argv[arg]-10]=0;
highway=HighwayType(string);
if(highway==Way_Count)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
profile->highway[highway]=atof(equal+1);
char *string;
if(!equal)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8);
string[equal-argv[arg]-8]=0;
highway=HighwayType(string);
if(highway==Way_Count)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
profile->speed[highway]=kph_to_speed(atof(equal+1));
char *string;
if(!equal)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11);
string[equal-argv[arg]-11]=0;
property=PropertyType(string);
if(property==Way_Count)
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
profile->props_yes[property]=atof(equal+1);
else if(!strncmp(argv[arg],"--length=",9))
profile->length=metres_to_length(atof(&argv[arg][9]));
else
- print_usage(0);
+ print_usage(0,argv[arg],NULL);
}
for(point=1;point<=NWAYPOINTS;point++)
if(point_used[point]==1 || point_used[point]==2)
- print_usage(0);
+ print_usage(0,NULL,"All waypoints must have latitude and longitude.");
if(help_profile)
{
if(option_html || option_gpx_route || option_gpx_track)
{
- if(translations && ExistsFile(translations))
- ;
- else if(!translations && ExistsFile(FileName(dirname,prefix,"translations.xml")))
- translations=FileName(dirname,prefix,"translations.xml");
-
- if(!translations && language)
+ if(translations)
{
- fprintf(stderr,"Error: Cannot use '--language' option without reading some translations.\n");
- return(1);
+ if(!ExistsFile(translations))
+ {
+ fprintf(stderr,"Error: The '--translations' option specifies a file that does not exist.\n");
+ return(1);
+ }
+ }
+ else
+ {
+ if(ExistsFile(FileName(dirname,prefix,"translations.xml")))
+ translations=FileName(dirname,prefix,"translations.xml");
+ else if(ExistsFile(FileName(DATADIR,NULL,"translations.xml")))
+ translations=FileName(DATADIR,NULL,"translations.xml");
+ else
+ {
+ fprintf(stderr,"Error: The '--translations' option was not used and the default 'translations.xml' does not exist.\n");
+ return(1);
+ }
}
- if(translations && ParseXMLTranslations(translations,language))
+ if(ParseXMLTranslations(translations,language))
{
fprintf(stderr,"Error: Cannot read the translations in the file '%s'.\n",translations);
return(1);
Results *begin,*end;
distance_t distmax=km_to_distance(MAXSEARCH);
distance_t distmin;
- Segment *segment=NULL;
+ index_t segment=NO_SEGMENT;
index_t node1,node2;
if(point_used[point]!=3)
{
distance_t dist1,dist2;
- if((segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2)))
- finish=CreateFakes(OSMNodes,point,segment,node1,node2,dist1,dist2);
+ segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2);
+
+ if(segment!=NO_SEGMENT)
+ finish=CreateFakes(OSMNodes,point,LookupSegment(OSMSegments,segment,1),node1,node2,dist1,dist2);
else
finish=NO_NODE;
}
GetLatLong(OSMNodes,finish,&lat,&lon);
if(IsFakeNode(finish))
- printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,IndexSegment(OSMSegments,segment),node1,node2,
+ printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,segment,node1,node2,
radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
else
printf("Point %d is node %d: %3.6f %4.6f = %2.3f km\n",point,finish,
/*++++++++++++++++++++++++++++++++++++++
- Create a pair of fake segments corresponding to the given segment split in two.
-
- index_t CreateFakes Returns the fake node index (or a real one in special cases).
-
- Nodes *nodes The set of nodes to use.
-
- int point Which of the waypoints is this.
-
- Segment *segment The segment to split.
-
- index_t node1 The first node at the end of this segment.
-
- index_t node2 The second node at the end of this segment.
-
- distance_t dist1 The distance to the first node.
-
- distance_t dist2 The distance to the second node.
- ++++++++++++++++++++++++++++++++++++++*/
-
-index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2)
-{
- index_t fakenode;
- double lat1,lon1,lat2,lon2;
-
- /* Check if we are actually close enough to an existing node */
-
- if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
- return(node1);
-
- if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
- return(node2);
-
- if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
- {
- if(dist1<dist2)
- return(node1);
- else
- return(node2);
- }
-
- /* Create the fake node */
-
- fakenode=point|NODE_SUPER;
-
- GetLatLong(nodes,node1,&lat1,&lon1);
- GetLatLong(nodes,node2,&lat2,&lon2);
-
- if(lat1>3 && lat2<-3)
- lat2+=2*M_PI;
- else if(lat1<-3 && lat2>3)
- lat1+=2*M_PI;
-
- point_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2);
- point_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2);
-
- if(point_lat[point]>M_PI) point_lat[point]-=2*M_PI;
-
- /* Create the first fake segment */
-
- fake_segments[2*point-2]=*segment;
-
- if(segment->node1==node1)
- fake_segments[2*point-2].node1=fakenode;
- else
- fake_segments[2*point-2].node2=fakenode;
-
- fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance);
-
- /* Create the second fake segment */
-
- fake_segments[2*point-1]=*segment;
-
- if(segment->node1==node2)
- fake_segments[2*point-1].node1=fakenode;
- else
- fake_segments[2*point-1].node2=fakenode;
-
- fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance);
-
- return(fakenode);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
- Lookup the latitude and longitude of a fake node.
-
- index_t fakenode The node to lookup.
-
- double *latitude Returns the latitude
-
- double *longitude Returns the longitude.
- ++++++++++++++++++++++++++++++++++++++*/
-
-void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- *latitude =point_lat[realnode];
- *longitude=point_lon[realnode];
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
- Finds the first fake segment associated to a fake node.
-
- Segment *FirstFakeSegment Returns the first fake segment.
-
- index_t fakenode The node to lookup.
- ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *FirstFakeSegment(index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- return(&fake_segments[2*realnode-2]);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
- Finds the next (there can only be two) fake segment associated to a fake node.
-
- Segment *NextFakeSegment Returns the second fake segment.
-
- Segment *segment The first fake segment.
-
- index_t fakenode The node to lookup.
- ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *NextFakeSegment(Segment *segment,index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- if(segment==&fake_segments[2*realnode-2])
- return(&fake_segments[2*realnode-1]);
- else
- return(NULL);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
- Finds the next (there can only be two) fake segment associated to a fake node.
-
- Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists.
-
- index_t node The real node.
-
- index_t fakenode The fake node to lookup.
- ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *ExtraFakeSegment(index_t node,index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node)
- return(&fake_segments[2*realnode-2]);
-
- if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node)
- return(&fake_segments[2*realnode-1]);
-
- return(NULL);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
Print out the usage information.
int detail The level of detail to use - 0 = low, 1 = high.
+
+ const char *argerr The argument that gave the error (if there is one).
+
+ const char *err Other error message (if there is one).
++++++++++++++++++++++++++++++++++++++*/
-static void print_usage(int detail)
+static void print_usage(int detail,const char *argerr,const char *err)
{
fprintf(stderr,
"Usage: router [--help | --help-profile | --help-profile-xml |\n"
" [--weight=<weight>]\n"
" [--height=<height>] [--width=<width>] [--length=<length>]\n");
+ if(argerr)
+ fprintf(stderr,
+ "\n"
+ "Error with command line parameter: %s\n",argerr);
+
+ if(err)
+ fprintf(stderr,
+ "\n"
+ "Error: %s\n",err);
+
if(detail)
fprintf(stderr,
"\n"
"\n"
"--dir=<dirname> The directory containing the routing database.\n"
"--prefix=<name> The filename prefix for the routing database.\n"
- "--profiles=<filename> The name of the profiles (defaults to 'profiles.xml'\n"
- " with '--dirname' and '--prefix' options).\n"
- "--translations=<fname> The filename of the translations (defaults to\n"
- " 'translations.xml' with '--dirname' and '--prefix').\n"
+ "--profiles=<filename> The name of the XML file containing the profiles\n"
+ " (defaults to 'profiles.xml' with '--dir' and\n"
+ " '--prefix' options or the file installed in\n"
+ " '" DATADIR "').\n"
+ "--translations=<fname> The name of the XML file containing the translations\n"
+ " (defaults to 'translations.xml' with '--dir' and\n"
+ " '--prefix' options or the file installed in\n"
+ " '" DATADIR "').\n"
"\n"
"--exact-nodes-only Only route between nodes (don't find closest segment).\n"
"\n"