From: Thibaut GRIDEL Date: Wed, 15 Dec 2010 13:51:44 +0000 (+0100) Subject: Imported Upstream version 1.5 X-Git-Url: http://git.maemo.org/git/?p=routino;a=commitdiff_plain;h=a5b34ad069a52ff6cf981f01667d102292988811 Imported Upstream version 1.5 --- diff --git a/ChangeLog b/ChangeLog index 7c79159..d013a33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,306 @@ +2010-10-30 Andrew M. Bishop + + Version 1.5 released + +2010-10-30 Andrew M. Bishop + + * doc/README.txt, doc/NEWS.txt: Updated for version 1.5. + +2010-10-18 Andrew M. Bishop + + * src/profiles.c: + Use sqrt() function to reduce the effect of property preferences close to 50%. + Ensure that preferences cannot equal zero (error on division). + + * doc/ALGORITHM.txt, doc/INSTALL.txt, doc/USAGE.txt: + Updated with information about the new features. + + * doc/CONFIGURATION.txt, doc/TAGGING.txt: + Add in the footroute and bicycleroute configuration options and route relation + tag processing. + +2010-10-16 Andrew M. Bishop + + * src/files.c: Fixed some comments for recent changes. + +2010-10-09 Andrew M. Bishop + + * xml/routino-profiles.xml: + Add footroute and bicycleroute to the profiles. + + * src/files.c, src/files.h, src/relationsx.c: + The ReOpenFile() function cannot be read/write because it stops the router + running with read-only access to the database. + + * src/nodesx.c, src/relationsx.c, src/segmentsx.c, src/superx.c: + Fix previous check-in on this set of files. + + * src/xmlparse.l: Ensure that comparisons are made with unsigned chars. + +2010-10-03 Andrew M. Bishop + + * src/nodesx.c, src/relationsx.c, src/segmentsx.c, src/superx.c: + Don't try mapping a file if it is zero length (e.g. no super-segments). + + * src/files.c, src/files.h, src/relationsx.c: + Add a function to map a file writeable and use it for updating the ways when + processing route relations. + + * src/relationsx.c: + Avoid self-recursion and adding route information to relations that already have + it. + +2010-09-25 Andrew M. Bishop + + * src/osmparser.c, src/relationsx.c, src/relationsx.h, src/waysx.h: + Apply the route=bicycle or route=foot tags from the relation to all ways + contained in it and to all ways in all sub-relations of it (including recursion + to depth 5). This requires all relations to be stored even if not routes + because they might be included by another relation that is. + + * src/segmentsx.c: Don't sort the (super-)segments if there are none. + + * src/nodesx.c, src/functions.h, src/sorting.c: + Rename the heapsort() function to filesort_heapsort(). + +2010-09-19 Andrew M. Bishop + + * src/files.c, src/files.h, src/nodesx.c, src/segmentsx.c, src/sorting.c, src/waysx.c: + Change the names of the functions used to open files, change the ReOpen function + to open R/W. + + * src/relationsx.c: Remove the sorting of the route relations. + +2010-09-17 Andrew M. Bishop + + * src/nodesx.c, src/segmentsx.c: + Zero the NodesFile and SegmentsFile data structures before writing them (zeros + unused bytes). + + * src/planetsplitter.c, src/waysx.c, src/waysx.h: + Split the sorting of waysx from the compacting so that the route relation + information can be included before compacting. + + * xml/routino-tagging.xml, src/functionsx.h, src/osmparser.c, src/planetsplitter.c: + Parse relations and extract foot and bicycle routes to be added as properties to + the ways. + + * src/types.c, src/types.h: Add footroute and bicycleroute properties. + + * src/relationsx.c, src/relationsx.h: New file. + + * src/typesx.h, src/Makefile: + Add files and datatypes for processing relations. + + * xml/routino-tagging-nomodify.xml, xml/routino-tagging.xsd, src/tagging.c: + Process tags for relations. + +2010-09-16 Andrew M. Bishop + + * src/waysx.c, src/segmentsx.c, src/nodesx.c: + Fix the comment for the Append...() function. + +2010-09-15 Andrew M. Bishop + + * xml/routino-profiles.xml, xml/routino-tagging.xml, xml/routino-translations.xml, + src/output.c, src/translations.c, src/types.c, src/types.h: + Add routing on ferries. + + * src/filedumper.c, src/planetsplitter.c, src/router.c: + Bug fix for last change. + + * src/filedumper.c, src/planetsplitter.c, src/router.c: + Improve the usage information to tell which command line argument was in error. + + * src/profiles.c: + Fix --help-profile-perl option and make perl and JSON outputs more pretty. + + * src/router.c, src/planetsplitter.c: + Usage message has wrong option name. + + * src/xmlparse.l: + Fix last change to make UTF-8 parsing more strict, also added strict conversion + to XML-safe character references. + + * src/translations.c: + Convert translations read from file into XML-safe encodings before using them. + + * src/output.c: HTML file has UTF-8 meta-tag. + + * xml/routino-translations.xml: + Revert to UTF-8 multi-byte representations instead of character references. + +2010-09-14 Andrew M. Bishop + + * src/xmlparse.l: Stricter checking on XML data (Unicode). + +2010-09-05 Andrew M. Bishop + + * xml/Makefile, src/Makefile, doc/Makefile, Makefile: + Move all of the installation pathnames to the top level Makefile and include it + into the lower level makefiles. + + * src/planetsplitter.c, src/router.c, src/tagmodifier.c: + Use the installed tagging.xml, profiles.xml or translations.xml files as the + fallback option if no other given. + +2010-09-04 Andrew M. Bishop + + * xml/routino-translations.xml: + Change German translations from named HTML character encodings to numeric ones + (works in GPX files as well as HTML). + + * xml/routino-translations.xml: + Added Dutch translations (from Jan Jansen). + +2010-08-30 Andrew M. Bishop + + * xml/routino-translations.xml: + Change German translation to UTF-8, add comments indicating the origin of the + two translations. + + * xml/routino-tagging-nomodify.xml: + Relation rules are not allowed at all. + + * xml/Makefile, src/Makefile, doc/Makefile, Makefile: + Added 'install' to top level (and lower) Makefiles. + + * src/ways.h, src/output.c: + Change the names of the functions used to get the highway names. + + * src/filedumper.c: + Only print the way name in OSM output when the way has a name. + Change the names of the functions used to get the highway names. + + * src/profiles.c: Fix bug with writing out JSON profile information. + +2010-08-30 Andrew M. Bishop + + * src/ways.h, src/output.c: + Change the names of the functions used to get the highway names. + + * src/filedumper.c: + Only print the way name in OSM output when the way has a name. + Change the names of the functions used to get the highway names. + + * src/profiles.c: Fix bug with writing out JSON profile information. + +2010-08-04 Andrew M. Bishop + + * src/output.c, src/segmentsx.c, src/types.h, src/fakes.c, src/functions.h, src/nodesx.c, + src/optimiser.c: + Change the way that fake nodes and segments are recognised (allows nearly 4G + nodes to be stored instead of 2G nodes). + +2010-08-03 Andrew M. Bishop + + * src/filedumper.c, src/nodes.h, src/nodesx.c, src/optimiser.c, src/types.h: + Rename the variables that hold the node allowed transports and flags. + +2010-08-02 Andrew M. Bishop + + * xml/routino-tagging-nomodify.xml, xml/routino-tagging.xml, xml/routino-tagging.xsd, + src/filedumper.c, src/nodesx.c, src/nodesx.h, src/optimiser.c, src/osmparser.c, + src/superx.c, src/tagging.c, src/types.h: + Understand node traffic type restrictions. + +2010-07-31 Andrew M. Bishop + + * src/profiles.h, src/types.c, src/types.h, src/ways.h, src/waysx.c: + Rename the wayallow_t type to allow_t (since it applies to nodes as well now). + + * src/filedumper.c, src/nodes.h, src/nodesx.c, src/segmentsx.c, src/types.h: + Add extra information to a node to store turn restrictions and properties. + (Move the super-node bit from the first segment to here.) + + * src/nodesx.c, src/segmentsx.c, src/waysx.c: + Assert if the number of nodes, segments or ways exceeds the legal range of the + index counters. + + * src/nodes.h, src/nodesx.h, src/segments.h, src/segmentsx.h, src/ways.h, src/waysx.h: + Change the data types to index_t where they are counting nodes/segments/ways. + + * src/nodes.h, src/nodesx.h, src/segments.h, src/segmentsx.h, src/ways.h, src/waysx.c, + src/waysx.h: + Ensure that seeking within a file uses a 64-bit offset. + + * src/nodesx.c, src/segmentsx.c, src/superx.c, src/waysx.c: + Remove the assert statements that check the order of calling the functions. + +2010-07-26 Andrew M. Bishop + + * src/filedumper.c, src/nodes.c, src/nodes.h, src/visualiser.c: + Final part of slim mode for the router (node offsets). + +2010-07-24 Andrew M. Bishop + + * src/nodesx.c, src/segmentsx.c, src/waysx.c: + Some tidying up of the writing of the file headers. + + * src/ways.c, src/ways.h, src/waysx.c, src/filedumper.c, src/nodes.c, src/optimiser.c, + src/output.c, src/profiles.c, src/visualiser.c: + Finished slim mode for the router by adding ways. + +2010-07-23 Andrew M. Bishop + + * src/filedumper.c, src/nodes.c, src/nodes.h, src/output.c, src/segments.c, src/segments.h, + src/segmentsx.c: + Added slim mode to the router for segments. + + * src/Makefile: Add the fakes.c file. + + * src/optimiser.c, src/results.c, src/results.h: + Change the results structure to hold the index of the segment instead of a + pointer to it. + + * src/types.h, src/router.c, src/functions.h: + Move the fake nodes and segments to a new file. + + * src/fakes.c: New file. + +2010-07-19 Andrew M. Bishop + + * xml/routino-profiles.xml: + Reduce the "multilane" preference for motor vehicles. Gives too much bias with + previous setting. + +2010-07-15 Andrew M. Bishop + + * src/Makefile, src/filedumper.c, src/nodes.c, src/nodes.h, src/nodesx.c, src/visualiser.c: + Added a slim mode to the router (just for nodes to start with). + +2010-07-14 Andrew M. Bishop + + * src/segmentsx.h, src/superx.c, src/waysx.c, src/waysx.h, src/Makefile, src/nodesx.c, + src/nodesx.h, src/planetsplitter.c, src/segmentsx.c: + Replaced the runtime selection of slim mode / non-slim mode with compile time + selection that gives no runtime overhead but gives two executables. + +2010-07-13 Andrew M. Bishop + + * src/nodesx.c, src/nodesx.h, src/segmentsx.c, src/segmentsx.h, src/waysx.c, src/waysx.h: + Move the functions for slim mode out into the header file and make it inline. + +2010-07-12 Andrew M. Bishop + + * src/files.h: New file. + + * src/segmentsx.h, src/sorting.c, src/superx.c, src/tagging.c, src/tagmodifier.c, + src/translations.c, src/ways.c, src/waysx.c, src/waysx.h, src/filedumper.c, src/files.c, + src/functions.h, src/nodes.c, src/nodesx.c, src/nodesx.h, src/optimiser.c, src/output.c, + src/planetsplitter.c, src/profiles.c, src/router.c, src/segments.c, src/segmentsx.c: + Create a files.h header and put some of the most heavily used files.c functions + into it and make them inline. + +2010-07-11 Andrew M. Bishop + + * src/segmentsx.c, src/segmentsx.h, src/files.c, src/nodesx.c, src/nodesx.h: + Made the planetsplitter slim mode handle the output node and segment data in a + slim way as well as in the input data. + + * src/nodesx.c, src/segmentsx.c, src/waysx.c: + Change the names of the temporary files. + 2010-07-10 Andrew M. Bishop Version 1.4.1 released diff --git a/Makefile b/Makefile index b6ee933..d1d4250 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Header: /home/amb/routino/RCS/Makefile,v 1.3 2010/05/31 12:44:43 amb Exp $ +# $Header: /home/amb/routino/RCS/Makefile,v 1.5 2010/09/05 18:26:57 amb Exp $ # # Makefile # @@ -20,26 +20,43 @@ # along with this program. If not, see . # -FILES=$(wildcard */Makefile) -DIRS=$(foreach f,$(FILES),$(dir $f)) +# Installation locations + +prefix=/usr/local +bindir=$(prefix)/bin +docdir=$(prefix)/doc/routino +datadir=$(prefix)/share/routino + +# Sub-directories and sub-makefiles + +TOPFILES=$(wildcard */Makefile) +TOPDIRS=$(foreach f,$(TOPFILES),$(dir $f)) + +######## + +all$(top): + for dir in $(TOPDIRS); do \ + ( cd $$dir && $(MAKE) $@ ); \ + done ######## -all: - for dir in $(DIRS); do \ +install$(top): all$(top) + for dir in $(TOPDIRS); do \ ( cd $$dir && $(MAKE) $@ ); \ done + @echo "Note: web directory is not installed automatically" ######## -clean: - for dir in $(DIRS); do \ +clean$(top): + for dir in $(TOPDIRS); do \ ( cd $$dir && $(MAKE) $@ ); \ done ######## -distclean: clean - for dir in $(DIRS); do \ +distclean$(top): clean$(top) + for dir in $(TOPDIRS); do \ ( cd $$dir && $(MAKE) $@ ); \ done diff --git a/doc/ALGORITHM.txt b/doc/ALGORITHM.txt index 2432a88..d61f09e 100644 --- a/doc/ALGORITHM.txt +++ b/doc/ALGORITHM.txt @@ -143,12 +143,16 @@ Routing Preferences The other highway properties are specified by the user as a percentage and each highway either has that property or not. The user's property preference is scaled into the range 0.0 (for 0%) - to 2.0 (for 100%) to give a weighted preference, a second + to 1.0 (for 100%) to give a weighted preference, a second "non-property" weighted preference is calcuated in the same way after subtracting the user's preference from 100%. If a segment - has this property then the calculated score is divided by the - weighted preference, if the segment does not have this property - then it is divided by the non-property weighted preference. + has a particular property then the calculated score is divided + by the weighted preference for that property, if the segment + does not have this property then it is divided by the + non-property weighted preference. To ensure that setting + property preferences near 50% do not cause large variations in + routes the highway's preference is found by taking the square + root of the property preference. Implementation -------------- diff --git a/doc/CONFIGURATION.txt b/doc/CONFIGURATION.txt index fa6ae48..3a1a131 100644 --- a/doc/CONFIGURATION.txt +++ b/doc/CONFIGURATION.txt @@ -110,10 +110,12 @@ Routing Profiles - - - - + + + + + + diff --git a/doc/INSTALL.txt b/doc/INSTALL.txt index 123f02c..170fc3a 100644 --- a/doc/INSTALL.txt +++ b/doc/INSTALL.txt @@ -27,26 +27,27 @@ Installation example web pages but is also a useful location to copy the files from for normal use. - The executable files are called 'planetsplitter', 'router' and 'filedumper' - (also 'tagmodifier' for debugging tag modifications). They can be copied - to any location and need no special installation environment. + The executable files are called 'planetsplitter', 'router' and + 'filedumper' (also 'tagmodifier' for debugging tag modifications). They + can be copied to any location and need no special installation + environment. - The default configuration files are called 'profiles.xml', 'tagging.xml' - and 'translations.xml'. The names of the configuration files can be - specified on the command line but by default are also looked for in the - directory that contains the routing database. + The default configuration files are called 'profiles.xml', + 'tagging.xml' and 'translations.xml'. The names of the configuration + files can be specified on the command line but by default are also + looked for in the directory that contains the routing database. Example Web Page ---------------- - The directory 'web' contains a set of files that can be used to create a - working set of web pages with interfaces to the routing algorithm. + The directory 'web' contains a set of files that can be used to create + a working set of web pages with interfaces to the routing algorithm. - The files in the 'web' directory will require copying to a location that - is accessible by a web server. After copying the files some of them - need to be edited; search through the files for lines that contain the - words "EDIT THIS" and make appropriate edits. The files that need + The files in the 'web' directory will require copying to a location + that is accessible by a web server. After copying the files some of + them need to be edited; search through the files for lines that contain + the words "EDIT THIS" and make appropriate edits. The files that need editing are 'paths.pl' (to set the directory paths) and 'router.js' and 'visualiser.js' to limit the range of the visible map (latitude, longitude and zoom). @@ -82,45 +83,48 @@ Configuration of web files + /openlayers/ <- A directory to hold the OpenLayers scripts. | + /routino/ <- The main HTML, Javascript, CSS and CGI files. + | + + /documentation/ <- The HTML version of the Routino documentation. The directory 'bin' will be filled by running the compilation process. For a secure installation the 'bin' directory should be outside of the - web server, the file 'www/routino/paths.pl' contains the path to the 'bin' - directory. + web server, the file 'www/routino/paths.pl' contains the path to the + 'bin' directory. The directory 'data' must contain the Routino database and is also the default location for the configuration files. The routing database is created by downloading the OSM files for the region of interest and - running the 'planetsplitter' program. There is a script in the directory - that will download the OSM files and create the required database. The - script should be edited to set the names of the files to be downloaded. - For a secure installation the 'data' directory should be outside of the - web server, the file 'www/routino/paths.pl' contains the path to the 'data' - directory. - - The directory 'results' is a temporary directory that it used to hold the - GPX and text files generated by the Routino router. The directory must - be writable by the web server process since it is the CGI scripts that - are run by the web server that writes the results here. For a secure - installation the results directory should be outside of the web server, - the file 'www/routino/paths.pl' contains the path to the results - directory. + running the 'planetsplitter' program. There is a script in the + directory that will download the OSM files and create the required + database. The script should be edited to set the names of the files to + be downloaded. For a secure installation the 'data' directory should + be outside of the web server, the file 'www/routino/paths.pl' contains + the path to the 'data' directory. + + The directory 'results' is a temporary directory that it used to hold + the GPX and text files generated by the Routino router. The directory + must be writable by the web server process since it is the CGI scripts + that are run by the web server that writes the results here. For a + secure installation the results directory should be outside of the web + server, the file 'www/routino/paths.pl' contains the path to the + results directory. The directory 'www' and its sub-directories are the only ones that need to be within the web server accessible directory. The directory 'www/openlayers' must be filled with the openlayers Javascript library that can be downloaded from - http://www.openlayers.org/. (This version of Routino has been tested - with OpenLayers library version 2.8). The files must be installed so + http://www.openlayers.org/. (This version of Routino has been tested + with OpenLayers library version 2.9.1). The files must be installed so that the file 'www/openlayers/OpenLayers.js' and the directories - 'www/openlayers/img/', 'www/openlayers/theme/' all exist. There is a script - in the directory that will automatically download and organise the - files. + 'www/openlayers/img/', 'www/openlayers/theme/' all exist. There is a + script in the directory that will automatically download and the files, + create an optimised "OpenLayers.js" and copy the files to the required + locations. The directory 'www/routino' contains the main HTML, Javascript and CSS - files as well as the CGI scripts that perform the server-side + files as well as the CGI scripts that perform the server-side routing functions. The description below lists all of the files that contain editable information. @@ -142,15 +146,18 @@ Configuration of web files visualiser.js The same parameters as in router.js are in this file. + The directory www/routino/documentation contains the HTML version of + the Routino documentation. Configuration of web server --------------------------- - The file 'www/routino/.htaccess' contains all of the Apache configuration - options that are required to get the example web pages running. The - only problem is that because of the way that the "AllowOverride" option - works one of the configuration options has been commented out. This - must be enabled in the main Apache server configuration file. + The file 'www/routino/.htaccess' contains all of the Apache + configuration options that are required to get the example web pages + running. The only problem is that because of the way that the + "AllowOverride" option works one of the configuration options has been + commented out. This must be enabled in the main Apache server + configuration file. -------- diff --git a/doc/Makefile b/doc/Makefile index 5bc7047..08801d4 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,4 +1,4 @@ -# $Header: /home/amb/routino/doc/RCS/Makefile,v 1.2 2010/07/07 17:27:03 amb Exp $ +# $Header: /home/amb/routino/doc/RCS/Makefile,v 1.4 2010/09/05 18:27:07 amb Exp $ # # Documentation directory Makefile # @@ -20,15 +20,20 @@ # along with this program. If not, see . # +# Web file paths + WEBDIR=../web/www/routino/documentation -FILES=html/* +# Files to install + +HTML_FILES=html/* +TXT_FILES=*.txt ######## all : -@[ -d $(WEBDIR) ] && \ - for file in $(FILES); do \ + for file in $(HTML_FILES); do \ if [ ! -f $(WEBDIR)/`basename $$file` ] || [ $$file -nt $(WEBDIR)/`basename $$file` ]; then \ echo cp $$file $(WEBDIR) ;\ cp -f $$file $(WEBDIR) ;\ @@ -37,6 +42,22 @@ all : ######## +install: all + -[ -d $(DESTDIR)$(docdir) ] || mkdir -p $(DESTDIR)$(docdir) + @[ -d $(DESTDIR)$(docdir) ] && \ + for file in $(TXT_FILES); do \ + echo cp $$file $(DESTDIR)$(docdir) ;\ + cp -f $$file $(DESTDIR)$(docdir) ;\ + done + -[ -d $(DESTDIR)$(docdir)/html ] || mkdir -p $(DESTDIR)$(docdir)/html + @[ -d $(DESTDIR)$(docdir)/html ] && \ + for file in $(HTML_FILES); do \ + echo cp $$file $(DESTDIR)$(docdir)/html ;\ + cp -f $$file $(DESTDIR)$(docdir)/html ;\ + done + +######## + clean: rm -f *~ rm -f html/*~ @@ -46,3 +67,8 @@ clean: distclean: clean rm -f $(WEBDIR)/* + +######## + +top=-top +include ../Makefile diff --git a/doc/NEWS.txt b/doc/NEWS.txt index a003671..51071ba 100644 --- a/doc/NEWS.txt +++ b/doc/NEWS.txt @@ -1,3 +1,48 @@ +Version 1.5 of Routino released : Sat Oct 30 2010 +------------------------------------------------- + +Bug fixes: + Check that number of nodes/segments/ways doesn't exceed numerical limits. + Allow 32-bit systems to seek within files larger than 4GB. + Allow nearly 4G nodes to be stored instead of 2G before. + Added rules to makefile for installation (paths specified in top-level). + Stricter checking of UTF-8 in XML files and better UTF-8 output. + Improve error message if parsing of command line options fail. + Fix bugs in router's --help-profile-json and --help-profile-perl options. + Rename heapsort function to allow compilation on Mac OS with no change. + Reduce impact of property preferences close to 50% by using sqrt(). + +Documentation: + Update documentation to reflect changes in program usage and function. + +OSM tagging + Traffic restrictions on nodes are now included in default tagging file. + Added processing for ferry routes (as pseudo-highway type 'ferry'). + Process foot and bicycle route relations to create new properties. + +Configuration Files: + Added Dutch output translations. + Added ferry information to profiles. + Added foot and bicycle route relation processing. + +planetsplitter + The slim mode now includes the output data as well as the temporary data. + The slim mode is now a separate executable and not a command line option. + Traffic restrictions on nodes are now understood when parsing OSM files. + Falls back to installed tagging.xml configuration file as last resort. + +router: + Added a slim mode (as a separate executable and not a command line option). + Traffic will not be routed through a node that does not allow it. + Falls back to installed profiles.xml & translations.xml files as last resort. + +filedumper: + Added a slim mode (as a separate executable and not a command line option). + +Web pages: + Added Dutch translation of router.html. + + Version 1.4.1 of Routino released : Sat Jul 10 2010 --------------------------------------------------- @@ -13,7 +58,7 @@ Documentation: Change URL for website to http://www.routino.org/. Configuration Files: - Added German translations. + Added German output translations. planetsplitter Slight change to algorithm for finding super-nodes. diff --git a/doc/README.txt b/doc/README.txt index 75fe606..9a6e336 100644 --- a/doc/README.txt +++ b/doc/README.txt @@ -102,6 +102,10 @@ Status Version 1.2 of Routino was released on 21st October 2009. Version 1.3 of Routino was released on 21st January 2010. Version 1.4 of Routino was released on 31st May 2010. + Version 1.4.1 of Routino was released on 10th July 2010. + Version 1.5 of Routino was released on 30th October 2010. + + The full version history is available in the NEWS.txt file. License diff --git a/doc/TAGGING.txt b/doc/TAGGING.txt index 6c23d8c..f5ee6d2 100644 --- a/doc/TAGGING.txt +++ b/doc/TAGGING.txt @@ -28,11 +28,21 @@ Tags Recognised After Processing Node Tags And Attributes ------------------------ - None of the node tags are used but the node attributes id, latitude and - longitude of the node. The id atribute is required to associate the - node with the ways and the position attributes are required to locate - the node. + The node attributes id, latitude and longitude are used. The id + atribute is required to associate the node with the ways and the + position attributes are required to locate the node. +Transport Specific Tags +- - - - - - - - - - - - + + One tag is recognised for each of the different modes of transport: + foot, horse, bicycle, wheelchair, moped, motorbike, motorcar, goods, + hgv and psv. These indicate whether the specific type of transport is + allowed to pass through the node or not. + + By default for nodes all types of transport are allowed to pass through + a node and specific tags must be used to remove the permissions for the + transport. Way Tags And Attributes ----------------------- @@ -77,6 +87,10 @@ Transport Specific Tags hgv and psv. These indicate whether the specific type of transport is allowed on the highway or not. + By default for ways no types of transport are allowed to pass along a + highway and specific tags must be used to add the permissions for the + transport. + The name Tag - - - - - - @@ -124,6 +138,24 @@ The tunnel Tag The tunnel tag is used to identify whether a highway is a tunnel and therefore set one of the available properties. +The footroute Tag +- - - - - - - - - + + The footroute tag is used to identify whether a highway is part of a + walking route and therefore set one of the available properties. This + is not a standard OSM tag and is normally added to the individual + highways by looking for route relations that are designated for foot + access. + +The bicycleroute Tag +- - - - - - - - - - + + The bicycleroute tag is used to identify whether a highway is part of a + bicycle route and therefore set one of the available properties. This + is not a standard OSM tag and is normally added to the individual + highways by looking for route relations that are designated for bicycle + access. + The oneway Tag - - - - - - - @@ -142,17 +174,17 @@ The maxweight Tag - - - - - - - - - The maxweight tag is used to specify the maximum weight of any traffic - on the way. In other words this must be set to the heaviest weight - allowed on the way (for example a bridge) in tonnes. If the tag value - contains "kg" then it is assumed that the value is in these units and - converted to tonnes. + on the highway. In other words this must be set to the heaviest weight + allowed on the highway (for example a bridge) in tonnes. If the tag + value contains "kg" then it is assumed that the value is in these units + and converted to tonnes. The maxheight Tag - - - - - - - - - The maxheight tag is used to specify the maximum height of any traffic - on the way. In other words this must be set to the lowest height of - anything above the way (like a bridge) in metres. If the tag value + on the highway. In other words this must be set to the lowest height of + anything above the highway (like a bridge) in metres. If the tag value contains a measurement in feet or feet and inches then attempts are made to convert this to metres. @@ -160,23 +192,39 @@ The maxwidth Tag - - - - - - - - The maxwidth tag is used to specify the maximum width of any traffic on - the way. This must be set to the minimum width of the contraints at the - wayside in metres. If the tag value contains a measurement in feet or - feet and inches then attempts are made to convert this to metres. + the highway. This must be set to the minimum width of the contraints at + the wayside in metres. If the tag value contains a measurement in feet + or feet and inches then attempts are made to convert this to metres. The maxlength Tag - - - - - - - - - The maxlength tag is used to specify the maximum length of any traffic - on the way (usually from a traffic sign) in metres. If the tag value - contains a measurement in feet or feet and inches then attempts are - made to convert this to metres. - + on the highway (usually from a traffic sign) in metres. If the tag + value contains a measurement in feet or feet and inches then attempts + are made to convert this to metres. Relation Tags And Attributes ---------------------------- - Currently no relation tags or attributes are used. + The tags from the relations are used to associate more properties with + the highways that are part of that relation. The id attribute is used + so that relations that are members of other relations can be + identified. + +The footroute Tag +- - - - - - - - - + + The footroute tag is used to identify whether a relation defines a + walking route and therefore should be applied to the individual member + highways. + +The bicycleroute Tag +- - - - - - - - - - + + The bicycleroute tag is used to identify whether a relation defines a + bicycle route and therefore should be applied to the individual member + highways. Tag Transformations @@ -191,8 +239,45 @@ Tag Transformations Node Tag Transformations ------------------------ - No transformations are applicable since no node tags are recognised. +Barrier Defaults +- - - - - - - - + + The first part of the tag transformations is to decide on defaults for + each type of node. This uses the barrier tag in the OSM file and + converts it into a default set of disallowed transport types. + + Barrier foot horse wheelchair bicycle moped motorbike motorcar goods hgv psv + ------- ---- ----- ---------- ------- ----- --------- -------- ----- --- --- + bollard yes yes yes yes yes yes no no no no + kissing_gate yes no no no no no no no no no + stile yes no no no no no no no no no + turnstile yes no no no no no no no no no +Generic Access Permissions +- - - - - - - - - - - - - + + The access tag is used to specify the default access restrictions + through the node. If the tag value is no or private then all transport + types are denied access (later tag transformation rules may add + specific transport types back again). + +Other Access Permissions +- - - - - - - - - - - - + + A tag named vehicle means any of the bicycle, moped, motorbike, + motorcar, goods, hgv and psv transport types. A tag named motor_vehicle + is transformed to mean any vehicle except a bicycle. + +Specific Access Permissions +- - - - - - - - - - - - - - + + The final part of the access permissions is to use the specific + transport type tags. + + One tag is recognised for each of the different modes of transport: + foot, horse, bicycle, wheelchair, moped, motorbike, motorcar, goods, + hgv and psv. These indicate whether the specific type of transport is + allowed through the node or not. Way Tag Transformations ----------------------- @@ -272,9 +357,9 @@ Generic Access Permissions - - - - - - - - - - - - - The access tag is used to specify the default access restrictions on - the way. If the tag value is "no" or "private" then all transport types - are denied access (later tag transformation rules may add specific - transport types back again). + the highway. If the tag value is "no" or "private" then all transport + types are denied access (later tag transformation rules may add + specific transport types back again). Other Access Permissions - - - - - - - - - - - - @@ -344,7 +429,22 @@ Highway Names and References Relation Tag Transformations ---------------------------- - No transformations are applicable since no relation tags are recognised. +Routes +- - - + + The route tag can be used to determine whether a relation is part of a + walking of bicycle route so that the footroute and bicycleroute + properties can be applied to the highways that make up that relation. + + The tag transformations that are applied for route relations are + defined in the table below. + + Relation Tag footroute Property bicycleroute Property + foot yes no + walking yes no + hiking yes no + bicycle no yes + bicycle;foot or foot;bicycle yes yes -------- diff --git a/doc/USAGE.txt b/doc/USAGE.txt index 48721bd..402810f 100644 --- a/doc/USAGE.txt +++ b/doc/USAGE.txt @@ -19,7 +19,7 @@ planetsplitter Usage: planetsplitter [--help] [--dir=] [--prefix=] - [--slim] [--sort-ram-size=] + [--sort-ram-size=] [--tmpdir=] [--parse-only | --process-only] [--max-iterations=] @@ -37,18 +37,10 @@ planetsplitter Sets the filename prefix for the files that are created. Defaults to no prefix. - --slim - Selects a mode of operation that uses less memory and will - therefore work where virtual memory is very limited or - unavailable. Selecting this option will cause raw data to be - held in disk files with only indexes in RAM. Not using this - option will still use disk files but only for sequential access - and the files are memory mapped for random access. - --sort-ram-size= Specifies the amount of RAM (in MB) to use for sorting the data. - If not specified then 64 MB will be used if the '--slim' option - is specified or 256 MB otherwise. + If not specified then 64 MB will be used in slim mode or 256 MB + otherwise. --tmpdir= Specifies the name of the directory to store the temporary disk @@ -69,8 +61,12 @@ planetsplitter enough. --tagging= - The name of the XML file containing the tagging rules (defaults - to 'tagging.xml' with '--dirname' and '--prefix' options). + Sets the filename containing the list of tagging rules in XML + format for the parsing the input files. If the file doesn't + exist then dirname, prefix and "profiles.xml" will be combined + and used, if that doesn't exist then the file + '/usr/local/share/routino/profiles.xml' (or custom installation + location) will be used. ... Specifies the filename(s) to read data from, by default data is @@ -81,6 +77,15 @@ planetsplitter achieved by editing the tagging rules file to not output unwwanted data. + Note: In version 1.5 of Routino the --slim option has been removed but + at compilation time a separate program called planetsplitter-slim is + created that operates in slim mode. In slim mode the temporary files + and database files are read as needed rather than being mapped into + memory. This allows a database size greater than 2 GB on 32-bit + machines or usage with little or no virtual memory (e.g. some virtual + machines). The penalty for this is that the program takes about four + times as long to run. + Example usage: ./planetsplitter --dir=data --prefix=gb great_britain.osm @@ -146,18 +151,19 @@ router Defaults to no prefix. --profiles= - Sets the filename containing the list of profiles in XML format. - If the file doesn't exist then dirname, prefix and + Sets the filename containing the list of routing profiles in XML + format. If the file doesn't exist then dirname, prefix and "profiles.xml" will be combined and used, if that doesn't exist - then the command line must contain all relevant profile - information. + then the file '/usr/local/share/routino/profiles.xml' (or custom + installation location) will be used. --translations= Sets the filename containing the list of translations in XML format for the output files. If the file doesn't exist then dirname, prefix and "translations.xml" will be combined and - used, if that doesn't exist then no file will be read and no - language can be selected. + used, if that doesn't exist then the file + '/usr/local/share/routino/translations.xml' (or custom + installation location) will be used. --exact-nodes-only When processing the specified latitude and longitude points only @@ -241,6 +247,7 @@ router + cycleway = Cycleway + path = Path + steps = Steps + + ferry = Ferry Default value depends on the profile selected by the --transport option. @@ -258,6 +265,8 @@ router + multilane = Multiple lanes + bridge = Bridge + tunnel = Tunnel + + footroute = A route marked for foot travel + + bicycleroute = A route marked for bicycle travel Default value depends on the profile selected by the --transport option. @@ -287,6 +296,11 @@ router that the length limit on the highway is not exceeded. Default value depends on the profile selected by the --transport option. + Note: In version 1.5 of Routino a slim option has been added and at + compilation time a separate program called router-slim is created that + operates in slim mode. In slim mode the database files are read as + needed rather than being mapped into memory. + The meaning of the parameter in the command line options is slightly different for the highway preferences and the property preferences. For the highway preference consider the choice between two @@ -294,11 +308,14 @@ router shortest route. If highway A has a preference of 100% and highway B has a preference of 90% then highway A will be chosen even if it is up to 11% longer (100/90 = 111%). For the highway properties each highway - either has a particular property or not. If the preference for highways - with the property is 60% then the preference for highways without the - property is 40%. The overall preference for the highway is the product - of the highway preference and the preference for highways with (or - without) each property that the highway has (or doesn't have). + either has a particular property or not. If the preference for the + property is 60% then a highway with the property has a preference of + 77% (sqrt(60%)) and one without has a preference of 63% + (sqrt(100-60%)). A highway with the property will be chosen even if it + is up to 22% longer than one without the property (77/63 = 122%). The + overall preference for each highway segment is the product of the + preference for the highway type and all of the preferences for the + highway properties. Example usage (motorbike journey, scenic route, not very fast): @@ -398,6 +415,11 @@ filedumper --lonmin= --lonmax= The range of longitudes to dump the data for. + Note: In version 1.5 of Routino a slim option has been added and at + compilation time a separate program called filedumper-slim is created + that operates in slim mode. In slim mode the database files are read as + needed rather than being mapped into memory. + tagmodifier ----------- diff --git a/doc/html/algorithm.html b/doc/html/algorithm.html index cec599f..3890b77 100644 --- a/doc/html/algorithm.html +++ b/doc/html/algorithm.html @@ -174,12 +174,15 @@ minimising the length.
Highway properties
The other highway properties are specified by the user as a percentage and each highway either has that property or not. The user's property preference - is scaled into the range 0.0 (for 0%) to 2.0 (for 100%) to give a weighted + is scaled into the range 0.0 (for 0%) to 1.0 (for 100%) to give a weighted preference, a second "non-property" weighted preference is calcuated in the same way after subtracting the user's preference from 100%. If a segment has - this property then the calculated score is divided by the weighted preference, - if the segment does not have this property then it is divided by the - non-property weighted preference. + a particular property then the calculated score is divided by the weighted + preference for that property, if the segment does not have this property then + it is divided by the non-property weighted preference. To ensure that setting + property preferences near 50% do not cause large variations in routes the + highway's preference is found by taking the square root of the property + preference.

Implementation

diff --git a/doc/html/configuration.html b/doc/html/configuration.html index 98fa009..6acc522 100644 --- a/doc/html/configuration.html +++ b/doc/html/configuration.html @@ -47,7 +47,7 @@

XML Configuration Files

-New in version 1.4 of Routino are the use of configuration files to allow more +New in version 1.4 of Routino is the use of configuration files to allow more information to be provided to the programs at run-time. The configuration files that are used are:
    @@ -167,10 +167,12 @@ foot is shown below: <preference highway="steps" percent="80" /> </preferences> <properties> - <property type="paved" percent="50" /> - <property type="multilane" percent="25" /> - <property type="bridge" percent="50" /> - <property type="tunnel" percent="50" /> + <property type="paved" percent="50" /> + <property type="multilane" percent="25" /> + <property type="bridge" percent="50" /> + <property type="tunnel" percent="50" /> + <property type="footroute" percent="55" /> + <property type="bicycleroute" percent="55" /> </properties> <restrictions> <oneway obey="0" /> diff --git a/doc/html/tagging.html b/doc/html/tagging.html index 5af6812..8565511 100644 --- a/doc/html/tagging.html +++ b/doc/html/tagging.html @@ -75,9 +75,23 @@ are recognised as being affirmative and any other value is ignored.

    Node Tags And Attributes

    -None of the node tags are used but the node attributes id, latitude -and longitude of the node. The id atribute is required to associate the -node with the ways and the position attributes are required to locate the node. +The node attributes id, latitude and longitude are +used. The id atribute is required to associate the node with the ways and the +position attributes are required to locate the node. + + +

    Transport Specific Tags

    + +One tag is recognised for each of the different modes of transport: foot, +horse, bicycle, wheelchair, moped, +motorbike, motorcar, goods, hgv +and psv. These indicate whether the specific type of transport is +allowed to pass through the node or not. + +

    + +By default for nodes all types of transport are allowed to pass through a node +and specific tags must be used to remove the permissions for the transport.

    Way Tags And Attributes

    @@ -133,6 +147,11 @@ One tag is recognised for each of the different modes of transport: footpsv. These indicate whether the specific type of transport is allowed on the highway or not. +

    + +By default for ways no types of transport are allowed to pass along a highway +and specific tags must be used to add the permissions for the transport. +

    The name Tag

    @@ -182,13 +201,29 @@ The tunnel tag is used to identify whether a highway is a tunnel and therefore set one of the available properties. -

    The oneway Tag

    +

    The footroute Tag

    + +The footroute tag is used to identify whether a highway is part of a +walking route and therefore set one of the available properties. This is not a +standard OSM tag and is normally added to the individual highways by looking for +route relations that are designated for foot access. + + +

    The bicycleroute Tag

    + +The bicycleroute tag is used to identify whether a highway is part of a +bicycle route and therefore set one of the available properties. This is not a +standard OSM tag and is normally added to the individual highways by looking for +route relations that are designated for bicycle access. + + +

    The oneway Tag

    The oneway tag is used to specify that traffic is only allowed to travel in one direction. -

    The maxspeed Tag

    +

    The maxspeed Tag

    The maxspeed tag is used to specify the maximum speed limit on the highway; this is always measured in km/hr in OpenStreetMap data. If the tag @@ -196,42 +231,56 @@ value contains "mph" then it is assumed to be a value in those units and converted to km/hr. -

    The maxweight Tag

    +

    The maxweight Tag

    The maxweight tag is used to specify the maximum weight of any traffic -on the way. In other words this must be set to the heaviest weight allowed on -the way (for example a bridge) in tonnes. If the tag value contains "kg" then -it is assumed that the value is in these units and converted to tonnes. +on the highway. In other words this must be set to the heaviest weight allowed +on the highway (for example a bridge) in tonnes. If the tag value contains "kg" +then it is assumed that the value is in these units and converted to tonnes. -

    The maxheight Tag

    +

    The maxheight Tag

    The maxheight tag is used to specify the maximum height of any traffic -on the way. In other words this must be set to the lowest height of anything -above the way (like a bridge) in metres. If the tag value contains a -measurement in feet or feet and inches then attempts are made to convert this to -metres. +on the highway. In other words this must be set to the lowest height of +anything above the highway (like a bridge) in metres. If the tag value contains +a measurement in feet or feet and inches then attempts are made to convert this +to metres. -

    The maxwidth Tag

    +

    The maxwidth Tag

    The maxwidth tag is used to specify the maximum width of any traffic on -the way. This must be set to the minimum width of the contraints at the wayside -in metres. If the tag value contains a measurement in feet or feet and inches -then attempts are made to convert this to metres. +the highway. This must be set to the minimum width of the contraints at the +wayside in metres. If the tag value contains a measurement in feet or feet and +inches then attempts are made to convert this to metres. -

    The maxlength Tag

    +

    The maxlength Tag

    The maxlength tag is used to specify the maximum length of any traffic -on the way (usually from a traffic sign) in metres. If the tag value contains a -measurement in feet or feet and inches then attempts are made to convert this to -metres. +on the highway (usually from a traffic sign) in metres. If the tag value +contains a measurement in feet or feet and inches then attempts are made to +convert this to metres.

    Relation Tags And Attributes

    -Currently no relation tags or attributes are used. +The tags from the relations are used to associate more properties with the +highways that are part of that relation. The id attribute is used so +that relations that are members of other relations can be identified. + + +

    The footroute Tag

    + +The footroute tag is used to identify whether a relation defines a +walking route and therefore should be applied to the individual member highways. + + +

    The bicycleroute Tag

    + +The bicycleroute tag is used to identify whether a relation defines a +bicycle route and therefore should be applied to the individual member highways.

    Tag Transformations

    @@ -243,7 +292,106 @@ sequence and this section of the document is arranged in the same order.

    Node Tag Transformations

    -No transformations are applicable since no node tags are recognised. +

    Barrier Defaults

    + +The first part of the tag transformations is to decide on defaults for each type +of node. This uses the barrier tag in the OSM file and converts it into +a default set of disallowed transport types. + +

    + + + + + + + + +
    Transport types through different barrier types
    Barrier + foot + horse + bicycle + wheelchair + moped + motorbike + motorcar + goods + hgv + psv +
    bollard + yes + yes + yes + yes + yes + yes + no + no + no + no +
    kissing_gate + yes + no + no + no + no + no + no + no + no + no +
    stile + yes + no + no + no + no + no + no + no + no + no +
    turnstile + yes + no + no + no + no + no + no + no + no + no +
    + +

    Generic Access Permissions

    + +The access tag is used to specify the default access restrictions +through the node. If the tag value is no or private then all +transport types are denied access (later tag transformation rules may add +specific transport types back again). + + +

    Other Access Permissions

    + +A tag named vehicle means any of the bicycle, moped, +motorbike, motorcar, goods, hgv +and psv transport types. A tag named motor_vehicle is +transformed to mean any vehicle except a bicycle. + + +

    Specific Access Permissions

    + +The final part of the access permissions is to use the specific transport type +tags. + +

    + +One tag is recognised for each of the different modes of transport: foot, +horse, bicycle, wheelchair, moped, +motorbike, motorcar, goods, hgv +and psv. These indicate whether the specific type of transport is +allowed through the node or not.

    Way Tag Transformations

    @@ -252,9 +400,9 @@ No transformations are applicable since no node tags are recognised.

    Highway Defaults

    The first part of the tag transformations is to decide on defaults for each type -of highway. This uses the highway tag in the OSM file and maps it into one of -the highway tags that are recognised by Routino, defining the default allowed -transport types and adding a number of properties. +of highway. This uses the highway tag in the OSM file and maps it into +one of the highway tags that are recognised by Routino, defining the +default allowed transport types and adding a number of properties.

    @@ -542,7 +690,7 @@ highway type.

    Generic Access Permissions

    The access tag is used to specify the default access restrictions on -the way. If the tag value is "no" or "private" then all transport types are +the highway. If the tag value is "no" or "private" then all transport types are denied access (later tag transformation rules may add specific transport types back again). @@ -634,7 +782,46 @@ the output.

    Relation Tag Transformations

    -No transformations are applicable since no relation tags are recognised. +

    Routes

    + +The route tag can be used to determine whether a relation is part of a +walking of bicycle route so that the footroute and bicycleroute properties can +be applied to the highways that make up that relation. + +

    + +The tag transformations that are applied for route relations are defined in the +table below. + +

    + + + + + + + + + +
    Route properties from different route types
    Relation Tag + footroute Property + bicycleroute Property +
    foot + yes + no +
    walking + yes + no +
    hiking + yes + no +
    bicycle + no + yes +
    bicycle;foot or foot;bicycle + yes + yes +
    diff --git a/doc/html/usage.html b/doc/html/usage.html index dc75888..74e33f7 100644 --- a/doc/html/usage.html +++ b/doc/html/usage.html @@ -62,7 +62,7 @@ database that is used for routing.

     Usage: planetsplitter [--help]
                           [--dir=<dirname>] [--prefix=<name>]
    -                      [--slim] [--sort-ram-size=<size>]
    +                      [--sort-ram-size=<size>]
                           [--tmpdir=<dirname>]
                           [--parse-only | --process-only]
                           [--max-iterations=<number>]
    @@ -79,16 +79,9 @@ Usage: planetsplitter [--help]
       
    --prefix=<name>
    Sets the filename prefix for the files that are created. Defaults to no prefix. -
    --slim -
    Selects a mode of operation that uses less memory and will therefore work - where virtual memory is very limited or unavailable. Selecting this option - will cause raw data to be held in disk files with only indexes in RAM. Not - using this option will still use disk files but only for sequential access - and the files are memory mapped for random access.
    --sort-ram-size=<size>
    Specifies the amount of RAM (in MB) to use for sorting the data. If not - specified then 64 MB will be used if the '--slim' option is specified or 256 - MB otherwise. + specified then 64 MB will be used in slim mode or 256 MB otherwise.
    --tmpdir=<dirname>
    Specifies the name of the directory to store the temporary disk files. If not specified then it defaults to either the value of the --dir option or the @@ -103,8 +96,11 @@ Usage: planetsplitter [--help]
    The maximum number of iterations to use when generating super-nodes and super-segments. Defaults to 10 which is normally enough.
    --tagging=<filename> -
    The name of the XML file containing the tagging rules (defaults to - 'tagging.xml' with '--dirname' and '--prefix' options). +
    Sets the filename containing the list of tagging rules in XML format for + the parsing the input files. If the file doesn't exist then dirname, prefix + and "profiles.xml" will be combined and used, if that doesn't exist then the + file '/usr/local/share/routino/profiles.xml' (or custom installation + location) will be used.
    <filename.osm> ...
    Specifies the filename(s) to read data from, by default data is read from the standard input. @@ -116,6 +112,15 @@ Usage: planetsplitter [--help] achieved by editing the tagging rules file to not output unwwanted data.

    +Note: In version 1.5 of Routino the --slim option has been removed but at +compilation time a separate program called planetsplitter-slim is +created that operates in slim mode. In slim mode the temporary files and +database files are read as needed rather than being mapped into memory. This +allows a database size greater than 2 GB on 32-bit machines or usage with little +or no virtual memory (e.g. some virtual machines). The penalty for this is that +the program takes about four times as long to run. + +

    Example usage:

    @@ -178,15 +183,17 @@ Usage: router [--help | --help-profile | --help-profile-xml |
       
    Sets the filename prefix for the files in the local database. Defaults to no prefix.
    --profiles=<filename> -
    Sets the filename containing the list of profiles in XML format. If the - file doesn't exist then dirname, prefix and "profiles.xml" will be combined - and used, if that doesn't exist then the command line must contain all - relevant profile information. +
    Sets the filename containing the list of routing profiles in XML format. + If the file doesn't exist then dirname, prefix and "profiles.xml" will be + combined and used, if that doesn't exist then the file + '/usr/local/share/routino/profiles.xml' (or custom installation location) + will be used.
    --translations=<filename>
    Sets the filename containing the list of translations in XML format for the output files. If the file doesn't exist then dirname, prefix and - "translations.xml" will be combined and used, if that doesn't exist then no - file will be read and no language can be selected. + "translations.xml" will be combined and used, if that doesn't exist then the + file '/usr/local/share/routino/translations.xml' (or custom installation + location) will be used.
    --exact-nodes-only
    When processing the specified latitude and longitude points only select the nearest node instead of finding the nearest point within a segment @@ -266,10 +273,12 @@ Usage: router [--help | --help-profile | --help-profile-xml | property The value of <property> can be selected from:
      -
    • paved = Paved (suitable for normal wheels) -
    • multilane = Multiple lanes -
    • bridge = Bridge -
    • tunnel = Tunnel +
    • paved = Paved (suitable for normal wheels) +
    • multilane = Multiple lanes +
    • bridge = Bridge +
    • tunnel = Tunnel +
    • footroute = A route marked for foot travel +
    • bicycleroute = A route marked for bicycle travel
    Default value depends on the profile selected by the --transport option.
    --oneway=[0|1] @@ -295,6 +304,12 @@ Usage: router [--help | --help-profile | --help-profile-xml |

    +Note: In version 1.5 of Routino a slim option has been added and at +compilation time a separate program called router-slim is created that +operates in slim mode. In slim mode the database files are read as needed +rather than being mapped into memory. + +

    The meaning of the <preference> parameter in the command line options is slightly different for the highway preferences and the property preferences. For the highway preference consider the choice between two possible highways @@ -302,10 +317,12 @@ between the start and finish when looking for the shortest route. If highway A has a preference of 100% and highway B has a preference of 90% then highway A will be chosen even if it is up to 11% longer (100/90 = 111%). For the highway properties each highway either has a particular property or not. If the -preference for highways with the property is 60% then the preference for -highways without the property is 40%. The overall preference for the highway is -the product of the highway preference and the preference for highways with (or -without) each property that the highway has (or doesn't have). +preference for the property is 60% then a highway with the property has a +preference of 77% (sqrt(60%)) and one without has a preference of 63% +(sqrt(100-60%)). A highway with the property will be chosen even if it is up to +22% longer than one without the property (77/63 = 122%). The overall preference +for each highway segment is the product of the preference for the highway type +and all of the preferences for the highway properties.

    Example usage (motorbike journey, scenic route, not very fast): @@ -398,6 +415,12 @@ Usage: filedumper [--help] +

    +Note: In version 1.5 of Routino a slim option has been added and at +compilation time a separate program called filedumper-slim is created +that operates in slim mode. In slim mode the database files are read as needed +rather than being mapped into memory. +

    tagmodifier

    diff --git a/src/Makefile b/src/Makefile index 49e583e..81332d4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -# $Header: /home/amb/routino/src/RCS/Makefile,v 1.36 2010/07/09 17:43:00 amb Exp $ +# $Header: /home/amb/routino/src/RCS/Makefile,v 1.42 2010/09/17 17:42:20 amb Exp $ # # Source code Makefile # @@ -20,21 +20,25 @@ # along with this program. If not, see . # -# Programs +# Web file paths + +WEBDIR=../web/bin + +# Compilation programs CC=gcc LD=gcc LEX=flex -# Program options +# Compilation program options CFLAGS=-Wall -Wmissing-prototypes #CFLAGS+= -Wextra -pedantic -std=c99 LDFLAGS=-lm -lc CFLAGS+= -O3 -#CFLAGS+= -O0 -g +CFLAGS+= -O0 -g #CFLAGS+= -pg #CFLAGS+= --coverage @@ -53,9 +57,7 @@ FLAGS64=-D_FILE_OFFSET_BITS=64 C=$(wildcard *.c) D=$(foreach f,$(C),$(addprefix .deps/,$(addsuffix .d,$(basename $f)))) -EXE=planetsplitter router filedumper tagmodifier - -WEBDIR=../web/bin +EXE=planetsplitter planetsplitter-slim router router-slim filedumper filedumper-slim tagmodifier ######## @@ -72,7 +74,7 @@ all : $(EXE) ######## PLANETSPLITTER_OBJ=planetsplitter.o \ - nodesx.o segmentsx.o waysx.o superx.o \ + nodesx.o segmentsx.o waysx.o relationsx.o superx.o \ ways.o types.o \ files.o \ results.o queue.o sorting.o \ @@ -83,26 +85,60 @@ planetsplitter : $(PLANETSPLITTER_OBJ) ######## +PLANETSPLITTER_SLIM_OBJ=planetsplitter-slim.o \ + nodesx-slim.o segmentsx-slim.o waysx-slim.o relationsx-slim.o superx-slim.o \ + ways.o types.o \ + files.o \ + results.o queue.o sorting.o \ + xmlparse.o tagging.o osmparser.o + +planetsplitter-slim : $(PLANETSPLITTER_SLIM_OBJ) + $(LD) $(PLANETSPLITTER_SLIM_OBJ) -o $@ $(LDFLAGS) + +######## + ROUTER_OBJ=router.o \ - nodes.o segments.o ways.o types.o \ + nodes.o segments.o ways.o types.o fakes.o \ + optimiser.o output.o \ files.o profiles.o xmlparse.o \ - optimiser.o output.o results.o queue.o translations.o + results.o queue.o translations.o router : $(ROUTER_OBJ) $(LD) $(ROUTER_OBJ) -o $@ $(LDFLAGS) ######## +ROUTER_SLIM_OBJ=router-slim.o \ + nodes-slim.o segments-slim.o ways-slim.o types.o fakes.o \ + optimiser-slim.o output-slim.o \ + files.o profiles.o xmlparse.o \ + results.o queue.o translations.o + +router-slim : $(ROUTER_SLIM_OBJ) + $(LD) $(ROUTER_SLIM_OBJ) -o $@ $(LDFLAGS) + +######## + FILEDUMPER_OBJ=filedumper.o \ nodes.o segments.o ways.o types.o \ - files.o xmlparse.o \ - visualiser.o + visualiser.o \ + files.o xmlparse.o filedumper : $(FILEDUMPER_OBJ) $(LD) $(FILEDUMPER_OBJ) -o $@ $(LDFLAGS) ######## +FILEDUMPER_SLIM_OBJ=filedumper-slim.o \ + nodes-slim.o segments-slim.o ways-slim.o types.o \ + visualiser-slim.o \ + files.o xmlparse.o + +filedumper-slim : $(FILEDUMPER_SLIM_OBJ) + $(LD) $(FILEDUMPER_SLIM_OBJ) -o $@ $(LDFLAGS) + +######## + TAGMODIFIER_OBJ=tagmodifier.o \ files.o \ xmlparse.o tagging.o @@ -120,7 +156,20 @@ xmlparse.c : xmlparse.l ######## %.o : %.c - $(CC) -c $(CFLAGS) $(FLAGS64) $< -o $@ -MMD -MP -MF $(addprefix .deps/,$(addsuffix .d,$(basename $<))) + $(CC) -c $(CFLAGS) $(FLAGS64) -DSLIM=0 -DDATADIR=\"$(datadir)\" $< -o $@ -MMD -MP -MF $(addprefix .deps/,$(addsuffix .d,$(basename $<))) + +%-slim.o : %.c + $(CC) -c $(CFLAGS) $(FLAGS64) -DSLIM=1 -DDATADIR=\"$(datadir)\" $< -o $@ -MMD -MP -MF $(addprefix .deps/,$(addsuffix .d,$(basename $<))) + +######## + +install: all + -[ -d $(DESTDIR)$(bindir) ] || mkdir -p $(DESTDIR)$(bindir) + @[ -d $(DESTDIR)$(bindir) ] && \ + for file in $(EXE); do \ + echo cp $$file $(DESTDIR)$(bindir) ;\ + cp -f $$file $(DESTDIR)$(bindir) ;\ + done ######## @@ -152,3 +201,8 @@ include $(D) ######## .FORCE : + +######## + +top=-top +include ../Makefile diff --git a/src/fakes.c b/src/fakes.c new file mode 100644 index 0000000..4d4df3c --- /dev/null +++ b/src/fakes.c @@ -0,0 +1,236 @@ +/*************************************** + $Header: /home/amb/routino/src/RCS/fakes.c,v 1.2 2010/08/04 16:44:51 amb Exp $ + + Fake node and segment generation. + + Part of the Routino routing software. + ******************/ /****************** + This file Copyright 2008-2010 Andrew M. Bishop + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + ***************************************/ + + +#include "types.h" +#include "nodes.h" +#include "segments.h" + +#include "functions.h" + + +/*+ 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. +*/ +static double fake_lon[NWAYPOINTS+1],fake_lat[NWAYPOINTS+1]; + + +/*++++++++++++++++++++++++++++++++++++++ + 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(dist1km_to_distance(MINSEGMENT)) + return(node1); + + if(dist2km_to_distance(MINSEGMENT)) + return(node2); + + if(dist13 && lat2<-3) + lat2+=2*M_PI; + else if(lat1<-3 && lat2>3) + lat1+=2*M_PI; + + fake_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2); + fake_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2); + + if(fake_lat[point]>M_PI) fake_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_FAKE; + + *latitude =fake_lat[realnode]; + *longitude=fake_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_FAKE; + + 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_FAKE; + + if(segment==&fake_segments[2*realnode-2]) + return(&fake_segments[2*realnode-1]); + else + return(NULL); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Finds the fake segment between a node and 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_FAKE; + + 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); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Lookup a fake segment given its index. + + Segment *LookupFakeSegment Returns a pointer to the segment. + + index_t fakesegment The index of the fake segment. + ++++++++++++++++++++++++++++++++++++++*/ + +Segment *LookupFakeSegment(index_t fakesegment) +{ + index_t realsegment=fakesegment-SEGMENT_FAKE; + + return(&fake_segments[realsegment]); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Find the fake index of a fake segment. + + index_t IndexFakeSegment Returns the fake segment. + + Segment *segment The segment to look for. + ++++++++++++++++++++++++++++++++++++++*/ + +index_t IndexFakeSegment(Segment *segment) +{ + index_t realsegment=segment-&fake_segments[0]; + + return(realsegment+SEGMENT_FAKE); +} diff --git a/src/filedumper.c b/src/filedumper.c index 463ab19..c1c67ec 100644 --- a/src/filedumper.c +++ b/src/filedumper.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/filedumper.c,v 1.43 2010/05/30 12:52:16 amb Exp $ + $Header: /home/amb/routino/src/RCS/filedumper.c,v 1.54 2010/09/15 18:19:36 amb Exp $ Memory file dumper. @@ -30,11 +30,12 @@ #include #include "types.h" -#include "functions.h" -#include "visualiser.h" #include "nodes.h" #include "segments.h" #include "ways.h" + +#include "files.h" +#include "visualiser.h" #include "xmlparse.h" @@ -51,7 +52,7 @@ static void print_tail_osm(void); static char *RFC822Date(time_t t); -static void print_usage(int detail); +static void print_usage(int detail,const char *argerr,const char *err); /*++++++++++++++++++++++++++++++++++++++ @@ -78,7 +79,7 @@ int main(int argc,char** argv) for(arg=1;argnumber); - printf("Number(super)=%9d\n",OSMNodes->snumber); + printf("Number =%9d\n",OSMNodes->file.number); + printf("Number(super)=%9d\n",OSMNodes->file.snumber); printf("\n"); - printf("Lat bins= %4d\n",OSMNodes->latbins); - printf("Lon bins= %4d\n",OSMNodes->lonbins); + printf("Lat bins= %4d\n",OSMNodes->file.latbins); + printf("Lon bins= %4d\n",OSMNodes->file.lonbins); printf("\n"); - printf("Lat zero=%5d (%8.4f deg)\n",OSMNodes->latzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->latzero)))); - printf("Lon zero=%5d (%8.4f deg)\n",OSMNodes->lonzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->lonzero)))); + printf("Lat zero=%5d (%8.4f deg)\n",OSMNodes->file.latzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->file.latzero)))); + printf("Lon zero=%5d (%8.4f deg)\n",OSMNodes->file.lonzero,radians_to_degrees(latlong_to_radians(bin_to_latlong(OSMNodes->file.lonzero)))); /* Examine the segments */ @@ -219,9 +211,9 @@ int main(int argc,char** argv) printf("\n"); printf("sizeof(Segment)=%9d Bytes\n",sizeof(Segment)); - printf("Number(total) =%9d\n",OSMSegments->number); - printf("Number(super) =%9d\n",OSMSegments->snumber); - printf("Number(normal) =%9d\n",OSMSegments->nnumber); + printf("Number(total) =%9d\n",OSMSegments->file.number); + printf("Number(super) =%9d\n",OSMSegments->file.snumber); + printf("Number(normal) =%9d\n",OSMSegments->file.nnumber); /* Examine the ways */ @@ -231,15 +223,15 @@ int main(int argc,char** argv) printf("\n"); printf("sizeof(Way) =%9d Bytes\n",sizeof(Way)); - printf("Number(compacted)=%9d\n",OSMWays->number); - printf("Number(original) =%9d\n",OSMWays->onumber); + printf("Number(compacted)=%9d\n",OSMWays->file.number); + printf("Number(original) =%9d\n",OSMWays->file.onumber); printf("\n"); - printf("Total names =%9ld Bytes\n",(long)buf.st_size-sizeof(Ways)-OSMWays->number*sizeof(Way)); + printf("Total names =%9ld Bytes\n",(long)buf.st_size-sizeof(Ways)-OSMWays->file.number*sizeof(Way)); printf("\n"); - printf("Included transports: %s\n",AllowedNameList(OSMWays->allow)); - printf("Included properties: %s\n",PropertiesNameList(OSMWays->props)); + printf("Included transports: %s\n",AllowedNameList(OSMWays->file.allow)); + printf("Included properties: %s\n",PropertiesNameList(OSMWays->file.props)); } /* Print out internal data */ @@ -251,45 +243,45 @@ int main(int argc,char** argv) for(arg=1;argnumber;item++) + for(item=0;itemfile.number;item++) print_node(OSMNodes,item); } else if(!strncmp(argv[arg],"--node=",7)) { item=atoi(&argv[arg][7]); - if(item>=0 && itemnumber) + if(item>=0 && itemfile.number) print_node(OSMNodes,item); else - printf("Invalid node number; minimum=0, maximum=%d.\n",OSMNodes->number-1); + printf("Invalid node number; minimum=0, maximum=%d.\n",OSMNodes->file.number-1); } else if(!strcmp(argv[arg],"--segment=all")) { - for(item=0;itemnumber;item++) + for(item=0;itemfile.number;item++) print_segment(OSMSegments,item); } else if(!strncmp(argv[arg],"--segment=",10)) { item=atoi(&argv[arg][10]); - if(item>=0 && itemnumber) + if(item>=0 && itemfile.number) print_segment(OSMSegments,item); else - printf("Invalid segment number; minimum=0, maximum=%d.\n",OSMSegments->number-1); + printf("Invalid segment number; minimum=0, maximum=%d.\n",OSMSegments->file.number-1); } else if(!strcmp(argv[arg],"--way=all")) { - for(item=0;itemnumber;item++) + for(item=0;itemfile.number;item++) print_way(OSMWays,item); } else if(!strncmp(argv[arg],"--way=",6)) { item=atoi(&argv[arg][6]); - if(item>=0 && itemnumber) + if(item>=0 && itemfile.number) print_way(OSMWays,item); else - printf("Invalid way number; minimum=0, maximum=%d.\n",OSMWays->number-1); + printf("Invalid way number; minimum=0, maximum=%d.\n",OSMWays->file.number-1); } } @@ -298,52 +290,53 @@ int main(int argc,char** argv) if(option_dump_osm) { if(coordcount>0 && coordcount!=4) - { - fprintf(stderr,"The --dump-osm option must have all of --latmin, --latmax, --lonmin, --lonmax or none.\n"); - exit(1); - } + print_usage(0,NULL,"The --dump-osm option must have all of --latmin, --latmax, --lonmin, --lonmax or none.\n"); print_head_osm(); if(coordcount) { - int32_t latminbin=latlong_to_bin(radians_to_latlong(latmin))-OSMNodes->latzero; - int32_t latmaxbin=latlong_to_bin(radians_to_latlong(latmax))-OSMNodes->latzero; - int32_t lonminbin=latlong_to_bin(radians_to_latlong(lonmin))-OSMNodes->lonzero; - int32_t lonmaxbin=latlong_to_bin(radians_to_latlong(lonmax))-OSMNodes->lonzero; + int32_t latminbin=latlong_to_bin(radians_to_latlong(latmin))-OSMNodes->file.latzero; + int32_t latmaxbin=latlong_to_bin(radians_to_latlong(latmax))-OSMNodes->file.latzero; + int32_t lonminbin=latlong_to_bin(radians_to_latlong(lonmin))-OSMNodes->file.lonzero; + int32_t lonmaxbin=latlong_to_bin(radians_to_latlong(lonmax))-OSMNodes->file.lonzero; int latb,lonb,llbin; - index_t node; + index_t item,index1,index2; /* Loop through all of the nodes. */ for(latb=latminbin;latb<=latmaxbin;latb++) for(lonb=lonminbin;lonb<=lonmaxbin;lonb++) { - llbin=lonb*OSMNodes->latbins+latb; + llbin=lonb*OSMNodes->file.latbins+latb; - if(llbin<0 || llbin>(OSMNodes->latbins*OSMNodes->lonbins)) + if(llbin<0 || llbin>(OSMNodes->file.latbins*OSMNodes->file.lonbins)) continue; - for(node=OSMNodes->offsets[llbin];nodeoffsets[llbin+1];node++) + index1=LookupNodeOffset(OSMNodes,llbin); + index2=LookupNodeOffset(OSMNodes,llbin+1); + + for(item=index1;itemlatzero+latb)+off_to_latlong(OSMNodes->nodes[node].latoffset)); - double lon=latlong_to_radians(bin_to_latlong(OSMNodes->lonzero+lonb)+off_to_latlong(OSMNodes->nodes[node].lonoffset)); + Node *node=LookupNode(OSMNodes,item,1); + double lat=latlong_to_radians(bin_to_latlong(OSMNodes->file.latzero+latb)+off_to_latlong(node->latoffset)); + double lon=latlong_to_radians(bin_to_latlong(OSMNodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); if(lat>latmin && latlonmin && lonOtherNode(segment,node)) + if(item>OtherNode(segment,item)) if(!option_no_super || IsNormalSegment(segment)) print_segment_osm(OSMSegments,IndexSegment(OSMSegments,segment),OSMWays); - segment=NextSegment(OSMSegments,segment,node); + segment=NextSegment(OSMSegments,segment,item); } } } @@ -353,11 +346,11 @@ int main(int argc,char** argv) { index_t item; - for(item=0;itemnumber;item++) + for(item=0;itemfile.number;item++) print_node_osm(OSMNodes,item); - for(item=0;itemnumber;item++) - if(!option_no_super || IsNormalSegment(LookupSegment(OSMSegments,item))) + for(item=0;itemfile.number;item++) + if(!option_no_super || IsNormalSegment(LookupSegment(OSMSegments,item,1))) print_segment_osm(OSMSegments,item,OSMWays); } @@ -378,14 +371,15 @@ int main(int argc,char** argv) static void print_node(Nodes* nodes,index_t item) { - Node *node=LookupNode(nodes,item); + Node *node=LookupNode(nodes,item,1); double latitude,longitude; GetLatLong(nodes,item,&latitude,&longitude); printf("Node %d\n",item); - printf(" firstseg=%d\n",SEGMENT(node->firstseg)); + printf(" firstseg=%d\n",node->firstseg); printf(" latoffset=%d lonoffset=%d (latitude=%.6f longitude=%.6f)\n",node->latoffset,node->lonoffset,radians_to_degrees(latitude),radians_to_degrees(longitude)); + printf(" allow=%02x (%s)\n",node->allow,AllowedNameList(node->allow)); if(IsSuperNode(nodes,item)) printf(" Super-Node\n"); } @@ -401,7 +395,7 @@ static void print_node(Nodes* nodes,index_t item) static void print_segment(Segments *segments,index_t item) { - Segment *segment=LookupSegment(segments,item); + Segment *segment=LookupSegment(segments,item,1); printf("Segment %d\n",item); printf(" node1=%d node2=%d\n",segment->node1,segment->node2); @@ -429,10 +423,11 @@ static void print_segment(Segments *segments,index_t item) static void print_way(Ways *ways,index_t item) { - Way *way=LookupWay(ways,item); + Way *way=LookupWay(ways,item,1); printf("Way %d\n",item); - printf(" name=%s\n",WayNameHighway(ways,way)); + if(*WayName(ways,way)) + printf(" name=%s\n",WayName(ways,way)); printf(" type=%02x (%s%s%s)\n",way->type,HighwayName(HIGHWAY(way->type)),way->type&Way_OneWay?",One-Way":"",way->type&Way_Roundabout?",Roundabout":""); printf(" allow=%02x (%s)\n",way->allow,AllowedNameList(way->allow)); if(way->props) @@ -471,14 +466,22 @@ static void print_head_osm(void) static void print_node_osm(Nodes* nodes,index_t item) { + Node *node=LookupNode(nodes,item,1); double latitude,longitude; GetLatLong(nodes,item,&latitude,&longitude); if(IsSuperNode(nodes,item)) { + int i; + printf(" \n",(unsigned long)item+1,radians_to_degrees(latitude),radians_to_degrees(longitude)); printf(" \n"); + + for(i=1;iallow & ALLOWED(i))) + printf(" \n",TransportName(i)); + printf(" \n"); } else @@ -498,8 +501,8 @@ static void print_node_osm(Nodes* nodes,index_t item) static void print_segment_osm(Segments *segments,index_t item,Ways *ways) { - Segment *segment=LookupSegment(segments,item); - Way *way=LookupWay(ways,segment->way); + Segment *segment=LookupSegment(segments,item,1); + Way *way=LookupWay(ways,segment->way,1); int i; printf(" \n",(unsigned long)item+1); @@ -527,8 +530,8 @@ static void print_segment_osm(Segments *segments,index_t item,Ways *ways) printf(" \n",HighwayName(HIGHWAY(way->type))); - if(IsNormalSegment(segment) && WayNamed(ways,way)) - printf(" \n",ParseXML_Encode_Safe_XML(WayNameHighway(ways,way))); + if(IsNormalSegment(segment) && *WayName(ways,way)) + printf(" \n",ParseXML_Encode_Safe_XML(WayName(ways,way))); for(i=1;iallow & ALLOWED(i)) @@ -612,9 +615,13 @@ static char *RFC822Date(time_t t) 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: filedumper [--help]\n" @@ -630,6 +637,16 @@ static void print_usage(int detail) " [--latmin= --latmax=\n" " --lonmin= --lonmax=]]\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" diff --git a/src/files.c b/src/files.c index ce595ab..8e54025 100644 --- a/src/files.c +++ b/src/files.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/files.c,v 1.18 2010/03/29 18:20:06 amb Exp $ + $Header: /home/amb/routino/src/RCS/files.c,v 1.24 2010/10/16 10:59:18 amb Exp $ Functions to handle files. @@ -21,9 +21,11 @@ along with this program. If not, see . ***************************************/ +#include #include #include +#include #include #include #include @@ -31,7 +33,7 @@ #include #include -#include "functions.h" +#include "files.h" /*+ A structure to contain the list of memory mapped files. +*/ @@ -100,7 +102,54 @@ void *MapFile(const char *filename) { close(fd); - fprintf(stderr,"Cannot mmap file '%s' [%s].\n",filename,strerror(errno)); + assert(0); + + fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno)); + exit(EXIT_FAILURE); + } + + mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); + + mappedfiles[nmappedfiles].filename=filename; + mappedfiles[nmappedfiles].fd=fd; + mappedfiles[nmappedfiles].address=address; + mappedfiles[nmappedfiles].length=size; + + nmappedfiles++; + + return(address); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Open a file and map it into memory. + + void *MapFileWriteable Returns the address of the file or exits in case of an error. + + const char *filename The name of the file to open. + ++++++++++++++++++++++++++++++++++++++*/ + +void *MapFileWriteable(const char *filename) +{ + int fd; + off_t size; + void *address; + + /* Open the file and get its size */ + + fd=ReOpenFileWriteable(filename); + + size=SizeFile(filename); + + /* Map the file */ + + address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); + + if(address==MAP_FAILED) + { + close(fd); + + fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno)); exit(EXIT_FAILURE); } @@ -161,18 +210,18 @@ void *UnmapFile(const char *filename) /*++++++++++++++++++++++++++++++++++++++ Open a new file on disk for writing to. - int OpenFile Returns the file descriptor if OK or exits in case of an error. + int OpenFileNew Returns the file descriptor if OK or exits in case of an error. const char *filename The name of the file to create. ++++++++++++++++++++++++++++++++++++++*/ -int OpenFile(const char *filename) +int OpenFileNew(const char *filename) { int fd; /* Open the file */ - fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if(fd<0) { @@ -185,14 +234,14 @@ int OpenFile(const char *filename) /*++++++++++++++++++++++++++++++++++++++ - Open a new file on disk for reading and appending. + Open a new file on disk for reading from and appending. - int AppendFile Returns the file descriptor if OK or exits in case of an error. + int OpenFileAppend Returns the file descriptor if OK or exits in case of an error. const char *filename The name of the file to create. ++++++++++++++++++++++++++++++++++++++*/ -int AppendFile(const char *filename) +int OpenFileAppend(const char *filename) { int fd; @@ -211,7 +260,7 @@ int AppendFile(const char *filename) /*++++++++++++++++++++++++++++++++++++++ - Open an existing file on disk for reading from. + Open an existing file on disk for reading. int ReOpenFile Returns the file descriptor if OK or exits in case of an error. @@ -237,48 +286,28 @@ int ReOpenFile(const char *filename) /*++++++++++++++++++++++++++++++++++++++ - Write data to a file on disk. - - int WriteFile Returns 0 if OK or something else in case of an error. + Open an existing file on disk for reading from or writing to. - int fd The file descriptor to write to. + int ReOpenFileWriteable Returns the file descriptor if OK or exits in case of an error. - const void *address The address of the data to be written from. - - size_t length The length of data to write. + const char *filename The name of the file to open. ++++++++++++++++++++++++++++++++++++++*/ -int WriteFile(int fd,const void *address,size_t length) +int ReOpenFileWriteable(const char *filename) { - /* Write the data */ - - if(write(fd,address,length)!=length) - return(-1); - - return(0); -} - - -/*++++++++++++++++++++++++++++++++++++++ - Read data from a file on disk. - - int ReadFile Returns 0 if OK or something else in case of an error. - - int fd The file descriptor to read from. - - void *address The address of the data to be read into. + int fd; - size_t length The length of data to read. - ++++++++++++++++++++++++++++++++++++++*/ + /* Open the file */ -int ReadFile(int fd,void *address,size_t length) -{ - /* Read the data */ + fd=open(filename,O_RDWR); - if(read(fd,address,length)!=length) - return(-1); + if(fd<0) + { + fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno)); + exit(EXIT_FAILURE); + } - return(0); + return(fd); } @@ -324,27 +353,6 @@ int ExistsFile(const char *filename) /*++++++++++++++++++++++++++++++++++++++ - Seek to a position in a file on disk. - - int SeekFile Returns 0 if OK or something else in case of an error. - - int fd The file descriptor to seek within. - - off_t position The position to seek to. - ++++++++++++++++++++++++++++++++++++++*/ - -int SeekFile(int fd,off_t position) -{ - /* Seek the data */ - - if(lseek(fd,position,SEEK_SET)!=position) - return(-1); - - return(0); -} - - -/*++++++++++++++++++++++++++++++++++++++ Close a file on disk. int fd The file descriptor to close. diff --git a/src/files.h b/src/files.h new file mode 100644 index 0000000..6edf55c --- /dev/null +++ b/src/files.h @@ -0,0 +1,127 @@ +/*************************************** + $Header: /home/amb/routino/src/RCS/files.h,v 1.4 2010/10/09 18:20:18 amb Exp $ + + Header file for file function prototypes + + Part of the Routino routing software. + ******************/ /****************** + This file Copyright 2008-2010 Andrew M. Bishop + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + ***************************************/ + + +#ifndef FILES_H +#define FILES_H /*+ To stop multiple inclusions. +*/ + +#include +#include + + +/* In files.c */ + +char *FileName(const char *dirname,const char *prefix, const char *name); + +void *MapFile(const char *filename); +void *MapFileWriteable(const char *filename); +void *UnmapFile(const char *filename); + +int OpenFileNew(const char *filename); +int OpenFileAppend(const char *filename); +int ReOpenFile(const char *filename); +int ReOpenFileWriteable(const char *filename); + +static int WriteFile(int fd,const void *address,size_t length); +static int ReadFile(int fd,void *address,size_t length); + +off_t SizeFile(const char *filename); +int ExistsFile(const char *filename); + +static int SeekFile(int fd,off_t position); + +void CloseFile(int fd); + +int DeleteFile(char *filename); + + +/* Inline the frequently called functions */ + +/*++++++++++++++++++++++++++++++++++++++ + Write data to a file on disk. + + int WriteFile Returns 0 if OK or something else in case of an error. + + int fd The file descriptor to write to. + + const void *address The address of the data to be written from. + + size_t length The length of data to write. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline int WriteFile(int fd,const void *address,size_t length) +{ + /* Write the data */ + + if(write(fd,address,length)!=length) + return(-1); + + return(0); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Read data from a file on disk. + + int ReadFile Returns 0 if OK or something else in case of an error. + + int fd The file descriptor to read from. + + void *address The address of the data to be read into. + + size_t length The length of data to read. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline int ReadFile(int fd,void *address,size_t length) +{ + /* Read the data */ + + if(read(fd,address,length)!=length) + return(-1); + + return(0); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Seek to a position in a file on disk. + + int SeekFile Returns 0 if OK or something else in case of an error. + + int fd The file descriptor to seek within. + + off_t position The position to seek to. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline int SeekFile(int fd,off_t position) +{ + /* Seek the data */ + + if(lseek(fd,position,SEEK_SET)!=position) + return(-1); + + return(0); +} + + +#endif /* FILES_H */ diff --git a/src/functions.h b/src/functions.h index 1ff10de..ffa499e 100644 --- a/src/functions.h +++ b/src/functions.h @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/functions.h,v 1.54 2010/04/24 16:47:56 amb Exp $ + $Header: /home/amb/routino/src/RCS/functions.h,v 1.58 2010/09/25 13:54:18 amb Exp $ Header file for function prototypes @@ -25,18 +25,23 @@ #ifndef FUNCTIONS_H #define FUNCTIONS_H /*+ To stop multiple inclusions. +*/ -#include -#include - #include "types.h" + #include "profiles.h" #include "results.h" -/* In router.c */ +/*+ The number of waypoints allowed to be specified. +*/ +#define NWAYPOINTS 99 + + +/* In fakes.c */ /*+ Return true if this is a fake node. +*/ -#define IsFakeNode(xxx) ((xxx)&NODE_SUPER) +#define IsFakeNode(xxx) ((xxx)>=NODE_FAKE) + +/*+ Return true if this is a fake segment. +*/ +#define IsFakeSegment(xxx) ((xxx)>=SEGMENT_FAKE) index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2); @@ -46,29 +51,8 @@ Segment *FirstFakeSegment(index_t node); Segment *NextFakeSegment(Segment *segment,index_t node); Segment *ExtraFakeSegment(index_t node,index_t fakenode); - -/* In files.c */ - -char *FileName(const char *dirname,const char *prefix, const char *name); - -void *MapFile(const char *filename); -void *UnmapFile(const char *filename); - -int OpenFile(const char *filename); -int AppendFile(const char *filename); -int ReOpenFile(const char *filename); - -int WriteFile(int fd,const void *address,size_t length); -int ReadFile(int fd,void *address,size_t length); - -off_t SizeFile(const char *filename); -int ExistsFile(const char *filename); - -int SeekFile(int fd,off_t position); - -void CloseFile(int fd); - -int DeleteFile(char *filename); +Segment *LookupFakeSegment(index_t index); +index_t IndexFakeSegment(Segment *segment); /* In optimiser.c */ @@ -100,7 +84,7 @@ void filesort_fixed(int fd_in,int fd_out,size_t itemsize,int (*compare)(const vo void filesort_vary(int fd_in,int fd_out,int (*compare)(const void*,const void*),int (*buildindex)(void*,index_t)); -void heapsort(void **datap,size_t nitems,int(*compare)(const void*, const void*)); +void filesort_heapsort(void **datap,size_t nitems,int(*compare)(const void*, const void*)); #endif /* FUNCTIONS_H */ diff --git a/src/functionsx.h b/src/functionsx.h index bb92183..4cf7594 100644 --- a/src/functionsx.h +++ b/src/functionsx.h @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/functionsx.h,v 1.5 2010/05/22 18:40:47 amb Exp $ + $Header: /home/amb/routino/src/RCS/functionsx.h,v 1.6 2010/09/17 17:44:15 amb Exp $ Header file for function prototypes for extended data types. @@ -33,7 +33,7 @@ /* In osmparser.c */ -int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays); +int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations); #endif /* FUNCTIONSX_H */ diff --git a/src/nodes.c b/src/nodes.c index 7430d62..f04678b 100644 --- a/src/nodes.c +++ b/src/nodes.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/nodes.c,v 1.39 2010/07/08 17:54:54 amb Exp $ + $Header: /home/amb/routino/src/RCS/nodes.c,v 1.44 2010/07/26 18:17:20 amb Exp $ Node data type functions. @@ -26,11 +26,12 @@ #include #include -#include "profiles.h" #include "nodes.h" #include "segments.h" #include "ways.h" -#include "functions.h" + +#include "files.h" +#include "profiles.h" /*++++++++++++++++++++++++++++++++++++++ @@ -43,22 +44,38 @@ Nodes *LoadNodeList(const char *filename) { - void *data; Nodes *nodes; nodes=(Nodes*)malloc(sizeof(Nodes)); - data=MapFile(filename); +#if !SLIM + + nodes->data=MapFile(filename); + + /* Copy the NodesFile header structure from the loaded data */ + + nodes->file=*((NodesFile*)nodes->data); + + /* Set the pointers in the Nodes structure. */ + + nodes->offsets=(index_t*)(nodes->data+sizeof(NodesFile)); + nodes->nodes =(Node* )(nodes->data+sizeof(NodesFile)+(nodes->file.latbins*nodes->file.lonbins+1)*sizeof(index_t)); + +#else + + nodes->fd=ReOpenFile(filename); - /* Copy the Nodes structure from the loaded data */ + /* Copy the NodesFile header structure from the loaded data */ - *nodes=*((Nodes*)data); + ReadFile(nodes->fd,&nodes->file,sizeof(NodesFile)); - /* Adjust the pointers in the Nodes structure. */ + nodes->nodesoffset=sizeof(NodesFile)+(nodes->file.latbins*nodes->file.lonbins+1)*sizeof(index_t); - nodes->data=data; - nodes->offsets=(index_t*)(data+sizeof(Nodes)); - nodes->nodes=(Node*)(data+(sizeof(Nodes)+(nodes->latbins*nodes->lonbins+1)*sizeof(index_t))); + nodes->incache[0]=NO_NODE; + nodes->incache[1]=NO_NODE; + nodes->incache[2]=NO_NODE; + +#endif return(nodes); } @@ -89,10 +106,11 @@ Nodes *LoadNodeList(const char *filename) index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, distance_t distance,Profile *profile,distance_t *bestdist) { - ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->latzero; - ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->lonzero; + ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->file.latzero; + ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->file.lonzero; int delta=0,count; - index_t i,bestn=NO_NODE; + index_t i,index1,index2; + index_t bestn=NO_NODE; distance_t bestd=INF_DISTANCE; /* Start with the bin containing the location, then spiral outwards. */ @@ -102,30 +120,30 @@ index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitu int latb,lonb,llbin; count=0; - + for(latb=latbin-delta;latb<=latbin+delta;latb++) { - if(latb<0 || latb>=nodes->latbins) + if(latb<0 || latb>=nodes->file.latbins) continue; for(lonb=lonbin-delta;lonb<=lonbin+delta;lonb++) { - if(lonb<0 || lonb>=nodes->lonbins) + if(lonb<0 || lonb>=nodes->file.lonbins) continue; if(abs(latb-latbin)latbins+latb; + llbin=lonb*nodes->file.latbins+latb; /* Check if this grid square has any hope of being close enough */ if(delta>0) { - double lat1=latlong_to_radians(bin_to_latlong(nodes->latzero+latb)); - double lon1=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb)); - double lat2=latlong_to_radians(bin_to_latlong(nodes->latzero+latb+1)); - double lon2=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb+1)); + double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)); + double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)); + double lat2=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb+1)); + double lon2=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb+1)); if(latb==latbin) { @@ -157,10 +175,14 @@ index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitu /* Check every node in this grid square. */ - for(i=nodes->offsets[llbin];ioffsets[llbin+1];i++) + index1=LookupNodeOffset(nodes,llbin); + index2=LookupNodeOffset(nodes,llbin+1); + + for(i=index1;ilatzero+latb)+off_to_latlong(nodes->nodes[i].latoffset)); - double lon=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb)+off_to_latlong(nodes->nodes[i].lonoffset)); + Node *node=LookupNode(nodes,i,1); + double lat=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(node->latoffset)); + double lon=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); distance_t dist=Distance(lat,lon,latitude,longitude); @@ -176,7 +198,7 @@ index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitu do { - Way *way=LookupWay(ways,segment->way); + Way *way=LookupWay(ways,segment->way,1); if(way->allow&profile->allow) break; @@ -210,7 +232,7 @@ index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitu /*++++++++++++++++++++++++++++++++++++++ Find the closest segment to a latitude, longitude and optionally profile. - Segment *FindClosestSegment Returns the closest segment. + index_t FindClosestSegment Returns the closest segment index. Nodes* nodes The set of nodes to search. @@ -237,16 +259,17 @@ index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitu distance_t *bestdist2 Returns the distance to the best node at the other end. ++++++++++++++++++++++++++++++++++++++*/ -Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, - distance_t distance,Profile *profile, distance_t *bestdist, - index_t *bestnode1,index_t *bestnode2,distance_t *bestdist1,distance_t *bestdist2) +index_t FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, + distance_t distance,Profile *profile, distance_t *bestdist, + index_t *bestnode1,index_t *bestnode2,distance_t *bestdist1,distance_t *bestdist2) { - ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->latzero; - ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->lonzero; + ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->file.latzero; + ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->file.lonzero; int delta=0,count; - index_t i,bestn1=NO_NODE,bestn2=NO_NODE; + index_t i,index1,index2; + index_t bestn1=NO_NODE,bestn2=NO_NODE; distance_t bestd=INF_DISTANCE,bestd1=INF_DISTANCE,bestd2=INF_DISTANCE; - Segment *bests=NULL; + index_t bests=NO_SEGMENT; /* Start with the bin containing the location, then spiral outwards. */ @@ -255,30 +278,30 @@ Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double la int latb,lonb,llbin; count=0; - + for(latb=latbin-delta;latb<=latbin+delta;latb++) { - if(latb<0 || latb>=nodes->latbins) + if(latb<0 || latb>=nodes->file.latbins) continue; for(lonb=lonbin-delta;lonb<=lonbin+delta;lonb++) { - if(lonb<0 || lonb>=nodes->lonbins) + if(lonb<0 || lonb>=nodes->file.lonbins) continue; if(abs(latb-latbin)latbins+latb; + llbin=lonb*nodes->file.latbins+latb; /* Check if this grid square has any hope of being close enough */ if(delta>0) { - double lat1=latlong_to_radians(bin_to_latlong(nodes->latzero+latb)); - double lon1=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb)); - double lat2=latlong_to_radians(bin_to_latlong(nodes->latzero+latb+1)); - double lon2=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb+1)); + double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)); + double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)); + double lat2=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb+1)); + double lon2=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb+1)); if(latb==latbin) { @@ -310,10 +333,14 @@ Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double la /* Check every node in this grid square. */ - for(i=nodes->offsets[llbin];ioffsets[llbin+1];i++) + index1=LookupNodeOffset(nodes,llbin); + index2=LookupNodeOffset(nodes,llbin+1); + + for(i=index1;ilatzero+latb)+off_to_latlong(nodes->nodes[i].latoffset)); - double lon1=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonb)+off_to_latlong(nodes->nodes[i].lonoffset)); + Node *node=LookupNode(nodes,i,1); + double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(node->latoffset)); + double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); distance_t dist1; dist1=Distance(lat1,lon1,latitude,longitude); @@ -333,7 +360,7 @@ Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double la Way *way=NULL; if(profile) - way=LookupWay(ways,segment->way); + way=LookupWay(ways,segment->way,1); if(!profile || way->allow&profile->allow) { @@ -368,7 +395,7 @@ Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double la if(distp<(double)bestd) { - bests=segment; + bests=IndexSegment(segments,segment); bestn1=i; bestn2=OtherNode(segment,i); bestd1=(distance_t)dist3a; @@ -418,9 +445,10 @@ Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double la void GetLatLong(Nodes *nodes,index_t index,double *latitude,double *longitude) { - Node *node=&nodes->nodes[index]; + Node *node=LookupNode(nodes,index,2); int latbin=-1,lonbin=-1; int start,end,mid; + index_t offset; /* Binary search - search key closest below is required. * @@ -436,63 +464,73 @@ void GetLatLong(Nodes *nodes,index_t index,double *latitude,double *longitude) /* Search for longitude */ start=0; - end=nodes->lonbins-1; + end=nodes->file.lonbins-1; do { - mid=(start+end)/2; /* Choose mid point */ + mid=(start+end)/2; /* Choose mid point */ - if(nodes->offsets[nodes->latbins*mid]file.latbins*mid); + + if(offsetoffsets[nodes->latbins*mid]>index) /* Mid point is too high */ + else if(offset>index) /* Mid point is too high */ end=mid-1; - else /* Mid point is correct */ + else /* Mid point is correct */ {lonbin=mid;break;} } while((end-start)>1); if(lonbin==-1) { - if(nodes->offsets[nodes->latbins*end]>index) + offset=LookupNodeOffset(nodes,nodes->file.latbins*end); + + if(offset>index) lonbin=start; else lonbin=end; } - while(lonbinlonbins && nodes->offsets[lonbin*nodes->latbins]==nodes->offsets[(lonbin+1)*nodes->latbins]) + while(lonbinfile.lonbins && + LookupNodeOffset(nodes,lonbin*nodes->file.latbins)==LookupNodeOffset(nodes,(lonbin+1)*nodes->file.latbins)) lonbin++; /* Search for latitude */ start=0; - end=nodes->latbins-1; + end=nodes->file.latbins-1; do { - mid=(start+end)/2; /* Choose mid point */ + mid=(start+end)/2; /* Choose mid point */ - if(nodes->offsets[lonbin*nodes->latbins+mid]file.latbins+mid); + + if(offsetoffsets[lonbin*nodes->latbins+mid]>index) /* Mid point is too high */ + else if(offset>index) /* Mid point is too high */ end=mid-1; - else /* Mid point is correct */ + else /* Mid point is correct */ {latbin=mid;break;} } while((end-start)>1); if(latbin==-1) { - if(nodes->offsets[lonbin*nodes->latbins+end]>index) + offset=LookupNodeOffset(nodes,lonbin*nodes->file.latbins+end); + + if(offset>index) latbin=start; else latbin=end; } - while(latbinlatbins && nodes->offsets[lonbin*nodes->latbins+latbin]==nodes->offsets[lonbin*nodes->latbins+latbin+1]) + while(latbinfile.latbins && + LookupNodeOffset(nodes,lonbin*nodes->file.latbins+latbin)==LookupNodeOffset(nodes,lonbin*nodes->file.latbins+latbin+1)) latbin++; /* Return the values */ - *latitude =latlong_to_radians(bin_to_latlong(nodes->latzero+latbin)+off_to_latlong(node->latoffset)); - *longitude=latlong_to_radians(bin_to_latlong(nodes->lonzero+lonbin)+off_to_latlong(node->lonoffset)); + *latitude =latlong_to_radians(bin_to_latlong(nodes->file.latzero+latbin)+off_to_latlong(node->latoffset)); + *longitude=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonbin)+off_to_latlong(node->lonoffset)); } diff --git a/src/nodes.h b/src/nodes.h index 8bfc2b6..a1722cd 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -1,11 +1,11 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/nodes.h,v 1.30 2009/11/14 19:39:19 amb Exp $ + $Header: /home/amb/routino/src/RCS/nodes.h,v 1.37 2010/08/03 18:28:30 amb Exp $ A header file for the nodes. Part of the Routino routing software. ******************/ /****************** - This file Copyright 2008,2009 Andrew M. Bishop + This file Copyright 2008-2010 Andrew M. Bishop This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -28,6 +28,8 @@ #include #include "types.h" + +#include "files.h" #include "profiles.h" @@ -41,54 +43,195 @@ struct _Node ll_off_t latoffset; /*+ The node latitude offset within its bin. +*/ ll_off_t lonoffset; /*+ The node longitude offset within its bin. +*/ + + allow_t allow; /*+ The types of transport that are allowed through the node. +*/ + uint16_t flags; /*+ Flags containing extra information (super-node, turn restriction). +*/ }; -/*+ A structure containing a set of nodes (mmap format). +*/ -struct _Nodes +/*+ A structure containing the header from the file. +*/ +typedef struct _NodesFile { - uint32_t number; /*+ How many nodes in total? +*/ - uint32_t snumber; /*+ How many super-nodes? +*/ + index_t number; /*+ How many nodes in total? +*/ + index_t snumber; /*+ How many super-nodes? +*/ - uint32_t latbins; /*+ The number of bins containing latitude. +*/ - uint32_t lonbins; /*+ The number of bins containing longitude. +*/ + index_t latbins; /*+ The number of bins containing latitude. +*/ + index_t lonbins; /*+ The number of bins containing longitude. +*/ ll_bin_t latzero; /*+ The bin number of the furthest south bin. +*/ ll_bin_t lonzero; /*+ The bin number of the furthest west bin. +*/ +} + NodesFile; - index_t *offsets; /*+ An array of offset to the first node in each bin. +*/ - Node *nodes; /*+ An array of nodes. +*/ +/*+ A structure containing a set of nodes (and pointers to mmap file). +*/ +struct _Nodes +{ + NodesFile file; /*+ The header data from the file. +*/ - void *data; /*+ The memory mapped data. +*/ -}; +#if !SLIM + void *data; /*+ The memory mapped data. +*/ -/* Macros */ + index_t *offsets; /*+ An array of offsets to the first node in each bin. +*/ -/*+ Return a Node pointer given a set of nodes and an index. +*/ -#define LookupNode(xxx,yyy) (&(xxx)->nodes[yyy]) + Node *nodes; /*+ An array of nodes. +*/ -/*+ Return a Segment points given a Node pointer and a set of segments. +*/ -#define FirstSegment(xxx,yyy,zzz) LookupSegment((xxx),SEGMENT((yyy)->nodes[zzz].firstseg)) +#else -/*+ Return true if this is a super-node. +*/ -#define IsSuperNode(xxx,yyy) (((xxx)->nodes[yyy].firstseg)&NODE_SUPER) + int fd; /*+ The file descriptor for the file. +*/ + off_t nodesoffset; /*+ The offset of the nodes within the file. +*/ + Node cached[3]; /*+ The cached nodes. +*/ + index_t incache[3]; /*+ The indexes of the cached nodes. +*/ -/* Functions */ +#endif +}; +/* Functions */ + Nodes *LoadNodeList(const char *filename); index_t FindClosestNode(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, distance_t distance,Profile *profile,distance_t *bestdist); -Segment *FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, - distance_t distance,Profile *profile, distance_t *bestdist, - index_t *bestnode1,index_t *bestnode2,distance_t *bestdist1,distance_t *bestdist2); +index_t FindClosestSegment(Nodes* nodes,Segments *segments,Ways *ways,double latitude,double longitude, + distance_t distance,Profile *profile, distance_t *bestdist, + index_t *bestnode1,index_t *bestnode2,distance_t *bestdist1,distance_t *bestdist2); void GetLatLong(Nodes *nodes,index_t index,double *latitude,double *longitude); +/* Macros and inline functions */ + +#if !SLIM + +/*+ Return a Node pointer given a set of nodes and an index. +*/ +#define LookupNode(xxx,yyy,zzz) (&(xxx)->nodes[yyy]) + +/*+ Return a Segment points given a Node pointer and a set of segments. +*/ +#define FirstSegment(xxx,yyy,zzz) LookupSegment((xxx),(yyy)->nodes[zzz].firstseg,1) + +/*+ Return true if this is a super-node. +*/ +#define IsSuperNode(xxx,yyy) (((xxx)->nodes[yyy].flags)&NODE_SUPER) + +/*+ Return the offset of a geographical region given a set of nodes and an index. +*/ +#define LookupNodeOffset(xxx,yyy) ((xxx)->offsets[yyy]) + +#else + +static Node *LookupNode(Nodes *nodes,index_t index,int position); + +#define FirstSegment(xxx,yyy,zzz) LookupSegment((xxx),FirstSegment_internal(yyy,zzz),1) + +static index_t FirstSegment_internal(Nodes *nodes,index_t index); + +static int IsSuperNode(Nodes *nodes,index_t index); + +static index_t LookupNodeOffset(Nodes *nodes,index_t index); + + +/*++++++++++++++++++++++++++++++++++++++ + Find the Node information for a particular node. + + Node *LookupNode Returns a pointer to the cached node information. + + Nodes *nodes The nodes structure to use. + + index_t index The index of the node. + + int position The position in the cache to store the value. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline Node *LookupNode(Nodes *nodes,index_t index,int position) +{ + SeekFile(nodes->fd,nodes->nodesoffset+(off_t)index*sizeof(Node)); + + ReadFile(nodes->fd,&nodes->cached[position-1],sizeof(Node)); + + nodes->incache[position-1]=index; + + return(&nodes->cached[position-1]); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Find the index of the first segment of a node (called by FirstSegment() macro). + + index_t FirstSegment_internal Returns the index of the first segment. + + Nodes *nodes The nodes structure to use. + + index_t index The index of the node. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline index_t FirstSegment_internal(Nodes *nodes,index_t index) +{ + if(nodes->incache[0]==index) + return(nodes->cached[0].firstseg); + else if(nodes->incache[1]==index) + return(nodes->cached[1].firstseg); + else if(nodes->incache[2]==index) + return(nodes->cached[2].firstseg); + else + { + Node *node=LookupNode(nodes,index,3); + + return(node->firstseg); + } +} + + +/*++++++++++++++++++++++++++++++++++++++ + Decide if a node is a super-node. + + int IsSuperNode Return true if it is a supernode. + + Nodes *nodes The nodes structure to use. + + index_t index The index of the node. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline int IsSuperNode(Nodes *nodes,index_t index) +{ + if(nodes->incache[0]==index) + return(nodes->cached[0].flags&NODE_SUPER); + else if(nodes->incache[1]==index) + return(nodes->cached[1].flags&NODE_SUPER); + else if(nodes->incache[2]==index) + return(nodes->cached[2].flags&NODE_SUPER); + else + { + Node *node=LookupNode(nodes,index,3); + + return(node->flags&NODE_SUPER); + } +} + + +/*++++++++++++++++++++++++++++++++++++++ + Find the offset of nodes in a geographical region. + + index_t LookupNodeOffset Returns the value of the index offset. + + Nodes *nodes The nodes structure to use. + + index_t index The index of the offset. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline index_t LookupNodeOffset(Nodes *nodes,index_t index) +{ + index_t offset; + + SeekFile(nodes->fd,sizeof(NodesFile)+(off_t)index*sizeof(index_t)); + + ReadFile(nodes->fd,&offset,sizeof(index_t)); + + return(offset); +} + +#endif + + #endif /* NODES_H */ diff --git a/src/nodesx.c b/src/nodesx.c index cc1e0a2..e5f0ae8 100644 --- a/src/nodesx.c +++ b/src/nodesx.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/nodesx.c,v 1.56 2010/04/28 17:27:02 amb Exp $ + $Header: /home/amb/routino/src/RCS/nodesx.c,v 1.75 2010/10/09 14:14:42 amb Exp $ Extented Node data type functions. @@ -29,18 +29,20 @@ #include #include "types.h" -#include "functions.h" +#include "nodes.h" +#include "segments.h" + #include "nodesx.h" #include "segmentsx.h" #include "waysx.h" -#include "segments.h" -#include "nodes.h" +#include "types.h" + +#include "files.h" +#include "functions.h" -/* Variables */ -/*+ The command line '--slim' option. +*/ -extern int option_slim; +/* Variables */ /*+ The command line '--tmpdir' option or its default value. +*/ extern char *option_tmpdirname; @@ -76,22 +78,28 @@ NodesX *NewNodeList(int append) nodesx->filename=(char*)malloc(strlen(option_tmpdirname)+32); if(append) - sprintf(nodesx->filename,"%s/nodes.input.tmp",option_tmpdirname); + sprintf(nodesx->filename,"%s/nodesx.input.tmp",option_tmpdirname); else - sprintf(nodesx->filename,"%s/nodes.%p.tmp",option_tmpdirname,nodesx); + sprintf(nodesx->filename,"%s/nodesx.%p.tmp",option_tmpdirname,nodesx); + +#if SLIM + nodesx->nfilename=(char*)malloc(strlen(option_tmpdirname)+32); + + sprintf(nodesx->nfilename,"%s/nodes.%p.tmp",option_tmpdirname,nodesx); +#endif if(append) { off_t size; - nodesx->fd=AppendFile(nodesx->filename); + nodesx->fd=OpenFileAppend(nodesx->filename); size=SizeFile(nodesx->filename); nodesx->xnumber=size/sizeof(NodeX); } else - nodesx->fd=OpenFile(nodesx->filename); + nodesx->fd=OpenFileNew(nodesx->filename); return(nodesx); } @@ -115,8 +123,16 @@ void FreeNodeList(NodesX *nodesx,int keep) if(nodesx->idata) free(nodesx->idata); +#if !SLIM if(nodesx->ndata) free(nodesx->ndata); +#endif + +#if SLIM + DeleteFile(nodesx->nfilename); + + free(nodesx->nfilename); +#endif if(nodesx->super) free(nodesx->super); @@ -129,7 +145,7 @@ void FreeNodeList(NodesX *nodesx,int keep) /*++++++++++++++++++++++++++++++++++++++ - Append a node to a newly created node list (unsorted). + Append a single node to an unsorted node list. NodesX* nodesx The set of nodes to process. @@ -138,21 +154,24 @@ void FreeNodeList(NodesX *nodesx,int keep) double latitude The latitude of the node. double longitude The longitude of the node. + + allow_t allow The allowed traffic types through the node. ++++++++++++++++++++++++++++++++++++++*/ -void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude) +void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude,allow_t allow) { NodeX nodex; - assert(!nodesx->idata); /* Must not have idata filled in => unsorted */ - nodex.id=id; nodex.latitude =radians_to_latlong(latitude); nodex.longitude=radians_to_latlong(longitude); + nodex.allow=allow; WriteFile(nodesx->fd,&nodex,sizeof(NodeX)); nodesx->xnumber++; + + assert(nodesx->xnumberidata); /* Must not have idata filled in => unsorted */ - /* Print the start message */ printf("Sorting Nodes"); @@ -182,7 +197,7 @@ void SortNodeList(NodesX* nodesx) DeleteFile(nodesx->filename); - fd=OpenFile(nodesx->filename); + fd=OpenFileNew(nodesx->filename); /* Allocate the array of indexes */ @@ -287,7 +302,7 @@ void SortNodeListGeographically(NodesX* nodesx) DeleteFile(nodesx->filename); - fd=OpenFile(nodesx->filename); + fd=OpenFileNew(nodesx->filename); /* Sort geographically */ @@ -345,7 +360,7 @@ static int sort_by_lat_long(NodeX *a,NodeX *b) else { #ifdef REGRESSION_TESTING - // Need this for regression testing because heapsort() is not order + // Need this for regression testing because filesort_heapsort() is not order // preserving like qsort() is (or was when tested). index_t a_id=a->id; @@ -404,8 +419,6 @@ index_t IndexNodeX(NodesX* nodesx,node_t id) int end=nodesx->number-1; int mid; - assert(nodesx->idata); /* Must have idata filled in => sorted by id */ - /* Binary search - search key exact match only is required. * * # <- start | Check mid and move start or end if it doesn't match @@ -450,37 +463,6 @@ index_t IndexNodeX(NodesX* nodesx,node_t id) /*++++++++++++++++++++++++++++++++++++++ - Lookup a particular node. - - NodeX *LookupNodeX Returns a pointer to the extended node with the specified id. - - NodesX* nodesx The set of nodes to process. - - index_t index The node index to look for. - - int position The position in the cache to use. - ++++++++++++++++++++++++++++++++++++++*/ - -NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position) -{ - assert(index!=NO_NODE); /* Must be a valid node */ - - if(option_slim) - { - SeekFile(nodesx->fd,index*sizeof(NodeX)); - - ReadFile(nodesx->fd,&nodesx->cached[position-1],sizeof(NodeX)); - - return(&nodesx->cached[position-1]); - } - else - { - return(&nodesx->xdata[index]); - } -} - - -/*++++++++++++++++++++++++++++++++++++++ Remove any nodes that are not part of a highway. NodesX *nodesx The complete node list. @@ -496,10 +478,6 @@ void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx) latlong_t lat_min,lat_max,lon_min,lon_max; int fd; - /* Check the start conditions */ - - assert(nodesx->idata); /* Must have idata filled in => data sorted */ - /* Print the start message */ printf("Checking: Nodes=0"); @@ -516,7 +494,7 @@ void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx) DeleteFile(nodesx->filename); - fd=OpenFile(nodesx->filename); + fd=OpenFileNew(nodesx->filename); SeekFile(nodesx->fd,0); while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX))) @@ -598,10 +576,6 @@ void CreateRealNodes(NodesX *nodesx,int iteration) { index_t i; - /* Check the start conditions */ - - assert(!nodesx->ndata); /* Must not have ndata filled in => no real nodes */ - /* Print the start message */ printf("Creating Real Nodes: Nodes=0"); @@ -609,27 +583,39 @@ void CreateRealNodes(NodesX *nodesx,int iteration) /* Map into memory */ - if(!option_slim) - nodesx->xdata=MapFile(nodesx->filename); +#if !SLIM + nodesx->xdata=MapFile(nodesx->filename); +#endif - /* Allocate the memory */ + /* Allocate the memory (or open the file) */ +#if !SLIM nodesx->ndata=(Node*)malloc(nodesx->number*sizeof(Node)); assert(nodesx->ndata); /* Check malloc() worked */ +#else + nodesx->nfd=OpenFileNew(nodesx->nfilename); +#endif /* Loop through and allocate. */ for(i=0;inumber;i++) { NodeX *nodex=LookupNodeX(nodesx,i,1); + Node *node =LookupNodeXNode(nodesx,nodex->id,1); - nodesx->ndata[nodex->id].latoffset=latlong_to_off(nodex->latitude); - nodesx->ndata[nodex->id].lonoffset=latlong_to_off(nodex->longitude); - nodesx->ndata[nodex->id].firstseg=SEGMENT(NO_SEGMENT); + node->latoffset=latlong_to_off(nodex->latitude); + node->lonoffset=latlong_to_off(nodex->longitude); + node->firstseg=NO_SEGMENT; + node->allow=nodex->allow; + node->flags=0; if(nodesx->super[nodex->id]==iteration) - nodesx->ndata[nodex->id].firstseg|=NODE_SUPER; + node->flags|=NODE_SUPER; + +#if SLIM + PutBackNodeXNode(nodesx,nodex->id,1); +#endif if(!((i+1)%10000)) { @@ -645,8 +631,9 @@ void CreateRealNodes(NodesX *nodesx,int iteration) /* Unmap from memory */ - if(!option_slim) - nodesx->xdata=UnmapFile(nodesx->filename); +#if !SLIM + nodesx->xdata=UnmapFile(nodesx->filename); +#endif /* Print the final message */ @@ -667,10 +654,8 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) { index_t i; - /* Check the start conditions */ - - assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ - assert(segmentsx->sdata); /* Must have sdata filled in => real segments exist */ + if(nodesx->number==0 || segmentsx->number==0) + return; /* Print the start message */ @@ -679,11 +664,10 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) /* Map into memory */ - if(!option_slim) - { - nodesx->xdata=MapFile(nodesx->filename); - segmentsx->xdata=MapFile(segmentsx->filename); - } +#if !SLIM + nodesx->xdata=MapFile(nodesx->filename); + segmentsx->xdata=MapFile(segmentsx->filename); +#endif /* Index the nodes */ @@ -692,19 +676,22 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); node_t id1=segmentx->node1; node_t id2=segmentx->node2; - Node *node1=&nodesx->ndata[id1]; - Node *node2=&nodesx->ndata[id2]; + Node *node1=LookupNodeXNode(nodesx,id1,1); + Node *node2=LookupNodeXNode(nodesx,id2,2); /* Check node1 */ - if(SEGMENT(node1->firstseg)==SEGMENT(NO_SEGMENT)) + if(node1->firstseg==NO_SEGMENT) { - node1->firstseg^=SEGMENT(NO_SEGMENT); - node1->firstseg|=i; + node1->firstseg=i; + +#if SLIM + PutBackNodeXNode(nodesx,id1,1); +#endif } else { - index_t index=SEGMENT(node1->firstseg); + index_t index=node1->firstseg; do { @@ -724,13 +711,20 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) } else { - if(segmentsx->sdata[index].next2==NO_NODE) + Segment *segment=LookupSegmentXSegment(segmentsx,index,1); + + if(segment->next2==NO_NODE) { - segmentsx->sdata[index].next2=i; + segment->next2=i; + +#if SLIM + PutBackSegmentXSegment(segmentsx,index,1); +#endif + break; } else - index=segmentsx->sdata[index].next2; + index=segment->next2; } } while(1); @@ -738,14 +732,17 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) /* Check node2 */ - if(SEGMENT(node2->firstseg)==SEGMENT(NO_SEGMENT)) + if(node2->firstseg==NO_SEGMENT) { - node2->firstseg^=SEGMENT(NO_SEGMENT); - node2->firstseg|=i; + node2->firstseg=i; + +#if SLIM + PutBackNodeXNode(nodesx,id2,2); +#endif } else { - index_t index=SEGMENT(node2->firstseg); + index_t index=node2->firstseg; do { @@ -765,13 +762,20 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) } else { - if(segmentsx->sdata[index].next2==NO_NODE) + Segment *segment=LookupSegmentXSegment(segmentsx,index,1); + + if(segment->next2==NO_NODE) { - segmentsx->sdata[index].next2=i; + segment->next2=i; + +#if SLIM + PutBackSegmentXSegment(segmentsx,index,1); +#endif + break; } else - index=segmentsx->sdata[index].next2; + index=segment->next2; } } while(1); @@ -786,11 +790,10 @@ void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx) /* Unmap from memory */ - if(!option_slim) - { - nodesx->xdata=UnmapFile(nodesx->filename); - segmentsx->xdata=UnmapFile(segmentsx->filename); - } +#if !SLIM + nodesx->xdata=UnmapFile(nodesx->filename); + segmentsx->xdata=UnmapFile(segmentsx->filename); +#endif /* Print the final message */ @@ -811,13 +814,9 @@ void SaveNodeList(NodesX* nodesx,const char *filename) { index_t i; int fd; - Nodes *nodes; + NodesFile nodesfile={0}; int super_number=0; - /* Check the start conditions */ - - assert(nodesx->ndata); /* Must have ndata filled in => real nodes exist */ - /* Print the start message */ printf("Writing Nodes: Nodes=0"); @@ -825,47 +824,24 @@ void SaveNodeList(NodesX* nodesx,const char *filename) /* Map into memory */ - if(!option_slim) - nodesx->xdata=MapFile(nodesx->filename); - - /* Count the number of super-nodes */ - - for(i=0;inumber;i++) - if(nodesx->ndata[i].firstseg&NODE_SUPER) - super_number++; - - /* Fill in a Nodes structure with the offset of the real data in the file after - the Node structure itself. */ - - nodes=calloc(1,sizeof(Nodes)); - - assert(nodes); /* Check calloc() worked */ - - nodes->number=nodesx->number; - nodes->snumber=super_number; - - nodes->latbins=nodesx->latbins; - nodes->lonbins=nodesx->lonbins; - - nodes->latzero=nodesx->latzero; - nodes->lonzero=nodesx->lonzero; - - nodes->data=NULL; - nodes->offsets=NULL; - nodes->nodes=NULL; - - /* Write out the Nodes structure and then the real data. */ +#if !SLIM + nodesx->xdata=MapFile(nodesx->filename); +#endif - fd=OpenFile(filename); + /* Write out the nodes data */ - WriteFile(fd,nodes,sizeof(Nodes)); + fd=OpenFileNew(filename); + SeekFile(fd,sizeof(NodesFile)); WriteFile(fd,nodesx->offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); - for(i=0;inumber;i++) + for(i=0;inumber;i++) { NodeX *nodex=LookupNodeX(nodesx,i,1); - Node *node=&nodesx->ndata[nodex->id]; + Node *node=LookupNodeXNode(nodesx,nodex->id,1); + + if(node->flags&NODE_SUPER) + super_number++; WriteFile(fd,node,sizeof(Node)); @@ -876,19 +852,30 @@ void SaveNodeList(NodesX* nodesx,const char *filename) } } + /* Write out the header structure */ + + nodesfile.number=nodesx->number; + nodesfile.snumber=super_number; + + nodesfile.latbins=nodesx->latbins; + nodesfile.lonbins=nodesx->lonbins; + + nodesfile.latzero=nodesx->latzero; + nodesfile.lonzero=nodesx->lonzero; + + SeekFile(fd,0); + WriteFile(fd,&nodesfile,sizeof(NodesFile)); + CloseFile(fd); /* Unmap from memory */ - if(!option_slim) - nodesx->xdata=UnmapFile(nodesx->filename); +#if !SLIM + nodesx->xdata=UnmapFile(nodesx->filename); +#endif /* Print the final message */ - printf("\rWrote Nodes: Nodes=%d \n",nodes->number); + printf("\rWrote Nodes: Nodes=%d \n",nodesx->number); fflush(stdout); - - /* Free the fake Nodes */ - - free(nodes); } diff --git a/src/nodesx.h b/src/nodesx.h index 2dc40a4..35908af 100644 --- a/src/nodesx.h +++ b/src/nodesx.h @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/nodesx.h,v 1.23 2010/03/19 19:47:09 amb Exp $ + $Header: /home/amb/routino/src/RCS/nodesx.h,v 1.30 2010/08/02 18:44:54 amb Exp $ A header file for the extended nodes. @@ -27,8 +27,12 @@ #include -#include "typesx.h" #include "types.h" +#include "nodes.h" + +#include "typesx.h" + +#include "files.h" /* Data structures */ @@ -41,6 +45,8 @@ struct _NodeX latlong_t latitude; /*+ The node latitude. +*/ latlong_t longitude; /*+ The node longitude. +*/ + + allow_t allow; /*+ The node allowed traffic. +*/ }; /*+ A structure containing a set of nodes (memory format). +*/ @@ -49,26 +55,44 @@ struct _NodesX char *filename; /*+ The name of the temporary file. +*/ int fd; /*+ The file descriptor of the temporary file. +*/ - uint32_t xnumber; /*+ The number of unsorted extended nodes. +*/ + index_t xnumber; /*+ The number of unsorted extended nodes. +*/ + +#if !SLIM NodeX *xdata; /*+ The extended node data (sorted). +*/ - NodeX cached[2]; /*+ Two cached nodes read from the file in slim mode. +*/ - uint32_t number; /*+ How many entries are still useful? +*/ +#else + + NodeX xcached[2]; /*+ Two cached nodes read from the file in slim mode. +*/ + +#endif + + index_t number; /*+ How many entries are still useful? +*/ node_t *idata; /*+ The extended node IDs (sorted by ID). +*/ uint8_t *super; /*+ A marker for super nodes (same order sorted nodes). +*/ +#if !SLIM + Node *ndata; /*+ The actual nodes (same order as geographically sorted nodes). +*/ - uint32_t latbins; /*+ The number of bins containing latitude. +*/ - uint32_t lonbins; /*+ The number of bins containing longitude. +*/ +#else + + char *nfilename; /*+ The name of the temporary file for nodes in slim mode. +*/ + int nfd; /*+ The file descriptor of the temporary file. +*/ + + Node ncached[2]; /*+ Two cached nodes read from the file in slim mode. +*/ + +#endif + + index_t latbins; /*+ The number of bins containing latitude. +*/ + index_t lonbins; /*+ The number of bins containing longitude. +*/ ll_bin_t latzero; /*+ The bin number of the furthest south bin. +*/ ll_bin_t lonzero; /*+ The bin number of the furthest west bin. +*/ - uint32_t latlonbin; /*+ A temporary index into the offsets array. +*/ + index_t latlonbin; /*+ A temporary index into the offsets array. +*/ index_t *offsets; /*+ An array of offset to the first node in each bin. +*/ }; @@ -82,9 +106,8 @@ void FreeNodeList(NodesX *nodesx,int keep); void SaveNodeList(NodesX *nodesx,const char *filename); index_t IndexNodeX(NodesX* nodesx,node_t id); -NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position); -void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude); +void AppendNode(NodesX* nodesx,node_t id,double latitude,double longitude,allow_t allow); void SortNodeList(NodesX *nodesx); @@ -97,4 +120,85 @@ void CreateRealNodes(NodesX *nodesx,int iteration); void IndexNodes(NodesX *nodesx,SegmentsX *segmentsx); +/* Macros / inline functions */ + +#if !SLIM + +#define LookupNodeX(nodesx,index,position) &(nodesx)->xdata[index] + +#define LookupNodeXNode(nodesx,index,position) &(nodesx)->ndata[index] + +#else + +static NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position); + +static Node *LookupNodeXNode(NodesX* nodesx,index_t index,int position); + +static void PutBackNodeXNode(NodesX* nodesx,index_t index,int position); + + +/*++++++++++++++++++++++++++++++++++++++ + Lookup a particular extended node. + + NodeX *LookupNodeX Returns a pointer to the extended node with the specified id. + + NodesX* nodesx The set of nodes to process. + + index_t index The node index to look for. + + int position The position in the cache to use. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline NodeX *LookupNodeX(NodesX* nodesx,index_t index,int position) +{ + SeekFile(nodesx->fd,(off_t)index*sizeof(NodeX)); + + ReadFile(nodesx->fd,&nodesx->xcached[position-1],sizeof(NodeX)); + + return(&nodesx->xcached[position-1]); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Lookup a particular extended node's normal node. + + Node *LookupNodeXNode Returns a pointer to the node with the specified id. + + NodesX* nodesx The set of nodes to process. + + index_t index The node index to look for. + + int position The position in the cache to use. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline Node *LookupNodeXNode(NodesX* nodesx,index_t index,int position) +{ + SeekFile(nodesx->nfd,(off_t)index*sizeof(Node)); + + ReadFile(nodesx->nfd,&nodesx->ncached[position-1],sizeof(Node)); + + return(&nodesx->ncached[position-1]); +} + + +/*++++++++++++++++++++++++++++++++++++++ + Put back an extended node's normal node. + + NodesX* nodesx The set of nodes to process. + + index_t index The node index to look for. + + int position The position in the cache to use. + ++++++++++++++++++++++++++++++++++++++*/ + +static inline void PutBackNodeXNode(NodesX* nodesx,index_t index,int position) +{ + SeekFile(nodesx->nfd,(off_t)index*sizeof(Node)); + + WriteFile(nodesx->nfd,&nodesx->ncached[position-1],sizeof(Node)); +} + +#endif /* SLIM */ + + #endif /* NODESX_H */ diff --git a/src/optimiser.c b/src/optimiser.c index cdb5986..55b4b32 100644 --- a/src/optimiser.c +++ b/src/optimiser.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/optimiser.c,v 1.87 2010/07/08 17:33:09 amb Exp $ + $Header: /home/amb/routino/src/RCS/optimiser.c,v 1.93 2010/08/04 16:44:51 amb Exp $ Routing optimiser. @@ -25,10 +25,11 @@ #include #include "types.h" -#include "functions.h" #include "nodes.h" #include "segments.h" #include "ways.h" + +#include "functions.h" #include "results.h" @@ -60,13 +61,14 @@ extern int option_quickest; Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile) { Results *results; - Queue *queue; + Queue *queue; index_t node1,node2; score_t finish_score; double finish_lat,finish_lon; - Result *result1,*result2; + Result *result1,*result2; + Node *node; Segment *segment; - Way *way; + Way *way; /* Set up the finish conditions */ @@ -125,7 +127,7 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star if(node2!=finish && !IsFakeNode(node2) && IsSuperNode(nodes,node2)) goto endloop; - way=LookupWay(ways,segment->way); + way=LookupWay(ways,segment->way,1); if(!(way->allow&profile->allow)) goto endloop; @@ -144,7 +146,7 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;iprops & PROPERTIES(i)) + if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; @@ -155,6 +157,14 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star if(segment_pref==0) goto endloop; + if(!IsFakeNode(node2)) + { + node=LookupNode(nodes,node2,1); + + if(!(node->allow&profile->allow)) + goto endloop; + } + if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else @@ -173,7 +183,10 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star result2->prev=node1; result2->next=NO_NODE; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(node2==finish) { @@ -190,7 +203,10 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star { result2->prev=node1; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(node2==finish) { @@ -258,14 +274,15 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile) { Results *results; - Queue *queue; + Queue *queue; index_t node1,node2; index_t end_prev; score_t finish_score; double finish_lat,finish_lon; - Result *result1,*result2,*result3; + Result *result1,*result2,*result3; + Node *node; Segment *segment; - Way *way; + Way *way; if(!option_quiet) { @@ -349,7 +366,7 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg if(result1->prev==node2) goto endloop; - way=LookupWay(ways,segment->way); + way=LookupWay(ways,segment->way,1); if(!(way->allow&profile->allow)) goto endloop; @@ -368,7 +385,7 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;iprops & PROPERTIES(i)) + if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; @@ -379,6 +396,11 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg if(segment_pref==0) goto endloop; + node=LookupNode(nodes,node2,1); + + if(!(node->allow&profile->allow)) + goto endloop; + if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else @@ -397,7 +419,7 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg result2->prev=node1; result2->next=NO_NODE; result2->score=cumulative_score; - result2->segment=segment; + result2->segment=IndexSegment(segments,segment); if((result3=FindResult(end,node2))) { @@ -427,7 +449,7 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg { result2->prev=node1; result2->score=cumulative_score; - result2->segment=segment; + result2->segment=IndexSegment(segments,segment); if((result3=FindResult(end,node2))) { @@ -520,11 +542,12 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile) { Results *results; - Queue *queue; + Queue *queue; index_t node1,node2; - Result *result1,*result2; + Result *result1,*result2; + Node *node; Segment *segment; - Way *way; + Way *way; /* Insert the first node into the queue */ @@ -567,7 +590,7 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star if(result1->prev==node2) goto endloop; - way=LookupWay(ways,segment->way); + way=LookupWay(ways,segment->way,1); if(!(way->allow&profile->allow)) goto endloop; @@ -586,7 +609,7 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;iprops & PROPERTIES(i)) + if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; @@ -597,6 +620,14 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star if(segment_pref==0) goto endloop; + if(!IsFakeNode(node2)) + { + node=LookupNode(nodes,node2,1); + + if(!(node->allow&profile->allow)) + goto endloop; + } + if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else @@ -612,7 +643,10 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star result2->prev=node1; result2->next=NO_NODE; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) { @@ -624,7 +658,10 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star { result2->prev=node1; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) { @@ -675,11 +712,12 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile) { Results *results; - Queue *queue; + Queue *queue; index_t node1,node2; - Result *result1,*result2; + Result *result1,*result2; + Node *node; Segment *segment; - Way *way; + Way *way; /* Insert the first node into the queue */ @@ -722,7 +760,7 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin if(result1->next==node2) goto endloop; - way=LookupWay(ways,segment->way); + way=LookupWay(ways,segment->way,1); if(!(way->allow&profile->allow)) goto endloop; @@ -741,7 +779,7 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin segment_pref=profile->highway[HIGHWAY(way->type)]; for(i=1;iprops & PROPERTIES(i)) + if(ways->file.props & PROPERTIES(i)) { if(way->props & PROPERTIES(i)) segment_pref*=profile->props_yes[i]; @@ -752,6 +790,14 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin if(segment_pref==0) goto endloop; + if(!IsFakeNode(node2)) + { + node=LookupNode(nodes,node2,1); + + if(!(node->allow&profile->allow)) + goto endloop; + } + if(option_quickest==0) segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; else @@ -767,7 +813,10 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin result2->prev=NO_NODE; result2->next=node1; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) { @@ -779,7 +828,10 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin { result2->next=node1; result2->score=cumulative_score; - result2->segment=segment; + if(IsFakeNode(node1) || IsFakeNode(node2)) + result2->segment=IndexFakeSegment(segment); + else + result2->segment=IndexSegment(segments,segment); if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) { diff --git a/src/osmparser.c b/src/osmparser.c index 3af039d..f8b47a9 100644 --- a/src/osmparser.c +++ b/src/osmparser.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/osmparser.c,v 1.69 2010/05/29 13:54:23 amb Exp $ + $Header: /home/amb/routino/src/RCS/osmparser.c,v 1.72 2010/09/25 18:47:32 amb Exp $ OSM XML file parser (either JOSM or planet) @@ -29,9 +29,12 @@ #include "typesx.h" #include "functionsx.h" + #include "nodesx.h" #include "segmentsx.h" #include "waysx.h" +#include "relationsx.h" + #include "xmlparse.h" #include "tagging.h" @@ -49,14 +52,24 @@ static TagList *current_tags=NULL; static node_t *way_nodes=NULL; static int way_nnodes=0; -static NodesX *nodes; -static SegmentsX *segments; -static WaysX *ways; +static node_t *relation_nodes=NULL; +static int relation_nnodes=0; +static way_t *relation_ways=NULL; +static int relation_nways=0; +static relation_t *relation_relations=NULL; +static int relation_nrelations=0; + +static NodesX *nodes; +static SegmentsX *segments; +static WaysX *ways; +static RelationsX *relations; /* Local functions */ +static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude); static void process_way_tags(TagList *tags,way_t id); +static void process_relation_tags(TagList *tags,relation_t id); /* The XML tag processing function prototypes */ @@ -65,7 +78,7 @@ static void process_way_tags(TagList *tags,way_t id); //static int osmType_function(const char *_tag_,int _type_); static int relationType_function(const char *_tag_,int _type_,const char *id); static int wayType_function(const char *_tag_,int _type_,const char *id); -//static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role); +static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role); static int ndType_function(const char *_tag_,int _type_,const char *ref); static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon); static int tagType_function(const char *_tag_,int _type_,const char *k,const char *v); @@ -114,7 +127,7 @@ static xmltag ndType_tag= static xmltag memberType_tag= {"member", 3, {"type","ref","role"}, - NULL, + memberType_function, {NULL}}; /*+ The wayType type tag. +*/ @@ -231,11 +244,11 @@ static int tagType_function(const char *_tag_,int _type_,const char *k,const cha static int nodeType_function(const char *_tag_,int _type_,const char *id,const char *lat,const char *lon) { + static node_t node_id; + static double latitude,longitude; + if(_type_&XMLPARSE_TAG_START) { - node_t node_id; - double latitude,longitude; - nnodes++; if(!(nnodes%1000)) @@ -244,25 +257,24 @@ static int nodeType_function(const char *_tag_,int _type_,const char *id,const c fflush(stdout); } + current_tags=NewTagList(); + /* Handle the node information */ XMLPARSE_ASSERT_STRING(_tag_,id); node_id=atoll(id); /* need long long conversion */ XMLPARSE_ASSERT_FLOATING(_tag_,lat,latitude); XMLPARSE_ASSERT_FLOATING(_tag_,lon,longitude); + } - AppendNode(nodes,node_id,degrees_to_radians(latitude),degrees_to_radians(longitude)); + if(_type_&XMLPARSE_TAG_END) + { + TagList *result=ApplyTaggingRules(&NodeRules,current_tags); -// current_tags=NewTagList(); - current_tags=NULL; - } + process_node_tags(result,node_id,latitude,longitude); -// if(_type_&XMLPARSE_TAG_END) -// { -// TagList *result=ApplyTaggingRules(&NodeRules,current_tags); -// -// DeleteTagList(current_tags); -// DeleteTagList(result); -// } + DeleteTagList(current_tags); + DeleteTagList(result); + } return(0); } @@ -288,7 +300,7 @@ static int ndType_function(const char *_tag_,int _type_,const char *ref) XMLPARSE_ASSERT_STRING(_tag_,ref); node_id=atoll(ref); /* need long long conversion */ - if((way_nnodes%256)==0) + if(way_nnodes && (way_nnodes%256)==0) way_nodes=(node_t*)realloc((void*)way_nodes,(way_nnodes+256)*sizeof(node_t)); way_nodes[way_nnodes++]=node_id; @@ -314,10 +326,44 @@ static int ndType_function(const char *_tag_,int _type_,const char *ref) const char *role The contents of the 'role' attribute (or NULL if not defined). ++++++++++++++++++++++++++++++++++++++*/ -//static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role) -//{ -// return(0); -//} +static int memberType_function(const char *_tag_,int _type_,const char *type,const char *ref,const char *role) +{ + if(_type_&XMLPARSE_TAG_START) + { + XMLPARSE_ASSERT_STRING(_tag_,type); + XMLPARSE_ASSERT_STRING(_tag_,ref); + + if(!strcmp(type,"node")) + { + node_t node_id=atoll(ref); /* need long long conversion */ + + if(relation_nnodes && (relation_nnodes%256)==0) + relation_nodes=(node_t*)realloc((void*)relation_nodes,(relation_nnodes+256)*sizeof(node_t)); + + relation_nodes[relation_nnodes++]=node_id; + } + else if(!strcmp(type,"way")) + { + way_t way_id=atoll(ref); /* need long long conversion */ + + if(relation_nways && (relation_nways%256)==0) + relation_ways=(way_t*)realloc((void*)relation_ways,(relation_nways+256)*sizeof(way_t)); + + relation_ways[relation_nways++]=way_id; + } + else if(!strcmp(type,"relation")) + { + relation_t relation_id=atoll(ref); /* need long long conversion */ + + if(relation_nrelations && (relation_nrelations%256)==0) + relation_relations=(relation_t*)realloc((void*)relation_relations,(relation_nrelations+256)*sizeof(relation_t)); + + relation_relations[relation_nrelations++]=relation_id; + } + } + + return(0); +} /*++++++++++++++++++++++++++++++++++++++ @@ -347,6 +393,7 @@ static int wayType_function(const char *_tag_,int _type_,const char *id) } current_tags=NewTagList(); + way_nnodes=0; /* Handle the way information */ @@ -382,6 +429,8 @@ static int wayType_function(const char *_tag_,int _type_,const char *id) static int relationType_function(const char *_tag_,int _type_,const char *id) { + static relation_t relation_id; + if(_type_&XMLPARSE_TAG_START) { nrelations++; @@ -392,17 +441,24 @@ static int relationType_function(const char *_tag_,int _type_,const char *id) fflush(stdout); } -// current_tags=NewTagList(); - current_tags=NULL; + current_tags=NewTagList(); + + relation_nnodes=relation_nways=relation_nrelations=0; + + /* Handle the relation information */ + + XMLPARSE_ASSERT_STRING(_tag_,id); relation_id=atoll(id); /* need long long conversion */ } -// if(_type_&XMLPARSE_TAG_END) -// { -// TagList *result=ApplyTaggingRules(&RelationRules,current_tags); -// -// DeleteTagList(current_tags); -// DeleteTagList(result); -// } + if(_type_&XMLPARSE_TAG_END) + { + TagList *result=ApplyTaggingRules(&RelationRules,current_tags); + + process_relation_tags(result,relation_id); + + DeleteTagList(current_tags); + DeleteTagList(result); + } return(0); } @@ -451,22 +507,33 @@ static int relationType_function(const char *_tag_,int _type_,const char *id) FILE *file The file to read from. - NodesX *OSMNodes The array of nodes to fill in. + NodesX *OSMNodes The data structure of nodes to fill in. + + SegmentsX *OSMSegments The data structure of segments to fill in. - SegmentsX *OSMSegments The array of segments to fill in. + WaysX *OSMWays The data structure of ways to fill in. - WaysX *OSMWays The arrray of ways to fill in. + RelationsX *OSMRelations The data structure of relations to fill in. ++++++++++++++++++++++++++++++++++++++*/ -int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays) +int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays,RelationsX *OSMRelations) { int retval; - /* Parse the file */ + /* Copy the function parameters and initialise the variables. */ nodes=OSMNodes; segments=OSMSegments; ways=OSMWays; + relations=OSMRelations; + + way_nodes=(node_t*)malloc(256*sizeof(node_t)); + + relation_nodes =(node_t *)malloc(256*sizeof(node_t)); + relation_ways =(way_t *)malloc(256*sizeof(way_t)); + relation_relations=(relation_t*)malloc(256*sizeof(relation_t)); + + /* Parse the file */ nnodes=0,nways=0,nrelations=0; @@ -483,6 +550,105 @@ int ParseOSM(FILE *file,NodesX *OSMNodes,SegmentsX *OSMSegments,WaysX *OSMWays) /*++++++++++++++++++++++++++++++++++++++ + Process the tags associated with a node. + + TagList *tags The list of node tags. + + node_t id The id of the node. + + double latitude The latitude of the node. + + double longitude The longitude of the node. + ++++++++++++++++++++++++++++++++++++++*/ + +static void process_node_tags(TagList *tags,node_t id,double latitude,double longitude) +{ + allow_t allow=Allow_ALL; + + int i; + + /* Parse the tags */ + + for(i=0;intags;i++) + { + char *k=tags->k[i]; + char *v=tags->v[i]; + + switch(*k) + { + case 'b': + if(!strcmp(k,"bicycle")) + if(!ISTRUE(v)) + allow&=~Allow_Bicycle; + + break; + + case 'f': + if(!strcmp(k,"foot")) + if(!ISTRUE(v)) + allow&=~Allow_Foot; + + break; + + case 'g': + if(!strcmp(k,"goods")) + if(!ISTRUE(v)) + allow&=~Allow_Goods; + + break; + + case 'h': + if(!strcmp(k,"horse")) + if(!ISTRUE(v)) + allow&=~Allow_Horse; + + if(!strcmp(k,"hgv")) + if(!ISTRUE(v)) + allow&=~Allow_HGV; + + break; + + case 'm': + if(!strcmp(k,"moped")) + if(!ISTRUE(v)) + allow&=~Allow_Moped; + + if(!strcmp(k,"motorbike")) + if(!ISTRUE(v)) + allow&=~Allow_Motorbike; + + if(!strcmp(k,"motorcar")) + if(!ISTRUE(v)) + allow&=~Allow_Motorcar; + + break; + + case 'p': + if(!strcmp(k,"psv")) + if(!ISTRUE(v)) + allow&=~Allow_PSV; + + break; + + case 'w': + if(!strcmp(k,"wheelchair")) + if(!ISTRUE(v)) + allow&=~Allow_Wheelchair; + + break; + + default: + ; + } + } + + /* Create the node */ + + AppendNode(nodes,id,degrees_to_radians(latitude),degrees_to_radians(longitude),allow); +} + + +/*++++++++++++++++++++++++++++++++++++++ Process the tags associated with a way. TagList *tags The list of way tags. @@ -512,6 +678,10 @@ static void process_way_tags(TagList *tags,way_t id) if(ISTRUE(v)) way.allow|= Allow_Bicycle; + if(!strcmp(k,"bicycleroute")) + if(ISTRUE(v)) + way.props|=Properties_BicycleRoute; + if(!strcmp(k,"bridge")) if(ISTRUE(v)) way.props|=Properties_Bridge; @@ -523,6 +693,10 @@ static void process_way_tags(TagList *tags,way_t id) if(ISTRUE(v)) way.allow|= Allow_Foot; + if(!strcmp(k,"footroute")) + if(ISTRUE(v)) + way.props|=Properties_FootRoute; + break; case 'g': @@ -746,3 +920,55 @@ static void process_way_tags(TagList *tags,way_t id) } } } + + +/*++++++++++++++++++++++++++++++++++++++ + Process the tags associated with a relation. + + TagList *tags The list of relation tags. + + relation_t id The id of the relation. + ++++++++++++++++++++++++++++++++++++++*/ + +static void process_relation_tags(TagList *tags,relation_t id) +{ + allow_t routes=Allow_None; + int i; + + /* Parse the tags */ + + for(i=0;intags;i++) + { + char *k=tags->k[i]; + char *v=tags->v[i]; + + switch(*k) + { + case 'b': + if(!strcmp(k,"bicycleroute")) + if(ISTRUE(v)) + routes|=Allow_Bicycle; + + break; + + case 'f': + if(!strcmp(k,"footroute")) + if(ISTRUE(v)) + routes|=Allow_Foot; + + break; + + default: + ; + } + } + + /* Create the route relation (must store all relations that have ways or + relations even if they are not routes because they might be referenced by + other relations that are routes) */ + + if(relation_nways || relation_nrelations) + AppendRouteRelation(relations,id,routes, + relation_ways,relation_nways, + relation_relations,relation_nrelations); +} diff --git a/src/output.c b/src/output.c index e40f750..cbada4f 100644 --- a/src/output.c +++ b/src/output.c @@ -1,5 +1,5 @@ /*************************************** - $Header: /home/amb/routino/src/RCS/output.c,v 1.33 2010/07/07 17:31:06 amb Exp $ + $Header: /home/amb/routino/src/RCS/output.c,v 1.40 2010/09/15 18:30:08 amb Exp $ Routing output generator. @@ -33,11 +33,13 @@ #include #include "types.h" -#include "functions.h" -#include "translations.h" #include "nodes.h" #include "segments.h" #include "ways.h" + +#include "files.h" +#include "functions.h" +#include "translations.h" #include "results.h" #include "xmlparse.h" @@ -54,19 +56,20 @@ extern int option_html,option_gpx_track,option_gpx_route,option_text,option_text /*+ Heuristics for determining if a junction is important. +*/ static char junction_other_way[Way_Count][Way_Count]= - { /* M, T, P, S, T, U, R, S, T, C, P, S = Way type of route not taken */ - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Motorway */ - { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Trunk */ - { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Primary */ - { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Secondary */ - { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, /* Tertiary */ - { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* Unclassified */ - { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, /* Residential */ - { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, /* Service */ - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }, /* Track */ - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, /* Cycleway */ - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */ - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */ + { /* M, T, P, S, T, U, R, S, T, C, P, S, F = Way type of route not taken */ + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Motorway */ + { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Trunk */ + { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Primary */ + { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Secondary */ + { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, /* Tertiary */ + { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1 }, /* Unclassified */ + { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, /* Residential */ + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, /* Service */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, /* Track */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1 }, /* Cycleway */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Path */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Steps */ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* Ferry */ }; @@ -174,7 +177,8 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W fprintf(htmlfile,""); fprintf(htmlfile,translate_html_title,option_quickest?translate_route_quickest:translate_route_shortest); fprintf(htmlfile,"\n"); - fprintf(htmlfile,"