Merge branch 'upstream' master
authorThibaut GRIDEL <tgridel@free.fr>
Tue, 28 Dec 2010 21:16:42 +0000 (22:16 +0100)
committerThibaut GRIDEL <tgridel@free.fr>
Tue, 28 Dec 2010 21:16:42 +0000 (22:16 +0100)
76 files changed:
ChangeLog
Makefile
doc/ALGORITHM.txt
doc/CONFIGURATION.txt
doc/INSTALL.txt
doc/Makefile
doc/NEWS.txt
doc/README.txt
doc/TAGGING.txt
doc/USAGE.txt
doc/html/algorithm.html
doc/html/configuration.html
doc/html/readme.html [new file with mode: 0644]
doc/html/tagging.html
doc/html/usage.html
src/Makefile
src/fakes.c [new file with mode: 0644]
src/filedumper.c
src/files.c
src/files.h [new file with mode: 0644]
src/functions.h
src/functionsx.h
src/logging.c [new file with mode: 0644]
src/logging.h [new file with mode: 0644]
src/nodes.c
src/nodes.h
src/nodesx.c
src/nodesx.h
src/optimiser.c
src/osmparser.c
src/output.c
src/planetsplitter.c
src/profiles.c
src/profiles.h
src/relationsx.c [new file with mode: 0644]
src/relationsx.h [new file with mode: 0644]
src/results.c
src/results.h
src/router.c
src/segments.c
src/segments.h
src/segmentsx.c
src/segmentsx.h
src/sorting.c
src/superx.c
src/tagging.c
src/tagmodifier.c
src/translations.c
src/types.c
src/types.h
src/typesx.h
src/visualiser.c
src/ways.c
src/ways.h
src/waysx.c
src/waysx.h
src/xml/test/bad-double-quote-attr-invalid-ascii.xml [new file with mode: 0644]
src/xml/test/bad-double-quote-attr-invalid-utf8.xml [new file with mode: 0644]
src/xml/test/bad-single-quote-attr-invalid-ascii.xml [new file with mode: 0644]
src/xml/test/bad-single-quote-attr-invalid-utf8.xml [new file with mode: 0644]
src/xmlparse.l
web/www/routino/noscript.cgi
web/www/routino/noscript.template.html
web/www/routino/paths.pl
web/www/routino/router.html.en
web/www/routino/router.html.nl [new file with mode: 0644]
web/www/routino/router.js
web/www/routino/router.pl
web/www/routino/statistics.cgi
web/www/routino/visualiser.cgi
xml/Makefile
xml/routino-profiles.xml
xml/routino-tagging-nomodify.xml
xml/routino-tagging.xml
xml/routino-tagging.xsd
xml/routino-translations.xml

index 7c79159..cfa3313 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,335 @@
+2010-11-13  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       Version 1.5.1 released
+
+2010-11-13  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * doc/NEWS.txt, doc/README.txt: Updated for version 1.5.1.
+
+       * doc/USAGE.txt: Update program usage for new logging option.
+
+       * xml/routino-translations.xml:
+       Add translation for ferry into German (patch from Michael G├╝nnewig).
+
+       * src/relationsx.c: Fix bug with relation processing.
+
+       * src/logging.h: Add GCC attributes for the logging functions.
+
+       * src/logging.h, src/logging.c: New file.
+
+       * src/Makefile, src/nodesx.c, src/optimiser.c, src/osmparser.c, src/planetsplitter.c,
+       src/relationsx.c, src/router.c, src/segmentsx.c, src/superx.c, src/tagmodifier.c,
+       src/waysx.c:
+       Add an option to make the output more suitable for a log file.
+
+2010-10-31  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * src/files.c:
+       Ensure that enough memory gets allocated in FileName() function.
+
+2010-10-30  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       Version 1.5 released
+
+2010-10-30  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * doc/README.txt, doc/NEWS.txt: Updated for version 1.5.
+
+2010-10-18  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * src/files.c: Fixed some comments for recent changes.
+
+2010-10-09  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * src/waysx.c, src/segmentsx.c, src/nodesx.c:
+       Fix the comment for the Append...() function.
+
+2010-09-15  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * src/xmlparse.l: Stricter checking on XML data (Unicode).
+
+2010-09-05  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * xml/routino-profiles.xml:
+       Reduce the "multilane" preference for motor vehicles.  Gives too much bias with
+       previous setting.
+
+2010-07-15  Andrew M. Bishop  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
+
+       * 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  <amb@gedanken.demon.co.uk>
 
        Version 1.4.1 released
index b6ee933..d1d4250 100644 (file)
--- 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
 #
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-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
index 2432a88..d61f09e 100644 (file)
@@ -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
 --------------
index fa6ae48..3a1a131 100644 (file)
@@ -110,10 +110,12 @@ Routing Profiles
       <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" />
index 123f02c..170fc3a 100644 (file)
@@ -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.
 
 
 --------
index 5bc7047..08801d4 100644 (file)
@@ -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
 #
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+# 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
index a003671..42bfc92 100644 (file)
@@ -1,3 +1,65 @@
+Version 1.5.1 of Routino released : Sat Nov 13 2010
+---------------------------------------------------
+
+Bug fixes:
+  Ensure that enough memory is allocated for filenames.
+  Fix bug that sometimes causes crash when processing route relations.
+
+Documentation:
+  Update documentation to reflect changes in program usage and function.
+
+Programs:
+  Add an option to make the output more suitable for a log file.
+
+Documentation:
+  Update documentation to reflect changes in program usage.
+
+
+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 +75,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.
index 75fe606..875c02e 100644 (file)
@@ -102,6 +102,11 @@ 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.
+   Version 1.5.1 of Routino was released on 13th November 2010.
+
+   The full version history is available in the NEWS.txt file.
 
 
 License
index 6c23d8c..f5ee6d2 100644 (file)
@@ -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
 
 
 --------
index 48721bd..fd8be31 100644 (file)
@@ -19,9 +19,10 @@ planetsplitter
 
   Usage: planetsplitter [--help]
                         [--dir=<dirname>] [--prefix=<name>]
-                        [--slim] [--sort-ram-size=<size>]
+                        [--sort-ram-size=<size>]
                         [--tmpdir=<dirname>]
                         [--parse-only | --process-only]
+                        [--loggable]
                         [--max-iterations=<number>]
                         [--tagging=<filename>]
                         [<filename.osm> ...]
@@ -37,18 +38,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=<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=<dirname>
           Specifies the name of the directory to store the temporary disk
@@ -63,14 +56,23 @@ planetsplitter
           Don't read in any files but process the existing temporary file
           into the routing database.
 
+   --loggable
+          Print progress messages that are suitable for logging to a file;
+          normally an incrementing counter is printed which is more
+          suitable for realtime display than logging.
+
    --max-iterations=<number>
           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
@@ -81,6 +83,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
@@ -100,7 +111,7 @@ router
                 [--dir=<dirname>] [--prefix=<name>]
                 [--profiles=<filename>] [--translations=<filename>]
                 [--exact-nodes-only]
-                [--quiet]
+                [--loggable | --quiet]
                 [--output-html]
                 [--output-gpx-track] [--output-gpx-route]
                 [--output-text] [--output-text-all]
@@ -146,18 +157,19 @@ router
           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
+          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=<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.
+          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
@@ -165,6 +177,11 @@ router
           within a segment (quicker but less accurate unless the points
           are already near nodes).
 
+   --loggable
+          Print progress messages that are suitable for logging to a file;
+          normally an incrementing counter is printed which is more
+          suitable for realtime display than logging.
+
    --quiet
           Don't generate any screen output while running (useful for
           running in a script).
@@ -241,6 +258,7 @@ router
           + cycleway = Cycleway
           + path = Path
           + steps = Steps
+          + ferry = Ferry
 
           Default value depends on the profile selected by the --transport
           option.
@@ -258,6 +276,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 +307,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 <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
@@ -294,11 +319,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 +426,11 @@ filedumper
         --lonmin=<lonmin> --lonmax=<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
 -----------
 
@@ -405,12 +438,18 @@ tagmodifier
    XML file for test purposes.
 
    Usage: tagmodifier [--help]
+                      [--loggable]
                       [--tagging=<filename>]
                       [<filename.osm>]
 
    --help
           Prints out the help information.
 
+   --loggable
+          Print progress messages that are suitable for logging to a file;
+          normally an incrementing counter is printed which is more
+          suitable for realtime display than logging.
+
    --tagging=<filename>
           The name of the XML file containing the tagging rules (defaults
           to 'tagging.xml' in the current directory).
index cec599f..3890b77 100644 (file)
@@ -174,12 +174,15 @@ minimising the length.
   <dt>Highway properties
   <dd>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.
 </dl>
 
 <h3><a name="H_1_1_5"></a>Implementation</h3>
index 98fa009..2f3ac77 100644 (file)
@@ -47,7 +47,7 @@
 
 <h2><a name="H_1_1"></a>XML Configuration Files</h2>
 
-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:
 <ul>
@@ -167,10 +167,11 @@ foot is shown below:
       &lt;preference highway="steps"         percent="80" /&gt;
     &lt;/preferences&gt;
     &lt;properties&gt;
-      &lt;property type="paved"      percent="50" /&gt;
-      &lt;property type="multilane"  percent="25" /&gt;
-      &lt;property type="bridge"     percent="50" /&gt;
-      &lt;property type="tunnel"     percent="50" /&gt;
+      &lt;property type="paved"        percent="50" /&gt;
+      &lt;property type="multilane"    percent="25" /&gt;
+      &lt;property type="bridge"       percent="50" /&gt;
+      &lt;property type="tunnel"       percent="50" /&gt;
+...
     &lt;/properties&gt;
     &lt;restrictions&gt;
       &lt;oneway obey="0" /&gt; 
diff --git a/doc/html/readme.html b/doc/html/readme.html
new file mode 100644 (file)
index 0000000..8dd0712
--- /dev/null
@@ -0,0 +1,276 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+
+<!--
+ Routino documentation - algorithm
+
+ 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 http://www.gnu.org/licenses/.
+-->
+
+<HEAD>
+<TITLE>Routino : Software</TITLE>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<LINK href="style.css" type="text/css" rel="stylesheet">
+</HEAD>
+
+<BODY>
+
+<!-- Header Start -->
+
+<div class="header" align="center">
+
+<h1>Routino : Software</h1>
+
+<hr>
+</div>
+
+<!-- Header End -->
+
+<!-- Content Start -->
+
+<div class="content">
+
+<h2><a name="H_1_1" title="Introduction"></a>Routino Introduction</h2>
+
+Routino is an application for finding a route between two points using the
+dataset of topographical information collected by
+<a class="ext" title="OpenStreetMap" href="http://www.openstreetmap.org/">http://www.OpenStreetMap.org</a>.
+
+<p>
+
+Starting from the raw OpenStreetMap data (in the form of the '.osm' XML files
+available on the internet) a custom database is generated that contains the
+information useful for routing.  With this database and two points specified by
+latitude and longitude an optimum route (either shortest or quickest) is
+determined.  The route is calculated for OpenStreetMap highways (roads, paths
+etc) using one of the common forms of transport defined in OpenStreetMap (foot,
+bicycle, horse, motorcar, motorbike etc).
+
+<p>
+
+When processing the OpenStreetMap data the types of highways are recorded and
+these set default limits on the types of traffic allowed.  More specific
+information about permissions for different types of transport are also recorded
+as are maximum speed limits.  Further restrictions like oneway streets, weight,
+height, width and length limits are also included where specified. Additionally
+a set of properties of each highway are also recorded.  The processing of the
+input file is controlled by a configuration file which determines the
+information that is used.
+
+<p>
+
+When calculating a route the type of transport to be used is taken into account
+to ensure that the known restrictions are followed.  Each of the different
+highway types can further be allowed or disallowed depending on preferences.
+For each type of highway a default speed limit is defined (although the actual
+speed used will be the lowest of the default and any specified in the original
+data).  To make use of the information about restrictions the weight, height,
+width and length of the transport can also be specified.  Further preferences
+about road properties (e.g. paved or not) can also be selected.
+
+<p>
+
+The result of calculating the route can be presented in several different ways.
+An HTML file can be produced that contains a description of the route to take
+with instructions for each of the important junctions.  The contents of the file
+are created based on a set of translations specified in a configuration file.
+The route is also available in a
+<a class="ext" title="GPX format" href="http://www.topografix.com/gpx.asp">GPX (GPS eXchange) XML format</a>.
+format file containing either every point and highway segment (a track file) or
+just a waypoint and translated instructions for the important junctions (a route
+file).
+Additionally there are two plain text files that contain all data points or just
+the important ones (intended for debugging and further processing).
+
+<p>
+
+One of the design aims of Routino was to make the software are flexible as
+possible in selecting routing preferences but also have a sensible set of
+default values.  Another design aim was that finding the optimum route should be
+very fast and most of the speed increases come from the carefully chosen and
+optimised data format.
+
+
+<h2><a name="H_1_2"></a>Disclaimer</h2>
+
+The route that is calculated by this software is only as good as the input data.
+
+<p>
+
+Routino comes with ABSOLUTELY NO WARRANTY for the software itself or the route
+that is calculated by it.
+
+
+<h2><a name="H_1_3"></a>Demonstration</h2>
+
+A live demonstration of the router for the UK is available on the internet:
+<br>
+<a title="Routino demo" href="http://www.routino.org/uk/">http://www.routino.org/uk/</a>
+
+<p>
+
+The source code download available below also includes a set of files that can
+be used to create your own interactive map.
+
+<p>
+
+The interactive map is made possible by use of the OpenLayers Javascript
+library from <a class="ext" href="http://www.openlayers.org" title="OpenLayers">http://www.openlayers.org/</a>.
+
+
+<h2><a name="H_1_4"></a>Documentation</h2>
+
+A full set of
+<a href="index.html" title="Documentation">documentation</a>
+is available that describes how to install and use the programs as well as
+what should go in the configuration files and how it works.
+
+
+<h2><a name="H_1_5"></a>Status</h2>
+
+Version 1.0 of Routino was released on 8th April 2009.
+<br>
+Version 1.1 of Routino was released on 13th June 2009.
+<br>
+Version 1.2 of Routino was released on 21st October 2009.
+<br>
+Version 1.3 of Routino was released on 21st January 2010.
+<br>
+Version 1.4 of Routino was released on 31st May 2010.
+<br>
+Version 1.4.1 of Routino was released on 10th July 2010.
+<br>
+Version 1.5 of Routino was released on 30th October 2010.
+<br>
+Version 1.5.1 of Routino was released on 13th November 2010.
+
+<p>
+
+The full version history is available in the NEWS file.
+
+
+<h3><a name="H_1_5_1" title="Changes"></a>Changes in Version 1.5</h3>
+
+<dl>
+  <dt>Bug fixes:
+  <dd>Check that number of nodes/segments/ways doesn't exceed numerical limits.
+  <br>Allow 32-bit systems to seek within files larger than 4GB.
+  <br>Allow nearly 4G nodes to be stored instead of 2G before.
+  <br>Added rules to makefile for installation (paths specified in top-level).
+  <br>Stricter checking of UTF-8 in XML files and better UTF-8 output.
+  <br>Improve error message if parsing of command line options fail.
+  <br>Fix bugs in router's --help-profile-json and --help-profile-perl options.
+  <br>Rename heapsort function to allow compilation on Mac OS with no change.
+  <br>Reduce impact of property preferences close to 50% by using sqrt().
+
+  <dt>Documentation:
+  <dd>Update documentation to reflect changes in program usage and function.
+
+  <dt>OSM tagging
+  <dd>Traffic restrictions on nodes are now included in default tagging file.
+  <br>Added processing for ferry routes (as pseudo-highway type 'ferry').
+  <br>Process foot and bicycle route relations to create new properties.
+
+  <dt>Configuration Files:
+  <dd>Added Dutch output translations.
+  <br>Added ferry information to profiles.
+  <br>Added foot and bicycle route relation processing.
+
+  <dt>planetsplitter
+  <dd>The slim mode now includes the output data as well as the temporary data.
+  <br>The slim mode is now a separate executable and not a command line option.
+  <br>Traffic restrictions on nodes are now understood when parsing OSM files.
+  <br>Falls back to installed tagging.xml configuration file as last resort.
+
+  <dt>router:
+  <dd>Added a slim mode (as a separate executable and not a command line option).
+  <br>Traffic will not be routed through a node that does not allow it.
+  <br>Falls back to installed profiles.xml & translations.xml files as last resort.
+
+  <dt>filedumper:
+  <dd>Added a slim mode (as a separate executable and not a command line option).
+
+  <dt>Web pages:
+  <dd>Added Dutch translation of router.html.
+</dl>
+
+<h3><a name="H_1_5_2"></a>Additional Changes in Version 1.5.1</h3>
+
+<dl>
+  <dt>Bug fixes:
+  <dd>Ensure that enough memory is allocated for filenames.
+  <br>Fix bug that sometimes causes crash when processing route relations.
+
+  <dt>Documentation:
+  <dd>Update documentation to reflect changes in program usage and function.
+
+  <dt>Programs:
+  <dd>Add an option to make the output more suitable for a log file.
+
+  <dt>Documentation:
+  <dd>Update documentation to reflect changes in program usage.
+</dl>
+
+
+<h3><a name="H_1_5_3"></a>License</h3>
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the
+<a class="ext" title="Affero GPLv3" href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">GNU Affero General Public License</a>
+as published by the Free Software Foundation; either version 3 of the License,
+or (at your option) any later version.
+
+<p>
+
+It is important to note that for this program I have decided to use the
+<em>Affero GPLv3</em> instead of just using the GPL.  This license adds
+additional requirements to anybody who provides a networked service using this
+software.
+
+
+<h3><a name="H_1_5_4"></a>Copyright</h3>
+
+Routino is copyright Andrew M. Bishop 2008-2010.
+
+
+<h2><a name="H_1_6"></a>Download</h2>
+
+The <a title="Download directory" href="http://www.routino.org/download/">download directory</a>
+contains the latest version of the source code.
+
+
+</div>
+
+<!-- Content End -->
+
+<!-- Footer Start -->
+
+<div class="footer" align="center">
+<hr>
+
+<address>
+&copy; Andrew M. Bishop = &lt;amb "at" gedanken.demon.co.uk&gt;
+</address>
+
+</div>
+
+<!-- Footer End -->
+
+</BODY>
+
+</HTML>
index 5af6812..8565511 100644 (file)
@@ -75,9 +75,23 @@ are recognised as being affirmative and any other value is ignored.
 
 <h3><a name="H_1_2_1" title="Nodes"></a>Node Tags And Attributes</h3>
 
-None of the node tags are used but the node attributes <em>id</em>, <em>latitude</em>
-and <em>longitude</em> 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 <em>id</em>, <em>latitude</em> and <em>longitude</em> are
+used.  The id atribute is required to associate the node with the ways and the
+position attributes are required to locate the node.
+
+
+<h4><a name="H_1_2_1_1" title="transport tags"></a>Transport Specific Tags</h4>
+
+One tag is recognised for each of the different modes of transport: <em>foot</em>,
+<em>horse</em>, <em>bicycle</em>, <em>wheelchair</em>, <em>moped</em>,
+<em>motorbike</em>, <em>motorcar</em>, <em>goods</em>, <em>hgv</em>
+and <em>psv</em>.  These indicate whether the specific type of transport is
+allowed to pass through the node or not.
+
+<p>
+
+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.
 
 
 <h3><a name="H_1_2_2" title="Ways"></a>Way Tags And Attributes</h3>
@@ -133,6 +147,11 @@ One tag is recognised for each of the different modes of transport: <em>foot</em
 and <em>psv</em>.  These indicate whether the specific type of transport is
 allowed on the highway or not.
 
+<p>
+
+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.
+
 
 <h4><a name="H_1_2_2_3" title="name"></a>The name Tag</h4>
 
@@ -182,13 +201,29 @@ The <em>tunnel</em> tag is used to identify whether a highway is a tunnel and
 therefore set one of the available properties.
 
 
-<h4><a name="H_1_2_2_10" title="oneway"></a>The oneway Tag</h4>
+<h4><a name="H_1_2_2_10" title="footroute"></a>The footroute Tag</h4>
+
+The <em>footroute</em> 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.
+
+
+<h4><a name="H_1_2_2_11" title="bicycleroute"></a>The bicycleroute Tag</h4>
+
+The <em>bicycleroute</em> 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.
+
+
+<h4><a name="H_1_2_2_12" title="oneway"></a>The oneway Tag</h4>
 
 The <em>oneway</em> tag is used to specify that traffic is only allowed to
 travel in one direction.
 
 
-<h4><a name="H_1_2_2_11" title="maxspeed"></a>The maxspeed Tag</h4>
+<h4><a name="H_1_2_2_13" title="maxspeed"></a>The maxspeed Tag</h4>
 
 The <em>maxspeed</em> 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.
 
 
-<h4><a name="H_1_2_2_12" title="maxweight"></a>The maxweight Tag</h4>
+<h4><a name="H_1_2_2_14" title="maxweight"></a>The maxweight Tag</h4>
 
 The <em>maxweight</em> 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.
 
 
-<h4><a name="H_1_2_2_13" title="maxheight"></a>The maxheight Tag</h4>
+<h4><a name="H_1_2_2_15" title="maxheight"></a>The maxheight Tag</h4>
 
 The <em>maxheight</em> 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.
 
 
-<h4><a name="H_1_2_2_14" title="maxwidth"></a>The maxwidth Tag</h4>
+<h4><a name="H_1_2_2_16" title="maxwidth"></a>The maxwidth Tag</h4>
 
 The <em>maxwidth</em> 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.
 
 
-<h4><a name="H_1_2_2_15" title="maxlength"></a>The maxlength Tag</h4>
+<h4><a name="H_1_2_2_17" title="maxlength"></a>The maxlength Tag</h4>
 
 The <em>maxlength</em> 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.
 
 
 <h3><a name="H_1_2_3" title="Relations"></a>Relation Tags And Attributes</h3>
 
-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 <em>id</em> attribute is used so
+that relations that are members of other relations can be identified.
+
+
+<h4><a name="H_1_2_3_1" title="footroute"></a>The footroute Tag</h4>
+
+The <em>footroute</em> tag is used to identify whether a relation defines a
+walking route and therefore should be applied to the individual member highways.
+
+
+<h4><a name="H_1_2_3_2" title="bicycleroute"></a>The bicycleroute Tag</h4>
+
+The <em>bicycleroute</em> tag is used to identify whether a relation defines a
+bicycle route and therefore should be applied to the individual member highways.
 
 
 <h2><a name="H_1_3" title="Tag Transformations"></a>Tag Transformations</h2>
@@ -243,7 +292,106 @@ sequence and this section of the document is arranged in the same order.
 
 <h3><a name="H_1_3_1" title="Nodes"></a>Node Tag Transformations</h3>
 
-No transformations are applicable since no node tags are recognised.
+<h4><a name="H_1_3_1_1" title="Barrier Defaults"></a>Barrier Defaults</h4>
+
+The first part of the tag transformations is to decide on defaults for each type
+of node.  This uses the <em>barrier</em> tag in the OSM file and converts it into
+a default set of disallowed transport types.
+
+<p>
+
+<table>
+  <caption>Transport types through different barrier types</caption>
+  <tr>
+    <th class="left">Barrier
+    <th class="center">foot
+    <th class="center">horse
+    <th class="center">bicycle
+    <th class="center">wheelchair
+    <th class="center">moped
+    <th class="center">motorbike
+    <th class="center">motorcar
+    <th class="center">goods
+    <th class="center">hgv
+    <th class="center">psv
+  <tr>
+    <td class="left">bollard
+    <td class="center">yes
+    <td class="center">yes
+    <td class="center">yes
+    <td class="center">yes
+    <td class="center">yes
+    <td class="center">yes
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+  <tr>
+    <td class="left">kissing_gate
+    <td class="center">yes
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+  <tr>
+    <td class="left">stile
+    <td class="center">yes
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+  <tr>
+    <td class="left">turnstile
+    <td class="center">yes
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+    <td class="center">no
+</table>
+
+<h4><a name="H_1_3_1_2" title="Generic access"></a>Generic Access Permissions</h4>
+
+The <em>access</em> tag is used to specify the default access restrictions
+through the node.  If the tag value is <em>no</em> or <em>private</em> then all
+transport types are denied access (later tag transformation rules may add
+specific transport types back again).
+
+
+<h4><a name="H_1_3_1_3" title="Other access"></a>Other Access Permissions</h4>
+
+A tag named <em>vehicle</em> means any of the <em>bicycle</em>, <em>moped</em>,
+<em>motorbike</em>, <em>motorcar</em>, <em>goods</em>, <em>hgv</em>
+and <em>psv</em> transport types.  A tag named <em>motor_vehicle</em> is
+transformed to mean any vehicle except a <em>bicycle</em>.
+
+
+<h4><a name="H_1_3_1_4" title="Specific access"></a>Specific Access Permissions</h4>
+
+The final part of the access permissions is to use the specific transport type
+tags.
+
+<p>
+
+One tag is recognised for each of the different modes of transport: <em>foot</em>,
+<em>horse</em>, <em>bicycle</em>, <em>wheelchair</em>, <em>moped</em>,
+<em>motorbike</em>, <em>motorcar</em>, <em>goods</em>, <em>hgv</em>
+and <em>psv</em>.  These indicate whether the specific type of transport is
+allowed through the node or not.
 
 
 <h3><a name="H_1_3_2" title="Ways"></a>Way Tag Transformations</h3>
@@ -252,9 +400,9 @@ No transformations are applicable since no node tags are recognised.
 <h4><a name="H_1_3_2_1" title="Highway Defaults"></a>Highway Defaults</h4>
 
 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 <em>highway</em> tag in the OSM file and maps it into
+one of the <em>highway</em> tags that are recognised by Routino, defining the
+default allowed transport types and adding a number of properties.
 
 <p>
 
@@ -542,7 +690,7 @@ highway type.
 <h4><a name="H_1_3_2_2" title="Generic access"></a>Generic Access Permissions</h4>
 
 The <em>access</em> 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.
 
 <h3><a name="H_1_3_3" title="Relations"></a>Relation Tag Transformations</h3>
 
-No transformations are applicable since no relation tags are recognised.
+<h4><a name="H_1_3_3_1" title="Routes"></a>Routes</h4>
+
+The <em>route</em> 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.
+
+<p>
+
+The tag transformations that are applied for route relations are defined in the
+table below.
+
+<p>
+
+<table>
+  <caption>Route properties from different route types</caption>
+  <tr>
+    <th class="center">Relation Tag
+    <th class="center">footroute Property
+    <th class="center">bicycleroute Property
+  <tr>
+    <td class="center">foot
+    <td class="center">yes
+    <td class="center">no
+  <tr>
+    <td class="center">walking
+    <td class="center">yes
+    <td class="center">no
+  <tr>
+    <td class="center">hiking
+    <td class="center">yes
+    <td class="center">no
+  <tr>
+    <td class="center">bicycle
+    <td class="center">no
+    <td class="center">yes
+  <tr>
+    <td class="center">bicycle;foot or foot;bicycle
+    <td class="center">yes
+    <td class="center">yes
+</table>
 
 </div>
 
index dc75888..873a5c3 100644 (file)
@@ -62,9 +62,10 @@ database that is used for routing.
 <pre class="boxed">
 Usage: planetsplitter [--help]
                       [--dir=&lt;dirname&gt;] [--prefix=&lt;name&gt;]
-                      [--slim] [--sort-ram-size=&lt;size&gt;]
+                      [--sort-ram-size=&lt;size&gt;]
                       [--tmpdir=&lt;dirname&gt;]
                       [--parse-only | --process-only]
+                      [--loggable]
                       [--max-iterations=&lt;number&gt;]
                       [--tagging=&lt;filename&gt;]
                       [&lt;filename.osm&gt; ...]
@@ -79,16 +80,9 @@ Usage: planetsplitter [--help]
   <dt>--prefix=&lt;name&gt;
   <dd>Sets the filename prefix for the files that are created.
     Defaults to no prefix.
-  <dt>--slim
-  <dd>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.
   <dt>--sort-ram-size=&lt;size&gt;
   <dd>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.
   <dt>--tmpdir=&lt;dirname&gt;
   <dd>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
@@ -99,12 +93,19 @@ Usage: planetsplitter [--help]
   <dt>--process-only
   <dd>Don't read in any files but process the existing temporary file into the
     routing database.
+  <dt>--loggable
+  <dd>Print progress messages that are suitable for logging to a file; normally
+    an incrementing counter is printed which is more suitable for realtime
+    display than logging.
   <dt>--max-iterations=&lt;number&gt;
   <dd>The maximum number of iterations to use when generating super-nodes and
     super-segments.  Defaults to 10 which is normally enough.
   <dt>--tagging=&lt;filename&gt;
-  <dd>The name of the XML file containing the tagging rules (defaults to
-    'tagging.xml' with '--dirname' and '--prefix' options).
+  <dd>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.
   <dt>&lt;filename.osm&gt; ...
   <dd>Specifies the filename(s) to read data from, by default data is read from
     the standard input.
@@ -116,6 +117,15 @@ Usage: planetsplitter [--help]
 achieved by editing the tagging rules file to not output unwwanted data.</i>
 
 <p>
+<i>Note: In version 1.5 of Routino the --slim option has been removed but at
+compilation time a separate program called <em>planetsplitter-slim</em> 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.</i>
+
+<p>
 Example usage:
 
 <pre class="boxed">
@@ -137,7 +147,7 @@ Usage: router [--help | --help-profile | --help-profile-xml |
               [--dir=&lt;dirname&gt;] [--prefix=&lt;name&gt;]
               [--profiles=&lt;filename&gt;] [--translations=&lt;filename&gt;]
               [--exact-nodes-only]
-              [--quiet]
+              [--loggable | --quiet]
               [--output-html]
               [--output-gpx-track] [--output-gpx-route]
               [--output-text] [--output-text-all]
@@ -178,19 +188,25 @@ Usage: router [--help | --help-profile | --help-profile-xml |
   <dd>Sets the filename prefix for the files in the local database.
     Defaults to no prefix.
   <dt>--profiles=&lt;filename&gt;
-  <dd>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.
+  <dd>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.
   <dt>--translations=&lt;filename&gt;
   <dd>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.
   <dt>--exact-nodes-only
   <dd>When processing the specified latitude and longitude points only select
     the nearest node instead of finding the nearest point within a segment
     (quicker but less accurate unless the points are already near nodes).
+  <dt>--loggable
+  <dd>Print progress messages that are suitable for logging to a file; normally
+    an incrementing counter is printed which is more suitable for realtime
+    display than logging.
   <dt>--quiet
   <dd>Don't generate any screen output while running (useful for running in a script).
   <dt>--language=&lt;lang&gt;
@@ -256,6 +272,7 @@ Usage: router [--help | --help-profile | --help-profile-xml |
       <li>cycleway     = Cycleway
       <li>path         = Path
       <li>steps        = Steps
+      <li>ferry        = Ferry
     </ul>
     Default value depends on the profile selected by the --transport option.
   <dt>--speed-&lt;highway&gt;=&lt;speed&gt;
@@ -266,10 +283,12 @@ Usage: router [--help | --help-profile | --help-profile-xml |
       property
     The value of &lt;property&gt; can be selected from:
     <ul>
-      <li>paved     = Paved (suitable for normal wheels)
-      <li>multilane = Multiple lanes
-      <li>bridge    = Bridge
-      <li>tunnel    = Tunnel
+      <li>paved        = Paved (suitable for normal wheels)
+      <li>multilane    = Multiple lanes
+      <li>bridge       = Bridge
+      <li>tunnel       = Tunnel
+      <li>footroute    = A route marked for foot travel
+      <li>bicycleroute = A route marked for bicycle travel
     </ul>
     Default value depends on the profile selected by the --transport option.
   <dt>--oneway=[0|1]
@@ -295,6 +314,12 @@ Usage: router [--help | --help-profile | --help-profile-xml |
 </dl>
 
 <p>
+<i>Note: In version 1.5 of Routino a slim option has been added and at
+compilation time a separate program called <em>router-slim</em> is created that
+operates in slim mode.  In slim mode the database files are read as needed
+rather than being mapped into memory.</i>
+
+<p>
 The meaning of the &lt;preference&gt; 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 +327,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.
 
 <p>
 Example usage (motorbike journey, scenic route, not very fast):
@@ -398,6 +425,12 @@ Usage: filedumper [--help]
     </dl>
 </dl>
 
+<p>
+<i>Note: In version 1.5 of Routino a slim option has been added and at
+compilation time a separate program called <em>filedumper-slim</em> is created
+that operates in slim mode.  In slim mode the database files are read as needed
+rather than being mapped into memory.</i>
+
 
 <h3><a name="H_1_1_4"></a>tagmodifier</h3>
 
@@ -406,6 +439,7 @@ for test purposes.
 
 <pre class="boxed">
 Usage: tagmodifier [--help]
+                   [--loggable]
                    [--tagging=&lt;filename&gt;]
                    [&lt;filename.osm&gt;]
 </pre>
@@ -413,6 +447,10 @@ Usage: tagmodifier [--help]
 <dl>
   <dt>--help
   <dd>Prints out the help information.
+  <dt>--loggable
+  <dd>Print progress messages that are suitable for logging to a file; normally
+    an incrementing counter is printed which is more suitable for realtime
+    display than logging.
   <dt>--tagging=&lt;filename&gt;
   <dd>The name of the XML file containing the tagging rules (defaults to
     'tagging.xml' in the current directory).
index 49e583e..76a4ea8 100644 (file)
@@ -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.43 2010/11/13 14:22:28 amb Exp $
 #
 # Source code Makefile
 #
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-# 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
@@ -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,9 +74,9 @@ 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 \
+                  files.o logging.o \
                   results.o queue.o sorting.o \
                   xmlparse.o tagging.o osmparser.o
 
@@ -83,28 +85,62 @@ 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 logging.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 \
-          files.o profiles.o xmlparse.o \
-          optimiser.o output.o results.o queue.o translations.o
+          nodes.o segments.o ways.o types.o fakes.o \
+          optimiser.o output.o \
+          files.o logging.o profiles.o xmlparse.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 logging.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 logging.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 logging.o xmlparse.o
+
+filedumper-slim : $(FILEDUMPER_SLIM_OBJ)
+       $(LD) $(FILEDUMPER_SLIM_OBJ) -o $@ $(LDFLAGS)
+
+########
+
 TAGMODIFIER_OBJ=tagmodifier.o \
-               files.o \
+               files.o logging.o \
                 xmlparse.o tagging.o
 
 tagmodifier : $(TAGMODIFIER_OBJ)
@@ -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 (file)
index 0000000..4d4df3c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#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(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
+    return(node1);
+
+ if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
+    return(node2);
+
+ if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
+   {
+    if(dist1<dist2)
+       return(node1);
+    else
+       return(node2);
+   }
+
+ /* Create the fake node */
+
+ fakenode=NODE_FAKE+point;
+
+ GetLatLong(nodes,node1,&lat1,&lon1);
+ GetLatLong(nodes,node2,&lat2,&lon2);
+
+ if(lat1>3 && lat2<-3)
+    lat2+=2*M_PI;
+ else if(lat1<-3 && lat2>3)
+    lat1+=2*M_PI;
+
+ 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);
+}
index 463ab19..c1c67ec 100644 (file)
@@ -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.
 
 #include <time.h>
 
 #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;arg<argc;arg++)
    {
     if(!strcmp(argv[arg],"--help"))
-       print_usage(1);
+       print_usage(1,NULL,NULL);
     else if(!strncmp(argv[arg],"--dir=",6))
        dirname=&argv[arg][6];
     else if(!strncmp(argv[arg],"--prefix=",9))
@@ -110,11 +111,11 @@ int main(int argc,char** argv)
     else if(!strncmp(argv[arg],"--way=",6))
        ;
     else
-       print_usage(0);
+       print_usage(0,argv[arg],NULL);
    }
 
- if(!option_statistics && !option_visualiser && !option_dump && !option_dump_osm)
-    print_usage(0);
+ if((option_statistics + option_visualiser + option_dump + option_dump_osm)!=1)
+    print_usage(0,NULL,"Must choose --visualiser, --statistics, --dump or --dump-osm.");
 
  /* Load in the data - Note: No error checking because Load*List() will call exit() in case of an error. */
 
@@ -129,16 +130,10 @@ int main(int argc,char** argv)
  if(option_visualiser)
    {
     if(coordcount!=4)
-      {
-       fprintf(stderr,"The --visualiser option must have --latmin, --latmax, --lonmin, --lonmax.\n");
-       exit(1);
-      }
+       print_usage(0,NULL,"The --visualiser option must have --latmin, --latmax, --lonmin, --lonmax.\n");
 
     if(!option_data)
-      {
-       fprintf(stderr,"The --visualiser option must have --data.\n");
-       exit(1);
-      }
+       print_usage(0,NULL,"The --visualiser option must have --data.\n");
 
     if(!strcmp(option_data,"junctions"))
        OutputJunctions(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
@@ -157,10 +152,7 @@ int main(int argc,char** argv)
     else if(!strcmp(option_data,"length"))
        OutputLengthLimits(OSMNodes,OSMSegments,OSMWays,latmin,latmax,lonmin,lonmax);
     else
-      {
-       fprintf(stderr,"Unrecognised data option '%s' with --visualiser.\n",option_data);
-       exit(1);
-      }
+       print_usage(0,option_data,NULL);
    }
 
  /* Print out statistics */
@@ -200,16 +192,16 @@ int main(int argc,char** argv)
     printf("\n");
 
     printf("sizeof(Node) =%9d Bytes\n",sizeof(Node));
-    printf("Number       =%9d\n",OSMNodes->number);
-    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;arg<argc;arg++)
        if(!strcmp(argv[arg],"--node=all"))
          {
-          for(item=0;item<OSMNodes->number;item++)
+          for(item=0;item<OSMNodes->file.number;item++)
              print_node(OSMNodes,item);
          }
        else if(!strncmp(argv[arg],"--node=",7))
          {
           item=atoi(&argv[arg][7]);
 
-          if(item>=0 && item<OSMNodes->number)
+          if(item>=0 && item<OSMNodes->file.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;item<OSMSegments->number;item++)
+          for(item=0;item<OSMSegments->file.number;item++)
              print_segment(OSMSegments,item);
          }
        else if(!strncmp(argv[arg],"--segment=",10))
          {
           item=atoi(&argv[arg][10]);
 
-          if(item>=0 && item<OSMSegments->number)
+          if(item>=0 && item<OSMSegments->file.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;item<OSMWays->number;item++)
+          for(item=0;item<OSMWays->file.number;item++)
              print_way(OSMWays,item);
          }
        else if(!strncmp(argv[arg],"--way=",6))
          {
           item=atoi(&argv[arg][6]);
 
-          if(item>=0 && item<OSMWays->number)
+          if(item>=0 && item<OSMWays->file.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];node<OSMNodes->offsets[llbin+1];node++)
+             index1=LookupNodeOffset(OSMNodes,llbin);
+             index2=LookupNodeOffset(OSMNodes,llbin+1);
+
+             for(item=index1;item<index2;item++)
                {
-                double lat=latlong_to_radians(bin_to_latlong(OSMNodes->latzero+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 && lat<latmax && lon>lonmin && lon<lonmax)
                   {
                    Segment *segment;
 
-                   print_node_osm(OSMNodes,node);
+                   print_node_osm(OSMNodes,item);
 
-                   segment=FirstSegment(OSMSegments,OSMNodes,node);
+                   segment=FirstSegment(OSMSegments,OSMNodes,item);
 
                    while(segment)
                      {
-                      if(node>OtherNode(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;item<OSMNodes->number;item++)
+       for(item=0;item<OSMNodes->file.number;item++)
           print_node_osm(OSMNodes,item);
 
-       for(item=0;item<OSMSegments->number;item++)
-          if(!option_no_super || IsNormalSegment(LookupSegment(OSMSegments,item)))
+       for(item=0;item<OSMSegments->file.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("  <node id='%lu' lat='%.7f' lon='%.7f' version='1'>\n",(unsigned long)item+1,radians_to_degrees(latitude),radians_to_degrees(longitude));
     printf("    <tag k='routino:super' v='yes' />\n");
+
+    for(i=1;i<Transport_Count;i++)
+       if(!(node->allow & ALLOWED(i)))
+          printf("    <tag k='%s' v='no' />\n",TransportName(i));
+
     printf("  </node>\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("  <way id='%lu' version='1'>\n",(unsigned long)item+1);
@@ -527,8 +530,8 @@ static void print_segment_osm(Segments *segments,index_t item,Ways *ways)
 
  printf("    <tag k='highway' v='%s' />\n",HighwayName(HIGHWAY(way->type)));
 
- if(IsNormalSegment(segment) && WayNamed(ways,way))
-    printf("    <tag k='name' v='%s' />\n",ParseXML_Encode_Safe_XML(WayNameHighway(ways,way)));
+ if(IsNormalSegment(segment) && *WayName(ways,way))
+    printf("    <tag k='name' v='%s' />\n",ParseXML_Encode_Safe_XML(WayName(ways,way)));
 
  for(i=1;i<Transport_Count;i++)
     if(way->allow & 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=<latmin> --latmax=<latmax>\n"
          "                               --lonmin=<lonmin> --lonmax=<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"
index ce595ab..fc42a27 100644 (file)
@@ -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.25 2010/10/31 17:52:40 amb Exp $
 
  Functions to handle files.
 
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  ***************************************/
 
+#include <assert.h>
 
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -31,7 +33,7 @@
 #include <sys/mman.h>
 #include <sys/types.h>
 
-#include "functions.h"
+#include "files.h"
 
 
 /*+ A structure to contain the list of memory mapped files. +*/
@@ -64,7 +66,7 @@ static int nmappedfiles=0;
 
 char *FileName(const char *dirname,const char *prefix, const char *name)
 {
- char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name));
+ char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1);
 
  sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
 
@@ -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 (file)
index 0000000..6edf55c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#ifndef FILES_H
+#define FILES_H    /*+ To stop multiple inclusions. +*/
+
+#include <unistd.h>
+#include <sys/types.h>
+
+
+/* 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 */
index 1ff10de..ffa499e 100644 (file)
@@ -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
 
 #ifndef FUNCTIONS_H
 #define FUNCTIONS_H    /*+ To stop multiple inclusions. +*/
 
-#include <sys/types.h>
-#include <stdio.h>
-
 #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 */
index bb92183..4cf7594 100644 (file)
@@ -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/logging.c b/src/logging.c
new file mode 100644 (file)
index 0000000..bb43c07
--- /dev/null
@@ -0,0 +1,253 @@
+/***************************************
+ $Header: /home/amb/routino/src/RCS/logging.c,v 1.1 2010/11/13 14:22:40 amb Exp $
+
+ Functions to handle logging functions.
+
+ 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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "logging.h"
+
+
+/*+ The option to print the output in a way that allows logging to a file. +*/
+int option_loggable=0;
+
+
+/* Local functions */
+
+static void vfprintf_first(FILE *file,const char *format,va_list ap);
+static void vfprintf_middle(FILE *file,const char *format,va_list ap);
+static void vfprintf_last(FILE *file,const char *format,va_list ap);
+
+/* Local variables */
+
+static int printed_length=0;
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the first message in an overwriting sequence.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void printf_first(const char *format, ...)
+{
+ va_list ap;
+
+ if(option_loggable)
+    return;
+
+ va_start(ap,format);
+
+ vfprintf_first(stdout,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the middle message in an overwriting sequence.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void printf_middle(const char *format, ...)
+{
+ va_list ap;
+
+ if(option_loggable)
+    return;
+
+ va_start(ap,format);
+
+ vfprintf_middle(stdout,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the last message in an overwriting sequence.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void printf_last(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap,format);
+
+ vfprintf_last(stdout,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the first message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void fprintf_first(FILE *file,const char *format, ...)
+{
+ va_list ap;
+
+ if(option_loggable)
+    return;
+
+ va_start(ap,format);
+
+ vfprintf_first(file,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the middle message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void fprintf_middle(FILE *file,const char *format, ...)
+{
+ va_list ap;
+
+ if(option_loggable)
+    return;
+
+ va_start(ap,format);
+
+ vfprintf_middle(file,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the last message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  ... The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void fprintf_last(FILE *file,const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap,format);
+
+ vfprintf_last(file,format,ap);
+
+ va_end(ap);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the first message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  va_list ap The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static void vfprintf_first(FILE *file,const char *format,va_list ap)
+{
+ int retval;
+
+ retval=vfprintf(file,format,ap);
+ fflush(file);
+
+ if(retval>0)
+    printed_length=retval;
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the middle message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  va_list ap The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static void vfprintf_middle(FILE *file,const char *format,va_list ap)
+{
+ int retval;
+
+ putchar('\r');
+ retval=vfprintf(file,format,ap);
+ fflush(file);
+
+ if(retval>0)
+    printed_length=retval;
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Print the last message in an overwriting sequence.
+
+  FILE *file The file to write to.
+
+  const char *format The format string.
+
+  va_list ap The other arguments.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static void vfprintf_last(FILE *file,const char *format,va_list ap)
+{
+ int retval;
+
+ if(!option_loggable)
+    putchar('\r');
+ retval=vfprintf(file,format,ap);
+
+ if(retval>0)
+    while(retval++<printed_length)
+       putchar(' ');
+
+ putchar('\n');
+ fflush(file);
+}
diff --git a/src/logging.h b/src/logging.h
new file mode 100644 (file)
index 0000000..e3fe945
--- /dev/null
@@ -0,0 +1,61 @@
+/***************************************
+ $Header: /home/amb/routino/src/RCS/logging.h,v 1.2 2010/11/13 14:50:33 amb Exp $
+
+ Header file for logging 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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#ifndef LOGGING_H
+#define LOGGING_H    /*+ To stop multiple inclusions. +*/
+
+#include <stdio.h>
+
+
+/* Variables */
+
+extern int option_loggable;
+
+
+/* In logging.c */
+
+#ifdef __GNUC__
+
+void printf_first(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+void printf_middle(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+void printf_last(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+
+void fprintf_first(FILE *file,const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+void fprintf_middle(FILE *file,const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+void fprintf_last(FILE *file,const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+
+#else
+
+void printf_first(const char *format, ...);
+void printf_middle(const char *format, ...);
+void printf_last(const char *format, ...);
+
+void fprintf_first(FILE *file,const char *format, ...);
+void fprintf_middle(FILE *file,const char *format, ...);
+void fprintf_last(FILE *file,const char *format, ...);
+
+#endif
+
+
+#endif /* LOGGING_H */
index 7430d62..f04678b 100644 (file)
@@ -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.
 
 #include <stdlib.h>
 #include <math.h>
 
-#include "profiles.h"
 #include "nodes.h"
 #include "segments.h"
 #include "ways.h"
-#include "functions.h"
+
+#include "files.h"
+#include "profiles.h"
 
 
 /*++++++++++++++++++++++++++++++++++++++
 
 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)<delta && abs(lonb-lonbin)<delta)
              continue;
 
-          llbin=lonb*nodes->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];i<nodes->offsets[llbin+1];i++)
+          index1=LookupNodeOffset(nodes,llbin);
+          index2=LookupNodeOffset(nodes,llbin+1);
+
+          for(i=index1;i<index2;i++)
             {
-             double lat=latlong_to_radians(bin_to_latlong(nodes->latzero+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)<delta && abs(lonb-lonbin)<delta)
              continue;
 
-          llbin=lonb*nodes->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];i<nodes->offsets[llbin+1];i++)
+          index1=LookupNodeOffset(nodes,llbin);
+          index2=LookupNodeOffset(nodes,llbin+1);
+
+          for(i=index1;i<index2;i++)
             {
-             double lat1=latlong_to_radians(bin_to_latlong(nodes->latzero+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]<index)       /* Mid point is too low */
+    offset=LookupNodeOffset(nodes,nodes->file.latbins*mid);
+
+    if(offset<index)                    /* Mid point is too low */
        start=mid;
-    else if(nodes->offsets[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(lonbin<nodes->lonbins && nodes->offsets[lonbin*nodes->latbins]==nodes->offsets[(lonbin+1)*nodes->latbins])
+ while(lonbin<nodes->file.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]<index)      /* Mid point is too low */
+    offset=LookupNodeOffset(nodes,lonbin*nodes->file.latbins+mid);
+
+    if(offset<index)                    /* Mid point is too low */
        start=mid;
-    else if(nodes->offsets[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(latbin<nodes->latbins && nodes->offsets[lonbin*nodes->latbins+latbin]==nodes->offsets[lonbin*nodes->latbins+latbin+1])
+ while(latbin<nodes->file.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));
 }
index 8bfc2b6..a1722cd 100644 (file)
@@ -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 <stdint.h>
 
 #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 */
index cc1e0a2..257a589 100644 (file)
@@ -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.76 2010/11/13 14:22:28 amb Exp $
 
  Extented Node data type functions.
 
 #include <sys/stat.h>
 
 #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 "logging.h"
+#include "functions.h"
 
 
 /* Variables */
 
-/*+ The command line '--slim' option. +*/
-extern int option_slim;
-
 /*+ The command line '--tmpdir' option or its default value. +*/
 extern char *option_tmpdirname;
 
@@ -76,22 +79,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 +124,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 +146,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 +155,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->xnumber<NODE_FAKE); /* NODE_FAKE marks the high-water mark for real nodes. */
 }
 
 
@@ -166,14 +186,9 @@ void SortNodeList(NodesX* nodesx)
 {
  int fd;
 
- /* Check the start conditions */
-
- assert(!nodesx->idata);        /* Must not have idata filled in => unsorted */
-
  /* Print the start message */
 
- printf("Sorting Nodes");
- fflush(stdout);
+ printf_first("Sorting Nodes");
 
  /* Close the files and re-open them (finished appending) */
 
@@ -182,7 +197,7 @@ void SortNodeList(NodesX* nodesx)
 
  DeleteFile(nodesx->filename);
 
- fd=OpenFile(nodesx->filename);
+ fd=OpenFileNew(nodesx->filename);
 
  /* Allocate the array of indexes */
 
@@ -205,8 +220,7 @@ void SortNodeList(NodesX* nodesx)
 
  /* Print the final message */
 
- printf("\rSorted Nodes: Nodes=%d Duplicates=%d\n",nodesx->xnumber,nodesx->xnumber-nodesx->number);
- fflush(stdout);
+ printf_last("Sorted Nodes: Nodes=%d Duplicates=%d",nodesx->xnumber,nodesx->xnumber-nodesx->number);
 }
 
 
@@ -271,8 +285,7 @@ void SortNodeListGeographically(NodesX* nodesx)
 
  /* Print the start message */
 
- printf("Sorting Nodes Geographically");
- fflush(stdout);
+ printf_first("Sorting Nodes Geographically");
 
  /* Allocate the memory for the geographical offsets array */
 
@@ -287,7 +300,7 @@ void SortNodeListGeographically(NodesX* nodesx)
 
  DeleteFile(nodesx->filename);
 
- fd=OpenFile(nodesx->filename);
+ fd=OpenFileNew(nodesx->filename);
 
  /* Sort geographically */
 
@@ -309,8 +322,7 @@ void SortNodeListGeographically(NodesX* nodesx)
 
  /* Print the final message */
 
- printf("\rSorted Nodes Geographically \n");
- fflush(stdout);
+ printf_last("Sorted Nodes Geographically");
 }
 
 
@@ -345,7 +357,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 +416,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 +460,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,14 +475,9 @@ 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");
- fflush(stdout);
+ printf_first("Checking: Nodes=0");
 
  /* While we are here we can work out the range of data */
 
@@ -516,7 +490,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)))
@@ -545,10 +519,7 @@ void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx)
     total++;
 
     if(!(total%10000))
-      {
-       printf("\rChecking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
-       fflush(stdout);
-      }
+       printf_middle("Checking: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
    }
 
  /* Close the files and re-open them */
@@ -581,8 +552,7 @@ void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx)
 
  /* Print the final message */
 
- printf("\rChecked: Nodes=%d Highway=%d not-Highway=%d  \n",total,highway,nothighway);
- fflush(stdout);
+ printf_last("Checked: Nodes=%d Highway=%d not-Highway=%d",total,highway,nothighway);
 }
 
 
@@ -598,44 +568,48 @@ 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");
- fflush(stdout);
+ printf_first("Creating Real Nodes: Nodes=0");
 
  /* 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;i<nodesx->number;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))
-      {
-       printf("\rCreating Real Nodes: Nodes=%d",i+1);
-       fflush(stdout);
-      }
+       printf_middle("Creating Real Nodes: Nodes=%d",i+1);
    }
 
  /* Free the unneeded memory */
@@ -645,13 +619,13 @@ 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 */
 
- printf("\rCreating Real Nodes: Nodes=%d \n",nodesx->number);
- fflush(stdout);
+ printf_last("Creating Real Nodes: Nodes=%d",nodesx->number);
 }
 
 
@@ -667,23 +641,19 @@ 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 */
 
- printf("Indexing Segments: Segments=0");
- fflush(stdout);
+ printf_first("Indexing Segments: Segments=0");
 
  /* 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 +662,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 +697,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 +718,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,37 +748,39 @@ 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);
       }
 
     if(!((i+1)%10000))
-      {
-       printf("\rIndexing Segments: Segments=%d",i+1);
-       fflush(stdout);
-      }
+       printf_middle("Indexing Segments: Segments=%d",i+1);
    }
 
  /* 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 */
 
- printf("\rIndexed Segments: Segments=%d \n",segmentsx->number);
- fflush(stdout);
+ printf_last("Indexed Segments: Segments=%d ",segmentsx->number);
 }
 
 
@@ -811,84 +796,63 @@ 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");
- fflush(stdout);
+ printf_first("Writing Nodes: Nodes=0");
 
  /* Map into memory */
 
- if(!option_slim)
-    nodesx->xdata=MapFile(nodesx->filename);
-
- /* Count the number of super-nodes */
-
- for(i=0;i<nodesx->number;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;i<nodes->number;i++)
+ for(i=0;i<nodesx->number;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));
 
     if(!((i+1)%10000))
-      {
-       printf("\rWriting Nodes: Nodes=%d",i+1);
-       fflush(stdout);
-      }
+       printf_middle("Writing Nodes: Nodes=%d",i+1);
    }
 
+ /* 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);
- fflush(stdout);
-
- /* Free the fake Nodes */
-
- free(nodes);
+ printf_last("Wrote Nodes: Nodes=%d",nodesx->number);
 }
index 2dc40a4..35908af 100644 (file)
@@ -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.
 
 
 #include <stdint.h>
 
-#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 */
index cdb5986..d66ed44 100644 (file)
@@ -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.94 2010/11/13 14:22:28 amb Exp $
 
  Routing optimiser.
 
 #include <stdio.h>
 
 #include "types.h"
-#include "functions.h"
 #include "nodes.h"
 #include "segments.h"
 #include "ways.h"
+
+#include "logging.h"
+#include "functions.h"
 #include "results.h"
 
 
@@ -60,13 +62,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 +128,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 +147,7 @@ Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t star
        segment_pref=profile->highway[HIGHWAY(way->type)];
 
        for(i=1;i<Property_Count;i++)
-          if(ways->props & PROPERTIES(i))
+          if(ways->file.props & PROPERTIES(i))
             {
              if(way->props & PROPERTIES(i))
                 segment_pref*=profile->props_yes[i];
@@ -155,6 +158,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 +184,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 +204,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,20 +275,18 @@ 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)
-   {
-    printf("Routing: Super-Nodes checked = 0");
-    fflush(stdout);
-   }
+    printf_first("Routing: Super-Nodes checked = 0");
 
  /* Set up the finish conditions */
 
@@ -349,7 +364,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 +383,7 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg
        segment_pref=profile->highway[HIGHWAY(way->type)];
 
        for(i=1;i<Property_Count;i++)
-          if(ways->props & PROPERTIES(i))
+          if(ways->file.props & PROPERTIES(i))
             {
              if(way->props & PROPERTIES(i))
                 segment_pref*=profile->props_yes[i];
@@ -379,6 +394,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 +417,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 +447,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)))
             {
@@ -457,20 +477,14 @@ Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *beg
       endloop:
 
        if(!option_quiet && !(results->number%10000))
-         {
-          printf("\rRouting: Super-Nodes checked = %d",results->number);
-          fflush(stdout);
-         }
+          printf_middle("Routing: Super-Nodes checked = %d",results->number);
 
        segment=NextSegment(segments,segment,node1);
       }
    }
 
  if(!option_quiet)
-   {
-    printf("\rRouting: Super-Nodes checked = %d\n",results->number);
-    fflush(stdout);
-   }
+    printf_last("Routing: Super-Nodes checked = %d",results->number);
 
  /* Finish off the end part of the route. */
 
@@ -520,11 +534,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 +582,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 +601,7 @@ Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t star
        segment_pref=profile->highway[HIGHWAY(way->type)];
 
        for(i=1;i<Property_Count;i++)
-          if(ways->props & PROPERTIES(i))
+          if(ways->file.props & PROPERTIES(i))
             {
              if(way->props & PROPERTIES(i))
                 segment_pref*=profile->props_yes[i];
@@ -597,6 +612,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 +635,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 +650,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 +704,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 +752,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 +771,7 @@ Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t fin
        segment_pref=profile->highway[HIGHWAY(way->type)];
 
        for(i=1;i<Property_Count;i++)
-          if(ways->props & PROPERTIES(i))
+          if(ways->file.props & PROPERTIES(i))
             {
              if(way->props & PROPERTIES(i))
                 segment_pref*=profile->props_yes[i];
@@ -752,6 +782,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 +805,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 +820,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))
             {
index 3af039d..03e17b7 100644 (file)
@@ -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.73 2010/11/13 14:22:28 amb Exp $
 
  OSM XML file parser (either JOSM or planet)
 
 
 #include "typesx.h"
 #include "functionsx.h"
+
 #include "nodesx.h"
 #include "segmentsx.h"
 #include "waysx.h"
+#include "relationsx.h"
+
 #include "xmlparse.h"
 #include "tagging.h"
 
+#include "logging.h"
+
 
 /* Macros */
 
@@ -49,14 +54,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 +80,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 +129,7 @@ static xmltag ndType_tag=
 static xmltag memberType_tag=
               {"member",
                3, {"type","ref","role"},
-               NULL,
+               memberType_function,
                {NULL}};
 
 /*+ The wayType type tag. +*/
@@ -231,38 +246,34 @@ 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))
-      {
-       printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
-       fflush(stdout);
-      }
+       printf_middle("Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
+
+    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 +299,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 +325,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);
+}
 
 
 /*++++++++++++++++++++++++++++++++++++++
@@ -341,12 +386,10 @@ static int wayType_function(const char *_tag_,int _type_,const char *id)
     nways++;
 
     if(!(nways%1000))
-      {
-       printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
-       fflush(stdout);
-      }
+       printf_middle("Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
 
     current_tags=NewTagList();
+
     way_nnodes=0;
 
     /* Handle the way information */
@@ -382,27 +425,33 @@ 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++;
 
     if(!(nrelations%1000))
-      {
-       printf("\rReading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
-       fflush(stdout);
-      }
+       printf_middle("Reading: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
+
+    current_tags=NewTagList();
 
-//    current_tags=NewTagList();
-    current_tags=NULL;
+    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,38 +500,146 @@ 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;
 
- printf("\rReading: Lines=0 Nodes=0 Ways=0 Relations=0");
- fflush(stdout);
+ printf_first("Reading: Lines=0 Nodes=0 Ways=0 Relations=0");
 
  retval=ParseXML(file,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE);
 
- printf("\rRead: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld   \n",ParseXML_LineNumber(),nnodes,nways,nrelations);
- fflush(stdout);
+ printf_last("Read: Lines=%ld Nodes=%ld Ways=%ld Relations=%ld",ParseXML_LineNumber(),nnodes,nways,nrelations);
 
  return(retval);
 }
 
 
 /*++++++++++++++++++++++++++++++++++++++
+  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;i<tags->ntags;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 +669,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 +684,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 +911,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;i<tags->ntags;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);
+}
index e40f750..cbada4f 100644 (file)
@@ -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.
 
 #include <unistd.h>
 
 #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,"<TITLE>");
     fprintf(htmlfile,translate_html_title,option_quickest?translate_route_quickest:translate_route_shortest);
     fprintf(htmlfile,"</TITLE>\n");
-    fprintf(htmlfile,"<STYLE type='text/css'>\n");
+    fprintf(htmlfile,"<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
+    fprintf(htmlfile,"<STYLE type=\"text/css\">\n");
     fprintf(htmlfile,"<!--\n");
     fprintf(htmlfile,"   table   {table-layout: fixed; border: none; border-collapse: collapse;}\n");
     fprintf(htmlfile,"   table.c {color: grey; font-size: x-small;} /* copyright */\n");
@@ -323,6 +327,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
       {
        double latitude,longitude;
        Result *nextresult;
+       Segment *nextresultsegment;
 
        if(result->node==results[point]->start)
          {latitude=start_lat; longitude=start_lon;}
@@ -346,25 +351,41 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                 break;
                }
 
+       if(nextresult)
+         {
+          if(IsFakeSegment(nextresult->segment))
+             nextresultsegment=LookupFakeSegment(nextresult->segment);
+          else
+             nextresultsegment=LookupSegment(segments,nextresult->segment,2);
+         }
+       else
+          nextresultsegment=NULL;
+
        if(result->node!=results[point]->start)
          {
           distance_t seg_distance=0;
           duration_t seg_duration=0;
+          Segment *resultsegment;
           Way *resultway;
           int important=0;
 
           /* Cache the values to be printed rather than calculating them repeatedly for each output format */
 
-          char *waynameraw=NULL,*wayname=NULL,*waynamexml=NULL;
+          char *waynameraw=NULL,*waynamexml=NULL;
+          const char *wayname=NULL;
           int bearing_int=0,bearing_next_int=0,turn_int=0;
           char *bearing_str=NULL,*bearing_next_str=NULL,*turn_str=NULL;
 
           /* Get the properties of this segment */
 
-          resultway=LookupWay(ways,result->segment->way);
+          if(IsFakeSegment(result->segment))
+             resultsegment=LookupFakeSegment(result->segment);
+          else
+             resultsegment=LookupSegment(segments,result->segment,3);
+          resultway=LookupWay(ways,resultsegment->way,1);
 
-          seg_distance+=DISTANCE(result->segment->distance);
-          seg_duration+=Duration(result->segment,resultway,profile);
+          seg_distance+=DISTANCE(resultsegment->distance);
+          seg_duration+=Duration(resultsegment,resultway,profile);
           junc_distance+=seg_distance;
           junc_duration+=seg_duration;
           cum_distance+=seg_distance;
@@ -382,10 +403,10 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                {
                 index_t othernode=OtherNode(segment,result->node);
 
-                if(othernode!=result->prev && segment!=result->segment)
+                if(othernode!=result->prev && segment!=resultsegment)
                    if(IsNormalSegment(segment) && (!profile->oneway || !IsOnewayTo(segment,result->node)))
                      {
-                      Way *way=LookupWay(ways,segment->way);
+                      Way *way=LookupWay(ways,segment->way,2);
 
                       if(othernode==result->next) /* the next segment that we follow */
                         {
@@ -426,7 +447,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
 
                 if(!waynameraw)
                   {
-                   waynameraw=WayNameRaw(ways,resultway);
+                   waynameraw=WayName(ways,resultway);
                    if(!*waynameraw)
                       waynameraw=translate_highway[HIGHWAY(resultway->type)];
                   }
@@ -450,13 +471,13 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                   {
                    if(!turn_str)
                      {
-                      turn_int=turn_angle(nodes,result->segment,nextresult->segment,result->node);
+                      turn_int=turn_angle(nodes,resultsegment,nextresultsegment,result->node);
                       turn_str=translate_turn[(4+(22+turn_int)/45)%8];
                      }
 
                    if(!bearing_next_str)
                      {
-                      bearing_next_int=bearing_angle(nodes,nextresult->segment,nextresult->node);
+                      bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
                       bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
                      }
 
@@ -484,7 +505,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                {
                 if(!waynameraw)
                   {
-                   waynameraw=WayNameRaw(ways,resultway);
+                   waynameraw=WayName(ways,resultway);
                    if(!*waynameraw)
                       waynameraw=translate_highway[HIGHWAY(resultway->type)];
                   }
@@ -494,7 +515,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
 
                 if(!bearing_str)
                   {
-                   bearing_int=bearing_angle(nodes,result->segment,result->node);
+                   bearing_int=bearing_angle(nodes,resultsegment,result->node);
                    bearing_str=translate_heading[(4+(22+bearing_int)/45)%8];
                   }
 
@@ -535,19 +556,23 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                    type="Junct";
 
                 if(!wayname)
-                   wayname=(char*)WayNameHighway(ways,resultway);
+                  {
+                   wayname=WayName(ways,resultway);
+                   if(!*wayname)
+                      wayname=HighwayName(HIGHWAY(resultway->type));
+                  }
 
                 if(nextresult)
                   {
                    if(!turn_str)
                      {
-                      turn_int=turn_angle(nodes,result->segment,nextresult->segment,result->node);
+                      turn_int=turn_angle(nodes,resultsegment,nextresultsegment,result->node);
                       turn_str=translate_turn[(4+(22+turn_int)/45)%8];
                      }
 
                    if(!bearing_next_str)
                      {
-                      bearing_next_int=bearing_angle(nodes,nextresult->segment,nextresult->node);
+                      bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
                       bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
                      }
 
@@ -589,17 +614,21 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
                 type="Inter";
 
              if(!wayname)
-                wayname=(char*)WayNameHighway(ways,resultway);
+               {
+                wayname=WayName(ways,resultway);
+                if(!*wayname)
+                   wayname=HighwayName(HIGHWAY(resultway->type));
+               }
 
              if(!bearing_str)
                {
-                bearing_int=bearing_angle(nodes,result->segment,result->node);
+                bearing_int=bearing_angle(nodes,resultsegment,result->node);
                 bearing_str=translate_heading[(4+(22+bearing_int)/45)%8];
                }
 
              fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t%3d\t%4d\t%s\n",
                                  radians_to_degrees(latitude),radians_to_degrees(longitude),
-                                 IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
+                                 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
                                  (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',type,
                                  distance_to_km(seg_distance),duration_to_minutes(seg_duration),
                                  distance_to_km(cum_distance),duration_to_minutes(cum_duration),
@@ -613,7 +642,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
          }
        else if(!cum_distance)
          {
-          int   bearing_next_int=bearing_angle(nodes,nextresult->segment,nextresult->node);
+          int   bearing_next_int=bearing_angle(nodes,nextresultsegment,nextresult->node);
           char *bearing_next_str=translate_heading[(4+(22+bearing_next_int)/45)%8];
 
           /* Print out the very first start point */
@@ -644,7 +673,7 @@ void PrintRoute(Results **results,int nresults,Nodes *nodes,Segments *segments,W
           if(textallfile)
              fprintf(textallfile,"%10.6f\t%11.6f\t%8d%c\t%s\t%5.3f\t%5.2f\t%5.2f\t%5.1f\t\t\t\n",
                                  radians_to_degrees(latitude),radians_to_degrees(longitude),
-                                 IsFakeNode(result->node)?-(result->node&(~NODE_SUPER)):result->node,
+                                 IsFakeNode(result->node)?(NODE_FAKE-result->node):result->node,
                                  (!IsFakeNode(result->node) && IsSuperNode(nodes,result->node))?'*':' ',"Waypt",
                                  0.0,0.0,0.0,0.0);
          }
index 5380455..cba9d4d 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/planetsplitter.c,v 1.73 2010/05/22 18:40:47 amb Exp $
+ $Header: /home/amb/routino/src/RCS/planetsplitter.c,v 1.82 2010/11/13 14:22:28 amb Exp $
 
  OSM planet file splitter.
 
 #include <string.h>
 #include <errno.h>
 
-#include "typesx.h"
 #include "types.h"
-#include "functionsx.h"
-#include "functions.h"
+#include "ways.h"
+
+#include "typesx.h"
 #include "nodesx.h"
 #include "segmentsx.h"
 #include "waysx.h"
+#include "relationsx.h"
 #include "superx.h"
-#include "ways.h"
+
+#include "files.h"
+#include "logging.h"
+#include "functions.h"
+#include "functionsx.h"
 #include "tagging.h"
 
 
 /* Global variables */
 
-/*+ The option to use a slim mode with file-backed read-only intermediate storage. +*/
-int option_slim=0;
-
 /*+ The name of the temporary directory. +*/
 char *option_tmpdirname=NULL;
 
@@ -53,7 +55,7 @@ size_t option_filesort_ramsize=0;
 
 /* Local functions */
 
-static void print_usage(int detail);
+static void print_usage(int detail,const char *argerr,const char *err);
 
 
 /*++++++++++++++++++++++++++++++++++++++
@@ -62,24 +64,23 @@ static void print_usage(int detail);
 
 int main(int argc,char** argv)
 {
- NodesX    *Nodes;
- SegmentsX *Segments,*SuperSegments=NULL,*MergedSegments=NULL;
- WaysX     *Ways;
- int        iteration=0,quit=0;
- int        max_iterations=10;
- char      *dirname=NULL,*prefix=NULL,*tagging=NULL;
- int        option_parse_only=0,option_process_only=0;
- int        option_filenames=0;
- int        arg;
+ NodesX     *Nodes;
+ SegmentsX  *Segments,*SuperSegments=NULL,*MergedSegments=NULL;
+ WaysX      *Ways;
+ RelationsX *Relations;
+ int         iteration=0,quit=0;
+ int         max_iterations=10;
+ char       *dirname=NULL,*prefix=NULL,*tagging=NULL;
+ int         option_parse_only=0,option_process_only=0;
+ int         option_filenames=0;
+ int         arg;
 
  /* Parse the command line arguments */
 
  for(arg=1;arg<argc;arg++)
    {
     if(!strcmp(argv[arg],"--help"))
-       print_usage(1);
-    else if(!strcmp(argv[arg],"--slim"))
-       option_slim=1;
+       print_usage(1,NULL,NULL);
     else if(!strncmp(argv[arg],"--sort-ram-size=",16))
        option_filesort_ramsize=atoi(&argv[arg][16]);
     else if(!strncmp(argv[arg],"--dir=",6))
@@ -92,12 +93,14 @@ int main(int argc,char** argv)
        option_parse_only=1;
     else if(!strcmp(argv[arg],"--process-only"))
        option_process_only=1;
+    else if(!strcmp(argv[arg],"--loggable"))
+       option_loggable=1;
     else if(!strncmp(argv[arg],"--max-iterations=",17))
        max_iterations=atoi(&argv[arg][17]);
     else if(!strncmp(argv[arg],"--tagging=",10))
        tagging=&argv[arg][10];
     else if(argv[arg][0]=='-' && argv[arg][1]=='-')
-       print_usage(0);
+       print_usage(0,argv[arg],NULL);
     else
        option_filenames++;
    }
@@ -105,17 +108,18 @@ int main(int argc,char** argv)
  /* Check the specified command line options */
 
  if(option_parse_only && option_process_only)
-    print_usage(0);
+    print_usage(0,NULL,"Cannot use '--parse-only' and '--process-only' at the same time.");
 
  if(option_filenames && option_process_only)
-    print_usage(0);
+    print_usage(0,NULL,"Cannot use '--process-only' and filenames at the same time.");
 
  if(!option_filesort_ramsize)
    {
-    if(option_slim)
+#if SLIM
        option_filesort_ramsize=64*1024*1024;
-    else
+#else
        option_filesort_ramsize=256*1024*1024;
+#endif
    }
  else
     option_filesort_ramsize*=1024*1024;
@@ -128,24 +132,34 @@ int main(int argc,char** argv)
        option_tmpdirname=dirname;
    }
 
- if(tagging && ExistsFile(tagging))
-    ;
- else if(!tagging && ExistsFile(FileName(dirname,prefix,"tagging.xml")))
-    tagging=FileName(dirname,prefix,"tagging.xml");
-
- if(tagging && ParseXMLTaggingRules(tagging))
+ if(tagging)
    {
-    fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
-    return(1);
+    if(!ExistsFile(tagging))
+      {
+       fprintf(stderr,"Error: The '--tagging' option specifies a file that does not exist.\n");
+       return(1);
+      }
+   }
+ else
+   {
+    if(ExistsFile(FileName(dirname,prefix,"tagging.xml")))
+       tagging=FileName(dirname,prefix,"tagging.xml");
+    else if(ExistsFile(FileName(DATADIR,NULL,"tagging.xml")))
+       tagging=FileName(DATADIR,NULL,"tagging.xml");
+    else
+      {
+       fprintf(stderr,"Error: The '--tagging' option was not used and the default 'tagging.xml' does not exist.\n");
+       return(1);
+      }
    }
 
- if(!tagging)
+ if(ParseXMLTaggingRules(tagging))
    {
-    fprintf(stderr,"Error: Cannot run without reading some tagging rules.\n");
+    fprintf(stderr,"Error: Cannot read the tagging rules in the file '%s'.\n",tagging);
     return(1);
    }
 
- /* Create new node, segment and way variables */
+ /* Create new node, segment, way and relation variables */
 
  Nodes=NewNodeList(option_parse_only||option_process_only);
 
@@ -153,6 +167,8 @@ int main(int argc,char** argv)
 
  Ways=NewWayList(option_parse_only||option_process_only);
 
+ Relations=NewRelationList(option_parse_only||option_process_only);
+
  /* Parse the file */
 
  if(option_filenames)
@@ -175,7 +191,7 @@ int main(int argc,char** argv)
        printf("\nParse OSM Data [%s]\n==============\n\n",argv[arg]);
        fflush(stdout);
 
-       if(ParseOSM(file,Nodes,Segments,Ways))
+       if(ParseOSM(file,Nodes,Segments,Ways,Relations))
           exit(EXIT_FAILURE);
 
        fclose(file);
@@ -186,7 +202,7 @@ int main(int argc,char** argv)
     printf("\nParse OSM Data\n==============\n\n");
     fflush(stdout);
 
-    if(ParseOSM(stdin,Nodes,Segments,Ways))
+    if(ParseOSM(stdin,Nodes,Segments,Ways,Relations))
        exit(EXIT_FAILURE);
    }
 
@@ -195,6 +211,7 @@ int main(int argc,char** argv)
     FreeNodeList(Nodes,1);
     FreeSegmentList(Segments,1);
     FreeWayList(Ways,1);
+    FreeRelationList(Relations,1);
 
     return(0);
    }
@@ -204,7 +221,7 @@ int main(int argc,char** argv)
  printf("\nProcess OSM Data\n================\n\n");
  fflush(stdout);
 
- /* Sort the nodes, segments and ways */
+ /* Sort the nodes, segments, ways and relations */
 
  SortNodeList(Nodes);
 
@@ -212,6 +229,18 @@ int main(int argc,char** argv)
 
  SortWayList(Ways);
 
+ SortRelationList(Relations);
+
+ /* Process the route relations (must be before compacting the ways) */
+
+ ProcessRouteRelations(Relations,Ways);
+
+ FreeRelationList(Relations,0);
+
+ /* Compact the ways (must be before measuring the segments) */
+
+ CompactWayList(Ways);
+
  /* Remove bad segments (must be after sorting the nodes and segments) */
 
  RemoveBadSegments(Nodes,Segments);
@@ -356,20 +385,35 @@ int main(int argc,char** argv)
   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: planetsplitter [--help]\n"
          "                      [--dir=<dirname>] [--prefix=<name>]\n"
-         "                      [--slim] [--sort-ram-size=<size>]\n"
+         "                      [--sort-ram-size=<size>]\n"
          "                      [--tmpdir=<dirname>]\n"
          "                      [--parse-only | --process-only]\n"
+         "                      [--loggable]\n"
          "                      [--max-iterations=<number>]\n"
          "                      [--tagging=<filename>]\n"
          "                      [<filename.osm> ...]\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"
@@ -378,20 +422,26 @@ static void print_usage(int detail)
             "--dir=<dirname>           The directory containing the routing database.\n"
             "--prefix=<name>           The filename prefix for the routing database.\n"
             "\n"
-            "--slim                    Use less RAM and more temporary files.\n"
             "--sort-ram-size=<size>    The amount of RAM (in MB) to use for data sorting\n"
-            "                          (defaults to 64MB with '--slim' or 256MB otherwise.)\n"
+#if SLIM
+            "                          (defaults to 64MB otherwise.)\n"
+#else
+            "                          (defaults to 256MB otherwise.)\n"
+#endif
             "--tmpdir=<dirname>        The directory name for temporary files.\n"
             "                          (defaults to the '--dir' option directory.)\n"
             "\n"
             "--parse-only              Parse the input OSM files and store the results.\n"
             "--process-only            Process the stored results from previous option.\n"
             "\n"
+            "--loggable                Print progress messages suitable for logging to file.\n"
+            "\n"
             "--max-iterations=<number> The number of iterations for finding super-nodes.\n"
             "\n"
             "--tagging=<filename>      The name of the XML file containing the tagging rules\n"
-            "                          (defaults to 'tagging.xml' with '--dirname' and\n"
-            "                           '--prefix' options).\n"
+            "                          (defaults to 'tagging.xml' with '--dir' and\n"
+            "                           '--prefix' options or the file installed in\n"
+            "                           '" DATADIR "').\n"
             "\n"
             "<filename.osm> ...        The name(s) of the file(s) to process (by default\n"
             "                          data is read from standard input).\n"
index e27a067..8c89d90 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/profiles.c,v 1.42 2010/05/29 10:37:12 amb Exp $
+ $Header: /home/amb/routino/src/RCS/profiles.c,v 1.47 2010/10/18 17:40:34 amb Exp $
 
  Load the profiles from a file and the functions for handling them.
 
 #include <string.h>
 #include <stdlib.h>
 
-#include "profiles.h"
 #include "types.h"
 #include "ways.h"
-#include "xmlparse.h"
+
+#include "files.h"
+#include "profiles.h"
 #include "functions.h"
+#include "xmlparse.h"
 
 
 /*+ The profiles that have been loaded from file. +*/
@@ -654,10 +656,10 @@ int UpdateProfile(Profile *profile,Ways *ways)
 
  profile->allow=ALLOWED(profile->transport);
 
- if(!(profile->allow & ways->allow))
+ if(!(profile->allow & ways->file.allow))
     return(1);
 
- /* Normalise the highway preferences into the range 0 -> 1 */
+ /* Normalise the highway preferences into the range ~0 -> 1 */
 
  for(i=1;i<Way_Count;i++)
    {
@@ -672,9 +674,14 @@ int UpdateProfile(Profile *profile,Ways *ways)
     return(1);
 
  for(i=1;i<Way_Count;i++)
+   {
     profile->highway[i]/=hmax;
 
- /* Normalise the property preferences into the range 0 -> 2 */
+    if(profile->highway[i]<0.0001)
+       profile->highway[i]=0.0001;
+   }
+
+ /* Normalise the property preferences into the range ~0 -> 1 */
 
  for(i=1;i<Property_Count;i++)
    {
@@ -684,8 +691,21 @@ int UpdateProfile(Profile *profile,Ways *ways)
     if(profile->props_yes[i]>100)
        profile->props_yes[i]=100;
 
-    profile->props_yes[i]/=50;
-    profile->props_no [i] =2-profile->props_yes[i];
+    profile->props_yes[i]/=100;
+    profile->props_no [i] =1-profile->props_yes[i];
+
+    /* Squash the properties; selecting 60% preference without the sqrt() allows
+       routes 50% longer on highways with the property compared to ones without.
+       With the sqrt() function the ratio is only 22% allowing finer control. */
+
+    profile->props_yes[i] =sqrt(profile->props_yes[i]);
+    profile->props_no [i] =sqrt(profile->props_no[i] );
+
+    if(profile->props_yes[i]<0.0001)
+       profile->props_yes[i]=0.0001;
+
+    if(profile->props_no[i]<0.0001)
+       profile->props_no[i]=0.0001;
    }
 
  /* Find the fastest preferred speed */
@@ -704,7 +724,7 @@ int UpdateProfile(Profile *profile,Ways *ways)
  profile->max_pref=1; /* since highway prefs were normalised to 1 */
 
  for(i=1;i<Property_Count;i++)
-    if(ways->props & PROPERTIES(i))
+    if(ways->file.props & PROPERTIES(i))
       {
        if(profile->props_yes[i]>profile->props_no[i])
           profile->max_pref*=profile->props_yes[i];
@@ -824,38 +844,38 @@ void PrintProfilesJSON(void)
  printf("\n");
 
  printf("  // Transport types\n");
- printf("  transports: {");
+ printf("  transports: { ");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),j);
- printf("},\n");
+    printf("%s%s: %d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),j+1);
+ printf(" },\n");
  printf("\n");
 
  printf("  // Highway types\n");
- printf("  highways: {");
+ printf("  highways: { ");
  for(i=1;i<Way_Count;i++)
     printf("%s%s: %d",i==1?"":", ",HighwayName(i),i);
- printf("},\n");
+ printf(" },\n");
  printf("\n");
 
  printf("  // Property types\n");
- printf("  properties: {");
+ printf("  properties: { ");
  for(i=1;i<Property_Count;i++)
     printf("%s%s: %d",i==1?"":", ",PropertyName(i),i);
- printf("},\n");
+ printf(" },\n");
  printf("\n");
 
  printf("  // Restriction types\n");
- printf("  restrictions: {oneway: 1, weight: 2, height: 3, width: 4, length: 5},\n");
+ printf("  restrictions: { oneway: 1, weight: 2, height: 3, width: 4, length: 5 },\n");
  printf("\n");
 
  printf("  // Allowed highways\n");
  printf("  profile_highway: {\n");
  for(i=1;i<Way_Count;i++)
    {
-    printf("    %12s: {",HighwayName(i));
+    printf("    %12s: { ",HighwayName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
-    printf("}%s\n",i==(Way_Count-1)?"":",");
+       printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
+    printf(" }%s\n",i==(Way_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
@@ -864,10 +884,10 @@ void PrintProfilesJSON(void)
  printf("  profile_speed: {\n");
  for(i=1;i<Way_Count;i++)
    {
-    printf("    %12s: {",HighwayName(i));
+    printf("    %12s: { ",HighwayName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
-    printf("}%s\n",i==(Way_Count-1)?"":",");
+       printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
+    printf(" }%s\n",i==(Way_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
@@ -876,36 +896,36 @@ void PrintProfilesJSON(void)
  printf("  profile_property: {\n");
  for(i=1;i<Property_Count;i++)
    {
-    printf("    %12s: {",PropertyName(i));
+    printf("    %12s: { ",PropertyName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s%s: %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
-    printf("}%s\n",i==(Property_Count-1)?"":",");
+       printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
+    printf(" }%s\n",i==(Property_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
 
  printf("  // Restrictions\n");
  printf("  profile_restrictions: {\n");
- printf("    %12s: {","oneway");
+ printf("    %12s: { ","oneway");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %4d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
- printf("},\n");
- printf("    %12s: {","weight");
+    printf("%s%s: %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
+ printf(" },\n");
+ printf("    %12s: { ","weight");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
- printf("},\n");
- printf("    %12s: {","height");
+    printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
+ printf(" },\n");
+ printf("    %12s: { ","height");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
- printf("},\n");
- printf("    %12s: {","width");
+    printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
+ printf(" },\n");
+ printf("    %12s: { ","width");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
- printf("},\n");
- printf("    %12s: {","length");
+    printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
+ printf(" },\n");
+ printf("    %12s: { ","length");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s: %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
- printf("}\n");
+    printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
+ printf(" }\n");
  printf("     }\n");
  printf("\n");
 
@@ -929,28 +949,28 @@ void PrintProfilesPerl(void)
  printf("\n");
 
  printf("  # Transport types\n");
- printf("  transports => {");
+ printf("  transports => { ");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s%s => %d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),j);
- printf("},\n");
+    printf("%s%s => %d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),j+1);
+ printf(" },\n");
  printf("\n");
 
  printf("  # Highway types\n");
- printf("  highways => {");
+ printf("  highways => { ");
  for(i=1;i<Way_Count;i++)
     printf("%s%s => %d",i==1?"":", ",HighwayName(i),i);
- printf("},\n");
+ printf(" },\n");
  printf("\n");
 
  printf("  # Property types\n");
- printf("  properties => {");
+ printf("  properties => { ");
  for(i=1;i<Property_Count;i++)
     printf("%s%s => %d",i==1?"":", ",PropertyName(i),i);
- printf("},\n");
+ printf(" },\n");
  printf("\n");
 
  printf("  # Restriction types\n");
- printf("  restrictions => {oneway => 1, weight => 2, height => 3, width => 4, length => 5},\n");
+ printf("  restrictions => { oneway => 1, weight => 2, height => 3, width => 4, length => 5 },\n");
  printf("\n");
 
  printf("  # Allowed highways\n");
@@ -959,8 +979,8 @@ void PrintProfilesPerl(void)
    {
     printf("  %12s => {",HighwayName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
-    printf("}%s\n",i==(Way_Count-1)?"":",");
+       printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]);
+    printf(" }%s\n",i==(Way_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
@@ -971,8 +991,8 @@ void PrintProfilesPerl(void)
    {
     printf("  %12s => {",HighwayName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
-    printf("}%s\n",i==(Way_Count-1)?"":",");
+       printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]);
+    printf(" }%s\n",i==(Way_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
@@ -983,8 +1003,8 @@ void PrintProfilesPerl(void)
    {
     printf("  %12s => {",PropertyName(i));
     for(j=0;j<nloaded_profiles;j++)
-       printf("%s %s => %3d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
-    printf("}%s\n",i==(Property_Count-1)?"":",");
+       printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]);
+    printf(" }%s\n",i==(Property_Count-1)?"":",");
    }
  printf("     },\n");
  printf("\n");
@@ -993,25 +1013,25 @@ void PrintProfilesPerl(void)
  printf("  profile_restrictions => {\n");
  printf("    %12s => {","oneway");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s %s => %4d",j==1?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
- printf("},\n");
+    printf("%s %s => %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway);
+ printf(" },\n");
  printf("    %12s => {","weight");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
- printf("},\n");
+    printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight));
+ printf(" },\n");
  printf("    %12s => {","height");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
- printf("},\n");
+    printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height));
+ printf(" },\n");
  printf("    %12s => {","width");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
- printf("},\n");
+    printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width));
+ printf(" },\n");
  printf("    %12s => {","length");
  for(j=0;j<nloaded_profiles;j++)
-    printf("%s %s => %4.1f",j==1?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
- printf("}\n");
- printf("     },\n");
+    printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length));
+ printf(" }\n");
+ printf("     }\n");
  printf("\n");
 
  printf("}; # end of routino variable\n");
index 25a933a..2082b5c 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/profiles.h,v 1.16 2010/05/29 10:37:12 amb Exp $
+ $Header: /home/amb/routino/src/RCS/profiles.h,v 1.17 2010/07/31 18:21:18 amb Exp $
 
  A header file for the profiles.
 
@@ -38,7 +38,7 @@ typedef struct _Profile
 
  Transport  transport;                 /*+ The type of transport. +*/
 
- wayallow_t allow;                     /*+ The type of transport expressed as what must be allowed on a way. +*/
+ allow_t    allow;                     /*+ The type of transport expressed as what must be allowed. +*/
 
  score_t    highway[Way_Count];        /*+ A floating point preference for travel on the highway. +*/
  score_t    max_pref;                  /*+ The maximum preference for any highway type. +*/
diff --git a/src/relationsx.c b/src/relationsx.c
new file mode 100644 (file)
index 0000000..1822f9d
--- /dev/null
@@ -0,0 +1,344 @@
+/***************************************
+ $Header: /home/amb/routino/src/RCS/relationsx.c,v 1.10 2010/11/13 14:57:30 amb Exp $
+
+ Extended Relation data type functions.
+
+ Part of the Routino routing software.
+ ******************/ /******************
+ This file Copyright 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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "waysx.h"
+#include "relationsx.h"
+
+#include "files.h"
+#include "logging.h"
+#include "functions.h"
+
+
+/* Variables */
+
+/*+ The command line '--tmpdir' option or its default value. +*/
+extern char *option_tmpdirname;
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Allocate a new relation list (create a new file or open an existing one).
+
+  RelationsX *NewRelationList Returns the relation list.
+
+  int append Set to 1 if the file is to be opened for appending (now or later).
+  ++++++++++++++++++++++++++++++++++++++*/
+
+RelationsX *NewRelationList(int append)
+{
+ RelationsX *relationsx;
+
+ relationsx=(RelationsX*)calloc(1,sizeof(RelationsX));
+
+ assert(relationsx); /* Check calloc() worked */
+
+ relationsx->rfilename=(char*)malloc(strlen(option_tmpdirname)+32);
+
+ if(append)
+    sprintf(relationsx->rfilename,"%s/relationsx.route.input.tmp",option_tmpdirname);
+ else
+    sprintf(relationsx->rfilename,"%s/relationsx.route.%p.tmp",option_tmpdirname,relationsx);
+
+ if(append)
+   {
+    off_t size,position=0;
+
+    relationsx->rfd=OpenFileAppend(relationsx->rfilename);
+
+    size=SizeFile(relationsx->rfilename);
+
+    while(position<size)
+      {
+       FILESORT_VARINT relationsize;
+
+       SeekFile(relationsx->rfd,position);
+       ReadFile(relationsx->rfd,&relationsize,FILESORT_VARSIZE);
+
+       relationsx->rxnumber++;
+       position+=relationsize+FILESORT_VARSIZE;
+      }
+
+    SeekFile(relationsx->rfd,size);
+   }
+ else
+    relationsx->rfd=OpenFileNew(relationsx->rfilename);
+
+ return(relationsx);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Free a relation list.
+
+  RelationsX *relationsx The list to be freed.
+
+  int keep Set to 1 if the file is to be kept.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void FreeRelationList(RelationsX *relationsx,int keep)
+{
+ if(!keep)
+    DeleteFile(relationsx->rfilename);
+
+ free(relationsx->rfilename);
+
+ free(relationsx);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Append a single relation to an unsorted route relation list.
+
+  RelationsX* relationsx The set of relations to process.
+
+  relation_t id The ID of the relation.
+
+  allow_t routes The types of routes that this relation is for.
+
+  way_t *ways The array of ways that are members of the relation.
+
+  int nways The number of ways that are members of the relation.
+
+  relation_t *relations The array of relations that are members of the relation.
+
+  int nrelations The number of relations that are members of the relation.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes,
+                         way_t *ways,int nways,
+                         relation_t *relations,int nrelations)
+{
+ RouteRelX relationx;
+ FILESORT_VARINT size;
+ way_t zeroway=0;
+ relation_t zerorelation=0;
+
+ relationx.id=id;
+ relationx.routes=routes;
+
+ size=sizeof(RouteRelX)+(nways+1)*sizeof(way_t)+(nrelations+1)*sizeof(relation_t);
+
+ WriteFile(relationsx->rfd,&size,FILESORT_VARSIZE);
+ WriteFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
+
+ WriteFile(relationsx->rfd,ways    ,nways*sizeof(way_t));
+ WriteFile(relationsx->rfd,&zeroway,      sizeof(way_t));
+
+ WriteFile(relationsx->rfd,relations    ,nrelations*sizeof(relation_t));
+ WriteFile(relationsx->rfd,&zerorelation,           sizeof(relation_t));
+
+ relationsx->rxnumber++;
+
+ assert(!(relationsx->rxnumber==0)); /* Zero marks the high-water mark for relations. */
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Sort the list of relations.
+
+  RelationsX* relationsx The set of relations to process.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void SortRelationList(RelationsX* relationsx)
+{
+ /* Don't need to sort route relations */
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Process the route relations and apply the information to the ways.
+
+  RelationsX *relationsx The set of relations to process.
+
+  WaysX *waysx The set of ways to update.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx)
+{
+ RouteRelX *unmatched=NULL,*lastunmatched=NULL;
+ int nunmatched=0,lastnunmatched=0,iteration=0;
+
+ if(waysx->number==0)
+    return;
+
+ /* Map into memory */
+
+#if !SLIM
+ waysx->xdata=MapFileWriteable(waysx->filename);
+#endif
+
+ /* Re-open the ways file read/write */
+
+#if SLIM
+ CloseFile(waysx->fd);
+ waysx->fd=ReOpenFileWriteable(waysx->filename);
+#endif
+
+ /* Open the file and read through it */
+
+ relationsx->rfd=ReOpenFile(relationsx->rfilename);
+
+ do
+   {
+    int ways=0,relations=0;
+    int i;
+
+    SeekFile(relationsx->rfd,0);
+
+    /* Print the start message */
+
+    printf_first("Processing Route Relations: Iteration=%d Relations=0 Modified Ways=0",iteration);
+
+    for(i=0;i<relationsx->rxnumber;i++)
+      {
+       FILESORT_VARINT size;
+       RouteRelX relationx;
+       way_t wayid;
+       relation_t relationid;
+       allow_t routes=Allow_None;
+
+       /* Read each route relation */
+
+       ReadFile(relationsx->rfd,&size,FILESORT_VARSIZE);
+       ReadFile(relationsx->rfd,&relationx,sizeof(RouteRelX));
+
+       /* Decide what type of route it is */
+
+       if(iteration==0)
+         {
+          relations++;
+          routes=relationx.routes;
+         }
+       else
+         {
+          int j;
+
+          for(j=0;j<lastnunmatched;j++)
+             if(lastunmatched[j].id==relationx.id)
+               {
+                relations++;
+
+                if((lastunmatched[j].routes|relationx.routes)==relationx.routes)
+                   routes=0; /* Nothing new to add */
+                else
+                   routes=lastunmatched[j].routes;
+                break;
+               }
+         }
+
+       /* Loop through the ways */
+
+       do
+         {
+          ReadFile(relationsx->rfd,&wayid,sizeof(way_t));
+
+          /* Update the ways that are listed for the relation */
+
+          if(wayid && routes)
+            {
+             index_t way=IndexWayX(waysx,wayid);
+
+             if(way!=NO_WAY)
+               {
+                WayX *wayx=LookupWayX(waysx,way,1);
+
+                if(routes&Allow_Foot)
+                   wayx->way.props|=Properties_FootRoute;
+
+                if(routes&Allow_Bicycle)
+                   wayx->way.props|=Properties_BicycleRoute;
+
+#if SLIM
+                PutBackWayX(waysx,way,1);
+#endif
+
+                ways++;
+               }
+            }
+         }
+       while(wayid);
+
+       /* Loop through the relations */
+
+       do
+         {
+          ReadFile(relationsx->rfd,&relationid,sizeof(relation_t));
+
+          /* Add the relations that are listed for this relation to the list for next time */
+
+          if(relationid && routes && relationid!=relationx.id)
+            {
+             if(nunmatched%256==0)
+                unmatched=(RouteRelX*)realloc((void*)unmatched,(nunmatched+256)*sizeof(RouteRelX));
+
+             unmatched[nunmatched].id=relationid;
+             unmatched[nunmatched].routes=routes;
+
+             nunmatched++;
+            }
+         }
+       while(relationid);
+
+       if(!((i+1)%10000))
+          printf_middle("Processing Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
+      }
+
+    if(lastunmatched)
+       free(lastunmatched);
+
+    lastunmatched=unmatched;
+    lastnunmatched=nunmatched;
+
+    unmatched=NULL;
+    nunmatched=0;
+
+    /* Print the final message */
+
+    printf_last("Processed Route Relations: Iteration=%d Relations=%d Modified Ways=%d",iteration,relations,ways);
+   }
+ while(lastnunmatched && ++iteration<5);
+
+ if(lastunmatched)
+    free(lastunmatched);
+
+ CloseFile(relationsx->rfd);
+
+ /* Unmap from memory */
+
+#if !SLIM
+ waysx->xdata=UnmapFile(waysx->filename);
+#endif
+
+ /* Re-open the ways file read only */
+
+#if SLIM
+ CloseFile(waysx->fd);
+ waysx->fd=ReOpenFile(waysx->filename);
+#endif
+}
diff --git a/src/relationsx.h b/src/relationsx.h
new file mode 100644 (file)
index 0000000..f215c65
--- /dev/null
@@ -0,0 +1,74 @@
+/***************************************
+ $Header: /home/amb/routino/src/RCS/relationsx.h,v 1.2 2010/09/25 18:47:32 amb Exp $
+
+ A header file for the extended Relations structure.
+
+ Part of the Routino routing software.
+ ******************/ /******************
+ This file Copyright 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 <http://www.gnu.org/licenses/>.
+ ***************************************/
+
+
+#ifndef RELATIONSX_H
+#define RELATIONSX_H    /*+ To stop multiple inclusions. +*/
+
+#include <stdint.h>
+
+#include "types.h"
+
+#include "typesx.h"
+
+
+/* Data structures */
+
+
+/*+ An extended structure containing a single route relation. +*/
+struct _RouteRelX
+{
+ relation_t id;                 /*+ The relation identifier. +*/
+
+ allow_t    routes;             /*+ The types of route that this relation belongs to. +*/
+};
+
+
+/*+ A structure containing a set of relations. +*/
+struct _RelationsX
+{
+ /* Route relations */
+
+ char      *rfilename;         /*+ The name of the temporary file (for the RouteRelX). +*/
+ int        rfd;               /*+ The file descriptor of the temporary file (for the RouteRelX). +*/
+
+ index_t    rxnumber;          /*+ The number of unsorted extended route relations. +*/
+};
+
+
+/* Functions */
+
+
+RelationsX *NewRelationList(int append);
+void FreeRelationList(RelationsX *relationsx,int keep);
+
+void AppendRouteRelation(RelationsX* relationsx,relation_t id,allow_t routes,
+                         way_t *ways,int nways,
+                         relation_t *relations,int nrelations);
+
+void SortRelationList(RelationsX *relationsx);
+
+void ProcessRouteRelations(RelationsX *relationsx,WaysX *waysx);
+
+
+#endif /* RELATIONSX_H */
index b5dec42..aa092de 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/results.c,v 1.21 2010/07/07 19:04:18 amb Exp $
+ $Header: /home/amb/routino/src/RCS/results.c,v 1.22 2010/07/23 14:32:16 amb Exp $
 
  Result data type functions.
 
@@ -163,13 +163,13 @@ Result *InsertResult(Results *results,index_t node)
 
 void ZeroResult(Result *result)
 {
+ result->segment=NO_SEGMENT;
+
  result->prev=NO_NODE;
  result->next=NO_NODE;
 
  result->score=0;
  result->sortby=0;
-
- result->segment=NULL;
 }
 
 
index a7191f0..871e4f2 100644 (file)
@@ -1,11 +1,11 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/results.h,v 1.17 2009/11/13 19:24:11 amb Exp $
+ $Header: /home/amb/routino/src/RCS/results.h,v 1.18 2010/07/23 14:32:16 amb Exp $
 
  A header file for the results.
 
  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
@@ -42,6 +42,7 @@
 typedef struct _Result
 {
  index_t   node;                /*+ The node for which this result applies. +*/
+ index_t   segment;             /*+ The segment for the path to here (from prev). +*/
 
  index_t   prev;                /*+ The previous node following the best path. +*/
  index_t   next;                /*+ The next node following the best path. +*/
@@ -50,8 +51,6 @@ typedef struct _Result
 
  score_t   sortby;              /*+ The best possible weighted distance or duration score from the start to the finish. +*/
  uint32_t  queued;              /*+ The position of this result in the queue. +*/
-
- Segment  *segment;             /*+ The segment for the path to here (from prev). +*/
 }
  Result;
 
index 46ca0b4..2b58f3b 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/router.c,v 1.83 2010/06/28 17:56:26 amb Exp $
+ $Header: /home/amb/routino/src/RCS/router.c,v 1.90 2010/11/13 14:22:28 amb Exp $
 
  OSM router.
 
 #include <ctype.h>
 
 #include "types.h"
-#include "functions.h"
-#include "translations.h"
-#include "profiles.h"
 #include "nodes.h"
 #include "segments.h"
 #include "ways.h"
 
+#include "files.h"
+#include "logging.h"
+#include "functions.h"
+#include "translations.h"
+#include "profiles.h"
 
-/*+ The number of waypoints allowed to be specified. +*/
-#define NWAYPOINTS 99
 
 /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
 #define MAXSEARCH  1
 
-/*+ The minimum distance along a segment from a node to insert a fake node. (in km). +*/
-#define MINSEGMENT 0.005
-
-
-/*+ A set of fake segments to allow start/finish in the middle of a segment. +*/
-static Segment fake_segments[2*NWAYPOINTS];
 
-/*+ A set of fake node latitudes and longitudes. +*/
+/*+ A set of waypoint latitudes and longitudes. +*/
 static double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
 
 /*+ The option not to print any progress information. +*/
@@ -64,7 +58,7 @@ int option_quickest=0;
 
 /* Local functions */
 
-static void print_usage(int detail);
+static void print_usage(int detail,const char *argerr,const char *err);
 
 
 /*++++++++++++++++++++++++++++++++++++++
@@ -91,14 +85,14 @@ int main(int argc,char** argv)
  /* Parse the command line arguments */
 
  if(argc<2)
-    print_usage(0);
+    print_usage(0,NULL,NULL);
 
  /* Get the non-routing, general program options */
 
  for(arg=1;arg<argc;arg++)
    {
     if(!strcmp(argv[arg],"--help"))
-       print_usage(1);
+       print_usage(1,NULL,NULL);
     else if(!strcmp(argv[arg],"--help-profile"))
        help_profile=1;
     else if(!strcmp(argv[arg],"--help-profile-xml"))
@@ -119,6 +113,8 @@ int main(int argc,char** argv)
        exactnodes=1;
     else if(!strcmp(argv[arg],"--quiet"))
        option_quiet=1;
+    else if(!strcmp(argv[arg],"--loggable"))
+       option_loggable=1;
     else if(!strcmp(argv[arg],"--output-html"))
        option_html=1;
     else if(!strcmp(argv[arg],"--output-gpx-track"))
@@ -140,7 +136,7 @@ int main(int argc,char** argv)
        transport=TransportType(&argv[arg][12]);
 
        if(transport==Transport_None)
-         print_usage(0);
+          print_usage(0,argv[arg],NULL);
       }
     else
        continue;
@@ -165,6 +161,8 @@ int main(int argc,char** argv)
    {
     if(ExistsFile(FileName(dirname,prefix,"profiles.xml")))
        profiles=FileName(dirname,prefix,"profiles.xml");
+    else if(ExistsFile(FileName(DATADIR,NULL,"tagging.xml")))
+       profiles=FileName(DATADIR,NULL,"profiles.xml");
     else
       {
        fprintf(stderr,"Error: The '--profiles' option was not used and the default 'profiles.xml' does not exist.\n");
@@ -172,7 +170,7 @@ int main(int argc,char** argv)
       }
    }
 
- if(profiles && ParseXMLProfiles(profiles))
+ if(ParseXMLProfiles(profiles))
    {
     fprintf(stderr,"Error: Cannot read the profiles in the file '%s'.\n",profiles);
     return(1);
@@ -231,11 +229,11 @@ int main(int argc,char** argv)
         char *p=&argv[arg][6];
         while(isdigit(*p)) p++;
         if(*p++!='=')
-           print_usage(0);
+           print_usage(0,argv[arg],NULL);
  
         point=atoi(&argv[arg][5]);
         if(point>NWAYPOINTS || point_used[point]&1)
-           print_usage(0);
+           print_usage(0,argv[arg],NULL);
  
        point_lon[point]=degrees_to_radians(atof(p));
        point_used[point]+=1;
@@ -245,11 +243,11 @@ int main(int argc,char** argv)
         char *p=&argv[arg][6];
         while(isdigit(*p)) p++;
         if(*p++!='=')
-           print_usage(0);
+           print_usage(0,argv[arg],NULL);
  
         point=atoi(&argv[arg][5]);
         if(point>NWAYPOINTS || point_used[point]&2)
-           print_usage(0);
+           print_usage(0,argv[arg],NULL);
  
        point_lat[point]=degrees_to_radians(atof(p));
        point_used[point]+=2;
@@ -263,7 +261,7 @@ int main(int argc,char** argv)
        char *string;
 
        if(!equal)
-           print_usage(0);
+           print_usage(0,argv[arg],NULL);
 
        string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10);
        string[equal-argv[arg]-10]=0;
@@ -271,7 +269,7 @@ int main(int argc,char** argv)
        highway=HighwayType(string);
 
        if(highway==Way_Count)
-          print_usage(0);
+          print_usage(0,argv[arg],NULL);
 
        profile->highway[highway]=atof(equal+1);
 
@@ -284,7 +282,7 @@ int main(int argc,char** argv)
        char *string;
 
        if(!equal)
-          print_usage(0);
+          print_usage(0,argv[arg],NULL);
 
        string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8);
        string[equal-argv[arg]-8]=0;
@@ -292,7 +290,7 @@ int main(int argc,char** argv)
        highway=HighwayType(string);
 
        if(highway==Way_Count)
-          print_usage(0);
+          print_usage(0,argv[arg],NULL);
 
        profile->speed[highway]=kph_to_speed(atof(equal+1));
 
@@ -305,7 +303,7 @@ int main(int argc,char** argv)
        char *string;
 
        if(!equal)
-          print_usage(0);
+          print_usage(0,argv[arg],NULL);
 
        string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11);
        string[equal-argv[arg]-11]=0;
@@ -313,7 +311,7 @@ int main(int argc,char** argv)
        property=PropertyType(string);
 
        if(property==Way_Count)
-          print_usage(0);
+          print_usage(0,argv[arg],NULL);
 
        profile->props_yes[property]=atof(equal+1);
 
@@ -330,12 +328,12 @@ int main(int argc,char** argv)
     else if(!strncmp(argv[arg],"--length=",9))
        profile->length=metres_to_length(atof(&argv[arg][9]));
     else
-       print_usage(0);
+       print_usage(0,argv[arg],NULL);
    }
 
  for(point=1;point<=NWAYPOINTS;point++)
     if(point_used[point]==1 || point_used[point]==2)
-       print_usage(0);
+       print_usage(0,NULL,"All waypoints must have latitude and longitude.");
 
  if(help_profile)
    {
@@ -369,18 +367,28 @@ int main(int argc,char** argv)
 
  if(option_html || option_gpx_route || option_gpx_track)
    {
-    if(translations && ExistsFile(translations))
-       ;
-    else if(!translations && ExistsFile(FileName(dirname,prefix,"translations.xml")))
-       translations=FileName(dirname,prefix,"translations.xml");
-
-    if(!translations && language)
+    if(translations)
       {
-       fprintf(stderr,"Error: Cannot use '--language' option without reading some translations.\n");
-       return(1);
+       if(!ExistsFile(translations))
+         {
+          fprintf(stderr,"Error: The '--translations' option specifies a file that does not exist.\n");
+          return(1);
+         }
+      }
+    else
+      {
+       if(ExistsFile(FileName(dirname,prefix,"translations.xml")))
+          translations=FileName(dirname,prefix,"translations.xml");
+       else if(ExistsFile(FileName(DATADIR,NULL,"translations.xml")))
+          translations=FileName(DATADIR,NULL,"translations.xml");
+       else
+         {
+          fprintf(stderr,"Error: The '--translations' option was not used and the default 'translations.xml' does not exist.\n");
+          return(1);
+         }
       }
 
-    if(translations && ParseXMLTranslations(translations,language))
+    if(ParseXMLTranslations(translations,language))
       {
        fprintf(stderr,"Error: Cannot read the translations in the file '%s'.\n",translations);
        return(1);
@@ -408,7 +416,7 @@ int main(int argc,char** argv)
     Results *begin,*end;
     distance_t distmax=km_to_distance(MAXSEARCH);
     distance_t distmin;
-    Segment *segment=NULL;
+    index_t segment=NO_SEGMENT;
     index_t node1,node2;
 
     if(point_used[point]!=3)
@@ -426,8 +434,10 @@ int main(int argc,char** argv)
       {
        distance_t dist1,dist2;
 
-       if((segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2)))
-          finish=CreateFakes(OSMNodes,point,segment,node1,node2,dist1,dist2);
+       segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2);
+
+       if(segment!=NO_SEGMENT)
+          finish=CreateFakes(OSMNodes,point,LookupSegment(OSMSegments,segment,1),node1,node2,dist1,dist2);
        else
           finish=NO_NODE;
       }
@@ -448,7 +458,7 @@ int main(int argc,char** argv)
           GetLatLong(OSMNodes,finish,&lat,&lon);
 
        if(IsFakeNode(finish))
-          printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,IndexSegment(OSMSegments,segment),node1,node2,
+          printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,segment,node1,node2,
                  radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
        else
           printf("Point %d is node %d: %3.6f %4.6f = %2.3f km\n",point,finish,
@@ -494,7 +504,7 @@ int main(int argc,char** argv)
 
        if(!option_quiet)
          {
-          printf("\rRouted: Super-Nodes Checked = %d\n",begin->number);
+          printf("Routed: Super-Nodes Checked = %d\n",begin->number);
           fflush(stdout);
          }
       }
@@ -556,176 +566,16 @@ int main(int argc,char** argv)
 
 
 /*++++++++++++++++++++++++++++++++++++++
-  Create a pair of fake segments corresponding to the given segment split in two.
-
-  index_t CreateFakes Returns the fake node index (or a real one in special cases).
-
-  Nodes *nodes The set of nodes to use.
-
-  int point Which of the waypoints is this.
-
-  Segment *segment The segment to split.
-
-  index_t node1 The first node at the end of this segment.
-
-  index_t node2 The second node at the end of this segment.
-
-  distance_t dist1 The distance to the first node.
-
-  distance_t dist2 The distance to the second node.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2)
-{
- index_t fakenode;
- double lat1,lon1,lat2,lon2;
-
- /* Check if we are actually close enough to an existing node */
-
- if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
-    return(node1);
-
- if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
-    return(node2);
-
- if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
-   {
-    if(dist1<dist2)
-       return(node1);
-    else
-       return(node2);
-   }
-
- /* Create the fake node */
-
- fakenode=point|NODE_SUPER;
-
- GetLatLong(nodes,node1,&lat1,&lon1);
- GetLatLong(nodes,node2,&lat2,&lon2);
-
- if(lat1>3 && lat2<-3)
-    lat2+=2*M_PI;
- else if(lat1<-3 && lat2>3)
-    lat1+=2*M_PI;
-
- point_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2);
- point_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2);
-
- if(point_lat[point]>M_PI) point_lat[point]-=2*M_PI;
-
- /* Create the first fake segment */
-
- fake_segments[2*point-2]=*segment;
-
- if(segment->node1==node1)
-    fake_segments[2*point-2].node1=fakenode;
- else
-    fake_segments[2*point-2].node2=fakenode;
-
- fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance);
-
- /* Create the second fake segment */
-
- fake_segments[2*point-1]=*segment;
-
- if(segment->node1==node2)
-    fake_segments[2*point-1].node1=fakenode;
- else
-    fake_segments[2*point-1].node2=fakenode;
-
- fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance);
-
- return(fakenode);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
-  Lookup the latitude and longitude of a fake node.
-
-  index_t fakenode The node to lookup.
-
-  double *latitude Returns the latitude
-
-  double *longitude Returns the longitude.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- *latitude =point_lat[realnode];
- *longitude=point_lon[realnode];
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
-  Finds the first fake segment associated to a fake node.
-
-  Segment *FirstFakeSegment Returns the first fake segment.
-
-  index_t fakenode The node to lookup.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *FirstFakeSegment(index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- return(&fake_segments[2*realnode-2]);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
-  Finds the next (there can only be two) fake segment associated to a fake node.
-
-  Segment *NextFakeSegment Returns the second fake segment.
-
-  Segment *segment The first fake segment.
-
-  index_t fakenode The node to lookup.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *NextFakeSegment(Segment *segment,index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- if(segment==&fake_segments[2*realnode-2])
-    return(&fake_segments[2*realnode-1]);
- else
-    return(NULL);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
-  Finds the next (there can only be two) fake segment associated to a fake node.
-
-  Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists.
-
-  index_t node The real node.
-
-  index_t fakenode The fake node to lookup.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-Segment *ExtraFakeSegment(index_t node,index_t fakenode)
-{
- index_t realnode=fakenode&(~NODE_SUPER);
-
- if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node)
-    return(&fake_segments[2*realnode-2]);
-
- if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node)
-    return(&fake_segments[2*realnode-1]);
-
- return(NULL);
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
   Print out the usage information.
 
   int detail The level of detail to use - 0 = low, 1 = high.
+
+  const char *argerr The argument that gave the error (if there is one).
+
+  const char *err Other error message (if there is one).
   ++++++++++++++++++++++++++++++++++++++*/
 
-static void print_usage(int detail)
+static void print_usage(int detail,const char *argerr,const char *err)
 {
  fprintf(stderr,
          "Usage: router [--help | --help-profile | --help-profile-xml |\n"
@@ -733,7 +583,7 @@ static void print_usage(int detail)
          "              [--dir=<dirname>] [--prefix=<name>]\n"
          "              [--profiles=<filename>] [--translations=<filename>]\n"
          "              [--exact-nodes-only]\n"
-         "              [--quiet]\n"
+         "              [--loggable | --quiet]\n"
          "              [--language=<lang>]\n"
          "              [--output-html]\n"
          "              [--output-gpx-track] [--output-gpx-route]\n"
@@ -752,6 +602,16 @@ static void print_usage(int detail)
          "              [--weight=<weight>]\n"
          "              [--height=<height>] [--width=<width>] [--length=<length>]\n");
 
+ if(argerr)
+    fprintf(stderr,
+            "\n"
+            "Error with command line parameter: %s\n",argerr);
+
+ if(err)
+    fprintf(stderr,
+            "\n"
+            "Error: %s\n",err);
+
  if(detail)
     fprintf(stderr,
             "\n"
@@ -763,14 +623,20 @@ static void print_usage(int detail)
             "\n"
             "--dir=<dirname>         The directory containing the routing database.\n"
             "--prefix=<name>         The filename prefix for the routing database.\n"
-            "--profiles=<filename>   The name of the profiles (defaults to 'profiles.xml'\n"
-            "                        with '--dirname' and '--prefix' options).\n"
-            "--translations=<fname>  The filename of the translations (defaults to\n"
-            "                         'translations.xml' with '--dirname' and '--prefix').\n"
+            "--profiles=<filename>   The name of the XML file containing the profiles\n"
+            "                        (defaults to 'profiles.xml' with '--dir' and\n"
+            "                         '--prefix' options or the file installed in\n"
+            "                         '" DATADIR "').\n"
+            "--translations=<fname>  The name of the XML file containing the translations\n"
+            "                        (defaults to 'translations.xml' with '--dir' and\n"
+            "                         '--prefix' options or the file installed in\n"
+            "                         '" DATADIR "').\n"
             "\n"
             "--exact-nodes-only      Only route between nodes (don't find closest segment).\n"
             "\n"
+            "--loggable              Print progress messages suitable for logging to file.\n"
             "--quiet                 Don't print any screen output when running.\n"
+            "\n"
             "--language=<lang>       Use the translations for specified language.\n"
             "--output-html           Write an HTML description of the route.\n"
             "--output-gpx-track      Write a GPX track file with all route points.\n"
index 0557d50..4b9f274 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/segments.c,v 1.45 2010/04/28 17:27:02 amb Exp $
+ $Header: /home/amb/routino/src/RCS/segments.c,v 1.47 2010/07/23 14:35:27 amb Exp $
 
  Segment data type functions.
 
 #include <stdlib.h>
 
 #include "types.h"
-#include "functions.h"
 #include "nodes.h"
 #include "segments.h"
 #include "ways.h"
+
+#include "files.h"
 #include "profiles.h"
 
 
 
 Segments *LoadSegmentList(const char *filename)
 {
- void *data;
  Segments *segments;
 
  segments=(Segments*)malloc(sizeof(Segments));
 
- data=MapFile(filename);
+#if !SLIM
+
+ segments->data=MapFile(filename);
+
+ /* Copy the SegmentsFile structure from the loaded data */
+
+ segments->file=*((SegmentsFile*)segments->data);
+
+ /* Set the pointers in the Segments structure. */
+
+ segments->segments=(Segment*)(segments->data+sizeof(SegmentsFile));
+
+#else
 
- /* Copy the Segments structure from the loaded data */
+ segments->fd=ReOpenFile(filename);
 
- *segments=*((Segments*)data);
+ /* Copy the SegmentsFile header structure from the loaded data */
 
- /* Adjust the pointers in the Segments structure. */
+ ReadFile(segments->fd,&segments->file,sizeof(SegmentsFile));
 
- segments->data=data;
- segments->segments=(Segment*)(data+sizeof(Segments));
+ segments->incache[0]=NO_SEGMENT;
+ segments->incache[1]=NO_SEGMENT;
+ segments->incache[2]=NO_SEGMENT;
+
+#endif
 
  return(segments);
 }
@@ -79,18 +94,31 @@ Segment *NextSegment(Segments* segments,Segment *segment,index_t node)
 {
  if(segment->node1==node)
    {
+#if SLIM
+    index_t index=IndexSegment(segments,segment);
+    index++;
+
+    if(index>=segments->file.number)
+       return(NULL);
+    segment=LookupSegment(segments,index,1);
+    if(segment->node1!=node)
+       return(NULL);
+    else
+       return(segment);
+#else
     segment++;
-    if((segment-segments->segments)>=segments->number || segment->node1!=node)
+    if(IndexSegment(segments,segment)>=segments->file.number || segment->node1!=node)
        return(NULL);
     else
        return(segment);
+#endif
    }
  else
    {
     if(segment->next2==NO_NODE)
        return(NULL);
     else
-       return(LookupSegment(segments,segment->next2));
+       return(LookupSegment(segments,segment->next2,1));
    }
 }
  
index 8b6554f..464d6a3 100644 (file)
@@ -1,11 +1,11 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/segments.h,v 1.34 2009/11/14 19:39:20 amb Exp $
+ $Header: /home/amb/routino/src/RCS/segments.h,v 1.37 2010/07/31 14:36:15 amb Exp $
 
  A header file for the segments.
 
  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 <stdint.h>
 
 #include "types.h"
+
+#include "files.h"
 #include "profiles.h"
 
 
@@ -48,27 +50,50 @@ struct _Segment
 };
 
 
-/*+ A structure containing a set of segments (mmap format). +*/
+/*+ A structure containing the header from the file. +*/
+typedef struct _SegmentsFile
+{
+ index_t   number;              /*+ How many segments in total? +*/
+ index_t   snumber;             /*+ How many super-segments? +*/
+ index_t   nnumber;             /*+ How many normal segments? +*/
+}
+ SegmentsFile;
+
+
+/*+ A structure containing a set of segments (and pointers to mmap file). +*/
 struct _Segments
 {
- uint32_t  number;              /*+ How many segments in total? +*/
- uint32_t  snumber;             /*+ How many super-segments? +*/
- uint32_t  nnumber;             /*+ How many normal segments? +*/
+ SegmentsFile file;             /*+ The header data from the file. +*/
+
+#if !SLIM
+
+ void        *data;             /*+ The memory mapped data. +*/
 
- Segment  *segments;            /*+ An array of segments. +*/
+ Segment     *segments;         /*+ An array of segments. +*/
 
- void     *data;                /*+ The memory mapped data. +*/
+#else
+
+ int          fd;               /*+ The file descriptor for the file. +*/
+
+ Segment      cached[3];        /*+ The cached segments. +*/
+ index_t      incache[3];       /*+ The indexes of the cached segments. +*/
+
+#endif
 };
 
 
-/* Macros */
+/* Functions */
 
+Segments *LoadSegmentList(const char *filename);
 
-/*+ Return a segment pointer given a set of segments and an index. +*/
-#define LookupSegment(xxx,yyy) (&(xxx)->segments[yyy])
+Segment *NextSegment(Segments* segments,Segment *segment,index_t node);
+
+distance_t Distance(double lat1,double lon1,double lat2,double lon2);
+
+duration_t Duration(Segment *segment,Way *way,Profile *profile);
 
-/*+ Return a segment index given a set of segments and a pointer. +*/
-#define IndexSegment(xxx,yyy)  ((yyy)-&(xxx)->segments[0])
+
+/* Macros and inline functions */
 
 /*+ Return true if this is a normal segment. +*/
 #define IsNormalSegment(xxx)   (((xxx)->distance)&SEGMENT_NORMAL)
@@ -86,16 +111,67 @@ struct _Segments
 #define OtherNode(xxx,yyy)     ((xxx)->node1==(yyy)?(xxx)->node2:(xxx)->node1)
 
 
-/* Functions */
+#if !SLIM
 
+/*+ Return a segment pointer given a set of segments and an index. +*/
+#define LookupSegment(xxx,yyy,zzz) (&(xxx)->segments[yyy])
 
-Segments *LoadSegmentList(const char *filename);
+/*+ Return a segment index given a set of segments and a pointer. +*/
+#define IndexSegment(xxx,yyy)      ((yyy)-&(xxx)->segments[0])
 
-Segment *NextSegment(Segments* segments,Segment *segment,index_t node);
+#else
 
-distance_t Distance(double lat1,double lon1,double lat2,double lon2);
+static Segment *LookupSegment(Segments *segments,index_t index,int position);
 
-duration_t Duration(Segment *segment,Way *way,Profile *profile);
+static index_t IndexSegment(Segments *segments,Segment *segment);
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Find the Segment information for a particular segment.
+
+  Segment *LookupSegment Returns a pointer to the cached segment information.
+
+  Segments *segments The segments structure to use.
+
+  index_t index The index of the segment.
+
+  int position The position in the cache to store the value.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static inline Segment *LookupSegment(Segments *segments,index_t index,int position)
+{
+ SeekFile(segments->fd,sizeof(SegmentsFile)+(off_t)index*sizeof(Segment));
+
+ ReadFile(segments->fd,&segments->cached[position-1],sizeof(Segment));
+
+ segments->incache[position-1]=index;
+
+ return(&segments->cached[position-1]);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Find the segment index for a particular segment pointer.
+
+  index_t IndexSegment Returns the index of the segment in the list.
+
+  Segments *segments The segments structure to use.
+
+  Segment *segment The segment whose index is to be found.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static inline index_t IndexSegment(Segments *segments,Segment *segment)
+{
+ int i;
+
+ for(i=0;i<sizeof(segments->cached)/sizeof(segments->cached[0]);i++)
+    if(&segments->cached[i]==segment)
+       return(segments->incache[i]);
+
+ return(NO_SEGMENT);
+}
+
+#endif
 
 
 #endif /* SEGMENTS_H */
index 5a4f03b..c831531 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/segmentsx.c,v 1.51 2010/04/28 17:27:02 amb Exp $
+ $Header: /home/amb/routino/src/RCS/segmentsx.c,v 1.69 2010/11/13 14:22:28 amb Exp $
 
  Extended Segment data type functions.
 
 #include <sys/stat.h>
 
 #include "types.h"
-#include "functions.h"
-#include "nodesx.h"
-#include "segmentsx.h"
-#include "waysx.h"
 #include "nodes.h"
 #include "segments.h"
 #include "ways.h"
 
+#include "nodesx.h"
+#include "segmentsx.h"
+#include "waysx.h"
 
-/* Variables */
+#include "types.h"
+
+#include "files.h"
+#include "logging.h"
+#include "functions.h"
 
-/*+ The command line '--slim' option. +*/
-extern int option_slim;
+
+/* Variables */
 
 /*+ The command line '--tmpdir' option or its default value. +*/
 extern char *option_tmpdirname;
@@ -73,22 +76,28 @@ SegmentsX *NewSegmentList(int append)
  segmentsx->filename=(char*)malloc(strlen(option_tmpdirname)+32);
 
  if(append)
-    sprintf(segmentsx->filename,"%s/segments.input.tmp",option_tmpdirname);
+    sprintf(segmentsx->filename,"%s/segmentsx.input.tmp",option_tmpdirname);
  else
-    sprintf(segmentsx->filename,"%s/segments.%p.tmp",option_tmpdirname,segmentsx);
+    sprintf(segmentsx->filename,"%s/segmentsx.%p.tmp",option_tmpdirname,segmentsx);
+
+#if SLIM
+ segmentsx->sfilename=(char*)malloc(strlen(option_tmpdirname)+32);
+
+ sprintf(segmentsx->sfilename,"%s/segments.%p.tmp",option_tmpdirname,segmentsx);
+#endif
 
  if(append)
    {
     off_t size;
 
-    segmentsx->fd=AppendFile(segmentsx->filename);
+    segmentsx->fd=OpenFileAppend(segmentsx->filename);
 
     size=SizeFile(segmentsx->filename);
 
     segmentsx->xnumber=size/sizeof(SegmentX);
    }
  else
-    segmentsx->fd=OpenFile(segmentsx->filename);
+    segmentsx->fd=OpenFileNew(segmentsx->filename);
 
  return(segmentsx);
 }
@@ -115,15 +124,23 @@ void FreeSegmentList(SegmentsX *segmentsx,int keep)
  if(segmentsx->firstnode)
     free(segmentsx->firstnode);
 
+#if !SLIM
  if(segmentsx->sdata)
     free(segmentsx->sdata);
+#endif
+
+#if SLIM
+ DeleteFile(segmentsx->sfilename);
+
+ free(segmentsx->sfilename);
+#endif
 
  free(segmentsx);
 }
 
 
 /*++++++++++++++++++++++++++++++++++++++
-  Append a single segment to a segment list.
+  Append a single segment to an unsorted segment list.
 
   SegmentsX* segmentsx The set of segments to process.
 
@@ -140,8 +157,6 @@ void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,dist
 {
  SegmentX segmentx;
 
- assert(!segmentsx->idata);    /* Must not have idata filled in => unsorted */
-
  segmentx.node1=node1;
  segmentx.node2=node2;
  segmentx.way=way;
@@ -150,6 +165,8 @@ void AppendSegment(SegmentsX* segmentsx,way_t way,node_t node1,node_t node2,dist
  WriteFile(segmentsx->fd,&segmentx,sizeof(SegmentX));
 
  segmentsx->xnumber++;
+
+ assert(segmentsx->xnumber<SEGMENT_FAKE); /* SEGMENT_FAKE marks the high-water mark for real segments. */
 }
 
 
@@ -163,14 +180,12 @@ void SortSegmentList(SegmentsX* segmentsx)
 {
  int fd;
 
- /* Check the start conditions */
-
- assert(!segmentsx->idata);    /* Must not have idata filled in => unsorted */
+ if(segmentsx->xnumber==0)
+    return;
 
  /* Print the start message */
 
- printf("Sorting Segments");
- fflush(stdout);
+ printf_first("Sorting Segments");
 
  /* Close the files and re-open them (finished appending) */
 
@@ -179,7 +194,7 @@ void SortSegmentList(SegmentsX* segmentsx)
 
  DeleteFile(segmentsx->filename);
 
- fd=OpenFile(segmentsx->filename);
+ fd=OpenFileNew(segmentsx->filename);
 
  /* Sort by node indexes */
 
@@ -196,8 +211,7 @@ void SortSegmentList(SegmentsX* segmentsx)
 
  /* Print the final message */
 
- printf("\rSorted Segments: Segments=%d\n",segmentsx->xnumber);
- fflush(stdout);
+ printf_last("Sorted Segments: Segments=%d",segmentsx->xnumber);
 }
 
 
@@ -274,8 +288,6 @@ index_t IndexFirstSegmentX(SegmentsX* segmentsx,node_t node)
     return(index);
    }
 
- assert(segmentsx->idata);      /* Must have idata filled in => sorted by node 1 */
-
  /* Binary search - search key exact match only is required.
   *
   *  # <- start  |  Check mid and move start or end if it doesn't match
@@ -340,8 +352,6 @@ index_t IndexFirstSegmentX(SegmentsX* segmentsx,node_t node)
 
 index_t IndexNextSegmentX(SegmentsX* segmentsx,index_t segindex,index_t nodeindex)
 {
- assert(segmentsx->firstnode);   /* Must have firstnode filled in => segments updated */
-
  if(++segindex==segmentsx->firstnode[nodeindex+1])
     return(NO_SEGMENT);
  else
@@ -350,37 +360,6 @@ index_t IndexNextSegmentX(SegmentsX* segmentsx,index_t segindex,index_t nodeinde
  
  
 /*++++++++++++++++++++++++++++++++++++++
-  Lookup a particular segment.
-
-  SegmentX *LookupSegmentX Returns a pointer to the extended segment with the specified id.
-
-  SegmentsX* segmentsx The set of segments to process.
-
-  index_t index The segment index to look for.
-
-  int position The position in the cache to use.
-  ++++++++++++++++++++++++++++++++++++++*/
-
-SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position)
-{
- assert(index!=NO_SEGMENT);     /* Must be a valid segment */
-
- if(option_slim)
-   {
-    SeekFile(segmentsx->fd,index*sizeof(SegmentX));
-
-    ReadFile(segmentsx->fd,&segmentsx->cached[position-1],sizeof(SegmentX));
-
-    return(&segmentsx->cached[position-1]);
-   }
- else
-   {
-    return(&segmentsx->xdata[index]);
-   }
-}
-
-
-/*++++++++++++++++++++++++++++++++++++++
   Remove bad segments (duplicated, zero length or missing nodes).
 
   NodesX *nodesx The nodes to check.
@@ -397,8 +376,7 @@ void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
 
  /* Print the start message */
 
- printf("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0");
- fflush(stdout);
+ printf_first("Checking: Segments=0 Duplicate=0 Loop=0 Missing-Node=0");
 
  /* Allocate the array of indexes */
 
@@ -410,7 +388,7 @@ void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
 
  DeleteFile(segmentsx->filename);
 
- fd=OpenFile(segmentsx->filename);
+ fd=OpenFileNew(segmentsx->filename);
  SeekFile(segmentsx->fd,0);
 
  while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
@@ -436,10 +414,7 @@ void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
     total++;
 
     if(!(total%10000))
-      {
-       printf("\rChecking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
-       fflush(stdout);
-      }
+       printf_middle("Checking: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
    }
 
  /* Close the files and re-open them */
@@ -453,8 +428,7 @@ void RemoveBadSegments(NodesX *nodesx,SegmentsX *segmentsx)
 
  /* Print the final message */
 
- printf("\rChecked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d  \n",total,duplicate,loop,missing);
- fflush(stdout);
+ printf_last("Checked: Segments=%d Duplicate=%d Loop=%d Missing-Node=%d",total,duplicate,loop,missing);
 }
 
 
@@ -476,13 +450,13 @@ void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  /* Print the start message */
 
- printf("Measuring Segments: Segments=0");
- fflush(stdout);
+ printf_first("Measuring Segments: Segments=0");
 
  /* Map into memory */
 
- if(!option_slim)
-    nodesx->xdata=MapFile(nodesx->filename);
+#if !SLIM
+ nodesx->xdata=MapFile(nodesx->filename);
+#endif
 
  /* Free the now-unneeded index */
 
@@ -504,7 +478,7 @@ void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  DeleteFile(segmentsx->filename);
 
- fd=OpenFile(segmentsx->filename);
+ fd=OpenFileNew(segmentsx->filename);
  SeekFile(segmentsx->fd,0);
 
  while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
@@ -538,10 +512,7 @@ void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
     index++;
 
     if(!(index%10000))
-      {
-       printf("\rMeasuring Segments: Segments=%d",index);
-       fflush(stdout);
-      }
+       printf_middle("Measuring Segments: Segments=%d",index);
    }
 
  /* Close the files and re-open them */
@@ -561,13 +532,13 @@ void UpdateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  /* Unmap from memory */
 
- if(!option_slim)
-    nodesx->xdata=UnmapFile(nodesx->filename);
+#if !SLIM
+ nodesx->xdata=UnmapFile(nodesx->filename);
+#endif
 
  /* Print the final message */
 
- printf("\rMeasured Segments: Segments=%d \n",segmentsx->number);
- fflush(stdout);
+ printf_last("Measured Segments: Segments=%d",segmentsx->number);
 }
 
 
@@ -583,14 +554,9 @@ void RotateSegments(SegmentsX* segmentsx)
  int fd;
  SegmentX segmentx;
 
- /* Check the start conditions */
-
- assert(!segmentsx->idata);    /* Must not have idata filled in => not sorted by node 1 */
-
  /* Print the start message */
 
- printf("Rotating Segments: Segments=0 Rotated=0");
- fflush(stdout);
+ printf_first("Rotating Segments: Segments=0 Rotated=0");
 
  /* Close the files and re-open them (finished appending) */
 
@@ -599,7 +565,7 @@ void RotateSegments(SegmentsX* segmentsx)
 
  DeleteFile(segmentsx->filename);
 
- fd=OpenFile(segmentsx->filename);
+ fd=OpenFileNew(segmentsx->filename);
 
  /* Modify the file contents */
 
@@ -624,10 +590,7 @@ void RotateSegments(SegmentsX* segmentsx)
     index++;
 
     if(!(index%10000))
-      {
-       printf("\rRotating Segments: Segments=%d Rotated=%d",index,rotated);
-       fflush(stdout);
-      }
+       printf_middle("Rotating Segments: Segments=%d Rotated=%d",index,rotated);
    }
 
  /* Close the files and re-open them */
@@ -639,8 +602,7 @@ void RotateSegments(SegmentsX* segmentsx)
 
  /* Print the final message */
 
- printf("\rRotated Segments: Segments=%d Rotated=%d \n",index,rotated);
- fflush(stdout);
+ printf_last("Rotated Segments: Segments=%d Rotated=%d",index,rotated);
 }
 
 
@@ -663,13 +625,13 @@ void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  /* Print the start message */
 
- printf("Deduplicating Segments: Segments=0 Duplicate=0");
- fflush(stdout);
+ printf_first("Deduplicating Segments: Segments=0 Duplicate=0");
 
  /* Map into memory */
 
- if(!option_slim)
-    waysx->xdata=MapFile(waysx->filename);
+#if !SLIM
+ waysx->xdata=MapFile(waysx->filename);
+#endif
 
  /* Allocate the array of indexes */
 
@@ -686,7 +648,7 @@ void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  DeleteFile(segmentsx->filename);
 
- fd=OpenFile(segmentsx->filename);
+ fd=OpenFileNew(segmentsx->filename);
  SeekFile(segmentsx->fd,0);
 
  while(!ReadFile(segmentsx->fd,&segmentx,sizeof(SegmentX)))
@@ -741,10 +703,7 @@ void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
     index++;
 
     if(!(index%10000))
-      {
-       printf("\rDeduplicating Segments: Segments=%d Duplicate=%d",index,duplicate);
-       fflush(stdout);
-      }
+       printf_middle("Deduplicating Segments: Segments=%d Duplicate=%d",index,duplicate);
    }
 
  /* Close the files and re-open them */
@@ -764,13 +723,13 @@ void DeduplicateSegments(SegmentsX* segmentsx,NodesX *nodesx,WaysX *waysx)
 
  /* Unmap from memory */
 
- if(!option_slim)
-    waysx->xdata=UnmapFile(waysx->filename);
+#if !SLIM
+ waysx->xdata=UnmapFile(waysx->filename);
+#endif
 
  /* Print the final message */
 
- printf("\rDeduplicated Segments: Segments=%d Duplicate=%d Unique=%d\n",index,duplicate,index-duplicate);
- fflush(stdout);
+ printf_last("Deduplicated Segments: Segments=%d Duplicate=%d Unique=%d",index,duplicate,index-duplicate);
 }
 
 
@@ -786,66 +745,67 @@ void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx)
 {
  index_t i;
 
- /* Check the start conditions */
-
- assert(!segmentsx->sdata);     /* Must not have sdata filled in => no real segments */
+ if(segmentsx->number==0 || waysx->number==0)
+    return;
 
  /* Print the start message */
 
- printf("Creating Real Segments: Segments=0");
- fflush(stdout);
+ printf_first("Creating Real Segments: Segments=0");
 
  /* Map into memory */
 
- if(!option_slim)
-   {
-    segmentsx->xdata=MapFile(segmentsx->filename);
-    waysx->xdata=MapFile(waysx->filename);
-   }
+#if !SLIM
+ segmentsx->xdata=MapFile(segmentsx->filename);
+ waysx->xdata=MapFile(waysx->filename);
+#endif
 
  /* Free the unneeded memory */
 
  free(segmentsx->firstnode);
  segmentsx->firstnode=NULL;
 
- /* Allocate the memory */
+ /* Allocate the memory (or open the file) */
 
+#if !SLIM
  segmentsx->sdata=(Segment*)malloc(segmentsx->number*sizeof(Segment));
 
  assert(segmentsx->sdata); /* Check malloc() worked */
+#else
+ segmentsx->sfd=OpenFileNew(segmentsx->sfilename);
+#endif
 
  /* Loop through and fill */
 
  for(i=0;i<segmentsx->number;i++)
    {
     SegmentX *segmentx=LookupSegmentX(segmentsx,i,1);
-    WayX *wayx=LookupWayX(waysx,segmentx->way,1);
+    Segment  *segment =LookupSegmentXSegment(segmentsx,i,1);
+    WayX     *wayx=LookupWayX(waysx,segmentx->way,1);
 
-    segmentsx->sdata[i].node1=0;
-    segmentsx->sdata[i].node2=0;
-    segmentsx->sdata[i].next2=NO_NODE;
-    segmentsx->sdata[i].way=wayx->prop;
-    segmentsx->sdata[i].distance=segmentx->distance;
+    segment->node1=0;
+    segment->node2=0;
+    segment->next2=NO_NODE;
+    segment->way=wayx->prop;
+    segment->distance=segmentx->distance;
+
+#if SLIM
+    PutBackSegmentXSegment(segmentsx,i,1);
+#endif
 
     if(!((i+1)%10000))
-      {
-       printf("\rCreating Real Segments: Segments=%d",i+1);
-       fflush(stdout);
-      }
+       printf_middle("Creating Real Segments: Segments=%d",i+1);
    }
 
  /* Unmap from memory */
 
- if(!option_slim)
-   {
-    segmentsx->xdata=UnmapFile(segmentsx->filename);
-    waysx->xdata=UnmapFile(waysx->filename);
-   }
+#if !SLIM
+ segmentsx->xdata=UnmapFile(segmentsx->filename);
+ waysx->xdata=UnmapFile(waysx->filename);
+#endif
 
  /* Print the final message */
 
- printf("\rCreating Real Segments: Segments=%d \n",segmentsx->number);
- fflush(stdout);
+ printf_last("Creating Real Segments: Segments=%d",segmentsx->number);
 }
 
 
@@ -861,39 +821,40 @@ void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
 {
  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 */
 
- printf("Indexing Nodes: Nodes=0");
- fflush(stdout);
+ printf_first("Indexing Nodes: Nodes=0");
 
  /* 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 segments */
 
  for(i=0;i<nodesx->number;i++)
    {
     NodeX  *nodex=LookupNodeX(nodesx,i,1);
-    Node   *node =&nodesx->ndata[nodex->id];
-    index_t index=SEGMENT(node->firstseg);
+    Node   *node =LookupNodeXNode(nodesx,nodex->id,1);
+    index_t index=node->firstseg;
 
     do
       {
        SegmentX *segmentx=LookupSegmentX(segmentsx,index,1);
+       Segment  *segment =LookupSegmentXSegment(segmentsx,index,1);
 
        if(segmentx->node1==nodex->id)
          {
-          segmentsx->sdata[index].node1=i;
+          segment->node1=i;
+
+#if SLIM
+          PutBackSegmentXSegment(segmentsx,index,1);
+#endif
 
           index++;
 
@@ -907,35 +868,34 @@ void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx)
          }
        else
          {
-          segmentsx->sdata[index].node2=i;
+          segment->node2=i;
 
-          if(segmentsx->sdata[index].next2==NO_NODE)
+#if SLIM
+          PutBackSegmentXSegment(segmentsx,index,1);
+#endif
+
+          if(segment->next2==NO_NODE)
              break;
           else
-             index=segmentsx->sdata[index].next2;
+             index=segment->next2;
          }
       }
     while(1);
 
     if(!((i+1)%10000))
-      {
-       printf("\rIndexing Nodes: Nodes=%d",i+1);
-       fflush(stdout);
-      }
+       printf_middle("Indexing Nodes: Nodes=%d",i+1);
    }
 
  /* 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 */
 
- printf("\rIndexed Nodes: Nodes=%d \n",nodesx->number);
- fflush(stdout);
+ printf_last("Indexed Nodes: Nodes=%d",nodesx->number);
 }
 
 
@@ -951,69 +911,48 @@ void SaveSegmentList(SegmentsX* segmentsx,const char *filename)
 {
  index_t i;
  int fd;
- Segments *segments;
+ SegmentsFile segmentsfile={0};
  int super_number=0,normal_number=0;
 
- /* Check the start conditions */
+ /* Print the start message */
 
- assert(segmentsx->sdata);      /* Must have sdata filled in => real segments */
+ printf_first("Writing Segments: Segments=0");
 
- /* Print the start message */
+ /* Write out the segments data */
 
- printf("Writing Segments: Segments=0");
- fflush(stdout);
+ fd=OpenFileNew(filename);
 
- /* Count the number of super-segments and normal segments */
+ SeekFile(fd,sizeof(SegmentsFile));
 
  for(i=0;i<segmentsx->number;i++)
    {
-    if(IsSuperSegment(&segmentsx->sdata[i]))
+    Segment *segment=LookupSegmentXSegment(segmentsx,i,1);
+
+    if(IsSuperSegment(segment))
        super_number++;
-    if(IsNormalSegment(&segmentsx->sdata[i]))
+    if(IsNormalSegment(segment))
        normal_number++;
-   }
-
- /* Fill in a Segments structure with the offset of the real data in the file after
-    the Segment structure itself. */
-
- segments=calloc(1,sizeof(Segments));
-
- assert(segments); /* Check calloc() worked */
-
- segments->number=segmentsx->number;
- segments->snumber=super_number;
- segments->nnumber=normal_number;
 
- segments->data=NULL;
- segments->segments=NULL;
+    WriteFile(fd,segment,sizeof(Segment));
 
- /* Write out the Segments structure and then the real data. */
+    if(!((i+1)%10000))
+       printf_middle("Writing Segments: Segments=%d",i+1);
+   }
 
- fd=OpenFile(filename);
+ /* Write out the header structure */
 
- WriteFile(fd,segments,sizeof(Segments));
+ segmentsfile.number=segmentsx->number;
+ segmentsfile.snumber=super_number;
+ segmentsfile.nnumber=normal_number;
 
- for(i=0;i<segments->number;i++)
-   {
-    WriteFile(fd,&segmentsx->sdata[i],sizeof(Segment));
-
-    if(!((i+1)%10000))
-      {
-       printf("\rWriting Segments: Segments=%d",i+1);
-       fflush(stdout);
-      }
-   }
+ SeekFile(fd,0);
+ WriteFile(fd,&segmentsfile,sizeof(SegmentsFile));
 
  CloseFile(fd);
 
  /* Print the final message */
 
- printf("\rWrote Segments: Segments=%d  \n",segments->number);
- fflush(stdout);
-
- /* Free the fake Segments */
-
- free(segments);
+ printf_last("Wrote Segments: Segments=%d",segmentsx->number);
 }
 
 
index ac19a77..a843900 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/segmentsx.h,v 1.20 2010/03/19 19:47:09 amb Exp $
+ $Header: /home/amb/routino/src/RCS/segmentsx.h,v 1.26 2010/07/31 14:36:15 amb Exp $
 
  A header file for the extended segments.
 
 
 #include <stdint.h>
 
-#include "typesx.h"
 #include "types.h"
+#include "segments.h"
+
+#include "typesx.h"
+
+#include "files.h"
 
 
 /* Data structures */
@@ -52,17 +56,35 @@ struct _SegmentsX
  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
 
  SegmentX  *xdata;              /*+ The extended segment data (unsorted). +*/
- SegmentX   cached[2];          /*+ Two cached segments read from the file in slim mode. +*/
 
- uint32_t   number;             /*+ How many entries are still useful? +*/
+#else
+
+ SegmentX   xcached[2];         /*+ Two cached segments read from the file in slim mode. +*/
+
+#endif
+
+ index_t    number;             /*+ How many entries are still useful? +*/
 
  node_t   *idata;               /*+ The extended segment data (sorted by node1 then node2). +*/
  index_t  *firstnode;           /*+ The first segment index for each node. +*/
 
+#if !SLIM
+
  Segment   *sdata;              /*+ The segment data (same order as n1data). +*/
+
+#else
+
+ char     *sfilename;           /*+ The name of the temporary file for segments in slim mode. +*/
+ int       sfd;                 /*+ The file descriptor of the temporary file. +*/
+
+ Segment   scached[2];          /*+ Two cached segments read from the file in slim mode. +*/
+
+#endif
 };
 
 
@@ -74,8 +96,6 @@ void FreeSegmentList(SegmentsX *segmentsx,int keep);
 
 void SaveSegmentList(SegmentsX *segmentsx,const char *filename);
 
-SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position);
-
 index_t IndexFirstSegmentX(SegmentsX* segmentsx,node_t node);
 
 index_t IndexNextSegmentX(SegmentsX* segmentsx,index_t segindex,index_t nodeindex);
@@ -97,4 +117,86 @@ void CreateRealSegments(SegmentsX *segmentsx,WaysX *waysx);
 void IndexSegments(SegmentsX* segmentsx,NodesX *nodesx);
 
 
+/* Macros / inline functions */
+
+
+#if !SLIM
+
+#define LookupSegmentX(segmentsx,index,position)         &(segmentsx)->xdata[index]
+  
+#define LookupSegmentXSegment(segmentsx,index,position)  &(segmentsx)->sdata[index]
+
+#else
+
+static SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position);
+
+static Segment *LookupSegmentXSegment(SegmentsX* segmentsx,index_t index,int position);
+
+static void PutBackSegmentXSegment(SegmentsX* segmentsx,index_t index,int position);
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Lookup a particular extended segment.
+
+  SegmentX *LookupSegmentX Returns a pointer to the extended segment with the specified id.
+
+  SegmentsX* segmentsx The set of segments to process.
+
+  index_t index The segment index to look for.
+
+  int position The position in the cache to use.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static inline SegmentX *LookupSegmentX(SegmentsX* segmentsx,index_t index,int position)
+{
+ SeekFile(segmentsx->fd,(off_t)index*sizeof(SegmentX));
+
+ ReadFile(segmentsx->fd,&segmentsx->xcached[position-1],sizeof(SegmentX));
+
+ return(&segmentsx->xcached[position-1]);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Lookup a particular extended segment's normal segment.
+
+  Segment *LookupSegmentXSegment Returns a pointer to the segment with the specified id.
+
+  SegmentsX* segmentsx The set of segments to process.
+
+  index_t index The segment index to look for.
+
+  int position The position in the cache to use.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static inline Segment *LookupSegmentXSegment(SegmentsX* segmentsx,index_t index,int position)
+{
+ SeekFile(segmentsx->sfd,(off_t)index*sizeof(Segment));
+
+ ReadFile(segmentsx->sfd,&segmentsx->scached[position-1],sizeof(Segment));
+
+ return(&segmentsx->scached[position-1]);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++
+  Put back an extended segment's normal segment.
+
+  SegmentsX* segmentsx The set of segments to process.
+
+  index_t index The segment index to look for.
+
+  int position The position in the cache to use.
+  ++++++++++++++++++++++++++++++++++++++*/
+
+static inline void PutBackSegmentXSegment(SegmentsX* segmentsx,index_t index,int position)
+{
+ SeekFile(segmentsx->sfd,(off_t)index*sizeof(Segment));
+
+ WriteFile(segmentsx->sfd,&segmentsx->scached[position-1],sizeof(Segment));
+}
+
+#endif /* SLIM */
+
+
 #endif /* SEGMENTSX_H */
index 54bfdf0..396d363 100644 (file)
@@ -1,11 +1,11 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/sorting.c,v 1.8 2010/04/09 15:15:02 amb Exp $
+ $Header: /home/amb/routino/src/RCS/sorting.c,v 1.11 2010/09/25 13:54:18 amb Exp $
 
  Merge sort functions.
 
  Part of the Routino routing software.
  ******************/ /******************
- This file Copyright 2009 Andrew M. Bishop
+ This file Copyright 2009-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
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <assert.h>
 
+#include "files.h"
 #include "functions.h"
 
 
@@ -107,7 +108,7 @@ void filesort_fixed(int fd_in,int fd_out,size_t itemsize,int (*compare)(const vo
 
     /* Sort the data pointers using a heap sort */
 
-    heapsort(datap,n,compare);
+    filesort_heapsort(datap,n,compare);
 
     /* Shortcut if all read in and sorted at once */
 
@@ -129,7 +130,7 @@ void filesort_fixed(int fd_in,int fd_out,size_t itemsize,int (*compare)(const vo
 
     sprintf(filename,"%s/filesort.%d.tmp",option_tmpdirname,nfiles);
 
-    fd=OpenFile(filename);
+    fd=OpenFileNew(filename);
 
     for(i=0;i<n;i++)
        WriteFile(fd,datap[i],itemsize);
@@ -374,7 +375,7 @@ void filesort_vary(int fd_in,int fd_out,int (*compare)(const void*,const void*),
 
     /* Sort the data pointers using a heap sort */
 
-    heapsort(datap,n,compare);
+    filesort_heapsort(datap,n,compare);
 
     /* Shortcut if all read in and sorted at once */
 
@@ -398,7 +399,7 @@ void filesort_vary(int fd_in,int fd_out,int (*compare)(const void*,const void*),
 
     sprintf(filename,"%s/filesort.%d.tmp",option_tmpdirname,nfiles);
 
-    fd=OpenFile(filename);
+    fd=OpenFileNew(filename);
 
     for(i=0;i<n;i++)
       {
@@ -574,7 +575,7 @@ void filesort_vary(int fd_in,int fd_out,int (*compare)(const void*,const void*),
                                             data to be sorted was an array of things not pointers).
   ++++++++++++++++++++++++++++++++++++++*/
 
-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*))
 {
  int i;
 
index 45b8227..182daef 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************
- $Header: /home/amb/routino/src/RCS/superx.c,v 1.38 2010/07/05 19:05:51 amb Exp $
+ $Header: /home/amb/routino/src/RCS/superx.c,v 1.45 2010/11/13 14:22:28 amb Exp $
 
  Super-Segment data type functions.
 
  ***************************************/
 
 
-#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 
-#include "results.h"
-#include "functions.h"
+#include "ways.h"
+
 #include "nodesx.h"
 #include "segmentsx.h"
 #include "waysx.h"
 #include "superx.h"
-#include "ways.h"
-
 
-/* Variables */
+#include "files.h"
+#include "logging.h"
+#include "results.h"
 
-/*+ The command line '--slim' option. +*/
-extern int option_slim;
 
 /* Local Functions */
 
@@ -60,27 +57,26 @@ void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
  index_t i;
  int nnodes=0;
 
- /* Check the start conditions */
-
- assert(segmentsx->firstnode); /* Must have firstnode filled in => segments are updated */
+ if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0)
+    return;
 
  /* Print the start message */
 
- printf("Finding Super-Nodes: Nodes=0 Super-Nodes=0");
- fflush(stdout);
+ printf_first("Finding Super-Nodes: Nodes=0 Super-Nodes=0");
 
  /* Map into memory */
 
- if(!option_slim)
-   {
-    segmentsx->xdata=MapFile(segmentsx->filename);
-    waysx->xdata=MapFile(waysx->filename);
-   }
+#if !SLIM
+ nodesx->xdata=MapFile(nodesx->filename);
+ segmentsx->xdata=MapFile(segmentsx->filename);
+ waysx->xdata=MapFile(waysx->filename);
+#endif
 
  /* Find super-nodes */
 
  for(i=0;i<nodesx->number;i++)
    {
+    NodeX *nodex=LookupNodeX(nodesx,i,1);
     int difference=0;
     index_t index1,index2;
 
@@ -94,12 +90,20 @@ void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
        index1=IndexNextSegmentX(segmentsx,index1,i);
        index2=index1;
 
+       /* If the node allows less traffic types than any connecting way ... */
+
+       if((wayx1->way.allow&nodex->allow)!=wayx1->way.allow)
+         {
+          difference=1;
+          break;
+         }
+
        while(index2!=NO_SEGMENT)
          {
           SegmentX *segmentx2=LookupSegmentX(segmentsx,index2,2);
           WayX *wayx2=LookupWayX(waysx,segmentx2->way,2);
 
-          /* If the ways are different in any way and there is a type of traffic that can use both ... */
+          /* If the ways are different in any attribute and there is a type of traffic that can use both ... */
 
           if(WaysCompare(&wayx1->way,&wayx2->way))
              if(wayx1->way.allow & wayx2->way.allow)
@@ -125,24 +129,20 @@ void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx)
       }
 
     if(!((i+1)%10000))
-      {
-       printf("\rFinding Super-Nodes: Nodes=%d Super-Nodes=%d",i+1,nnodes);
-       fflush(stdout);
-      }
+       printf_middle("Finding Super-Nodes: Nodes=%d Super-Nodes=%d",i+1,nnodes);
    }
 
  /* Unmap from memory */
 
- if(!option_slim)
-   {
-    segmentsx->xdata=UnmapFile(segmentsx->filename);
-    waysx->xdata=UnmapFile(waysx->filename);
-   }
+#if !SLIM
+ nodesx->xdata=UnmapFile(nodesx->filename);
+ segmentsx->xdata=UnmapFile(segmentsx->filename);
+ waysx->xdata=UnmapFile(waysx->filename);
+#endif
 
  /* Print the final message */
 
- printf("\rFound Super-Nodes: Nodes=%d Super-Nodes=%d  \n",nodesx->number,nnodes);
- fflush(stdout);
+ printf_last("Found Super-Nodes: Nodes=%d Super-Nodes=%d",nodesx->number,nnodes);
 }
 
 
@@ -166,27 +166,24 @@ SegmentsX *CreateSuperSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx,
  SegmentsX *supersegmentsx;
  int sn=0,ss=0;
 
- /* Check the start conditions */
+ supersegmentsx=NewSegmentList(0);
 
- assert(segmentsx->firstnode); /* Must have firstnode filled in => segments are updated */
+ if(segmentsx->number==0 || waysx->number==0)
+    return(supersegmentsx);
 
  /* Print the start message */
 
- printf("Creating Super-Segments: Super-Nodes=0 Super-Segments=0");
- fflush(stdout);
+ printf_first("Creating Super-Segments: Super-Nodes=0 Super-Segments=0");
 
  /* Map into memory */
 
- if(!option_slim)
-   {
-    segmentsx->xdata=MapFile(segmentsx->filename);
-    waysx->xdata=MapFile(waysx->filename);
-   }
+#if !SLIM
+ segmentsx->xdata=MapFile(segmentsx->filename);
+ waysx->xdata=MapFile(waysx->filename);
+#endif
 
  /* Create super-segments for each super-node. */
 
- supersegmentsx=NewSegmentList(0);
-
  for(i=0;i<nodesx->number;i++)
    {
     if(nodesx->super[i]>iteration)